def find_graph(hostnames): filename = os.path.join(LAB_GRAPHFILE_PATH, LAB_CONNECTION_GRAPH_FILE) with open(filename) as fd: file_list = yaml.safe_load(fd) # Finding the graph file contains all duts from hostnames, for fn in file_list: print_debug_msg( debug_fname, "Looking at conn graph file: %s for hosts %s" % (fn, hostnames)) filename = os.path.join(LAB_GRAPHFILE_PATH, fn) lab_graph = Parse_Lab_Graph(filename) lab_graph.parse_graph() if lab_graph.contains_hosts(hostnames): print_debug_msg( debug_fname, ("Returning lab graph from conn graph file: %s for hosts %s" % (fn, hostnames))) return lab_graph # Fallback to return an empty connection graph, this is # needed to bridge the kvm test needs. The KVM test needs # A graph file, which used to be whatever hardcoded file. # Here we provide one empty file for the purpose. lab_graph = Parse_Lab_Graph( os.path.join(LAB_GRAPHFILE_PATH, EMPTY_GRAPH_FILE)) lab_graph.parse_graph() return lab_graph
def find_graph(hostnames, part=False): """ Find a graph file contains all devices in testbed. duts are spcified by hostnames Parameters: hostnames: list of duts in the target testbed. part: select the graph file if over 80% of hosts are found in conn_graph when part is True """ global debug_fname filename = os.path.join(LAB_GRAPHFILE_PATH, LAB_CONNECTION_GRAPH_FILE) with open(filename) as fd: file_list = yaml.safe_load(fd) # Finding the graph file contains all duts from hostnames, for fn in file_list: print_debug_msg( debug_fname, "Looking at conn graph file: %s for hosts %s" % (fn, hostnames)) filename = os.path.join(LAB_GRAPHFILE_PATH, fn) lab_graph = Parse_Lab_Graph(filename) lab_graph.parse_graph() print_debug_msg( debug_fname, "For file %s, got hostnames %s" % (fn, lab_graph.devices)) if lab_graph.contains_hosts(hostnames, part): print_debug_msg( debug_fname, ("Returning lab graph from conn graph file: %s for hosts %s" % (fn, hostnames))) return lab_graph # Fallback to return an empty connection graph, this is # needed to bridge the kvm test needs. The KVM test needs # A graph file, which used to be whatever hardcoded file. # Here we provide one empty file for the purpose. lab_graph = Parse_Lab_Graph( os.path.join(LAB_GRAPHFILE_PATH, EMPTY_GRAPH_FILE)) lab_graph.parse_graph() return lab_graph
def main(): module = AnsibleModule(argument_spec=dict( host=dict(required=False), hosts=dict(required=False, type='list'), filename=dict(required=False), filepath=dict(required=False), anchor=dict(required=False, type='list'), ), mutually_exclusive=[['host', 'hosts', 'anchor']], supports_check_mode=True) m_args = module.params global debug_fname debug_fname = create_debug_file("/tmp/conn_graph_debug.txt") anchor = m_args['anchor'] if m_args['hosts']: hostnames = m_args['hosts'] elif m_args['host']: hostnames = [m_args['host']] else: # return the whole graph hostnames = [] try: # When called by pytest, the file path is obscured to /tmp/.../. # we need the caller to tell us where the graph files are with # filepath argument. if m_args['filepath']: global LAB_GRAPHFILE_PATH LAB_GRAPHFILE_PATH = m_args['filepath'] if m_args['filename']: filename = os.path.join(LAB_GRAPHFILE_PATH, m_args['filename']) lab_graph = Parse_Lab_Graph(filename) lab_graph.parse_graph() else: # When calling passed in anchor instead of hostnames, # the caller is asking to return the whole graph. This # is needed when configuring the root fanout switch. target = anchor if anchor else hostnames lab_graph = find_graph(target) # early return for the whole graph or empty graph file(vtestbed) if (not hostnames or not lab_graph.devices and not lab_graph.links and not lab_graph.vlanport): results = { 'device_info': lab_graph.devices, 'device_conn': lab_graph.links, 'device_port_vlans': lab_graph.vlanport, } module.exit_json(ansible_facts=results) device_info = {} device_conn = {} device_port_vlans = {} device_vlan_range = {} device_vlan_list = {} device_vlan_map_list = {} device_console_info = {} device_console_link = {} device_pdu_info = {} device_pdu_links = {} for hostname in hostnames: dev = lab_graph.get_host_device_info(hostname) if dev is None: module.fail_json(msg="cannot find info for %s" % hostname) device_info[hostname] = dev device_conn[hostname] = lab_graph.get_host_connections(hostname) host_vlan = lab_graph.get_host_vlan(hostname) port_vlans = lab_graph.get_host_port_vlans(hostname) # for multi-DUTs, must ensure all have vlan configured. if host_vlan: device_vlan_range[hostname] = host_vlan["VlanRange"] device_vlan_list[hostname] = host_vlan["VlanList"] if dev["Type"].lower() != "devsonic": device_vlan_map_list[hostname] = host_vlan["VlanList"] else: device_vlan_map_list[hostname] = {} port_name_list_sorted = get_port_name_list(dev['HwSku']) print_debug_msg( debug_fname, "For %s with hwsku %s, port_name_list is %s" % (hostname, dev['HwSku'], port_name_list_sorted)) for a_host_vlan in host_vlan["VlanList"]: # Get the corresponding port for this vlan from the port vlan list for this hostname found_port_for_vlan = False for a_port in port_vlans: if a_host_vlan in port_vlans[a_port]['vlanlist']: if a_port in port_name_list_sorted: port_index = port_name_list_sorted.index( a_port) device_vlan_map_list[hostname][ port_index] = a_host_vlan found_port_for_vlan = True break else: module.fail_json( msg= "Did not find port for %s in the ports based on hwsku '%s' for host %s" % (a_port, dev['HwSku'], hostname)) if not found_port_for_vlan: module.fail_json( msg= "Did not find corresponding link for vlan %d in %s for host %s" % (a_host_vlan, port_vlans, hostname)) device_port_vlans[hostname] = port_vlans device_console_info[hostname] = lab_graph.get_host_console_info( hostname) device_console_link[hostname] = lab_graph.get_host_console_link( hostname) device_pdu_info[hostname] = lab_graph.get_host_pdu_info(hostname) device_pdu_links[hostname] = lab_graph.get_host_pdu_links(hostname) results = { k: v for k, v in locals().items() if (k.startswith("device_") and v) } module.exit_json(ansible_facts=results) except (IOError, OSError): module.fail_json(msg="Can not find lab graph file under {}".format( LAB_GRAPHFILE_PATH)) except Exception as e: module.fail_json(msg=traceback.format_exc())
def parse_graph(self): """ Parse the xml graph file """ deviceinfo = {} deviceroot = self.root.find(self.pngtag).find('Devices') devices = deviceroot.findall('Device') if devices is not None: for dev in devices: hostname = dev.attrib['Hostname'] if hostname is not None: deviceinfo[hostname] = {} hwsku = dev.attrib['HwSku'] devtype = dev.attrib['Type'] deviceinfo[hostname]['HwSku'] = hwsku deviceinfo[hostname]['Type'] = devtype self.links[hostname] = {} devicel2info = {} devicel3s = self.root.find(self.dpgtag).findall('DevicesL3Info') devicel2s = self.root.find(self.dpgtag).findall('DevicesL2Info') if devicel2s is not None: for l2info in devicel2s: hostname = l2info.attrib['Hostname'] if hostname is not None: devicel2info[hostname] = {} vlans = l2info.findall('InterfaceVlan') for vlan in vlans: portname = vlan.attrib['portname'] portmode = vlan.attrib['mode'] portvlanid = vlan.attrib['vlanids'] portvlanlist = self.port_vlanlist(portvlanid) devicel2info[hostname][portname] = { 'mode': portmode, 'vlanids': portvlanid, 'vlanlist': portvlanlist } if devicel3s is not None: for l3info in devicel3s: hostname = l3info.attrib['Hostname'] if hostname is not None: management_ip = l3info.find( 'ManagementIPInterface').attrib['Prefix'] deviceinfo[hostname]['ManagementIp'] = management_ip mgmtip = ipaddress.IPNetwork(management_ip) deviceinfo[hostname]['mgmtip'] = str(mgmtip.ip) management_gw = str(mgmtip.network + 1) deviceinfo[hostname]['ManagementGw'] = management_gw allinks = self.root.find(self.pngtag).find( 'DeviceInterfaceLinks').findall('DeviceInterfaceLink') if allinks is not None: for link in allinks: start_dev = link.attrib['StartDevice'] end_dev = link.attrib['EndDevice'] if start_dev: self.links[start_dev][link.attrib['StartPort']] = { 'peerdevice': link.attrib['EndDevice'], 'peerport': link.attrib['EndPort'], 'speed': link.attrib['BandWidth'] } if end_dev: self.links[end_dev][link.attrib['EndPort']] = { 'peerdevice': link.attrib['StartDevice'], 'peerport': link.attrib['StartPort'], 'speed': link.attrib['BandWidth'] } console_root = self.root.find(self.csgtag) if console_root: devicecsgroot = console_root.find('DevicesConsoleInfo') devicescsg = devicecsgroot.findall('DeviceConsoleInfo') if devicescsg is not None: for dev in devicescsg: hostname = dev.attrib['Hostname'] if hostname is not None: deviceinfo[hostname] = {} hwsku = dev.attrib['HwSku'] devtype = dev.attrib['Type'] protocol = dev.attrib['Protocol'] mgmt_ip = dev.attrib['ManagementIp'] deviceinfo[hostname]['HwSku'] = hwsku deviceinfo[hostname]['Type'] = devtype deviceinfo[hostname]['Protocol'] = protocol deviceinfo[hostname]['ManagementIp'] = mgmt_ip self.consolelinks[hostname] = {} console_link_root = console_root.find('ConsoleLinksInfo') if console_link_root: allconsolelinks = console_link_root.findall('ConsoleLinkInfo') if allconsolelinks is not None: for consolelink in allconsolelinks: start_dev = consolelink.attrib['StartDevice'] end_dev = consolelink.attrib['EndDevice'] if start_dev: if start_dev not in self.consolelinks: self.consolelinks.update({start_dev: {}}) self.consolelinks[start_dev][ consolelink.attrib['StartPort']] = { 'peerdevice': consolelink.attrib['EndDevice'], 'peerport': 'ConsolePort' } if end_dev: if end_dev not in self.consolelinks: self.consolelinks.update({end_dev: {}}) self.consolelinks[end_dev]['ConsolePort'] = { 'peerdevice': consolelink.attrib['StartDevice'], 'peerport': consolelink.attrib['StartPort'] } pdu_root = self.root.find(self.pcgtag) if pdu_root: devicepcgroot = pdu_root.find('DevicesPowerControlInfo') devicespcsg = devicepcgroot.findall('DevicePowerControlInfo') if devicespcsg is not None: for dev in devicespcsg: hostname = dev.attrib['Hostname'] if hostname is not None: deviceinfo[hostname] = {} hwsku = dev.attrib['HwSku'] devtype = dev.attrib['Type'] protocol = dev.attrib['Protocol'] mgmt_ip = dev.attrib['ManagementIp'] deviceinfo[hostname]['HwSku'] = hwsku deviceinfo[hostname]['Type'] = devtype deviceinfo[hostname]['Protocol'] = protocol deviceinfo[hostname]['ManagementIp'] = mgmt_ip self.pdulinks[hostname] = {} pdu_link_root = pdu_root.find('PowerControlLinksInfo') if pdu_link_root: allpdulinks = pdu_link_root.findall('PowerControlLinkInfo') if allpdulinks is not None: for pdulink in allpdulinks: start_dev = pdulink.attrib['StartDevice'] end_dev = pdulink.attrib['EndDevice'] print_debug_msg(debug_fname, "pdulink {}".format(pdulink.attrib)) print_debug_msg( debug_fname, "self.pdulinks {}".format(self.pdulinks)) if start_dev: if start_dev not in self.pdulinks: self.pdulinks.update({start_dev: {}}) self.pdulinks[start_dev][ pdulink.attrib['StartPort']] = { 'peerdevice': pdulink.attrib['EndDevice'], 'peerport': pdulink.attrib['EndPort'] } if end_dev: if end_dev not in self.pdulinks: self.pdulinks.update({end_dev: {}}) self.pdulinks[end_dev][ pdulink.attrib['EndPort']] = { 'peerdevice': pdulink.attrib['StartDevice'], 'peerport': pdulink.attrib['StartPort'] } self.devices = deviceinfo self.vlanport = devicel2info
def build_results(lab_graph, hostnames, ignore_error=False): """ Refactor code for building json results. Code is refactored because same logic is needed in devutil """ device_info = {} device_conn = {} device_port_vlans = {} device_vlan_range = {} device_vlan_list = {} device_vlan_map_list = {} device_console_info = {} device_console_link = {} device_pdu_info = {} device_pdu_links = {} msg = {} for hostname in hostnames: dev = lab_graph.get_host_device_info(hostname) if dev is None and not ignore_error: msg = "cannot find info for %s" % hostname return (False, msg) device_info[hostname] = dev device_conn[hostname] = lab_graph.get_host_connections(hostname) host_vlan = lab_graph.get_host_vlan(hostname) port_vlans = lab_graph.get_host_port_vlans(hostname) # for multi-DUTs, must ensure all have vlan configured. if host_vlan: device_vlan_range[hostname] = host_vlan["VlanRange"] device_vlan_list[hostname] = host_vlan["VlanList"] if dev["Type"].lower() != "devsonic": device_vlan_map_list[hostname] = host_vlan["VlanList"] else: device_vlan_map_list[hostname] = {} port_name_list_sorted = get_port_name_list(dev['HwSku']) print_debug_msg( debug_fname, "For %s with hwsku %s, port_name_list is %s" % (hostname, dev['HwSku'], port_name_list_sorted)) for a_host_vlan in host_vlan["VlanList"]: # Get the corresponding port for this vlan from the port vlan list for this hostname found_port_for_vlan = False for a_port in port_vlans: if a_host_vlan in port_vlans[a_port]['vlanlist']: if a_port in port_name_list_sorted: port_index = port_name_list_sorted.index( a_port) device_vlan_map_list[hostname][ port_index] = a_host_vlan found_port_for_vlan = True break elif not ignore_error: msg = "Did not find port for %s in the ports based on hwsku '%s' for host %s" % ( a_port, dev['HwSku'], hostname) return (False, msg) if not found_port_for_vlan and not ignore_error: msg = "Did not find corresponding link for vlan %d in %s for host %s" % ( a_host_vlan, port_vlans, hostname) return (False, msg) device_port_vlans[hostname] = port_vlans device_console_info[hostname] = lab_graph.get_host_console_info( hostname) device_console_link[hostname] = lab_graph.get_host_console_link( hostname) device_pdu_info[hostname] = lab_graph.get_host_pdu_info(hostname) device_pdu_links[hostname] = lab_graph.get_host_pdu_links(hostname) results = { k: v for k, v in locals().items() if (k.startswith("device_") and v) } return (True, results)