diff options
author | Håkon Solbjørg <hakon@solbj.org> | 2023-03-22 22:36:09 +0100 |
---|---|---|
committer | Håkon Solbjørg <hakon@solbj.org> | 2023-03-22 22:36:09 +0100 |
commit | 9ba884b5c483c1c7a8f8076c1d038162f07dbe5e (patch) | |
tree | 4d766b027c2f722447b5d4bc5999dd8ae516feb6 | |
parent | 8c185ddbd59cb61835c615a5b7207a2b2fc99cd5 (diff) |
chore(netbox2gondul): Separate gondul posting from NetBox script a bit
-rw-r--r-- | tools/netbox/scripts/netbox2gondul/netbox2gondul.py | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/tools/netbox/scripts/netbox2gondul/netbox2gondul.py b/tools/netbox/scripts/netbox2gondul/netbox2gondul.py index 3ab345b..61af762 100644 --- a/tools/netbox/scripts/netbox2gondul/netbox2gondul.py +++ b/tools/netbox/scripts/netbox2gondul/netbox2gondul.py @@ -1,3 +1,5 @@ +import os + from django.contrib.contenttypes.models import ContentType from django.db.models import F from django.utils.text import slugify @@ -14,16 +16,56 @@ import re import requests from requests.models import HTTPBasicAuth -GONDUL_URL = "" -GONDUL_USERNAME = "" -GONDUL_PASSWORD = "" +class GondulConfigError(Exception): + def __init__(self, msg): + self.message = msg + super().__init__(self.message) -def find_prefix_for_device(device) -> Prefix: - pass +GONDUL_CONFIG_FILE = os.getenv("GONDUL_CONFIG_FILE_PATH", "/etc/netbox/scripts/gondul.json") -class Netbox2Gondul(Script): +class Gondul(object): + url = "" + username = "" + password = "" + + def __init__(self, url, username, password) -> None: + self.url = url + self.username = username + self.password = password + + @classmethod + def read_config_from_file(cls, path): + with open(path, 'r') as f: + conf = json.loads(f.read()) + + try: + url = conf['url'] + username = conf['username'] + password = conf['password'] + return Gondul(url, username, password) + except KeyError as e: + raise GondulConfigError(f"Missing Gondul Configuration key: {e} in {path}") + + def gondul_auth(self): + return HTTPBasicAuth(self.username, self.password) + + def gondul_post(self, path, data): + return requests.post( + f"{self.url}{path}", + auth=self.gondul_auth(), + headers={'content-type': 'application/json'}, + data=json.dumps(data), + ) + + def update_networks(self, networks): + return self.gondul_post("/api/write/networks", networks) + + def update_switches(self, switches): + return self.gondul_post("/api/write/switches", switches) + +class Netbox2Gondul(Script): class Meta: name = "Sync NetBox to Gondul" description = re.sub(r'^\s*', '', """ @@ -37,11 +79,11 @@ class Netbox2Gondul(Script): required=True, ) + _gondul = None + def network_to_gondul(self, vlan: VLAN, prefix_v4: Prefix, prefix_v6: Prefix): - self.log_info(f"Posting {vlan.name} to Gondul") + self.log_info(f"Preparing {vlan.name} for Gondul") - gondul_auth = HTTPBasicAuth(GONDUL_USERNAME, GONDUL_PASSWORD) - subnet4 = None subnet6 = None gw4 = None @@ -73,7 +115,7 @@ class Netbox2Gondul(Script): vlan_name = override vlan_name += f".{router}" - data = json.dumps([{ + networks = [{ "name": vlan_name, "subnet4": subnet4, "subnet6": subnet6, @@ -81,14 +123,9 @@ class Netbox2Gondul(Script): "gw6": gw6, "router": router, "vlan": vlan.vid, - }]) + }] - req = requests.post( - f"{GONDUL_URL}/api/write/networks", - auth=gondul_auth, - headers={'content-type': 'application/json'}, - data=data, - ) + req = self._gondul.update_networks(networks) if req.ok: self.log_success(f"Gondul said (HTTP {req.status_code}): {req.text}") @@ -122,7 +159,7 @@ class Netbox2Gondul(Script): router = "r1.tele" mgmt_vlan_name += f".{router}" - data = json.dumps([{ + switches = [{ # "community": "", # Not implemented "tags": list(device.tags.all()), "distro_name": distro.name, @@ -135,34 +172,17 @@ class Netbox2Gondul(Script): "sysname": device.name, # "traffic_vlan": "", # Not implemented # "deleted": False, # Not implemented - }]) + }] - gondul_auth = HTTPBasicAuth(GONDUL_USERNAME, GONDUL_PASSWORD) - req = requests.post( - f"{GONDUL_URL}/api/write/switches", - auth=gondul_auth, - headers={'content-type': 'application/json'}, - data=data, - ) + req = self._gondul.update_switches(switches) if req.ok: self.log_success(f"Gondul said (HTTP {req.status_code}): {req.text}") else: self.log_failure(f"Gondul said HTTP {req.status_code} and {req.text}") - def run(self, data, commit): - + def run(self, data): device: Device = data['device'] - """ - vlan: VLAN = data['vlan'] - prefix_v4: Prefix = data['prefix_v4'] - prefix_v6: Prefix = data['prefix_v6'] - """ - - """ - if prefix_v4 is None: - self.log_info(f"v4 not provided, default") - """ if not device.primary_ip4 and not device.primary_ip6: self.log_failure(f'Device <a href="{device.get_absolute_url()}">{device.name}</a> is missing primary IPv4 and IPv6 address.') @@ -187,6 +207,8 @@ class Netbox2Gondul(Script): self.log_failure(f'VLANs differ for the IPv4 and IPv6 addresses.') return + self._gondul = Gondul.read_config_from_file(GONDUL_CONFIG_FILE) + self.network_to_gondul(vlan, prefix_v4, prefix_v6) self.log_success("All good, sending to Gondul") |