Commit 0f928f9c authored by Konstantinos Poulakakis's avatar Konstantinos Poulakakis
Browse files

Refactor automation component. Add plugin mechanism for creating a ZSM Loop....

Refactor automation component. Add plugin mechanism for creating a ZSM Loop. Create some basic test for zsm_handler.
parent 3327ab15
Loading
Loading
Loading
Loading
+10 −3
Original line number Original line Diff line number Diff line
@@ -38,10 +38,17 @@ enum ZSMServiceStateEnum {
  ZSM_REMOVED = 5;       // ZSM loop is removed
  ZSM_REMOVED = 5;       // ZSM loop is removed
}
}


enum ZSMTypeEnum {
  ZSMTYPE_UNKNOWN = 0;
  ZSMTYPE_P4 = 1;
  ZSMTYPE_L2NM = 2;
}

message ZSMCreateRequest {
message ZSMCreateRequest {
  context.ServiceId serviceId = 1;
  context.ServiceId targetServiceId = 1;
  analytics_frontend.Analyzer analyzer = 2;
  context.ServiceId telemetryServiceId = 2;
  policy.PolicyRuleService policy = 3;
  analytics_frontend.Analyzer analyzer = 3;
  policy.PolicyRuleService policy = 4;
}
}


message ZSMCreateUpdate {
message ZSMCreateUpdate {
+1 −2
Original line number Original line Diff line number Diff line
@@ -66,8 +66,7 @@ unit_test automation:
    - sleep 5
    - sleep 5
    - docker ps -a
    - docker ps -a
    - docker logs $IMAGE_NAME
    - docker logs $IMAGE_NAME
    - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_emulated.py --junitxml=/opt/results/${IMAGE_NAME}_report_emulated.xml"
    - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_automation_handlers.py --junitxml=/opt/results/${IMAGE_NAME}_report_ietf_actn.xml"
    - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_ietf_actn.py --junitxml=/opt/results/${IMAGE_NAME}_report_ietf_actn.xml"
    - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing"
    - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing"
  coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
  coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
  after_script:
  after_script:
+22 −0
Original line number Original line Diff line number Diff line
# Plug In A ZSM LOOP

### Initialization
The following requirements should be fulfilled before the execuation of Analytics service.

1. IN ZSMFilterFieldEnum add the new available services
2. In zsm_handlers folder , on the init file and the ZSM_SERVICE_HANDLERS. Give the name of the file and the filter criteria 
3. Add the handler with the same name as you add it in ZSM_SERVICE_HANDLERS.
4. Implement some of those methods in side your handler

```
    def zsmCreate(self,request : ZSMCreateRequest, context : grpc.ServicerContext):
       LOGGER.info('Init zsmUpdate method')
    def zsmUpdate(self):
        LOGGER.info('Init zsmUpdate method')
    def zsmDelete(self):
        LOGGER.info('Init zsmDelete method')
    def ZSMGetById(self):
        LOGGER.info('Init ZSMGetById method')
    def ZSMGetByService(self):
        LOGGER.info('Init ZSMGetByService method')
```
 No newline at end of file
+35 −108
Original line number Original line Diff line number Diff line
@@ -15,22 +15,14 @@
import grpc, json, logging
import grpc, json, logging
from uuid import uuid4
from uuid import uuid4
from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method
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 InvalidArgumentException
from common.method_wrappers.ServiceExceptions import InvalidArgumentException
from common.proto.analytics_frontend_pb2 import Analyzer, AnalyzerId
from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService, ZSMServiceID, ZSMServiceState, ZSMCreateUpdate
from common.proto.automation_pb2 import ZSMCreateRequest, ZSMService, ZSMServiceID, ZSMServiceState, ZSMCreateUpdate
from common.proto.automation_pb2_grpc import AutomationServiceServicer
from common.proto.context_pb2 import Service, ServiceId
from common.proto.context_pb2 import Service, ServiceId
from common.proto.kpi_manager_pb2 import KpiId, KpiDescriptor
from automation.service.zsm_handlers import ZSM_SERVICE_HANDLERS
from common.proto.policy_pb2 import PolicyRuleService, PolicyRuleState
from automation.service.zsm_handler_api.ZSMFilterFields import ZSMFilterFieldEnum , TELEMETRY_SERVICE_TYPE_VALUES, TARGET_SERVICE_TYPE_VALUES , ZSM_FILTER_FIELD_ALLOWED_VALUES
from common.proto.policy_action_pb2 import PolicyRuleAction, PolicyRuleActionConfig
from common.proto.context_pb2 import ServiceTypeEnum , DeviceDriverEnum
from common.proto.policy_condition_pb2 import PolicyRuleCondition
from common.proto.telemetry_frontend_pb2 import Collector, CollectorId

from analytics.frontend.client.AnalyticsFrontendClient import AnalyticsFrontendClient
from automation.client.PolicyClient import PolicyClient
from context.client.ContextClient import ContextClient
from context.client.ContextClient import ContextClient
from kpi_manager.client.KpiManagerClient import KpiManagerClient
from telemetry.frontend.client.TelemetryFrontendClient import TelemetryFrontendClient


LOGGER = logging.getLogger(__name__)
LOGGER = logging.getLogger(__name__)
METRICS_POOL = MetricsPool('Automation', 'RPC')
METRICS_POOL = MetricsPool('Automation', 'RPC')
@@ -41,107 +33,19 @@ class AutomationServiceServicerImpl(AutomationServiceServicer):


    @safe_and_metered_rpc_method(METRICS_POOL,LOGGER)
    @safe_and_metered_rpc_method(METRICS_POOL,LOGGER)
    def ZSMCreate(self, request : ZSMCreateRequest, context : grpc.ServicerContext) -> ZSMService:
    def ZSMCreate(self, request : ZSMCreateRequest, context : grpc.ServicerContext) -> ZSMService:

        # check that service does not exist
        context_client = ContextClient()
        context_client = ContextClient()
        kpi_manager_client = KpiManagerClient()
        policy_client = PolicyClient()
        telemetry_frontend_client = TelemetryFrontendClient()
        analytics_frontend_client = AnalyticsFrontendClient()


        try:
        targetService = context_client.GetService(request.targetServiceId)
            # TODO: Remove static variables(get them from ZSMCreateRequest)
        telemetryService = context_client.GetService(request.telemetryServiceId)
            # TODO: Refactor policy component (remove unnecessary variables)
            LOGGER.info('request ({:s})'.format(str(request)))
            LOGGER.info('serviceId ({:s})'.format(str(request.serviceId)))
            LOGGER.info('analyzer ({:s})'.format(str(request.analyzer)))
            LOGGER.info('policy ({:s})'.format(str(request.policy)))


            #############################################
        handler_cls = self.get_service_handler_based_on_service_types(targetService.service_type , telemetryService.service_type , ZSM_SERVICE_HANDLERS)
            # kpiIdIn = KpiId()
            # kpiIdIn.kpi_id.uuid = request.serviceId.service_uuid.uuid
            #
            # kpiIdOut = KpiId()
            # kpiIdOut.kpi_id.uuid = request.serviceId.context_id.context_uuid.uuid
            #
            # # ##### START Analyzer LAT ################
            # analyzer = Analyzer()
            # analyzer.analyzer_id.analyzer_id.uuid = str(uuid4())
            # analyzer.algorithm_name = 'Test_Aggregate_and_Threshold'  # static
            # analyzer.operation_mode = 2
            # analyzer.input_kpi_ids.append(kpiIdIn)
            # analyzer.output_kpi_ids.append(kpiIdOut)
            #
            # # thresholdStr = service.service_constraints[0].custom.constraint_type
            # _threshold_dict = {
            #     'var_latency': (0, 2),
            #     'task_type': 'AggregationHandler',
            #     "task_parameter": [
            #         {"total": [650, 699]},
            #     ],
            # }
            # analyzer.parameters['thresholds'] = json.dumps(_threshold_dict)
            # analyzer.parameters['window_size'] = "61"
            # analyzer.parameters['window_slider'] = "31"
            #
            # analyzer.batch_min_duration_s = 10.0
            # # analyzer.batch_min_size = 18
            #
            analyzer_id_lat: AnalyzerId = analytics_frontend_client.StartAnalyzer(request.analyzer)
            LOGGER.info('analyzer_id_lat({:s})'.format(str(analyzer_id_lat)))
            # ###########################################################
            #
            # ####### SET Policy LAT ################
            # policy_lat = PolicyRuleService()
            # policy_lat.serviceId.service_uuid.uuid = '66d498ad-5d94-5d90-8cb4-861e30689c64'
            # policy_lat.serviceId.context_id.context_uuid.uuid = '43813baf-195e-5da6-af20-b3d0922e71a7'
            #
            # # PolicyRuleBasic
            # policy_lat.policyRuleBasic.priority = 0
            # policy_lat.policyRuleBasic.policyRuleId.uuid.uuid = str(uuid4())
            # policy_lat.policyRuleBasic.booleanOperator = 2
            #
            # # PolicyRuleAction
            # policyRuleActionConfig = PolicyRuleActionConfig()
            # policyRuleActionConfig.action_key = ""
            # policyRuleActionConfig.action_value = ""
            #
            # policyRuleAction = PolicyRuleAction()
            # policyRuleAction.action = 5
            # policyRuleAction.action_config.append(policyRuleActionConfig)
            # policy_lat.policyRuleBasic.actionList.append(policyRuleAction)
            #
            # # for constraint in service.service_constraints:
            #
            #     # PolicyRuleCondition
            # policyRuleCondition = PolicyRuleCondition()
            # policyRuleCondition.kpiId.kpi_id.uuid = kpiIdOut.kpi_id.uuid
            # policyRuleCondition.numericalOperator = 5
            # policyRuleCondition.kpiValue.floatVal = 300
            #
            # policy_lat.policyRuleBasic.conditionList.append(policyRuleCondition)
            #

            policyRuleCondition = PolicyRuleCondition()
            policyRuleCondition.kpiId.kpi_id.uuid = request.analyzer.output_kpi_ids[0].kpi_id.uuid
            request.policy.policyRuleBasic.conditionList.append(policyRuleCondition)


            policy_rule_state: PolicyRuleState = policy_client.PolicyAddService(request.policy)
        if handler_cls:
            LOGGER.info('policy_rule_state({:s})'.format(str(policy_rule_state)))
            handler_obj = handler_cls()  # instantiate it
            handler_obj.zsmCreate(request , context)
        else:
            LOGGER.info("No matching handler found.")


        except grpc.RpcError as e:
            if e.code() != grpc.StatusCode.NOT_FOUND: raise  # pylint: disable=no-member
            LOGGER.exception('Unable to get Service({:s})'.format(str(request)))
            context_client.close()
            kpi_manager_client.close()
            policy_client.close()
            telemetry_frontend_client.close()
            return None

        context_client.close()
        kpi_manager_client.close()
        policy_client.close()
        telemetry_frontend_client.close()
        return ZSMService()
        return ZSMService()


    @safe_and_metered_rpc_method(METRICS_POOL,LOGGER)
    @safe_and_metered_rpc_method(METRICS_POOL,LOGGER)
@@ -164,3 +68,26 @@ class AutomationServiceServicerImpl(AutomationServiceServicer):
    def ZSMGetByService(self, request : ServiceId, context : grpc.ServicerContext) -> ZSMService:
    def ZSMGetByService(self, request : ServiceId, context : grpc.ServicerContext) -> ZSMService:
        LOGGER.info('NOT IMPLEMENTED ZSMGetByService')
        LOGGER.info('NOT IMPLEMENTED ZSMGetByService')
        return ZSMService()
        return ZSMService()

    def get_service_handler_based_on_service_types(self, targetServiceType ,telemetryServiceType , ZSM_SERVICE_HANDLERS):
        flag = True
        for handler_cls, filters in ZSM_SERVICE_HANDLERS:
            for filter in filters:
                flag = self.check_if_requested_services_pass_filter_criteria(filter , targetServiceType, telemetryServiceType)
            if flag:
                return handler_cls
        return None

    def check_if_requested_services_pass_filter_criteria(self ,filter , targetServiceType , telemetryServiceType):
        flag = True
        for filter_key, filter_value in filter.items():
            if filter_value in ZSM_FILTER_FIELD_ALLOWED_VALUES[filter_key.value]:
                if filter_key.value == ZSMFilterFieldEnum.TARGET_SERVICE_TYPE.value:
                    if filter_value != targetServiceType:
                        flag = False
                elif filter_key.value == ZSMFilterFieldEnum.TELEMETRY_SERVICE_TYPE.value:
                    if filter_value != telemetryServiceType:
                        flag = False
            else:
                flag = False
        return flag
+37 −0
Original line number Original line Diff line number Diff line
# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from enum import Enum
from common.proto.context_pb2 import ServiceTypeEnum

class ZSMFilterFieldEnum(Enum):
    TARGET_SERVICE_TYPE  = 'target_service_type'
    TELEMETRY_SERVICE_TYPE = 'telemetry_service_driver'


TARGET_SERVICE_TYPE_VALUES = {
    ServiceTypeEnum.SERVICETYPE_L2NM,
    ServiceTypeEnum.SERVICETYPE_INT
}

TELEMETRY_SERVICE_TYPE_VALUES = {
    ServiceTypeEnum.SERVICETYPE_INT,
    ServiceTypeEnum.SERVICETYPE_L2NM
}

# Map allowed filter fields to allowed values per Filter field. If no restriction (free text) None is specified
ZSM_FILTER_FIELD_ALLOWED_VALUES = {
    ZSMFilterFieldEnum.TARGET_SERVICE_TYPE.value  : TARGET_SERVICE_TYPE_VALUES,
    ZSMFilterFieldEnum.TELEMETRY_SERVICE_TYPE.value : TELEMETRY_SERVICE_TYPE_VALUES,
}
Loading