From 6f42e246e99aa390e9b55c62bb47ef2ef556c2e6 Mon Sep 17 00:00:00 2001 From: Yaron Yogev Date: Mon, 31 Jul 2017 08:02:26 +0300 Subject: US2765 ACI scanning: Added spine switches and pnics fetching functionality Change-Id: Ifc090b31e3821303b94d7a4efe8f887c47458071 Signed-off-by: Yaron Yogev --- app/config/scanners.json | 9 +++- app/discover/fetchers/aci/aci_fetch_switch_pnic.py | 58 +++++++++++++--------- app/utils/util.py | 4 +- 3 files changed, 45 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/config/scanners.json b/app/config/scanners.json index 3c17918..feaafcb 100644 --- a/app/config/scanners.json +++ b/app/config/scanners.json @@ -225,7 +225,14 @@ "ScanHostPnic": [ { "type": "pnic", - "fetcher": "AciFetchSwitchPnic" + "fetcher": "AciFetchSwitchPnic", + "children_scanner": "ScanSpines" + } + ], + "ScanSpines": [ + { + "type": "pnic", + "fetcher": "AciFetchLeafToSpinePnics" } ], "ScanProject": [ diff --git a/app/discover/fetchers/aci/aci_fetch_switch_pnic.py b/app/discover/fetchers/aci/aci_fetch_switch_pnic.py index a4216ea..965fc79 100644 --- a/app/discover/fetchers/aci/aci_fetch_switch_pnic.py +++ b/app/discover/fetchers/aci/aci_fetch_switch_pnic.py @@ -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] diff --git a/app/utils/util.py b/app/utils/util.py index 4695879..385dea7 100644 --- a/app/utils/util.py +++ b/app/utils/util.py @@ -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): -- cgit 1.2.3-korg