diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2025-06-09 09:03:22 +0200 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2025-06-09 09:03:22 +0200 |
commit | b67989737a1aa1972eafdafec5f36eb2a37939f9 (patch) | |
tree | 2b27365a72b0bf00d9f04db67c1aa705a3ee7da0 /ansible/netbox | |
parent | 8d543808b0516194c9b1831a86209fd024dc48a3 (diff) | |
download | infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.gz infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.bz2 infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.xz infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.zip |
netbox
Diffstat (limited to 'ansible/netbox')
-rw-r--r-- | ansible/netbox/sync-unifi.py | 110 |
1 files changed, 47 insertions, 63 deletions
diff --git a/ansible/netbox/sync-unifi.py b/ansible/netbox/sync-unifi.py index 7995866..4ee9c84 100644 --- a/ansible/netbox/sync-unifi.py +++ b/ansible/netbox/sync-unifi.py @@ -1,10 +1,11 @@ import os import sys -from unifi_controller_api import UnifiController +from unifi_controller_api import UnifiController, UnifiDevice from unifi_controller_api.exceptions import UnifiAuthenticationError, UnifiAPIError from pprint import pprint import pynetbox +from pynetbox.core.response import Record class Db(): def __init__(self): @@ -12,11 +13,18 @@ class Db(): self.interfaces = [] self.ips = [] +class Ip(): + def __init__(self, vrf): + self.address = address + self.vrf = vrf + self.ips = ips + class NetboxCache(): def __init__(self, nb): self.nb = nb self.device_roles = {} self.device_types = {} + self.ip_addresses = {} def get_device_role(self, slug): dt = self.device_roles.get(slug) @@ -25,7 +33,6 @@ class NetboxCache(): return dt dt = self.nb.dcim.device_roles.get(slug=slug) - if dt is None: raise Exception(f"No such device type: {slug}") @@ -39,22 +46,50 @@ class NetboxCache(): return dt dt = self.nb.dcim.device_types.get(slug=slug) - if dt is None: raise Exception(f"No such device type: {slug}") self.device_types[slug] = dt return dt -def process_switch(d, db: Db, nb: NetboxCache, site, vrf): - db.devices.append({ + def get_or_create_ip_address(self, addr: str, vrf: Record | None): + vrf_id = vrf.id if vrf is not None else None + key = (addr, vrf_id) + ip = self.ip_addresses.get(key) + if ip is not None: + return ip + + ip = self.nb.ipam.ip_addresses.get(address=addr, vrf_id=vrf_id) + if ip is not None: + print(f"Found IP address {ip.id}") + self.ip_addresses[key] = ip + return ip + + ip = self.nb.ipam.ip_addresses.create(address=addr, vrf=vrf_id, status="active") + self.ip_addresses[key] = ip + return ip + +def process_switch(d: UnifiDevice, db: Db, nb: NetboxCache, site, vrf): + ip = nb.get_or_create_ip_address(f"{d.ip}/32", vrf) + + d = { "name": d.name, "device_type": nb.get_device_type("ubiquiti-us-8-150w").id, "role": nb.get_device_role("switch").id, - "mac": d.mac, +# "mac": d.mac, "serial": d.serial, "site": site.id, - }) + } + + device = nb.nb.dcim.devices.get(name = d["name"]) + if device is None: + device = nb.nb.dcim.devices.create(d) + print(f"Created device id={device.id}, name={device.name}") + else: + print(f"Updating device id={device.id}, name={device.name}") + device.update(d) + +# pprint(device.serialize()) def main(): unifi_url=os.getenv("UNIFI_URL") @@ -78,14 +113,10 @@ def main(): nb_cache = NetboxCache(nb) db = Db() for d in devices: - pprint(d) +# pprint(d) if d.model == "US8P150": process_switch(d, db, nb_cache, netbox_site, netbox_vrf) - print_db(db) - - sync_db(nb, db) - def controller_login(url, username, password) -> UnifiController: # try: controller = UnifiController( @@ -107,7 +138,7 @@ def controller_login(url, username, password) -> UnifiController: # except Exception as e: # print(f"An unexpected error occurred: {e}") -def collect_devices(controller: UnifiController, site_name: str) -> list[any]: +def collect_devices(controller: UnifiController, site_name: str) -> list[UnifiDevice]: try: return controller.get_unifi_site_device(site_name=site_name, detailed=True, raw=False) except UnifiAPIError as e: @@ -115,53 +146,6 @@ def collect_devices(controller: UnifiController, site_name: str) -> list[any]: except Exception as e: print(f"An unexpected error occurred: {e}") - devices = sorted(devices, key=lambda d: d.name) - for d in devices: - print(f"{d.name}", file=sys.stderr) - print(f"{d}", file=sys.stderr) - db.devices = devices -# db.devices.append({ -# "name": d.name, -# "mac": d.mac, -# "serial": d.serial, -# }) -# db.ips.append({ -# "address": d.ip, -# "status": "active", -# "vrf": None, -# "device": d.name, -# "interface": "", -# "is_primary": "true", -# }) -# db.interfaces.append({ -# }) - - return db - -def print_db(db: Db): - def p(xs): - for x in xs: - print(f"---") - for k, v in x.items(): - print(f"{k}: {v}") - - p(sorted(db.devices, key=lambda d: d["name"])) - p(sorted(db.interfaces, key=lambda d: d["address"])) - p(sorted(db.ips, key=lambda d: d["address"])) - -def sync_db(nb, db: Db): - print("Synchronizing") - for d in db.devices: - pprint(d) - remote = nb.dcim.devices.get(name = d["name"]) - if remote is None: - print(f"Creating new for {d['name']}") - remote = nb.dcim.devices.create(d) - pprint(remote.serialize()) - else: - pprint(remote.serialize()) - remote.update(d) - def netbox_login(url: str, token: str, site_name: str, vrf_name: str) -> pynetbox.core.api.Api: nb = pynetbox.api(url, token=token) @@ -169,16 +153,16 @@ def netbox_login(url: str, token: str, site_name: str, vrf_name: str) -> pynetbo if site is None: site = nb.dcim.sites.get(slug=site_name) if site is None: - print(f"Could not look up site by name or slug: {site_name}", file=sys.stderr) + print(f"Could not look up site by name or slug: {site_name}") exit(1) - print(f"NetBox site {site.name}", file=sys.stderr) + print(f"NetBox site {site.name}") vrf = None vrf_id = None if vrf_name is not None: vrf = nb.ipam.vrfs.get(site=site, name=vrf_name) if vrf is None: - print(f"Could not look up VRF by slug: {vrf_name}", file=sys.stderr) + print(f"Could not look up VRF by slug: {vrf_name}") exit(1) vrf_id = vrf.id |