from django.db.models.signals import post_delete, post_save, pre_delete from django.dispatch import receiver from dcim.models import Device from virtualization.models import VirtualMachine from .models import IPAddress, Prefix def update_parents_children(prefix): """ Update depth on prefix & containing prefixes """ parents = prefix.get_parents(include_self=True).annotate_hierarchy() for parent in parents: parent._children = parent.hierarchy_children Prefix.objects.bulk_update(parents, ['_children']) def update_children_depth(prefix): """ Update children count on prefix & contained prefixes """ children = prefix.get_children(include_self=True).annotate_hierarchy() for child in children: child._depth = child.hierarchy_depth Prefix.objects.bulk_update(children, ['_depth']) @receiver(post_save, sender=Prefix) def handle_prefix_saved(instance, created, **kwargs): # Prefix has changed (or new instance has been created) if created or instance.vrf != instance._vrf or instance.prefix != instance._prefix: update_parents_children(instance) update_children_depth(instance) # If this is not a new prefix, clean up parent/children of previous prefix if not created: old_prefix = Prefix(vrf=instance._vrf, prefix=instance._prefix) update_parents_children(old_prefix) update_children_depth(old_prefix) @receiver(post_delete, sender=Prefix) def handle_prefix_deleted(instance, **kwargs): update_parents_children(instance) update_children_depth(instance) @receiver(pre_delete, sender=IPAddress) def clear_primary_ip(instance, **kwargs): """ When an IPAddress is deleted, trigger save() on any Devices/VirtualMachines for which it was a primary IP. """ field_name = f'primary_ip{instance.family}' device = Device.objects.filter(**{field_name: instance}).first() if device: device.save() virtualmachine = VirtualMachine.objects.filter(**{field_name: instance}).first() if virtualmachine: virtualmachine.save()