Skip to content

Commit e42298a

Browse files
authored
[pytest]: add EosHost (nbrhosts) for neighbor devices (#1475)
- also use eos_facts to check eos neighbor device health - add nbrhosts fixture to denote the neighbor devices Signed-off-by: Guohan Lu <[email protected]>
1 parent 733da92 commit e42298a

File tree

4 files changed

+115
-22
lines changed

4 files changed

+115
-22
lines changed

tests/common/devices.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ class AnsibleHostBase(object):
2525
on the host.
2626
"""
2727

28-
def __init__(self, ansible_adhoc, hostname):
28+
def __init__(self, ansible_adhoc, hostname, connection=None):
2929
if hostname == 'localhost':
3030
self.host = ansible_adhoc(inventory='localhost', connection='local', host_pattern=hostname)[hostname]
3131
else:
32-
self.host = ansible_adhoc(become=True)[hostname]
32+
if connection is None:
33+
self.host = ansible_adhoc(become=True)[hostname]
34+
else:
35+
logging.debug("connection {} for {}".format(connection, hostname))
36+
self.host = ansible_adhoc(become=True, connection=connection)[hostname]
3337
self.hostname = hostname
3438

3539
def __getattr__(self, item):
@@ -307,3 +311,18 @@ def get_networking_uptime(self):
307311
except Exception as e:
308312
self.logger.error("Exception raised while getting networking restart time: %s" % repr(e))
309313
return None
314+
315+
class EosHost(AnsibleHostBase):
316+
"""
317+
@summary: Class for Eos switch
318+
319+
For running ansible module on the Eos switch
320+
"""
321+
322+
def __init__(self, ansible_adhoc, hostname, user, passwd, gather_facts=False):
323+
AnsibleHostBase.__init__(self, ansible_adhoc, hostname, connection="network_cli")
324+
evars = { 'ansible_connection':'network_cli', \
325+
'ansible_network_os':'eos', \
326+
'ansible_user': user, \
327+
'ansible_password': passwd }
328+
self.host.options['variable_manager'].extra_vars.update(evars)

tests/conftest.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sys
22
import os
33
import glob
4+
import json
45
import tarfile
56
import logging
67
import time
@@ -12,7 +13,7 @@
1213

1314
from ansible_host import AnsibleHost
1415
from collections import defaultdict
15-
from common.devices import SonicHost, Localhost, PTFHost
16+
from common.devices import SonicHost, Localhost, PTFHost, EosHost
1617

1718
logger = logging.getLogger(__name__)
1819

@@ -123,15 +124,8 @@ def testbed_devices(ansible_adhoc, testbed):
123124
ptf_host = dut.host.options["inventory_manager"].get_host(dut.hostname).get_vars()["ptf_host"]
124125
devices["ptf"] = PTFHost(ansible_adhoc, ptf_host)
125126

126-
# In the future, we can implement more classes for interacting with other testbed devices in the lib.devices
127-
# module. Then, in this fixture, we can initialize more instance of the classes and store the objects in the
128-
# devices dict here. For example, we could have
129-
# from common.devices import FanoutHost
130-
# devices["fanout"] = FanoutHost(ansible_adhoc, testbed["dut"])
131-
132127
return devices
133128

134-
135129
def disable_ssh_timout(dut):
136130
'''
137131
@summary disable ssh session on target dut
@@ -186,6 +180,17 @@ def ptfhost(testbed_devices):
186180

187181
return testbed_devices["ptf"]
188182

183+
@pytest.fixture(scope="module")
184+
def nbrhosts(ansible_adhoc, testbed, creds):
185+
"""
186+
Shortcut fixture for getting PTF host
187+
"""
188+
189+
vm_base = int(testbed['vm_base'][2:])
190+
devices = {}
191+
for k, v in testbed['topo']['properties']['topology']['VMs'].items():
192+
devices[k] = EosHost(ansible_adhoc, "VM%04d" % (vm_base + v['vm_offset']), creds['eos_login'], creds['eos_password'])
193+
return devices
189194

190195
@pytest.fixture(scope='session')
191196
def eos():
@@ -199,10 +204,15 @@ def eos():
199204
def creds():
200205
""" read and yield lab configuration """
201206
files = glob.glob("../ansible/group_vars/lab/*.yml")
207+
files += glob.glob("../ansible/group_vars/all/*.yml")
202208
creds = {}
203209
for f in files:
204210
with open(f) as stream:
205-
creds.update(yaml.safe_load(stream))
211+
v = yaml.safe_load(stream)
212+
if v is not None:
213+
creds.update(v)
214+
else:
215+
logging.info("skip empty var file {}".format(f))
206216
return creds
207217

208218

tests/test_nbr_health.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import pytest
23
import logging
34
logger = logging.getLogger(__name__)
@@ -7,24 +8,60 @@
78
pytest.mark.disable_loganalyzer,
89
]
910

10-
def test_neighbors_health(duthost, testbed_devices, eos):
11+
def check_snmp(hostname, mgmt_addr, localhost, community):
12+
logger.info("Check neighbor {}, mgmt ip {} snmp".format(hostname, mgmt_addr))
13+
res = localhost.snmp_facts(host=mgmt_addr, version='v2c', is_eos=True, community=community)
14+
try:
15+
snmp_data = res['ansible_facts']
16+
except:
17+
return "neighbor {} has no snmp data".format(hostname)
18+
logger.info("Neighbor {}, sysdescr {}".format(hostname, snmp_data['ansible_sysdescr']))
19+
20+
def check_eos_facts(hostname, mgmt_addr, host):
21+
logger.info("Check neighbor {} eos facts".format(hostname))
22+
res = host.eos_facts()
23+
logger.info("facts: {}".format(json.dumps(res, indent=4)))
24+
try:
25+
eos_facts = res['ansible_facts']
26+
except:
27+
return "neighbor {} has no eos_facts".format(hostname)
28+
29+
try:
30+
mgmt_ip = eos_facts['ansible_net_interfaces']['Management0']['ipv4']['address']
31+
except:
32+
return "neighbor {} managment address not assigned".format(hostname)
33+
34+
if mgmt_ip != mgmt_addr:
35+
return "neighbor {} management address {} not correct".format(hostname, mgmt_ip)
36+
37+
def check_bgp_facts(hostname, host):
38+
logger.info("Check neighbor {} bgp facts".format(hostname))
39+
res = host.eos_command(commands=['show ip bgp sum'])
40+
logger.info("bgp: {}".format(res))
41+
if not res.has_key('stdout_lines') or u'BGP summary' not in res['stdout_lines'][0][0]:
42+
return "neighbor {} bgp not configured correctly".format(hostname)
43+
44+
def test_neighbors_health(duthost, testbed_devices, nbrhosts, eos):
1145
"""Check each neighbor device health"""
1246

1347
fails = []
1448
localhost = testbed_devices['localhost']
1549
config_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts']
1650
nei_meta = config_facts.get('DEVICE_NEIGHBOR_METADATA', {})
1751
for k, v in nei_meta.items():
18-
logger.info("Check neighbor {}, mgmt ip {} snmp".format(k, v['mgmt_addr']))
19-
res = localhost.snmp_facts(host=v['mgmt_addr'], version='v2c', is_eos=True, community=eos['snmp_rocommunity'])
20-
try:
21-
snmp_data = res['ansible_facts']
22-
except:
23-
fails.append("neighbor {} has no snmp data".format(k))
24-
continue
25-
logger.info("Neighbor {}, sysdescr {}".format(k, snmp_data['ansible_sysdescr']))
52+
failmsg = check_snmp(k, v['mgmt_addr'], localhost, eos['snmp_rocommunity'])
53+
if failmsg:
54+
fails.append(failmsg)
55+
56+
eoshost = nbrhosts[k]
57+
failmsg = check_eos_facts(k, v['mgmt_addr'], eoshost)
58+
if failmsg:
59+
fails.append(failmsg)
2660

27-
# TODO: check link, bgp, etc. on
61+
failmsg = check_bgp_facts(k, eoshost)
62+
if failmsg:
63+
fails.append(failmsg)
2864

65+
# TODO: check link, bgp, etc. on
2966
if len(fails) > 0:
3067
pytest.fail("\n".join(fails))

tests/veos.vtb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,34 @@ VM0100 ansible_host=10.250.0.51
99
VM0101 ansible_host=10.250.0.52
1010
VM0102 ansible_host=10.250.0.53
1111
VM0103 ansible_host=10.250.0.54
12-
12+
VM0104 ansible_host=10.250.0.55
13+
VM0105 ansible_host=10.250.0.56
14+
VM0106 ansible_host=10.250.0.57
15+
VM0107 ansible_host=10.250.0.58
16+
VM0108 ansible_host=10.250.0.59
17+
VM0109 ansible_host=10.250.0.60
18+
VM0110 ansible_host=10.250.0.61
19+
VM0111 ansible_host=10.250.0.62
20+
VM0112 ansible_host=10.250.0.63
21+
VM0113 ansible_host=10.250.0.64
22+
VM0114 ansible_host=10.250.0.65
23+
VM0115 ansible_host=10.250.0.66
24+
VM0116 ansible_host=10.250.0.67
25+
VM0117 ansible_host=10.250.0.68
26+
VM0118 ansible_host=10.250.0.69
27+
VM0119 ansible_host=10.250.0.70
28+
VM0120 ansible_host=10.250.0.71
29+
VM0121 ansible_host=10.250.0.72
30+
VM0122 ansible_host=10.250.0.73
31+
VM0123 ansible_host=10.250.0.74
32+
VM0124 ansible_host=10.250.0.75
33+
VM0125 ansible_host=10.250.0.76
34+
VM0126 ansible_host=10.250.0.77
35+
VM0127 ansible_host=10.250.0.78
36+
VM0128 ansible_host=10.250.0.79
37+
VM0129 ansible_host=10.250.0.80
38+
VM0130 ansible_host=10.250.0.81
39+
VM0131 ansible_host=10.250.0.82
1340

1441
[eos:children]
1542
vms_1

0 commit comments

Comments
 (0)