def get_sublevel_config(running_config, module): contents = list() current_config_contents = list() sublevel_config = NetworkConfig(indent=0) obj = running_config.get_object(module.params['parents']) if obj: contents = obj._children for c in contents: if isinstance(c, ConfigLine): current_config_contents.append(c.raw) sublevel_config.add(current_config_contents, module.params['parents']) return sublevel_config
def get_candidate_config(module): candidate = '' if module.params['src']: candidate = module.params['src'] elif module.params['lines']: candidate_obj = NetworkConfig(indent=1) parents = module.params['parents'] or list() candidate_obj.add(module.params['lines'], parents=parents) candidate = dumps(candidate_obj, 'raw') return candidate
def get_candidate(module): candidate = "" if module.params["src"]: if module.params["replace"] != "config": candidate = module.params["src"] if module.params["replace"] == "config": candidate = "config replace {0}".format(module.params["replace_src"]) elif module.params["lines"]: candidate_obj = NetworkConfig(indent=2) parents = module.params["parents"] or list() candidate_obj.add(module.params["lines"], parents=parents) candidate = dumps(candidate_obj, "raw") return candidate
def get_candidate(module): candidate = '' if module.params['src']: if module.params['replace'] != 'config': candidate = module.params['src'] if module.params['replace'] == 'config': candidate = 'config replace {0}'.format(module.params['replace_src']) elif module.params['lines']: candidate_obj = NetworkConfig(indent=2) parents = module.params['parents'] or list() candidate_obj.add(module.params['lines'], parents=parents) candidate = dumps(candidate_obj, 'raw') return candidate
def run(module, result): match = module.params['match'] replace = module.params['replace'] replace_config = replace == 'config' diff_ignore_lines = module.params['diff_ignore_lines'] path = module.params['parents'] check_mode = module.check_mode candidate = get_candidate(module) if match != 'none' and replace != 'config': contents = get_running_config(module) configobj = NetworkConfig(contents=contents, indent=1) commands = candidate.difference(configobj, path=path, match=match, replace=replace) else: commands = candidate.items if commands: commands = dumps(commands, 'commands').split('\n') if any((module.params['lines'], module.params['src'])): if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) result['commands'] = commands diff = load_config(module, commands) if diff: result['diff'] = dict(prepared=diff) 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)
def get_candidate(module): candidate = NetworkConfig(indent=1) if module.params['src']: candidate.load(module.params['src']) elif module.params['lines']: parents = module.params['parents'] or list() commands = module.params['lines'][0] if (isinstance(commands, dict)) and (isinstance(commands['command'], list)): candidate.add(commands['command'], parents=parents) elif (isinstance(commands, dict)) and (isinstance(commands['command'], str)): candidate.add([commands['command']], parents=parents) else: candidate.add(module.params['lines'], parents=parents) return candidate
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): 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_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): 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 run(module, result): match = module.params['match'] replace = module.params['replace'] replace_config = replace == 'config' path = module.params['parents'] comment = module.params['comment'] admin = module.params['admin'] check_mode = module.check_mode candidate = get_candidate(module) if match != 'none' and replace != 'config': contents = get_running_config(module) configobj = NetworkConfig(contents=contents, indent=1) commands = candidate.difference(configobj, path=path, match=match, replace=replace) else: commands = candidate.items if commands: commands = dumps(commands, 'commands').split('\n') if any((module.params['lines'], module.params['src'])): if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) result['commands'] = commands diff = load_config(module, commands) if diff: result['diff'] = dict(prepared=diff) result['changed'] = True
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) configobj = NetworkConfig(indent=1, contents=config) match = re.findall("^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): compare = module.params['check_running_config'] config = get_config(module, flags=['| begin interface'], compare=compare) configobj = NetworkConfig(indent=1, contents=config) match = re.findall(r'^interface (\S+ \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: 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 get_running_config(module, current_config=None): contents = module.params['running_config'] if not contents: if current_config: contents = current_config.config_text else: contents = get_config(module) return NetworkConfig(indent=1, contents=contents)
def get_config(module, result): contents = module.params['config'] if not contents: defaults = module.params['defaults'] contents = module.config.get_config(include_defaults=defaults) contents, banners = extract_banners(contents) return NetworkConfig(indent=1, contents=contents), banners
def get_running_config(module, config=None): contents = module.params['running_config'] if not contents: if config: contents = config else: contents = get_config(module) return NetworkConfig(contents=contents)
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=2, contents=config) vrf_config = {} vrfs = re.findall(r'^vrf context (\S+)$', config, re.M) for vrf in vrfs: config_data = configobj.get_block_config(path=['vrf context %s' % vrf]) vrf_config[vrf] = config_data return { 'hostname': parse_hostname(config), 'domain_lookup': 'no ip domain-lookup' not in config, 'domain_name': parse_domain_name(config, vrf_config), 'domain_search': parse_domain_search(config, vrf_config), 'name_servers': parse_name_servers(config, vrf_config, vrfs), 'system_mtu': parse_system_mtu(config) }
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=2, contents=config) vrf_config = {} vrfs = re.findall(r"^vrf context (\S+)$", config, re.M) for vrf in vrfs: config_data = configobj.get_block_config(path=["vrf context %s" % vrf]) vrf_config[vrf] = config_data return { "hostname": parse_hostname(config), "domain_lookup": "no ip domain-lookup" not in config, "domain_name": parse_domain_name(config, vrf_config), "domain_search": parse_domain_search(config, vrf_config), "name_servers": parse_name_servers(config, vrf_config, vrfs), "system_mtu": parse_system_mtu(config), }
def get_sublevel_config(running_config, module): contents = list() current_config_contents = list() running_config = NetworkConfig(contents=running_config, indent=1) obj = running_config.get_object(module.params['parents']) if obj: contents = obj.children contents[:0] = module.params['parents'] indent = 0 for c in contents: if isinstance(c, str): current_config_contents.append(c.rjust(len(c) + indent, ' ')) if isinstance(c, ConfigLine): current_config_contents.append(c.raw) indent = 1 sublevel_config = '\n'.join(current_config_contents) return sublevel_config
def map_config_to_obj(module, warnings): config = get_config(module, flags=["| section interface"]) configobj = NetworkConfig(indent=3, contents=config) match = re.findall(r"^interface (\S+)", config, re.M) if not match: return list() instances = list() for item in set(match): command = { "command": "show interfaces {0} switchport | include Switchport".format(item), "output": "text", } command_result = run_commands(module, command, check_rc=False) if "Interface does not exist" in command_result[0]: warnings.append( "Could not gather switchport information for {0}: {1}".format( item, command_result[0])) continue if command_result[0]: switchport_cfg = command_result[0].split(":")[1].strip() if switchport_cfg == "Enabled": state = "present" else: state = "absent" obj = { "name": item.lower(), "state": state, "access_vlan": parse_config_argument(configobj, item, "switchport access vlan"), "native_vlan": parse_config_argument(configobj, item, "switchport trunk native vlan"), "trunk_allowed_vlans": parse_config_argument(configobj, item, "switchport trunk allowed vlan"), } if obj["access_vlan"]: obj["mode"] = "access" else: obj["mode"] = "trunk" instances.append(obj) return instances
def main(): """ main entry point for module execution """ argument_spec = dict(rollback_location=dict(), local_max_checkpoints=dict(type='int'), remote_max_checkpoints=dict(type='int'), rescue_location=dict(), state=dict(default='present', choices=['present', 'absent'])) argument_spec.update(sros_argument_spec) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) state = module.params['state'] result = dict(changed=False) commands = list() invoke(state, module, commands) candidate = NetworkConfig(indent=4, contents='\n'.join(commands)) config = get_device_config(module) configobjs = candidate.difference(config) if configobjs: # commands = dumps(configobjs, 'lines') commands = dumps(configobjs, 'commands') commands = sanitize_config(commands.split('\n')) result['updates'] = commands result['commands'] = commands # send the configuration commands to the device and merge # them with the current running config if not module.check_mode: load_config(module, commands) result['changed'] = True module.exit_json(**result)
def map_config_to_obj(module): config = get_config(module) configobj = NetworkConfig(indent=2, contents=config) return { 'hostname': parse_hostname(config), 'lookup_enabled': 'no ip domain-lookup' not in config, 'domain_name': parse_domain_name(config), 'domain_search': parse_domain_search(config), 'name_servers': parse_name_servers(config), }
def get_acl_config(module, acl_name): contents = module.params['config'] if not contents: contents = get_config(module) filtered_config = list() for item in contents.split('\n'): if item.startswith('access-list %s ' % acl_name): filtered_config.append(item) return NetworkConfig(indent=1, contents='\n'.join(filtered_config))
def get_acl_config(module, acl_name): contents = module.params["config"] if not contents: contents = get_config(module) filtered_config = list() for item in contents.split("\n"): if item.startswith("access-list %s " % acl_name): filtered_config.append(item) return NetworkConfig(indent=1, contents="\n".join(filtered_config))
def get_diff(self, candidate=None, running=None, diff_match='line', path=None, diff_replace='line'): diff = {} device_operations = self.get_device_operations() option_values = self.get_option_values() if candidate is None and device_operations['supports_generate_diff']: raise ValueError( "candidate configuration is required to generate diff") if diff_match not in option_values['diff_match']: raise ValueError( "'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match']))) if diff_replace not in option_values['diff_replace']: raise ValueError( "'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace']))) # prepare candidate configuration candidate_obj = NetworkConfig(indent=4, contents=candidate) if running and diff_match != "none" and diff_replace != "config": running_obj = load_running_config(running=running) configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace) else: configdiffobjs = candidate_obj.items diff["config_diff"] = (dumps(configdiffobjs, "commands") if configdiffobjs else "") return diff
def run(module, result): match = module.params["match"] replace = module.params["replace"] path = module.params["parents"] candidate = get_candidate(module) if match != "none": contents = module.params["config"] if not contents: contents = get_config(module) config = NetworkConfig(indent=1, contents=contents) configobjs = candidate.difference(config, path=path, match=match, replace=replace) else: configobjs = candidate.items if configobjs: commands = dumps(configobjs, "commands").split("\n") if module.params["lines"]: if module.params["before"]: commands[:0] = module.params["before"] if module.params["after"]: commands.extend(module.params["after"]) result["updates"] = commands # send the configuration commands to the device and merge # them with the current running config if not module.check_mode: load_config(module, commands) result["changed"] = True if module.params["save"]: module.warn( "module param save is deprecated, please use newer and updated param save_when instead which is released with more functionality!" ) save_config(module, result) if module.params["save_when"] == "always": save_config(module, result) elif module.params["save_when"] == "modified": running_config_checksum = run_commands( module, "show running-config | include checksum:") startup_config_checksum = run_commands( module, "show startup-config | include checksum:") if running_config_checksum != startup_config_checksum: save_config(module, result) elif module.params["save_when"] == "changed" and result["changed"]: save_config(module, result)
def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'): diff = {} device_operations = self.get_device_operations() option_values = self.get_option_values() if candidate is None and device_operations['supports_generate_diff']: raise ValueError("candidate configuration is required to generate diff") if diff_match not in option_values['diff_match']: raise ValueError("'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match']))) if diff_replace not in option_values['diff_replace']: raise ValueError("'replace' value %s in invalid, valid values are %s" % (diff_replace, ', '.join(option_values['diff_replace']))) # prepare candidate configuration sanitized_candidate = sanitize_config(candidate) candidate_obj = NetworkConfig(indent=1) candidate_obj.load(sanitized_candidate) if running and diff_match != 'none': # running configuration running = mask_config_blocks_from_diff(running, candidate, "ansible") running = sanitize_config(running) running_obj = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines) configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace) else: configdiffobjs = candidate_obj.items diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else '' return diff
def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'): diff = {} # prepare candidate configuration candidate_obj = NetworkConfig(indent=1) candidate_obj.load(candidate) if running and diff_match != 'none' and diff_replace != 'config': # running configuration running_obj = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines) configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace) else: configdiffobjs = candidate_obj.items diff['config_diff'] = dumps(configdiffobjs, 'commands') if configdiffobjs else '' return diff
def get_diff( self, candidate=None, running=None, diff_match="line", diff_ignore_lines=None, path=None, diff_replace="line", ): diff = {} # prepare candidate configuration candidate_obj = NetworkConfig(indent=3) candidate_obj.load(candidate) if running and diff_match != "none" and diff_replace != "config": # running configuration running_obj = NetworkConfig( indent=3, contents=running, ignore_lines=diff_ignore_lines ) configdiffobjs = candidate_obj.difference( running_obj, path=path, match=diff_match, replace=diff_replace ) else: configdiffobjs = candidate_obj.items diff["config_diff"] = ( dumps(configdiffobjs, "commands") if configdiffobjs else {} ) return diff
def get_diff(self, candidate=None, running=None, diff_match=None, diff_ignore_lines=None): diff = {} device_operations = self.get_device_operations() option_values = self.get_option_values() if candidate is None and device_operations['supports_generate_diff']: raise ValueError( "candidate configuration is required to generate diff") if diff_match not in option_values['diff_match']: raise ValueError( "'match' value %s in invalid, valid values are %s" % (diff_match, ', '.join(option_values['diff_match']))) candidate_obj = NetworkConfig(indent=1) candidate_obj.load(candidate) if running and diff_match != 'none': running_obj = NetworkConfig(indent=1, contents=running, ignore_lines=diff_ignore_lines) config_diff_objs = candidate_obj.difference(running_obj, match=diff_match) else: config_diff_objs = candidate_obj.items diff['config_diff'] = dumps(config_diff_objs, 'commands') if config_diff_objs else '' return diff
def main(): argument_spec = dict( lines=dict( aliases=["commands"], required=True, type="list", elements="str" ), before=dict(type="list", elements="str"), after=dict(type="list", elements="str"), match=dict( default="line", choices=["line", "strict", "exact"], type="str" ), replace=dict(default="line", choices=["line", "block"], type="str"), force=dict(default=False, type="bool"), config=dict(type="str"), ) argument_spec.update(asa_argument_spec) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True ) lines = module.params["lines"] result = {"changed": False} if len(lines) > 0: candidate = NetworkConfig(indent=1) candidate.add(lines) acl_name = parse_acl_name(module) if not module.params["force"]: contents = get_acl_config(module, acl_name) config = NetworkConfig(indent=1, contents=contents) commands = candidate.difference(config) if commands and module.params["replace"] == "block": commands = str(candidate).split("\n") else: commands = dumps(commands, "commands").split("\n") commands = [str(c) for c in commands if c] else: commands = str(candidate).split("\n") if commands: if module.params["before"]: commands[:0] = module.params["before"] if module.params["after"]: commands.extend(module.params["after"]) if not module.check_mode: load_config(module, commands) result["changed"] = True result["updates"] = commands module.exit_json(**result)