def map_config_to_obj(module): obj = [] dest_group = ('console', 'host', 'monitor', 'buffered', 'on', 'facility') data = get_config(module, flags=['| include logging']) for line in data.split('\n'): match = re.search(r'logging (\S+)', line, re.M) if match: if match.group(1) in dest_group: dest = match.group(1) obj.append({ 'dest': dest, 'name': parse_name(line, dest), 'size': parse_size(line, dest), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) else: ip_match = re.search(r'\d+\.\d+\.\d+\.\d+', match.group(1), re.M) if ip_match: dest = 'host' obj.append({ 'dest': dest, 'name': match.group(1), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) return obj
def interface_is_portchannel(name, module): if get_interface_type(name) == 'ethernet': config = get_config(module, flags=[' | section interface']) if 'channel group' in config: return True return False
def has_vrf(module, vrf): global _CONFIGURED_VRFS if _CONFIGURED_VRFS is not None: return vrf in _CONFIGURED_VRFS config = get_config(module) _CONFIGURED_VRFS = re.findall(r'vrf definition (\S+)', config) return vrf in _CONFIGURED_VRFS
def map_config_to_obj(module): data = get_config(module, flags=['| section username']) match = re.findall(r'(?:^(?:u|\s{2}u))sername (\S+)', data, re.M) if not match: return list() instances = list() for user in set(match): regex = r'username %s .+$' % user cfg = re.findall(regex, data, re.M) cfg = '\n'.join(cfg) obj = { 'name': user, 'state': 'present', 'nopassword': '******' in cfg, 'configured_password': None, 'hashed_password': None, 'password_type': parse_password_type(cfg), 'sshkey': parse_sshkey(data, user), 'privilege': parse_privilege(cfg), 'view': parse_view(cfg) } instances.append(obj) return instances
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^vrf definition (\S+)', config, re.M) if not match: return list() instances = list() interfaces = parse_interfaces(configobj) for item in set(match): obj = { 'name': item, 'state': 'present', 'description': parse_description(configobj, item), 'rd': parse_rd(configobj, item), 'interfaces': interfaces.get(item), 'route_import': parse_import(configobj, item), 'route_export': parse_export(configobj, item), 'route_both': parse_both(configobj, item), 'route_import_ipv4': parse_import_ipv4(configobj, item), 'route_export_ipv4': parse_export_ipv4(configobj, item), 'route_both_ipv4': parse_both(configobj, item, address_family='ipv4'), 'route_import_ipv6': parse_import_ipv6(configobj, item), 'route_export_ipv6': parse_export_ipv6(configobj, item), 'route_both_ipv6': parse_both(configobj, item, address_family='ipv6'), } instances.append(obj) return instances
def map_config_to_obj(module): config = get_config(module, flags=['| section interface']) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^interface (\S+)', config, re.M) if not match: return list() instances = list() for item in set(match): ipv4 = parse_config_argument(configobj, item, 'ip address') if ipv4: # eg. 192.168.2.10 255.255.255.0 -> 192.168.2.10/24 address = ipv4.strip().split(' ') if len(address) == 2 and is_netmask(address[1]): ipv4 = '{0}/{1}'.format(address[0], to_text(to_masklen(address[1]))) obj = { 'name': item, 'ipv4': ipv4, 'ipv6': parse_config_argument(configobj, item, 'ipv6 address'), 'state': 'present' } instances.append(obj) return instances
def map_obj_to_commands(updates, module): commands = list() state = module.params['state'] # FIXME NOT USED for update in updates: want, have = update def needs_update(want, have, x): return want.get(x) and (want.get(x) != have.get(x)) if want['state'] == 'absent': commands.append('no vrf definition %s' % want['name']) continue if not have.get('state'): commands.extend([ 'vrf definition %s' % want['name'], 'address-family ipv4', 'exit', 'address-family ipv6', 'exit', ]) if needs_update(want, have, 'description'): cmd = 'description %s' % want['description'] add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'rd'): cmd = 'rd %s' % want['rd'] add_command_to_vrf(want['name'], cmd, commands) if want['interfaces'] is not None: # handle the deletes for intf in set(have.get('interfaces', [])).difference(want['interfaces']): commands.extend([ 'interface %s' % intf, 'no vrf forwarding %s' % want['name'] ]) # handle the adds for intf in set(want['interfaces']).difference( have.get('interfaces', [])): cfg = get_config(module) configobj = NetworkConfig(indent=1, contents=cfg) children = configobj['interface %s' % intf].children intf_config = '\n'.join(children) commands.extend([ 'interface %s' % intf, 'vrf forwarding %s' % want['name'] ]) match = re.search('ip address .+', intf_config, re.M) if match: commands.append(match.group()) return commands
def get_running_config(module, current_config=None, flags=None): running = module.params['running_config'] if not running: if not module.params['defaults'] and current_config: running = current_config else: running = get_config(module, flags=flags) return running
def map_config_to_obj(module): config = get_config(module) return { 'hostname': parse_hostname(config), 'domain_name': parse_domain_name(config), 'domain_search': parse_domain_search(config), 'lookup_source': parse_lookup_source(config), 'lookup_enabled': 'no ip domain lookup' not in config, 'name_servers': parse_name_servers(config) }
def get_running_config(module, current_config=None): contents = module.params['running_config'] if not contents: if not module.params['defaults'] and current_config: contents, banners = extract_banners(current_config.config_text) else: flags = get_defaults_flag(module) if module.params['defaults'] else [] contents = get_config(module, flags=flags) contents, banners = extract_banners(contents) return NetworkConfig(indent=1, contents=contents), banners
def get_running_config(module, current_config=None, flags=None): contents = module.params['running_config'] if not contents: if not module.params['defaults'] and current_config: contents, banners = extract_banners(current_config.config_text) else: contents = get_config(module, flags=flags) contents, banners = extract_banners(contents) return NetworkConfig(indent=1, contents=contents), banners
def map_config_to_obj(module): obj = [] try: out = run_commands(module, 'show ip static route')[0] match = re.search(r'.*Static local RIB for default\s*(.*)$', out, re.DOTALL) if match and match.group(1): for r in match.group(1).splitlines(): splitted_line = r.split() code = splitted_line[0] if code != 'M': continue cidr = ip_network(to_text(splitted_line[1])) prefix = str(cidr.network_address) mask = str(cidr.netmask) next_hop = splitted_line[4] admin_distance = splitted_line[2][1] obj.append({ 'prefix': prefix, 'mask': mask, 'next_hop': next_hop, 'admin_distance': admin_distance }) except ConnectionError: out = get_config(module, flags='| include ip route') for line in out.splitlines(): splitted_line = line.split() if len(splitted_line) not in (5, 6): continue prefix = splitted_line[2] mask = splitted_line[3] next_hop = splitted_line[4] if len(splitted_line) == 6: admin_distance = splitted_line[5] else: admin_distance = '1' obj.append({ 'prefix': prefix, 'mask': mask, 'next_hop': next_hop, 'admin_distance': admin_distance }) return obj
def get_running_config(module, current_config=None, flags=None): contents = module.params['running_config'] if not contents: if not module.params['defaults'] and current_config: contents, banners = extract_banners(current_config.config_text) else: contents = get_config(module, flags=flags) contents, banners = extract_banners(contents) return NetworkConfig( indent=1, contents=contents, ignore_lines=module.params['diff_ignore_lines']), banners
def map_config_to_obj(module): objs = list() config = get_config(module) for line in config.split('\n'): l = line.strip() match = re.search(r'interface Port-channel(\S+)', l, re.M) if match: obj = {} group = match.group(1) obj['group'] = group obj.update(get_channel(module, config, group)) objs.append(obj) return objs
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^vrf definition (\S+)', config, re.M) if not match: return list() instances = list() for item in set(match): obj = { 'name': item, 'state': 'present', 'description': parse_description(configobj, item), 'rd': parse_rd(configobj, item), 'interfaces': parse_interfaces(configobj, item) } instances.append(obj) return instances
def map_config_to_obj(module): obj_dict = {} obj = [] server_list = [] config = get_config(module, flags=['| include ntp']) for line in config.splitlines(): match = re.search(r'ntp (\S+)', line, re.M) if match: dest = match.group(1) server = parse_server(line, dest) source_int = parse_source_int(line, dest) acl = parse_acl(line, dest) logging = parse_logging(line, dest) auth = parse_auth(dest) auth_key = parse_auth_key(line, dest) key_id = parse_key_id(line, dest) if server: server_list.append(server) if source_int: obj_dict['source_int'] = source_int if acl: obj_dict['acl'] = acl if logging: obj_dict['logging'] = True if auth: obj_dict['auth'] = True if auth_key: obj_dict['auth_key'] = auth_key if key_id: obj_dict['key_id'] = key_id obj_dict['server'] = server_list obj.append(obj_dict) return obj
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^interface (\S+)', config, re.M) if not match: return list() instances = list() for item in set(match): obj = { 'name': item, 'description': parse_config_argument(configobj, item, 'description'), 'speed': parse_config_argument(configobj, item, 'speed'), 'duplex': parse_config_argument(configobj, item, 'duplex'), 'mtu': parse_config_argument(configobj, item, 'mtu'), 'disable': True if parse_shutdown(configobj, item) else False, 'state': 'present' } instances.append(obj) return instances
def map_config_to_obj(module): obj = [] out = get_config(module, flags='| include ip route') for line in out.splitlines(): splitted_line = findall( r'[^"\s]\S*|".+?"', line ) # Split by whitespace but do not split quotes, needed for name parameter if splitted_line[2] == 'vrf': route = {'vrf': splitted_line[3]} del splitted_line[:4] # Removes the words ip route vrf vrf_name else: route = {} del splitted_line[:2] # Removes the words ip route prefix = splitted_line[0] mask = splitted_line[1] route.update({'prefix': prefix, 'mask': mask, 'admin_distance': '1'}) next_word = None for word in splitted_line[2:]: if next_word: route[next_word] = word.strip( '"') # Remove quotes which is needed for name next_word = None elif validate_ip_address(word): route.update(next_hop=word) elif word.isdigit(): route.update(admin_distance=word) elif word in ('tag', 'name', 'track'): next_word = word else: route.update(interface=word) obj.append(route) return obj
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^vrf definition (\S+)', config, re.M) if not match: return list() instances = list() for item in set(match): obj = { 'name': item, 'state': 'present', 'description': parse_description(configobj, item), 'rd': parse_rd(configobj, item), 'interfaces': parse_interfaces(configobj, item), 'route_import': parse_import(configobj, item), 'route_export': parse_export(configobj, item), 'route_both': parse_both(configobj, item) } instances.append(obj) return instances
def map_config_to_obj(module): obj = [] dest_group = ('console', 'host', 'monitor', 'buffered', 'on', 'facility') data = get_config(module, flags=['| include logging']) for line in data.split('\n'): match = re.search(r'logging (\S+)', line, re.M) if match: if match.group(1) in dest_group: dest = match.group(1) obj.append({ 'dest': dest, 'name': parse_name(line, dest), 'size': parse_size(line, dest), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) elif validate_ip_address(match.group(1)): dest = 'host' obj.append({ 'dest': dest, 'name': match.group(1), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) else: ip_match = re.search(r'\d+\.\d+\.\d+\.\d+', match.group(1), re.M) if ip_match: dest = 'host' obj.append({ 'dest': dest, 'name': match.group(1), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) return obj
def map_config_to_obj(module): data = get_config(module, flags=['| section username']) match = re.findall(r'^username (\S+)', data, re.M) if not match: return list() instances = list() for user in set(match): regex = r'username %s .+$' % user cfg = re.findall(regex, data, re.M) cfg = '\n'.join(cfg) obj = { 'name': user, 'state': 'present', 'nopassword': '******' in cfg, 'configured_password': None, 'privilege': parse_privilege(cfg), 'view': parse_view(cfg) } instances.append(obj) return instances
def map_obj_to_commands(updates, module): commands = list() for update in updates: want, have = update def needs_update(want, have, x): if isinstance(want.get(x), list) and isinstance(have.get(x), list): return want.get(x) and (want.get(x) != have.get(x) ) and not all(elem in have.get(x) for elem in want.get(x)) return want.get(x) and (want.get(x) != have.get(x)) if want['state'] == 'absent': commands.append('no vrf definition %s' % want['name']) continue if not have.get('state'): commands.extend(['vrf definition %s' % want['name']]) ipv6 = len([ k for k, v in module.params.items() if (k.endswith('_ipv6') or k.endswith('_both')) and v ]) != 0 ipv4 = len([ k for k, v in module.params.items() if (k.endswith('_ipv4') or k.endswith('_both')) and v ]) != 0 if ipv4: commands.extend(['address-family ipv4', 'exit']) if ipv6: commands.extend(['address-family ipv6', 'exit']) if needs_update(want, have, 'description'): cmd = 'description %s' % want['description'] add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'rd'): cmd = 'rd %s' % want['rd'] add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_import'): for route in want['route_import']: cmd = 'route-target import %s' % route add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_export'): for route in want['route_export']: cmd = 'route-target export %s' % route add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_import_ipv4'): cmd = 'address-family ipv4' add_command_to_vrf(want['name'], cmd, commands) for route in want['route_import_ipv4']: cmd = 'route-target import %s' % route add_command_to_vrf(want['name'], cmd, commands) cmd = 'exit-address-family' add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_export_ipv4'): cmd = 'address-family ipv4' add_command_to_vrf(want['name'], cmd, commands) for route in want['route_export_ipv4']: cmd = 'route-target export %s' % route add_command_to_vrf(want['name'], cmd, commands) cmd = 'exit-address-family' add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_import_ipv6'): cmd = 'address-family ipv6' add_command_to_vrf(want['name'], cmd, commands) for route in want['route_import_ipv6']: cmd = 'route-target import %s' % route add_command_to_vrf(want['name'], cmd, commands) cmd = 'exit-address-family' add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_export_ipv6'): cmd = 'address-family ipv6' add_command_to_vrf(want['name'], cmd, commands) for route in want['route_export_ipv6']: cmd = 'route-target export %s' % route add_command_to_vrf(want['name'], cmd, commands) cmd = 'exit-address-family' add_command_to_vrf(want['name'], cmd, commands) if want['interfaces'] is not None: # handle the deletes for intf in set(have.get('interfaces', [])).difference(want['interfaces']): commands.extend([ 'interface %s' % intf, 'no vrf forwarding %s' % want['name'] ]) # handle the adds for intf in set(want['interfaces']).difference( have.get('interfaces', [])): cfg = get_config(module) configobj = NetworkConfig(indent=1, contents=cfg) children = configobj['interface %s' % intf].children intf_config = '\n'.join(children) commands.extend([ 'interface %s' % intf, 'vrf forwarding %s' % want['name'] ]) match = re.search('ip address .+', intf_config, re.M) if match: commands.append(match.group()) return commands
def main(): """ main entry point for module execution """ backup_spec = dict(filename=dict(), dir_path=dict(type='path')) argument_spec = dict( src=dict(type='path'), lines=dict(aliases=['commands'], type='list'), parents=dict(type='list'), before=dict(type='list'), after=dict(type='list'), match=dict(default='line', choices=['line', 'strict', 'exact', 'none']), replace=dict(default='line', choices=['line', 'block']), multiline_delimiter=dict(default='@'), running_config=dict(aliases=['config']), intended_config=dict(), defaults=dict(type='bool', default=False), backup=dict(type='bool', default=False), backup_options=dict(type='dict', options=backup_spec), save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'), diff_against=dict(choices=['startup', 'intended', 'running']), diff_ignore_lines=dict(type='list'), ) argument_spec.update(ios_argument_spec) mutually_exclusive = [('lines', 'src'), ('parents', 'src')] required_if = [('match', 'strict', ['lines']), ('match', 'exact', ['lines']), ('replace', 'block', ['lines']), ('diff_against', 'intended', ['intended_config'])] module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, required_if=required_if, supports_check_mode=True) result = {'changed': False} warnings = list() check_args(module, warnings) result['warnings'] = warnings diff_ignore_lines = module.params['diff_ignore_lines'] config = None contents = None flags = get_defaults_flag(module) if module.params['defaults'] else [] connection = get_connection(module) if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'): contents = get_config(module, flags=flags) config = NetworkConfig(indent=1, contents=contents) if module.params['backup']: result['__backup__'] = contents if any((module.params['lines'], module.params['src'])): match = module.params['match'] replace = module.params['replace'] path = module.params['parents'] candidate = get_candidate_config(module) running = get_running_config(module, contents, flags=flags) try: response = connection.get_diff(candidate=candidate, running=running, diff_match=match, diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=replace) except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) config_diff = response['config_diff'] banner_diff = response['banner_diff'] if config_diff or banner_diff: commands = config_diff.split('\n') if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) result['commands'] = commands result['updates'] = commands result['banners'] = banner_diff # send the configuration commands to the device and merge # them with the current running config if not module.check_mode: if commands: edit_config_or_macro(connection, commands) if banner_diff: connection.edit_banner(candidate=json.dumps(banner_diff), multiline_delimiter=module. params['multiline_delimiter']) result['changed'] = True running_config = module.params['running_config'] startup_config = None if module.params['save_when'] == 'always': save_config(module, result) elif module.params['save_when'] == 'modified': output = run_commands(module, ['show running-config', 'show startup-config']) running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines) startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines) if running_config.sha1 != startup_config.sha1: save_config(module, result) elif module.params['save_when'] == 'changed' and result['changed']: save_config(module, result) if module._diff: if not running_config: output = run_commands(module, 'show running-config') contents = output[0] else: contents = running_config # recreate the object in order to process diff_ignore_lines running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if module.params['diff_against'] == 'running': if module.check_mode: module.warn( "unable to perform diff against running-config due to check mode" ) contents = None else: contents = config.config_text elif module.params['diff_against'] == 'startup': if not startup_config: output = run_commands(module, 'show startup-config') contents = output[0] else: contents = startup_config.config_text elif module.params['diff_against'] == 'intended': contents = module.params['intended_config'] if contents is not None: base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if running_config.sha1 != base_config.sha1: if module.params['diff_against'] == 'intended': before = running_config after = base_config elif module.params['diff_against'] in ('startup', 'running'): before = base_config after = running_config result.update({ 'changed': True, 'diff': { 'before': str(before), 'after': str(after) } }) module.exit_json(**result)
def main(): """ main entry point for module execution """ argument_spec = dict( src=dict(type='path'), lines=dict(aliases=['commands'], type='list'), parents=dict(type='list'), before=dict(type='list'), after=dict(type='list'), match=dict(default='line', choices=['line', 'strict', 'exact', 'none']), replace=dict(default='line', choices=['line', 'block']), multiline_delimiter=dict(default='@'), running_config=dict(aliases=['config']), intended_config=dict(), defaults=dict(type='bool', default=False), backup=dict(type='bool', default=False), save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'), diff_against=dict(choices=['startup', 'intended', 'running']), diff_ignore_lines=dict(type='list'), # save is deprecated as of ans2.4, use save_when instead save=dict(default=False, type='bool', removed_in_version='2.8'), # force argument deprecated in ans2.2 force=dict(default=False, type='bool', removed_in_version='2.6') ) argument_spec.update(ios_argument_spec) mutually_exclusive = [('lines', 'src'), ('parents', 'src'), ('save', 'save_when')] required_if = [('match', 'strict', ['lines']), ('match', 'exact', ['lines']), ('replace', 'block', ['lines']), ('diff_against', 'intended', ['intended_config'])] module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, required_if=required_if, supports_check_mode=True) result = {'changed': False} warnings = list() check_args(module, warnings) result['warnings'] = warnings config = None flags = get_defaults_flag(module) if module.params['defaults'] else [] if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'): contents = get_config(module, flags=flags) config = NetworkConfig(indent=1, contents=contents) if module.params['backup']: result['__backup__'] = contents if any((module.params['lines'], module.params['src'])): match = module.params['match'] replace = module.params['replace'] path = module.params['parents'] candidate, want_banners = get_candidate(module) if match != 'none': config, have_banners = get_running_config(module, config, flags=flags) path = module.params['parents'] configobjs = candidate.difference(config, path=path, match=match, replace=replace) else: configobjs = candidate.items have_banners = {} banners = diff_banners(want_banners, have_banners) if configobjs or banners: commands = dumps(configobjs, 'commands').split('\n') if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) result['commands'] = commands result['updates'] = commands result['banners'] = banners # send the configuration commands to the device and merge # them with the current running config if not module.check_mode: if commands: load_config(module, commands) if banners: load_banners(module, banners) result['changed'] = True running_config = None startup_config = None diff_ignore_lines = module.params['diff_ignore_lines'] if module.params['save_when'] == 'always' or module.params['save']: save_config(module, result) elif module.params['save_when'] == 'modified': output = run_commands(module, ['show running-config', 'show startup-config']) running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines) startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines) if running_config.sha1 != startup_config.sha1: save_config(module, result) elif module.params['save_when'] == 'changed' and result['changed']: save_config(module, result) if module._diff: if not running_config: output = run_commands(module, 'show running-config') contents = output[0] else: contents = running_config.config_text # recreate the object in order to process diff_ignore_lines running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if module.params['diff_against'] == 'running': if module.check_mode: module.warn("unable to perform diff against running-config due to check mode") contents = None else: contents = config.config_text elif module.params['diff_against'] == 'startup': if not startup_config: output = run_commands(module, 'show startup-config') contents = output[0] else: contents = startup_config.config_text elif module.params['diff_against'] == 'intended': contents = module.params['intended_config'] if contents is not None: base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if running_config.sha1 != base_config.sha1: if module.params['diff_against'] == 'intended': before = running_config after = base_config elif module.params['diff_against'] in ('startup', 'running'): before = base_config after = running_config result.update({ 'changed': True, 'diff': {'before': str(before), 'after': str(after)} }) module.exit_json(**result)
def main(): """ main entry point for module execution """ argument_spec = dict( src=dict(type='path'), lines=dict(aliases=['commands'], type='list'), parents=dict(type='list'), before=dict(type='list'), after=dict(type='list'), match=dict(default='line', choices=['line', 'strict', 'exact', 'none']), replace=dict(default='line', choices=['line', 'block']), multiline_delimiter=dict(default='@'), running_config=dict(aliases=['config']), intended_config=dict(), defaults=dict(type='bool', default=False), backup=dict(type='bool', default=False), save_when=dict(choices=['always', 'never', 'modified'], default='never'), diff_against=dict(choices=['startup', 'intended', 'running']), diff_ignore_lines=dict(type='list'), # save is deprecated as of ans2.4, use save_when instead save=dict(default=False, type='bool', removed_in_version='2.4'), # force argument deprecated in ans2.2 force=dict(default=False, type='bool', removed_in_version='2.2') ) argument_spec.update(ios_argument_spec) mutually_exclusive = [('lines', 'src'), ('save', 'save_when')] required_if = [('match', 'strict', ['lines']), ('match', 'exact', ['lines']), ('replace', 'block', ['lines']), ('diff_against', 'intended', ['intended_config'])] module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, required_if=required_if, supports_check_mode=True) result = {'changed': False} warnings = list() check_args(module, warnings) result['warnings'] = warnings config = None if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'): contents = get_config(module) config = NetworkConfig(indent=1, contents=contents) if module.params['backup']: result['__backup__'] = contents if any((module.params['lines'], module.params['src'])): match = module.params['match'] replace = module.params['replace'] path = module.params['parents'] candidate, want_banners = get_candidate(module) if match != 'none': config, have_banners = get_running_config(module, config) path = module.params['parents'] configobjs = candidate.difference(config, path=path, match=match, replace=replace) else: configobjs = candidate.items have_banners = {} banners = diff_banners(want_banners, have_banners) if configobjs or banners: commands = dumps(configobjs, 'commands').split('\n') if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) result['commands'] = commands result['updates'] = commands result['banners'] = banners # send the configuration commands to the device and merge # them with the current running config if not module.check_mode: if commands: load_config(module, commands) if banners: load_banners(module, banners) result['changed'] = True running_config = None startup_config = None diff_ignore_lines = module.params['diff_ignore_lines'] if module.params['save_when'] != 'never': output = run_commands(module, ['show running-config', 'show startup-config']) running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines) startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines) if running_config.sha1 != startup_config.sha1 or module.params['save_when'] == 'always': result['changed'] = True if not module.check_mode: run_commands(module, 'copy running-config startup-config\r') else: module.warn('Skipping command `copy running-config startup-config` ' 'due to check_mode. Configuration not copied to ' 'non-volatile storage') if module._diff: if not running_config: output = run_commands(module, 'show running-config') contents = output[0] else: contents = running_config.config_text # recreate the object in order to process diff_ignore_lines running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if module.params['diff_against'] == 'running': if module.check_mode: module.warn("unable to perform diff against running-config due to check mode") contents = None else: contents = config.config_text elif module.params['diff_against'] == 'startup': if not startup_config: output = run_commands(module, 'show startup-config') contents = output[0] else: contents = startup_config.config_text elif module.params['diff_against'] == 'intended': contents = module.params['intended_config'] if contents is not None: base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) if running_config.sha1 != base_config.sha1: result.update({ 'changed': True, 'diff': {'before': str(base_config), 'after': str(running_config)} }) module.exit_json(**result)
def map_obj_to_commands(updates, module): commands = list() state = module.params['state'] # FIXME NOT USED for update in updates: want, have = update def needs_update(want, have, x): return want.get(x) and (want.get(x) != have.get(x)) if want['state'] == 'absent': commands.append('no vrf definition %s' % want['name']) continue if not have.get('state'): commands.extend([ 'vrf definition %s' % want['name'], 'address-family ipv4', 'exit', 'address-family ipv6', 'exit', ]) if needs_update(want, have, 'description'): cmd = 'description %s' % want['description'] add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'rd'): cmd = 'rd %s' % want['rd'] add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_import'): for route in want['route_import']: cmd = 'route-target import %s' % route add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_export'): for route in want['route_export']: cmd = 'route-target export %s' % route add_command_to_vrf(want['name'], cmd, commands) if needs_update(want, have, 'route_both'): for route in want['route_both']: cmd = 'route-target both %s' % route add_command_to_vrf(want['name'], cmd, commands) if want['interfaces'] is not None: # handle the deletes for intf in set(have.get('interfaces', [])).difference(want['interfaces']): commands.extend(['interface %s' % intf, 'no vrf forwarding %s' % want['name']]) # handle the adds for intf in set(want['interfaces']).difference(have.get('interfaces', [])): cfg = get_config(module) configobj = NetworkConfig(indent=1, contents=cfg) children = configobj['interface %s' % intf].children intf_config = '\n'.join(children) commands.extend(['interface %s' % intf, 'vrf forwarding %s' % want['name']]) match = re.search('ip address .+', intf_config, re.M) if match: commands.append(match.group()) return commands