aboutsummaryrefslogtreecommitdiff
path: root/ansible/netbox/sync-unifi.py
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2025-06-09 09:03:22 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2025-06-09 09:03:22 +0200
commitb67989737a1aa1972eafdafec5f36eb2a37939f9 (patch)
tree2b27365a72b0bf00d9f04db67c1aa705a3ee7da0 /ansible/netbox/sync-unifi.py
parent8d543808b0516194c9b1831a86209fd024dc48a3 (diff)
downloadinfra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.gz
infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.bz2
infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.tar.xz
infra-b67989737a1aa1972eafdafec5f36eb2a37939f9.zip
netbox
Diffstat (limited to 'ansible/netbox/sync-unifi.py')
-rw-r--r--ansible/netbox/sync-unifi.py110
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