fix for handling commands that return no data or error (#22086)

This patch addresses a problem in nxos_facts where certain commands are
not supported or return no data, the module would raise an exception.
With this patch, the nxos_facts module will now print a warning for any
commands that return no data and not populate the facts.

fixes #22001
pull/22213/head
Peter Sprygada 8 years ago committed by GitHub
parent d66ce40ecb
commit 8d76703a9d

@ -255,13 +255,16 @@ class Nxapi:
except ValueError: except ValueError:
self._module.fail_json(msg='unable to parse response') self._module.fail_json(msg='unable to parse response')
if check_status: output = response['ins_api']['outputs']['output']
output = response['ins_api']['outputs']['output'] for item in to_list(output):
for item in to_list(output): if check_status and item['code'] != '200':
if item['code'] != '200': self._error(output=output, **item)
self._error(output=output, **item) elif 'body' in item:
else: result.append(item['body'])
result.append(item['body']) #else:
# error in command but since check_status is disabled
# silently drop it.
#result.append(item['msg'])
return result return result

@ -180,7 +180,7 @@ vlan_list:
""" """
import re import re
from ansible.module_utils.nxos import run_commands from ansible.module_utils.nxos import run_commands, get_config
from ansible.module_utils.nxos import nxos_argument_spec, check_args from ansible.module_utils.nxos import nxos_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
@ -188,15 +188,24 @@ from ansible.module_utils.six import iteritems
class FactsBase(object): class FactsBase(object):
COMMANDS = frozenset()
def __init__(self, module): def __init__(self, module):
self.module = module self.module = module
self.warnings = list()
self.facts = dict() self.facts = dict()
self.responses = None
def populate(self): def populate(self):
self.responses = run_commands(self.module, list(self.COMMANDS)) pass
def run(self, command, output=None):
command_string = command
if output:
command = {'command': command, 'output': output}
resp = run_commands(self.module, command, check_rc=False)
try:
return resp[0]
except IndexError:
self.warnings.append('command %s returned to data, facts will not be populated' % command_string)
return None
def transform_dict(self, data, keymap): def transform_dict(self, data, keymap):
transform = dict() transform = dict()
@ -210,6 +219,7 @@ class FactsBase(object):
yield self.transform_dict(item, keymap) yield self.transform_dict(item, keymap)
class Default(FactsBase): class Default(FactsBase):
VERSION_MAP = frozenset([ VERSION_MAP = frozenset([
@ -220,38 +230,30 @@ class Default(FactsBase):
('host_name', 'hostname') ('host_name', 'hostname')
]) ])
COMMANDS = ['show version | json']
def populate(self): def populate(self):
super(Default, self).populate() data = self.run('show version', 'json')
data = self.responses[0] if data:
self.facts.update(self.transform_dict(data, self.VERSION_MAP)) self.facts.update(self.transform_dict(data, self.VERSION_MAP))
class Config(FactsBase): class Config(FactsBase):
COMMANDS = ['show running-config']
def populate(self): def populate(self):
super(Config, self).populate() super(Config, self).populate()
data = self.responses[0] self.facts['config'] = get_config(self.module)
self.facts['config'] = data
class Hardware(FactsBase): class Hardware(FactsBase):
COMMANDS = [
{'command': 'dir', 'output': 'text'},
'show system resources | json'
]
def populate(self): def populate(self):
super(Hardware, self).populate() cmd = {'command': 'dir', 'output': 'text'},
data = self.responses[0] data = self.run('dir', 'text')
self.facts['filesystems'] = self.parse_filesystems(data) if data:
self.facts['filesystems'] = self.parse_filesystems(data)
data = self.responses[1] data = self.run('show system resources', 'json')
self.facts['memtotal_mb'] = int(data['memory_usage_total']) / 1024 if data:
self.facts['memfree_mb'] = int(data['memory_usage_free']) / 1024 self.facts['memtotal_mb'] = int(data['memory_usage_total']) / 1024
self.facts['memfree_mb'] = int(data['memory_usage_free']) / 1024
def parse_filesystems(self, data): def parse_filesystems(self, data):
return re.findall(r'^Usage for (\S+)//', data, re.M) return re.findall(r'^Usage for (\S+)//', data, re.M)
@ -285,15 +287,16 @@ class Interfaces(FactsBase):
self.facts['all_ipv4_addresses'] = list() self.facts['all_ipv4_addresses'] = list()
self.facts['all_ipv6_addresses'] = list() self.facts['all_ipv6_addresses'] = list()
data = run_commands(self.module, ['show interface | json'])[0] data = self.run('show interface', 'json')
self.facts['interfaces'] = self.populate_interfaces(data) if data:
self.facts['interfaces'] = self.populate_interfaces(data)
out = run_commands(self.module, ['show ipv6 interface | json']) data = self.run('show ipv6 inteface', 'json')
if out[0]: if data:
self.parse_ipv6_interfaces(out) self.parse_ipv6_interfaces(out)
out = run_commands(self.module, ['show lldp neighbors'], check_rc=False) data = self.run('show lldp neighbors')
if out and out[0]: if data:
self.facts['neighbors'] = self.populate_neighbors(out) self.facts['neighbors'] = self.populate_neighbors(out)
def populate_interfaces(self, data): def populate_interfaces(self, data):
@ -371,32 +374,27 @@ class Legacy(FactsBase):
('total_capa', 'total_capacity') ('total_capa', 'total_capacity')
]) ])
COMMANDS = [
'show version | json',
'show module | json',
'show environment | json',
'show interface | json',
'show vlan brief | json'
]
def populate(self): def populate(self):
super(Legacy, self).populate() data = self.run('show version', 'json')
data = self.responses[0] if data:
self.facts.update(self.transform_dict(data, self.VERSION_MAP)) self.facts.update(self.transform_dict(data, self.VERSION_MAP))
data = self.responses[3] data = self.run('show interface', 'json')
self.facts['_interfaces_list'] = self.parse_interfaces(data) if data:
self.facts['_interfaces_list'] = self.parse_interfaces(data)
data = self.responses[4] data = self.run('show vlan brief', 'json')
self.facts['_vlan_list'] = self.parse_vlans(data) if data:
self.facts['_vlan_list'] = self.parse_vlans(data)
data = self.responses[1] data = self.run('show module', 'json')
self.facts['_module'] = self.parse_module(data) if data:
self.facts['_module'] = self.parse_module(data)
data = self.responses[2] data = self.run('show environment', 'json')
self.facts['_fan_info'] = self.parse_fan_info(data) if data:
self.facts['_power_supply_info'] = self.parse_power_supply_info(data) self.facts['_fan_info'] = self.parse_fan_info(data)
self.facts['_power_supply_info'] = self.parse_power_supply_info(data)
def parse_interfaces(self, data): def parse_interfaces(self, data):
objects = list() objects = list()
@ -497,6 +495,7 @@ def main():
for inst in instances: for inst in instances:
inst.populate() inst.populate()
facts.update(inst.facts) facts.update(inst.facts)
warnings.extend(inst.warnings)
ansible_facts = dict() ansible_facts = dict()
for key, value in iteritems(facts): for key, value in iteritems(facts):

Loading…
Cancel
Save