def save_bootvar(self, testbed): """Check boot information and save bootvar to startup-config Args: testbed (`obj`): Testbed object Returns: None Raises: pyATS Results """ # Create Summary summary = Summary(title='Summary', width=90) devices = [] for dev in self.parent.mapping_data['devices']: device = testbed.devices[dev] if device.type in EXCLUDED_DEVICE_TYPES: msg = " - This subsection is not supported for 'TGN' devices" summarize(summary, message=msg, device=dev) continue devices.append(device) device_dict = {} failed = False # We don't catch exceptions since failures will lead to passx in that # CommonSetup subsection asynchronous_boot_var_output = pcall(asynchronous_save_boot_variable, ckwargs={ 'self': self, 'device_dict': device_dict }, device=tuple(devices)) for item in asynchronous_boot_var_output: for dev, res in item.items(): if res == 'Failed': failed = True msg = " - Failed to save boot variable or copy "\ "running-config to startup-config" summarize(summary, message=msg, device=dev) elif res == 'Skipped': msg = " - Skipped saving boot variable or copy "\ "running-config to startup-config" summarize(summary, message=msg, device=dev) else: msg = " - Successfully saved boot variable" summarize(summary, message=msg, device=dev) summary.print() if failed: self.passx("Issue while saving boot variable on one of the devices, " "Check section summary for more details")
def learn_the_system_from_conf_ops(self, testbed, steps, features=None): """Learn and store the system properties Args: testbed (`obj`): Testbed object steps (`obj`): aetest steps object features (`dict`): dict of feature and attributes which want to learn. ex. {'conf.pim.Pim': [ 'pim[vrf_attr][(.*)][address_family_attr][ipv4][send_rp_announce_intf]', 'pim[vrf_attr][(.*)][address_family_attr][ipv4][send_rp_announce_group_list]'], 'conf.bgp.Bgp': ['bgp[instance][(.*)][vrf_attr][(.*)][confederation_peers_as]']} Returns: None Raises: pyATS Results """ def remove_parent_from_conf_dict(conf_dict): temp_dict = deepcopy(conf_dict) for key, val in temp_dict.items(): if key == 'parent': conf_dict.pop('parent') if isinstance(val, dict): remove_parent_from_conf_dict(conf_dict[key]) def store_structure(device, feature): # get feature and attributes [(ft, attr)] = feature.items() log.info(banner("Learning '{n}' feature with " "attribues {a} on device {d}" .format(n=ft, a=attr, d=device))) # perform lookup per device lib = Lookup.from_device(device) # attach ops and conf lib.conf = getattr(lib, 'conf', conf) lib.ops = getattr(lib, 'ops', ops) # create the ops/conf instance try: obj = attrgetter(ft)(lib) except Exception: raise AttributeError('Cannot load %s for ' 'device %s.' % (ft, device.name)) # conf learn_config if issubclass(obj, ConfBase): ret = obj.learn_config(device=device, attributes=attr) ret = _to_dict(ret[0]) # delete the non-used objects for pcall to retrun ret.pop('__testbed__') ret.pop('devices') ret.pop('interfaces') remove_parent_from_conf_dict(ret['device_attr'][device.name]) elif issubclass(obj, OpsBase): ret = obj(device, attributes=attr) ret.learn() temp = AttrDict() temp.info = getattr(ret, 'info', {}) ret = temp ret_dict = {} ret_dict.setdefault('lts', {}).\ setdefault(ft, {}).setdefault(device.name, ret) # return the dictionary return ret_dict devices = [] for name in testbed.devices: dev = testbed.devices[name] if not dev.is_connected(): continue devices.append(dev) # create the abstract object list merged_dict = {} for ft in features: worker_devs = [] worker_features = [] for device in devices: worker_devs.append(device) worker_features.append({ft: features[ft]}) # pcall for each feature ret = pcall(store_structure, device=worker_devs, feature=worker_features) [merge_dict(merged_dict, i) for i in ret] self.parent.parameters.update(merged_dict) # print out what we learned in LTS log.info('LTS information is \n{d}'.format(d=dumps(merged_dict, indent=5)))
def get_uut_neighbor(section, **kwargs): '''Get uut neighbors from learned LTS in common_setup Can be controlled via sections parameters which is provided by the triggers/verification datafile Args: Mandatory: section (`obj`): Aetest Subsection object. Returns: AETEST results Raises: None ''' def get_peer(device, intf_dict, routing_dict, uut): log.info( banner('Get device %s interface ip and vrf information' % device)) # rebuild interface dict to has structure as # vrf[<vrf>][address_family][af][ip][<ip>][interface][<intf>] new_intf_dict = {} intf_dict = getattr(intf_dict, 'info') for intf in intf_dict: if intf_dict[intf].get('vrf'): vrf_dict = new_intf_dict.setdefault('vrf', {})\ .setdefault(intf_dict[intf].pop('vrf'), {}) else: continue for af in intf_dict[intf]: if af not in ['ipv4', 'ipv6']: continue af_dict = vrf_dict.setdefault('address_family', {})\ .setdefault(af, {}) for ip in intf_dict[intf][af]: ip_dict = af_dict.setdefault('ip', {})\ .setdefault(intf_dict[intf][af][ip]['ip'], {}) ip_dict['interface'] = intf # find routing ip to see if it is from other deivce # if yes, then store the device into to uut neighbors ret = {} for vrf in routing_dict.get('vrf', {}): for af in routing_dict['vrf'][vrf]['address_family']: for route in routing_dict['vrf'][vrf]['address_family'][af][ 'routes']: if routing_dict['vrf'][vrf]['address_family'][af]\ ['routes'][route].get('source_protocol', '') in ['direct', 'local']: continue ip = route.split('/')[0] if new_intf_dict.get('vrf', {}).get(vrf, {}).get('address_family', {})\ .get(af, {}).get('ip', {}).get(ip, {}): ret.setdefault(device, {}).setdefault('vrf', {})\ .setdefault(vrf, {}).setdefault('address_family', {})\ .setdefault(af, {}).setdefault('ip', {}).setdefault(ip, {})\ .update(new_intf_dict.get('vrf', {}).get(vrf, {})\ .get('address_family', {}).get(af, {}).get('ip', {}).get(ip, {})) return ret log.info(banner('Get uut neighbors')) if section and getattr(section, 'parameters', {}): # get testbed testbed = section.parameters.get('testbed', {}) # get default uut uut = section.parameters.get( 'uut', getattr(section, 'uut', testbed.devices['uut'])) # get LTS lts_dict = section.parent.parameters.get('lts', {})\ .get('ops.interface.interface.Interface', None) if not lts_dict: section.skipped('No LTS is learned, No peer found for uut %s' % uut.name) # learning ops routing ops lookup = Lookup.from_device(uut) route_ret = lookup.ops.routing.routing.Routing( uut, attributes=[ 'info[vrf][(.*)][address_family][(.*)][routes][(.*)][source_protocol]', 'info[vrf][(.*)][address_family][(.*)][routes][(.*)][active]' ]) route_ret.learn() # find if uut routing table has the route from other deivces interfaces ip address worker_devices = [] worker_dicts = [] for dev, intf_dict in lts_dict.items(): worker_devices.append(dev) worker_dicts.append(intf_dict) ret = pcall(get_peer, device=worker_devices, intf_dict=worker_dicts, ckwargs={ 'routing_dict': getattr(route_ret, 'info', {}), 'uut': uut }) uut.neighbors = {} [uut.neighbors.update(i) for i in ret] log.info('Get uut {u} neighbors information \n{d}'.format( u=uut.name, d=yaml.dump(uut.neighbors)))