def test_voq_switch_create(self, duthosts, enum_frontend_dut_hostname, enum_asic_index, all_cfg_facts): """Compare the config facts with the asic db for switch: * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs. * Verify object creation and values of port attributes. """ per_host = duthosts[enum_frontend_dut_hostname] asic = per_host.asics[enum_asic_index if enum_asic_index is not None else 0] cfg_facts = all_cfg_facts[per_host.hostname][asic.asic_index]['ansible_facts'] dev_facts = cfg_facts['DEVICE_METADATA']['localhost'] asicdb = AsicDbCli(asic) switchkey = asicdb.get_switch_key() logger.info("Checking switch %s", switchkey) check_list = { "max_cores": "SAI_SWITCH_ATTR_MAX_SYSTEM_CORES", "switch_id": "SAI_SWITCH_ATTR_SWITCH_ID"} for k in check_list: asicdb.get_and_check_key_value(switchkey, dev_facts[k], field=check_list[k]) pytest_assert(dev_facts["switch_id"] not in TestVoqSwitch.SWITCH_ID_LIST, "Switch ID: %s has been used more than once" % dev_facts["switch_id"]) TestVoqSwitch.SWITCH_ID_LIST.append(dev_facts["switch_id"]) asicdb.get_and_check_key_value(switchkey, "SAI_SWITCH_TYPE_VOQ", field="SAI_SWITCH_ATTR_TYPE")
def test_voq_local_port_create(duthosts, enum_frontend_dut_hostname, enum_asic_index, all_cfg_facts): """Compare the config facts with the asic db for local ports * Verify ASIC_DB has host interface information for all local ports on all cards and ASICs. * Verify host interfaces exist on host CLI (ifconfig). * Verify interfaces exist in show interfaces on the linecard. """ per_host = duthosts[enum_frontend_dut_hostname] asic = per_host.asics[enum_asic_index if enum_asic_index is not None else 0] cfg_facts = all_cfg_facts[per_host.hostname][asic.asic_index]['ansible_facts'] dev_ports = cfg_facts['PORT'] asicdb = AsicDbCli(asic) hostif_table = asicdb.get_hostif_table(refresh=True) keylist = hostif_table.keys() pytest_assert(len(keylist) == len(dev_ports.keys()), "Found %d hostif keys, %d entries in cfg_facts" % (len(keylist), len(dev_ports.keys()))) logger.info("Found %s ports to check on host:%s, asic: %s.", len(dev_ports.keys()), per_host.hostname, asic.asic_index) show_intf = asic.show_interface(command="status", include_internal_intfs=True)['ansible_facts'] for portkey in keylist: portkey = portkey.decode('unicode-escape') # need to handle the hyphen in the inband port name port_name = hostif_table[portkey]['value']["SAI_HOSTIF_ATTR_NAME"].decode('unicode-escape') port_state = hostif_table[portkey]['value']["SAI_HOSTIF_ATTR_OPER_STATUS"] port_type = hostif_table[portkey]['value']["SAI_HOSTIF_ATTR_TYPE"] logger.info("Checking port: %s, state: %s", port_name, port_state) # "SAI_HOSTIF_ATTR_NAME": "Ethernet0", # "SAI_HOSTIF_ATTR_OBJ_ID": "oid:0x1000000000002", # "SAI_HOSTIF_ATTR_OPER_STATUS": "false", # "SAI_HOSTIF_ATTR_TYPE": "SAI_HOSTIF_TYPE_NETDEV" pytest_assert(port_type == "SAI_HOSTIF_TYPE_NETDEV", "Port %s is not type netdev" % portkey) if port_state == "true": pytest_assert(show_intf['int_status'][port_name]['oper_state'] == "up", "Show interface state is down when it should be up") if port_state == "false": pytest_assert(show_intf['int_status'][port_name]['oper_state'] == "down", "Show interface state is up when it should be down") if asic.namespace is None: cmd = "sudo ifconfig %s" % port_name else: cmd = "sudo ip netns exec %s ifconfig %s" % (asic.namespace, port_name) ifout = per_host.command(cmd) assert "not found" not in ifout['stdout_lines'][0], "Interface %s not found" % port_name if port_state == "true" and "RUNNING" in ifout['stdout_lines'][0]: logger.debug("Interface state is up and matches") elif port_state == "false" and "RUNNING" not in ifout['stdout_lines'][0]: logger.debug("Interface state is down and matches") else: raise AssertionError("Interface state does not match: %s %s", port_state, ifout['stdout_lines'][0])
def test_voq_system_port_create(duthosts, enum_frontend_dut_hostname, enum_asic_index, all_cfg_facts): """Compare the config facts with the asic db for system ports * Verify ASIC_DB get all system ports referenced in configDB created on all hosts and ASICs. * Verify object creation and values of port attributes. """ per_host = duthosts[enum_frontend_dut_hostname] asic = per_host.asics[enum_asic_index if enum_asic_index is not None else 0] cfg_facts = all_cfg_facts[per_host.hostname][asic.asic_index]['ansible_facts'] logger.info("Checking system ports on host: %s, asic: %s", per_host.hostname, asic.asic_index) dev_ports = get_device_system_ports(cfg_facts) asicdb = AsicDbCli(asic) sys_port_table = asicdb.dump(asicdb.ASIC_SYSPORT_TABLE) keylist = sys_port_table.keys() pytest_assert(len(keylist) == len(dev_ports.keys()), "Found %d system port keys, %d entries in cfg_facts, not matching" % ( len(keylist), len(dev_ports.keys()))) logger.info("Found %d system port keys, %d entries in cfg_facts, checking each.", len(keylist), len(dev_ports.keys())) for portkey in keylist: try: port_config_info = sys_port_table[portkey]['value']['SAI_SYSTEM_PORT_ATTR_CONFIG_INFO'] except KeyError: # TODO: Need to check on behavior here. logger.warning("System port: %s had no SAI_SYSTEM_PORT_ATTR_CONFIG_INFO", portkey) continue port_data = json.loads(port_config_info) for cfg_port in dev_ports: if dev_ports[cfg_port]['system_port_id'] == port_data['port_id']: # "switch_id": "0", # "core_index": "1", # "core_port_index": "6", # "speed": "400000" pytest_assert(dev_ports[cfg_port]['switch_id'] == port_data[ 'attached_switch_id'], "switch IDs do not match for port: %s" % portkey) pytest_assert(dev_ports[cfg_port]['core_index'] == port_data[ 'attached_core_index'], "switch IDs do not match for port: %s" % portkey) pytest_assert(dev_ports[cfg_port]['core_port_index'] == port_data[ 'attached_core_port_index'], "switch IDs do not match for port: %s" % portkey) pytest_assert(dev_ports[cfg_port]['speed'] == port_data[ 'speed'], "switch IDs do not match for port: %s" % portkey) break else: logger.error("Could not find config entry for portkey: %s" % portkey) logger.info("Host: %s, Asic: %s all ports match all parameters", per_host.hostname, asic.asic_index)
def verify_lag_member_in_asic_db(asics, lag_id, pc_members, deleted=False): """ Verifies lag member in ASIC DB It runs the command e.g. """ for asic in asics: asicdb = AsicDbCli(asic) asic_lag_list = asicdb.get_asic_db_lag_list() asic_db_lag_member_list = asicdb.get_asic_db_lag_member_list() lag_oid = None if deleted: for lag in asic_lag_list: if asicdb.hget_key_value( lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id: lag_oid = ":".join(lag for lag in lag.split(':')[-1:-3:-1]) for lag_member in asic_db_lag_member_list: if asicdb.hget_key_value( lag_member, "SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_oid: pytest.fail( "lag members {} still exist in lag member table on {}," " Expected was should be deleted".format( pc_members, asic.sonichost.hostname)) logging.info('Lag members are deleted from {} on {}'.format( asic.asic_index, asic.sonichost.hostname)) else: for lag in asic_lag_list: if asicdb.hget_key_value( lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id: lag_oid = ":".join(lag for lag in lag.split(':')[-2::1]) break for lag_member in asic_db_lag_member_list: if asicdb.hget_key_value( lag_member, "SAI_LAG_MEMBER_ATTR_LAG_ID") == lag_oid: logging.info('Lag members exist in {} on {}'.format( asic.asic_index, asic.sonichost.hostname)) return pytest.fail('Lag members {} does not exist in {} on {}'.format( pc_members, asic.asic_index, asic.sonichost.hostname))
def verify_lag_in_asic_db(asics, lag_id, deleted=False): """ Verifies LAG in ASIC DB Args: asics<list>: asic lag_id<int>: lag id deleted<bool>: True if lag is deleted """ for asic in asics: asicdb = AsicDbCli(asic) asic_db_lag_list = asicdb.get_asic_db_lag_list() if deleted: for lag in asic_db_lag_list: if asicdb.hget_key_value( lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id: pytest.fail('LAG id {} for LAG {} exist in ASIC DB,' ' Expected was should not be present'.format( lag_id, TMP_PC)) logging.info( 'LAG id {} for LAG {} does not exist in ASIC DB'.format( lag_id, TMP_PC)) else: for lag in asic_db_lag_list: if asicdb.hget_key_value( lag, "SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID") == lag_id: logging.info( 'LAG id {} for LAG {} exist in ASIC DB'.format( lag_id, TMP_PC)) return pytest.fail( 'LAG id {} for LAG {} does not exist in ASIC DB'.format( lag_id, TMP_PC))
def check_voq_interfaces(duthosts, per_host, asic, cfg_facts): """ Checks router interfaces on a dut. Args: duthosts: The duthosts fixture per_host: Instance of MultiAsicSonic host to check. asic: Instance of SonicAsic to check, cfg_facts: Config facts for the frontend duthost/asic under test """ logger.info("Check router interfaces on node: %s, asic: %d", per_host.hostname, asic.asic_index) dev_intfs = cfg_facts.get('INTERFACE', {}) voq_intfs = cfg_facts.get('VOQ_INBAND_INTERFACE', []) dev_sysports = get_device_system_ports(cfg_facts) rif_ports_in_asicdb = [] # intf_list = get_router_interface_list(dev_intfs) asicdb = AsicDbCli(asic) asicdb_rif_table = asicdb.dump(asicdb.ASIC_ROUTERINTF_TABLE) sys_port_table = asicdb.dump(asicdb.ASIC_SYSPORT_TABLE) # asicdb_intf_key_list = asicdb.get_router_if_list() # Check each rif in the asicdb, if it is local port, check VOQ DB for correct RIF. # If it is on system port, verify slot/asic/port and OID match a RIF in VoQDB for rif in asicdb_rif_table.keys(): rif_type = asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_TYPE"] if rif_type != "SAI_ROUTER_INTERFACE_TYPE_PORT": logger.info("Skip this rif: %s, it is not on a port: %s", rif, rif_type) continue else: portid = asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_PORT_ID"] logger.info("Process RIF %s, Find port with ID: %s", rif, portid) porttype = asicdb.get_rif_porttype(portid) logger.info("RIF: %s is of type: %s", rif, porttype) if porttype == 'hostif': # find the hostif entry to get the physical port the router interface is on. hostifkey = asicdb.find_hostif_by_portid(portid) hostif = asicdb.hget_key_value(hostifkey, 'SAI_HOSTIF_ATTR_NAME') logger.info("RIF: %s is on local port: %s", rif, hostif) rif_ports_in_asicdb.append(hostif) if hostif not in dev_intfs and hostif not in voq_intfs: pytest.fail("Port: %s has a router interface, but it isn't in configdb." % portid) # check MTU and ethernet address pytest_assert(asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"] == cfg_facts['PORT'][hostif]['mtu'], "MTU for rif %s is not %s" % (rif, cfg_facts['PORT'][hostif]['mtu'])) intf_mac = get_sonic_mac(per_host, asic.asic_index, hostif) pytest_assert(asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() == intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac)) sysport_info = {'slot': cfg_facts['DEVICE_METADATA']['localhost']['hostname'], 'asic': cfg_facts['DEVICE_METADATA']['localhost']['asic_name']} if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0: check_rif_on_sup(per_host, sysport_info['slot'], sysport_info['asic'], hostif) else: for sup in duthosts.supervisor_nodes: check_rif_on_sup(sup, sysport_info['slot'], sysport_info['asic'], hostif) elif porttype == 'sysport': try: port_output = sys_port_table["ASIC_STATE:SAI_OBJECT_TYPE_SYSTEM_PORT:" + portid]['value']['SAI_SYSTEM_PORT_ATTR_CONFIG_INFO'] except KeyError: # not a hostif or system port, log error and continue logger.error("Did not find OID %s in local or system tables" % portid) continue port_data = json.loads(port_output) for cfg_port in dev_sysports: if dev_sysports[cfg_port]['system_port_id'] == port_data['port_id']: logger.info("RIF: %s is on remote port: %s", rif, cfg_port) break else: raise AssertionError("Did not find OID %s in local or system tables" % portid) sys_slot, sys_asic, sys_port = cfg_port.split("|") if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0: check_rif_on_sup(per_host, sys_slot, sys_asic, sys_port) else: for sup in duthosts.supervisor_nodes: check_rif_on_sup(sup, sys_slot, sys_asic, sys_port) elif porttype == 'port': # this is the RIF on the inband port. inband = get_inband_info(cfg_facts) logger.info("RIF: %s is on local port: %s", rif, inband['port']) # check MTU and ethernet address pytest_assert(asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_MTU"] == cfg_facts['PORT'][inband['port']]['mtu'], "MTU for rif %s is not %s" % (rif, cfg_facts['PORT'][inband['port']]['mtu'])) intf_mac = get_sonic_mac(per_host, asic.asic_index, inband['port']) pytest_assert(asicdb_rif_table[rif]['value']["SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS"].lower() == intf_mac.lower(), "MAC for rif %s is not %s" % (rif, intf_mac)) sysport_info = {'slot': cfg_facts['DEVICE_METADATA']['localhost']['hostname'], 'asic': cfg_facts['DEVICE_METADATA']['localhost']['asic_name']} if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0: check_rif_on_sup(per_host, sysport_info['slot'], sysport_info['asic'], inband['port']) else: for sup in duthosts.supervisor_nodes: check_rif_on_sup(sup, sysport_info['slot'], sysport_info['asic'], inband['port']) # TODO: Could be on a LAG elif porttype == 'lag': lagid = asicdb.hget_key_value("%s:%s" % (AsicDbCli.ASIC_LAG_TABLE, portid), 'SAI_LAG_ATTR_SYSTEM_PORT_AGGREGATE_ID') logger.info("RIF: %s is on system LAG: %s", rif, lagid) if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0: voqdb = VoqDbCli(per_host) else: voqdb = VoqDbCli(duthosts.supervisor_nodes[0]) systemlagtable = voqdb.dump("SYSTEM_LAG_ID_TABLE") for lag, sysid in systemlagtable['SYSTEM_LAG_ID_TABLE']['value'].iteritems(): if sysid == lagid: logger.info("System LAG ID %s is portchannel: %s", lagid, lag) break myslot = cfg_facts['DEVICE_METADATA']['localhost']['hostname'] myasic = cfg_facts['DEVICE_METADATA']['localhost']['asic_name'] if lag.startswith("%s|%s" % (myslot, myasic)): logger.info("Lag: %s is a local portchannel with a router interface.", lag) (s, a, lagname) = lag.split("|") pytest_assert(lagname in cfg_facts['PORTCHANNEL_INTERFACE'], "RIF Interface %s is in configdb.json but not in asicdb" % rif) if per_host.is_multi_asic and len(duthosts.supervisor_nodes) == 0: check_rif_on_sup(per_host, myslot, myasic, lagname) else: for sup in duthosts.supervisor_nodes: check_rif_on_sup(sup, myslot, myasic, lagname) else: logger.info("Lag: %s is a remote portchannel with a router interface.", lag) # Verify each RIF in config had a corresponding local port RIF in the asicDB. for rif in dev_intfs: if rif not in rif_ports_in_asicdb: raise AssertionError("Interface %s is in configdb.json but not in asicdb" % rif) logger.info("Interfaces %s are present in configdb.json and asicdb" % str(dev_intfs.keys()))