Loading src/service/service/ServiceServiceServicerImpl.py +10 −6 Original line number Diff line number Diff line Loading @@ -96,12 +96,16 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED # pylint: disable=no-member del service.service_endpoint_ids[:] # pylint: disable=no-member for service_endpoint_id in request.service_endpoint_ids: service.service_endpoint_ids.add().CopyFrom(service_endpoint_id) # pylint: disable=no-member for endpoint_id in request.service_endpoint_ids: service.service_endpoint_ids.add().CopyFrom(endpoint_id) # pylint: disable=no-member del service.service_constraints[:] # pylint: disable=no-member for service_constraint in request.service_constraints: service.service_constraints.add().CopyFrom(service_constraint) # pylint: disable=no-member for constraint in request.service_constraints: service.service_constraints.add().CopyFrom(constraint) # pylint: disable=no-member del service.service_config.config_rules[:] # pylint: disable=no-member for config_rule in request.service_config.config_rules: service.service_config.config_rules.add().CopyFrom(config_rule) # pylint: disable=no-member service_id_with_uuids = context_client.SetService(service) service_with_uuids = context_client.GetService(service_id_with_uuids) Loading src/service/service/service_handler_api/SettingsHandler.py 0 → 100644 +88 −0 Original line number Diff line number Diff line # Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) # # 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. import anytree, json, logging from typing import Any, List, Optional, Tuple, Union from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, Device, EndPoint, ServiceConfig from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value LOGGER = logging.getLogger(__name__) class SettingsHandler: def __init__(self, service_config : ServiceConfig, **settings) -> None: self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service_config.config_rules: self.update_config_rule(config_rule) @staticmethod def _config_rule_to_raw(config_rule : ConfigRule) -> Optional[Tuple[int, str, Any]]: action = config_rule.action kind = config_rule.WhichOneof('config_rule') if kind == 'custom': key_or_path = config_rule.custom.resource_key value = config_rule.custom.resource_value try: value = json.loads(value) except: # pylint: disable=bare-except pass elif kind == 'acl': device_uuid = config_rule.acl.endpoint_id.device_id.device_uuid.uuid endpoint_uuid = config_rule.acl.endpoint_id.endpoint_uuid.uuid acl_ruleset_name = config_rule.acl.rule_set.name ACL_KEY_TEMPLATE = '/device[{:s}]/endpoint[{:s}]/acl_ruleset[{:s}]' key_or_path = ACL_KEY_TEMPLATE.format(device_uuid, endpoint_uuid, acl_ruleset_name) value = grpc_message_to_json(config_rule.acl) else: MSG = 'Unsupported Kind({:s}) in ConfigRule({:s})' LOGGER.warning(MSG.format(str(kind), grpc_message_to_json_string(config_rule))) return None return action, key_or_path, value def get(self, key_or_path : Union[str, List[str]], default : Optional[Any] = None) -> Optional[TreeNode]: return get_subnode(self.__resolver, self.__config, key_or_path, default=default) def get_endpoint_settings(self, device : Device, endpoint : EndPoint) -> Optional[TreeNode]: device_keys = device.device_id.device_uuid.uuid, device.name endpoint_keys = endpoint.endpoint_id.endpoint_uuid.uuid, endpoint.name for device_key in device_keys: for endpoint_key in endpoint_keys: endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_key, endpoint_key) endpoint_settings = self.get(endpoint_settings_uri) if endpoint_settings is not None: return endpoint_settings return None def set(self, key_or_path : Union[str, List[str]], value : Any) -> None: set_subnode_value(self.__resolver, self.__config, key_or_path, value) def delete(self, key_or_path : Union[str, List[str]]) -> None: delete_subnode(self.__resolver, self.__config, key_or_path) def update_config_rule(self, config_rule : ConfigRule) -> None: raw_data = SettingsHandler._config_rule_to_raw(config_rule) if raw_data is None: return action, key_or_path, value = raw_data if action == ConfigActionEnum.CONFIGACTION_SET: self.set(key_or_path, value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: self.delete(key_or_path) else: MSG = 'Unsupported Action({:s}) in ConfigRule({:s})' LOGGER.warning(MSG.format(str(action), grpc_message_to_json_string(config_rule))) return src/service/service/service_handler_api/Tools.py +11 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ import functools from typing import Any, List, Union from common.method_wrappers.ServiceExceptions import NotFoundException from common.proto.context_pb2 import Device, EndPoint ACTION_MSG_SET_ENDPOINT = 'Set EndPoint(device_uuid={:s}, endpoint_uuid={:s}, topology_uuid={:s})' ACTION_MSG_DELETE_ENDPOINT = 'Delete EndPoint(device_uuid={:s}, endpoint_uuid={:s}, topology_uuid={:s})' Loading @@ -40,3 +42,12 @@ check_errors_setconstraint = functools.partial(_check_errors, ACTION_MSG_SET_ check_errors_deleteconstraint = functools.partial(_check_errors, ACTION_MSG_DELETE_CONSTRAINT) check_errors_setconfig = functools.partial(_check_errors, ACTION_MSG_SET_CONFIG ) check_errors_deleteconfig = functools.partial(_check_errors, ACTION_MSG_DELETE_CONFIG ) def get_endpoint_matching(device : Device, endpoint_uuid_or_name : str) -> EndPoint: for endpoint in device.device_endpoints: choices = {endpoint.endpoint_id.endpoint_uuid.uuid, endpoint.name} if endpoint_uuid_or_name in choices: return endpoint device_uuid = device.device_id.device_uuid.uuid extra_details = 'Device({:s})'.format(str(device_uuid)) raise NotFoundException('Endpoint', endpoint_uuid_or_name, extra_details=extra_details) src/service/service/service_handlers/l2nm_emulated/L2NMEmulatedServiceHandler.py +23 −38 Original line number Diff line number Diff line Loading @@ -12,14 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. import anytree, json, logging import json, logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, DeviceId, Service from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_length, chk_type from service.service.service_handler_api.Tools import get_endpoint_matching from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.task_scheduler.TaskExecutor import TaskExecutor from .ConfigRules import setup_config_rules, teardown_config_rules Loading Loading @@ -47,22 +48,8 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): self, service : Service, task_executor : TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor # pylint: disable=unused-private-member self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service.service_config.config_rules: action = config_rule.action if config_rule.WhichOneof('config_rule') != 'custom': continue resource_key = config_rule.custom.resource_key resource_value = config_rule.custom.resource_value if action == ConfigActionEnum.CONFIGACTION_SET: try: resource_value = json.loads(resource_value) except: # pylint: disable=bare-except pass set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: delete_subnode(self.__resolver, self.__config, resource_key) self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( Loading @@ -72,7 +59,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -81,17 +68,17 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint))) Loading @@ -107,7 +94,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -116,17 +103,17 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint))) Loading Loading @@ -160,9 +147,8 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, resource_value = resource resource_value = json.loads(resource_value) set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource))) Loading @@ -178,8 +164,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, _ = resource delete_subnode(self.__resolver, self.__config, resource_key) self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource))) results.append(e) Loading src/service/service/service_handlers/l2nm_openconfig/L2NMOpenConfigServiceHandler.py +23 −38 Original line number Diff line number Diff line Loading @@ -12,14 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. import anytree, json, logging import json, logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, DeviceId, Service from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_length, chk_type from service.service.service_handler_api.Tools import get_endpoint_matching from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.task_scheduler.TaskExecutor import TaskExecutor from .ConfigRules import setup_config_rules, teardown_config_rules Loading Loading @@ -47,22 +48,8 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): self, service : Service, task_executor : TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor # pylint: disable=unused-private-member self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service.service_config.config_rules: action = config_rule.action if config_rule.WhichOneof('config_rule') != 'custom': continue resource_key = config_rule.custom.resource_key resource_value = config_rule.custom.resource_value if action == ConfigActionEnum.CONFIGACTION_SET: try: resource_value = json.loads(resource_value) except: # pylint: disable=bare-except pass set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: delete_subnode(self.__resolver, self.__config, resource_key) self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( Loading @@ -72,7 +59,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -81,17 +68,17 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint))) Loading @@ -107,7 +94,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -116,17 +103,17 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint))) Loading Loading @@ -160,9 +147,8 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, resource_value = resource resource_value = json.loads(resource_value) set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource))) Loading @@ -178,8 +164,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, _ = resource delete_subnode(self.__resolver, self.__config, resource_key) self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource))) results.append(e) Loading Loading
src/service/service/ServiceServiceServicerImpl.py +10 −6 Original line number Diff line number Diff line Loading @@ -96,12 +96,16 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED # pylint: disable=no-member del service.service_endpoint_ids[:] # pylint: disable=no-member for service_endpoint_id in request.service_endpoint_ids: service.service_endpoint_ids.add().CopyFrom(service_endpoint_id) # pylint: disable=no-member for endpoint_id in request.service_endpoint_ids: service.service_endpoint_ids.add().CopyFrom(endpoint_id) # pylint: disable=no-member del service.service_constraints[:] # pylint: disable=no-member for service_constraint in request.service_constraints: service.service_constraints.add().CopyFrom(service_constraint) # pylint: disable=no-member for constraint in request.service_constraints: service.service_constraints.add().CopyFrom(constraint) # pylint: disable=no-member del service.service_config.config_rules[:] # pylint: disable=no-member for config_rule in request.service_config.config_rules: service.service_config.config_rules.add().CopyFrom(config_rule) # pylint: disable=no-member service_id_with_uuids = context_client.SetService(service) service_with_uuids = context_client.GetService(service_id_with_uuids) Loading
src/service/service/service_handler_api/SettingsHandler.py 0 → 100644 +88 −0 Original line number Diff line number Diff line # Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/) # # 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. import anytree, json, logging from typing import Any, List, Optional, Tuple, Union from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, Device, EndPoint, ServiceConfig from common.tools.grpc.Tools import grpc_message_to_json, grpc_message_to_json_string from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value LOGGER = logging.getLogger(__name__) class SettingsHandler: def __init__(self, service_config : ServiceConfig, **settings) -> None: self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service_config.config_rules: self.update_config_rule(config_rule) @staticmethod def _config_rule_to_raw(config_rule : ConfigRule) -> Optional[Tuple[int, str, Any]]: action = config_rule.action kind = config_rule.WhichOneof('config_rule') if kind == 'custom': key_or_path = config_rule.custom.resource_key value = config_rule.custom.resource_value try: value = json.loads(value) except: # pylint: disable=bare-except pass elif kind == 'acl': device_uuid = config_rule.acl.endpoint_id.device_id.device_uuid.uuid endpoint_uuid = config_rule.acl.endpoint_id.endpoint_uuid.uuid acl_ruleset_name = config_rule.acl.rule_set.name ACL_KEY_TEMPLATE = '/device[{:s}]/endpoint[{:s}]/acl_ruleset[{:s}]' key_or_path = ACL_KEY_TEMPLATE.format(device_uuid, endpoint_uuid, acl_ruleset_name) value = grpc_message_to_json(config_rule.acl) else: MSG = 'Unsupported Kind({:s}) in ConfigRule({:s})' LOGGER.warning(MSG.format(str(kind), grpc_message_to_json_string(config_rule))) return None return action, key_or_path, value def get(self, key_or_path : Union[str, List[str]], default : Optional[Any] = None) -> Optional[TreeNode]: return get_subnode(self.__resolver, self.__config, key_or_path, default=default) def get_endpoint_settings(self, device : Device, endpoint : EndPoint) -> Optional[TreeNode]: device_keys = device.device_id.device_uuid.uuid, device.name endpoint_keys = endpoint.endpoint_id.endpoint_uuid.uuid, endpoint.name for device_key in device_keys: for endpoint_key in endpoint_keys: endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_key, endpoint_key) endpoint_settings = self.get(endpoint_settings_uri) if endpoint_settings is not None: return endpoint_settings return None def set(self, key_or_path : Union[str, List[str]], value : Any) -> None: set_subnode_value(self.__resolver, self.__config, key_or_path, value) def delete(self, key_or_path : Union[str, List[str]]) -> None: delete_subnode(self.__resolver, self.__config, key_or_path) def update_config_rule(self, config_rule : ConfigRule) -> None: raw_data = SettingsHandler._config_rule_to_raw(config_rule) if raw_data is None: return action, key_or_path, value = raw_data if action == ConfigActionEnum.CONFIGACTION_SET: self.set(key_or_path, value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: self.delete(key_or_path) else: MSG = 'Unsupported Action({:s}) in ConfigRule({:s})' LOGGER.warning(MSG.format(str(action), grpc_message_to_json_string(config_rule))) return
src/service/service/service_handler_api/Tools.py +11 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ import functools from typing import Any, List, Union from common.method_wrappers.ServiceExceptions import NotFoundException from common.proto.context_pb2 import Device, EndPoint ACTION_MSG_SET_ENDPOINT = 'Set EndPoint(device_uuid={:s}, endpoint_uuid={:s}, topology_uuid={:s})' ACTION_MSG_DELETE_ENDPOINT = 'Delete EndPoint(device_uuid={:s}, endpoint_uuid={:s}, topology_uuid={:s})' Loading @@ -40,3 +42,12 @@ check_errors_setconstraint = functools.partial(_check_errors, ACTION_MSG_SET_ check_errors_deleteconstraint = functools.partial(_check_errors, ACTION_MSG_DELETE_CONSTRAINT) check_errors_setconfig = functools.partial(_check_errors, ACTION_MSG_SET_CONFIG ) check_errors_deleteconfig = functools.partial(_check_errors, ACTION_MSG_DELETE_CONFIG ) def get_endpoint_matching(device : Device, endpoint_uuid_or_name : str) -> EndPoint: for endpoint in device.device_endpoints: choices = {endpoint.endpoint_id.endpoint_uuid.uuid, endpoint.name} if endpoint_uuid_or_name in choices: return endpoint device_uuid = device.device_id.device_uuid.uuid extra_details = 'Device({:s})'.format(str(device_uuid)) raise NotFoundException('Endpoint', endpoint_uuid_or_name, extra_details=extra_details)
src/service/service/service_handlers/l2nm_emulated/L2NMEmulatedServiceHandler.py +23 −38 Original line number Diff line number Diff line Loading @@ -12,14 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. import anytree, json, logging import json, logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, DeviceId, Service from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_length, chk_type from service.service.service_handler_api.Tools import get_endpoint_matching from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.task_scheduler.TaskExecutor import TaskExecutor from .ConfigRules import setup_config_rules, teardown_config_rules Loading Loading @@ -47,22 +48,8 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): self, service : Service, task_executor : TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor # pylint: disable=unused-private-member self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service.service_config.config_rules: action = config_rule.action if config_rule.WhichOneof('config_rule') != 'custom': continue resource_key = config_rule.custom.resource_key resource_value = config_rule.custom.resource_value if action == ConfigActionEnum.CONFIGACTION_SET: try: resource_value = json.loads(resource_value) except: # pylint: disable=bare-except pass set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: delete_subnode(self.__resolver, self.__config, resource_key) self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( Loading @@ -72,7 +59,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -81,17 +68,17 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint))) Loading @@ -107,7 +94,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -116,17 +103,17 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint))) Loading Loading @@ -160,9 +147,8 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, resource_value = resource resource_value = json.loads(resource_value) set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource))) Loading @@ -178,8 +164,7 @@ class L2NMEmulatedServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, _ = resource delete_subnode(self.__resolver, self.__config, resource_key) self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource))) results.append(e) Loading
src/service/service/service_handlers/l2nm_openconfig/L2NMOpenConfigServiceHandler.py +23 −38 Original line number Diff line number Diff line Loading @@ -12,14 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. import anytree, json, logging import json, logging from typing import Any, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, DeviceId, Service from common.proto.context_pb2 import ConfigRule, DeviceId, Service from common.tools.object_factory.Device import json_device_id from common.type_checkers.Checkers import chk_length, chk_type from service.service.service_handler_api.Tools import get_endpoint_matching from service.service.service_handler_api._ServiceHandler import _ServiceHandler from service.service.service_handler_api.AnyTreeTools import TreeNode, delete_subnode, get_subnode, set_subnode_value from service.service.service_handler_api.SettingsHandler import SettingsHandler from service.service.task_scheduler.TaskExecutor import TaskExecutor from .ConfigRules import setup_config_rules, teardown_config_rules Loading Loading @@ -47,22 +48,8 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): self, service : Service, task_executor : TaskExecutor, **settings ) -> None: self.__service = service self.__task_executor = task_executor # pylint: disable=unused-private-member self.__resolver = anytree.Resolver(pathattr='name') self.__config = TreeNode('.') for config_rule in service.service_config.config_rules: action = config_rule.action if config_rule.WhichOneof('config_rule') != 'custom': continue resource_key = config_rule.custom.resource_key resource_value = config_rule.custom.resource_value if action == ConfigActionEnum.CONFIGACTION_SET: try: resource_value = json.loads(resource_value) except: # pylint: disable=bare-except pass set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) elif action == ConfigActionEnum.CONFIGACTION_DELETE: delete_subnode(self.__resolver, self.__config, resource_key) self.__task_executor = task_executor self.__settings_handler = SettingsHandler(service.service_config, **settings) @metered_subclass_method(METRICS_POOL) def SetEndpoint( Loading @@ -72,7 +59,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -81,17 +68,17 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = setup_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint))) Loading @@ -107,7 +94,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid settings : TreeNode = get_subnode(self.__resolver, self.__config, '/settings', None) settings = self.__settings_handler.get('/settings') results = [] for endpoint in endpoints: Loading @@ -116,17 +103,17 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): chk_length('endpoint', endpoint, min_length=2, max_length=3) device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now endpoint_settings_uri = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid) endpoint_settings : TreeNode = get_subnode(self.__resolver, self.__config, endpoint_settings_uri, None) 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) json_config_rules = teardown_config_rules( service_uuid, connection_uuid, device_uuid, endpoint_uuid, settings, endpoint_settings) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] del device_obj.device_config.config_rules[:] for json_config_rule in json_config_rules: device.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device) device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule)) self.__task_executor.configure_device(device_obj) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint))) Loading Loading @@ -160,9 +147,8 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, resource_value = resource resource_value = json.loads(resource_value) set_subnode_value(self.__resolver, self.__config, resource_key, resource_value) resource_value = json.loads(resource[1]) self.__settings_handler.set(resource[0], resource_value) results.append(True) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to SetConfig({:s})'.format(str(resource))) Loading @@ -178,8 +164,7 @@ class L2NMOpenConfigServiceHandler(_ServiceHandler): results = [] for resource in resources: try: resource_key, _ = resource delete_subnode(self.__resolver, self.__config, resource_key) self.__settings_handler.delete(resource[0]) except Exception as e: # pylint: disable=broad-except LOGGER.exception('Unable to DeleteConfig({:s})'.format(str(resource))) results.append(e) Loading