def render(self, config=None): commands = list() existing_as = None if config: match = re.search(r'router bgp (\d+)', config, re.M) if match: existing_as = match.group(1) operation = self.params['operation'] context = None if self.params['config']: context = 'router bgp %s' % self.get_value('config.bgp_as') if operation == 'delete': if existing_as: commands.append('no router bgp %s' % existing_as) elif context: commands.append('no %s' % context) else: self._validate_input(config) if operation == 'replace': if existing_as and int(existing_as) != self.get_value( 'config.bgp_as'): commands.append('no router bgp %s' % existing_as) config = None elif operation == 'override': if existing_as: commands.append('no router bgp %s' % existing_as) config = None context_commands = list() for key, value in iteritems(self.get_value('config')): if value is not None: meth = getattr(self, '_render_%s' % key, None) if meth: resp = meth(config) if resp: context_commands.extend(to_list(resp)) if context and context_commands: commands.append(context) commands.extend(context_commands) commands.append('exit') return commands
def get_config(module, flags=None): flag_str = ' '.join(to_list(flags)) try: return _DEVICE_CONFIGS[flag_str] except KeyError: connection = get_connection(module) try: out = connection.get_config(flags=flags) except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) cfg = to_text(out, errors='surrogate_then_replace').strip() _DEVICE_CONFIGS[flag_str] = cfg return cfg
def set_config(self, existing_lacp_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ want = self._module.params.get("config") if not want: want = {} have = existing_lacp_facts resp = self.set_state(want, have) return to_list(resp)
def edit_config(self, command): for cmd in chain(['configure terminal'], to_list(command), ['end']): if isinstance(cmd, dict): command = cmd['command'] prompt = cmd['prompt'] answer = cmd['answer'] newline = cmd.get('newline', True) else: command = cmd prompt = None answer = None newline = True self.send_command(command, prompt, answer, False, newline)
def load_config(module, commands): rc, out, err = exec_command(module, 'configure terminal') if rc != 0: module.fail_json(msg='unable to enter configuration mode', err=to_text(out, errors='surrogate_then_replace')) for command in to_list(commands): if command == 'end': continue rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) exec_command(module, 'end')
def wrapper(cls): _provider_lock.acquire() try: if network_os not in _registered_providers: _registered_providers[network_os] = {} for ct in cls.supported_connections: if ct not in _registered_providers[network_os]: _registered_providers[network_os][ct] = {} for item in to_list(module_name): for entry in itervalues(_registered_providers[network_os]): entry[item] = cls finally: _provider_lock.release() return cls
def set_config(self, existing_interfaces_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ want = self._module.params['config'] normalize_interface_name(want, self._module) have = existing_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
def load_config(module, commands): response = {} results = [] requests = [] for line in to_list(commands): requests.append(line) out = run_commands(module, commands=line) results.append("\n".join(out)) reset_config(line) response["results"] = results response["requests"] = requests return response
def render(self, config=None): commands = list() existing_as = None if config: match = re.search(r"router bgp (\d+)", config, re.M) if match: existing_as = match.group(1) operation = self.params["operation"] context = None if self.params["config"]: context = "router bgp %s" % self.get_value("config.bgp_as") if operation == "delete": if existing_as: commands.append("no router bgp %s" % existing_as) elif context: commands.append("no %s" % context) else: self._validate_input(config) if operation == "replace": if existing_as and int(existing_as) != self.get_value( "config.bgp_as"): commands.append("no router bgp %s" % existing_as) config = None elif operation == "override": if existing_as: commands.append("no router bgp %s" % existing_as) config = None context_commands = list() for key, value in iteritems(self.get_value("config")): if value is not None: meth = getattr(self, "_render_%s" % key, None) if meth: resp = meth(config) if resp: context_commands.extend(to_list(resp)) if context and context_commands: commands.append(context) commands.extend(context_commands) commands.append("exit") return commands
def send_requests(self, requests): """Send a list of http requests to remote device and return results """ if requests is None: raise ValueError("'requests' value is required") responses = list() for req in to_list(requests): try: response = self._connection.send_request(**req) except ConnectionError as exc: self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) responses.append(response) return responses
def run_commands(self, commands, check_rc=True): """Runs list of commands on remote device and returns results""" output = None queue = list() responses = list() def run_queue(queue, output, version): try: response = to_list( self._connection.send_request( queue, output=output, version=version ) ) except ConnectionError as exc: if check_rc: raise return to_list(to_text(exc)) if output == "json": response = [json.loads(item) for item in response] return response for item in to_list(commands): cmd_output = "text" if isinstance(item, dict): command = item["command"] if "output" in item: cmd_output = item["output"] if "version" in item: version = item["version"] else: command = item # Emulate '| json' from CLI if is_json(command): command = command.rsplit("|", 1)[0] cmd_output = "json" if output and output != cmd_output: responses.extend(run_queue(queue, output, version)) queue = list() output = cmd_output queue.append(command) if queue: responses.extend(run_queue(queue, output, version)) return responses
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) if not self.is_classic_mode(): raise ValueError( "Nokia SROS node is not running in classic mode. Use ansible_network_os=nokia.sros.md" ) if not commit: raise ValueError( "Changes without commit or in --check mode are not supported by light plugin." ) requests = [] responses = [] try: self.send_command('exit all') for cmd in to_list(candidate): if isinstance(cmd, Mapping): requests.append(cmd['command']) responses.append(self.send_command(**cmd)) else: requests.append(cmd) responses.append(self.send_command(cmd)) except AnsibleConnectionFailure as exc: self.send_command('exit all') raise exc self.send_command('exit all') prompt = self._connection.get_prompt() match = re.search( r'^\*', to_text(prompt, errors='surrogate_or_strict').strip()) if match: return { 'request': requests, 'response': responses, 'diff': match.group(0) } else: return {'request': requests, 'response': responses}
def get_config(self, source="running", flags=None, format=None): if source not in ("running", "startup"): raise ValueError( "fetching configuration from %s is not supported" % source ) if not flags: flags = [] if source == "running": cmd = "show running-config " else: cmd = "show startup-config " cmd += " ".join(to_list(flags)) cmd = cmd.strip() return self.send_command(cmd)
def get_config(self, source='running', flags=None): if source not in ('running', 'startup'): raise ValueError( "fetching configuration from %s is not supported" % source) if source == 'running': cmd = 'show running-config ' else: cmd = 'show startup-config ' if flags: cmd += ' '.join(to_list(flags)) cmd = cmd.strip() return self.send_command(cmd)
def map_config_to_obj(module): out = run_commands(module, ["show user-account | json"]) data = out[0] objects = list() for item in to_list(data["TABLE_template"]["ROW_template"]): objects.append({ "name": item["usr_name"], "configured_password": parse_password(item), "sshkey": item.get("sshkey_info"), "roles": parse_roles(item), "state": "present", }) return objects
def _set_config(self, existing): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the deisred configuration """ config = self._module.params.get("config") want = [] if config: for each in config: want.append(each) have = existing resp = self._set_state(want, have) return to_list(resp)
def set_config(self, existing_acl_interfaces_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the deisred configuration """ want = self._module.params["config"] if want: for item in want: item["name"] = normalize_interface(item["name"]) have = existing_acl_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
def get_startup_config(module, flags=None): reply = run_commands(module, {'command': 'show switch', 'output': 'text'}) match = re.search(r'Config Selected: +(\S+)\.cfg', to_text(reply, errors='surrogate_or_strict').strip(), re.MULTILINE) if match: cfgname = match.group(1).strip() command = ' '.join(['debug cfgmgr show configuration file', cfgname]) if flags: command += ' '.join(to_list(flags)).strip() reply = run_commands(module, {'command': command, 'output': 'text'}) data = reply[0] else: data = '' return data
def map_config_to_obj(module): out = run_commands(module, ['show user-account | json']) data = out[0] objects = list() for item in to_list(data['TABLE_template']['ROW_template']): objects.append({ 'name': item['usr_name'], 'configured_password': parse_password(item), 'sshkey': item.get('sshkey_info'), 'roles': parse_roles(item), 'state': 'present' }) return objects
def set_config(self, existing_l3_interfaces_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ config = self._module.params.get("config") want = [] if config: for each in config: each.update({"name": normalize_interface(each["name"])}) want.append(each) have = existing_l3_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): resp = list() self.check_edit_config_capability(candidate, commit, replace, comment) if replace: candidate = "config replace {0}".format(replace) responses = self._connection.send_request(candidate, output="config") for response in to_list(responses): if response != "{}": resp.append(response) if not resp: resp = [""] return resp
def get_config(self, source='running', format='text', flags=None): options_values = self.get_option_values() if format not in options_values['format']: raise ValueError("'format' value %s is invalid. Valid values are %s" % (format, ','.join(options_values['format']))) lookup = {'running': 'running-config', 'startup': 'startup-config'} if source not in lookup: raise ValueError("fetching configuration from %s is not supported" % source) cmd = 'show %s ' % lookup[source] if format and format != 'text': cmd += '| %s ' % format cmd += ' '.join(to_list(flags)) cmd = cmd.strip() return self.send_command(cmd)
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) if not self.is_classic_mode(): raise ValueError("Nokia SROS node is not running in classic mode. Use ansible_network_os=nokia.sros.md") requests = [] responses = [] try: self.send_command('exit all') self.send_command('admin rollback save') # Save rollback to compare if changes occur. This rollback will be removed upon module completion. for cmd in to_list(candidate): if isinstance(cmd, Mapping): requests.append(cmd['command']) responses.append(self.send_command(**cmd)) else: requests.append(cmd) responses.append(self.send_command(cmd)) except AnsibleConnectionFailure as exc: self.send_command('exit all') self.send_command('admin rollback revert latest-rb') self.send_command('admin rollback delete latest-rb') raise exc self.send_command('exit all') rawdiffs = self.send_command('admin rollback compare') match = re.search(r'\r?\n-+\r?\n(.*)\r?\n-+\r?\n', rawdiffs, re.DOTALL) if match: if commit: pass else: # Special hack! We load the config to running and rollback # to just figure out the delta. this might be risky in # check-mode, because it causes the changes contained to # become temporary active. self.send_command('admin rollback revert latest-rb') # Remove latest rollback to leave rollback history intact. self.send_command('admin rollback delete latest-rb') return {'request': requests, 'response': responses, 'diff': match.group(1)} else: # Remove latest rollback to leave rollback history intact. self.send_command('admin rollback delete latest-rb') return {'request': requests, 'response': responses}
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): resp = {} operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) results = [] requests = [] self.send_command("configure") for cmd in to_list(candidate): if not isinstance(cmd, Mapping): cmd = {"command": cmd} results.append(self.send_command(**cmd)) requests.append(cmd["command"]) out = self.get("compare") out = to_text(out, errors="surrogate_or_strict") diff_config = out if not out.startswith("No changes") else None if diff_config: if commit: try: self.commit(comment) except AnsibleConnectionFailure as e: msg = "commit failed: %s" % e.message self.discard_changes() raise AnsibleConnectionFailure(msg) else: self.send_command("exit") else: self.discard_changes() else: self.send_command("exit") if (to_text(self._connection.get_prompt(), errors="surrogate_or_strict").strip().endswith("#")): self.discard_changes() if diff_config: resp["diff"] = diff_config resp["response"] = results resp["request"] = requests return resp
def edit_config( self, candidate=None, commit=True, admin=False, exclusive=False, replace=None, comment=None, label=None, ): operations = self.get_device_operations() self.check_edit_config_capability( operations, candidate, commit, replace, comment ) resp = {} results = [] requests = [] self.configure(admin=admin, exclusive=exclusive) if replace: candidate = "load {0}".format(replace) for line in to_list(candidate): if not isinstance(line, Mapping): line = {"command": line} cmd = line["command"] results.append(self.send_command(**line)) requests.append(cmd) # Before any commit happend, we can get a real configuration # diff from the device and make it available by the iosxr_config module. # This information can be usefull either in check mode or normal mode. resp["show_commit_config_diff"] = self.get("show commit changes diff") if commit: self.commit(comment=comment, label=label, replace=replace) else: self.discard_changes() self.abort(admin=admin) resp["request"] = requests resp["response"] = results return resp
def set_config(self, existing_hsrp_interfaces_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ config = self._module.params['config'] want = [] if config: for w in config: w.update({'name': normalize_interface(w['name'])}) want.append(w) have = existing_hsrp_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
def get_config(self, source='running', flags=None, format=None): if source not in ('running', 'startup'): raise ValueError("fetching configuration from %s is not supported" % source) if format: raise ValueError("'format' value %s is not supported for get_config" % format) if not flags: flags = [] if source == 'running': cmd = 'show running-config ' cmd += ' '.join(to_list(flags)) cmd = cmd.strip() else: cmd = 'more /intflash/config.cfg' return self.send_command(cmd)
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) resp = {} results = [] requests = [] if replace: candidate = "load override {0}".format(replace) for line in to_list(candidate): if not isinstance(line, Mapping): line = {"command": line} cmd = line["command"] try: results.append(self.send_command(**line)) except AnsibleConnectionFailure as exc: if "error: commit failed" in exc.message: self.discard_changes() raise requests.append(cmd) diff = self.compare_configuration() if diff: resp["diff"] = diff if commit: self.commit(comment=comment) else: self.discard_changes() else: self.send_command("top") self.discard_changes() resp["request"] = requests resp["response"] = results return resp
def render(self, config=None): commands = list() safe_list = list() router_context = "router bgp %s" % self.get_value("config.bgp_as") context_config = None for item in self.get_value("config.neighbors"): context_commands = list() neighbor = item["neighbor"] try: socket.inet_aton(neighbor) context = "neighbor %s" % neighbor except socket.error: context = "neighbor-group %s" % neighbor if config: context_path = [router_context, context] context_config = self.get_config_context( config, context_path, indent=1, ) for key, value in iteritems(item): if value is not None: meth = getattr(self, "_render_%s" % key, None) if meth: resp = meth(item, context_config) if resp: context_commands.extend(to_list(resp)) if context_commands: commands.append(context) commands.extend(context_commands) commands.append("exit") safe_list.append(context) if config and safe_list: commands.extend(self._negate_config(config, safe_list)) return commands
def set_config(self, existing_vlans_facts): """ Collect the configuration from the args passed to the module, collect the current configuration (as a dict from facts) :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ config = self._module.params.get('config') want = [] if config: for w in config: if int(w['vlan_id']) == 1: self._module.fail_json(msg="Vlan 1 is not allowed to be managed by this module") want.append(remove_empties(w)) have = existing_vlans_facts resp = self.set_state(want, have) return to_list(resp)