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 = [] if commit: prompt = self._connection.get_prompt() if (b'(config-if' in prompt) or (b'(config' in prompt) or (b'(config-lag-if' in prompt): self.send_command('end') self.send_command('configure terminal') for line in to_list(candidate): if not isinstance(line, Mapping): line = {'command': line} cmd = line['command'] if cmd != 'end' and cmd[0] != '!': results.append(self.send_command(**line)) requests.append(cmd) self.send_command('end') else: raise ValueError('check mode is not supported') resp['request'] = requests resp['response'] = results return resp
def render(self, config=None, nbr_list=None): commands = list() safe_list = list() if not nbr_list: nbr_list = self.get_value('config.neighbors') for item in nbr_list: neighbor_commands = list() context = 'neighbor %s' % item['neighbor'] cmd = '%s remote-as %s' % (context, item['remote_as']) if not config or cmd not in config: neighbor_commands.append(cmd) for key, value in iteritems(item): if value is not None: meth = getattr(self, '_render_%s' % key, None) if meth: resp = meth(item, config) if resp: neighbor_commands.extend(to_list(resp)) commands.extend(neighbor_commands) safe_list.append(context) if self.params['operation'] == 'replace': if config and safe_list: commands.extend(self._negate_config(config, safe_list)) return commands
def execute_module(self): """ Execute the module :rtype: A dictionary :returns: The result from module execution """ result = {'changed': False} warnings = list() existing_lag_interfaces_facts = self.get_lag_interfaces_facts() config_xmls = self.set_config(existing_lag_interfaces_facts) with locked_config(self._module): for config_xml in to_list(config_xmls): diff = load_config(self._module, config_xml, warnings) commit = not self._module.check_mode if diff: if commit: commit_configuration(self._module) else: discard_changes(self._module) result['changed'] = True if self._module._diff: result['diff'] = {'prepared': diff} result['commands'] = config_xmls changed_lag_interfaces_facts = self.get_lag_interfaces_facts() result['before'] = existing_lag_interfaces_facts if result['changed']: result['after'] = changed_lag_interfaces_facts return result
def get_section(self, config, section): if config is not None: netcfg = NetworkConfig(indent=1, contents=config) try: config = netcfg.get_block_config(to_list(section)) except ValueError: config = None return config
def get_config_context(self, config, path, indent=1): if config is not None: netcfg = NetworkConfig(indent=indent, contents=config) try: config = netcfg.get_block_config(to_list(path)) except ValueError: config = None return config
def load_config(module, commands): for command in to_list(commands): rc, out, err = exec_command(module, command) if rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), command=command, rc=rc) exec_command(module, 'exit all')
def execute_show_commands(module, commands, output='text'): cmds = [] for command in to_list(commands): cmd = {'command': command, 'output': output, } cmds.append(cmd) body = run_commands(module, cmds) return body
def run_commands(self, commands, check_rc=True): if commands is None: raise ValueError("'commands' value is required") headers = {'Content-Type': 'application/json'} responses = list() for cmd in to_list(commands): if not isinstance(cmd, Mapping): cmd = {'command': cmd} cmd['command'] = strip_run_script_cli2json(cmd['command']) output = cmd.pop('output', None) if output and output not in self.get_option_values().get('output'): raise ValueError( "'output' value is %s is invalid. Valid values are %s" % (output, ','.join(self.get_option_values().get('output')))) data = request_builder(cmd['command']) response, response_data = self.connection.send( '/jsonrpc', data, cookies=self._auth_token, headers=headers, method='POST') try: response_data = json.loads(to_text(response_data.getvalue())) except ValueError: raise ConnectionError( 'Response was not valid JSON, got {0}'.format( to_text(response_data.getvalue()))) if response_data.get('error', None): raise ConnectionError("Request Error, got {0}".format( response_data['error'])) if not response_data.get('result', None): raise ConnectionError( "Request Error, got {0}".format(response_data)) response_data = response_data['result'] if output and output == 'text': statusOut = getKeyInResponse(response_data, 'status') cliOut = getKeyInResponse(response_data, 'CLIoutput') if statusOut == "ERROR": raise ConnectionError( "Command error({1}) for request {0}".format( cmd['command'], cliOut)) if cliOut is None: raise ValueError( "Response for request {0} doesn't have the CLIoutput field, got {1}" .format(cmd['command'], response_data)) response_data = cliOut responses.append(response_data) return responses
def load_config(module, config, commit=False): conn = get_connection(module) try: resp = conn.edit_config(to_list(config) + ['top'], commit) except ConnectionError as exc: module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) diff = resp.get('diff', '') return to_text(diff, errors='surrogate_then_replace').strip()
def to_command(module, commands): transform = ComplexList(dict( command=dict(key=True), output=dict(default='text'), prompt=dict(type='list'), answer=dict(type='list'), sendonly=dict(type='bool', default=False), check_all=dict(type='bool', default=False), ), module) return transform(to_list(commands))
def parse_roles(data): configured_roles = None if 'TABLE_role' in data: configured_roles = data.get('TABLE_role')['ROW_role'] roles = list() if configured_roles: for item in to_list(configured_roles): roles.append(item['role']) return roles
def to_command(module, commands): default_output = 'text' transform = ComplexList( dict(command=dict(key=True), output=dict(default=default_output), prompt=dict(), answer=dict()), module) commands = transform(to_list(commands)) return commands
def run_commands(module, commands, check_rc=True): responses = list() commands = to_commands(module, to_list(commands)) for cmd in commands: cmd = module.jsonify(cmd) rc, out, err = exec_command(module, cmd) if check_rc and rc != 0: module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc) responses.append(to_text(out, errors='surrogate_or_strict')) return responses
def run_commands(module, commands, check_rc=True): responses = list() commands = to_commands(module, to_list(commands)) for cmd in commands: cmd = module.jsonify(cmd) rc, out, err = exec_command(module, cmd) if check_rc and rc != 0: raise F5ModuleError(to_text(err, errors='surrogate_then_replace')) result = to_text(out, errors='surrogate_then_replace') responses.append(result) return responses
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: if operation == 'replace': if existing_as and int(existing_as) != self.get_value( 'config.bgp_as'): # The negate command has to be committed before new BGP AS is used. self.connection.edit_config('no router bgp %s' % existing_as) config = None elif operation == 'override': if existing_as: # The negate command has to be committed before new BGP AS is used. self.connection.edit_config('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 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 """ want = self._module.params['config'] have = existing_l3_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
def get_config(self, source='running', format='text', flags=None): if source not in ['running']: raise ValueError( "fetching configuration from %s is not supported" % source) lookup = {'running': 'running-config'} cmd = 'show {0} '.format(lookup[source]) cmd += ' '.join(to_list(flags)) cmd = cmd.strip() return self.send_command(cmd)
def run_commands(module, commands, check_rc=True): connection = get_connection(module) connection.get('enable') commands = to_commands(module, to_list(commands)) responses = list() for cmd in commands: out = connection.get(**cmd) responses.append(to_text(out, errors='surrogate_then_replace')) return responses
def set_config(self, existing_tms_global_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 = dict((k, v) for k, v in config.items() if v is not None) have = existing_tms_global_facts resp = self.set_state(want, have) return to_list(resp)
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(err, errors='surrogate_or_strict')) 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_or_strict'), command=command, rc=rc) exec_command(module, 'end')
def get_config(module, flags=None, compare=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, compare=compare) 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 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 set_config(self, existing_lldp_global_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'] if not want and self._module.params['state'] == 'deleted': want = {} have = existing_lldp_global_facts resp = self.set_state(want, have) return to_list(resp)
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 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 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 edit_config(self, command): results = [] 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 results.append(self.send_command(command, prompt, answer, False, newline)) return results[1:-1]
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 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)