Skip to content

Commit 4aa512c

Browse files
authored
[sfputil] Firmware download/upgrade CLI support for QSFP-DD (#1947) (#2349)
* [sfputil] Firmware download/upgrade CLI support for QSFP-DD (#1947) - Description Checking that the running image is switched or not after CDB_run during firmware upgrade process. - Motivation and Context CDB_run will maybe cause several seconds NACK or stretching on i2c bus which depend on the implementation of module vendor, checking the status after CDB_run for compatible with different implementation. * Update unit tests for sfputil. Test : Creating "is_fw_switch_done" test, this function expected to return 1 when 'status' == True and running image('result'[1, 5]) different with committed('result'[2, 6]) one, otherwise return -1. * [sfputil] Firmware download/upgrade CLI support for QSFP-DD (#1947) - Description Adding error judgements in "is_fw_switch_done" function. Update unit tests for "is_fw_switch_done". - Motivation and Context Checking status of images to avoid committing image with a wrong status. * [sfputil] Firmware download/upgrade CLI support for QSFP-DD (#1947) Fixing : Comparing error code with a wrong variable. Refactor : Renaming variables for more suitable its purpose. Refactor : Removing if case which is low correlation with function. Feat : Adding "echo" to display detail result. * Update unit tests for sfputil. * [sfputil] Firmware download/upgrade CLI support for QSFP-DD (#1947) Feat : Reducing frequency of check during "is_fw_switch_done". Refactor : Removing a repeated line.
1 parent f63ef9a commit 4aa512c

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

sfputil/main.py

+57
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,59 @@ def run_firmware(port_name, mode):
12441244

12451245
return status
12461246

1247+
def is_fw_switch_done(port_name):
1248+
"""
1249+
Make sure the run_firmware cmd is done
1250+
@port_name:
1251+
Returns 1 on success, and exit_code = -1 on failure
1252+
"""
1253+
status = 0
1254+
physical_port = logical_port_to_physical_port_index(port_name)
1255+
sfp = platform_chassis.get_sfp(physical_port)
1256+
1257+
try:
1258+
api = sfp.get_xcvr_api()
1259+
except NotImplementedError:
1260+
click.echo("This functionality is currently not implemented for this platform")
1261+
sys.exit(ERROR_NOT_IMPLEMENTED)
1262+
1263+
try:
1264+
MAX_WAIT = 60 # 60s timeout.
1265+
is_busy = 1 # Initial to 1 for entering while loop at least one time.
1266+
timeout_time = time.time() + MAX_WAIT
1267+
while is_busy and (time.time() < timeout_time):
1268+
fw_info = api.get_module_fw_info()
1269+
is_busy = 1 if (fw_info['status'] == False) and (fw_info['result'] is not None) else 0
1270+
time.sleep(2)
1271+
1272+
if fw_info['status'] == True:
1273+
(ImageA, ImageARunning, ImageACommitted, ImageAInvalid,
1274+
ImageB, ImageBRunning, ImageBCommitted, ImageBInvalid) = fw_info['result']
1275+
1276+
if (ImageARunning == 1) and (ImageAInvalid == 1): # ImageA is running, but also invalid.
1277+
click.echo("FW info error : ImageA shows running, but also shows invalid!")
1278+
status = -1 # Abnormal status.
1279+
elif (ImageBRunning == 1) and (ImageBInvalid == 1): # ImageB is running, but also invalid.
1280+
click.echo("FW info error : ImageB shows running, but also shows invalid!")
1281+
status = -1 # Abnormal status.
1282+
elif (ImageARunning == 1) and (ImageACommitted == 0): # ImageA is running, but not committed.
1283+
click.echo("FW images switch successful : ImageA is running")
1284+
status = 1 # run_firmware is done.
1285+
elif (ImageBRunning == 1) and (ImageBCommitted == 0): # ImageB is running, but not committed.
1286+
click.echo("FW images switch successful : ImageB is running")
1287+
status = 1 # run_firmware is done.
1288+
else: # No image is running, or running and committed image is same.
1289+
click.echo("FW info error : Failed to switch into uncommitted image!")
1290+
status = -1 # Failure for Switching images.
1291+
else:
1292+
click.echo("FW switch : Timeout!")
1293+
status = -1 # Timeout or check code error or CDB not supported.
1294+
1295+
except NotImplementedError:
1296+
click.echo("This functionality is not applicable for this transceiver")
1297+
1298+
return status
1299+
12471300
def commit_firmware(port_name):
12481301
status = 0
12491302
physical_port = logical_port_to_physical_port_index(port_name)
@@ -1412,6 +1465,10 @@ def upgrade(port_name, filepath):
14121465

14131466
click.echo("Firmware run in mode 1 successful")
14141467

1468+
if is_fw_switch_done(port_name) != 1:
1469+
click.echo('Failed to switch firmware images!')
1470+
sys.exit(EXIT_FAIL)
1471+
14151472
status = commit_firmware(port_name)
14161473
if status != 1:
14171474
click.echo('Failed to commit firmware! CDB status: {}'.format(status))

tests/sfputil_test.py

+24
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,30 @@ def test_run_firmwre(self, mock_chassis):
706706
status = sfputil.run_firmware("Ethernet0", 1)
707707
assert status == 1
708708

709+
@patch('sfputil.main.platform_chassis')
710+
@patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=1))
711+
@pytest.mark.parametrize("mock_response, expected", [
712+
({'status': False, 'result': None} , -1),
713+
({'status': True, 'result': ("1.0.1", 1, 1, 0, "1.0.2", 0, 0, 0)} , -1),
714+
({'status': True, 'result': ("1.0.1", 0, 0, 0, "1.0.2", 1, 1, 0)} , -1),
715+
({'status': True, 'result': ("1.0.1", 1, 0, 0, "1.0.2", 0, 1, 0)} , 1),
716+
({'status': True, 'result': ("1.0.1", 0, 1, 0, "1.0.2", 1, 0, 0)} , 1),
717+
({'status': True, 'result': ("1.0.1", 1, 0, 1, "1.0.2", 0, 1, 0)} , -1),
718+
({'status': True, 'result': ("1.0.1", 0, 1, 0, "1.0.2", 1, 0, 1)} , -1),
719+
720+
# "is_fw_switch_done" function will waiting until timeout under below condition, so that this test will spend around 1min.
721+
({'status': False, 'result': 0} , -1),
722+
])
723+
def test_is_fw_switch_done(self, mock_chassis, mock_response, expected):
724+
mock_sfp = MagicMock()
725+
mock_api = MagicMock()
726+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api)
727+
mock_sfp.get_presence.return_value = True
728+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
729+
mock_api.get_module_fw_info.return_value = mock_response
730+
status = sfputil.is_fw_switch_done("Ethernet0")
731+
assert status == expected
732+
709733
@patch('sfputil.main.platform_chassis')
710734
@patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=1))
711735
def test_commit_firmwre(self, mock_chassis):

0 commit comments

Comments
 (0)