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 neighbors(): """Show vnet neighbors information""" config_db = ConfigDBConnector() config_db.connect() header = ['<vnet_name>', 'neighbor', 'mac_address', 'interfaces'] # Fetching data from config_db for interfaces intfs_data = config_db.get_table("INTERFACE") vlan_intfs_data = config_db.get_table("VLAN_INTERFACE") vnet_intfs = {} for k, v in intfs_data.items(): if 'vnet_name' in v: vnet_name = v['vnet_name'] if vnet_name in vnet_intfs: vnet_intfs[vnet_name].append(k) else: vnet_intfs[vnet_name] = [k] for k, v in vlan_intfs_data.items(): if 'vnet_name' in v: vnet_name = v['vnet_name'] if vnet_name in vnet_intfs: vnet_intfs[vnet_name].append(k) else: vnet_intfs[vnet_name] = [k] appl_db = SonicV2Connector() appl_db.connect(appl_db.APPL_DB) # Fetching data from appl_db for neighbors nbrs = appl_db.keys(appl_db.APPL_DB, "NEIGH_TABLE:*") nbrs_data = {} for nbr in nbrs if nbrs else []: tbl, intf, ip = nbr.split(":", 2) mac = appl_db.get(appl_db.APPL_DB, nbr, 'neigh') if intf in nbrs_data: nbrs_data[intf].append((ip, mac)) else: nbrs_data[intf] = [(ip, mac)] table = [] for k, v in vnet_intfs.items(): v = natsorted(v) header[0] = k table = [] for intf in v: if intf in nbrs_data: for ip, mac in nbrs_data[intf]: r = ["", ip, mac, intf] table.append(r) click.echo(tabulate(table, header)) click.echo() if not bool(vnet_intfs): click.echo(tabulate(table, header))
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 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 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 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)
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 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
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 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}
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 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 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 interface(): """Show VXLAN VTEP Information""" config_db = ConfigDBConnector() config_db.connect() # Fetching VTEP keys from config DB click.secho('VTEP Information:\n', bold=True, underline=True) vxlan_table = config_db.get_table('VXLAN_TUNNEL') vxlan_keys = vxlan_table.keys() vtep_sip = '0.0.0.0' if vxlan_keys is not None: for key in natsorted(vxlan_keys): key1 = key.split('|', 1) vtepname = key1.pop() if 'src_ip' in vxlan_table[key]: vtep_sip = vxlan_table[key]['src_ip'] if vtep_sip is not '0.0.0.0': output = '\tVTEP Name : ' + vtepname + ', SIP : ' + vxlan_table[ key]['src_ip'] else: output = '\tVTEP Name : ' + vtepname click.echo(output) if vtep_sip is not '0.0.0.0': vxlan_table = config_db.get_table('VXLAN_EVPN_NVO') vxlan_keys = vxlan_table.keys() if vxlan_keys is not None: for key in natsorted(vxlan_keys): key1 = key.split('|', 1) vtepname = key1.pop() output = '\tNVO Name : ' + vtepname + ', VTEP : ' + vxlan_table[ key]['source_vtep'] click.echo(output) vxlan_keys = config_db.keys('CONFIG_DB', "LOOPBACK_INTERFACE|*") loopback = 'Not Configured' if vxlan_keys is not None: for key in natsorted(vxlan_keys): key1 = key.split('|', 2) if len(key1) == 3 and key1[2] == vtep_sip + '/32': loopback = key1[1] break output = '\tSource interface : ' + loopback if vtep_sip != '0.0.0.0': click.echo(output)
def breakout(ctx): """Show Breakout Mode information by interfaces""" # Reading data from Redis configDb config_db = ConfigDBConnector() config_db.connect() ctx.obj = {'db': config_db} try: cur_brkout_tbl = config_db.get_table('BREAKOUT_CFG') except Exception as e: click.echo("Breakout table is not present in Config DB") raise click.Abort() if ctx.invoked_subcommand is None: # Get port capability from platform and hwsku related files hwsku_path = device_info.get_path_to_hwsku_dir() platform_file = device_info.get_path_to_port_config_file() platform_dict = readJsonFile(platform_file)['interfaces'] hwsku_file = os.path.join(hwsku_path, HWSKU_JSON) hwsku_dict = readJsonFile(hwsku_file)['interfaces'] if not platform_dict or not hwsku_dict: click.echo("Can not load port config from {} or {} file".format( platform_file, hwsku_file)) raise click.Abort() for port_name in platform_dict: cur_brkout_mode = cur_brkout_tbl[port_name]["brkout_mode"] # Update deafult breakout mode and current breakout mode to platform_dict platform_dict[port_name].update(hwsku_dict[port_name]) platform_dict[port_name]["Current Breakout Mode"] = cur_brkout_mode # List all the child ports if present child_port_dict = get_child_ports(port_name, cur_brkout_mode, platform_file) if not child_port_dict: click.echo( "Cannot find ports from {} file ".format(platform_file)) raise click.Abort() child_ports = natsorted(list(child_port_dict.keys())) children, speeds = [], [] # Update portname and speed of child ports if present for port in child_ports: speed = config_db.get_entry('PORT', port).get('speed') if speed is not None: speeds.append(str(int(speed) // 1000) + 'G') children.append(port) platform_dict[port_name]["child ports"] = ",".join(children) platform_dict[port_name]["child port speeds"] = ",".join(speeds) # Sorted keys by name in natural sort Order for human readability parsed = OrderedDict((k, platform_dict[k]) for k in natsorted(list(platform_dict.keys()))) click.echo(json.dumps(parsed, indent=4))
def address (): """Show IP address configured for management interface""" config_db = ConfigDBConnector() config_db.connect() # Fetching data from config_db for MGMT_INTERFACE mgmt_ip_data = config_db.get_table('MGMT_INTERFACE') for key in natsorted(list(mgmt_ip_data.keys())): click.echo("Management IP address = {0}".format(key[1])) click.echo("Management Network Default Gateway = {0}".format(mgmt_ip_data[key]['gwaddr']))
def snmpagentaddress(ctx): """Show SNMP agent listening IP address configuration""" config_db = ConfigDBConnector() config_db.connect() agenttable = config_db.get_table('SNMP_AGENT_ADDRESS_CONFIG') header = ['ListenIP', 'ListenPort', 'ListenVrf'] body = [] for agent in agenttable: body.append([agent[0], agent[1], agent[2]]) click.echo(tabulate(body, header))
def remove_bindings(ctx): """Remove all Bindings for Dynamic configutation""" config_db = ConfigDBConnector() config_db.connect() binding_table_name = 'NAT_BINDINGS' binding_dict = config_db.get_table(binding_table_name) if binding_dict: for binding_key_name in binding_dict: config_db.set_entry(binding_table_name, binding_key_name, None)
def remove_static_all(ctx): """Remove all Static related configutation""" config_db = ConfigDBConnector() config_db.connect() tables = ['STATIC_NAT', 'STATIC_NAPT'] for table_name in tables: table_dict = config_db.get_table(table_name) if table_dict: for table_key_name in table_dict: config_db.set_entry(table_name, table_key_name, None)
def memory(): """Show kdump memory information""" kdump_memory = "0M-2G:256M,2G-4G:320M,4G-8G:384M,8G-:448M" config_db = ConfigDBConnector() if config_db is not None: config_db.connect() table_data = config_db.get_table('KDUMP') if table_data is not None: config_data = table_data.get('config') if config_data is not None: kdump_memory_from_db = config_data.get('memory') if kdump_memory_from_db is not None: kdump_memory = kdump_memory_from_db click.echo("Memory Reserved: {}".format(kdump_memory))
def nat_interface_name_is_valid(interface_name): """Check if the given nat interface is valid""" config_db = ConfigDBConnector() config_db.connect() if interface_name.startswith("Ethernet"): interface_dict = config_db.get_table('PORT') elif interface_name.startswith("PortChannel"): interface_dict = config_db.get_table('PORTCHANNEL') elif interface_name.startswith("Vlan"): interface_dict = config_db.get_table('VLAN') elif interface_name.startswith("Loopback"): return True else: return False if interface_name is not None: if not interface_dict: return False return interface_name in interface_dict return False
def interfaces(): """Show vnet interfaces information""" config_db = ConfigDBConnector() config_db.connect() header = ['vnet name', 'interfaces'] # Fetching data from config_db for interfaces intfs_data = config_db.get_table("INTERFACE") vlan_intfs_data = config_db.get_table("VLAN_INTERFACE") vnet_intfs = {} for k, v in intfs_data.items(): if 'vnet_name' in v: vnet_name = v['vnet_name'] if vnet_name in vnet_intfs: vnet_intfs[vnet_name].append(k) else: vnet_intfs[vnet_name] = [k] for k, v in vlan_intfs_data.items(): if 'vnet_name' in v: vnet_name = v['vnet_name'] if vnet_name in vnet_intfs: vnet_intfs[vnet_name].append(k) else: vnet_intfs[vnet_name] = [k] table = [] for k, v in vnet_intfs.items(): r = [] r.append(k) r.append(",".join(natsorted(v))) table.append(r) click.echo(tabulate(table, header))
def get_localhost_info(field, config_db=None): 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') if 'localhost' in metadata and field in metadata['localhost']: return metadata['localhost'][field] except Exception: pass return None
def num_dumps(): """Show kdump max number of dump files""" kdump_num_dumps = "3" config_db = ConfigDBConnector() if config_db is not None: config_db.connect() table_data = config_db.get_table('KDUMP') if table_data is not None: config_data = table_data.get('config') if config_data is not None: kdump_num_dumps_from_db = config_data.get('num_dumps') if kdump_num_dumps_from_db is not None: kdump_num_dumps = kdump_num_dumps_from_db click.echo("Maximum number of Kernel Core files Stored: {}".format( kdump_num_dumps))
def remove_pools(ctx): """Remove all Pools for Dynamic configutation""" config_db = ConfigDBConnector() config_db.connect() entryFound = False pool_table_name = 'NAT_POOL' binding_table_name = 'NAT_BINDINGS' binding_dict = config_db.get_table(binding_table_name) pool_dict = config_db.get_table(pool_table_name) if pool_dict: for pool_key_name in pool_dict: entryFound = False for binding_name, binding_values in binding_dict.items(): if binding_values['nat_pool'] == pool_key_name: click.echo( "Pool {} is not removed, as it is mapped to Binding {}, remove the pool binding first !!" .format(pool_key_name, binding_name)) entryFound = True break if entryFound == False: config_db.set_entry(pool_table_name, pool_key_name, None)
def enabled(): """Show if kdump is enabled or disabled""" kdump_is_enabled = False config_db = ConfigDBConnector() if config_db is not None: config_db.connect() table_data = config_db.get_table('KDUMP') if table_data is not None: config_data = table_data.get('config') if config_data is not None: if config_data.get('enabled').lower() == 'true': kdump_is_enabled = True if kdump_is_enabled: click.echo("kdump is enabled") else: click.echo("kdump is disabled")
def snmptrap (ctx): """Show SNMP agent Trap server configuration""" config_db = ConfigDBConnector() config_db.connect() traptable = config_db.get_table('SNMP_TRAP_CONFIG') header = ['Version', 'TrapReceiverIP', 'Port', 'VRF', 'Community'] body = [] for row in traptable: if row == "v1TrapDest": ver=1 elif row == "v2TrapDest": ver=2 else: ver=3 body.append([ver, traptable[row]['DestIp'], traptable[row]['DestPort'], traptable[row]['vrf'], traptable[row]['Community']]) click.echo(tabulate(body, header))
def add(address, retransmit, timeout, key, auth_type, auth_port, pri, use_mgmt_vrf, source_interface): """Specify a RADIUS server""" if key: if len(key) > RADIUS_PASSKEY_MAX_LEN: click.echo('--key: Maximum of %d chars can be configured' % RADIUS_PASSKEY_MAX_LEN) return elif not is_secret(key): click.echo('--key: ' + VALID_CHARS_MSG) return config_db = ConfigDBConnector() config_db.connect() old_data = config_db.get_table('RADIUS_SERVER') if address in old_data: click.echo('server %s already exists' % address) return if len(old_data) == RADIUS_MAXSERVERS: click.echo('Maximum of %d can be configured' % RADIUS_MAXSERVERS) else: data = {'auth_port': str(auth_port), 'priority': pri} if auth_type is not None: data['auth_type'] = auth_type if retransmit is not None: data['retransmit'] = str(retransmit) if timeout is not None: data['timeout'] = str(timeout) if key is not None: data['passkey'] = key if use_mgmt_vrf: data['vrf'] = "mgmt" if source_interface: if (source_interface.startswith("Ethernet") or \ source_interface.startswith("PortChannel") or \ source_interface.startswith("Vlan") or \ source_interface.startswith("Loopback") or \ source_interface == "eth0"): data['src_intf'] = source_interface else: click.echo( 'Not supported interface name (valid interface name: Etherent<id>/PortChannel<id>/Vlan<id>/Loopback<id>/eth0)' ) config_db.set_entry('RADIUS_SERVER', address, data)
def test_ConfigDBConnectorSeparator(): db = swsscommon.DBConnector("APPL_DB", 0, True) config_db = ConfigDBConnector() config_db.db_connect("APPL_DB", False, False) config_db.get_redis_client(config_db.APPL_DB).flushdb() config_db.set_entry("TEST_PORT", "Ethernet222", {"alias": "etp2x"}) db.set("ItemWithoutSeparator", "item11") allconfig = config_db.get_config() assert "TEST_PORT" in allconfig assert "ItemWithoutSeparator" not in allconfig alltable = config_db.get_table("*") assert "Ethernet222" in alltable config_db.delete_table("TEST_PORT") db.delete("ItemWithoutSeparator") allconfig = config_db.get_config() assert len(allconfig) == 0
def get_kdump_config(field_name): """Fetches the configuration of Kdump from `CONFIG_DB`. Args: field_name: A string contains the field name in the sub-table of 'config'. Returns: field_value: If field name was found, then returns the corresponding value. Otherwise, returns "Unknown". """ field_value = "Unknown" config_db = ConfigDBConnector() config_db.connect() kdump_table = config_db.get_table("KDUMP") if kdump_table and "config" in kdump_table and field_name in kdump_table["config"]: field_value = kdump_table["config"][field_name] return field_value