Skip to content

Instantly share code, notes, and snippets.

@candlerb
Last active February 27, 2024 23:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save candlerb/9616db031301ec8fc737c620881d2fb8 to your computer and use it in GitHub Desktop.
Save candlerb/9616db031301ec8fc737c620881d2fb8 to your computer and use it in GitHub Desktop.
Custom script to backfill missing components from device type template
"""
This script adds missing components from the device type to selected device(s)
"""
from dcim.models import Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, RearPort, FrontPort, DeviceBay
from extras.scripts import Script, MultiObjectVar
class AddDeviceTypeComponents(Script):
class Meta:
name = "Add Device Type Components"
description = "Add missing components to selected devices"
devices = MultiObjectVar(
model=Device,
)
def run(self, data, commit):
for device in data["devices"]:
dt = device.device_type
# Based on Device.save():
# "If this is a new Device, instantiate all of the related components per the DeviceType definition"
# Note that ordering is important: e.g. PowerPort before PowerOutlet, RearPort before FrontPort
for klass, item, templateitem in [
(ConsolePort, 'consoleports', 'consoleporttemplates'),
(ConsoleServerPort, 'consoleserverports', 'consoleserverporttemplates'),
(PowerPort, 'powerports', 'powerporttemplates'),
(PowerOutlet, 'poweroutlets', 'poweroutlettemplates'),
(Interface, 'interfaces', 'interfacetemplates'),
(RearPort, 'rearports', 'rearporttemplates'),
(FrontPort, 'frontports', 'frontporttemplates'),
(DeviceBay,'devicebays', 'devicebaytemplates'),
]:
names = {i.name for i in getattr(device, item).all()}
templates = getattr(dt, templateitem).all()
items = [
x.instantiate(device)
for x in templates
if x.name not in names
]
if items:
klass.objects.bulk_create(items)
self.log_success("%s (%d): created %d %s" % (device.name, device.id, len(items), item))
@candlerb
Copy link
Author

candlerb commented Jan 1, 2022

Changed to "Custom Script" which can be run within Netbox; also refactored to use template.instantiate

@sbeaudoin
Copy link

Usage bug from my part? It gives me :

An exception occurred: TypeError: PowerPortTemplate.instantiate() takes 1 positional argument but 2 were given

Traceback (most recent call last):
  File "/app/netbox/netbox/extras/scripts.py", line 512, in _run_script
    script.output = script.run(data=data, commit=commit)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/scripts/device_add_missing_components.py", line 36, in run
    items = [
            ^
  File "/config/scripts/device_add_missing_components.py", line 37, in <listcomp>
    x.instantiate(device)
TypeError: PowerPortTemplate.instantiate() takes 1 positional argument but 2 were given

@candlerb
Copy link
Author

What's your Netbox version?

Also, there is a more up-to-date version of this script at https://github.com/netbox-community/customizations/blob/master/scripts/add_device_type_components.py

@sbeaudoin
Copy link

Netbox v3.7.3, I will try the other version tomorrow.

@sbeaudoin
Copy link

sbeaudoin commented Feb 27, 2024

I thought it was because I selected two devices in the "devices" dropdown, but it occurs also with only one device.

@sbeaudoin
Copy link

The new version of the script works great. Thank you very much for providing us those fantastic tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment