|
112 | 112 | - tenant
|
113 | 113 | - racks
|
114 | 114 | - rack
|
| 115 | + - rack_group |
| 116 | + - rack_role |
115 | 117 | - tags
|
116 | 118 | - tag
|
117 | 119 | - device_roles
|
@@ -367,6 +369,8 @@ def group_extractors(self):
|
367 | 369 | self._pluralize_group_by("site"): self.extract_site,
|
368 | 370 | self._pluralize_group_by("tenant"): self.extract_tenant,
|
369 | 371 | self._pluralize_group_by("rack"): self.extract_rack,
|
| 372 | + "rack_group": self.extract_rack_group, |
| 373 | + "rack_role": self.extract_rack_role, |
370 | 374 | self._pluralize_group_by("tag"): self.extract_tags,
|
371 | 375 | self._pluralize_group_by("role"): self.extract_device_role,
|
372 | 376 | self._pluralize_group_by("platform"): self.extract_platform,
|
@@ -411,6 +415,28 @@ def _pluralize(self, extracted_value):
|
411 | 415 | else:
|
412 | 416 | return extracted_value
|
413 | 417 |
|
| 418 | + def _objects_array_following_parents( |
| 419 | + self, initial_object_id, object_lookup, object_parent_lookup |
| 420 | + ): |
| 421 | + objects = [] |
| 422 | + |
| 423 | + object_id = initial_object_id |
| 424 | + |
| 425 | + # Keep looping until the object has no parent |
| 426 | + while object_id is not None: |
| 427 | + object_slug = object_lookup[object_id] |
| 428 | + |
| 429 | + if object_slug in objects: |
| 430 | + # Won't ever happen - defensively guard against infinite loop |
| 431 | + break |
| 432 | + |
| 433 | + objects.append(object_slug) |
| 434 | + |
| 435 | + # Get the parent of this object |
| 436 | + object_id = object_parent_lookup[object_id] |
| 437 | + |
| 438 | + return objects |
| 439 | + |
414 | 440 | def extract_disk(self, host):
|
415 | 441 | return host.get("disk")
|
416 | 442 |
|
@@ -451,6 +477,35 @@ def extract_rack(self, host):
|
451 | 477 | except Exception:
|
452 | 478 | return
|
453 | 479 |
|
| 480 | + def extract_rack_group(self, host): |
| 481 | + # A host may have a rack. A rack may have a rack_group. A rack_group may have a parent rack_group. |
| 482 | + # Produce a list of rack_groups: |
| 483 | + # - it will be empty if the device has no rack, or the rack has no rack_group |
| 484 | + # - it will have 1 element if the rack's group has no parent |
| 485 | + # - it will have multiple elements if the rack's group has a parent group |
| 486 | + |
| 487 | + rack = host.get("rack", None) |
| 488 | + if not isinstance(rack, dict): |
| 489 | + # Device has no rack |
| 490 | + return None |
| 491 | + |
| 492 | + rack_id = rack.get("id", None) |
| 493 | + if rack_id is None: |
| 494 | + # Device has no rack |
| 495 | + return None |
| 496 | + |
| 497 | + return self._objects_array_following_parents( |
| 498 | + initial_object_id=self.racks_group_lookup[rack_id], |
| 499 | + object_lookup=self.rack_groups_lookup, |
| 500 | + object_parent_lookup=self.rack_group_parent_lookup, |
| 501 | + ) |
| 502 | + |
| 503 | + def extract_rack_role(self, host): |
| 504 | + try: |
| 505 | + return self.racks_role_lookup[host["rack"]["id"]] |
| 506 | + except Exception: |
| 507 | + return |
| 508 | + |
454 | 509 | def extract_site(self, host):
|
455 | 510 | try:
|
456 | 511 | return self._pluralize(self.sites_lookup[host["site"]["id"]])
|
@@ -570,21 +625,11 @@ def extract_regions(self, host):
|
570 | 625 | # Device has no site
|
571 | 626 | return []
|
572 | 627 |
|
573 |
| - regions = [] |
574 |
| - region_id = self.sites_region_lookup[site_id] |
575 |
| - |
576 |
| - # Keep looping until the region has no parent |
577 |
| - while region_id is not None: |
578 |
| - region_slug = self.regions_lookup[region_id] |
579 |
| - if region_slug in regions: |
580 |
| - # Won't ever happen - defensively guard against infinite loop |
581 |
| - break |
582 |
| - regions.append(region_slug) |
583 |
| - |
584 |
| - # Get the parent of this region |
585 |
| - region_id = self.regions_parent_lookup[region_id] |
586 |
| - |
587 |
| - return regions |
| 628 | + return self._objects_array_following_parents( |
| 629 | + initial_object_id=self.sites_region_lookup[site_id], |
| 630 | + object_lookup=self.regions_lookup, |
| 631 | + object_parent_lookup=self.regions_parent_lookup, |
| 632 | + ) |
588 | 633 |
|
589 | 634 | def extract_cluster(self, host):
|
590 | 635 | try:
|
@@ -628,9 +673,7 @@ def get_region_for_site(site):
|
628 | 673 | return (site["id"], None)
|
629 | 674 |
|
630 | 675 | # Dictionary of site id to region id
|
631 |
| - self.sites_region_lookup = dict( |
632 |
| - filter(lambda x: x is not None, map(get_region_for_site, sites)) |
633 |
| - ) |
| 676 | + self.sites_region_lookup = dict(map(get_region_for_site, sites)) |
634 | 677 |
|
635 | 678 | def refresh_regions_lookup(self):
|
636 | 679 | url = self.api_endpoint + "/api/dcim/regions/?limit=0"
|
@@ -659,6 +702,37 @@ def refresh_racks_lookup(self):
|
659 | 702 | racks = self.get_resource_list(api_url=url)
|
660 | 703 | self.racks_lookup = dict((rack["id"], rack["name"]) for rack in racks)
|
661 | 704 |
|
| 705 | + def get_group_for_rack(rack): |
| 706 | + try: |
| 707 | + return (rack["id"], rack["group"]["id"]) |
| 708 | + except Exception: |
| 709 | + return (rack["id"], None) |
| 710 | + |
| 711 | + def get_role_for_rack(rack): |
| 712 | + try: |
| 713 | + return (rack["id"], rack["role"]["slug"]) |
| 714 | + except Exception: |
| 715 | + return (rack["id"], None) |
| 716 | + |
| 717 | + self.racks_group_lookup = dict(map(get_group_for_rack, racks)) |
| 718 | + self.racks_role_lookup = dict(map(get_role_for_rack, racks)) |
| 719 | + |
| 720 | + def refresh_rack_groups_lookup(self): |
| 721 | + url = self.api_endpoint + "/api/dcim/rack-groups/?limit=0" |
| 722 | + rack_groups = self.get_resource_list(api_url=url) |
| 723 | + self.rack_groups_lookup = dict( |
| 724 | + (rack_group["id"], rack_group["slug"]) for rack_group in rack_groups |
| 725 | + ) |
| 726 | + |
| 727 | + def get_rack_group_parent(rack_group): |
| 728 | + try: |
| 729 | + return (rack_group["id"], rack_group["parent"]["id"]) |
| 730 | + except Exception: |
| 731 | + return (rack_group["id"], None) |
| 732 | + |
| 733 | + # Dictionary of rack group id to parent rack group id |
| 734 | + self.rack_group_parent_lookup = dict(map(get_rack_group_parent, rack_groups)) |
| 735 | + |
662 | 736 | def refresh_device_roles_lookup(self):
|
663 | 737 | url = self.api_endpoint + "/api/dcim/device-roles/?limit=0"
|
664 | 738 | device_roles = self.get_resource_list(api_url=url)
|
@@ -698,13 +772,8 @@ def get_cluster_group(cluster):
|
698 | 772 | except Exception:
|
699 | 773 | return (cluster["id"], None)
|
700 | 774 |
|
701 |
| - self.clusters_type_lookup = dict( |
702 |
| - filter(lambda x: x is not None, map(get_cluster_type, clusters)) |
703 |
| - ) |
704 |
| - |
705 |
| - self.clusters_group_lookup = dict( |
706 |
| - filter(lambda x: x is not None, map(get_cluster_group, clusters)) |
707 |
| - ) |
| 775 | + self.clusters_type_lookup = dict(map(get_cluster_type, clusters)) |
| 776 | + self.clusters_group_lookup = dict(map(get_cluster_group, clusters)) |
708 | 777 |
|
709 | 778 | def refresh_services(self):
|
710 | 779 | url = self.api_endpoint + "/api/ipam/services/?limit=0"
|
@@ -855,6 +924,7 @@ def lookup_processes(self):
|
855 | 924 | self.refresh_regions_lookup,
|
856 | 925 | self.refresh_tenants_lookup,
|
857 | 926 | self.refresh_racks_lookup,
|
| 927 | + self.refresh_rack_groups_lookup, |
858 | 928 | self.refresh_device_roles_lookup,
|
859 | 929 | self.refresh_platforms_lookup,
|
860 | 930 | self.refresh_device_types_lookup,
|
@@ -1184,6 +1254,9 @@ def _fill_host_variables(self, host, hostname):
|
1184 | 1254 | if attribute == "region":
|
1185 | 1255 | attribute = "regions"
|
1186 | 1256 |
|
| 1257 | + if attribute == "rack_group": |
| 1258 | + attribute = "rack_groups" |
| 1259 | + |
1187 | 1260 | # Flatten the dict into separate host vars, if enabled
|
1188 | 1261 | if isinstance(extracted_value, dict) and (
|
1189 | 1262 | (attribute == "config_context" and self.flatten_config_context)
|
|
0 commit comments