Skip to content
L2NMOpenConfigServiceHandler.py 7.36 KiB
Newer Older
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
#
# 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.

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
import json, logging
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from typing import Any, List, Optional, Tuple, Union
from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from common.proto.context_pb2 import ConfigRule, DeviceId, Service
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from common.tools.object_factory.Device import json_device_id
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from common.type_checkers.Checkers import chk_type
from service.service.service_handler_api.Tools import get_device_endpoint_uuids, get_endpoint_matching
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from service.service.service_handler_api._ServiceHandler import _ServiceHandler
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from service.service.service_handler_api.SettingsHandler import SettingsHandler
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
from service.service.task_scheduler.TaskExecutor import TaskExecutor
from .ConfigRules import setup_config_rules, teardown_config_rules

LOGGER = logging.getLogger(__name__)

METRICS_POOL = MetricsPool('Service', 'Handler', labels={'handler': 'l2nm_openconfig'})

class L2NMOpenConfigServiceHandler(_ServiceHandler):
    def __init__(   # pylint: disable=super-init-not-called
        self, service : Service, task_executor : TaskExecutor, **settings
    ) -> None:
        self.__service = service
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        self.__task_executor = task_executor
        self.__settings_handler = SettingsHandler(service.service_config, **settings)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

    @metered_subclass_method(METRICS_POOL)
    def SetEndpoint(
        self, endpoints : List[Tuple[str, str, Optional[str]]], connection_uuid : Optional[str] = None
    ) -> List[Union[bool, Exception]]:
        chk_type('endpoints', endpoints, list)
        if len(endpoints) == 0: return []

        service_uuid = self.__service.service_id.service_uuid.uuid
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        settings = self.__settings_handler.get('/settings')
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

        results = []
        for endpoint in endpoints:
            try:
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
                endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
                endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj)
Pablo Armingol's avatar
Pablo Armingol committed
                endpoint_acls = self.__settings_handler.get_endpoint_acls(device_obj, endpoint_obj)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                endpoint_name = endpoint_obj.name
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

                json_config_rules = setup_config_rules(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                    service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name,
Pablo Armingol's avatar
Pablo Armingol committed
                    settings, endpoint_settings, endpoint_acls)
Pablo Armingol's avatar
Pablo Armingol committed
                if len(json_config_rules) > 0:
Pablo Armingol's avatar
Pablo Armingol committed
                    for json_config_rule in json_config_rules:
                        device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule))
                    self.__task_executor.configure_device(device_obj)

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                results.append(True)
            except Exception as e: # pylint: disable=broad-except
                LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint)))
                results.append(e)

        return results

    @metered_subclass_method(METRICS_POOL)
    def DeleteEndpoint(
        self, endpoints : List[Tuple[str, str, Optional[str]]], connection_uuid : Optional[str] = None
    ) -> List[Union[bool, Exception]]:
        chk_type('endpoints', endpoints, list)
        if len(endpoints) == 0: return []

        service_uuid = self.__service.service_id.service_uuid.uuid
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
        settings = self.__settings_handler.get('/settings')
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

        results = []
        for endpoint in endpoints:
            try:
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
                endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
                endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                endpoint_name = endpoint_obj.name
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed

                json_config_rules = teardown_config_rules(
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                    service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name,
                    settings, endpoint_settings)
Pablo Armingol's avatar
Pablo Armingol committed
                if len(json_config_rules) > 0:
Pablo Armingol's avatar
Pablo Armingol committed
                    for json_config_rule in json_config_rules:
                        device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule))
                    self.__task_executor.configure_device(device_obj)

Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                results.append(True)
            except Exception as e: # pylint: disable=broad-except
                LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint)))
                results.append(e)

        return results

    @metered_subclass_method(METRICS_POOL)
    def SetConstraint(self, constraints : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
        chk_type('constraints', constraints, list)
        if len(constraints) == 0: return []

        msg = '[SetConstraint] Method not implemented. Constraints({:s}) are being ignored.'
        LOGGER.warning(msg.format(str(constraints)))
        return [True for _ in range(len(constraints))]

    @metered_subclass_method(METRICS_POOL)
    def DeleteConstraint(self, constraints : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
        chk_type('constraints', constraints, list)
        if len(constraints) == 0: return []

        msg = '[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored.'
        LOGGER.warning(msg.format(str(constraints)))
        return [True for _ in range(len(constraints))]

    @metered_subclass_method(METRICS_POOL)
    def SetConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
        chk_type('resources', resources, list)
        if len(resources) == 0: return []

        results = []
        for resource in resources:
            try:
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                resource_value = json.loads(resource[1])
                self.__settings_handler.set(resource[0], resource_value)
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                results.append(True)
            except Exception as e: # pylint: disable=broad-except
                LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource)))
                results.append(e)

        return results

    @metered_subclass_method(METRICS_POOL)
    def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
        chk_type('resources', resources, list)
        if len(resources) == 0: return []

        results = []
        for resource in resources:
            try:
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
                self.__settings_handler.delete(resource[0])
Lluis Gifre Renom's avatar
Lluis Gifre Renom committed
            except Exception as e: # pylint: disable=broad-except
                LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource)))
                results.append(e)

        return results