utils.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. from collections import defaultdict
  2. from django.apps import apps
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.db import router, transaction
  5. def compile_path_node(ct_id, object_id):
  6. return f'{ct_id}:{object_id}'
  7. def decompile_path_node(repr):
  8. ct_id, object_id = repr.split(':')
  9. return int(ct_id), int(object_id)
  10. def object_to_path_node(obj):
  11. """
  12. Return a representation of an object suitable for inclusion in a CablePath path. Node representation is in the
  13. form <ContentType ID>:<Object ID>.
  14. """
  15. ct = ContentType.objects.get_for_model(obj)
  16. return compile_path_node(ct.pk, obj.pk)
  17. def path_node_to_object(repr):
  18. """
  19. Given the string representation of a path node, return the corresponding instance. If the object no longer
  20. exists, return None.
  21. """
  22. ct_id, object_id = decompile_path_node(repr)
  23. ct = ContentType.objects.get_for_id(ct_id)
  24. return ct.model_class().objects.filter(pk=object_id).first()
  25. def create_cablepaths(objects):
  26. """
  27. Create CablePaths for all paths originating from the specified set of nodes.
  28. :param objects: Iterable of cabled objects (e.g. Interfaces)
  29. """
  30. from dcim.models import CablePath
  31. # Arrange objects by cable connector. All objects with a null connector are grouped together.
  32. origins = defaultdict(list)
  33. for obj in objects:
  34. origins[obj.cable_connector].append(obj)
  35. for connector, objects in origins.items():
  36. if cp := CablePath.from_origin(objects):
  37. cp.save()
  38. def rebuild_paths(terminations):
  39. """
  40. Rebuild all CablePaths which traverse the specified nodes.
  41. """
  42. from dcim.models import CablePath
  43. for obj in terminations:
  44. cable_paths = CablePath.objects.filter(_nodes__contains=obj)
  45. with transaction.atomic(using=router.db_for_write(CablePath)):
  46. for cp in cable_paths:
  47. cp.delete()
  48. create_cablepaths(cp.origins)
  49. def update_interface_bridges(device, interface_templates, module=None):
  50. """
  51. Used for device and module instantiation. Iterates all InterfaceTemplates with a bridge assigned
  52. and applies it to the actual interfaces.
  53. """
  54. Interface = apps.get_model('dcim', 'Interface')
  55. for interface_template in interface_templates.exclude(bridge=None):
  56. interface = Interface.objects.get(device=device, name=interface_template.resolve_name(module=module))
  57. if interface_template.bridge:
  58. interface.bridge = Interface.objects.get(
  59. device=device,
  60. name=interface_template.bridge.resolve_name(module=module)
  61. )
  62. interface.full_clean()
  63. interface.save()
  64. def create_port_mappings(device, device_or_module_type, module=None):
  65. """
  66. Replicate all front/rear port mappings from a DeviceType or ModuleType to the given device.
  67. """
  68. from dcim.models import FrontPort, PortMapping, RearPort
  69. templates = device_or_module_type.port_mappings.prefetch_related('front_port', 'rear_port')
  70. # Cache front & rear ports for efficient lookups by name
  71. front_ports = {
  72. fp.name: fp for fp in FrontPort.objects.filter(device=device)
  73. }
  74. rear_ports = {
  75. rp.name: rp for rp in RearPort.objects.filter(device=device)
  76. }
  77. # Replicate PortMappings
  78. mappings = []
  79. for template in templates:
  80. front_port = front_ports.get(template.front_port.resolve_name(module=module))
  81. rear_port = rear_ports.get(template.rear_port.resolve_name(module=module))
  82. mappings.append(
  83. PortMapping(
  84. device_id=front_port.device_id,
  85. front_port=front_port,
  86. front_port_position=template.front_port_position,
  87. rear_port=rear_port,
  88. rear_port_position=template.rear_port_position,
  89. )
  90. )
  91. PortMapping.objects.bulk_create(mappings)