def disable(): """ Disable queue counter query """ configdb = ConfigDBConnector() configdb.connect() queue_info = {} queue_info['FLEX_COUNTER_STATUS'] = 'disable' configdb.mod_entry("FLEX_COUNTER_TABLE", "QUEUE", queue_info)
def remove_basic(ctx, global_ip, local_ip): """Remove Static NAT-related configutation""" # Verify the ip address format if is_valid_ipv4_address(local_ip) is False: ctx.fail( "Given local ip address {} is invalid. Please enter a valid local ip address !!" .format(local_ip)) if is_valid_ipv4_address(global_ip) is False: ctx.fail( "Given global ip address {} is invalid. Please enter a valid global ip address !!" .format(global_ip)) config_db = ConfigDBConnector() config_db.connect() entryFound = False table = 'STATIC_NAT' key = global_ip dataKey = 'local_ip' data = config_db.get_entry(table, key) if data: if data[dataKey] == local_ip: config_db.set_entry(table, key, None) entryFound = True if entryFound is False: click.echo("Trying to delete static nat entry, which is not present.")
def tacacs(): """Show TACACS+ configuration""" config_db = ConfigDBConnector() config_db.connect() output = '' data = config_db.get_table('TACPLUS') tacplus = { 'global': { 'auth_type': 'pap (default)', 'timeout': '5 (default)', 'passkey': '<EMPTY_STRING> (default)' } } if 'global' in data: tacplus['global'].update(data['global']) for key in tacplus['global']: output += ('TACPLUS global %s %s\n' % (str(key), str(tacplus['global'][key]))) data = config_db.get_table('TACPLUS_SERVER') if data != {}: for row in data: entry = data[row] output += ('\nTACPLUS_SERVER address %s\n' % row) for key in entry: output += (' %s %s\n' % (key, str(entry[key]))) click.echo(output)
def disable(): """ Disable port counter query """ configdb = ConfigDBConnector() configdb.connect() port_info = {} port_info['FLEX_COUNTER_STATUS'] = DISABLE configdb.mod_entry("FLEX_COUNTER_TABLE", PORT_BUFFER_DROP, port_info)
def disable(): """ Disable tunnel counter query """ configdb = ConfigDBConnector() configdb.connect() tunnel_info = {} tunnel_info['FLEX_COUNTER_STATUS'] = DISABLE configdb.mod_entry("FLEX_COUNTER_TABLE", "TUNNEL", tunnel_info)
def get_all_namespaces(config_db=None): """ In case of Multi-Asic platform, Each ASIC will have a linux network namespace created. So we loop through the databases in different namespaces and depending on the sub_role decide whether this is a front end ASIC/namespace or a back end one. """ front_ns = [] back_ns = [] num_npus = get_num_npus() if is_multi_npu(): for npu in range(num_npus): namespace = "{}{}".format(NPU_NAME_PREFIX, npu) # TODO: enforce caller to provide config_db explicitly and remove its default value if not config_db: config_db = ConfigDBConnector(use_unix_socket_path=True, namespace=namespace) config_db.connect() metadata = config_db.get_table('DEVICE_METADATA') if metadata['localhost']['sub_role'] == FRONTEND_ASIC_SUB_ROLE: front_ns.append(namespace) elif metadata['localhost']['sub_role'] == BACKEND_ASIC_SUB_ROLE: back_ns.append(namespace) return {'front_ns': front_ns, 'back_ns': back_ns}
class TestBreakout(TestCase): @classmethod def setup_class(cls): print("SETUP") os.environ["UTILITIES_UNIT_TESTING"] = "1" def setUp(self): self.runner = CliRunner() self.config_db = ConfigDBConnector() self.config_db.connect() self.obj = {'db': self.config_db} # Test 'show interfaces breakout current-mode' def test_all_intf_current_mode(self): result = self.runner.invoke(show.cli.commands["interfaces"].commands["breakout"].commands["current-mode"], [], obj=self.obj) print(sys.stderr, result.output) assert result.output == current_mode_all_output # Test 'show interfaces breakout current-mode Ethernet0' def test_single_intf_current_mode(self): result = self.runner.invoke(show.cli.commands["interfaces"].commands["breakout"].commands["current-mode"], ["Ethernet0"], obj=self.obj) print(sys.stderr, result.output) assert result.output == current_mode_intf_output @classmethod def teardown_class(cls): print("TEARDOWN") os.environ["UTILITIES_UNIT_TESTING"] = "0"
def add(address, timeout, key, auth_type, port, pri, use_mgmt_vrf): """Specify a TACACS+ server""" if not clicommon.is_ipaddress(address): click.echo('Invalid ip address') return config_db = ConfigDBConnector() config_db.connect() old_data = config_db.get_entry('TACPLUS_SERVER', address) if old_data != {}: click.echo('server %s already exists' % address) else: data = { 'tcp_port': str(port), 'priority': pri } if auth_type is not None: data['auth_type'] = auth_type if timeout is not None: data['timeout'] = str(timeout) if key is not None: data['passkey'] = key if use_mgmt_vrf : data['vrf'] = "mgmt" config_db.set_entry('TACPLUS_SERVER', address, data)
def show(): """ Show the counter configuration """ configdb = ConfigDBConnector() configdb.connect() queue_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'QUEUE') port_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'PORT') port_drop_info = configdb.get_entry('FLEX_COUNTER_TABLE', PORT_BUFFER_DROP) rif_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'RIF') queue_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'QUEUE_WATERMARK') pg_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'PG_WATERMARK') pg_drop_info = configdb.get_entry('FLEX_COUNTER_TABLE', PG_DROP) buffer_pool_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', BUFFER_POOL_WATERMARK) header = ("Type", "Interval (in ms)", "Status") data = [] if queue_info: data.append(["QUEUE_STAT", queue_info.get("POLL_INTERVAL", DEFLT_10_SEC), queue_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if port_info: data.append(["PORT_STAT", port_info.get("POLL_INTERVAL", DEFLT_1_SEC), port_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if port_drop_info: data.append([PORT_BUFFER_DROP, port_drop_info.get("POLL_INTERVAL", DEFLT_60_SEC), port_drop_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if rif_info: data.append(["RIF_STAT", rif_info.get("POLL_INTERVAL", DEFLT_1_SEC), rif_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if queue_wm_info: data.append(["QUEUE_WATERMARK_STAT", queue_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), queue_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if pg_wm_info: data.append(["PG_WATERMARK_STAT", pg_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), pg_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if pg_drop_info: data.append(['PG_DROP_STAT', pg_drop_info.get("POLL_INTERVAL", DEFLT_10_SEC), pg_drop_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if buffer_pool_wm_info: data.append(["BUFFER_POOL_WATERMARK_STAT", buffer_pool_wm_info.get("POLL_INTERVAL", DEFLT_10_SEC), buffer_pool_wm_info.get("FLEX_COUNTER_STATUS", DISABLE)]) click.echo(tabulate(data, headers=header, tablefmt="simple", missingval=""))
def profile(profile): # Check if profile can be changed completed_process = subprocess.run( ['docker', 'exec', '-it', 'syncd', 'test', '-h', '/opt/bfn/install']) if completed_process.returncode != 0: click.echo('Cannot change profile: default one is in use') raise click.Abort() # Get chip family hwsku_dir = device_info.get_path_to_hwsku_dir() with open(hwsku_dir + '/switch-tna-sai.conf') as file: chip_family = json.load(file)['chip_list'][0]['chip_family'].lower() # Check if profile is supported if chip_family == 'tofino' and profile[0] == 'y' or \ chip_family == 'tofino2' and profile[0] == 'x': click.echo('Specified profile is unsupported on the system') raise click.Abort() # Check if profile exists completed_process = subprocess.run([ 'docker', 'exec', '-it', 'syncd', 'test', '-d', '/opt/bfn/install_' + profile + '_profile' ]) if completed_process.returncode != 0: click.echo('No profile with the provided name found') raise click.Abort() # Update configuration config_db = ConfigDBConnector() config_db.connect() config_db.mod_entry('DEVICE_METADATA', 'localhost', {'p4_profile': profile + '_profile'}) subprocess.run(['systemctl', 'restart', 'swss'], check=True)
def tunnel(): """Show vxlan tunnel information""" config_db = ConfigDBConnector() config_db.connect() header = [ 'vxlan tunnel name', 'source ip', 'destination ip', 'tunnel map name', 'tunnel map mapping(vni -> vlan)' ] # Fetching data from config_db for VXLAN TUNNEL vxlan_data = config_db.get_table('VXLAN_TUNNEL') vxlan_keys = natsorted(list(vxlan_data.keys())) table = [] for k in vxlan_keys: r = [] r.append(k) r.append(vxlan_data[k].get('src_ip')) r.append(vxlan_data[k].get('dst_ip')) vxlan_map_keys = config_db.keys( config_db.CONFIG_DB, 'VXLAN_TUNNEL_MAP{}{}{}*'.format(config_db.KEY_SEPARATOR, k, config_db.KEY_SEPARATOR)) if vxlan_map_keys: vxlan_map_mapping = config_db.get_all(config_db.CONFIG_DB, vxlan_map_keys[0]) r.append(vxlan_map_keys[0].split(config_db.KEY_SEPARATOR, 2)[2]) r.append("{} -> {}".format(vxlan_map_mapping.get('vni'), vxlan_map_mapping.get('vlan'))) table.append(r) click.echo(tabulate(table, header))
def vlanvnimap(count): """Show VLAN VNI Mapping Information""" header = ['VLAN', 'VNI'] body = [] config_db = ConfigDBConnector() config_db.connect() if count is not None: vxlan_keys = config_db.keys('CONFIG_DB', "VXLAN_TUNNEL_MAP|*") if not vxlan_keys: vxlan_count = 0 else: vxlan_count = len(vxlan_keys) output = 'Total count : ' output += ('%s \n' % (str(vxlan_count))) click.echo(output) else: vxlan_table = config_db.get_table('VXLAN_TUNNEL_MAP') vxlan_keys = vxlan_table.keys() num = 0 if vxlan_keys is not None: for key in natsorted(vxlan_keys): body.append( [vxlan_table[key]['vlan'], vxlan_table[key]['vni']]) num += 1 click.echo(tabulate(body, header, tablefmt="grid")) output = 'Total count : ' output += ('%s \n' % (str(num))) click.echo(output)
def showPfcPrio(interface): """ PFC handler to display PFC enabled priority information. """ header = ('Interface', 'Lossless priorities') table = [] configdb = ConfigDBConnector() configdb.connect() """Get all the interfaces with QoS map information""" intfs = configdb.get_keys('PORT_QOS_MAP') """The user specifies an interface but we cannot find it""" if interface and interface not in intfs: click.echo('Cannot find interface {0}'.format(interface)) return if interface: intfs = [interface] for intf in intfs: entry = configdb.get_entry('PORT_QOS_MAP', intf) table.append([intf, entry.get('pfc_enable', 'N/A')]) sorted_table = natsorted(table) click.echo() click.echo(tabulate(sorted_table, headers=header, tablefmt="simple", missingval="")) click.echo()
def configPfcPrio(status, interface, priority): configdb = ConfigDBConnector() configdb.connect() if interface not in configdb.get_keys('PORT_QOS_MAP'): click.echo('Cannot find interface {0}'.format(interface)) return """Current lossless priorities on the interface""" entry = configdb.get_entry('PORT_QOS_MAP', interface) enable_prio = entry.get('pfc_enable').split(',') """Avoid '' in enable_prio""" enable_prio = [x.strip() for x in enable_prio if x.strip()] if status == 'on' and priority in enable_prio: click.echo('Priority {0} has already been enabled on {1}'.format(priority, interface)) return if status == 'off' and priority not in enable_prio: click.echo('Priority {0} is not enabled on {1}'.format(priority, interface)) return if status == 'on': enable_prio.append(priority) else: enable_prio.remove(priority) enable_prio.sort() configdb.mod_entry("PORT_QOS_MAP", interface, {'pfc_enable': ','.join(enable_prio)}) """Show the latest PFC configuration""" showPfcPrio(interface)
def remove_pool(ctx, pool_name): """Remove Pool for Dynamic NAT-related configutation""" entryFound = False table = "NAT_POOL" key = pool_name if len(pool_name) > 32: ctx.fail( "Invalid pool name. Maximum allowed pool name is 32 characters !!") config_db = ConfigDBConnector() config_db.connect() data = config_db.get_entry(table, key) if not data: click.echo("Trying to delete pool, which is not present.") entryFound = True binding_dict = config_db.get_table('NAT_BINDINGS') if binding_dict and entryFound == False: for binding_name, binding_values in binding_dict.items(): if binding_values['nat_pool'] == pool_name: click.echo( "Pool is not removed, as it is mapped to Binding {}, remove the pool binding first !!" .format(binding_name)) entryFound = True break if entryFound == False: config_db.set_entry(table, key, None)
class Db(object): def __init__(self): self.cfgdb_clients = {} self.db_clients = {} self.cfgdb = ConfigDBConnector() self.cfgdb.connect() self.cfgdb_pipe = ConfigDBPipeConnector() self.cfgdb_pipe.connect() self.db = SonicV2Connector(host="127.0.0.1") # Skip connecting to chassis databases in line cards self.db_list = list(self.db.get_db_list()) if not device_info.is_supervisor(): try: self.db_list.remove('CHASSIS_APP_DB') self.db_list.remove('CHASSIS_STATE_DB') except Exception: pass for db_id in self.db_list: self.db.connect(db_id) self.cfgdb_clients[constants.DEFAULT_NAMESPACE] = self.cfgdb self.db_clients[constants.DEFAULT_NAMESPACE] = self.db if multi_asic.is_multi_asic(): self.ns_list = multi_asic_ns_choices() for ns in self.ns_list: self.cfgdb_clients[ns] = ( multi_asic.connect_config_db_for_ns(ns)) self.db_clients[ns] = multi_asic.connect_to_all_dbs_for_ns(ns) def get_data(self, table, key): data = self.cfgdb.get_table(table) return data[key] if key in data else None
def isOverlappingWithAnyDynamicEntry(ipAddress): """Check if the given ipAddress is overlapping with any dynamic pool entry""" config_db = ConfigDBConnector() config_db.connect() ip = int(ipaddress.IPv4Address(ipAddress)) nat_pool_dict = config_db.get_table('NAT_POOL') if not nat_pool_dict: return False for values in nat_pool_dict.values(): global_ip = values["nat_ip"] ipAddr = global_ip.split('-') if (len(ipAddr) == 1): startIp = int(ipaddress.IPv4Address(ipAddr[0])) endIp = int(ipaddress.IPv4Address(ipAddr[0])) else: startIp = int(ipaddress.IPv4Address(ipAddr[0])) endIp = int(ipaddress.IPv4Address(ipAddr[1])) if ((ip >= startIp) and (ip <= endIp)): return True return False
def interval(poll_interval): """ Set tunnel counter query interval """ configdb = ConfigDBConnector() configdb.connect() tunnel_info = {} tunnel_info['POLL_INTERVAL'] = poll_interval configdb.mod_entry("FLEX_COUNTER_TABLE", "TUNNEL", tunnel_info)
def add_interface(ctx, interface_name, nat_zone): """Add interface related nat configuration""" config_db = ConfigDBConnector() config_db.connect() if nat_interface_name_is_valid(interface_name) is False: ctx.fail( "Interface name is invalid. Please enter a valid interface name!!" ) if interface_name.startswith("Ethernet"): interface_table_type = "INTERFACE" elif interface_name.startswith("PortChannel"): interface_table_type = "PORTCHANNEL_INTERFACE" elif interface_name.startswith("Vlan"): interface_table_type = "VLAN_INTERFACE" elif interface_name.startswith("Loopback"): interface_table_type = "LOOPBACK_INTERFACE" interface_table_dict = config_db.get_table(interface_table_type) if not interface_table_dict or interface_name not in interface_table_dict: ctx.fail( "Interface table is not present. Please configure ip-address on {} and apply the nat zone !!" .format(interface_name)) config_db.mod_entry(interface_table_type, interface_name, {"nat_zone": nat_zone})
def get_platform_info(config_db=None): """ This function is used to get the HW info helper function """ from .multi_asic import get_num_asics hw_info_dict = {} version_info = get_sonic_version_info() hw_info_dict['platform'] = get_platform() hw_info_dict['hwsku'] = get_hwsku() if version_info: hw_info_dict['asic_type'] = version_info.get('asic_type') hw_info_dict['asic_count'] = get_num_asics() try: # TODO: enforce caller to provide config_db explicitly and remove its default value if not config_db: config_db = ConfigDBConnector() config_db.connect() metadata = config_db.get_table('DEVICE_METADATA')["localhost"] switch_type = metadata.get('switch_type') if switch_type: hw_info_dict['switch_type'] = switch_type except Exception: pass return hw_info_dict
def remove_interface(ctx, interface_name): """Remove interface related NAT configuration""" config_db = ConfigDBConnector() config_db.connect() if nat_interface_name_is_valid(interface_name) is False: ctx.fail( "Interface name is invalid. Please enter a valid interface name!!" ) if interface_name.startswith("Ethernet"): interface_table_type = "INTERFACE" elif interface_name.startswith("PortChannel"): interface_table_type = "PORTCHANNEL_INTERFACE" elif interface_name.startswith("Vlan"): interface_table_type = "VLAN_INTERFACE" elif interface_name.startswith("Loopback"): interface_table_type = "LOOPBACK_INTERFACE" interface_table_dict = config_db.get_table(interface_table_type) if not interface_table_dict or interface_name not in interface_table_dict: ctx.fail( "Interface table is not present. Ignoring the nat zone configuration" ) config_db.mod_entry(interface_table_type, interface_name, {"nat_zone": "0"})
def connect_config_db(): """ Connects to config_db """ config_db = ConfigDBConnector() config_db.connect() return config_db
def udp_timeout(ctx): """Reset NAT UDP timeout configuration to default value (300 seconds)""" config_db = ConfigDBConnector() config_db.connect() seconds = 300 config_db.mod_entry("NAT_GLOBAL", "Values", {"nat_udp_timeout": seconds})
def alias(vnet_alias): """Show vnet alias to name information""" config_db = ConfigDBConnector() config_db.connect() header = ['Alias', 'Name'] # Fetching data from config_db for VNET vnet_data = config_db.get_table('VNET') vnet_keys = natsorted(list(vnet_data.keys())) def tablelize(vnet_keys, vnet_data, vnet_alias): table = [] for k in vnet_keys: r = [] if vnet_alias is not None: if vnet_data[k].get('guid') == vnet_alias: r.append(vnet_data[k].get('guid')) r.append(k) table.append(r) return table else: continue r.append(vnet_data[k].get('guid')) r.append(k) table.append(r) return table click.echo(tabulate(tablelize(vnet_keys, vnet_data, vnet_alias), header))
def getTwiceNatIdCountWithDynamicBinding(twice_nat_id, count, dynamic_key): """Get the twice nat id count with dynamic binding""" config_db = ConfigDBConnector() config_db.connect() nat_binding_dict = config_db.get_table('NAT_BINDINGS') twice_id_count = count if not nat_binding_dict: return twice_id_count for key, values in nat_binding_dict.items(): nat_pool_data = config_db.get_entry('NAT_POOL', values["nat_pool"]) twice_id = 0 if dynamic_key is not None: if dynamic_key == key: continue if not nat_pool_data: continue if "twice_nat_id" in values: if values["twice_nat_id"] == "NULL": continue else: twice_id = int(values["twice_nat_id"]) else: continue if twice_id == twice_nat_id: twice_id_count += 1 return twice_id_count
def disable(): """ Disable rif counter query """ configdb = ConfigDBConnector() configdb.connect() rif_info = {} rif_info['FLEX_COUNTER_STATUS'] = 'disable' configdb.mod_entry("FLEX_COUNTER_TABLE", "RIF", rif_info)
def remove_udp(ctx, global_ip, global_port, local_ip, local_port): """Remove Static UDP Protocol NAPT-related configutation""" # Verify the ip address format if is_valid_ipv4_address(local_ip) is False: ctx.fail( "Given local ip address {} is invalid. Please enter a valid local ip address !!" .format(local_ip)) if is_valid_ipv4_address(global_ip) is False: ctx.fail( "Given global ip address {} is invalid. Please enter a valid global ip address !!" .format(global_ip)) config_db = ConfigDBConnector() config_db.connect() entryFound = False table = "STATIC_NAPT" key = "{}|UDP|{}".format(global_ip, global_port) dataKey1 = 'local_ip' dataKey2 = 'local_port' data = config_db.get_entry(table, key) if data: if data[dataKey1] == local_ip and data[dataKey2] == str(local_port): config_db.set_entry(table, key, None) entryFound = True if entryFound is False: click.echo("Trying to delete static napt entry, which is not present.")
def disable(): """ Disable port counter query """ configdb = ConfigDBConnector() configdb.connect() port_info = {} port_info['FLEX_COUNTER_STATUS'] = 'disable' configdb.mod_entry("FLEX_COUNTER_TABLE", "PORT", port_info)
def showPfcAsym(interface): """ PFC handler to display asymmetric PFC information. """ header = ('Interface', 'Asymmetric') configdb = ConfigDBConnector() configdb.connect() if interface: db_keys = configdb.keys(configdb.CONFIG_DB, 'PORT|{0}'.format(interface)) else: db_keys = configdb.keys(configdb.CONFIG_DB, 'PORT|*') table = [] for i in db_keys or [None]: key = None if i: key = i.split('|')[-1] if key and key.startswith('Ethernet'): entry = configdb.get_entry('PORT', key) table.append([key, entry.get('pfc_asym', 'N/A')]) sorted_table = natsorted(table) click.echo() click.echo(tabulate(sorted_table, headers=header, tablefmt="simple", missingval="")) click.echo()
def interval(poll_interval): """ Set queue counter query interval """ configdb = ConfigDBConnector() configdb.connect() port_info = {} if poll_interval is not None: port_info['POLL_INTERVAL'] = poll_interval configdb.mod_entry("FLEX_COUNTER_TABLE", "PORT", port_info)