Ejemplo n.º 1
0
        def load_template_input(template_name, saved_id, target_id):
            if target_id is None:
                cls.log_debug('Skip %s, saved template is not on target node', template_name)
                return None

            saved_values = DeviceTemplateValues.load(workdir, ext_name, template_name, saved_id)
            if saved_values is None:
                cls.log_error('DeviceTemplateValues file not found: %s, %s', template_name, saved_id)
                return None
            if saved_values.is_empty:
                cls.log_debug('Skip %s, saved template has no attachments', template_name)
                return None

            target_attached_uuid_set = {uuid for uuid, _ in DeviceTemplateAttached.get_raise(api, target_id)}
            if target_uuid_set is None:
                allowed_uuid_set = target_attached_uuid_set
            else:
                saved_attached = DeviceTemplateAttached.load(workdir, ext_name, template_name, saved_id)
                if saved_attached is None:
                    cls.log_error('DeviceTemplateAttached file not found: %s, %s', template_name, saved_id)
                    return None
                saved_attached_uuid_set = {uuid for uuid, _ in saved_attached}
                allowed_uuid_set = target_uuid_set & saved_attached_uuid_set - target_attached_uuid_set

            input_list = saved_values.input_list(allowed_uuid_set)
            if len(input_list) == 0:
                cls.log_debug('Skip %s, no devices to attach', template_name)
                return None

            return input_list
Ejemplo n.º 2
0
        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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
 def get_template_input(template_id):
     uuid_list = [
         uuid for uuid, _ in DeviceTemplateAttached.get_raise(
             api, template_id)
     ]
     values = DeviceTemplateValues(
         api.post(
             DeviceTemplateValues.api_params(template_id, uuid_list),
             DeviceTemplateValues.api_path.post))
     return values.input_list()
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)