From f0ba2c48a398888c83b156f094b06e963662de0c Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Wed, 9 Oct 2024 09:50:29 -0700 Subject: [PATCH 1/9] Add functionality to Dispatcher-agent for handling RPC command Requests from Cloudadapter-agent --- .../dispatcher/dispatcher_class.py | 9 +++++++ .../schedule/rpc_activate_operation.py | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py diff --git a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py index 302362088..92762042c 100644 --- a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py +++ b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py @@ -34,6 +34,7 @@ from inbm_common_lib.exceptions import UrlSecurityException from .schedule.manifest_parser import ScheduleManifestParser, SCHEDULE_SCHEMA_LOCATION +from .schedule.rpc_activate_operation import RpcActivateOperation from .schedule.schedules import Schedule from .schedule.sqlite_manager import SqliteManager from .schedule.apscheduler import APScheduler @@ -259,6 +260,14 @@ def _perform_cmd_type_operation(self, parsed_head: XmlHandler, xml: str) -> Resu elif cmd == "query": self._dispatcher_broker.mqtt_publish(QUERY_CMD_CHANNEL, xml) return PUBLISH_SUCCESS + elif cmd == "rpc": + url = parsed_head.get_children('type/rpc')['fetch'] + name = parsed_head.get_children('type/rpc')['profileName'] + rpc_result = RpcActivateOperation(url, name) + if rpc_result == 'success': + dispatcher._send_result(str(Result(CODE_OK, rpc_result))) + else: + dispatcher._send_result(str(Result(CODE_BAD_REQUEST, rpc_result))) elif cmd == "custom": header = parsed_head.get_children('custom') json_data = header['data'] diff --git a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py new file mode 100644 index 000000000..2fc2e686f --- /dev/null +++ b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py @@ -0,0 +1,24 @@ +""" + Runs the Rpc command with parameters from the manifest. + + Copyright (C) 2024 Intel Corporation + SPDX-License-Identifier: Apache-2.0 +""" +import logging +from typing import Optional +from ..dispatcher import inbm_common_lib.shell_runner.PseudoShellRunner + +logger = logging.getLogger(__name__) + + +class RpcActivateOperation: + def __init__(self, url: str, profile_name: str) -> str: + return self._execute_rpc_activation_cmd(url, profile_name) + + def _execute_rpc_activation(self, url, name) -> str: + command = f"" + (out, err, code) = PseudoShellRunner().run(command) + if code == 0 and out.strip() == 'success': + return "Success" + else: + return "Failure" From daa45adbaa8cee0c53c49d807c95e36edb5d80a3 Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Wed, 9 Oct 2024 09:50:29 -0700 Subject: [PATCH 2/9] Add functionality to Dispatcher-agent for handling RPC command Requests from Cloudadapter-agent --- .../dispatcher/dispatcher_class.py | 9 +++++++ .../schedule/rpc_activate_operation.py | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py diff --git a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py index 302362088..92762042c 100644 --- a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py +++ b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py @@ -34,6 +34,7 @@ from inbm_common_lib.exceptions import UrlSecurityException from .schedule.manifest_parser import ScheduleManifestParser, SCHEDULE_SCHEMA_LOCATION +from .schedule.rpc_activate_operation import RpcActivateOperation from .schedule.schedules import Schedule from .schedule.sqlite_manager import SqliteManager from .schedule.apscheduler import APScheduler @@ -259,6 +260,14 @@ def _perform_cmd_type_operation(self, parsed_head: XmlHandler, xml: str) -> Resu elif cmd == "query": self._dispatcher_broker.mqtt_publish(QUERY_CMD_CHANNEL, xml) return PUBLISH_SUCCESS + elif cmd == "rpc": + url = parsed_head.get_children('type/rpc')['fetch'] + name = parsed_head.get_children('type/rpc')['profileName'] + rpc_result = RpcActivateOperation(url, name) + if rpc_result == 'success': + dispatcher._send_result(str(Result(CODE_OK, rpc_result))) + else: + dispatcher._send_result(str(Result(CODE_BAD_REQUEST, rpc_result))) elif cmd == "custom": header = parsed_head.get_children('custom') json_data = header['data'] diff --git a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py new file mode 100644 index 000000000..5a33ac4d2 --- /dev/null +++ b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py @@ -0,0 +1,24 @@ +""" + Runs the AMT Rpc Activation command. + + Copyright (C) 2024 Intel Corporation + SPDX-License-Identifier: Apache-2.0 +""" +import logging +from typing import Optional +from ..dispatcher import inbm_common_lib.shell_runner.PseudoShellRunner + +logger = logging.getLogger(__name__) + + +class RpcActivateOperation: + def __init__(self, url: str, profile_name: str) -> str: + return self._execute_rpc_activation_cmd(url, profile_name) + + def _execute_rpc_activation_cmd(self, url, name) -> str: + command = f"./rpc activate -u {url}/activate -n --profile {name}" + (out, err, code) = PseudoShellRunner().run(command) + if code == 0 and 'CIRA: Configured' in out: + return "Success" + else: + return "Failure" From 5497c99e1164366d2ae588e946a5dd660329cbbe Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Wed, 9 Oct 2024 12:00:19 -0700 Subject: [PATCH 3/9] Rpc execution command --- .../dispatcher/dispatcher_class.py | 2 +- .../schedule/rpc_activate_operation.py | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py index 92762042c..5047aa336 100644 --- a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py +++ b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py @@ -263,7 +263,7 @@ def _perform_cmd_type_operation(self, parsed_head: XmlHandler, xml: str) -> Resu elif cmd == "rpc": url = parsed_head.get_children('type/rpc')['fetch'] name = parsed_head.get_children('type/rpc')['profileName'] - rpc_result = RpcActivateOperation(url, name) + rpc_result = RpcActivateOperation.execute_rpc_activation_cmd(url, name) if rpc_result == 'success': dispatcher._send_result(str(Result(CODE_OK, rpc_result))) else: diff --git a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py index feddb4819..54d3f5fbf 100644 --- a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py +++ b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py @@ -1,25 +1,31 @@ """ - Runs the AMT Rpc Activation command. + Executes the AMT Rpc Activation command. Copyright (C) 2024 Intel Corporation SPDX-License-Identifier: Apache-2.0 """ -import logging from typing import Optional -from ..dispatcher import inbm_common_lib.shell_runner.PseudoShellRunner +from inbm_common_lib.shell_runner import PseudoShellRunner -logger = logging.getLogger(__name__) class RpcActivateOperation: def __init__(self, url: str, profile_name: str) -> str: - return self._execute_rpc_activation_cmd(url, profile_name) + """RpcActivateOperation class is to execute rpc activate command - def _execute_rpc_activation_cmd(self, url, name) -> str: + @param url: url address of the RPS + @param profile_name: profile_name used for rpc configuration + """ + pass + + def execute_rpc_activation_cmd(self, url, name) -> str: + """Executes the RPC activation command. + + @return: return 'success' if execution succeeds else returns 'Failure' + """ command = f"./rpc activate -u {url}/activate -n --profile {name}" (out, err, code) = PseudoShellRunner().run(command) if code == 0 and 'CIRA: Configured' in out: - return "Success" else: return "Failure" From 64dc92538fe448f10b1d120fe3738d0d775cb5a5 Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Wed, 9 Oct 2024 14:24:19 -0700 Subject: [PATCH 4/9] Change manifest --- .../cloudadapter/cloud/adapters/inbs/operation.py | 10 +--------- .../tests/unit/cloud/adapters/inbs/test_operation.py | 8 ++++---- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/inbm/cloudadapter-agent/cloudadapter/cloud/adapters/inbs/operation.py b/inbm/cloudadapter-agent/cloudadapter/cloud/adapters/inbs/operation.py index 9aa977c48..7007052f2 100644 --- a/inbm/cloudadapter-agent/cloudadapter/cloud/adapters/inbs/operation.py +++ b/inbm/cloudadapter-agent/cloudadapter/cloud/adapters/inbs/operation.py @@ -3,7 +3,6 @@ SPDX-License-Identifier: Apache-2.0 """ - import xml.etree.ElementTree as ET from google.protobuf.timestamp_pb2 import Timestamp from cloudadapter.pb.common.v1.common_pb2 import UpdateSystemSoftwareOperation, RpcActivateOperation, Operation, Schedule @@ -115,7 +114,6 @@ def convert_operation_to_xml_manifests(operation: Operation) -> ET.Element: result.append(xml_manifest) return result - def convert_rpc_activate_operation_to_xml_manifest(operation: RpcActivateOperation) -> str: """Converts a RpcActivateOperation message to an XML manifest string for Dispatcher.""" # Create the root element @@ -123,11 +121,7 @@ def convert_rpc_activate_operation_to_xml_manifest(operation: RpcActivateOperati ET.SubElement(manifest, 'type').text = 'cmd' cmd = ET.SubElement(manifest, 'cmd') - header = ET.SubElement(cmd, 'header') - ET.SubElement(header, 'type').text = 'rpc' - - type = ET.SubElement(cmd, 'type') - rpc = ET.SubElement(type, 'rpc') + rpc = ET.SubElement(cmd, 'rpc') if operation.url: ET.SubElement(rpc, 'fetch').text = operation.url @@ -140,8 +134,6 @@ def convert_rpc_activate_operation_to_xml_manifest(operation: RpcActivateOperati xml_str = ET.tostring(manifest, encoding='utf-8', method='xml').decode('utf-8') return xml_declaration + '\n' + xml_str - - def convert_system_software_operation_to_xml_manifest(operation: UpdateSystemSoftwareOperation) -> str: """Converts a UpdateSystemSoftwareOperation message to an XML manifest string for Dispatcher.""" # Create the root element diff --git a/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py b/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py index df36e46e9..54bb339db 100644 --- a/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py +++ b/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py @@ -37,10 +37,10 @@ ) RPC_OPERATION_LARGE_MANIFEST_XML = ( - '\n' - "cmd
rpc
" - 'http://example.com/serverUDM' - "
" + '\n' + "cmdrpc" + "http://example.com/serverUDM" + "" ) From 27b2345b6bf19d559b4d6b7ebb949ef836f9abfd Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Wed, 9 Oct 2024 15:40:40 -0700 Subject: [PATCH 5/9] Change rpc command to send result instead of publish mqtt --- inbm/dispatcher-agent/dispatcher/dispatcher_class.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py index 5047aa336..b57e4b446 100644 --- a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py +++ b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py @@ -261,13 +261,13 @@ def _perform_cmd_type_operation(self, parsed_head: XmlHandler, xml: str) -> Resu self._dispatcher_broker.mqtt_publish(QUERY_CMD_CHANNEL, xml) return PUBLISH_SUCCESS elif cmd == "rpc": - url = parsed_head.get_children('type/rpc')['fetch'] - name = parsed_head.get_children('type/rpc')['profileName'] + url = parsed_head.get_children('rpc')['fetch'] + name = parsed_head.get_children('rpc')['profileName'] rpc_result = RpcActivateOperation.execute_rpc_activation_cmd(url, name) if rpc_result == 'success': - dispatcher._send_result(str(Result(CODE_OK, rpc_result))) + self._send_result(message= "Successful RPC Activation Operation") else: - dispatcher._send_result(str(Result(CODE_BAD_REQUEST, rpc_result))) + self._send_result(message= "Failed RPC Activation Operation") elif cmd == "custom": header = parsed_head.get_children('custom') json_data = header['data'] From f3b234331a8804add44fe847c0887655c5433269 Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Thu, 10 Oct 2024 14:53:25 -0700 Subject: [PATCH 6/9] Changes and unit tests --- .../schedule/rpc_activate_operation.py | 12 ++++---- .../schedule/test_rpc_activate_operation.py | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py diff --git a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py index 54d3f5fbf..c6c4ce773 100644 --- a/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py +++ b/inbm/dispatcher-agent/dispatcher/schedule/rpc_activate_operation.py @@ -5,25 +5,27 @@ SPDX-License-Identifier: Apache-2.0 """ from typing import Optional +import shlex from inbm_common_lib.shell_runner import PseudoShellRunner class RpcActivateOperation: - def __init__(self, url: str, profile_name: str) -> str: + def __init__(self) -> None: """RpcActivateOperation class is to execute rpc activate command - - @param url: url address of the RPS - @param profile_name: profile_name used for rpc configuration """ pass def execute_rpc_activation_cmd(self, url, name) -> str: """Executes the RPC activation command. + @param url: url address of the RPS + @param name: profile name used for rpc configuration @return: return 'success' if execution succeeds else returns 'Failure' """ - command = f"./rpc activate -u {url}/activate -n --profile {name}" + url = shlex.quote(url) + name = shlex.quote(name) + command = f"rpc activate -u {url}/activate -n --profile {name}" (out, err, code) = PseudoShellRunner().run(command) if code == 0 and 'CIRA: Configured' in out: return "Success" diff --git a/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py b/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py new file mode 100644 index 000000000..71a34b6f8 --- /dev/null +++ b/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py @@ -0,0 +1,28 @@ +""" + Execute Rpc Activation command functionality test. + + Copyright (C) 2024 Intel Corporation + SPDX-License-Identifier: Apache-2.0 +""" +from unittest import TestCase + +from unittest.mock import patch +from dispatcher.schedule.rpc_activate_operation import * + + +class TestRpcActivateOperation(TestCase): + + def setUp(self) -> None: + self.url = "wss://1.1.1.1" + self.profile_name = "profilename" + pass + + @patch("inbm_common_lib.shell_runner.PseudoShellRunner.run", return_value=('Success', "", 0)) + def test_execute_rpc_activation_cmd_success(self, mock_run) -> None: + rpc_result = RpcActivateOperation(self).execute_rpc_activation_cmd(self.url, self.name) + self.assertEqual(rpc_result, 'Success') + + @patch("inbm_common_lib.shell_runner.PseudoShellRunner.run", return_value=('Failure', "", 0)) + def test_execute_rpc_activation_cmd_failure(self, mock_run) -> None: + rpc_result = RpcActivateOperation(self).execute_rpc_activation_cmd(self.url, self.name) + self.assertEqual(rpc_result, 'Failure') \ No newline at end of file From 839f138ff2c54b4eb2cbfdad2fa828ed826c7445 Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Thu, 10 Oct 2024 15:14:39 -0700 Subject: [PATCH 7/9] Add missing argument --- inbm/dispatcher-agent/dispatcher/dispatcher_class.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py index b57e4b446..9875fd976 100644 --- a/inbm/dispatcher-agent/dispatcher/dispatcher_class.py +++ b/inbm/dispatcher-agent/dispatcher/dispatcher_class.py @@ -263,7 +263,7 @@ def _perform_cmd_type_operation(self, parsed_head: XmlHandler, xml: str) -> Resu elif cmd == "rpc": url = parsed_head.get_children('rpc')['fetch'] name = parsed_head.get_children('rpc')['profileName'] - rpc_result = RpcActivateOperation.execute_rpc_activation_cmd(url, name) + rpc_result = RpcActivateOperation().execute_rpc_activation_cmd(url, name) if rpc_result == 'success': self._send_result(message= "Successful RPC Activation Operation") else: From 974e4380c318106da9cd75108f91a5cccf7bff2d Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Thu, 10 Oct 2024 15:19:57 -0700 Subject: [PATCH 8/9] Fix unit test parameters --- .../tests/unit/schedule/test_rpc_activate_operation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py b/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py index 71a34b6f8..fbf91ece9 100644 --- a/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py +++ b/inbm/dispatcher-agent/tests/unit/schedule/test_rpc_activate_operation.py @@ -19,10 +19,10 @@ def setUp(self) -> None: @patch("inbm_common_lib.shell_runner.PseudoShellRunner.run", return_value=('Success', "", 0)) def test_execute_rpc_activation_cmd_success(self, mock_run) -> None: - rpc_result = RpcActivateOperation(self).execute_rpc_activation_cmd(self.url, self.name) + rpc_result = RpcActivateOperation().execute_rpc_activation_cmd(self.url, self.profile_name) self.assertEqual(rpc_result, 'Success') @patch("inbm_common_lib.shell_runner.PseudoShellRunner.run", return_value=('Failure', "", 0)) def test_execute_rpc_activation_cmd_failure(self, mock_run) -> None: - rpc_result = RpcActivateOperation(self).execute_rpc_activation_cmd(self.url, self.name) + rpc_result = RpcActivateOperation().execute_rpc_activation_cmd(self.url, self.profile_name) self.assertEqual(rpc_result, 'Failure') \ No newline at end of file From b60d503184149caecd2c27d1d19ac13ba27331ba Mon Sep 17 00:00:00 2001 From: "Sirlapu, Tejaswini" Date: Mon, 14 Oct 2024 15:56:41 -0700 Subject: [PATCH 9/9] Remove extra character --- .../tests/unit/cloud/adapters/inbs/test_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py b/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py index 54bb339db..91f03abe3 100644 --- a/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py +++ b/inbm/cloudadapter-agent/tests/unit/cloud/adapters/inbs/test_operation.py @@ -37,7 +37,7 @@ ) RPC_OPERATION_LARGE_MANIFEST_XML = ( - '\n' + '' "cmdrpc" "http://example.com/serverUDM" ""