from dcim.models import Device from extras.scripts import Script, ObjectVar class ReplaceDevice(Script): ''' Replace a device with another. Used for instance to upgrade classroom PCs. This renames the new device, switches existing primary IPs from the old device to it and sets it active. The old device is unnamed and set as inventory. ''' class Meta: name = 'Replace device' description = 'Replace a device with another, preserving the name and primary IPs' commit_default = False scheduling_enabled = False old = ObjectVar(model=Device, label='Old device') new = ObjectVar(model=Device, label='New device') def run(self, data, commit): old = data['old'] new = data['new'] new.name = old.name new.status = 'active' old.name = None if old.status == 'active': # could be failed old.status = 'inventory' if ip4 := old.primary_ip4: old.primary_ip4 = None old.full_clean() old.save() old_iface = ip4.interface.get() new_iface = new.interfaces.get(name=old_iface.name) ip4.assigned_object = new_iface ip4.full_clean() ip4.save() new.primary_ip4 = ip4 self.log_info(f'set {ip4} as primary IP for new {new.name} ({new.asset_tag})') if ip6 := old.primary_ip6: old.primary_ip6 = None old.full_clean() old.save() old_iface = ip6.interface.get() new_iface = new.interfaces.get(name=old_iface.name) ip6.assigned_object = new_iface ip6.full_clean() ip6.save() new.primary_ip6 = ip6 self.log_info(f'set {ip6} as primary IP for new {new.name} ({new.asset_tag})') new.full_clean() new.save() self.log_success(f'replaced device {new.name}: {old.asset_tag} → {new.asset_tag}')