US2853 ACI data & links added 75/38975/1
authorYaron Yogev <yaronyogev@gmail.com>
Wed, 9 Aug 2017 14:15:31 +0000 (17:15 +0300)
committerYaron Yogev <yaronyogev@gmail.com>
Wed, 9 Aug 2017 14:15:31 +0000 (17:15 +0300)
Change-Id: I26d67bd8a03815e816babc5f6bd525bd32efef9c
Signed-off-by: Yaron Yogev <yaronyogev@gmail.com>
app/discover/fetchers/aci/aci_fetch_leaf_to_spine_pnics.py
app/discover/fetchers/aci/aci_fetch_switch_pnic.py
app/discover/fetchers/cli/cli_fetch_host_pnics.py
app/discover/find_links_for_pnics.py

index 48cf243..b9be5cd 100644 (file)
@@ -28,9 +28,9 @@ class AciFetchLeafToSpinePnics(AciAccess):
         self.inv = InventoryMgr()
 
     def fetch_switches_by_role(self, role_name):
-        query_filter = "eq(fabricNode.role, \"{}\")".format(role_name)
-        switches = self.fetch_objects_by_class("fabricNode",
-                                               {"query-target-filter": query_filter})
+        query_filter = {"query-target-filter":
+                        "eq(fabricNode.role, \"{}\")".format(role_name)}
+        switches = self.fetch_objects_by_class("fabricNode", query_filter)
         return [switch["attributes"] for switch in switches]
 
     def fetch_adjacent_connections(self, device_id):
@@ -61,8 +61,10 @@ class AciFetchLeafToSpinePnics(AciAccess):
             if connection:
                 try:
                     # Extract pnics from adjacency data
-                    uplink_pnic = re.match(".*\[(.+?)\].*", connection["dn"]).group(1)
-                    downlink_pnic = re.match(".*\[(.+?)\].*", connection["portDesc"]).group(1)
+                    uplink_pnic = re.match(".*\[(.+?)\].*",
+                                           connection["dn"]).group(1)
+                    downlink_pnic = re.match(".*\[(.+?)\].*",
+                                             connection["portDesc"]).group(1)
                     spines.append({
                         "device": spine,
                         "downlink_pnic": downlink_pnic,
@@ -76,7 +78,8 @@ class AciFetchLeafToSpinePnics(AciAccess):
     @aci_config_required(default=[])
     def get(self, db_leaf_pnic_id):
         environment = self.get_env()
-        pnic = self.inv.get_by_id(environment=environment, item_id=db_leaf_pnic_id)
+        pnic = self.inv.get_by_id(environment=environment,
+                                  item_id=db_leaf_pnic_id)
 
         # Decode aci leaf switch id from db format
         aci_leaf_pnic_id = decode_aci_dn(db_leaf_pnic_id)
@@ -93,22 +96,23 @@ class AciFetchLeafToSpinePnics(AciAccess):
             # Add spine switch to db if it's not there yet
             spine_id_match = re.match("topology/(.+)", spine["dn"])
             if not spine_id_match:
-                raise ValueError("Failed to fetch spine switch id from switch dn: {}"
-                                 .format(spine["dn"]))
+                raise ValueError("Failed to fetch spine switch id "
+                                 "from switch dn: {}".format(spine["dn"]))
 
             aci_spine_id = spine_id_match.group(1)
-            db_spine_id = "-".join(("switch", encode_aci_dn(aci_spine_id), spine["role"]))
+            db_spine_id = "-".join(("switch", encode_aci_dn(aci_spine_id),
+                                    spine["role"]))
             if not self.inv.get_by_id(environment, db_spine_id):
                 spine_json = {
                     "id": db_spine_id,
                     "type": "switch",
-                    "host": db_spine_id,
                     "aci_document": spine
                 }
                 # Region name is the same as region id
                 region_id = get_object_path_part(pnic["name_path"], "Regions")
                 region = self.inv.get_by_id(environment, region_id)
-                self.inv.save_inventory_object(o=spine_json, parent=region, environment=environment)
+                self.inv.save_inventory_object(o=spine_json, parent=region,
+                                               environment=environment)
 
             # Add downlink and uplink pnics to results list,
             # including their mutual connection data
@@ -121,18 +125,20 @@ class AciFetchLeafToSpinePnics(AciAccess):
             downlink_pnic_json = {
                 "id": db_downlink_pnic_id,
                 "type": "pnic",
+                "role": "downlink",
                 "pnic_type": "switch",
-                "host": db_spine_id,
                 "connected_to": db_uplink_pnic_id,
+                "switch": db_spine_id,
                 "aci_document": {}  # TODO: what can we add here?
             }
 
             uplink_pnic_json = {
                 "id": db_uplink_pnic_id,
                 "type": "pnic",
+                "role": "uplink",
                 "pnic_type": "switch",
-                "host": pnic["host"],
                 "connected_to": db_downlink_pnic_id,
+                "switch": db_spine_id,
                 "aci_document": {}  # TODO: what can we add here?
             }
 
index 965fc79..2b1a21d 100644 (file)
@@ -30,10 +30,10 @@ class AciFetchSwitchPnic(AciAccess):
         mac_filter = "eq(epmMacEp.addr,\"{}\")".format(mac_address)
         # We are only interested in Ethernet interfaces
         pnic_filter = "wcard(epmMacEp.ifId, \"eth\")"
-        query_filter = "and({},{})".format(mac_filter, pnic_filter)
+        query_filter = {"query-target-filter":
+                        "and({},{})".format(mac_filter, pnic_filter)}
 
-        pnics = self.fetch_objects_by_class("epmMacEp",
-                                            {"query-target-filter": query_filter})
+        pnics = self.fetch_objects_by_class("epmMacEp", query_filter)
 
         return [pnic["attributes"] for pnic in pnics]
 
@@ -41,7 +41,8 @@ class AciFetchSwitchPnic(AciAccess):
         dn = "/".join((switch_id, "sys"))
         response = self.fetch_mo_data(dn)
         # Unwrap switches
-        switch_data = self.get_objects_by_field_names(response, "topSystem", "attributes")
+        switch_data = self.get_objects_by_field_names(response, "topSystem",
+                                                      "attributes")
         return switch_data[0] if switch_data else None
 
     @aci_config_required(default=[])
@@ -73,7 +74,8 @@ class AciFetchSwitchPnic(AciAccess):
                              .format(leaf_pnic["dn"]))
             return []
 
-        db_leaf_id = "-".join(("switch", encode_aci_dn(aci_leaf_id), leaf_data["role"]))
+        db_leaf_id = "-".join(("switch", encode_aci_dn(aci_leaf_id),
+                               leaf_data["role"]))
         if not self.inv.get_by_id(environment, db_leaf_id):
             leaf_json = {
                 "id": db_leaf_id,
@@ -85,7 +87,8 @@ class AciFetchSwitchPnic(AciAccess):
             # Region name is the same as region id
             region_id = get_object_path_part(pnic["name_path"], "Regions")
             region = self.inv.get_by_id(environment, region_id)
-            self.inv.save_inventory_object(o=leaf_json, parent=region, environment=environment)
+            self.inv.save_inventory_object(o=leaf_json, parent=region,
+                                           environment=environment)
 
         # Prepare pnic json for results list
         db_pnic_id = "-".join((db_leaf_id,
@@ -94,10 +97,12 @@ class AciFetchSwitchPnic(AciAccess):
         pnic_json = {
             "id": db_pnic_id,
             "type": "pnic",
+            "role": "hostlink",
+            "parent_id": db_leaf_id,
             "pnic_type": "switch",
             "mac_address": mac_address,
-            "host": db_leaf_id,
+            "host": pnic["host"],
+            "switch": db_leaf_id,
             "aci_document": leaf_pnic
         }
         return [pnic_json]
-
index 3516e25..86aa693 100644 (file)
@@ -71,7 +71,8 @@ class CliFetchHostPnics(CliAccess):
                         "host": host_id,
                         "name": id,
                         "local_name": interface_name,
-                        "lines": []
+                        "lines": [],
+                        "pnic_type": "host"
                     }
                     self.handle_line(interface, line_remainder)
                     if '<UP,' in line:
index 19828d0..717c1c1 100644 (file)
@@ -18,10 +18,11 @@ class FindLinksForPnics(FindLinks):
         pnics = self.inv.find_items({
             "environment": self.get_env(),
             "type": "pnic",
-            "pnic_type": {"$ne": "switch"}  # TODO: make a more educated guess
+            "pnic_type": "host"
         })
         for pnic in pnics:
             self.add_pnic_network_links(pnic)
+            self.add_host_pnic_to_switch_pnic_link(pnic)
 
     def add_pnic_network_links(self, pnic):
         self.log.info("adding links of type: pnic-network")
@@ -56,3 +57,31 @@ class FindLinksForPnics(FindLinks):
                              link_type, link_name, state, link_weight,
                              source_label,
                              extra_attributes={"network": target_id})
+
+    def add_host_pnic_to_switch_pnic_link(self, host_pnic):
+        link_type = "host_pnic-switch_pnic"
+        self.log.info("adding links of type: {}".format(link_type))
+        # find ports for that host, and fetch just the network ID
+        switch_pnics = self.inv.find_items({
+            "environment": self.get_env(),
+            "type": "pnic",
+            "pnic_type": "switch",
+            "mac_address": host_pnic["mac_address"]
+        }, {"id": 1})
+        if not switch_pnics:
+            return
+        if len(switch_pnics) > 1:
+            self.log.warn("multiple matching switch pNICs found "
+                          "for host pNIC: mac_address={}"
+                          .format(host_pnic["mac_address"]))
+        switch_pnic = switch_pnics[0]
+        source = host_pnic["_id"]
+        source_id = host_pnic["id"]
+        target = switch_pnic["_id"]
+        target_id = switch_pnic["id"]
+        link_name = "{}-{}".format(target_id, source_id)
+        state = "up" if host_pnic["Link detected"] == "yes" else "down"
+        link_weight = 0  # TBD
+        self.create_link(self.get_env(), host_pnic['host'],
+                         source, source_id, target, target_id,
+                         link_type, link_name, state, link_weight)
\ No newline at end of file