def test_to_list(): for scalar in ('string', 1, True, False, None): assert isinstance(to_list(scalar), list) for container in ([1, 2, 3], {'one': 1}): assert isinstance(to_list(container), list) test_list = [1, 2, 3] assert id(test_list) != id(to_list(test_list))
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): 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.address_family'): context = 'address-family %s %s' % (item['afi'], item['safi']) context_commands = list() 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: resp = self._negate_config(config, safe_list) commands.extend(resp) return commands
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 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 execute_show_commands(self, commands): body = [] uri = "https://{0}:{1}/mgmt/tm/util/bash".format( self.client.provider['server'], self.client.provider['server_port'] ) for command in to_list(commands): command = 'imish -r {0} -e \\\"{1}\\\"'.format(self.want.route_domain, command) params = { "command": "run", "utilCmdArgs": '-c "{0}"'.format(command) } resp = self.client.api.post(uri, json=params) try: response = resp.json() if 'commandResult' in response: if 'Dynamic routing is not enabled' in response['commandResult']: raise F5ModuleError(response['commandResult']) except ValueError as ex: raise F5ModuleError(str(ex)) if 'code' in response and response['code'] in [400, 403]: if 'message' in response: raise F5ModuleError(response['message']) else: raise F5ModuleError(resp.content) body.append(response['commandResult']) return body
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 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: 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 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 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, errors='surrogate_then_replace')) 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: 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', e) responses.append(out) return responses
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: raise out = getattr(e, 'err', e) out = to_text(out, errors='surrogate_or_strict') if out is not None: try: out = json.loads(out) except ValueError: out = out.strip() responses.append(out) return responses
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 set_config(self, existing_bfd_interfaces_facts, platform): """ 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 """ if re.search('N[56]K', platform): # Some platforms do not support the 'bfd' interface keyword; # remove the 'bfd' key from each want/have interface. orig_want = self._module.params['config'] want = [] for w in orig_want: del w['bfd'] want.append(w) orig_have = existing_bfd_interfaces_facts have = [] for h in orig_have: del h['bfd'] have.append(h) else: want = self._module.params['config'] have = existing_bfd_interfaces_facts resp = self.set_state(want, have) return to_list(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': '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 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} existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts() config_xmls = self.set_config(existing_lacp_interfaces_facts) with locked_config(self._module): for config_xml in to_list(config_xmls): diff = load_config(self._module, config_xml, []) 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_lacp_interfaces_facts = self.get_lacp_interfaces_facts() result['before'] = existing_lacp_interfaces_facts if result['changed']: result['after'] = changed_lacp_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 to_request(module, requests): transform = ComplexList( dict( path=dict(key=True), method=dict(), data=dict(type='dict'), ), module) return transform(to_list(requests))
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 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 run_commands(module, commands, check_rc=True): 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 = (to_text(out, errors='surrogate_or_strict')) return rc, out, err
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 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 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 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 set_config(self, existing_lacp_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_lacp_interfaces_facts resp = self.set_state(want, have) return to_list(resp)
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