diff --git a/tests/common/devices.py b/tests/common/devices.py index 6931d0b80ca..615d6e96a40 100644 --- a/tests/common/devices.py +++ b/tests/common/devices.py @@ -25,11 +25,15 @@ class AnsibleHostBase(object): on the host. """ - def __init__(self, ansible_adhoc, hostname): + def __init__(self, ansible_adhoc, hostname, connection=None): if hostname == 'localhost': self.host = ansible_adhoc(inventory='localhost', connection='local', host_pattern=hostname)[hostname] else: - self.host = ansible_adhoc(become=True)[hostname] + if connection is None: + self.host = ansible_adhoc(become=True)[hostname] + else: + logging.debug("connection {} for {}".format(connection, hostname)) + self.host = ansible_adhoc(become=True, connection=connection)[hostname] self.hostname = hostname def __getattr__(self, item): @@ -307,3 +311,18 @@ def get_networking_uptime(self): except Exception as e: self.logger.error("Exception raised while getting networking restart time: %s" % repr(e)) return None + +class EosHost(AnsibleHostBase): + """ + @summary: Class for Eos switch + + For running ansible module on the Eos switch + """ + + def __init__(self, ansible_adhoc, hostname, user, passwd, gather_facts=False): + AnsibleHostBase.__init__(self, ansible_adhoc, hostname, connection="network_cli") + evars = { 'ansible_connection':'network_cli', \ + 'ansible_network_os':'eos', \ + 'ansible_user': user, \ + 'ansible_password': passwd } + self.host.options['variable_manager'].extra_vars.update(evars) diff --git a/tests/conftest.py b/tests/conftest.py index 9e4d2d030af..7e0801cc0bb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ import sys import os import glob +import json import tarfile import logging import time @@ -12,7 +13,7 @@ from ansible_host import AnsibleHost from collections import defaultdict -from common.devices import SonicHost, Localhost, PTFHost +from common.devices import SonicHost, Localhost, PTFHost, EosHost logger = logging.getLogger(__name__) @@ -123,15 +124,8 @@ def testbed_devices(ansible_adhoc, testbed): ptf_host = dut.host.options["inventory_manager"].get_host(dut.hostname).get_vars()["ptf_host"] devices["ptf"] = PTFHost(ansible_adhoc, ptf_host) - # In the future, we can implement more classes for interacting with other testbed devices in the lib.devices - # module. Then, in this fixture, we can initialize more instance of the classes and store the objects in the - # devices dict here. For example, we could have - # from common.devices import FanoutHost - # devices["fanout"] = FanoutHost(ansible_adhoc, testbed["dut"]) - return devices - def disable_ssh_timout(dut): ''' @summary disable ssh session on target dut @@ -186,6 +180,17 @@ def ptfhost(testbed_devices): return testbed_devices["ptf"] +@pytest.fixture(scope="module") +def nbrhosts(ansible_adhoc, testbed, creds): + """ + Shortcut fixture for getting PTF host + """ + + vm_base = int(testbed['vm_base'][2:]) + devices = {} + for k, v in testbed['topo']['properties']['topology']['VMs'].items(): + devices[k] = EosHost(ansible_adhoc, "VM%04d" % (vm_base + v['vm_offset']), creds['eos_login'], creds['eos_password']) + return devices @pytest.fixture(scope='session') def eos(): @@ -199,10 +204,15 @@ def eos(): def creds(): """ read and yield lab configuration """ files = glob.glob("../ansible/group_vars/lab/*.yml") + files += glob.glob("../ansible/group_vars/all/*.yml") creds = {} for f in files: with open(f) as stream: - creds.update(yaml.safe_load(stream)) + v = yaml.safe_load(stream) + if v is not None: + creds.update(v) + else: + logging.info("skip empty var file {}".format(f)) return creds diff --git a/tests/test_nbr_health.py b/tests/test_nbr_health.py index 9bd55708155..a92d59cfab6 100644 --- a/tests/test_nbr_health.py +++ b/tests/test_nbr_health.py @@ -1,3 +1,4 @@ +import json import pytest import logging logger = logging.getLogger(__name__) @@ -7,7 +8,40 @@ pytest.mark.disable_loganalyzer, ] -def test_neighbors_health(duthost, testbed_devices, eos): +def check_snmp(hostname, mgmt_addr, localhost, community): + logger.info("Check neighbor {}, mgmt ip {} snmp".format(hostname, mgmt_addr)) + res = localhost.snmp_facts(host=mgmt_addr, version='v2c', is_eos=True, community=community) + try: + snmp_data = res['ansible_facts'] + except: + return "neighbor {} has no snmp data".format(hostname) + logger.info("Neighbor {}, sysdescr {}".format(hostname, snmp_data['ansible_sysdescr'])) + +def check_eos_facts(hostname, mgmt_addr, host): + logger.info("Check neighbor {} eos facts".format(hostname)) + res = host.eos_facts() + logger.info("facts: {}".format(json.dumps(res, indent=4))) + try: + eos_facts = res['ansible_facts'] + except: + return "neighbor {} has no eos_facts".format(hostname) + + try: + mgmt_ip = eos_facts['ansible_net_interfaces']['Management0']['ipv4']['address'] + except: + return "neighbor {} managment address not assigned".format(hostname) + + if mgmt_ip != mgmt_addr: + return "neighbor {} management address {} not correct".format(hostname, mgmt_ip) + +def check_bgp_facts(hostname, host): + logger.info("Check neighbor {} bgp facts".format(hostname)) + res = host.eos_command(commands=['show ip bgp sum']) + logger.info("bgp: {}".format(res)) + if not res.has_key('stdout_lines') or u'BGP summary' not in res['stdout_lines'][0][0]: + return "neighbor {} bgp not configured correctly".format(hostname) + +def test_neighbors_health(duthost, testbed_devices, nbrhosts, eos): """Check each neighbor device health""" fails = [] @@ -15,16 +49,19 @@ def test_neighbors_health(duthost, testbed_devices, eos): config_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts'] nei_meta = config_facts.get('DEVICE_NEIGHBOR_METADATA', {}) for k, v in nei_meta.items(): - logger.info("Check neighbor {}, mgmt ip {} snmp".format(k, v['mgmt_addr'])) - res = localhost.snmp_facts(host=v['mgmt_addr'], version='v2c', is_eos=True, community=eos['snmp_rocommunity']) - try: - snmp_data = res['ansible_facts'] - except: - fails.append("neighbor {} has no snmp data".format(k)) - continue - logger.info("Neighbor {}, sysdescr {}".format(k, snmp_data['ansible_sysdescr'])) + failmsg = check_snmp(k, v['mgmt_addr'], localhost, eos['snmp_rocommunity']) + if failmsg: + fails.append(failmsg) + + eoshost = nbrhosts[k] + failmsg = check_eos_facts(k, v['mgmt_addr'], eoshost) + if failmsg: + fails.append(failmsg) - # TODO: check link, bgp, etc. on + failmsg = check_bgp_facts(k, eoshost) + if failmsg: + fails.append(failmsg) + # TODO: check link, bgp, etc. on if len(fails) > 0: pytest.fail("\n".join(fails)) diff --git a/tests/veos.vtb b/tests/veos.vtb index 16506979387..a7ffee0e001 100644 --- a/tests/veos.vtb +++ b/tests/veos.vtb @@ -9,7 +9,34 @@ VM0100 ansible_host=10.250.0.51 VM0101 ansible_host=10.250.0.52 VM0102 ansible_host=10.250.0.53 VM0103 ansible_host=10.250.0.54 - +VM0104 ansible_host=10.250.0.55 +VM0105 ansible_host=10.250.0.56 +VM0106 ansible_host=10.250.0.57 +VM0107 ansible_host=10.250.0.58 +VM0108 ansible_host=10.250.0.59 +VM0109 ansible_host=10.250.0.60 +VM0110 ansible_host=10.250.0.61 +VM0111 ansible_host=10.250.0.62 +VM0112 ansible_host=10.250.0.63 +VM0113 ansible_host=10.250.0.64 +VM0114 ansible_host=10.250.0.65 +VM0115 ansible_host=10.250.0.66 +VM0116 ansible_host=10.250.0.67 +VM0117 ansible_host=10.250.0.68 +VM0118 ansible_host=10.250.0.69 +VM0119 ansible_host=10.250.0.70 +VM0120 ansible_host=10.250.0.71 +VM0121 ansible_host=10.250.0.72 +VM0122 ansible_host=10.250.0.73 +VM0123 ansible_host=10.250.0.74 +VM0124 ansible_host=10.250.0.75 +VM0125 ansible_host=10.250.0.76 +VM0126 ansible_host=10.250.0.77 +VM0127 ansible_host=10.250.0.78 +VM0128 ansible_host=10.250.0.79 +VM0129 ansible_host=10.250.0.80 +VM0130 ansible_host=10.250.0.81 +VM0131 ansible_host=10.250.0.82 [eos:children] vms_1