Add platform facts in network facts modules (#51434)
* Add platform facts in network facts modules Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add nxos Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add vyos Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add iosxr Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * Add junos Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix pep8 Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * update unit test Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix vyos_facts unittest Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix ios_facts unittest Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix iosxr unittests Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix CI failure Signed-off-by: Trishna Guha <trishnaguha17@gmail.com> * fix junos test Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
This commit is contained in:
parent
5cd7bf39dd
commit
a41028244d
16 changed files with 303 additions and 180 deletions
|
@ -185,6 +185,20 @@ class Cli:
|
|||
self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
|
||||
return diff
|
||||
|
||||
def get_capabilities(self):
|
||||
"""Returns platform info of the remove device
|
||||
"""
|
||||
if hasattr(self._module, '_capabilities'):
|
||||
return self._module._capabilities
|
||||
|
||||
connection = self._get_connection()
|
||||
try:
|
||||
capabilities = connection.get_capabilities()
|
||||
except ConnectionError as exc:
|
||||
self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
|
||||
self._module._capabilities = json.loads(capabilities)
|
||||
return self._module._capabilities
|
||||
|
||||
|
||||
class LocalEapi:
|
||||
|
||||
|
@ -617,3 +631,8 @@ def load_config(module, config, commit=False, replace=False):
|
|||
def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
|
||||
conn = self.get_connection()
|
||||
return conn.get_diff(candidate=candidate, running=running, diff_match=diff_match, diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=diff_replace)
|
||||
|
||||
|
||||
def get_capabilities(module):
|
||||
conn = get_connection(module)
|
||||
return conn.get_capabilities()
|
||||
|
|
|
@ -145,7 +145,7 @@ def get_connection(module):
|
|||
if hasattr(module, 'connection'):
|
||||
return module.connection
|
||||
|
||||
capabilities = get_device_capabilities(module)
|
||||
capabilities = get_capabilities(module)
|
||||
network_api = capabilities.get('network_api')
|
||||
if network_api == 'cliconf':
|
||||
module.connection = Connection(module._socket_path)
|
||||
|
@ -157,7 +157,7 @@ def get_connection(module):
|
|||
return module.connection
|
||||
|
||||
|
||||
def get_device_capabilities(module):
|
||||
def get_capabilities(module):
|
||||
if hasattr(module, 'capabilities'):
|
||||
return module.capabilities
|
||||
try:
|
||||
|
@ -317,12 +317,12 @@ def etree_findall(root, node):
|
|||
|
||||
|
||||
def is_cliconf(module):
|
||||
capabilities = get_device_capabilities(module)
|
||||
capabilities = get_capabilities(module)
|
||||
return (capabilities.get('network_api') == 'cliconf')
|
||||
|
||||
|
||||
def is_netconf(module):
|
||||
capabilities = get_device_capabilities(module)
|
||||
capabilities = get_capabilities(module)
|
||||
network_api = capabilities.get('network_api')
|
||||
if network_api == 'netconf':
|
||||
if not HAS_NCCLIENT:
|
||||
|
|
|
@ -96,6 +96,14 @@ ansible_net_fqdn:
|
|||
description: The fully qualified domain name of the device
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_api:
|
||||
description: The name of the transport
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_python_version:
|
||||
description: The Python version Ansible controller is using
|
||||
returned: always
|
||||
type: str
|
||||
|
||||
# hardware
|
||||
ansible_net_filesystems:
|
||||
|
@ -135,11 +143,13 @@ ansible_net_neighbors:
|
|||
returned: when interfaces is configured
|
||||
type: dict
|
||||
"""
|
||||
|
||||
import platform
|
||||
import re
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.six import iteritems
|
||||
from ansible.module_utils.network.eos.eos import run_commands
|
||||
from ansible.module_utils.network.eos.eos import run_commands, get_capabilities
|
||||
from ansible.module_utils.network.eos.eos import eos_argument_spec, check_args
|
||||
|
||||
|
||||
|
@ -159,15 +169,12 @@ class FactsBase(object):
|
|||
class Default(FactsBase):
|
||||
|
||||
SYSTEM_MAP = {
|
||||
'version': 'version',
|
||||
'serialNumber': 'serialnum',
|
||||
'modelName': 'model'
|
||||
}
|
||||
|
||||
COMMANDS = [
|
||||
'show version | json',
|
||||
'show hostname | json',
|
||||
'bash timeout 5 cat /mnt/flash/boot-config'
|
||||
]
|
||||
|
||||
def populate(self):
|
||||
|
@ -178,18 +185,25 @@ class Default(FactsBase):
|
|||
self.facts[value] = data[key]
|
||||
|
||||
self.facts.update(self.responses[1])
|
||||
self.facts.update(self.parse_image())
|
||||
self.facts.update(self.platform_facts())
|
||||
|
||||
def parse_image(self):
|
||||
data = self.responses[2]
|
||||
if isinstance(data, dict):
|
||||
data = data['messages'][0]
|
||||
match = re.search(r'SWI=(.+)$', data, re.M)
|
||||
if match:
|
||||
value = match.group(1)
|
||||
else:
|
||||
value = None
|
||||
return dict(image=value)
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
resp = get_capabilities(self.module)
|
||||
device_info = resp['device_info']
|
||||
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
|
||||
class Hardware(FactsBase):
|
||||
|
|
|
@ -103,6 +103,14 @@ ansible_net_stacked_serialnums:
|
|||
description: The serial numbers of each device in the stack
|
||||
returned: when multiple devices are configured in a stack
|
||||
type: list
|
||||
ansible_net_api:
|
||||
description: The name of the transport
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_python_version:
|
||||
description: The Python version Ansible controller is using
|
||||
returned: always
|
||||
type: str
|
||||
|
||||
# hardware
|
||||
ansible_net_filesystems:
|
||||
|
@ -148,9 +156,10 @@ ansible_net_neighbors:
|
|||
returned: when interfaces is configured
|
||||
type: dict
|
||||
"""
|
||||
import platform
|
||||
import re
|
||||
|
||||
from ansible.module_utils.network.ios.ios import run_commands
|
||||
from ansible.module_utils.network.ios.ios import run_commands, get_capabilities
|
||||
from ansible.module_utils.network.ios.ios import ios_argument_spec, check_args
|
||||
from ansible.module_utils.network.ios.ios import normalize_interface
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
@ -180,21 +189,13 @@ class Default(FactsBase):
|
|||
|
||||
def populate(self):
|
||||
super(Default, self).populate()
|
||||
self.facts.update(self.platform_facts())
|
||||
data = self.responses[0]
|
||||
if data:
|
||||
self.facts['version'] = self.parse_version(data)
|
||||
self.facts['iostype'] = self.parse_iostype(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)
|
||||
self.parse_stacks(data)
|
||||
|
||||
def parse_version(self, data):
|
||||
match = re.search(r'Version (\S+?)(?:,\s|\s)', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_iostype(self, data):
|
||||
match = re.search(r'\S+(X86_64_LINUX_IOSD-UNIVERSALK9-M)(\S+)', data)
|
||||
if match:
|
||||
|
@ -202,21 +203,6 @@ class Default(FactsBase):
|
|||
else:
|
||||
return "IOS"
|
||||
|
||||
def parse_hostname(self, data):
|
||||
match = re.search(r'^(.+) uptime', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_model(self, data):
|
||||
match = re.search(r'^[Cc]isco (\S+).+bytes of .*memory', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_image(self, data):
|
||||
match = re.search(r'image file is "(.+)"', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_serialnum(self, data):
|
||||
match = re.search(r'board ID (\S+)', data)
|
||||
if match:
|
||||
|
@ -231,6 +217,24 @@ class Default(FactsBase):
|
|||
if match:
|
||||
self.facts['stacked_serialnums'] = match
|
||||
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
resp = get_capabilities(self.module)
|
||||
device_info = resp['device_info']
|
||||
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
|
||||
class Hardware(FactsBase):
|
||||
|
||||
|
|
|
@ -76,6 +76,14 @@ ansible_net_image:
|
|||
description: The image file the device is running
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_api:
|
||||
description: The name of the transport
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_python_version:
|
||||
description: The Python version Ansible controller is using
|
||||
returned: always
|
||||
type: str
|
||||
|
||||
# hardware
|
||||
ansible_net_filesystems:
|
||||
|
@ -115,61 +123,67 @@ ansible_net_neighbors:
|
|||
returned: when interfaces is configured
|
||||
type: dict
|
||||
"""
|
||||
|
||||
import platform
|
||||
import re
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.network.iosxr.iosxr import iosxr_argument_spec, run_commands
|
||||
from ansible.module_utils.network.iosxr.iosxr import iosxr_argument_spec, run_commands, get_capabilities
|
||||
from ansible.module_utils.six import iteritems
|
||||
from ansible.module_utils.six.moves import zip
|
||||
|
||||
|
||||
class FactsBase(object):
|
||||
|
||||
def __init__(self):
|
||||
self.facts = dict()
|
||||
self.commands()
|
||||
COMMANDS = frozenset()
|
||||
|
||||
def commands(self):
|
||||
raise NotImplementedError
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
self.facts = dict()
|
||||
self.responses = None
|
||||
|
||||
def populate(self):
|
||||
self.responses = run_commands(self.module, list(self.COMMANDS), check_rc=False)
|
||||
|
||||
|
||||
class Default(FactsBase):
|
||||
|
||||
def commands(self):
|
||||
return(['show version | utility head -n 20'])
|
||||
def populate(self):
|
||||
self.facts.update(self.platform_facts())
|
||||
|
||||
def populate(self, results):
|
||||
self.facts['version'] = self.parse_version(results['show version | utility head -n 20'])
|
||||
self.facts['image'] = self.parse_image(results['show version | utility head -n 20'])
|
||||
self.facts['hostname'] = self.parse_hostname(results['show version | utility head -n 20'])
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
def parse_version(self, data):
|
||||
match = re.search(r'Version (\S+)$', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
resp = get_capabilities(self.module)
|
||||
device_info = resp['device_info']
|
||||
|
||||
def parse_hostname(self, data):
|
||||
match = re.search(r'^(.+) uptime', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
def parse_image(self, data):
|
||||
match = re.search(r'image file is "(.+)"', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
|
||||
class Hardware(FactsBase):
|
||||
|
||||
def commands(self):
|
||||
return(['dir /all', 'show memory summary'])
|
||||
COMMANDS = [
|
||||
'dir /all',
|
||||
'show memory summary'
|
||||
]
|
||||
|
||||
def populate(self, results):
|
||||
self.facts['filesystems'] = self.parse_filesystems(
|
||||
results['dir /all'])
|
||||
def populate(self):
|
||||
super(Hardware, self).populate()
|
||||
data = self.responses[0]
|
||||
self.facts['filesystems'] = self.parse_filesystems(data)
|
||||
|
||||
match = re.search(r'Physical Memory: (\d+)M total \((\d+)',
|
||||
results['show memory summary'])
|
||||
data = self.responses[1]
|
||||
match = re.search(r'Physical Memory: (\d+)M total \((\d+)', data)
|
||||
if match:
|
||||
self.facts['memtotal_mb'] = match.group(1)
|
||||
self.facts['memfree_mb'] = match.group(2)
|
||||
|
@ -180,33 +194,39 @@ class Hardware(FactsBase):
|
|||
|
||||
class Config(FactsBase):
|
||||
|
||||
def commands(self):
|
||||
return(['show running-config'])
|
||||
COMMANDS = [
|
||||
'show running-config'
|
||||
]
|
||||
|
||||
def populate(self, results):
|
||||
self.facts['config'] = results['show running-config']
|
||||
def populate(self):
|
||||
super(Config, self).populate()
|
||||
self.facts['config'] = self.responses[0]
|
||||
|
||||
|
||||
class Interfaces(FactsBase):
|
||||
|
||||
def commands(self):
|
||||
return(['show interfaces', 'show ipv6 interface',
|
||||
'show lldp', 'show lldp neighbors detail'])
|
||||
COMMANDS = [
|
||||
'show interfaces',
|
||||
'show ipv6 interface',
|
||||
'show lldp',
|
||||
'show lldp neighbors detail'
|
||||
]
|
||||
|
||||
def populate(self, results):
|
||||
def populate(self):
|
||||
super(Interfaces, self).populate()
|
||||
self.facts['all_ipv4_addresses'] = list()
|
||||
self.facts['all_ipv6_addresses'] = list()
|
||||
|
||||
interfaces = self.parse_interfaces(results['show interfaces'])
|
||||
interfaces = self.parse_interfaces(self.responses[0])
|
||||
self.facts['interfaces'] = self.populate_interfaces(interfaces)
|
||||
|
||||
data = results['show ipv6 interface']
|
||||
data = self.responses[1]
|
||||
if len(data) > 0:
|
||||
data = self.parse_interfaces(data)
|
||||
self.populate_ipv6_interfaces(data)
|
||||
|
||||
if 'LLDP is not enabled' not in results['show lldp']:
|
||||
neighbors = results['show lldp neighbors detail']
|
||||
if 'LLDP is not enabled' not in self.responses[2]:
|
||||
neighbors = self.responses[3]
|
||||
self.facts['neighbors'] = self.parse_neighbors(neighbors)
|
||||
|
||||
def populate_interfaces(self, interfaces):
|
||||
|
@ -402,17 +422,11 @@ def main():
|
|||
|
||||
instances = list()
|
||||
for key in runable_subsets:
|
||||
instances.append(FACT_SUBSETS[key]())
|
||||
instances.append(FACT_SUBSETS[key](module))
|
||||
|
||||
try:
|
||||
for inst in instances:
|
||||
commands = inst.commands()
|
||||
responses = run_commands(module, commands)
|
||||
results = dict(zip(commands, responses))
|
||||
inst.populate(results)
|
||||
facts.update(inst.facts)
|
||||
except Exception:
|
||||
module.exit_json(out=module.from_json(results))
|
||||
for inst in instances:
|
||||
inst.populate()
|
||||
facts.update(inst.facts)
|
||||
|
||||
ansible_facts = dict()
|
||||
for key, value in iteritems(facts):
|
||||
|
|
|
@ -86,10 +86,13 @@ ansible_facts:
|
|||
returned: always
|
||||
type: dict
|
||||
"""
|
||||
|
||||
import platform
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.network.common.netconf import exec_rpc
|
||||
from ansible.module_utils.network.junos.junos import junos_argument_spec, get_param, tostring
|
||||
from ansible.module_utils.network.junos.junos import get_configuration, get_connection
|
||||
from ansible.module_utils.network.junos.junos import get_configuration, get_capabilities
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.six import iteritems
|
||||
|
||||
|
@ -138,19 +141,30 @@ class FactsBase(object):
|
|||
class Default(FactsBase):
|
||||
|
||||
def populate(self):
|
||||
reply = self.rpc('get-software-information')
|
||||
data = reply.find('.//software-information')
|
||||
|
||||
self.facts.update({
|
||||
'hostname': self.get_text(data, 'host-name'),
|
||||
'version': self.get_text(data, 'junos-version'),
|
||||
'model': self.get_text(data, 'product-model')
|
||||
})
|
||||
self.facts.update(self.platform_facts())
|
||||
|
||||
reply = self.rpc('get-chassis-inventory')
|
||||
data = reply.find('.//chassis-inventory/chassis')
|
||||
self.facts['serialnum'] = self.get_text(data, 'serial-number')
|
||||
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
resp = get_capabilities(self.module)
|
||||
device_info = resp['device_info']
|
||||
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
|
||||
class Config(FactsBase):
|
||||
|
||||
|
@ -318,7 +332,6 @@ def main():
|
|||
module = AnsibleModule(argument_spec=argument_spec,
|
||||
supports_check_mode=True)
|
||||
|
||||
get_connection(module)
|
||||
warnings = list()
|
||||
gather_subset = module.params['gather_subset']
|
||||
|
||||
|
|
|
@ -95,6 +95,18 @@ ansible_net_image:
|
|||
description: The image file the device is running
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_api:
|
||||
description: The name of the transport
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_license_hostid:
|
||||
description: The License host id of the device
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_python_version:
|
||||
description: The Python version Ansible controller is using
|
||||
returned: always
|
||||
type: str
|
||||
|
||||
# hardware
|
||||
ansible_net_filesystems:
|
||||
|
@ -170,6 +182,8 @@ vlan_list:
|
|||
returned: when legacy is configured
|
||||
type: list
|
||||
"""
|
||||
|
||||
import platform
|
||||
import re
|
||||
|
||||
from ansible.module_utils.network.nxos.nxos import run_commands, get_config
|
||||
|
@ -190,6 +204,7 @@ class FactsBase(object):
|
|||
self.module = module
|
||||
self.warnings = list()
|
||||
self.facts = dict()
|
||||
self.capabilities = get_capabilities(self.module)
|
||||
|
||||
def populate(self):
|
||||
pass
|
||||
|
@ -227,39 +242,12 @@ class FactsBase(object):
|
|||
|
||||
class Default(FactsBase):
|
||||
|
||||
VERSION_MAP_7K = frozenset([
|
||||
('sys_ver_str', 'version'),
|
||||
('proc_board_id', 'serialnum'),
|
||||
('chassis_id', 'model'),
|
||||
('isan_file_name', 'image'),
|
||||
('host_name', 'hostname')
|
||||
])
|
||||
|
||||
VERSION_MAP = frozenset([
|
||||
('kickstart_ver_str', 'version'),
|
||||
('proc_board_id', 'serialnum'),
|
||||
('chassis_id', 'model'),
|
||||
('kick_file_name', 'image'),
|
||||
('host_name', 'hostname')
|
||||
])
|
||||
|
||||
def populate(self):
|
||||
data = None
|
||||
|
||||
data = self.run('show version', output='json')
|
||||
data = self.run('show version')
|
||||
|
||||
if data:
|
||||
if isinstance(data, dict):
|
||||
if data.get('sys_ver_str'):
|
||||
self.facts.update(self.transform_dict(data, self.VERSION_MAP_7K))
|
||||
else:
|
||||
self.facts.update(self.transform_dict(data, self.VERSION_MAP))
|
||||
else:
|
||||
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)
|
||||
self.facts['serialnum'] = self.parse_serialnum(data)
|
||||
|
||||
data = self.run('show license host-id')
|
||||
if data:
|
||||
|
@ -279,24 +267,28 @@ class Default(FactsBase):
|
|||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_model(self, data):
|
||||
match = re.search(r'Hardware\n\s+cisco\s*(\S+\s+\S+)', data, re.M)
|
||||
def parse_license_hostid(self, data):
|
||||
match = re.search(r'License hostid: VDH=(.+)$', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_image(self, data):
|
||||
match = re.search(r'\s+system image file is:\s*(\S+)', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
else:
|
||||
match = re.search(r'\s+kickstart image file is:\s*(\S+)', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
def parse_hostname(self, data):
|
||||
match = re.search(r'\s+Device name:\s*(\S+)', data, re.M)
|
||||
if match:
|
||||
return match.group(1)
|
||||
resp = self.capabilities
|
||||
device_info = resp['device_info']
|
||||
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
def parse_license_hostid(self, data):
|
||||
match = re.search(r'License hostid: VDH=(.+)$', data, re.M)
|
||||
|
@ -398,7 +390,7 @@ class Interfaces(FactsBase):
|
|||
])
|
||||
|
||||
def ipv6_structure_op_supported(self):
|
||||
data = get_capabilities(self.module)
|
||||
data = self.capabilities
|
||||
if data:
|
||||
nxos_os_version = data['device_info']['network_os_version']
|
||||
unsupported_versions = ['I2', 'F1', 'A8']
|
||||
|
|
|
@ -95,12 +95,22 @@ ansible_net_gather_subset:
|
|||
description: The list of subsets gathered by the module
|
||||
returned: always
|
||||
type: list
|
||||
ansible_net_api:
|
||||
description: The name of the transport
|
||||
returned: always
|
||||
type: str
|
||||
ansible_net_python_version:
|
||||
description: The Python version Ansible controller is using
|
||||
returned: always
|
||||
type: str
|
||||
"""
|
||||
|
||||
import platform
|
||||
import re
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.six import iteritems
|
||||
from ansible.module_utils.network.vyos.vyos import run_commands
|
||||
from ansible.module_utils.network.vyos.vyos import run_commands, get_capabilities
|
||||
from ansible.module_utils.network.vyos.vyos import vyos_argument_spec
|
||||
|
||||
|
||||
|
@ -121,34 +131,37 @@ class Default(FactsBase):
|
|||
|
||||
COMMANDS = [
|
||||
'show version',
|
||||
'show host name',
|
||||
]
|
||||
|
||||
def populate(self):
|
||||
super(Default, self).populate()
|
||||
data = self.responses[0]
|
||||
|
||||
self.facts['version'] = self.parse_version(data)
|
||||
self.facts['serialnum'] = self.parse_serialnum(data)
|
||||
self.facts['model'] = self.parse_model(data)
|
||||
|
||||
self.facts['hostname'] = self.responses[1]
|
||||
|
||||
def parse_version(self, data):
|
||||
match = re.search(r'Version:\s*(.*)', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def parse_model(self, data):
|
||||
match = re.search(r'HW model:\s*(\S+)', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
self.facts.update(self.platform_facts())
|
||||
|
||||
def parse_serialnum(self, data):
|
||||
match = re.search(r'HW S/N:\s+(\S+)', data)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
def platform_facts(self):
|
||||
platform_facts = {}
|
||||
|
||||
resp = get_capabilities(self.module)
|
||||
device_info = resp['device_info']
|
||||
|
||||
platform_facts['system'] = device_info['network_os']
|
||||
|
||||
for item in ('model', 'image', 'version', 'platform', 'hostname'):
|
||||
val = device_info.get('network_os_%s' % item)
|
||||
if val:
|
||||
platform_facts[item] = val
|
||||
|
||||
platform_facts['api'] = resp['network_api']
|
||||
platform_facts['python_version'] = platform.python_version()
|
||||
|
||||
return platform_facts
|
||||
|
||||
|
||||
class Config(FactsBase):
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ options:
|
|||
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
|
||||
from ansible.errors import AnsibleConnectionFailure
|
||||
from ansible.module_utils._text import to_text
|
||||
|
@ -246,6 +247,11 @@ class Cliconf(CliconfBase):
|
|||
|
||||
device_info['network_os_hostname'] = data['hostname']
|
||||
|
||||
reply = self.get('bash timeout 5 cat /mnt/flash/boot-config')
|
||||
match = re.search(r'SWI=(.+)$', reply, re.M)
|
||||
if match:
|
||||
device_info['network_os_image'] = match.group(1)
|
||||
|
||||
return device_info
|
||||
|
||||
def get_device_operations(self):
|
||||
|
|
|
@ -216,6 +216,10 @@ class Cliconf(CliconfBase):
|
|||
if match:
|
||||
device_info['network_os_hostname'] = match.group(1)
|
||||
|
||||
match = re.search(r'image file is "(.+)"', data)
|
||||
if match:
|
||||
device_info['network_os_image'] = match.group(1)
|
||||
|
||||
return device_info
|
||||
|
||||
def get_device_operations(self):
|
||||
|
|
|
@ -80,9 +80,9 @@ class Cliconf(CliconfBase):
|
|||
if match_sys_ver:
|
||||
device_info['network_os_version'] = match_sys_ver.group(1)
|
||||
|
||||
match_chassis_id = re.search(r'Hardware\n\s+cisco\s*(\S+\s+\S+)', reply, re.M)
|
||||
match_chassis_id = re.search(r'Hardware\n\s+cisco(.+)$', reply, re.M)
|
||||
if match_chassis_id:
|
||||
device_info['network_os_model'] = match_chassis_id.group(1)
|
||||
device_info['network_os_model'] = match_chassis_id.group(1).strip()
|
||||
|
||||
match_host_name = re.search(r'\s+Device name:\s*(\S+)', reply, re.M)
|
||||
if match_host_name:
|
||||
|
|
|
@ -52,7 +52,7 @@ class Cliconf(CliconfBase):
|
|||
reply = self.get('show version')
|
||||
data = to_text(reply, errors='surrogate_or_strict').strip()
|
||||
|
||||
match = re.search(r'Version:\s*(\S+)', data)
|
||||
match = re.search(r'Version:\s*(.*)', data)
|
||||
if match:
|
||||
device_info['network_os_version'] = match.group(1)
|
||||
|
||||
|
|
|
@ -33,9 +33,23 @@ class TestIosFactsModule(TestIosModule):
|
|||
self.mock_run_commands = patch('ansible.modules.network.ios.ios_facts.run_commands')
|
||||
self.run_commands = self.mock_run_commands.start()
|
||||
|
||||
self.mock_get_capabilities = patch('ansible.modules.network.ios.ios_facts.get_capabilities')
|
||||
self.get_capabilities = self.mock_get_capabilities.start()
|
||||
self.get_capabilities.return_value = {
|
||||
'device_info': {
|
||||
'network_os': 'ios',
|
||||
'network_os_hostname': 'an-ios-01',
|
||||
'network_os_image': 'flash0:/vios-adventerprisek9-m',
|
||||
'network_os_model': 'WS-C3750-24TS',
|
||||
'network_os_version': '15.6(3)M2'
|
||||
},
|
||||
'network_api': 'cliconf'
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
super(TestIosFactsModule, self).tearDown()
|
||||
self.mock_run_commands.stop()
|
||||
self.mock_get_capabilities.stop()
|
||||
|
||||
def load_fixtures(self, commands=None):
|
||||
def load_from_file(*args, **kwargs):
|
||||
|
|
|
@ -38,10 +38,23 @@ class TestIosxrFacts(TestIosxrModule):
|
|||
'ansible.modules.network.iosxr.iosxr_facts.run_commands')
|
||||
self.run_commands = self.mock_run_commands.start()
|
||||
|
||||
self.mock_get_capabilities = patch('ansible.modules.network.iosxr.iosxr_facts.get_capabilities')
|
||||
self.get_capabilities = self.mock_get_capabilities.start()
|
||||
self.get_capabilities.return_value = {
|
||||
'device_info': {
|
||||
'network_os': 'iosxr',
|
||||
'network_os_hostname': 'iosxr01',
|
||||
'network_os_image': 'bootflash:disk0/xrvr-os-mbi-6.1.3/mbixrvr-rp.vm',
|
||||
'network_os_version': '6.1.3[Default]'
|
||||
},
|
||||
'network_api': 'cliconf'
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
super(TestIosxrFacts, self).tearDown()
|
||||
|
||||
self.mock_run_commands.stop()
|
||||
self.mock_get_capabilities.stop()
|
||||
|
||||
def load_fixtures(self, commands=None):
|
||||
|
||||
|
|
|
@ -49,9 +49,6 @@ class TestJunosCommandModule(TestJunosModule):
|
|||
self.mock_get_config = patch('ansible.modules.network.junos.junos_facts.get_configuration')
|
||||
self.get_config = self.mock_get_config.start()
|
||||
|
||||
self.mock_conn = patch('ansible.module_utils.connection.Connection')
|
||||
self.conn = self.mock_conn.start()
|
||||
|
||||
self.mock_netconf = patch('ansible.module_utils.network.junos.junos.NetconfConnection')
|
||||
self.netconf_conn = self.mock_netconf.start()
|
||||
|
||||
|
@ -61,13 +58,20 @@ class TestJunosCommandModule(TestJunosModule):
|
|||
self.mock_netconf_rpc = patch('ansible.module_utils.network.common.netconf.NetconfConnection')
|
||||
self.netconf_rpc = self.mock_netconf_rpc.start()
|
||||
|
||||
self.mock_get_capabilities = patch('ansible.module_utils.network.junos.junos.get_capabilities')
|
||||
self.mock_get_capabilities = patch('ansible.modules.network.junos.junos_facts.get_capabilities')
|
||||
self.get_capabilities = self.mock_get_capabilities.start()
|
||||
self.get_capabilities.return_value = {'network_api': 'netconf'}
|
||||
self.get_capabilities.return_value = {
|
||||
'device_info': {
|
||||
'network_os': 'junos',
|
||||
'network_os_hostname': 'vsrx01',
|
||||
'network_os_model': 'vsrx',
|
||||
'network_os_version': '17.3R1.10'
|
||||
},
|
||||
'network_api': 'netconf'
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
super(TestJunosCommandModule, self).tearDown()
|
||||
self.mock_conn.stop()
|
||||
self.mock_netconf.stop()
|
||||
self.mock_exec_rpc.stop()
|
||||
self.mock_netconf_rpc.stop()
|
||||
|
|
|
@ -36,9 +36,22 @@ class TestVyosFactsModule(TestVyosModule):
|
|||
self.mock_run_commands = patch('ansible.modules.network.vyos.vyos_facts.run_commands')
|
||||
self.run_commands = self.mock_run_commands.start()
|
||||
|
||||
self.mock_get_capabilities = patch('ansible.modules.network.vyos.vyos_facts.get_capabilities')
|
||||
self.get_capabilities = self.mock_get_capabilities.start()
|
||||
self.get_capabilities.return_value = {
|
||||
'device_info': {
|
||||
'network_os': 'vyos',
|
||||
'network_os_hostname': 'vyos01',
|
||||
'network_os_model': 'VMware',
|
||||
'network_os_version': 'VyOS 1.1.7'
|
||||
},
|
||||
'network_api': 'cliconf'
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
super(TestVyosFactsModule, self).tearDown()
|
||||
self.mock_run_commands.stop()
|
||||
self.mock_get_capabilities.stop()
|
||||
|
||||
def load_fixtures(self, commands=None):
|
||||
def load_from_file(*args, **kwargs):
|
||||
|
@ -61,7 +74,7 @@ class TestVyosFactsModule(TestVyosModule):
|
|||
set_module_args(dict(gather_subset='default'))
|
||||
result = self.execute_module()
|
||||
facts = result.get('ansible_facts')
|
||||
self.assertEqual(len(facts), 5)
|
||||
self.assertEqual(len(facts), 8)
|
||||
self.assertEqual(facts['ansible_net_hostname'].strip(), 'vyos01')
|
||||
self.assertEqual(facts['ansible_net_version'], 'VyOS 1.1.7')
|
||||
|
||||
|
@ -69,7 +82,7 @@ class TestVyosFactsModule(TestVyosModule):
|
|||
set_module_args(dict(gather_subset='!all'))
|
||||
result = self.execute_module()
|
||||
facts = result.get('ansible_facts')
|
||||
self.assertEqual(len(facts), 5)
|
||||
self.assertEqual(len(facts), 8)
|
||||
self.assertEqual(facts['ansible_net_hostname'].strip(), 'vyos01')
|
||||
self.assertEqual(facts['ansible_net_version'], 'VyOS 1.1.7')
|
||||
|
||||
|
@ -77,7 +90,7 @@ class TestVyosFactsModule(TestVyosModule):
|
|||
set_module_args(dict(gather_subset=['!neighbors', '!config']))
|
||||
result = self.execute_module()
|
||||
facts = result.get('ansible_facts')
|
||||
self.assertEqual(len(facts), 5)
|
||||
self.assertEqual(len(facts), 8)
|
||||
self.assertEqual(facts['ansible_net_hostname'].strip(), 'vyos01')
|
||||
self.assertEqual(facts['ansible_net_version'], 'VyOS 1.1.7')
|
||||
|
||||
|
|
Loading…
Reference in a new issue