US2765 ACI scanning: 09/38409/1
authorYaron Yogev <yaronyogev@gmail.com>
Mon, 31 Jul 2017 05:02:26 +0000 (08:02 +0300)
committerYaron Yogev <yaronyogev@gmail.com>
Mon, 31 Jul 2017 05:59:46 +0000 (08:59 +0300)
Added spine switches and pnics fetching functionality

Change-Id: Ifc090b31e3821303b94d7a4efe8f887c47458071
Signed-off-by: Yaron Yogev <yaronyogev@gmail.com>
app/config/scanners.json
app/discover/fetchers/aci/aci_fetch_switch_pnic.py
app/utils/util.py

index 3c17918..feaafcb 100644 (file)
     "ScanHostPnic": [
       {
         "type": "pnic",
-        "fetcher": "AciFetchSwitchPnic"
+        "fetcher": "AciFetchSwitchPnic",
+        "children_scanner": "ScanSpines"
+      }
+    ],
+    "ScanSpines": [
+      {
+        "type": "pnic",
+        "fetcher": "AciFetchLeafToSpinePnics"
       }
     ],
     "ScanProject": [
index a4216ea..965fc79 100644 (file)
@@ -14,6 +14,12 @@ from utils.inventory_mgr import InventoryMgr
 from utils.util import encode_aci_dn, get_object_path_part
 
 
+# Fetches and adds to database:
+# 1. ACI Switch
+#
+# Returns:
+# 1. ACI Switch pnic that belongs to the ACI Switch (mentioned above)
+# and is connected to Calipso host pnic.
 class AciFetchSwitchPnic(AciAccess):
 
     def __init__(self):
@@ -22,6 +28,7 @@ class AciFetchSwitchPnic(AciAccess):
 
     def fetch_pnics_by_mac_address(self, mac_address):
         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)
 
@@ -33,6 +40,7 @@ class AciFetchSwitchPnic(AciAccess):
     def fetch_switch_by_id(self, switch_id):
         dn = "/".join((switch_id, "sys"))
         response = self.fetch_mo_data(dn)
+        # Unwrap switches
         switch_data = self.get_objects_by_field_names(response, "topSystem", "attributes")
         return switch_data[0] if switch_data else None
 
@@ -46,46 +54,50 @@ class AciFetchSwitchPnic(AciAccess):
         if not mac_address:
             return []
 
-        switch_pnics = self.fetch_pnics_by_mac_address(mac_address)
-        if not switch_pnics:
+        # Query ACI for related switch pnic
+        leaf_pnics = self.fetch_pnics_by_mac_address(mac_address)
+        if not leaf_pnics:
             return []
-        switch_pnic = switch_pnics[0]
+        leaf_pnic = leaf_pnics[0]
 
         # Prepare and save switch data in inventory
-        aci_id_match = re.match("topology/(.+)/sys", switch_pnic["dn"])
-        if not aci_id_match:
-            raise ValueError("Failed to fetch switch id from pnic dn: {}"
-                             .format(switch_pnic["dn"]))
+        leaf_id_match = re.match("topology/(.+)/sys", leaf_pnic["dn"])
+        if not leaf_id_match:
+            raise ValueError("Failed to fetch leaf switch id from pnic dn: {}"
+                             .format(leaf_pnic["dn"]))
 
-        aci_switch_id = aci_id_match.group(1)
-        db_switch_id = encode_aci_dn(aci_switch_id)
-        if not self.inv.get_by_id(environment, db_switch_id):
-            switch_data = self.fetch_switch_by_id(aci_switch_id)
-            if not switch_data:
-                self.log.warning("No switch found for switch pnic dn: {}"
-                                 .format(switch_pnic["dn"]))
-                return []
+        aci_leaf_id = leaf_id_match.group(1)
+        leaf_data = self.fetch_switch_by_id(aci_leaf_id)
+        if not leaf_data:
+            self.log.warning("No switch found for switch pnic dn: {}"
+                             .format(leaf_pnic["dn"]))
+            return []
 
-            switch_json = {
-                "id": db_switch_id,
-                "ip_address": switch_data["address"],
+        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,
+                "ip_address": leaf_data["address"],
                 "type": "switch",
-                "aci_document": switch_data
+                "host": db_leaf_id,
+                "aci_document": leaf_data
             }
             # 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=switch_json, parent=region, environment=environment)
+            self.inv.save_inventory_object(o=leaf_json, parent=region, environment=environment)
 
-        db_pnic_id = "-".join((db_switch_id,
-                               encode_aci_dn(switch_pnic["ifId"]),
+        # Prepare pnic json for results list
+        db_pnic_id = "-".join((db_leaf_id,
+                               encode_aci_dn(leaf_pnic["ifId"]),
                                mac_address))
         pnic_json = {
             "id": db_pnic_id,
             "type": "pnic",
             "pnic_type": "switch",
             "mac_address": mac_address,
-            "aci_document": switch_pnic
+            "host": db_leaf_id,
+            "aci_document": leaf_pnic
         }
         return [pnic_json]
 
index 4695879..385dea7 100644 (file)
@@ -160,11 +160,11 @@ def get_extension(file_path: str) -> str:
 
 
 def encode_aci_dn(object_id):
-    return object_id.replace("topology/", "").replace("/", "___").replace("-", "__")
+    return object_id.replace("topology/", "").replace("/", "__")
 
 
 def decode_aci_dn(object_id):
-    return object_id.replace("___", "/").replace("__", "-")
+    return object_id.replace("__", "/")
 
 
 def get_object_path_part(path: str, part_name: str):