def get_active_outgoing_interface(device, destination_address, extensive=False): """ Get active outgoing interface value Args: device (`obj`): Device object destination_address (`str`): Destination address value extensive ('bool'): Try command with extensive Returns: Interface name """ try: if extensive: out = device.parse('show route protocol static extensive') else: out = device.parse('show route protocol static') except SchemaEmptyParserError: return None # Example dictionary structure: # { # "rt": [ # { # "rt-destination": "10.169.14.240/32", # "rt-entry": { # "nh": [ # { # "to": "10.169.14.121", # "via": "ge-0/0/1.0" # } # ], # "rt-tag": "100", # "preference": "5", # "protocol-name": "Static" # } # } # ], # "table-name": "inet.0", # "total-route-count": "240" # }, rt_list = Dq(out).get_values("rt") for rt_dict in rt_list: rt_destination_ = Dq(rt_dict).get_values("rt-destination", 0) if not rt_destination_.startswith(destination_address): continue active_tag_ = Dq(rt_dict).get_values("active-tag", None) if not active_tag_: continue via_ = Dq(rt_dict).get_values("via", None) if not via_: continue return via_.pop() return None
def _get_actions(self, data): """ get action items only from any Blitz sections such as parallel and loop Arguments: data (`dict`) : data of section Returns: (`dict`): only actions from data """ if data: if isinstance(data, list): # parallel or normal actions if 'parallel' in data[0]: return data[0]['parallel'] else: return data elif isinstance(data, dict): # loop if Dq(data).contains('actions'): return Dq(data).get_values('actions') # for case section doesn't have loop/parallel # return data as is. return data
def verify_ospf3_database_prefix(device, expected_prefix, ipaddress=None, max_time=100, check_interval=10): """API for verifying ospf3 prefix exists in database Args: device (obj): device object expected_prefix (string): prefix being searched for ipaddress (string): IP address to use in show command. Defaults to None. max_time (int, optional): maximum timeoute time. Defaults to 60. check_interval (int, optional): check interval. Defaults to 10. Returns: True/False Raises: N/A """ # 'ospf3-database':{ # 'ospf3-inter-area-prefix-lsa': # 'FFFF::FF/128' # } # show ospf3 database link advertising-router 192.168.219.235 detail # "ospf3-database-information": { # "ospf3-database": [ # { # "ospf3-link-lsa": { # "ospf3-prefix": "2001:db8:dae9:cf16::/64", # }, timeout = Timeout(max_time, check_interval) while timeout.iterate(): try: if ipaddress: out = device.parse( 'show ospf3 database link advertising-router {ipaddress} detail' .format(ipaddress=ipaddress)) else: out = device.parse('show ospf3 database extensive') except SchemaEmptyParserError: timeout.sleep() continue # show ospf3 database link advertising-router {ipaddress} detail if ipaddress: prefix = out.q.get_values('ospf3-prefix') if expected_prefix in prefix: return True else: for ospf3_database in Dq(out).get_values('ospf3-database'): prefix_ = Dq(ospf3_database).get_values('ospf3-prefix', 0) if not isinstance(prefix_, list): if prefix_.startswith(expected_prefix): return True timeout.sleep() return False
def get_interface_speed(device, interface, bit_size='gbps'): """Get speed of an interface Args: device (obj): device object interface (str): interface name bit_size (str): desired return size (gbps/mbps/kbps) Returns: Device speed or None Raises: None """ try: out = device.parse('show interfaces extensive {interface}'.format( interface=interface.split('.')[0] )) except SchemaEmptyParserError as e: return None # Example Dictionary # "physical-interface": [ # { # "name": "ge-0/0/0", # "speed": "1000mbps", # } speed_matrix = { 'kbps': { 'kbps': 1, 'mbps': 1000, 'gbps': 1000000, }, 'mbps': { 'kbps': 0.001, 'mbps': 1, 'gbps': 1000, }, 'gbps': { 'kbps': .0000001, 'mbps': 0.001, 'gbps': 1, }, } interfaces_list = Dq(out).get_values('physical-interface') for interfaces_dict in interfaces_list: speed_ = Dq(interfaces_dict).get_values('speed', 0) if not speed_: continue if 'kbps' in speed_: speed_ = int(re.sub(r'[a-z,]', '', speed_)) / speed_matrix['kbps'][bit_size] elif 'mbps' in speed_: speed_ = int(re.sub(r'[a-z,]', '', speed_)) / speed_matrix['mbps'][bit_size] else: speed_ = int(re.sub(r'[a-z,]', '', speed_)) / speed_matrix['gbps'][bit_size] return speed_
def bgp_state_af_vpnv4(self): for device in self.parameters["testbed"].devices.values(): os = device.os if os == "iosxr": bgp_status = device.parse('show bgp ipv4 unicast neighbors') bgp_vrfs = bgp_status.q.get_values('vrf') with open( f"/root/NETDEVOPS/NORNIR/PROJECTS/DEMOS/Test/golden_ops/{device.name}_show-bgp-ipv4-unicast-neighbors_parsed.txt", "rb") as file: golden_template = json.load(file) for vrf in bgp_vrfs: current_vrf = bgp_status['instance']['all']['vrf'][vrf] bgp_neighbors = Dq(current_vrf).get_values("neighbor") golden_vrf = golden_template['instance']['all']['vrf'][ vrf] golden_bgp_neighbors = Dq(golden_vrf).get_values( "neighbor") for neighbor in golden_bgp_neighbors: current_states = Dq( current_vrf).contains_key_value( "neighbor", neighbor).get_values("session_state") golden_states = Dq(golden_vrf).contains_key_value( "neighbor", neighbor).get_values("session_state") try: assert neighbor in bgp_neighbors except Exception as e: self.failed( f"{device.name} {neighbor} is not active int vrf {vrf}" )
def get_ospf_metric(device, destination_address): """Get OSPF metric Args: device (obj): Device object destination_address (str): Destination address """ out = device.parse('show route') # Example dictionary # "route-table": [ # { # "active-route-count": "0", # "destination-count": "0", # "hidden-route-count": "0", # "holddown-route-count": "0", # "rt": [ # { # "metric": "101", # } # }, rt_list = Dq(out).get_values('rt') for rt_dict in rt_list: rt_destination_ = Dq(rt_dict).get_values("rt-destination", 0) if not isinstance(rt_destination_, list): if rt_destination_.startswith(str(destination_address)): metric_ = Dq(rt_dict).get_values('metric', 0) if not metric_: continue return metric_ return None
def verify_path_type(device, expected_interface, expected_path_type, max_time=60, check_interval=10): """Verify 'show ospf route network extensive' Args: device ('obj'): device to use expected_interface ('str'): address to verify expected_path_type ('str'): path to verify max_time ('int'): Maximum time to keep checking. Defaults to 60 check_interval ('int'): How often to check. Defaults to 10 Raise: None Returns: Boolean """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): out = None try: out = device.parse('show ospf route network extensive') except SchemaEmptyParserError: timeout.sleep() continue #{'ospf-route-entry': # {'address-prefix': '1.1.1.1/32', # 'route-path-type': 'Intra', 'route-type': 'Network', # 'next-hop-type': 'IP', 'interface-cost': '0', # 'ospf-next-hop': {'next-hop-name': {'interface-name': 'lo0.0'}}, # 'ospf-area': '0.0.0.0', # 'route-origin': '1.1.1.1', # 'route-priority': 'low' # } # } ospf_route = Dq(out).get_values('ospf-route') for routes in ospf_route: #{'address-prefix': '1.1.1.1/32'} address_prefix = Dq(routes).get_values('address-prefix', 0) if address_prefix and address_prefix != expected_interface: continue #{'route-path-type': 'Intra'} path_type = Dq(routes).get_values('route-path-type', 0) if path_type and path_type.lower() != expected_path_type.lower(): continue return True timeout.sleep() return False
def get_bgp_peer_prefixes( device: object, peer_address: str, ) -> dict: """Return a dictionary of BGP prefix value Args: device (object): Device object peer_address (str): Peer address Returns: dict: Dictionary of prefix values """ try: out = device.parse('show bgp neighbor') except SchemaEmptyParserError: return dict() # Example dict # "bgp-information": { # "bgp-peer": [ # { # "bgp-rib": [ # { # "accepted-prefix-count": str, # "active-prefix-count": str, # "received-prefix-count": str, # "advertised-prefix-count": str, # "suppressed-prefix-count": str, for peer in out.q.get_values('bgp-peer'): peer_interface_ = peer.get('peer-address') # 20.0.0.3+63208 if '+' in peer_interface_: peer_interface_ = peer_interface_.split('+')[0] # 20.0.0.2/24 if '/' in peer_address: peer_address = peer_address.split('/')[0] if peer_interface_ != peer_address: continue ret_dict = { "accepted-prefix-count": Dq(peer).get_values('accepted-prefix-count', 0), "active-prefix-count": Dq(peer).get_values('active-prefix-count', 0), "received-prefix-count": Dq(peer).get_values('received-prefix-count', 0), "advertised-prefix-count": Dq(peer).get_values('advertised-prefix-count', 0), "suppressed-prefix-count": Dq(peer).get_values('suppressed-prefix-count', 0), } return ret_dict
def verify_module_status(device, timeout=180, interval=30, ignore_modules=None): ''' Check status of slot using 'show module' Args: device ('obj'): Device object timeout ('int'): Max timeout to re-check module status interval ('int'): Max interval to re-check module status ignore_modules ('list'): Modules to ignore the status check ''' timeout = Timeout(max_time=timeout, interval=interval) while timeout.iterate(): # Reset failed_slots = [] try: output = device.parse("show module") except SchemaEmptyParserError: timeout.sleep() continue # Check state for all slots failed_slots = Dq(output).contains('status').\ not_contains_key_value('status', '.*ok.*|active|standby|ha-standby|Ready', value_regex=True).\ get_values('lc') failed_slots.extend(Dq(output).contains('status').\ not_contains_key_value('status', '.*ok.*|active|standby|ha-standby|Ready', value_regex=True).\ get_values('rp')) # To ignore specified modules if ignore_modules: for module in ignore_modules: if module in failed_slots: failed_slots.remove(module) log.info("Ignoring the following modules '{}'".\ format(ignore_modules)) if not failed_slots: log.info("All modules on '{}' are in stable state".\ format(device.name)) break else: log.warning("The following modules are not in stable state {}".\ format(failed_slots)) log.warning("Sleeping {} seconds before rechecking".format(interval)) timeout.sleep() continue else: raise Exception("Modules on '{}' are not in stable state".\ format(device.name))
def verify_specific_route(device, address, learn_protocol, max_time=60, check_interval=10): """Verifies address list agianst 'show route protocol {protocol}' Args: device ('obj'): device to use address('str'): address to search for learn_protocol('str'): Learned protocol max_time ('int'): Maximum time to keep checking check_interval ('int'): How often to check Returns: True/False Raises: N/A """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): try: output = device.parse( "show route {address}".format(address=address)) except SchemaEmptyParserError: timeout.sleep() continue # [{'rt-entry': {'active-tag': '*', 'protocol-name': 'OSPF', # 'preference': '10', 'metric': '1', 'age': {'#text': '00:00:01'}, # 'nh': [{'to': '106.187.14.158', 'via': 'ge-0/0/0.0'}]}, # 'rt-destination': '59.128.2.250/32'}] rt_destination_ = Dq(output).get_values("rt-destination", 0) # [{'rt-entry': {'active-tag': '*', 'protocol-name': 'OSPF', # 'preference': '10', 'metric': '1', 'age': {'#text': '00:00:01'} protocol_name = Dq(output).get_values("protocol-name", 0) if protocol_name: if rt_destination_.startswith(str(address)) and \ protocol_name.lower() == learn_protocol.lower(): return True else: timeout.sleep() continue timeout.sleep() return False
def verify_ospf_metric(device, interface, metric, max_time=60, check_interval=10): """Verify the OSPF metric Args: device (obj): Device object interface (str): Interface name metric (str): OSPF metric Returns: True/False Raises: N/A """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): out = None try: out = device.parse('show ospf interface extensive') except SchemaEmptyParserError: timeout.sleep() continue # Example dictionary # "ospf-interface": [ # { # "interface-name": "ge-0/0/0.0", # "ospf-interface-topology": { # "ospf-topology-metric": "5", # }, # }, ospf_interface_list = Dq(out).get_values('ospf-interface') for ospf_interface_dict in ospf_interface_list: #{'interface-name': 'ge-0/0/1.0'} interface_ = Dq(ospf_interface_dict).get_values( 'interface-name', 0) #{'ospf-topology-metric': '5'} metric_ = Dq(ospf_interface_dict).get_values( 'ospf-topology-metric', 0) if interface_.lower() == interface.lower() and str(metric_) == str( metric): return True timeout.sleep() return False
def verify_traffic_statistics_data(device, interface, expected_input_packet=None, expected_output_packet=None, max_time=60, check_interval=10): """ Verify queue counters dropped based on interfaces queue Args: device ('obj'): Device object interface('str'): Interface name expected_input_packet ('str'): input packet expected_output_packet ('str'): output packet max_time (`int`, Optional): Max time, default: 60 seconds check_interval (`int`, Optional): Check interval, default: 10 seconds Returns: Boolean Raises: None """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): try: out = device.parse('show interfaces extensive {interface}'.format( interface=interface)) except SchemaEmptyParserError as e: timeout.sleep() continue #"traffic-statistics": { # "input-bytes": "19732539397", # "input-packets": "133726363", # } actual_input_packet_list = Dq(out).contains( 'traffic-statistics').get_values('input-packets') actual_output_packet_list = Dq(out).contains( 'traffic-statistics').get_values('output-packets') if expected_input_packet and str( expected_input_packet) in actual_input_packet_list: return True if expected_output_packet and str( expected_output_packet) in actual_output_packet_list: return True timeout.sleep() return False
def get_route_advertising_label(device, protocol, ip_address, route, table_name): """Get the label with given table_name via 'show route advertising-protocol {protocol} {ip_address} {route} detail' Args: device ('obj'): Device to use protocol ('str'): Protocol used in show command ip_address ('str'): IP address used in show command route ('str'): Route used in show command table_name ('str'): Label inet Returns: str Raises: N/A """ out = device.parse( "show route advertising-protocol {protocol} {ip_address} {route} detail" .format(protocol=protocol, ip_address=ip_address, route=route)) # Example output # {'route-information': {'route-table': [{'table-name': 'inet.3', <------------------ # 'rt-entry': {'active-tag': '*', # 'as-path': '[1] I', # 'bgp-group': {'bgp-group-name': 'eBGP_SUT-2', # 'bgp-group-type': 'External'}, # 'flags': 'Nexthop Change', # 'med': '1', # 'nh': {'to': 'Self'}, # 'route-label': '17', <------------------ filtered_out = out.q.contains( '{table_name}|route-label'.format(table_name=table_name), regex=True).reconstruct() # filtered_out: # {'route-information': {'route-table': [{'rt-entry': {'route-label': '19'}, # 'table-name': 'inet.3'}]}} rt_list = Dq(filtered_out).get_values('route-table') # rt_list: # [{'table-name': 'inet.3', 'rt-entry': {'route-label': '19'}}] for rt in rt_list: if rt.get('table-name') == table_name: label = Dq(rt).get_values('route-label', 0) if type(label) == str: return int(label) return None
def _search_table_for_metric(op, **kwargs): route_tables = Dq(kwargs['output']).get_values('route-table') for route_table in route_tables: for rt in Dq(route_table).get_values('rt'): destination_address_ = Dq(rt).get_values('rt-destination', 0) if kwargs['address_exceptions'] and destination_address_ in kwargs[ 'address_exceptions']: continue metric_ = Dq(rt).get_values('metric', 0) if op(int(metric_), int(kwargs['metric'])): return False return True
def verify_file_size(device, root_path, file, file_size, max_time=30, check_interval=10): """ Verify specified file size Args: device (obj): Device object root_path (str): Root path file (str): File name file_size (int): File size max_time (int, optional): Maximum sleep time. Defaults to 30. check_interval (int, optional): Check interval. Defaults to 10. """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): out = None try: out = device.parse( 'file list {root_path} detail'.format(root_path=root_path)) except SchemaEmptyParserError: timeout.sleep() continue file_info_list = Dq(out).get_values('file-information') for file_info_dict in file_info_list: if file == file_info_dict.get('file-name'): if int(file_info_dict.get('file-size', 0)) == int(file_size): return True return False
def get_default_dir(device): """ Get the default directory of this device Args: Mandatory: device (`obj`) : Device object. Returns: default_dir (`str`): Default directory of the system Raises: None Example: >>> get_default_dir(device=device) """ try: out = device.parse('file list') default_dir = Dq(out).get_values('dir', 0) except Exception as e: log.error(str(e)) default_dir = '' # Return default_dir to caller log.info("Default directory on '{d}' is '{dir}'".format(d=device.name, dir=default_dir)) return default_dir
def _check_all_devices_connected(self, testbed, data): """ Check if all the targeted devices are connected. each device will be checked. if one of devices is not connected, return False Arguments: testbed (`obj`) : testbed object data (`dict`) : data of section Returns: dev_list (`list`): device list which is connected """ dev_list = [] for each_data in data: for dev in Dq(each_data).get_values('device'): # check if device object, or not if hasattr(dev, 'name'): dev = dev.name # check if device exists in testbed and if connected if dev in testbed.devices and testbed.devices[ dev].is_connected(): dev_list.append(dev) return dev_list
def get_system_users(device): """ Get list of users via show system user Args: device ('obj'): Device object Returns: result (`list`): Get list of username and ip address pairs Raises: N/A """ user_list = [] try: output = device.parse('show system users') except SchemaEmptyParserError: return user_list # schema = { # "user-table": { # "user-entry": [ # { # "command": str, # "from": str, # ... user_table = Dq(output).get_values('user-entry') if user_table: for user in user_table: user_list.append({user['user']: user['from']}) return user_list
def get_system_connections_sessions(device): """ Get list of system connections via show system connections Args: device ('obj'): Device object Returns: result (`list`): Get list of system connection sessions Raises: N/A """ connections = [] try: output = device.parse('show system connections') except SchemaEmptyParserError: return connections # "output": { # "connections-table": [ # { # "proto": str, # "recv-Q": str, # "send-Q": str, # "local-address": str, # "foreign-address": str, # "state": str, # } # ... connections = Dq(output).get_values('connections-table') return connections
def get_ntp_peer_information(device, expected_mode=None): """ Get ntp peer information Args: device (`obj`): Device object expected_mode(`str`, Optional): Expected ntp mode. Defaults to None. Returns: result (`list`): List of peers Raises: N/A """ peer_list = [] try: output = device.parse('show ntp associations') except SchemaEmptyParserError: return peer_list # Example output # 'peer': { # Any(): { # 'local_mode': { # Any(): { # 'remote': str, # 'mode': str, if expected_mode: peer_list = Dq( output.q.contains_key_value( 'mode', expected_mode).reconstruct()).get_values('peer') else: peer_list = output.q.get_values('peer') return peer_list
def get_interface_traffic_input_pps(device: object, interface: str) -> str: """Get interface input pps Args: device (object): Device object interface (str): Interface to check Returns: str: Interface pps """ try: out = device.parse('show interfaces {interface} extensive'.format( interface=interface)) except SchemaEmptyParserError as e: return None # Example dict # "interface-information": { # "physical-interface": [ # { # "traffic-statistics": { # "input-pps": str phy_ = out.q.get_values('physical-interface', 0) return Dq(phy_).get_values('input-pps',0)
def get_available_space(device, directory='', output=None): '''Gets available space on a given directory Args: device ('str'): Device object directory ('str'): Directory to check space If not provided, checks current working directory i.e. media:/path/to/my/dir output ('str'): Output of 'dir' command if not provided, executes the cmd on device Returns: space available in bytes in `int` type or None if failed to retrieve available space ''' try: dir_output = device.parse('dir {}'.format(directory), output=output) except Exception as e: log.error("Failed to parse the directory listing due to: {}".\ format(str(e))) return None bytes_free = Dq(dir_output).get_values(key='bytes_free') if bytes_free: return int(bytes_free[0]) else: log.error("Failed to get available space for {}".format(directory))
def verify_module_status(device, timeout=180, interval=30): ''' Check status of slot using 'show platform' Args: device ('obj'): Device object timeout ('int'): Max timeout to re-check slot status interval ('int'): Max interval to re-check slot status ''' timeout = Timeout(max_time=timeout, interval=interval) while timeout.iterate(): # Reset failed_slots = [] try: output = device.parse("show platform") except SchemaEmptyParserError: timeout.sleep() continue failed_slots = Dq(output).\ contains_key_value('state','IOS XR RUN', value_regex=True) if failed_slots: log.info("All modules on '{}' are in stable state".\ format(device.name)) break else: log.warning("The following modules are not in stable state {}".\ format(failed_slots)) log.warning("Sleeping {} seconds before rechecking".format(interval)) timeout.sleep() continue else: raise Exception("Modules on '{}' are not in stable state".\ format(device.name))
def get_file_size(device, file, output=None): '''Get file size on the device Args: device (`obj`): Device object file (`str`): File name output ('str'): Output of 'dir' command if not provided, executes the cmd on device Returns: file size in `int` type or None if file size is not available ''' directory = ''.join([os.path.dirname(file), '/']) filename = os.path.basename(file) try: dir_output = device.parse('dir {}'.format(directory), output=output) except Exception as e: log.error("Failed to parse the directory listing due to: {}".\ format(str(e))) return None size = Dq(dir_output).contains(filename).get_values('size') if size: return int(size[0]) else: log.error("File '{}' is not found on device".format(file))
def verify_ping(device, ip_addr, max_time=30, check_interval=10): """ Verify ping Args: device ('obj'): Device object ip_addr ('str'): An ip address max_time ('int'): Max time to execute; default is 30 check_interval ('int'): An interval to check again; default is 10 """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): try: out = device.parse('ping {}'.format(ip_addr)) except SubCommandFailure as e: timeout.sleep() continue rate = Dq(out).contains('statistics').get_values('received') if rate: if rate[0] > 0: return True else: timeout.sleep() continue return False
def get_interface_output_pps(device, interface): """ Retrieve output pps value from interface Args: device ('obj'): Device object interface ('str'): Interface name Returns: Output pps value """ out = None try: out = device.parse('monitor interface traffic') except SchemaEmptyParserError as e: return None if not out: return None # Example dict # { # "monitor-time": { # "06:01:12": { # "hostname": "genie", # "interface": { # "ge-0.0.0": { # "output-packets": 0 # }, # } # } # } # } output_pps = Dq(out).contains(interface). \ get_values('output-pps') if not output_pps: return None return output_pps.pop()
def verify_file_details_exists(device, root_path, file, max_time=30, check_interval=10): """ Verify file details exists Args: device ('obj'): Device object root_path ('str'): Root path for command file ('str'): File name max_time (`int`): Max time, default: 30 check_interval (`int`): Check interval, default: 10 Returns: Boolean Raises: None """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): out = None try: out = device.parse( 'file list {root_path} detail'.format(root_path=root_path)) except SchemaEmptyParserError as e: timeout.sleep() continue file_found = Dq(out).contains_key_value('file-name', file, value_regex=True) if file_found: return True timeout.sleep() return False
def get_routing_best_routes( device: object, address: str, protocol: str, active_tag: str = "*", ) -> list: """Return a list of best routes Args: device (object): Device object address (str): Address to check protocol (str): Protocol to check active_tag (str, optional): Active tag. Defaults to "*". Returns: list: List of best routes """ try: out = device.parse("show route protocol {protocol} {address}".format( protocol=protocol, address=address, )) except SchemaEmptyParserError: return list() for rt_ in out.q.get_values('rt'): if rt_.get('rt-entry').get('active-tag') == active_tag: return Dq(rt_).get_values('nh') return list()
def get_file_size(device, root_path, file): """ Get file size from device Args: device ('obj'): Device object root_path ('str'): Root path for command file ('str'): File name Returns: Boolean Raises: None """ out = None out = device.parse( 'file list {root_path} detail'.format(root_path=root_path)) try: file_info_list = out.q.contains( '{}|file-size'.format(file), regex=True).get_values('file-information') for file_info_dict in file_info_list: if 'file-name' in file_info_dict and 'file-size' in file_info_dict: return int(file_info_dict['file-size']) except: file_info_list = Dq(out).get_values('file-information') for file_info_dict in file_info_list: if file == file_info_dict.get('file-name'): return int(file_info_dict.get('file-size', 0)) return None
def verify_config_exists_in_routing_options(device, regex, max_time=60, check_interval=10): """ Verify maximum-path exists in configuration Args: device (`obj`): Device object regex (`str`): Config to search max_time (`int`): Max time, default: 60 check_interval (`int`): Check interval, default: 10 Returns: result (`bool`): Verified result Raises: N/A """ timeout = Timeout(max_time, check_interval) while timeout.iterate(): out = None try: out = device.execute('show configuration routing-options') except SubCommandFailure as e: timeout.sleep() continue if not out: return False config_dict = get_config_dict(out) config_found = Dq(config_dict).contains(regex, regex=True) if config_found: return True timeout.sleep() return False