def send(self, command, prompt=None, answer=None, newline=True, sendonly=False, prompt_retry_check=False, check_all=False): ''' Sends the command to the device in the opened shell ''' if check_all: prompt_len = len(to_list(prompt)) answer_len = len(to_list(answer)) if prompt_len != answer_len: raise AnsibleConnectionFailure( "Number of prompts (%s) is not same as that of answers (%s)" % (prompt_len, answer_len)) try: cmd = b'%s\r' % command self._history.append(cmd) self._ssh_shell.sendall(cmd) self._log_messages('send command: %s' % cmd) if sendonly: return response = self.receive(command, prompt, answer, newline, prompt_retry_check, check_all) return to_text(response, errors='surrogate_then_replace') except (socket.timeout, AttributeError): self.queue_message('error', traceback.format_exc()) raise AnsibleConnectionFailure( "timeout value %s seconds reached while trying to send command: %s" % (self._ssh_shell.gettimeout(), command.strip()))
def run_queue(queue, output): try: response = to_list(self._connection.send_request(queue, output=output)) 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
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 get_config(self, source='running', flags=None, format=None, compare=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 compare is False: return '' else: if source == 'running': cmd = 'show running-config ' else: cmd = 'show configuration ' cmd += ' '.join(to_list(flags)) cmd = cmd.strip() return self.send_command(cmd)
def send_request(self, data, **message_kwargs): output = None queue = list() responses = list() for item in to_list(data): cmd_output = message_kwargs.get('output', 'text') if isinstance(item, dict): command = item['command'] if 'output' in item: cmd_output = item['output'] else: command = item # Emulate '| json' from CLI if command.endswith('| json'): command = command.rsplit('|', 1)[0] cmd_output = 'json' if output and output != cmd_output: responses.extend(self._run_queue(queue, output)) queue = list() output = cmd_output queue.append(command) if queue: responses.extend(self._run_queue(queue, output)) if len(responses) == 1: return responses[0] return responses
def edit_config(self, command): resp = {} results = [] requests = [] self.send_command('configure terminal') for cmd in to_list(command): 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 if cmd != 'end' and cmd[0] != '!': results.append(self.send_command(command, prompt, answer, False, newline)) requests.append(cmd) self.send_command('end') resp['request'] = requests resp['response'] = results return resp
def send_request(self, commands, output='text'): commands = to_list(commands) if self._enable: commands.insert(0, self._enable) body = self._request_builder(commands, output) data = self._module.jsonify(body) headers = {'Content-Type': 'application/json-rpc'} timeout = self._module.params['provider']['timeout'] use_proxy = self._module.params['provider']['use_proxy'] response, headers = fetch_url( self._module, self._url, data=data, headers=headers, method='POST', timeout=timeout, use_proxy=use_proxy ) if headers['status'] != 200: self._module.fail_json(**headers) try: data = response.read() response = self._module.from_json(to_text(data, errors='surrogate_then_replace')) except ValueError: self._module.fail_json(msg='unable to load response from device', data=data) if self._enable and 'result' in response: response['result'].pop(0) return response
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': 'show configuration', 'startup': 'debug cfgmgr show configuration file' } if source not in lookup: raise ValueError( "fetching configuration from %s is not supported" % source) cmd = {'command': lookup[source], 'output': 'text'} if source == 'startup': reply = self.run_commands({ 'command': 'show switch', 'format': 'text' }) data = to_text(reply, errors='surrogate_or_strict').strip() match = re.search(r'Config Selected: +(\S+)\.cfg', data, re.MULTILINE) if match: cmd['command'] += match.group(1) else: # No Startup(/Selected) Config return {} cmd['command'] += ' '.join(to_list(flags)) cmd['command'] = cmd['command'].strip() return self.run_commands(cmd)[0]
def edit_config(self, candidate=None, commit=True, replace=None, diff=False, comment=None): resp = {} operations = self.get_device_operations() self.check_edit_config_capability(operations, candidate, commit, replace, comment) results = [] requests = [] if commit: for line in to_list(candidate): if not isinstance(line, Mapping): line = {'command': line} results.append(self.send_command(**line)) requests.append(line['command']) else: raise ValueError('check mode is not supported') resp['request'] = requests resp['response'] = results return resp
def run_commands(module, commands, check_rc=True): responses = list() connection = get_connection(module) for cmd in to_list(commands): if isinstance(cmd, dict): command = cmd['command'] prompt = cmd['prompt'] answer = cmd['answer'] else: command = cmd prompt = None answer = None try: out = connection.get(command, prompt, answer) except ConnectionError as exc: module.fail_json(msg=to_text(exc)) try: out = to_text(out, errors='surrogate_or_strict') except UnicodeError: module.fail_json(msg=u'Failed to decode output from %s: %s' % (cmd, to_text(out))) responses.append(out) return responses
def send_request(self, data, **message_kwargs): data = to_list(data) become = self._become if become: self.connection.queue_message('vvvv', 'firing event: on_become') data.insert(0, {"cmd": "enable", "input": self._become_pass}) output = message_kwargs.get('output', 'text') request = request_builder(data, output) headers = {'Content-Type': 'application/json-rpc'} response, response_data = self.connection.send('/command-api', request, 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()))) results = handle_response(response_data) if become: results = results[1:] if len(results) == 1: results = results[0] return results
def run_commands(self, commands=None, check_rc=True): if commands is None: raise ValueError("'commands' value is required") responses = list() for cmd in to_list(commands): if not isinstance(cmd, Mapping): cmd = {'command': cmd} output = cmd.pop('output', None) if output: cmd['command'] = self._get_command_with_output(cmd['command'], output) try: out = self.send_command(**cmd) except AnsibleConnectionFailure as e: if check_rc is True: raise out = getattr(e, 'err', e) if out is not None: try: out = to_text(out, errors='surrogate_or_strict').strip() except UnicodeError: raise ConnectionError(message=u'Failed to decode output from %s: %s' % (cmd, to_text(out))) try: out = json.loads(out) except ValueError: pass responses.append(out) return 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 = [] if replace: device_info = self.get_device_info() if '9K' not in device_info.get('network_os_platform', ''): raise ConnectionError(message=u'replace is supported only on Nexus 9K devices') candidate = 'config replace {0}'.format(replace) if commit: 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': 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 edit_config(self, candidate=None, commit=True, replace=False, comment=None): for cmd in chain(['configure'], to_list(candidate)): self.send_command(cmd)
def run_commands(self, commands=None, check_rc=True): if commands is None: raise ValueError("'commands' value is required") responses = list() for cmd in to_list(commands): if not isinstance(cmd, Mapping): cmd = {'command': cmd} output = cmd.pop('output', None) if output: raise ValueError( "'output' value %s is not supported for run_commands" % output) try: out = self.send_command(**cmd) except AnsibleConnectionFailure as e: if check_rc: raise out = getattr(e, 'err', to_text(e)) responses.append(out) return responses
def edit_config(self, candidate=None, commit=True, replace=None, comment=None): resp = {} results = [] requests = [] if commit: 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 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=2): 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 to_request(module, requests): transform = ComplexList( dict( path=dict(key=True), method=dict(), data=dict(type='dict'), ), module) return transform(to_list(requests))
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 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_then_replace'), rc=rc) responses.append(to_text(out, errors='surrogate_then_replace')) return responses
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 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 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 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) 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 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 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 # cmd = {'command': command, 'prompt': WARNING_PROMPTS_RE, 'answer': 'yes'} 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 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