From 81979b25a4d30eae5e14af594606e9c776162bc8 Mon Sep 17 00:00:00 2001 From: Scott Register Date: Thu, 26 Feb 2026 09:16:59 -0800 Subject: [PATCH 1/3] fix: accept alternate mirror profile success response On different IPU control-plane versions, adding a mirror profile can return different success messages; accept both known success outputs. Signed-off-by: Scott Register --- mfd_cli_client/base.py | 7 ++++- tests/unit/test_mfd_cli_client/test_base.py | 32 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mfd_cli_client/base.py b/mfd_cli_client/base.py index 4afdec5..4af9337 100644 --- a/mfd_cli_client/base.py +++ b/mfd_cli_client/base.py @@ -103,6 +103,10 @@ class CliClient(ToolTemplate): tool_executable_name = "cli_client" ALL_USER_PRIORITY_TRAFFIC_CLASS = 8 + _MIRROR_PROFILE_SUCCESS_MARKERS = ( + "command succeeded", + "random mirror profile set", + ) __init__ = os_supported(OSName.LINUX)(ToolTemplate.__init__) @@ -563,7 +567,8 @@ def create_mirror_profile(self, profile_id: int, vsi_id: int) -> None: cmd = f"--modify --config --mir_prof {profile_id} --vsi {vsi_id} --func_valid" output = self.execute_cli_client_command(command=cmd) - if "command succeeded" in output.lower(): + output_lower = output.lower() + if any(marker in output_lower for marker in self._MIRROR_PROFILE_SUCCESS_MARKERS): logger.log(level=log_levels.MODULE_DEBUG, msg=f"Mirror profile ({cmd}) passed.") else: raise CliClientException(f"Mirror profile ({cmd}) failed.") diff --git a/tests/unit/test_mfd_cli_client/test_base.py b/tests/unit/test_mfd_cli_client/test_base.py index 60d0219..851814e 100644 --- a/tests/unit/test_mfd_cli_client/test_base.py +++ b/tests/unit/test_mfd_cli_client/test_base.py @@ -16,6 +16,7 @@ VSIFlowStats, VSIStats, ) +from mfd_cli_client.exceptions import CliClientException from mfd_typing import OSName, MACAddress @@ -705,6 +706,37 @@ def test_create_mirror_profile(self, cli_client, mocker): ] assert cli_client.execute_cli_client_command.mock_calls == cmd + def test_create_mirror_profile_random_profile_set_success(self, cli_client, mocker): + output = dedent( + """\ + No IP address specified, defaulting to localhost + random mirror profile set. + + server finished responding =======================""" + ) + cli_client.execute_cli_client_command = mocker.create_autospec( + cli_client.execute_cli_client_command, return_value=output + ) + cli_client.create_mirror_profile(profile_id=16, vsi_id=1) + cmd = [ + mocker.call(command="--modify --config --mir_prof 16 --vsi 1 --func_valid"), + ] + assert cli_client.execute_cli_client_command.mock_calls == cmd + + def test_create_mirror_profile_failure_output_raises(self, cli_client, mocker): + output = dedent( + """\ + No IP address specified, defaulting to localhost + mirror profile set failed + + server finished responding =======================""" + ) + cli_client.execute_cli_client_command = mocker.create_autospec( + cli_client.execute_cli_client_command, return_value=output + ) + with pytest.raises(CliClientException): + cli_client.create_mirror_profile(profile_id=16, vsi_id=1) + def test_add_psm_vm_rl(self, cli_client, mocker): output = dedent( """\ From cbcb181c7da11fcf237d23942724c166df6e12e1 Mon Sep 17 00:00:00 2001 From: Scott Register Date: Thu, 26 Feb 2026 11:09:20 -0800 Subject: [PATCH 2/3] feat: add delete mirror profile API Add CliClient.delete_mirror_profile() for clearing mirror profile func_valid and validate both known success responses from cli_client. v2: bump ci/cd Signed-off-by: Scott Register --- mfd_cli_client/base.py | 18 ++++++++ tests/unit/test_mfd_cli_client/test_base.py | 48 +++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/mfd_cli_client/base.py b/mfd_cli_client/base.py index 4af9337..3affe3f 100644 --- a/mfd_cli_client/base.py +++ b/mfd_cli_client/base.py @@ -573,6 +573,24 @@ def create_mirror_profile(self, profile_id: int, vsi_id: int) -> None: else: raise CliClientException(f"Mirror profile ({cmd}) failed.") + def delete_mirror_profile(self, profile_id: int, vsi_id: int) -> None: + """ + Disable mirror profile by clearing func_valid for a specific profile/vsi mapping. + + :param profile_id: Mirror profile id (must be >= 16) + :param vsi_id: VSI id currently configured on the mirror profile + """ + if profile_id < 16: + raise CliClientException(f"Mirror profile id {profile_id} must be >=16. Profiles < 16 are reserved.") + + cmd = f"--modify --config --mir_prof {profile_id} --vsi {vsi_id}" + output = self.execute_cli_client_command(command=cmd) + output_lower = output.lower() + if any(marker in output_lower for marker in self._MIRROR_PROFILE_SUCCESS_MARKERS): + logger.log(level=log_levels.MODULE_DEBUG, msg=f"Mirror profile delete ({cmd}) passed.") + else: + raise CliClientException(f"Mirror profile delete ({cmd}) failed.") + def add_psm_vm_rl(self, vm_id: Union[int, str] = 1, limit: int = 10000, burst: int = 2048) -> None: """ Add a VM rate limit in the LAN PSM/Work Scheduler tree. diff --git a/tests/unit/test_mfd_cli_client/test_base.py b/tests/unit/test_mfd_cli_client/test_base.py index 851814e..836815a 100644 --- a/tests/unit/test_mfd_cli_client/test_base.py +++ b/tests/unit/test_mfd_cli_client/test_base.py @@ -737,6 +737,54 @@ def test_create_mirror_profile_failure_output_raises(self, cli_client, mocker): with pytest.raises(CliClientException): cli_client.create_mirror_profile(profile_id=16, vsi_id=1) + def test_delete_mirror_profile(self, cli_client, mocker): + output = dedent( + """\ + No IP address specified, defaulting to localhost + Command Succeeded + + server finished responding =======================""" + ) + cli_client.execute_cli_client_command = mocker.create_autospec( + cli_client.execute_cli_client_command, return_value=output + ) + cli_client.delete_mirror_profile(profile_id=16, vsi_id=1) + cmd = [ + mocker.call(command="--modify --config --mir_prof 16 --vsi 1"), + ] + assert cli_client.execute_cli_client_command.mock_calls == cmd + + def test_delete_mirror_profile_random_profile_set_success(self, cli_client, mocker): + output = dedent( + """\ + No IP address specified, defaulting to localhost + random mirror profile set. + + server finished responding =======================""" + ) + cli_client.execute_cli_client_command = mocker.create_autospec( + cli_client.execute_cli_client_command, return_value=output + ) + cli_client.delete_mirror_profile(profile_id=16, vsi_id=1) + cmd = [ + mocker.call(command="--modify --config --mir_prof 16 --vsi 1"), + ] + assert cli_client.execute_cli_client_command.mock_calls == cmd + + def test_delete_mirror_profile_failure_output_raises(self, cli_client, mocker): + output = dedent( + """\ + No IP address specified, defaulting to localhost + mirror profile set failed + + server finished responding =======================""" + ) + cli_client.execute_cli_client_command = mocker.create_autospec( + cli_client.execute_cli_client_command, return_value=output + ) + with pytest.raises(CliClientException): + cli_client.delete_mirror_profile(profile_id=16, vsi_id=1) + def test_add_psm_vm_rl(self, cli_client, mocker): output = dedent( """\ From 8f103b9abd1ceba55b28274ce114806fe40a5381 Mon Sep 17 00:00:00 2001 From: mfd-intel-bot Date: Mon, 16 Mar 2026 15:58:52 +0000 Subject: [PATCH 3/3] chore: Release v1.12.0 Signed-off-by: mfd-intel-bot --- CHANGELOG.md | 13 +++++++++++++ pyproject.toml | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3638ae8..4e73338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ +## v1.12.0 (2026-03-16) + +### Bug Fixes + +- Accept alternate mirror profile success response + ([`81979b2`](https://github.com/intel/mfd-cli-client/commit/81979b25a4d30eae5e14af594606e9c776162bc8)) + +### Features + +- Add delete mirror profile API + ([`cbcb181`](https://github.com/intel/mfd-cli-client/commit/cbcb181c7da11fcf237d23942724c166df6e12e1)) + + ## v1.11.1 (2026-03-05) ### Bug Fixes diff --git a/pyproject.toml b/pyproject.toml index da92338..2044308 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ dependencies = { file = ["requirements.txt"] } name = "mfd-cli-client" description = "Module for cli_client (command line interface client) utility for the IntelĀ® Infrastructure Processing Unit (IntelĀ® IPU)." requires-python = ">=3.10, <3.14" -version = "1.11.1" +version = "1.12.0" dynamic = ["dependencies"] license-files = ["LICENSE.md", "AUTHORS.md"] readme = {file = "README.md", content-type = "text/markdown"}