Skip to content

Commit 4cb5653

Browse files
neethajohnyxieca
authored andcommitted
Preboot sad path automation for n vlan ports (#1096)
Signed-off-by: Neetha John <nejo@microsoft.com>
1 parent 9ddd92e commit 4cb5653

File tree

7 files changed

+127
-37
lines changed

7 files changed

+127
-37
lines changed

ansible/roles/test/files/ptftests/advanced-reboot.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,12 @@ def build_peer_mapping(self):
349349
self.get_neigh_port_info()
350350
self.get_portchannel_info()
351351

352+
def build_vlan_if_port_mapping(self):
353+
content = self.read_json('vlan_ports_file')
354+
if len(content) > 1:
355+
raise Exception("Too many vlans")
356+
return [(ifname, self.port_indices[ifname]) for ifname in content.values()[0]['members']]
357+
352358
def populate_fail_info(self, fails):
353359
for key in fails:
354360
if key not in self.fails:
@@ -386,6 +392,7 @@ def setUp(self):
386392
self.vlan_ports = self.read_vlan_ports()
387393
if self.test_params['preboot_oper'] is not None:
388394
self.build_peer_mapping()
395+
self.test_params['vlan_if_port'] = self.build_vlan_if_port_mapping()
389396

390397
self.vlan_ip_range = self.test_params['vlan_ip_range']
391398
self.default_ip_range = self.test_params['default_ip_range']
@@ -410,8 +417,8 @@ def setUp(self):
410417
self.log("Converted addresses VMs: %s" % str(self.ssh_targets))
411418
if self.preboot_oper is not None:
412419
self.log("Preboot Operations:")
413-
self.pre_handle = sp.PrebootTest(self.preboot_oper, self.ssh_targets, self.portchannel_ports, self.vm_dut_map, self.test_params, self.dut_ssh)
414-
(self.ssh_targets, self.portchannel_ports, self.neigh_vm), (log_info, fails) = self.pre_handle.setup()
420+
self.pre_handle = sp.PrebootTest(self.preboot_oper, self.ssh_targets, self.portchannel_ports, self.vm_dut_map, self.test_params, self.dut_ssh, self.vlan_ports)
421+
(self.ssh_targets, self.portchannel_ports, self.neigh_vm, self.vlan_ports), (log_info, fails) = self.pre_handle.setup()
415422
self.populate_fail_info(fails)
416423
for log in log_info:
417424
self.log(log)

ansible/roles/test/files/ptftests/sad_path.py

Lines changed: 86 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,30 @@
77

88

99
class PrebootTest(object):
10-
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, dut_ssh):
10+
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, dut_ssh, vlan_ports):
1111
self.oper_type = oper_type
1212
self.vm_list = vm_list
1313
self.portchannel_ports = portchannel_ports
1414
self.vm_dut_map = vm_dut_map
1515
self.test_args = test_args
1616
self.dut_ssh = dut_ssh
17+
self.vlan_ports = vlan_ports
1718
self.fails_vm = set()
1819
self.fails_dut = set()
1920
self.log = []
20-
self.shandle = SadOper(self.oper_type, self.vm_list, self.portchannel_ports, self.vm_dut_map, self.test_args, self.dut_ssh)
21+
self.shandle = SadOper(self.oper_type, self.vm_list, self.portchannel_ports, self.vm_dut_map, self.test_args, self.dut_ssh, self.vlan_ports)
2122

2223
def setup(self):
2324
self.shandle.sad_setup(is_up=False)
2425
return self.shandle.retreive_test_info(), self.shandle.retreive_logs()
2526

2627
def verify(self, pre_check=True):
27-
self.shandle.sad_bgp_verify()
28-
if 'lag' in self.oper_type:
29-
self.shandle.sad_lag_verify(pre_check=pre_check)
28+
if 'vlan' in self.oper_type:
29+
self.shandle.verify_vlan_port_state(pre_check=pre_check)
30+
else:
31+
self.shandle.sad_bgp_verify()
32+
if 'lag' in self.oper_type:
33+
self.shandle.sad_lag_verify(pre_check=pre_check)
3034
return self.shandle.retreive_logs()
3135

3236
def revert(self):
@@ -35,14 +39,16 @@ def revert(self):
3539

3640

3741
class SadPath(object):
38-
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args):
42+
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, vlan_ports):
3943
self.oper_type = ''
4044
self.cnt = 1
4145
self.memb_cnt = 0
4246
self.vm_list = vm_list
4347
self.portchannel_ports = portchannel_ports
4448
self.vm_dut_map = vm_dut_map
4549
self.test_args = test_args
50+
self.vlan_ports = vlan_ports
51+
self.vlan_if_port = self.test_args['vlan_if_port']
4652
self.neigh_vms = []
4753
self.neigh_names = dict()
4854
self.vm_handles = dict()
@@ -53,13 +59,16 @@ def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args)
5359
self.fails['dut'] = set()
5460
self.tot_memb_cnt = 0
5561
self.memb_index = 0
62+
self.if_port = []
63+
self.down_vlan_info = []
5664
self.extract_oper_info(oper_type)
5765

5866
def extract_oper_info(self, oper_type):
5967
if oper_type and ':' in oper_type:
6068
temp = oper_type.split(':')
6169
self.oper_type = temp[0]
62-
# get number of VMs where the sad pass oper needs to be done
70+
# get number of VMs where the sad pass oper needs to be done. For vlan_member case,
71+
# this will be the number of down vlan ports
6372
self.cnt = int(temp[1])
6473
if len(temp) > 2:
6574
# get the number of lag members in a portchannel that should be brought down
@@ -122,6 +131,24 @@ def select_member(self):
122131
if self.tot_memb_cnt != 0:
123132
self.memb_index = datetime.datetime.now().day % self.tot_memb_cnt
124133

134+
def select_vlan_ports(self):
135+
self.if_port = sorted(self.vlan_if_port, key=lambda tup: tup[0])
136+
vlan_len = len(self.if_port)
137+
vlan_index = datetime.datetime.now().day % vlan_len if vlan_len > 0 else 0
138+
exceed_len = vlan_index + self.cnt - vlan_len
139+
if exceed_len <= 0:
140+
self.down_vlan_info.extend(self.if_port[vlan_index:vlan_index+self.cnt])
141+
self.if_port = self.if_port[0:vlan_index] + self.if_port[vlan_index+self.cnt:]
142+
else:
143+
self.down_vlan_info.extend(self.if_port[vlan_index:])
144+
self.down_vlan_info.extend(self.if_port[0:exceed_len])
145+
self.if_port = self.if_port[exceed_len:exceed_len + vlan_len - self.cnt]
146+
147+
def down_vlan_ports(self):
148+
# extract the selected vlan ports and mark them down
149+
for item in self.down_vlan_info:
150+
self.vlan_ports.remove(item[1])
151+
125152
def setup(self):
126153
self.select_vm()
127154
self.get_neigh_name()
@@ -146,15 +173,15 @@ def setup(self):
146173
self.log.append('DUT BGP v6: %s' % self.dut_bgps[vm]['v6'])
147174

148175
def retreive_test_info(self):
149-
return self.vm_list, self.portchannel_ports, self.neigh_vms
176+
return self.vm_list, self.portchannel_ports, self.neigh_vms, self.vlan_ports
150177

151178
def retreive_logs(self):
152179
return self.log, self.fails
153180

154181

155182
class SadOper(SadPath):
156-
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, dut_ssh):
157-
super(SadOper, self).__init__(oper_type, vm_list, portchannel_ports, vm_dut_map, test_args)
183+
def __init__(self, oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, dut_ssh, vlan_ports):
184+
super(SadOper, self).__init__(oper_type, vm_list, portchannel_ports, vm_dut_map, test_args, vlan_ports)
158185
self.dut_ssh = dut_ssh
159186
self.dut_needed = dict()
160187
self.lag_members_down = dict()
@@ -185,10 +212,14 @@ def sad_setup(self, is_up=True):
185212
self.log = []
186213

187214
if not is_up:
188-
self.setup()
189-
self.populate_bgp_state()
190-
if 'lag' in self.oper_type:
191-
self.populate_lag_state()
215+
if 'vlan' in self.oper_type:
216+
self.select_vlan_ports()
217+
self.down_vlan_ports()
218+
else:
219+
self.setup()
220+
self.populate_bgp_state()
221+
if 'lag' in self.oper_type:
222+
self.populate_lag_state()
192223

193224
if 'bgp' in self.oper_type:
194225
self.log.append('BGP state change will be for %s' % ", ".join(self.neigh_vms))
@@ -220,6 +251,47 @@ def sad_setup(self, is_up=True):
220251
# wait for sometime for lag members state to sync
221252
time.sleep(120)
222253

254+
elif 'vlan' in self.oper_type:
255+
self.change_vlan_port_state(is_up=is_up)
256+
257+
def change_vlan_port_state(self, is_up=True):
258+
state = ['shutdown', 'startup']
259+
260+
for intf, port in self.down_vlan_info:
261+
if not re.match('Ethernet\d+', intf): continue
262+
self.log.append('Changing state of %s from DUT side to %s' % (intf, state[is_up]))
263+
stdout, stderr, return_code = self.cmd(['ssh', '-oStrictHostKeyChecking=no', self.dut_ssh, 'sudo config interface %s %s' % (state[is_up], intf)])
264+
if return_code != 0:
265+
self.fails['dut'].add('%s: State change not successful from DUT side for %s' % (self.msg_prefix[1 - is_up], intf))
266+
self.fails['dut'].add('%s: Return code: %d' % (self.msg_prefix[1 - is_up], return_code))
267+
self.fails['dut'].add('%s: Stderr: %s' % (self.msg_prefix[1 - is_up], stderr))
268+
else:
269+
self.log.append('State change successful on DUT for %s' % intf)
270+
271+
def verify_vlan_port_state(self, state='down', pre_check=True):
272+
self.log = []
273+
# pattern match "Ethernet252 177,178,179,180 40G 9100 Ethernet64/1 routed down down QSFP28 off"
274+
# extract the admin status
275+
pat = re.compile('(\S+\s+){7}%s' % state)
276+
for intf, port in self.down_vlan_info:
277+
stdout, stderr, return_code = self.cmd(['ssh', '-oStrictHostKeyChecking=no', self.dut_ssh, 'show interfaces status %s' % intf])
278+
if return_code == 0:
279+
for line in stdout.split('\n'):
280+
if intf in line:
281+
is_match = pat.match(line.strip())
282+
if is_match:
283+
self.log.append('Interface state is down as expected on the DUT for %s' % intf)
284+
self.log.append('Pattern check: %s' % line)
285+
break
286+
287+
else:
288+
self.fails['dut'].add('%s: Interface state is not down on the DUT for %s' % (self.msg_prefix[pre_check], intf))
289+
self.fails['dut'].add('%s: Obtained: %s' % (self.msg_prefix[pre_check], line))
290+
else:
291+
self.fails['dut'].add('%s: Retreiving interface %s info from DUT side failed' % (self.msg_prefix[pre_check], intf))
292+
self.fails['dut'].add('%s: Return code: %d' % (self.msg_prefix[pre_check], return_code))
293+
self.fails['dut'].add('%s: Stderr: %s' % (self.msg_prefix[pre_check], stderr))
294+
223295
def change_bgp_dut_state(self, is_up=True):
224296
state = ['shutdown', 'startup']
225297
for vm in self.neigh_vms:

ansible/roles/test/tasks/advanced-reboot.yml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,6 @@
5252
copy: src=roles/test/files/ptftests dest=/root
5353
delegate_to: "{{ ptf_host }}"
5454

55-
- name: Copy arp responder to the PTF container
56-
copy: src=roles/test/files/helpers/arp_responder.py dest=/opt
57-
delegate_to: "{{ ptf_host }}"
58-
59-
- name: Copy arp responder supervisor configuration to the PTF container
60-
template: src=arp_responder.conf.j2 dest=/etc/supervisor/conf.d/arp_responder.conf
61-
vars:
62-
- arp_responder_args: '-e'
63-
delegate_to: "{{ ptf_host }}"
64-
65-
- name: Reread supervisor configuration
66-
shell: supervisorctl reread
67-
delegate_to: "{{ ptf_host }}"
68-
69-
- name: Update supervisor configuration
70-
shell: supervisorctl update
71-
delegate_to: "{{ ptf_host }}"
72-
7355
- name: Remove old keys
7456
file:
7557
path: "{{ item }}"

ansible/roles/test/tasks/advanced_reboot/validate_preboot_list.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
item_cnt: "{{ item.split(':')[-1]|int }}"
33
host_max_len: "{{ vm_hosts|length - 1 }}"
44
member_max_cnt: "{{ minigraph_portchannels.values()[0]['members']|length }}"
5+
vlan_max_cnt: "{{ minigraph_vlans.values()[0]['members']|length - 1 }}"
56

67
- fail: msg="Bgp neigh down count is greater than or equal to number of VM hosts. Current val = {{ item_cnt }} Max val = {{ host_max_len }}"
78
when: "{{ 'bgp_down' in item and item_cnt > host_max_len }}"
@@ -11,3 +12,6 @@
1112

1213
- fail: msg="Lag member count is greater than available number of lag members. Current val = {{ item_cnt }} Available cnt = {{ member_max_cnt }}"
1314
when: "{{ 'lag_member_down' in item and item_cnt > member_max_cnt }}"
15+
16+
- fail: msg="Vlan count is greater than or equal to number of Vlan interfaces. Current val = {{ item_cnt }} Max val = {{ vlan_max_cnt }}"
17+
when: "{{ 'vlan_port_down' in item and item_cnt|int > vlan_max_cnt|int }}"

ansible/roles/test/tasks/ptf_runner_reboot.yml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
11
- block:
2+
- name: Copy arp responder to the PTF container
3+
copy: src=roles/test/files/helpers/arp_responder.py dest=/opt
4+
delegate_to: "{{ ptf_host }}"
5+
6+
- name: Copy arp responder supervisor configuration to the PTF container. No args when there is no preboot type
7+
template: src=arp_responder.conf.j2 dest=/etc/supervisor/conf.d/arp_responder.conf
8+
vars:
9+
- arp_responder_args: '-e'
10+
delegate_to: "{{ ptf_host }}"
11+
when: not item or item == 'None'
12+
13+
- name: Copy arp responder supervisor configuration to the PTF container. Specifying args when there is a preboot type
14+
template: src=arp_responder.conf.j2 dest=/etc/supervisor/conf.d/arp_responder.conf
15+
vars:
16+
- arp_responder_args: '-e -c /tmp/from_t1_{{ item }}.json'
17+
delegate_to: "{{ ptf_host }}"
18+
when: item and item != 'None'
19+
20+
- name: Update supervisor configuration
21+
include: "roles/test/tasks/common_tasks/update_supervisor.yml"
22+
vars:
23+
supervisor_host: "{{ ptf_host }}"
24+
25+
- name: Clear FDB entries on the DUT
26+
command: sonic-clear fdb all
27+
228
- include: ptf_runner.yml
329
vars:
430
ptf_test_name: Advanced-reboot test
@@ -101,7 +127,6 @@
101127
dest: '/tmp/'
102128
flat: yes
103129

104-
105130
- name: Wait for the DUT to be ready for the next test
106131
pause: seconds=420
107132
when: preboot_list|length > 1

ansible/roles/test/tasks/warm-reboot-multi-sad.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# preboot_list format is 'preboot oper type:number of VMS down:number of lag members down'. for non lag member cases, this parameter will be skipped
77
- name: Set vars
88
set_fact:
9-
pre_list: ['neigh_bgp_down:2', 'dut_bgp_down:3', 'dut_lag_down:2', 'neigh_lag_down:3', 'dut_lag_member_down:3:1', 'neigh_lag_member_down:2:1']
9+
pre_list: ['neigh_bgp_down:2', 'dut_bgp_down:3', 'dut_lag_down:2', 'neigh_lag_down:3', 'dut_lag_member_down:3:1', 'neigh_lag_member_down:2:1', 'vlan_port_down:4']
1010
lag_memb_cnt: "{{ minigraph_portchannels.values()[0]['members']|length }}"
1111

1212
- name: Add all lag member down case

ansible/roles/test/tasks/warm-reboot-sad.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
include: advanced-reboot.yml
88
vars:
99
reboot_type: warm-reboot
10-
preboot_list: ['neigh_bgp_down', 'dut_bgp_down', 'dut_lag_down', 'neigh_lag_down']
10+
preboot_list: ['neigh_bgp_down', 'dut_bgp_down', 'dut_lag_down', 'neigh_lag_down', 'dut_lag_member_down:1:1', 'neigh_lag_member_down:1:1', 'vlan_port_down']
1111
preboot_files: "peer_dev_info,neigh_port_info"

0 commit comments

Comments
 (0)