Skip to content

Commit

Permalink
add module to manage Kea DHCP subnets
Browse files Browse the repository at this point in the history
Prior to this change, it was not possible to manage the subnets in the
Kea DHCP service. I.e. it was not possible to add/remove subnets.

This change adds a new module that allows to manage subnets. The code is
split in two python files. 'plugins/modules/dhcp_subnet.py' and
'plugins/module_utils/main/dhcp_subnet_v4.py'
  • Loading branch information
Thomas Wölfle committed Jan 6, 2025
1 parent 4507e99 commit 8e2d72c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ action_groups:
dhcp:
- ansibleguy.opnsense.dhcp_reservation
- ansibleguy.opnsense.dhcp_controlagent
- ansibleguy.opnsense.dhcp_subnet
acme:
- ansibleguy.opnsense.acme_general
- ansibleguy.opnsense.acme_account
Expand Down
46 changes: 46 additions & 0 deletions plugins/module_utils/main/dhcp_subnet_v4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from ansible.module_utils.basic import AnsibleModule

from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.api import \
Session
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.main import \
is_ip, is_network, is_unset
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.cls import BaseModule

class SubnetV4(BaseModule):
FIELD_ID = 'subnet'
CMDS = {
'add': 'addSubnet',
'del': 'delSubnet',
'set': 'setSubnet',
'search': 'searchSubnet',
'detail': 'getSubnet',
}
API_KEY_PATH = 'subnet4'
API_MOD = 'kea'
API_CONT = 'dhcpv4'
API_CONT_REL = 'service'
FIELDS_CHANGE = [
'subnet', 'description', 'pools'
]
FIELDS_ALL = [FIELD_ID]
FIELDS_ALL.extend(FIELDS_CHANGE)
FIELDS_TYPING = {}
FIELDS_TRANSLATE = {}
EXIST_ATTR = 'subnet'

def __init__(self, module: AnsibleModule, result: dict, session: Session = None):
BaseModule.__init__(self=self, m=module, r=result, s=session)
self.subnet = {}
self.existing_subnets = None

def check(self) -> None:
if self.p['state'] == 'present':
if is_unset(self.p['subnet']):
self.m.fail_json(
"You need to provide the 'subnet' you want to create. E.g. (192.168.1.0/24)!"
)

if is_unset(self.p['pools']):
self.m.fail_json("You need to provide the IP 'pools' to be used in the subnet!")

self._base_check()
60 changes: 60 additions & 0 deletions plugins/modules/dhcp_subnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: (C) 2024, AnsibleGuy <[email protected]>
# GNU General Public License v3.0+ (see https://www.gnu.org/licenses/gpl-3.0.txt)

# see: https://docs.opnsense.org/development/api/core/kea.html

from ansible.module_utils.basic import AnsibleModule

from ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler import \
module_dependency_error, MODULE_EXCEPTIONS

try:
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.wrapper import module_wrapper
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.defaults.main import \
OPN_MOD_ARGS, STATE_MOD_ARG, RELOAD_MOD_ARG
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_subnet_v4 import SubnetV4

except MODULE_EXCEPTIONS:
module_dependency_error()


# DOCUMENTATION = 'https://opnsense.ansibleguy.net/modules/dhcp.html'
# EXAMPLES = 'https://opnsense.ansibleguy.net/modules/dhcp.html'


def run_module():
module_args = dict(
subnet=dict(type='str', required=True, description='Subnet to create'),
description=dict(type='str', required=False),
pools=dict(type='str', required=True, description='IP address pools to offer in the subnet'),
**RELOAD_MOD_ARG,
**STATE_MOD_ARG,
**OPN_MOD_ARGS,
)

result = dict(
changed=False,
diff={
'before': {},
'after': {},
}
)

module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True,
)

module_wrapper(SubnetV4(module=module, result=result))
module.exit_json(**result)


def main():
run_module()


if __name__ == '__main__':
main()
7 changes: 6 additions & 1 deletion plugins/modules/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
'ipsec_child', 'ipsec_vti', 'ipsec_auth_local', 'ipsec_auth_remote', 'frr_general', 'unbound_general',
'unbound_acl', 'ids_general', 'ids_policy', 'ids_rule', 'ids_ruleset', 'ids_user_rule', 'ids_policy_rule',
'openvpn_instance', 'openvpn_static_key', 'openvpn_client_override', 'dhcrelay_destination', 'dhcrelay_relay',
'interface_lagg', 'interface_loopback', 'unbound_dnsbl', 'dhcp_reservation', 'acme_general', 'acme_account',
'interface_lagg', 'interface_loopback', 'unbound_dnsbl', 'dhcp_reservation', 'dhcp_subnet', 'acme_general', 'acme_account',
'acme_validation', 'acme_action', 'acme_certificate',
]

Expand Down Expand Up @@ -419,6 +419,11 @@ def run_module():
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.acme_certificate import \
Certificate as Target_Obj

elif target == 'dhcp_subnet':
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.main.dhcp_subnet_v4 import \
SubnetV4 as Target_Obj


except AttributeError:
module_dependency_error()

Expand Down

0 comments on commit 8e2d72c

Please sign in to comment.