Skip to content

Commit a089e53

Browse files
author
Praveen Chaudhary
authored
[DPB]: Shut down interface before dynamic port breakout (sonic-net#1303)
Changes: -- Shutdown the interfaces after config validation while Dy Port Breakout. -- Validate del ports before calling breakOutPorts API. Signed-off-by: Praveen Chaudhary [email protected] Fixes sonic-net#6646, sonic-net#6631, Signed-off-by: Praveen Chaudhary [email protected]
1 parent 4e45d9c commit a089e53

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

config/config_mgmt.py

+27-3
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,12 @@ def breakOutPort(self, delPorts=list(), portJson=dict(), force=False, \
369369
if_name_map, if_oid_map = port_util.get_interface_oid_map(dataBase)
370370
self.sysLog(syslog.LOG_DEBUG, 'if_name_map {}'.format(if_name_map))
371371

372-
# If we are here, then get ready to update the Config DB, Update
373-
# deletion of Config first, then verify in Asic DB for port deletion,
374-
# then update addition of ports in config DB.
372+
# If we are here, then get ready to update the Config DB as below:
373+
# -- shutdown the ports,
374+
# -- Update deletion of ports in Config DB,
375+
# -- verify Asic DB for port deletion,
376+
# -- then update addition of ports in config DB.
377+
self._shutdownIntf(delPorts)
375378
self.writeConfigDB(delConfigToLoad)
376379
# Verify in Asic DB,
377380
self._verifyAsicDB(db=dataBase, ports=delPorts, portMap=if_name_map, \
@@ -507,6 +510,27 @@ def _addPorts(self, portJson=dict(), loadDefConfig=True):
507510

508511
return configToLoad, True
509512

513+
def _shutdownIntf(self, ports):
514+
"""
515+
Based on the list of Ports, create a dict to shutdown port, update Config DB.
516+
Shut down all the interfaces before deletion.
517+
518+
Parameters:
519+
ports(list): list of ports, which are getting deleted due to DPB.
520+
521+
Returns:
522+
void
523+
"""
524+
shutDownConf = dict(); shutDownConf["PORT"] = dict()
525+
for intf in ports:
526+
shutDownConf["PORT"][intf] = {"admin_status": "down"}
527+
self.sysLog(msg='shutdown Interfaces: {}'.format(shutDownConf))
528+
529+
if len(shutDownConf["PORT"]):
530+
self.writeConfigDB(shutDownConf)
531+
532+
return
533+
510534
def _mergeConfigs(self, D1, D2, uniqueKeys=True):
511535
'''
512536
Merge D2 dict in D1 dict, Note both first and second dict will change.

config/main.py

+6-31
Original file line numberDiff line numberDiff line change
@@ -114,32 +114,6 @@ def _get_breakout_options(ctx, args, incomplete):
114114
all_mode_options = [str(c) for c in breakout_mode_options if incomplete in c]
115115
return all_mode_options
116116

117-
def shutdown_interfaces(ctx, del_intf_dict):
118-
""" shut down all the interfaces before deletion """
119-
for intf in del_intf_dict:
120-
config_db = ctx.obj['config_db']
121-
if clicommon.get_interface_naming_mode() == "alias":
122-
interface_name = interface_alias_to_name(config_db, intf)
123-
if interface_name is None:
124-
click.echo("[ERROR] interface name is None!")
125-
return False
126-
127-
if interface_name_is_valid(config_db, intf) is False:
128-
click.echo("[ERROR] Interface name is invalid. Please enter a valid interface name!!")
129-
return False
130-
131-
port_dict = config_db.get_table('PORT')
132-
if not port_dict:
133-
click.echo("port_dict is None!")
134-
return False
135-
136-
if intf in port_dict:
137-
config_db.mod_entry("PORT", intf, {"admin_status": "down"})
138-
else:
139-
click.secho("[ERROR] Could not get the correct interface name, exiting", fg='red')
140-
return False
141-
return True
142-
143117
def _validate_interface_mode(ctx, breakout_cfg_file, interface_name, target_brkout_mode, cur_brkout_mode):
144118
""" Validate Parent interface and user selected mode before starting deletion or addition process """
145119
breakout_file_input = readJsonFile(breakout_cfg_file)["interfaces"]
@@ -3181,12 +3155,7 @@ def breakout(ctx, interface_name, mode, verbose, force_remove_dependencies, load
31813155
del_intf_dict = {intf: del_ports[intf]["speed"] for intf in del_ports}
31823156

31833157
if del_intf_dict:
3184-
""" shut down all the interface before deletion """
3185-
ret = shutdown_interfaces(ctx, del_intf_dict)
3186-
if not ret:
3187-
raise click.Abort()
31883158
click.echo("\nPorts to be deleted : \n {}".format(json.dumps(del_intf_dict, indent=4)))
3189-
31903159
else:
31913160
click.secho("[ERROR] del_intf_dict is None! No interfaces are there to be deleted", fg='red')
31923161
raise click.Abort()
@@ -3213,6 +3182,12 @@ def breakout(ctx, interface_name, mode, verbose, force_remove_dependencies, load
32133182
del_intf_dict.pop(item)
32143183
add_intf_dict.pop(item)
32153184

3185+
# validate all del_ports before calling breakOutPort
3186+
for intf in del_intf_dict.keys():
3187+
if not interface_name_is_valid(config_db, intf):
3188+
click.secho("[ERROR] Interface name {} is invalid".format(intf))
3189+
raise click.Abort()
3190+
32163191
click.secho("\nFinal list of ports to be deleted : \n {} \nFinal list of ports to be added : \n {}".format(json.dumps(del_intf_dict, indent=4), json.dumps(add_intf_dict, indent=4), fg='green', blink=True))
32173192
if not add_intf_dict:
32183193
click.secho("[ERROR] add_intf_dict is None or empty! No interfaces are there to be added", fg='red')

tests/config_mgmt_test.py

+36-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,41 @@ def test_break_out(self):
7878
self.dpb_port4_4x25G_2x50G_f_l(curConfig)
7979
return
8080

81+
def test_shutdownIntf_call(self):
82+
'''
83+
Verify that _shutdownIntf() is called with deleted ports while calling
84+
breakOutPort()
85+
'''
86+
curConfig = deepcopy(configDbJson)
87+
cmdpb = self.config_mgmt_dpb(curConfig)
88+
89+
# create ARGS
90+
dPorts, pJson = self.generate_args(portIdx=8, laneIdx=73, \
91+
curMode='1x50G(2)+2x25G(2)', newMode='2x50G')
92+
93+
# Try to breakout and see if _shutdownIntf is called
94+
deps, ret = cmdpb.breakOutPort(delPorts=dPorts, portJson=pJson, \
95+
force=True, loadDefConfig=False)
96+
97+
# verify correct function call to writeConfigDB after _shutdownIntf()
98+
assert cmdpb.writeConfigDB.call_count == 3
99+
print(cmdpb.writeConfigDB.call_args_list[0])
100+
(args, kwargs) = cmdpb.writeConfigDB.call_args_list[0]
101+
print(args)
102+
103+
# in case of tuple also, we should have only one element
104+
if type(args) == tuple:
105+
args = args[0]
106+
assert "PORT" in args
107+
108+
# {"admin_status": "down"} should be set for all ports in dPorts
109+
assert len(args["PORT"]) == len(dPorts)
110+
# each port should have {"admin_status": "down"}
111+
for port in args["PORT"].keys():
112+
assert args["PORT"][port]['admin_status'] == 'down'
113+
114+
return
115+
81116
def tearDown(self):
82117
try:
83118
os.remove(config_mgmt.CONFIG_DB_JSON_FILE)
@@ -229,7 +264,7 @@ def checkResult(self, cmdpb, delConfig, addConfig):
229264
void
230265
'''
231266
calls = [mock.call(delConfig), mock.call(addConfig)]
232-
assert cmdpb.writeConfigDB.call_count == 2
267+
assert cmdpb.writeConfigDB.call_count == 3
233268
cmdpb.writeConfigDB.assert_has_calls(calls, any_order=False)
234269
return
235270

@@ -497,7 +532,6 @@ def dpb_port8_4x25G_2x50G_f_l(self, curConfig):
497532
}
498533
}
499534
}
500-
assert cmdpb.writeConfigDB.call_count == 2
501535
self.checkResult(cmdpb, delConfig, addConfig)
502536
self.postUpdateConfig(curConfig, delConfig, addConfig)
503537
return

0 commit comments

Comments
 (0)