From a9232e4f305fd4273a37cff615a5e4e47a9ad006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Dunand?= Date: Fri, 22 May 2020 17:37:14 +0200 Subject: [PATCH 1/2] Add optional primary_ip on virtual machines initializer --- startup_scripts/230_virtual_machines.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/startup_scripts/230_virtual_machines.py b/startup_scripts/230_virtual_machines.py index 6776c4df3..4236fa42e 100644 --- a/startup_scripts/230_virtual_machines.py +++ b/startup_scripts/230_virtual_machines.py @@ -1,4 +1,5 @@ from dcim.models import Site, Platform, DeviceRole +from ipam.models import IPAddress from virtualization.models import Cluster, VirtualMachine from tenancy.models import Tenant from extras.models import CustomField, CustomFieldValue @@ -17,7 +18,9 @@ optional_assocs = { 'tenant': (Tenant, 'name'), 'platform': (Platform, 'name'), - 'role': (DeviceRole, 'name') + 'role': (DeviceRole, 'name'), + 'primary_ip4': (IPAddress, 'address'), + 'primary_ip6': (IPAddress, 'address') } for params in virtual_machines: From df72d6bbb56a19807b14adce56b7e0e9ca0073ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Dunand?= Date: Thu, 4 Jun 2020 20:46:40 +0200 Subject: [PATCH 2/2] Handle primary IPs on devices and VMs --- initializers/devices.yml | 2 ++ initializers/virtual_machines.yml | 2 ++ startup_scripts/130_devices.py | 8 ++--- startup_scripts/230_virtual_machines.py | 8 ++--- startup_scripts/270_primary_ips.py | 43 +++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 startup_scripts/270_primary_ips.py diff --git a/initializers/devices.yml b/initializers/devices.yml index 708b68caa..e9685033c 100644 --- a/initializers/devices.yml +++ b/initializers/devices.yml @@ -29,6 +29,8 @@ # rack: rack-02 # face: front # position: 2 +# primary_ip4: 10.1.1.2/24 +# primary_ip6: 2001:db8:a000:1::2/64 # custom_fields: # text_field: Description # - name: server03 diff --git a/initializers/virtual_machines.yml b/initializers/virtual_machines.yml index 21229206f..918df938a 100644 --- a/initializers/virtual_machines.yml +++ b/initializers/virtual_machines.yml @@ -21,6 +21,8 @@ # memory: 2048 # name: virtual machine 2 # platform: Platform 2 +# primary_ip4: 10.1.1.10/24 +# primary_ip6: 2001:db8:a000:1::10/64 # status: active # tenant: tenant1 # vcpus: 8 diff --git a/startup_scripts/130_devices.py b/startup_scripts/130_devices.py index 1e0d8948c..7233dd0a1 100644 --- a/startup_scripts/130_devices.py +++ b/startup_scripts/130_devices.py @@ -1,5 +1,4 @@ from dcim.models import Site, Rack, DeviceRole, DeviceType, Device, Platform -from ipam.models import IPAddress from virtualization.models import Cluster from tenancy.models import Tenant from extras.models import CustomField, CustomFieldValue @@ -21,13 +20,14 @@ 'tenant': (Tenant, 'name'), 'platform': (Platform, 'name'), 'rack': (Rack, 'name'), - 'cluster': (Cluster, 'name'), - 'primary_ip4': (IPAddress, 'address'), - 'primary_ip6': (IPAddress, 'address') + 'cluster': (Cluster, 'name') } for params in devices: custom_fields = params.pop('custom_fields', None) + # primary ips are handled later in `270_primary_ips.py` + params.pop('primary_ip4', None) + params.pop('primary_ip6', None) for assoc, details in required_assocs.items(): model, field = details diff --git a/startup_scripts/230_virtual_machines.py b/startup_scripts/230_virtual_machines.py index 4236fa42e..f138886fd 100644 --- a/startup_scripts/230_virtual_machines.py +++ b/startup_scripts/230_virtual_machines.py @@ -1,5 +1,4 @@ from dcim.models import Site, Platform, DeviceRole -from ipam.models import IPAddress from virtualization.models import Cluster, VirtualMachine from tenancy.models import Tenant from extras.models import CustomField, CustomFieldValue @@ -18,13 +17,14 @@ optional_assocs = { 'tenant': (Tenant, 'name'), 'platform': (Platform, 'name'), - 'role': (DeviceRole, 'name'), - 'primary_ip4': (IPAddress, 'address'), - 'primary_ip6': (IPAddress, 'address') + 'role': (DeviceRole, 'name') } for params in virtual_machines: custom_fields = params.pop('custom_fields', None) + # primary ips are handled later in `270_primary_ips.py` + params.pop('primary_ip4', None) + params.pop('primary_ip6', None) for assoc, details in required_assocs.items(): model, field = details diff --git a/startup_scripts/270_primary_ips.py b/startup_scripts/270_primary_ips.py new file mode 100644 index 000000000..2ddab814f --- /dev/null +++ b/startup_scripts/270_primary_ips.py @@ -0,0 +1,43 @@ +from dcim.models import Device +from ipam.models import IPAddress +from virtualization.models import VirtualMachine +from startup_script_utils import load_yaml +import sys + +def link_primary_ip(assets, asset_model): + for params in assets: + primary_ip_fields = set(params) & {'primary_ip4', 'primary_ip6'} + if not primary_ip_fields: + continue + + for assoc, details in optional_assocs.items(): + if assoc in params: + model, field = details + query = { field: params.pop(assoc) } + + try: + params[assoc] = model.objects.get(**query) + except model.DoesNotExist: + primary_ip_fields -= {assoc} + print(f"⚠️ IP Address {query[field]} not found") + + asset = asset_model.objects.get(name=params['name']) + for field in primary_ip_fields: + if getattr(asset, field) != params[field]: + setattr(asset, field, params[field]) + print(f"🧬 Linked primary IP {params[field].address} on {asset.name}") + asset.save() + +devices = load_yaml('/opt/netbox/initializers/devices.yml') +virtual_machines = load_yaml('/opt/netbox/initializers/virtual_machines.yml') + +if devices is None and virtual_machines is None: + sys.exit() + +optional_assocs = { + 'primary_ip4': (IPAddress, 'address'), + 'primary_ip6': (IPAddress, 'address') +} + +link_primary_ip(devices, Device) +link_primary_ip(virtual_machines, VirtualMachine)