icx: new module icx_facts (#61225)

* new cliconf

* cliconf

* icx cliconf

* icx test units module

* icx units module

* icx banner unit test

* added notes

* new changes

* icx .rst

* modified platform_index.rst

* test

* Revert "test"

This reverts commit 99b72c6614.

* new module icx_facts

* fixtures added

* Rebase causing problem on branch-PR4. So created new PR

* new commit

* new changes
This commit is contained in:
sushma-alethea 2019-08-26 14:00:00 +05:30 committed by Ganesh Nalawade
parent 8ed3a0b360
commit c729f3ba61
12 changed files with 870 additions and 0 deletions

View file

@ -56,6 +56,7 @@ options:
by specifying it as module parameter.
type: bool
default: yes
"""
EXAMPLES = """

View file

@ -0,0 +1,549 @@
#!/usr/bin/python
# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
---
module: icx_facts
version_added: "2.9"
author: "Ruckus Wireless (@Commscope)"
short_description: Collect facts from remote Ruckus ICX 7000 series switches
description:
- Collects a base set of device facts from a remote device that
is running ICX. This module prepends all of the
base network fact keys with C(ansible_net_<fact>). The facts
module will always collect a base set of facts from the device
and can enable or disable collection of additional facts.
notes:
- Tested against ICX 10.1.
- For information on using ICX platform, see L(the ICX OS Platform Options guide,../network/user_guide/platform_icx.html).
options:
gather_subset:
description:
- When supplied, this argument will restrict the facts collected
to a given subset. Possible values for this argument include
all, hardware, config, and interfaces. Can specify a list of
values to include a larger subset. Values can also be used
with an initial C(M(!)) to specify that a specific subset should
not be collected.
required: false
type: list
default: '!config'
"""
EXAMPLES = """
# Collect all facts from the device
- icx_facts:
gather_subset: all
# Collect only the config and default facts
- icx_facts:
gather_subset:
- config
# Do not collect hardware facts
- icx_facts:
gather_subset:
- "!hardware"
"""
RETURN = """
ansible_net_gather_subset:
description: The list of fact subsets collected from the device
returned: always
type: list
# default
ansible_net_model:
description: The model name returned from the device
returned: always
type: str
ansible_net_serialnum:
description: The serial number of the remote device
returned: always
type: str
ansible_net_version:
description: The operating system version running on the remote device
returned: always
type: str
ansible_net_hostname:
description: The configured hostname of the device
returned: always
type: str
ansible_net_image:
description: The image file the device is running
returned: always
type: str
ansible_net_stacked_models:
description: The model names of each device in the stack
returned: when multiple devices are configured in a stack
type: list
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
# hardware
ansible_net_filesystems:
description: All file system names available on the device
returned: when hardware is configured
type: list
ansible_net_filesystems_info:
description: A hash of all file systems containing info about each file system (e.g. free and total space)
returned: when hardware is configured
type: dict
ansible_net_memfree_mb:
description: The available free memory on the remote device in Mb
returned: when hardware is configured
type: int
ansible_net_memtotal_mb:
description: The total memory on the remote device in Mb
returned: when hardware is configured
type: int
# config
ansible_net_config:
description: The current active config from the device
returned: when config is configured
type: str
# interfaces
ansible_net_all_ipv4_addresses:
description: All IPv4 addresses configured on the device
returned: when interfaces is configured
type: list
ansible_net_all_ipv6_addresses:
description: All IPv6 addresses configured on the device
returned: when interfaces is configured
type: list
ansible_net_interfaces:
description: A hash of all interfaces running on the system
returned: when interfaces is configured
type: dict
ansible_net_neighbors:
description: The list of LLDP neighbors from the remote device
returned: when interfaces is configured
type: dict
"""
import re
from ansible.module_utils.network.icx.icx import run_commands
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
from ansible.module_utils.six.moves import zip
class FactsBase(object):
COMMANDS = list()
def __init__(self, module):
self.module = module
self.facts = dict()
self.responses = None
def populate(self):
self.responses = run_commands(self.module, commands=self.COMMANDS, check_rc=False)
def run(self, cmd):
return run_commands(self.module, commands=cmd, check_rc=False)
class Default(FactsBase):
COMMANDS = ['show version', 'show running-config | include hostname']
def populate(self):
super(Default, self).run(['skip'])
super(Default, self).populate()
data = self.responses[0]
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(self.responses[1])
self.parse_stacks(data)
def parse_version(self, data):
match = re.search(r'SW: Version ([0-9]+.[0-9]+.[0-9a-zA-Z]+)', data)
if match:
return match.group(1)
def parse_hostname(self, data):
match = re.search(r'^hostname (\S+)', data, re.M)
if match:
return match.group(1)
def parse_model(self, data):
match = re.search(r'HW: (\S+ \S+)', data, re.M)
if match:
return match.group(1)
def parse_image(self, data):
match = re.search(r'\([0-9]+ bytes\) from \S+ (\S+)', data)
if match:
return match.group(1)
def parse_serialnum(self, data):
match = re.search(r'Serial #:(\S+)', data)
if match:
return match.group(1)
def parse_stacks(self, data):
match = re.findall(r'UNIT [1-9]+: SL [1-9]+: (\S+)', data, re.M)
if match:
self.facts['stacked_models'] = match
match = re.findall(r'^System [Ss]erial [Nn]umber\s+: (\S+)', data, re.M)
if match:
self.facts['stacked_serialnums'] = match
class Hardware(FactsBase):
COMMANDS = [
'show memory',
'show flash'
]
def populate(self):
super(Hardware, self).populate()
data = self.responses[0]
if data:
self.facts['filesystems'] = self.parse_filesystems(data)
self.facts['filesystems_info'] = self.parse_filesystems_info(self.responses[1])
if data:
if 'Invalid input detected' in data:
warnings.append('Unable to gather memory statistics')
else:
match = re.search(r'Dynamic memory: ([0-9]+) bytes total, ([0-9]+) bytes free, ([0-9]+%) used', data)
if match:
self.facts['memtotal_mb'] = int(match.group(1)) / 1024
self.facts['memfree_mb'] = int(match.group(2)) / 1024
def parse_filesystems(self, data):
return "flash"
def parse_filesystems_info(self, data):
facts = dict()
fs = ''
for line in data.split('\n'):
match = re.match(r'^(Stack unit \S+):', line)
if match:
fs = match.group(1)
facts[fs] = dict()
continue
match = re.match(r'\W+NAND Type: Micron NAND (\S+)', line)
if match:
facts[fs]['spacetotal'] = match.group(1)
match = re.match(r'\W+Code Flash Free Space = (\S+)', line)
if match:
facts[fs]['spacefree'] = int(int(match.group(1)) / 1024)
facts[fs]['spacefree'] = str(facts[fs]['spacefree']) + "Kb"
return {"flash": facts}
class Config(FactsBase):
COMMANDS = ['skip', 'show running-config']
def populate(self):
super(Config, self).populate()
data = self.responses[1]
if data:
self.facts['config'] = data
class Interfaces(FactsBase):
COMMANDS = [
'skip',
'show interfaces',
'show running-config',
'show lldp',
'show media'
]
def populate(self):
super(Interfaces, self).populate()
self.facts['all_ipv4_addresses'] = list()
self.facts['all_ipv6_addresses'] = list()
data = self.responses[1]
if data:
interfaces = self.parse_interfaces(data)
self.facts['interfaces'] = self.populate_interfaces(interfaces)
data = self.responses[1]
if data:
data = self.parse_interfaces(data)
self.populate_ipv4_interfaces(data)
data = self.responses[2]
if data:
self.populate_ipv6_interfaces(data)
data = self.responses[3]
lldp_errs = ['Invalid input', 'LLDP is not enabled']
if data and not any(err in data for err in lldp_errs):
neighbors = self.run(['show lldp neighbors detail'])
if neighbors:
self.facts['neighbors'] = self.parse_neighbors(neighbors[0])
data = self.responses[4]
self.populate_mediatype(data)
interfaceList = {}
for iface in self.facts['interfaces']:
if 'type' in self.facts['interfaces'][iface]:
newName = self.facts['interfaces'][iface]['type'] + iface
else:
newName = iface
interfaceList[newName] = self.facts['interfaces'][iface]
self.facts['interfaces'] = interfaceList
def populate_mediatype(self, data):
lines = data.split("\n")
for line in lines:
match = re.match(r'Port (\S+):\W+Type\W+:\W+(.*)', line)
if match:
self.facts['interfaces'][match.group(1)]["mediatype"] = match.group(2)
def populate_interfaces(self, interfaces):
facts = dict()
for key, value in iteritems(interfaces):
intf = dict()
intf['description'] = self.parse_description(value)
intf['macaddress'] = self.parse_macaddress(value)
intf['mtu'] = self.parse_mtu(value)
intf['bandwidth'] = self.parse_bandwidth(value)
intf['duplex'] = self.parse_duplex(value)
intf['lineprotocol'] = self.parse_lineprotocol(value)
intf['operstatus'] = self.parse_operstatus(value)
intf['type'] = self.parse_type(value)
facts[key] = intf
return facts
def populate_ipv4_interfaces(self, data):
for key, value in data.items():
self.facts['interfaces'][key]['ipv4'] = dict()
primary_address = addresses = []
primary_address = re.findall(r'Internet address is (\S+/\S+), .*$', value, re.M)
addresses = re.findall(r'Secondary address (.+)$', value, re.M)
if len(primary_address) == 0:
continue
addresses.append(primary_address[0])
for address in addresses:
addr, subnet = address.split("/")
ipv4 = dict(address=addr.strip(), subnet=subnet.strip())
self.add_ip_address(addr.strip(), 'ipv4')
self.facts['interfaces'][key]['ipv4'] = ipv4
def populate_ipv6_interfaces(self, data):
parts = data.split("\n")
for line in parts:
match = re.match(r'\W*interface \S+ (\S+)', line)
if match:
key = match.group(1)
try:
self.facts['interfaces'][key]['ipv6'] = list()
except KeyError:
self.facts['interfaces'][key] = dict()
self.facts['interfaces'][key]['ipv6'] = list()
self.facts['interfaces'][key]['ipv6'] = {}
continue
match = re.match(r'\W+ipv6 address (\S+)/(\S+)', line)
if match:
self.add_ip_address(match.group(1), "ipv6")
self.facts['interfaces'][key]['ipv6']["address"] = match.group(1)
self.facts['interfaces'][key]['ipv6']["subnet"] = match.group(2)
def add_ip_address(self, address, family):
if family == 'ipv4':
self.facts['all_ipv4_addresses'].append(address)
else:
self.facts['all_ipv6_addresses'].append(address)
def parse_neighbors(self, neighbors):
facts = dict()
for entry in neighbors.split('------------------------------------------------'):
if entry == '':
continue
intf = self.parse_lldp_intf(entry)
if intf not in facts:
facts[intf] = list()
fact = dict()
fact['host'] = self.parse_lldp_host(entry)
fact['port'] = self.parse_lldp_port(entry)
facts[intf].append(fact)
return facts
def parse_interfaces(self, data):
parsed = dict()
key = ''
for line in data.split('\n'):
if len(line) == 0:
continue
elif line[0] == ' ':
parsed[key] += '\n%s' % line
else:
match = re.match(r'\S+Ethernet(\S+)', line)
if match:
key = match.group(1)
parsed[key] = line
return parsed
def parse_description(self, data):
match = re.search(r'Port name is ([ \S]+)', data, re.M)
if match:
return match.group(1)
def parse_macaddress(self, data):
match = re.search(r'Hardware is \S+, address is (\S+)', data)
if match:
return match.group(1)
def parse_ipv4(self, data):
match = re.search(r'Internet address is (\S+)', data)
if match:
addr, masklen = match.group(1).split('/')
return dict(address=addr, masklen=int(masklen))
def parse_mtu(self, data):
match = re.search(r'MTU (\d+)', data)
if match:
return int(match.group(1))
def parse_bandwidth(self, data):
match = re.search(r'Configured speed (\S+), actual (\S+)', data)
if match:
return match.group(1)
def parse_duplex(self, data):
match = re.search(r'configured duplex (\S+), actual (\S+)', data, re.M)
if match:
return match.group(2)
def parse_mediatype(self, data):
match = re.search(r'media type is (.+)$', data, re.M)
if match:
return match.group(1)
def parse_type(self, data):
match = re.search(r'Hardware is (.+),', data, re.M)
if match:
return match.group(1)
def parse_lineprotocol(self, data):
match = re.search(r'line protocol is (.+)$', data, re.M)
if match:
return match.group(1)
def parse_operstatus(self, data):
match = re.search(r'^(?:.+) is (.+),', data, re.M)
if match:
return match.group(1)
def parse_lldp_intf(self, data):
match = re.search(r'^Local Intf: (.+)$', data, re.M)
if match:
return match.group(1)
def parse_lldp_host(self, data):
match = re.search(r'System Name: (.+)$', data, re.M)
if match:
return match.group(1)
def parse_lldp_port(self, data):
match = re.search(r'Port id: (.+)$', data, re.M)
if match:
return match.group(1)
FACT_SUBSETS = dict(
default=Default,
hardware=Hardware,
interfaces=Interfaces,
config=Config,
)
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
warnings = list()
def main():
"""main entry point for module execution
"""
argument_spec = dict(
gather_subset=dict(default=['!config'], type='list')
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
gather_subset = module.params['gather_subset']
runable_subsets = set()
exclude_subsets = set()
for subset in gather_subset:
if subset == 'all':
runable_subsets.update(VALID_SUBSETS)
continue
if subset.startswith('!'):
subset = subset[1:]
if subset == 'all':
exclude_subsets.update(VALID_SUBSETS)
continue
exclude = True
else:
exclude = False
if subset not in VALID_SUBSETS:
module.fail_json(msg='Bad subset')
if exclude:
exclude_subsets.add(subset)
else:
runable_subsets.add(subset)
if not runable_subsets:
runable_subsets.update(VALID_SUBSETS)
runable_subsets.difference_update(exclude_subsets)
runable_subsets.add('default')
facts = dict()
facts['gather_subset'] = list(runable_subsets)
instances = list()
for key in runable_subsets:
instances.append(FACT_SUBSETS[key](module))
for inst in instances:
inst.populate()
facts.update(inst.facts)
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, warnings=warnings)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,6 @@
Stack unit 1:
NAND Type: Micron NAND 2GiB (x 1)
Compressed Pri Code size = 25966800, Version:08.0.80bT211 (primary.bin)
Compressed Sec Code size = 29451996, Version:08.0.70dT213 (SPR08070d.bin)
Compressed Boot-Monitor Image size = 786944, Version:10.1.09T225
Code Flash Free Space = 1318699008

View file

@ -0,0 +1,85 @@
GigabitEthernet1/1/1 is down, line protocol is down
Port down for 2 day(s) 23 hour(s) 4 minute(s) 18 second(s)
Hardware is GigabitEthernet, address is 609c.9fe7.d600 (bia 609c.9fe7.d600)
Configured speed 10Mbit, actual unknown, configured duplex fdx, actual unknown
Configured mdi mode AUTO, actual unknown
Member of L2 VLAN ID 1, port is untagged, port state is BLOCKING
BPDU guard is Disabled, ROOT protect is Disabled, Designated protect is Disabled
Link Error Dampening is Disabled
STP configured to ON, priority is level0, mac-learning is enabled
Openflow is Disabled, Openflow Hybrid mode is Disabled, Flow Control is config enabled, oper enabled, negotiation disabled
Mirror disabled, Monitor disabled
Mac-notification is disabled
Not member of any active trunks
Not member of any configured trunks
Port name is test name
IPG MII 0 bits-time, IPG GMII 0 bits-time
Internet address is 192.168.1.1/24, MTU 1500 bytes, encapsulation ethernet
MMU Mode is Store-and-forward
300 second input rate: 0 bits/sec, 0 packets/sec, 0.00% utilization
300 second output rate: 0 bits/sec, 0 packets/sec, 0.00% utilization
0 packets input, 0 bytes, 0 no buffer
Received 0 broadcasts, 0 multicasts, 0 unicasts
0 input errors, 0 CRC, 0 frame, 0 ignored
0 runts, 0 giants
0 packets output, 0 bytes, 0 underruns
Transmitted 0 broadcasts, 0 multicasts, 0 unicasts
0 output errors, 0 collisions
Relay Agent Information option: Disabled
Protected: No
MAC Port Security: Disabled
This port is not being monitored for queue drops
Egress queues:
Queue counters Queued packets Dropped Packets
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0
GigabitEthernet1/1/2 is down, line protocol is down
Port down for 2 day(s) 23 hour(s) 4 minute(s) 18 second(s)
Hardware is GigabitEthernet, address is 609c.9fe7.d601 (bia 609c.9fe7.d601)
Configured speed auto, actual unknown, configured duplex fdx, actual unknown
Configured mdi mode AUTO, actual unknown
Member of L2 VLAN ID 1, port is untagged, port state is BLOCKING
BPDU guard is Disabled, ROOT protect is Disabled, Designated protect is Disabled
Link Error Dampening is Disabled
STP configured to ON, priority is level0, mac-learning is enabled
Openflow is Disabled, Openflow Hybrid mode is Disabled, Flow Control is config enabled, oper enabled, negotiation disabled
Mirror disabled, Monitor disabled
Mac-notification is disabled
Not member of any active trunks
Not member of any configured trunks
No port name
IPG MII 0 bits-time, IPG GMII 0 bits-time
MTU 1500 bytes, encapsulation ethernet
MMU Mode is Store-and-forward
300 second input rate: 0 bits/sec, 0 packets/sec, 0.00% utilization
300 second output rate: 0 bits/sec, 0 packets/sec, 0.00% utilization
0 packets input, 0 bytes, 0 no buffer
Received 0 broadcasts, 0 multicasts, 0 unicasts
0 input errors, 0 CRC, 0 frame, 0 ignored
0 runts, 0 giants
0 packets output, 0 bytes, 0 underruns
Transmitted 0 broadcasts, 0 multicasts, 0 unicasts
0 output errors, 0 collisions
Relay Agent Information option: Disabled
Protected: No
MAC Port Security: Disabled
This port is not being monitored for queue drops
Egress queues:
Queue counters Queued packets Dropped Packets
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0

View file

@ -0,0 +1,9 @@
LLDP transmit interval : 30 seconds
LLDP transmit hold multiplier : 4 (transmit TTL: 120 seconds)
LLDP transmit delay : 2 seconds
LLDP SNMP notification interval : 5 seconds
LLDP reinitialize delay : 2 seconds
LLDP-MED fast start repeat count : 3
LLDP maximum neighbors : 2048
LLDP maximum neighbors per port : 4

View file

@ -0,0 +1,2 @@
Port 1/1/1: Type : 1G M-C (Gig-Copper)
Port 1/1/2: Type : 1G M-C (Gig-Copper)

View file

@ -0,0 +1,3 @@
Stack unit 1:
Total DRAM: 954695680 bytes
Dynamic memory: 954695680 bytes total, 375963648 bytes free, 60% used

View file

@ -0,0 +1,76 @@
Current configuration:
!
ver 08.0.70dT213
!
stack unit 1
module 1 icx7150-48-port-management-module
module 2 icx7150-2-copper-port-2g-module
module 3 icx7150-4-sfp-plus-port-40g-module
!
!
!
lag LAG1 dynamic id 100
ports ethe 1/1/4 to 1/1/7
!
lag LAG2 dynamic id 200
ports ethe 1/1/12 to 1/1/15
!
!
!
!
!
!
!
!
!
aaa authentication enable implicit-user
aaa authentication login default local
enable super-user-password .....
hostname ruchusRouter148
ip dns domain-list fileserver.alethea.in
ip dns server-address 8.8.8.8
!
username alethea password .....
username ale6 password .....
!
!
banner exec ^C
welcome icx exec^C
^C
!
banner motd ^C
welcome icx motd^C
^C
!
banner incoming ^C
welcome icx incomingg^C
^C
!
!
!
!
!
!
!
!
interface management 1
no ip dhcp-client enable
ip address 10.10.10.148 255.255.255.0
!
interface ethernet 1/1/1
port-name test name
ip address 192.168.1.1 255.255.255.0
ipv6 address 2001:db8:85a3::8a2e:370:7334/64
speed-duplex 10-full
!
!
!
!
!
lldp run
!
!
!
!
!
end

View file

@ -0,0 +1 @@
hostname ruchusRouter148

View file

@ -0,0 +1 @@
Disable page display mode

View file

@ -0,0 +1,137 @@
# Copyright: (c) 2019, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from units.compat.mock import patch
from ansible.modules.network.icx import icx_facts
from units.modules.utils import set_module_args
from .icx_module import TestICXModule, load_fixture
class TestICXFactsModule(TestICXModule):
module = icx_facts
def setUp(self):
super(TestICXFactsModule, self).setUp()
self.mock_run_commands = patch('ansible.modules.network.icx.icx_facts.run_commands')
self.run_commands = self.mock_run_commands.start()
def tearDown(self):
super(TestICXFactsModule, self).tearDown()
self.mock_run_commands.stop()
def load_fixtures(self, commands=None):
def load_from_file(*args, **kwargs):
module = args
commands = kwargs['commands']
if(commands):
resp = list()
for cmd in commands:
fixtureName = cmd.replace(" ", "_")
newFixtureName = fixtureName.replace("_|_", "_")
output = load_fixture(newFixtureName).strip()
if(output):
resp.append(output)
return resp
self.run_commands.side_effect = load_from_file
def test_icx_facts_default(self):
set_module_args(dict(gather_subset=["default"]))
result = self.execute_module()
self.assertEqual(
result['ansible_facts']['ansible_net_model'], 'Stackable ICX7150-48-POE'
)
self.assertEqual(
result['ansible_facts']['ansible_net_serialnum'], 'FEC3220N00C'
)
self.assertEqual(
result['ansible_facts']['ansible_net_version'], '08.0.60T211'
)
self.assertEqual(
result['ansible_facts']['ansible_net_hostname'], 'ruchusRouter148'
)
self.assertEqual(
result['ansible_facts']['ansible_net_image'], 'SPS08060.bin'
)
self.assertEqual(
result['ansible_facts']['ansible_net_stacked_models'], ['ICX7150-48P-4X1G', 'ICX7150-2X1GC', 'ICX7150-4X10GF']
)
def test_icx_facts_interfaces(self):
set_module_args(dict(gather_subset=["interfaces"]))
result = self.execute_module()
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["macaddress"], "609c.9fe7.d600"
)
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["ipv4"]["address"], "192.168.1.1"
)
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["ipv4"]["subnet"], "24"
)
def test_icx_facts_hardware(self):
set_module_args(dict(gather_subset=["hardware"]))
result = self.execute_module()
self.assertEqual(
result['ansible_facts']['ansible_net_filesystems'], "flash"
)
self.assertEqual(
result['ansible_facts']['ansible_net_filesystems_info'], {'flash': {'Stack unit 1': {'spacetotal': '2GiB', 'spacefree': '1287792Kb'}}}
)
self.assertEqual(
result['ansible_facts']['ansible_net_memfree_mb'], 367152
)
self.assertEqual(
result['ansible_facts']['ansible_net_memtotal_mb'], 932320
)
def test_icx_facts_not_hardware(self):
set_module_args(dict(gather_subset=["!hardware"]))
result = self.execute_module()
print(result)
def test_icx_facts_all(self):
set_module_args(dict(gather_subset=["all"]))
result = self.execute_module()
self.assertEqual(
result['ansible_facts']['ansible_net_filesystems'], "flash"
)
self.assertEqual(
result['ansible_facts']['ansible_net_filesystems_info'], {'flash': {'Stack unit 1': {'spacetotal': '2GiB', 'spacefree': '1287792Kb'}}}
)
self.assertEqual(
result['ansible_facts']['ansible_net_memfree_mb'], 367152
)
self.assertEqual(
result['ansible_facts']['ansible_net_memtotal_mb'], 932320
)
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["macaddress"], "609c.9fe7.d600"
)
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["ipv4"]["address"], "192.168.1.1"
)
self.assertEqual(
result['ansible_facts']['ansible_net_interfaces']["GigabitEthernet1/1/1"]["ipv4"]["subnet"], "24"
)
self.assertEqual(
result['ansible_facts']['ansible_net_model'], 'Stackable ICX7150-48-POE'
)
self.assertEqual(
result['ansible_facts']['ansible_net_serialnum'], 'FEC3220N00C'
)
self.assertEqual(
result['ansible_facts']['ansible_net_version'], '08.0.60T211'
)
self.assertEqual(
result['ansible_facts']['ansible_net_hostname'], 'ruchusRouter148'
)
self.assertEqual(
result['ansible_facts']['ansible_net_image'], 'SPS08060.bin'
)
self.assertEqual(
result['ansible_facts']['ansible_net_stacked_models'], ['ICX7150-48P-4X1G', 'ICX7150-2X1GC', 'ICX7150-4X10GF']
)