From 6f83eb0a58ae01f8e1c44aeebe77c88c9f246a10 Mon Sep 17 00:00:00 2001 From: "Georgios P. Katsikas" Date: Thu, 26 Feb 2026 06:53:18 +0000 Subject: [PATCH] fix: automation details --- src/automation/client/AutomationClient.py | 2 +- src/automation/client/PolicyClient.py | 2 +- .../service/AutomationServiceServicerImpl.py | 27 +++++++++--------- src/automation/service/__main__.py | 3 -- .../service/database/AutomationDB.py | 1 - .../service/database/AutomationModel.py | 7 ++--- .../service/database/models/_Base.py | 4 +-- .../service/zsm_handler_api/_ZSMHandler.py | 13 ++++----- .../service/zsm_handlers/P4INTZSMPlugin.py | 28 ++++++++++++++----- .../service/zsm_handlers/__init__.py | 2 +- .../tests/test_automation_handlers.py | 8 +++--- .../automation/descriptors/automation.json | 4 +-- 12 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/automation/client/AutomationClient.py b/src/automation/client/AutomationClient.py index 09a39f71e..64a8d425e 100644 --- a/src/automation/client/AutomationClient.py +++ b/src/automation/client/AutomationClient.py @@ -16,7 +16,7 @@ import grpc, logging from common.Constants import ServiceNameEnum from common.Settings import get_service_host, get_service_port_grpc from common.proto.automation_pb2_grpc import AutomationServiceStub -from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService, ZSMServiceID, ZSMServiceState +from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService from common.tools.client.RetryDecorator import retry, delay_exponential from common.tools.grpc.Tools import grpc_message_to_json_string diff --git a/src/automation/client/PolicyClient.py b/src/automation/client/PolicyClient.py index e364bf17b..f2cc50c15 100644 --- a/src/automation/client/PolicyClient.py +++ b/src/automation/client/PolicyClient.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import grpc, logging, uuid +import grpc, logging from common.Constants import ServiceNameEnum from common.Settings import get_service_host, get_service_port_grpc from common.proto.policy_pb2 import PolicyRuleService, PolicyRuleState diff --git a/src/automation/service/AutomationServiceServicerImpl.py b/src/automation/service/AutomationServiceServicerImpl.py index 7113c268b..5c31b11bd 100644 --- a/src/automation/service/AutomationServiceServicerImpl.py +++ b/src/automation/service/AutomationServiceServicerImpl.py @@ -13,7 +13,6 @@ # limitations under the License. import grpc, logging -from uuid import uuid4 from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method from common.proto.automation_pb2_grpc import AutomationServiceServicer from common.method_wrappers.ServiceExceptions import NotFoundException @@ -23,7 +22,7 @@ from automation.service.database.AutomationDB import AutomationDB from automation.service.database.AutomationModel import AutomationModel from automation.service.zsm_handlers import ZSM_SERVICE_HANDLERS from automation.service.zsm_handler_api.ZSMFilterFields import ( - ZSMFilterFieldEnum, #TELEMETRY_SERVICE_TYPE_VALUES, TARGET_SERVICE_TYPE_VALUES, + ZSMFilterFieldEnum, ZSM_FILTER_FIELD_ALLOWED_VALUES ) from context.client.ContextClient import ContextClient @@ -48,17 +47,19 @@ class AutomationServiceServicerImpl(AutomationServiceServicer): targetService.service_type, telemetryService.service_type, ZSM_SERVICE_HANDLERS ) + response = None if handler_cls: handler_obj = handler_cls() # instantiate it - handler_obj.zsmCreate(request, context) + response = handler_obj.zsmCreate(request, context) else: - LOGGER.info("No matching handler found.") + LOGGER.info("No matching handler found") - response = ZSMService() - automation_id = str(uuid4()) - zsm_to_insert = AutomationModel.convert_Automation_to_row(automation_id , "Test Description") - if self.automation_db_obj.add_row_to_db(zsm_to_insert): - response.zsmServiceId.uuid.uuid = automation_id + zsm_to_insert = AutomationModel.convert_Automation_to_row( + response.zsmServiceId.uuid.uuid, "ZSM service" + ) + if not self.automation_db_obj.add_row_to_db(zsm_to_insert): + LOGGER.error("Failed to insert new ZSM service") + return response return response @@ -76,7 +77,7 @@ class AutomationServiceServicerImpl(AutomationServiceServicer): zsmServiceState = ZSMServiceState() zsmServiceState.zsmServiceState = 5 - zsmServiceState.zsmServiceStateMessage = "Removed id: {:}".format(request) + zsmServiceState.zsmServiceStateMessage = "Removed ZSM ID: {:}".format(request) return zsmServiceState @@ -86,14 +87,14 @@ class AutomationServiceServicerImpl(AutomationServiceServicer): zsm_id_to_search = request.uuid.uuid row = self.automation_db_obj.search_db_row_by_id(AutomationModel, 'zsm_id', zsm_id_to_search) if row is None: - LOGGER.info('No matching row found zsm id: {:}'.format(zsm_id_to_search)) - raise NotFoundException('ZsmID', zsm_id_to_search) + LOGGER.info('No matching row found for ZSM ID: {:}'.format(zsm_id_to_search)) + raise NotFoundException('ZSM ID', zsm_id_to_search) response = AutomationModel.convert_row_to_Automation(row) return response @safe_and_metered_rpc_method(METRICS_POOL,LOGGER) def ZSMGetByService(self, request : ServiceId, context : grpc.ServicerContext) -> ZSMService: - LOGGER.info('NOT IMPLEMENTED ZSMGetByService') + LOGGER.info('ZSMGetByService is not implemented') return ZSMService() def get_service_handler_based_on_service_types( diff --git a/src/automation/service/__main__.py b/src/automation/service/__main__.py index 9d7a2acee..a43b64d0e 100644 --- a/src/automation/service/__main__.py +++ b/src/automation/service/__main__.py @@ -14,7 +14,6 @@ import logging, signal, sys, threading from prometheus_client import start_http_server -# from automation.service.EventEngine import EventEngine from common.Constants import ServiceNameEnum from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, @@ -22,8 +21,6 @@ from common.Settings import ( wait_for_environment_variables ) from .AutomationService import AutomationService -# from common.tools.database.GenericDatabase import Database -# from automation.service.database.AutomationModel import AutomationModel from .database.Engine import Engine from .database.models._Base import rebuild_database diff --git a/src/automation/service/database/AutomationDB.py b/src/automation/service/database/AutomationDB.py index 9b13ebd03..08670989e 100644 --- a/src/automation/service/database/AutomationDB.py +++ b/src/automation/service/database/AutomationDB.py @@ -15,7 +15,6 @@ import logging from common.method_wrappers.Decorator import MetricsPool from common.tools.database.GenericDatabase import Database -from common.method_wrappers.ServiceExceptions import OperationFailedException LOGGER = logging.getLogger(__name__) METRICS_POOL = MetricsPool('Automation', 'Database') diff --git a/src/automation/service/database/AutomationModel.py b/src/automation/service/database/AutomationModel.py index bbf4d5f1f..89e940673 100644 --- a/src/automation/service/database/AutomationModel.py +++ b/src/automation/service/database/AutomationModel.py @@ -14,8 +14,7 @@ import logging from sqlalchemy.dialects.postgresql import UUID -from sqlalchemy import Column, Integer, String, Text -from sqlalchemy.orm import registry +from sqlalchemy import Column, Text from .models._Base import _Base from common.proto.automation_pb2 import ZSMService @@ -25,14 +24,14 @@ class AutomationModel(_Base): __tablename__ = 'automation' zsm_id = Column(UUID(as_uuid=False), primary_key=True) - zsm_description = Column(Text , nullable=False) + zsm_description = Column(Text, nullable=False) # helps in logging the information def __repr__(self): return (f"") @classmethod - def convert_Automation_to_row(cls, uuid , zsm_description): + def convert_Automation_to_row(cls, uuid, zsm_description): """ Create an instance of Automation from a request object. Args: request: The request object containing the data. diff --git a/src/automation/service/database/models/_Base.py b/src/automation/service/database/models/_Base.py index 06c5f6b02..7c019cdd7 100644 --- a/src/automation/service/database/models/_Base.py +++ b/src/automation/service/database/models/_Base.py @@ -14,9 +14,7 @@ import sqlalchemy from typing import Any, List -from sqlalchemy.orm import Session, sessionmaker, declarative_base -from sqlalchemy.sql import text -from sqlalchemy_cockroachdb import run_transaction +from sqlalchemy.orm import declarative_base _Base = declarative_base() diff --git a/src/automation/service/zsm_handler_api/_ZSMHandler.py b/src/automation/service/zsm_handler_api/_ZSMHandler.py index aaf5f9cc5..7dbcb467b 100644 --- a/src/automation/service/zsm_handler_api/_ZSMHandler.py +++ b/src/automation/service/zsm_handler_api/_ZSMHandler.py @@ -13,10 +13,7 @@ # limitations under the License. import grpc , logging -from common.proto.automation_pb2 import ( - ZSMCreateRequest, #ZSMService, - ZSMServiceID, #ZSMServiceState, -) +from common.proto.automation_pb2 import ZSMCreateRequest, ZSMServiceID from common.proto.context_pb2 import ServiceId LOGGER = logging.getLogger(__name__) @@ -25,14 +22,14 @@ class _ZSMHandler: def __init__(self): LOGGER.info('ZSM init') - def zsmCreate(self, request : ZSMCreateRequest, context : grpc.ServicerContext): + def zsmCreate(self, request : ZSMCreateRequest, context : grpc.ServicerContext): # type: ignore LOGGER.info('zsmCreate method') - def zsmDelete(self, request : ZSMServiceID, context : grpc.ServicerContext): + def zsmDelete(self, request : ZSMServiceID, context : grpc.ServicerContext): # type: ignore LOGGER.info('zsmDelete method') - def zsmGetById(self, request : ZSMServiceID, context : grpc.ServicerContext): + def zsmGetById(self, request : ZSMServiceID, context : grpc.ServicerContext): # type: ignore LOGGER.info('zsmGetById method') - def zsmGetByService(self, request : ServiceId, context : grpc.ServicerContext): + def zsmGetByService(self, request : ServiceId, context : grpc.ServicerContext): # type: ignore LOGGER.info('zsmGetByService method') diff --git a/src/automation/service/zsm_handlers/P4INTZSMPlugin.py b/src/automation/service/zsm_handlers/P4INTZSMPlugin.py index 05d866ce8..74694a376 100644 --- a/src/automation/service/zsm_handlers/P4INTZSMPlugin.py +++ b/src/automation/service/zsm_handlers/P4INTZSMPlugin.py @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import grpc , logging +import grpc, logging +from uuid import uuid4 from common.proto.analytics_frontend_pb2 import AnalyzerId from common.proto.policy_pb2 import PolicyRuleState from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService @@ -22,6 +23,7 @@ from automation.client.PolicyClient import PolicyClient from context.client.ContextClient import ContextClient from automation.service.zsm_handler_api._ZSMHandler import _ZSMHandler + LOGGER = logging.getLogger(__name__) class P4INTZSMPlugin(_ZSMHandler): @@ -40,7 +42,7 @@ class P4INTZSMPlugin(_ZSMHandler): LOGGER.exception(f'Unable to get target service:\n{str(target_service_id)}') if ex.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member context_client.close() - return None + return self._zsm_create_response_empty() # Verify the input telemetry service ID try: @@ -49,7 +51,7 @@ class P4INTZSMPlugin(_ZSMHandler): LOGGER.exception(f'Unable to get telemetry service:\n{str(telemetry_service_id)}') if ex.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member context_client.close() - return None + return self._zsm_create_response_empty() # Start an analyzer try: @@ -60,7 +62,7 @@ class P4INTZSMPlugin(_ZSMHandler): if ex.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member context_client.close() analytics_frontend_client.close() - return None + return self._zsm_create_response_empty() # Create a policy try: @@ -69,15 +71,17 @@ class P4INTZSMPlugin(_ZSMHandler): LOGGER.info(f'Policy rule state:\n{policy_rule_state}') except Exception as ex: LOGGER.exception(f'Unable to create policy:\n{str(request.policy)}') - if ex.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member + LOGGER.exception(ex.code()) + # ToDo: Investigate why PolicyAddService throws exception + # if ex.code() != grpc.StatusCode.NOT_FOUND: raise # pylint: disable=no-member context_client.close() policy_client.close() - return None + return self._zsm_create_response_empty() context_client.close() analytics_frontend_client.close() policy_client.close() - return ZSMService() + return self._zsm_create_response(request) def zsmDelete(self): LOGGER.info('zsmDelete method') @@ -87,3 +91,13 @@ class P4INTZSMPlugin(_ZSMHandler): def zsmGetByService(self): LOGGER.info('zsmGetByService method') + + def _zsm_create_response(self, request): + response = ZSMService() + automation_id = str(uuid4()) + response.zsmServiceId.uuid.uuid = automation_id + response.serviceId.service_uuid.uuid = request.target_service_id.service_uuid.uuid + return response + + def _zsm_create_response_empty(self): + return ZSMService() \ No newline at end of file diff --git a/src/automation/service/zsm_handlers/__init__.py b/src/automation/service/zsm_handlers/__init__.py index 6a371461b..dcb533e61 100644 --- a/src/automation/service/zsm_handlers/__init__.py +++ b/src/automation/service/zsm_handlers/__init__.py @@ -19,7 +19,7 @@ from automation.service.zsm_handlers.P4INTZSMPlugin import P4INTZSMPlugin ZSM_SERVICE_HANDLERS = [ (P4INTZSMPlugin, [ { - ZSMFilterFieldEnum.TARGET_SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_L2NM, + ZSMFilterFieldEnum.TARGET_SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_L2NM, ZSMFilterFieldEnum.TELEMETRY_SERVICE_TYPE : ServiceTypeEnum.SERVICETYPE_INT, } ]) diff --git a/src/automation/tests/test_automation_handlers.py b/src/automation/tests/test_automation_handlers.py index 0530e7614..516a6b5e0 100644 --- a/src/automation/tests/test_automation_handlers.py +++ b/src/automation/tests/test_automation_handlers.py @@ -38,7 +38,7 @@ ZSM_SERVICE_HANDLERS = [ def test_get_service_handler_based_on_service_types(): automation = AutomationServiceServicerImpl() - handler_cls = automation.get_service_handler_based_on_service_types(ServiceTypeEnum.SERVICETYPE_INT, ServiceTypeEnum.SERVICETYPE_L2NM , ZSM_SERVICE_HANDLERS) + handler_cls = automation.get_service_handler_based_on_service_types(ServiceTypeEnum.SERVICETYPE_INT, ServiceTypeEnum.SERVICETYPE_L2NM, ZSM_SERVICE_HANDLERS) if handler_cls: assert True else: @@ -48,7 +48,7 @@ def test_get_service_handler_based_on_service_types(): def test_get_service_handler_based_on_service_types_error(): automation = AutomationServiceServicerImpl() - handler_cls = automation.get_service_handler_based_on_service_types(ServiceTypeEnum.SERVICETYPE_INT , ServiceTypeEnum.SERVICETYPE_L2NM , ZSM_SERVICE_HANDLERS) + handler_cls = automation.get_service_handler_based_on_service_types(ServiceTypeEnum.SERVICETYPE_INT, ServiceTypeEnum.SERVICETYPE_L2NM, ZSM_SERVICE_HANDLERS) if handler_cls: assert True else: @@ -61,7 +61,7 @@ def test_check_if_requested_services_pass_filter_criteria(): } automation = AutomationServiceServicerImpl() - flag = automation.check_if_requested_services_pass_filter_criteria(filter , ServiceTypeEnum.SERVICETYPE_L2NM , ServiceTypeEnum.SERVICETYPE_INT) + flag = automation.check_if_requested_services_pass_filter_criteria(filter, ServiceTypeEnum.SERVICETYPE_L2NM, ServiceTypeEnum.SERVICETYPE_INT) if flag: assert True @@ -75,7 +75,7 @@ def test_check_if_requested_services_pass_filter_criteria_error(): } automation = AutomationServiceServicerImpl() - flag = automation.check_if_requested_services_pass_filter_criteria(filter , ServiceTypeEnum.SERVICETYPE_INT , ServiceTypeEnum.SERVICETYPE_L2NM) + flag = automation.check_if_requested_services_pass_filter_criteria(filter, ServiceTypeEnum.SERVICETYPE_INT, ServiceTypeEnum.SERVICETYPE_L2NM) if flag: assert False diff --git a/src/tests/automation/descriptors/automation.json b/src/tests/automation/descriptors/automation.json index 5876de4ae..711dad5c7 100644 --- a/src/tests/automation/descriptors/automation.json +++ b/src/tests/automation/descriptors/automation.json @@ -13,7 +13,7 @@ "thresholds": "{\"task_type\": \"AggregationHandler\",\"task_parameter\": [ {\"avg\": [0, 2500]}]}" }, "input_kpi_ids": [ - {"kpi_id": { "uuid": "b9f915e2-402d-4788-9e7d-6bd1055b5e8b"}} + {"kpi_id": { "uuid": "58ed7d00-eca9-4d02-95d1-52ca9ad2532a"}} ], "output_kpi_ids": [ {"kpi_id": { "uuid": "c45b09d8-c84a-45d8-b4c2-9fa9902d157d"}} @@ -21,7 +21,7 @@ "batch_min_duration_s": 10, "batch_min_size": 5 }, - "policy":{ + "policy": { "serviceId": { "context_id": {"context_uuid": {"uuid": "43813baf-195e-5da6-af20-b3d0922e71a7"}}, "service_uuid": {"uuid": "66d498ad-5d94-5d90-8cb4-861e30689c64"} -- GitLab