diff options
author | Peter Sprygada <privateip@users.noreply.github.com> | 2016-11-03 21:41:17 -0400 |
---|---|---|
committer | Peter Sprygada <psprygada@ansible.com> | 2016-11-03 21:42:42 -0400 |
commit | 203fcad34723388f6610cbd7f1ac1986a5108d81 (patch) | |
tree | b1ab7255e5966ef15193520d865ac7795a87a3e8 | |
parent | 64314c8e98475d6c954a8c12a46be13735231572 (diff) | |
download | ansible-modules-core-203fcad34723388f6610cbd7f1ac1986a5108d81.tar.gz |
ios_facts module will no longer error on missing command (#5491)
The module will error if it tries to use a cli command that is not available
on a given platform. This fix will address that problem. If the cli
command is not available, then the command is silently discarded and the
facts that the command output is based on is not returned. Any failed
commands are provided in the module return under the failed_commands
key. This fix also updates the Examples docstring to make it consistent
with other ios_* modules
fixes #5444
fixes #5372
(cherry picked from commit be846c0995c1052929977ef2fd92b78e4852bad1)
-rw-r--r-- | network/ios/ios_facts.py | 116 |
1 files changed, 56 insertions, 60 deletions
diff --git a/network/ios/ios_facts.py b/network/ios/ios_facts.py index 503d394b..c030e78a 100644 --- a/network/ios/ios_facts.py +++ b/network/ios/ios_facts.py @@ -42,19 +42,31 @@ options: """ EXAMPLES = """ +# Note: examples below use the following provider dict to handle +# transport and authentication to the node. +vars: + cli: + host: "{{ inventory_hostname }}" + username: cisco + password: cisco + transport: cli + # Collect all facts from the device - ios_facts: gather_subset: all + provider: "{{ cli }}" # Collect only the config and default facts - ios_facts: gather_subset: - config + provider: "{{ cli }}" # Do not collect hardware facts - ios_facts: gather_subset: - "!hardware" + provider: "{{ cli }}" """ RETURN = """ @@ -127,44 +139,35 @@ import re import itertools import ansible.module_utils.ios -from ansible.module_utils.netcli import CommandRunner, AddCommandError from ansible.module_utils.network import NetworkModule from ansible.module_utils.six import iteritems from ansible.module_utils.six.moves import zip -def add_command(runner, command): - try: - runner.add_command(command) - except AddCommandError: - # AddCommandError is raised for any issue adding a command to - # the runner. Silently ignore the exception in this case - pass - class FactsBase(object): - def __init__(self, runner): - self.runner = runner + def __init__(self, module): + self.module = module self.facts = dict() + self.failed_commands = list() - self.commands() + def run(self, cmd): + try: + return self.module.cli(cmd)[0] + except: + self.failed_commands.append(cmd) - def commands(self): - raise NotImplementedError class Default(FactsBase): - def commands(self): - add_command(self.runner, 'show version') - def populate(self): - data = self.runner.get_command('show version') - - self.facts['version'] = self.parse_version(data) - self.facts['serialnum'] = self.parse_serialnum(data) - self.facts['model'] = self.parse_model(data) - self.facts['image'] = self.parse_image(data) - self.facts['hostname'] = self.parse_hostname(data) + data = self.run('show version') + if data: + self.facts['version'] = self.parse_version(data) + self.facts['serialnum'] = self.parse_serialnum(data) + self.facts['model'] = self.parse_model(data) + self.facts['image'] = self.parse_image(data) + self.facts['hostname'] = self.parse_hostname(data) def parse_version(self, data): match = re.search(r'Version (\S+),', data) @@ -194,20 +197,17 @@ class Default(FactsBase): class Hardware(FactsBase): - def commands(self): - add_command(self.runner, 'dir | include Directory') - add_command(self.runner, 'show version') - add_command(self.runner, 'show memory statistics | include Processor') - def populate(self): - data = self.runner.get_command('dir | include Directory') - self.facts['filesystems'] = self.parse_filesystems(data) + data = self.run('dir | include Directory') + if data: + self.facts['filesystems'] = self.parse_filesystems(data) - data = self.runner.get_command('show memory statistics | include Processor') - match = re.findall(r'\s(\d+)\s', data) - if match: - self.facts['memtotal_mb'] = int(match[0]) / 1024 - self.facts['memfree_mb'] = int(match[1]) / 1024 + data = self.run('show memory statistics | include Processor') + if data: + match = re.findall(r'\s(\d+)\s', data) + if match: + self.facts['memtotal_mb'] = int(match[0]) / 1024 + self.facts['memfree_mb'] = int(match[1]) / 1024 def parse_filesystems(self, data): return re.findall(r'^Directory of (\S+)/', data, re.M) @@ -215,37 +215,33 @@ class Hardware(FactsBase): class Config(FactsBase): - def commands(self): - add_command(self.runner, 'show running-config') - def populate(self): - self.facts['config'] = self.runner.get_command('show running-config') + data = self.run('show running-config') + if data: + self.facts['config'] = data class Interfaces(FactsBase): - def commands(self): - add_command(self.runner, 'show interfaces') - add_command(self.runner, 'show ipv6 interface') - add_command(self.runner, 'show lldp') - add_command(self.runner, 'show lldp neighbors detail') - def populate(self): self.facts['all_ipv4_addresses'] = list() self.facts['all_ipv6_addresses'] = list() - data = self.runner.get_command('show interfaces') - interfaces = self.parse_interfaces(data) - self.facts['interfaces'] = self.populate_interfaces(interfaces) + data = self.run('show interfaces') + if data: + interfaces = self.parse_interfaces(data) + self.facts['interfaces'] = self.populate_interfaces(interfaces) - data = self.runner.get_command('show ipv6 interface') - if len(data) > 0: + data = self.run('show ipv6 interface') + if data: data = self.parse_interfaces(data) self.populate_ipv6_interfaces(data) - if 'LLDP is not enabled' not in self.runner.get_command('show lldp'): - neighbors = self.runner.get_command('show lldp neighbors detail') - self.facts['neighbors'] = self.parse_neighbors(neighbors) + data = self.run('show lldp') + if 'LLDP is not enabled' not in data: + neighbors = self.run('show lldp neighbors detail') + if neighbors: + self.facts['neighbors'] = self.parse_neighbors(neighbors) def populate_interfaces(self, interfaces): facts = dict() @@ -434,27 +430,27 @@ def main(): facts = dict() facts['gather_subset'] = list(runable_subsets) - runner = CommandRunner(module) - instances = list() for key in runable_subsets: - instances.append(FACT_SUBSETS[key](runner)) + instances.append(FACT_SUBSETS[key](module)) - runner.run() + failed_commands = list() try: for inst in instances: inst.populate() + failed_commands.extend(inst.failed_commands) facts.update(inst.facts) except Exception: - module.exit_json(out=module.from_json(runner.items)) + exc = get_exception() + module.fail_json(msg=str(exc)) ansible_facts = dict() for key, value in iteritems(facts): key = 'ansible_net_%s' % key ansible_facts[key] = value - module.exit_json(ansible_facts=ansible_facts) + module.exit_json(ansible_facts=ansible_facts, failed_commands=failed_commands) if __name__ == '__main__': |