class Files(object): """Read and write data to file. """ def __init__(self, session, host, port=443): """Initialize Files object with session parameters. Args: session (obj): Requests Session object host (str): hostname or IP address of vManage port (int): default HTTPS 443 """ self.session = session self.host = host self.port = port self.base_url = f'https://{self.host}:{self.port}/dataservice/' self.device_templates = DeviceTemplates(self.session, self.host, self.port) self.feature_templates = FeatureTemplates(self.session, self.host, self.port) self.template_data = TemplateData(self.session, self.host, self.port) self.policy_data = PolicyData(self.session, self.host, self.port) self.policy_lists = PolicyLists(self.session, self.host, self.port) self.policy_definitions = PolicyDefinitions(self.session, self.host, self.port) self.local_policy = LocalPolicy(self.session, self.host, self.port) self.central_policy = CentralPolicy(self.session, self.host, self.port) self.security_policy = SecurityPolicy(self.session, self.host, self.port) self.vmanage_device = Device(self.session, self.host, self.port) def export_templates_to_file(self, export_file, name_list=None, template_type=None): """Export templates to a file. All object IDs will be translated to names. Use a '.yml' extention to export as YAML and a '.json' extension to export as JSON. Args: export_file (str): The name of the export file name_list (list): List of device templates to export template_type (str): Template type: device or template """ template_export = {} #pylint: disable=too-many-nested-blocks if template_type != 'feature': # Export the device templates and associated feature templates device_template_list = self.template_data.export_device_template_list(name_list=name_list) template_export.update({'vmanage_device_templates': device_template_list}) feature_name_list = [] if name_list: for device_template in device_template_list: if 'generalTemplates' in device_template: for general_template in device_template['generalTemplates']: if 'templateName' in general_template: feature_name_list.append(general_template['templateName']) if 'subTemplates' in general_template: for sub_template in general_template['subTemplates']: if 'templateName' in sub_template: feature_name_list.append(sub_template['templateName']) name_list = list(set(feature_name_list)) # Since device templates depend on feature templates, we always add them. feature_template_list = self.feature_templates.get_feature_template_list(name_list=name_list) template_export.update({'vmanage_feature_templates': feature_template_list}) if export_file.endswith('.json'): with open(export_file, 'w') as outfile: json.dump(template_export, outfile, indent=4, sort_keys=False) elif export_file.endswith('.yaml') or export_file.endswith('.yml'): with open(export_file, 'w') as outfile: yaml.dump(template_export, outfile, indent=4, sort_keys=False) else: raise Exception("File format not supported") #pylint: disable=unused-argument def import_templates_from_file(self, import_file, update=False, check_mode=False, name_list=None, template_type=None): """Import templates from a file. All object Names will be translated to IDs. Args: import_file (str): The name of the import file name_list (list): List of device templates to export template_type (str): Template type: device or template check_mode (bool): Try the import, but don't make changes (default: False) update (bool): Update existing templates (default: False) """ feature_template_updates = [] device_template_updates = [] imported_template_data = {} # Read in the datafile if not os.path.exists(import_file): raise Exception(f"Cannot find file {import_file}") with open(import_file) as f: if import_file.endswith('.yaml') or import_file.endswith('.yml'): imported_template_data = yaml.safe_load(f) else: imported_template_data = json.load(f) if 'vmanage_feature_templates' in imported_template_data: imported_feature_template_list = imported_template_data['vmanage_feature_templates'] else: imported_feature_template_list = [] imported_device_template_list = [] #pylint: disable=too-many-nested-blocks if template_type != 'feature': # Import the device templates and associated feature templates if 'vmanage_device_templates' in imported_template_data: imported_device_template_list = imported_template_data['vmanage_device_templates'] if name_list: feature_name_list = [] pruned_device_template_list = [] for device_template in imported_device_template_list: if device_template['templateName'] in name_list: pruned_device_template_list.append(device_template) if 'generalTemplates' in device_template: for general_template in device_template['generalTemplates']: if 'templateName' in general_template: feature_name_list.append(general_template['templateName']) if 'subTemplates' in general_template: for sub_template in general_template['subTemplates']: if 'templateName' in sub_template: feature_name_list.append(sub_template['templateName']) imported_device_template_list = pruned_device_template_list name_list = list(set(feature_name_list)) # Since device templates depend on feature templates, we always add them. if name_list: pruned_feature_template_list = [] imported_feature_template_dict = list_to_dict(imported_feature_template_list, key_name='templateName', remove_key=False) for feature_template_name in name_list: if feature_template_name in imported_feature_template_dict: pruned_feature_template_list.append(imported_feature_template_dict[feature_template_name]) # Otherwise, we hope the feature list is already there (e.g. Factory Default) imported_feature_template_list = pruned_feature_template_list # Process the feature templates feature_template_updates = self.template_data.import_feature_template_list(imported_feature_template_list, check_mode=check_mode, update=update) # Process the device templates device_template_updates = self.template_data.import_device_template_list(imported_device_template_list, check_mode=check_mode, update=update) return { 'feature_template_updates': feature_template_updates, 'device_template_updates': device_template_updates, } # # Policy # def export_policy_to_file(self, export_file): """Export policy to a file. All object IDs will be translated to names. Use a '.yml' extention to export as YAML and a '.json' extension to export as JSON. Args: export_file (str): The name of the export file """ policy_lists_list = self.policy_lists.get_policy_list_list() policy_definitions_list = self.policy_data.export_policy_definition_list() central_policies_list = self.policy_data.export_central_policy_list() local_policies_list = self.local_policy.get_local_policy_list() security_policies_list = self.policy_data.export_security_policy_list() policy_export = { 'vmanage_policy_lists': policy_lists_list, 'vmanage_policy_definitions': policy_definitions_list, 'vmanage_central_policies': central_policies_list, 'vmanage_local_policies': local_policies_list, 'vmanage_security_policies': security_policies_list } if export_file.endswith('.json'): with open(export_file, 'w') as outfile: json.dump(policy_export, outfile, indent=4, sort_keys=False) elif export_file.endswith(('.yaml', 'yml')): with open(export_file, 'w') as outfile: yaml.dump(policy_export, outfile, default_flow_style=False) else: raise Exception("File format not supported") def import_policy_from_file(self, file, update=False, check_mode=False, push=False): """Import policy from a file. All object Names will be translated to IDs. Args: import_file (str): The name of the import file check_mode (bool): Try the import, but don't make changes (default: False) update (bool): Update existing templates (default: False) push (bool): Push tempaltes to devices if changed (default: False) """ policy_list_updates = [] policy_definition_updates = [] central_policy_updates = [] local_policy_updates = [] security_policy_updates = [] # Read in the datafile if not os.path.exists(file): raise Exception('Cannot find file {0}'.format(file)) with open(file) as f: if file.endswith('.yaml') or file.endswith('.yml'): policy_data = yaml.safe_load(f) else: policy_data = json.load(f) # Separate the feature template data from the device template data if 'vmanage_policy_lists' in policy_data: policy_list_data = policy_data['vmanage_policy_lists'] else: policy_list_data = [] if 'vmanage_policy_definitions' in policy_data: policy_definition_data = policy_data['vmanage_policy_definitions'] else: policy_definition_data = [] if 'vmanage_central_policies' in policy_data: central_policy_data = policy_data['vmanage_central_policies'] else: central_policy_data = [] if 'vmanage_local_policies' in policy_data: local_policy_data = policy_data['vmanage_local_policies'] else: local_policy_data = [] if 'vmanage_security_policies' in policy_data: security_policy_data = policy_data['vmanage_security_policies'] else: security_policy_data = [] policy_list_updates = self.policy_data.import_policy_list_list(policy_list_data, check_mode=check_mode, update=update, push=push) self.policy_lists.clear_policy_list_cache() policy_definition_updates = self.policy_data.import_policy_definition_list(policy_definition_data, check_mode=check_mode, update=update, push=push) central_policy_updates = self.policy_data.import_central_policy_list(central_policy_data, check_mode=check_mode, update=update, push=push) local_policy_updates = self.policy_data.import_local_policy_list(local_policy_data, check_mode=check_mode, update=update, push=push) security_policy_updates = self.policy_data.import_security_policy_list(security_policy_data, check_mode=check_mode, update=update, push=push) return { 'policy_list_updates': policy_list_updates, 'policy_definition_updates': policy_definition_updates, 'central_policy_updates': central_policy_updates, 'local_policy_updates': local_policy_updates, 'security_policy_updates': security_policy_updates } def export_attachments_to_file(self, export_file, name_list=None, device_type=None): """Export attachments to a file. All object IDs will be translated to names. Use a '.yml' extention to export as YAML and a '.json' extension to export as JSON. Args: export_file (str): The name of the export file """ if name_list is None: name_list = [] device_template_dict = self.device_templates.get_device_template_dict() attachments_list = [] # Create a device config of the right type of things device_list = [] if device_type in (None, 'controllers'): device_list = self.vmanage_device.get_device_config_list('controllers') if device_type in (None, 'vedges'): edge_list = self.vmanage_device.get_device_config_list('vedges') device_list = device_list + edge_list for device_config in device_list: if 'configStatusMessage' in device_config and device_config['configStatusMessage'] != 'In Sync': continue if 'template' in device_config: if device_config['template'] in device_template_dict: template_id = device_template_dict[device_config['template']]['templateId'] else: raise Exception(f"Could not find ID for template {device_config['template']}") if name_list == [] or device_config.get('host-name') in name_list: variable_dict = {} template_input = self.device_templates.get_template_input(template_id, device_id_list=[device_config['uuid']]) data = template_input['data'][0] for column in template_input['columns']: variable_dict[column['variable']] = data[column['property']] entry = { 'host_name': device_config.get('host-name'), 'device_type': device_config['deviceType'], 'uuid': device_config['chasisNumber'], 'system_ip': device_config['deviceIP'], 'site_id': device_config.get('site-id'), 'template': device_config['template'], 'variables': variable_dict } attachments_list.append(entry) attachment_export = {'vmanage_attachments': attachments_list} if export_file.endswith('.json'): with open(export_file, 'w') as outfile: json.dump(attachment_export, outfile, indent=4, sort_keys=False) elif export_file.endswith(('.yaml', 'yml')): with open(export_file, 'w') as outfile: yaml.dump(attachment_export, outfile, indent=4, sort_keys=False) else: raise Exception("File format not supported") return (len(attachments_list)) def import_attachments_from_file(self, import_file, update=False, check_mode=False, name_list=None, template_type=None): """Import policy from a file. All object Names will be translated to IDs. Args: import_file (str): The name of the import file check_mode (bool): Try the import, but don't make changes (default: False) update (bool): Update existing templates (default: False) """ template_data = {} # Read in the datafile if not os.path.exists(import_file): raise Exception(f"Cannot find file {import_file}") with open(import_file) as f: if import_file.endswith('.yaml') or import_file.endswith('.yml'): template_data = yaml.safe_load(f) else: template_data = json.load(f) if 'vmanage_attachments' in template_data: imported_attachment_list = template_data['vmanage_attachments'] else: imported_attachment_list = [] # Process the device templates result = self.template_data.import_attachment_list(imported_attachment_list, check_mode=check_mode, update=update) return result
def run_module(): # define available arguments/parameters a user can pass to the module argument_spec = vmanage_argument_spec() argument_spec.update(state=dict(type='str', choices=['absent', 'present'], default='present'), aggregate=dict(type='list'), name=dict(type='str'), description=dict(type='str'), type=dict(type='str', required=False, choices=['all', 'color', 'vpn', 'site', 'app', 'dataprefix', 'prefix', 'aspath', 'class', 'community', 'extcommunity', 'mirror', 'tloc', 'sla', 'policer', 'ipprefixall', 'dataprefixall'], default='all'), entries=dict(type='list'), update=dict(type='bool', default=False), push=dict(type='bool', default=False), force=dict(type='bool', default=False) ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict( changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, ) vmanage = Vmanage(module) vmanage_policy_lists = PolicyLists(vmanage.auth, vmanage.host) vmanage_policy_data = PolicyData(vmanage.auth, vmanage.host) # Always as an aggregate... make a list if just given a single entry if vmanage.params['aggregate']: policy_list_list = vmanage.params['aggregate'] else: policy_list_list = [ { "name": vmanage.params['name'], "description": vmanage.params['description'], "type": vmanage.params['type'], "entries": vmanage.params['entries'], } ] # Import site lists policy_list_updates = [] if vmanage.params['state'] == 'present': policy_list_updates = vmanage_policy_data.import_policy_list_list( policy_list_list, check_mode=module.check_mode, update=vmanage.params['update'], push=vmanage.params['push'] ) if policy_list_updates: vmanage.result['changed'] = True else: policy_list_dict = vmanage_policy_lists.get_policy_list_dict(vmanage.params['type'], remove_key=False) for policy_list in policy_list_list: if policy_list['name'] in policy_list_dict: diff = list(dictdiffer.diff({}, policy_list)) policy_list_updates.append({'name': policy_list['name'], 'diff': diff}) if not module.check_mode: vmanage_policy_lists.delete_policy_list(policy_list['type'].lower(), policy_list['listId']) vmanage.result['changed'] = True vmanage.params['updates'] = policy_list_updates vmanage.exit_json(**vmanage.result)