Skip to content

Commit a39bbcf

Browse files
added port autoneg test support for testbeds with AOS fanouts (#5206)
What is the motivation for this PR? Port autoneg tests execute fanout commands via a common class FanoutHost which in turn delegates commands to OS specific impl. For now AOS class does not have methods required by port autoneg test. The PR resolves the issue How did you do it? Implemented methods tests require How did you verify/test it? py.test --inventory=../ansible/lab,../ansible/veos --testbed_file=../ansible/testbed.csv --module-path=../ansible/library -v -rA --topology=t1,any platform_tests/test_auto_negotiation.py
1 parent 1494b28 commit a39bbcf

File tree

1 file changed

+98
-3
lines changed

1 file changed

+98
-3
lines changed

tests/common/devices/aos.py

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,31 @@
22
import logging
33
import os
44

5+
from tests.common.devices.base import AnsibleHostBase
6+
import re
57

6-
class AosHost():
8+
def _raise_err(msg):
9+
raise Exception(msg)
10+
11+
class AosHost(AnsibleHostBase):
712
"""
813
@summary: Class for Accton switch
914
For running ansible module on the Accton switch
1015
"""
1116

1217
def __init__(self, ansible_adhoc, hostname, user, passwd, gather_facts=False):
18+
AnsibleHostBase.__init__(self, ansible_adhoc, hostname)
1319
self.hostname = hostname
14-
self.user = user
15-
self.passwd = passwd
1620
self.localhost = ansible_adhoc(inventory='localhost', connection='local', host_pattern="localhost")["localhost"]
1721

22+
self.admin_conn_props = {
23+
'ansible_connection': 'network_cli',
24+
'ansible_network_os':'aos',
25+
'ansible_become_method': 'enable',
26+
'ansible_user': user,
27+
'ansible_password': passwd
28+
}
29+
1830
def _exec_jinja_template(self, task_name, jinja_template):
1931
inventory = 'lab'
2032
ansible_root = '../ansible/'
@@ -97,3 +109,86 @@ def exec_template(self, ansible_root, ansible_playbook, inventory, **kwargs):
97109

98110
if res["localhost"]["rc"] != 0:
99111
raise Exception("Unable to execute template\n{}".format(res["localhost"]["stdout"]))
112+
113+
# delegate AOS related commands to Ansible
114+
def __getattr__(self, module_name):
115+
if not module_name.startswith('aos_'):
116+
return None
117+
self.host.options['variable_manager'].extra_vars.update(self.admin_conn_props)
118+
return super(AosHost, self).__getattr__(module_name)
119+
120+
def _has_cli_cmd_failed(self, cmd_output_obj):
121+
return 'failed' in cmd_output_obj and cmd_output_obj['failed']
122+
123+
def cli_command(self, cmd):
124+
return self.aos_command(commands=[cmd])['stdout'][0]
125+
126+
def get_auto_negotiation_mode(self, port):
127+
return self.get_speed(port) == 'Auto'
128+
129+
def set_auto_negotiation_mode(self, port, enabled):
130+
if self.get_auto_negotiation_mode(port) == enabled:
131+
return True
132+
if enabled:
133+
out = self.aos_config(
134+
lines=['negotiation'],
135+
parents=['interface {}'.format(port)])
136+
else:
137+
out = self.aos_config(
138+
lines=['no negotiation'],
139+
parents=['interface {}'.format(port)])
140+
return not self._has_cli_cmd_failed(out)
141+
142+
def get_speed(self, port):
143+
output = self.cli_command('show interfaces status {}'.format(port))
144+
145+
found_txt = extract_val('Speed-duplex', output)
146+
if found_txt is None:
147+
_raise_err('Not able to extract interface %s speed from output: %s' % (port, output))
148+
149+
return speed_gb_to_mb(found_txt)
150+
151+
def get_supported_speeds(self, port):
152+
"""Get supported speeds for a given interface
153+
154+
Args:
155+
interface_name (str): Interface name
156+
157+
Returns:
158+
list: A list of supported speed strings or None
159+
"""
160+
output = self.cli_command('show interfaces status {}'.format(port))
161+
found_txt = extract_val('Capabilities', output)
162+
163+
if found_txt is None:
164+
_raise_err('Failed to find port speeds list in output: %s' % output)
165+
166+
speed_list = found_txt.split(',')
167+
return list(map(speed_gb_to_mb, speed_list))
168+
169+
def set_speed(self, interface_name, speed):
170+
171+
if not speed:
172+
# other set_speed implementations advertise port speeds when speed=None
173+
# but in AOS autoneg activation and speeds advertisement is done via a single CLI cmd
174+
# so this branch left nop intentionally
175+
return True
176+
speed = speed_mb_to_gb(speed)
177+
out = self.aos_config(
178+
lines=['speed {}'.format(speed)],
179+
parents='interface %s' % interface_name)
180+
return not self._has_cli_cmd_failed(out)
181+
182+
def speed_gb_to_mb(speed):
183+
res = re.search(r'(\d+)(\w)', speed)
184+
if not res:
185+
return speed
186+
speed = res.groups()[0]
187+
return speed + '000'
188+
189+
def speed_mb_to_gb(val):
190+
return '{}Gfull'.format(int(val) // 1000)
191+
192+
def extract_val(prop_name, output):
193+
found_txt = re.search(r'{}\s+:\s+(.+)'.format(prop_name), output)
194+
return found_txt.groups()[0] if found_txt else None

0 commit comments

Comments
 (0)