def template_values(ext_name, template_name, template_id): if show_args.workdir is None: # Load from vManage via API devices_attached = DeviceTemplateAttached.get(api, template_id) if devices_attached is None: cls.log_error('Failed to retrieve %s attached devices', template_name) return None try: uuid_list = [uuid for uuid, _ in devices_attached] values = DeviceTemplateValues( api.post( DeviceTemplateValues.api_params( template_id, uuid_list), DeviceTemplateValues.api_path.post)) except RestAPIException: cls.log_error('Failed to retrieve %s values', template_name) return None else: # Load from local backup values = DeviceTemplateValues.load(show_args.workdir, ext_name, template_name, template_id) if values is None: cls.log_debug('Skipped %s. No template values file found.', template_name) return values
def detach_template(cls, api, template_index, filter_fn): """ :param api: Instance of Rest API :param template_index: Instance of DeviceTemplateIndex :param filter_fn: Function used to filter elements to be returned :return: List of worker actions to monitor [(<action_worker>, <template_name>), ...] """ action_list = [] for item_id, item_name in template_index.filtered_iter(filter_fn): devices_attached = DeviceTemplateAttached.get(api, item_id) if devices_attached is None: cls.log_warning( 'Failed to retrieve %s attached devices from vManage', item_name) continue uuids, personalities = zip(*devices_attached) # Personalities for all devices attached to the same template are always the same action_worker = DeviceModeCli( api.post(DeviceModeCli.api_params(personalities[0], *uuids), DeviceModeCli.api_path.post)) cls.log_debug('Template detach requested: %s', action_worker.uuid) action_list.append((action_worker, item_name)) return action_list
def runner(cls, api, parsed_args): cls.log_info('Starting backup: vManage URL: "%s" > Local workdir: "%s"', api.base_url, parsed_args.workdir) # Backup workdir must be empty for a new backup saved_workdir = cls.clean_workdir(parsed_args.workdir) if saved_workdir: cls.log_info('Previous backup under "%s" was saved as "%s"', parsed_args.workdir, saved_workdir) target_info = ServerInfo(server_version=api.server_version) if target_info.save(parsed_args.workdir): cls.log_info('Saved vManage server information') if CATALOG_TAG_ALL in parsed_args.tags: # Items without index files to be included with tag 'all' edge_certs = EdgeCertificate.get(api) if edge_certs is None: cls.log_error('Failed backup WAN edge certificates') elif edge_certs.save(parsed_args.workdir): cls.log_info('Saved WAN edge certificates') for _, info, index_cls, item_cls in catalog_entries(*parsed_args.tags): item_index = index_cls.get(api) if item_index is None: cls.log_debug('Skipped %s, item not supported by this vManage', info) continue if item_index.save(parsed_args.workdir): cls.log_info('Saved %s index', info) matched_item_iter = ( (item_id, item_name) for item_id, item_name in item_index if parsed_args.regex is None or regex_search(parsed_args.regex, item_name) ) for item_id, item_name in matched_item_iter: item = item_cls.get(api, item_id) if item is None: cls.log_error('Failed backup %s %s', info, item_name) continue if item.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): cls.log_info('Done %s %s', info, item_name) # Special case for DeviceTemplateAttached and DeviceTemplateValues if isinstance(item, DeviceTemplate): devices_attached = DeviceTemplateAttached.get(api, item_id) if devices_attached is None: cls.log_error('Failed backup %s %s attached devices', info, item_name) continue if devices_attached.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): cls.log_info('Done %s %s attached devices', info, item_name) else: cls.log_debug('Skipped %s %s attached devices, none found', info, item_name) continue try: uuid_list = [uuid for uuid, _ in devices_attached] values = DeviceTemplateValues(api.post(DeviceTemplateValues.api_params(item_id, uuid_list), DeviceTemplateValues.api_path.post)) if values.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): cls.log_info('Done %s %s values', info, item_name) except RestAPIException as ex: cls.log_error('Failed backup %s %s values: %s', info, item_name, ex)
def runner(self, parsed_args, api, task_output=None): self.log_info('Starting backup: vManage URL: "%s" -> Local workdir: "%s"', api.base_url, parsed_args.workdir) # Backup workdir must be empty for a new backup saved_workdir = clean_dir(parsed_args.workdir, max_saved=0 if parsed_args.no_rollover else 99) if saved_workdir: self.log_info('Previous backup under "%s" was saved as "%s"', parsed_args.workdir, saved_workdir) target_info = ServerInfo(server_version=api.server_version) if target_info.save(parsed_args.workdir): self.log_info('Saved vManage server information') # Backup items not registered to the catalog, but to be included when tag is 'all' if CATALOG_TAG_ALL in parsed_args.tags: edge_certs = EdgeCertificate.get(api) if edge_certs is None: self.log_error('Failed backup WAN edge certificates') elif edge_certs.save(parsed_args.workdir): self.log_info('Saved WAN edge certificates') for inventory, info in ((EdgeInventory.get(api), 'WAN edge'), (ControlInventory.get(api), 'controller')): if inventory is None: self.log_error('Failed retrieving %s inventory', info) continue for uuid, _, hostname, _ in inventory.extended_iter(): if hostname is None: self.log_debug('Skipping %s, no hostname', uuid) continue for item, config_type in ((DeviceConfig.get(api, DeviceConfig.api_params(uuid)), 'CFS'), (DeviceConfigRFS.get(api, DeviceConfigRFS.api_params(uuid)), 'RFS')): if item is None: self.log_error('Failed backup %s device configuration %s', config_type, hostname) continue if item.save(parsed_args.workdir, item_name=hostname, item_id=uuid): self.log_info('Done %s device configuration %s', config_type, hostname) # Backup items registered to the catalog for _, info, index_cls, item_cls in catalog_iter(*parsed_args.tags, version=api.server_version): item_index = index_cls.get(api) if item_index is None: self.log_debug('Skipped %s, item not supported by this vManage', info) continue if item_index.save(parsed_args.workdir): self.log_info('Saved %s index', info) matched_item_iter = ( (item_id, item_name) for item_id, item_name in item_index if parsed_args.regex is None or regex_search(parsed_args.regex, item_name) ) for item_id, item_name in matched_item_iter: item = item_cls.get(api, item_id) if item is None: self.log_error('Failed backup %s %s', info, item_name) continue if item.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): self.log_info('Done %s %s', info, item_name) # Special case for DeviceTemplateAttached and DeviceTemplateValues if isinstance(item, DeviceTemplate): devices_attached = DeviceTemplateAttached.get(api, item_id) if devices_attached is None: self.log_error('Failed backup %s %s attached devices', info, item_name) continue if devices_attached.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): self.log_info('Done %s %s attached devices', info, item_name) else: self.log_debug('Skipped %s %s attached devices, none found', info, item_name) continue try: uuid_list = [uuid for uuid, _ in devices_attached] values = DeviceTemplateValues(api.post(DeviceTemplateValues.api_params(item_id, uuid_list), DeviceTemplateValues.api_path.post)) if values.save(parsed_args.workdir, item_index.need_extended_name, item_name, item_id): self.log_info('Done %s %s values', info, item_name) except RestAPIException as ex: self.log_error('Failed backup %s %s values: %s', info, item_name, ex)
def detach(self, api: Rest, template_iter: Iterator[tuple], device_map: Optional[dict] = None, *, chunk_size: int = 10, dryrun: bool = False, log_context: str, raise_on_failure: bool = True) -> int: """ Detach devices from device templates :param api: Instance of Rest API :param template_iter: An iterator of (<template id>, <template name>) tuples containing templates to detach :param device_map: {<uuid>: <name>, ...} dict containing allowed devices for the detach. If None, all attached devices are detached. :param chunk_size: Maximum number of device detachments per request :param dryrun: Indicates dryrun mode :param raise_on_failure: If True, raise exception on action failures :param log_context: Message to log during wait actions :return: Number of detach requests processed """ def grouper(request_list): while True: section_dict = yield from chopper(chunk_size) if not section_dict: continue wait_list = [] for device_type, key_dict in section_dict.items(): request_details = ( f"{t_name} ({', '.join(device_map.get(device_id, '-') for device_id in device_id_list)})" for t_name, device_id_list in key_dict.items()) self.log_info('%sTemplate detach: %s', 'DRY-RUN: ' if dryrun else '', ', '.join(request_details)) if not dryrun: id_list = (device_id for device_id_list in key_dict.values() for device_id in device_id_list) action_worker = DeviceModeCli( api.post( DeviceModeCli.api_params( device_type, *id_list), DeviceModeCli.api_path.post)) wait_list.append((action_worker, ', '.join(key_dict))) self.log_debug('Device template attach requested: %s', action_worker.uuid) request_list.append(...) if wait_list: self.wait_actions(api, wait_list, log_context, raise_on_failure) detach_reqs = [] group = grouper(detach_reqs) next(group) if device_map is None: device_map = dict(device_iter(api)) for template_id, template_name in template_iter: devices_attached = DeviceTemplateAttached.get(api, template_id) if devices_attached is None: self.log_warning( 'Failed to retrieve %s attached devices from vManage', template_name) continue for uuid, personality in devices_attached: if uuid in device_map: group.send((personality, template_name, uuid)) group.send(None) return len(detach_reqs)