@@ -397,11 +397,13 @@ def extract_platform(self, host):
397
397
398
398
def extract_services (self , host ):
399
399
try :
400
- return (
400
+ services_lookup = (
401
401
self .vm_services_lookup
402
402
if host ["is_virtual" ]
403
403
else self .device_services_lookup
404
- )[host ["id" ]]
404
+ )
405
+
406
+ return list (services_lookup [host ["id" ]].values ())
405
407
406
408
except Exception :
407
409
return
@@ -485,15 +487,20 @@ def extract_tags(self, host):
485
487
486
488
def extract_interfaces (self , host ):
487
489
try :
488
- interfaces = (
490
+
491
+ interfaces_lookup = (
489
492
self .vm_interfaces_lookup
490
493
if host ["is_virtual" ]
491
494
else self .device_interfaces_lookup
492
- )[host ["id" ]]
495
+ )
496
+
497
+ interfaces = list (interfaces_lookup [host ["id" ]].values ())
493
498
494
499
# Attach IP Addresses to their interface
495
500
for interface in interfaces :
496
- interface ["ip_addresses" ] = self .ipaddresses_lookup [interface ["id" ]]
501
+ interface ["ip_addresses" ] = list (
502
+ self .ipaddresses_lookup [interface ["id" ]].values ()
503
+ )
497
504
498
505
return interfaces
499
506
except Exception :
@@ -677,18 +684,23 @@ def refresh_services(self):
677
684
)
678
685
services = chain (device_services , vm_services )
679
686
680
- # Construct a dictionary of lists , separately for devices and vms.
681
- # Allows looking up a list of services by device id or vm id
682
- self .device_services_lookup = defaultdict (list )
683
- self .vm_services_lookup = defaultdict (list )
687
+ # Construct a dictionary of dictionaries , separately for devices and vms.
688
+ # Allows looking up services by device id or vm id
689
+ self .device_services_lookup = defaultdict (dict )
690
+ self .vm_services_lookup = defaultdict (dict )
684
691
685
692
for service in services :
693
+ service_id = service ["id" ]
694
+
686
695
if service .get ("device" ):
687
- self .device_services_lookup [service ["device" ]["id" ]].append (service )
696
+ self .device_services_lookup [service ["device" ]["id" ]][
697
+ service_id
698
+ ] = service
699
+
688
700
if service .get ("virtual_machine" ):
689
- self .vm_services_lookup [service ["virtual_machine" ]["id" ]]. append (
690
- service
691
- )
701
+ self .vm_services_lookup [service ["virtual_machine" ]["id" ]][
702
+ service_id
703
+ ] = service
692
704
693
705
def refresh_interfaces (self ):
694
706
@@ -715,14 +727,17 @@ def refresh_interfaces(self):
715
727
query_values = self .vms_lookup .keys (),
716
728
)
717
729
718
- # Construct a dictionary of lists, separately for devices and vms.
719
- # Allows looking up a list of interfaces by device id or vm id
720
- self .device_interfaces_lookup = defaultdict (list )
721
- self .vm_interfaces_lookup = defaultdict (list )
730
+ # Construct a dictionary of dictionaries, separately for devices and vms.
731
+ # For a given device id or vm id, get a lookup of interface id to interface
732
+ # This is because interfaces may be returned multiple times when querying for virtual chassis parent and child in separate queries
733
+ self .device_interfaces_lookup = defaultdict (dict )
734
+ self .vm_interfaces_lookup = defaultdict (dict )
735
+
722
736
# /dcim/interfaces gives count_ipaddresses per interface. /virtualization/interfaces does not
723
737
self .devices_with_ips = set ()
724
738
725
739
for interface in device_interfaces :
740
+ interface_id = interface ["id" ]
726
741
device_id = interface ["device" ]["id" ]
727
742
728
743
# Check if device_id is actually a device we've fetched, and was not filtered out by query_filters
@@ -736,16 +751,17 @@ def refresh_interfaces(self):
736
751
if virtual_chassis_master is not None :
737
752
device_id = virtual_chassis_master
738
753
739
- self .device_interfaces_lookup [device_id ]. append ( interface )
754
+ self .device_interfaces_lookup [device_id ][ interface_id ] = interface
740
755
741
756
# Keep track of what devices have interfaces with IPs, so if fetch_all is False we can avoid unnecessary queries
742
757
if interface ["count_ipaddresses" ] > 0 :
743
758
self .devices_with_ips .add (device_id )
744
759
745
760
for interface in vm_interfaces :
746
- self .vm_interfaces_lookup [interface ["virtual_machine" ]["id" ]].append (
747
- interface
748
- )
761
+ interface_id = interface ["id" ]
762
+ vm_id = interface ["virtual_machine" ]["id" ]
763
+
764
+ self .vm_interfaces_lookup [vm_id ][interface_id ] = interface
749
765
750
766
# Note: depends on the result of refresh_interfaces for self.devices_with_ips
751
767
def refresh_ipaddresses (self ):
@@ -773,13 +789,17 @@ def refresh_ipaddresses(self):
773
789
774
790
# Construct a dictionary of lists, to allow looking up ip addresses by interface id
775
791
# Note that interface ids share the same namespace for both devices and vms so this is a single dictionary
776
- self .ipaddresses_lookup = defaultdict (list )
792
+ self .ipaddresses_lookup = defaultdict (dict )
793
+
777
794
for ipaddress in ipaddresses :
778
795
779
796
if not ipaddress .get ("interface" ):
780
797
continue
781
798
782
- self .ipaddresses_lookup [ipaddress ["interface" ]["id" ]].append (ipaddress )
799
+ interface_id = ipaddress ["interface" ]["id" ]
800
+ ip_id = ipaddress ["id" ]
801
+
802
+ self .ipaddresses_lookup [interface_id ][ip_id ] = ipaddress
783
803
784
804
# Remove "interface" attribute, as that's redundant when ipaddress is added to an interface
785
805
del ipaddress ["interface" ]
0 commit comments