From 16e0dae421405c2d6624288be2eee46f8f1e7991 Mon Sep 17 00:00:00 2001 From: mansoca Date: Wed, 23 Nov 2022 09:55:08 +0100 Subject: [PATCH 1/5] First implementation of PolicyService. Not tested Signed-off-by: mansoca --- .../service/database/PolicyRuleModel.py | 55 +++++++++++++++++ .../grpc_server/ContextServiceServicerImpl.py | 60 ++++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/context/service/database/PolicyRuleModel.py diff --git a/src/context/service/database/PolicyRuleModel.py b/src/context/service/database/PolicyRuleModel.py new file mode 100644 index 000000000..268bca284 --- /dev/null +++ b/src/context/service/database/PolicyRuleModel.py @@ -0,0 +1,55 @@ +# 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 logging +from typing import Dict, List, Optional, Tuple +from common.orm.Database import Database +from common.orm.HighLevel import get_object +from common.orm.backend.Tools import key_to_str +from common.orm.fields.EnumeratedField import EnumeratedField +from common.orm.fields.ForeignKeyField import ForeignKeyField +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model +from common.proto.context_pb2 import EndPointId +from .DeviceModel import DeviceModel +from .KpiSampleType import ORM_KpiSampleTypeEnum, grpc_to_enum__kpi_sample_type +from .TopologyModel import TopologyModel + +LOGGER = logging.getLogger(__name__) + + +class PolicyRuleModel(Model): + pk = PrimaryKeyField() + value = StringField(required=True, allow_empty=False) + + def delete(self) -> None: + db_policy_rule_pks = self.references(PolicyRuleModel) + for pk,_ in db_policy_rule_pks: + PolicyRuleModel(self.database, pk).delete() + super().delete() + + def dump_id(self) -> Dict: + if 'service' in self.value: + policy_rule_type = 'service' + else: + policy_rule_type = 'device' + + result = { + 'uuid': self.value[policy_rule_type].uuid + } + return result + + def dump(self) -> Dict: + return self.value diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index 88f7bd8af..b3a2f084a 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -28,13 +28,16 @@ from common.proto.context_pb2 import ( Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) +from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) from common.proto.context_pb2_grpc import ContextServiceServicer +from common.proto.context_policy_pb2_grpc import ContextPolicyServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException from context.service.database.ConfigModel import update_config from context.service.database.ConnectionModel import ConnectionModel, set_path from context.service.database.ConstraintModel import set_constraints from context.service.database.ContextModel import ContextModel +from context.service.database.PolicyRuleModel import PolicyRuleModel from context.service.database.DeviceModel import DeviceModel, grpc_to_enum__device_operational_status, set_drivers from context.service.database.EndPointModel import EndPointModel, set_kpi_sample_types from context.service.database.Events import notify_event @@ -49,6 +52,7 @@ from context.service.database.TopologyModel import TopologyModel from .Constants import ( CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, TOPIC_TOPOLOGY) +from common.tools.grpc.Tools import grpc_message_to_json_string LOGGER = logging.getLogger(__name__) @@ -61,11 +65,12 @@ METHOD_NAMES = [ 'ListLinkIds', 'ListLinks', 'GetLink', 'SetLink', 'RemoveLink', 'GetLinkEvents', 'ListServiceIds', 'ListServices', 'GetService', 'SetService', 'RemoveService', 'GetServiceEvents', 'ListSliceIds', 'ListSlices', 'GetSlice', 'SetSlice', 'RemoveSlice', 'GetSliceEvents', + 'ListPolicyRuleIds', 'ListPolicyRules', 'GetPolicyRule', 'SetPolicyRule', 'RemovePolicyRule', 'UnsetService', 'UnsetSlice', ] METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES) -class ContextServiceServicerImpl(ContextServiceServicer): +class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceServicer): def __init__(self, database : Database, messagebroker : MessageBroker): LOGGER.debug('Creating Servicer...') self.lock = threading.Lock() @@ -73,6 +78,59 @@ class ContextServiceServicerImpl(ContextServiceServicer): self.messagebroker = messagebroker LOGGER.debug('Servicer Created') + # ----- Policy ---------------------------------------------------------------------------------------------------- + @safe_and_metered_rpc_method(METRICS, LOGGER) + def ListPolicyRuleIds(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleIdList: + with self.lock: + db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) + db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) + return PolicyRuleIdList(policies_ids=[db_policy_rule.dump_id() for db_policy_rule in db_policy_rules]) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def ListPolicyRules(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleList: + with self.lock: + db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) + db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) + return PolicyRuleList(contexts=[db_policy_rule.dump() for db_policy_rule in db_policy_rules]) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def GetPolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> PolicyRule: + with self.lock: + policy_rule_uuid = request.uuid + db_policy_rule: PolicyRuleModel = get_object(self.database, PolicyRuleModel, policy_rule_uuid) + return PolicyRule(**db_policy_rule.dump()) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def SetPolicyRule(self, request: PolicyRule, context: grpc.ServicerContext) -> PolicyRuleId: + with self.lock: + policy_rule_type = request.WichOneof('policy_rule') + policy_rule_json = grpc_message_to_json_string(request) + # policy = PolicyRuleModel(**policy_rule_json) + policy_rule_uuid = policy_rule_json[policy_rule_type]['policyRuleBasic'].uuid + + result: Tuple[PolicyRuleModel, bool] = update_or_create_object( + self.database, PolicyRuleModel, policy_rule_uuid, policy_rule_json) + db_policy, updated = result + + event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + dict_policy_id = db_policy.dump_id() + notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'policy_id': dict_policy_id}) + return PolicyRuleId(**dict_policy_id) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def RemovePolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> Empty: + with self.lock: + policy_uuid = request.uuid + db_policy = PolicyRuleModel(self.database, policy_uuid, auto_load=False) + found = db_policy.load() + if not found: + return Empty() + + dict_policy_id = db_policy.dump_id() + db_policy.delete() + event_type = EventTypeEnum.EVENTTYPE_REMOVE + notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_policy_id}) + return Empty() # ----- Context ---------------------------------------------------------------------------------------------------- -- GitLab From 9416c3e40accff65cf6fdab1cb4d7252446a55d3 Mon Sep 17 00:00:00 2001 From: mansoca Date: Wed, 23 Nov 2022 10:19:31 +0100 Subject: [PATCH 2/5] Revert "First implementation of PolicyService." This reverts commit 16e0dae421405c2d6624288be2eee46f8f1e7991. --- .../service/database/PolicyRuleModel.py | 55 ----------------- .../grpc_server/ContextServiceServicerImpl.py | 60 +------------------ 2 files changed, 1 insertion(+), 114 deletions(-) delete mode 100644 src/context/service/database/PolicyRuleModel.py diff --git a/src/context/service/database/PolicyRuleModel.py b/src/context/service/database/PolicyRuleModel.py deleted file mode 100644 index 268bca284..000000000 --- a/src/context/service/database/PolicyRuleModel.py +++ /dev/null @@ -1,55 +0,0 @@ -# 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 logging -from typing import Dict, List, Optional, Tuple -from common.orm.Database import Database -from common.orm.HighLevel import get_object -from common.orm.backend.Tools import key_to_str -from common.orm.fields.EnumeratedField import EnumeratedField -from common.orm.fields.ForeignKeyField import ForeignKeyField -from common.orm.fields.PrimaryKeyField import PrimaryKeyField -from common.orm.fields.StringField import StringField -from common.orm.model.Model import Model -from common.proto.context_pb2 import EndPointId -from .DeviceModel import DeviceModel -from .KpiSampleType import ORM_KpiSampleTypeEnum, grpc_to_enum__kpi_sample_type -from .TopologyModel import TopologyModel - -LOGGER = logging.getLogger(__name__) - - -class PolicyRuleModel(Model): - pk = PrimaryKeyField() - value = StringField(required=True, allow_empty=False) - - def delete(self) -> None: - db_policy_rule_pks = self.references(PolicyRuleModel) - for pk,_ in db_policy_rule_pks: - PolicyRuleModel(self.database, pk).delete() - super().delete() - - def dump_id(self) -> Dict: - if 'service' in self.value: - policy_rule_type = 'service' - else: - policy_rule_type = 'device' - - result = { - 'uuid': self.value[policy_rule_type].uuid - } - return result - - def dump(self) -> Dict: - return self.value diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index b3a2f084a..88f7bd8af 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -28,16 +28,13 @@ from common.proto.context_pb2 import ( Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) -from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) from common.proto.context_pb2_grpc import ContextServiceServicer -from common.proto.context_policy_pb2_grpc import ContextPolicyServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException from context.service.database.ConfigModel import update_config from context.service.database.ConnectionModel import ConnectionModel, set_path from context.service.database.ConstraintModel import set_constraints from context.service.database.ContextModel import ContextModel -from context.service.database.PolicyRuleModel import PolicyRuleModel from context.service.database.DeviceModel import DeviceModel, grpc_to_enum__device_operational_status, set_drivers from context.service.database.EndPointModel import EndPointModel, set_kpi_sample_types from context.service.database.Events import notify_event @@ -52,7 +49,6 @@ from context.service.database.TopologyModel import TopologyModel from .Constants import ( CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, TOPIC_TOPOLOGY) -from common.tools.grpc.Tools import grpc_message_to_json_string LOGGER = logging.getLogger(__name__) @@ -65,12 +61,11 @@ METHOD_NAMES = [ 'ListLinkIds', 'ListLinks', 'GetLink', 'SetLink', 'RemoveLink', 'GetLinkEvents', 'ListServiceIds', 'ListServices', 'GetService', 'SetService', 'RemoveService', 'GetServiceEvents', 'ListSliceIds', 'ListSlices', 'GetSlice', 'SetSlice', 'RemoveSlice', 'GetSliceEvents', - 'ListPolicyRuleIds', 'ListPolicyRules', 'GetPolicyRule', 'SetPolicyRule', 'RemovePolicyRule', 'UnsetService', 'UnsetSlice', ] METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES) -class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceServicer): +class ContextServiceServicerImpl(ContextServiceServicer): def __init__(self, database : Database, messagebroker : MessageBroker): LOGGER.debug('Creating Servicer...') self.lock = threading.Lock() @@ -78,59 +73,6 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer self.messagebroker = messagebroker LOGGER.debug('Servicer Created') - # ----- Policy ---------------------------------------------------------------------------------------------------- - @safe_and_metered_rpc_method(METRICS, LOGGER) - def ListPolicyRuleIds(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleIdList: - with self.lock: - db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) - db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) - return PolicyRuleIdList(policies_ids=[db_policy_rule.dump_id() for db_policy_rule in db_policy_rules]) - - @safe_and_metered_rpc_method(METRICS, LOGGER) - def ListPolicyRules(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleList: - with self.lock: - db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) - db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) - return PolicyRuleList(contexts=[db_policy_rule.dump() for db_policy_rule in db_policy_rules]) - - @safe_and_metered_rpc_method(METRICS, LOGGER) - def GetPolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> PolicyRule: - with self.lock: - policy_rule_uuid = request.uuid - db_policy_rule: PolicyRuleModel = get_object(self.database, PolicyRuleModel, policy_rule_uuid) - return PolicyRule(**db_policy_rule.dump()) - - @safe_and_metered_rpc_method(METRICS, LOGGER) - def SetPolicyRule(self, request: PolicyRule, context: grpc.ServicerContext) -> PolicyRuleId: - with self.lock: - policy_rule_type = request.WichOneof('policy_rule') - policy_rule_json = grpc_message_to_json_string(request) - # policy = PolicyRuleModel(**policy_rule_json) - policy_rule_uuid = policy_rule_json[policy_rule_type]['policyRuleBasic'].uuid - - result: Tuple[PolicyRuleModel, bool] = update_or_create_object( - self.database, PolicyRuleModel, policy_rule_uuid, policy_rule_json) - db_policy, updated = result - - event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE - dict_policy_id = db_policy.dump_id() - notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'policy_id': dict_policy_id}) - return PolicyRuleId(**dict_policy_id) - - @safe_and_metered_rpc_method(METRICS, LOGGER) - def RemovePolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> Empty: - with self.lock: - policy_uuid = request.uuid - db_policy = PolicyRuleModel(self.database, policy_uuid, auto_load=False) - found = db_policy.load() - if not found: - return Empty() - - dict_policy_id = db_policy.dump_id() - db_policy.delete() - event_type = EventTypeEnum.EVENTTYPE_REMOVE - notify_event(self.messagebroker, TOPIC_CONTEXT, event_type, {'context_id': dict_policy_id}) - return Empty() # ----- Context ---------------------------------------------------------------------------------------------------- -- GitLab From 2f4526b858ef8adf2d3ba157fa213d94ad382856 Mon Sep 17 00:00:00 2001 From: mansoca Date: Mon, 28 Nov 2022 09:06:17 +0100 Subject: [PATCH 3/5] Implementation of PolicyService. Lacks events. Signed-off-by: mansoca --- src/common/tools/object_factory/PolicyRule.py | 45 ++++++++ src/context/client/ContextClient.py | 37 ++++++ .../service/database/PolicyRuleModel.py | 35 ++++++ src/context/service/grpc_server/Constants.py | 4 +- .../service/grpc_server/ContextService.py | 2 + .../grpc_server/ContextServiceServicerImpl.py | 64 ++++++++++- src/context/tests/Objects.py | 8 ++ src/context/tests/test_unitary.py | 106 +++++++++++++++++- src/policy/client/PolicyClient.py | 89 +++++++++++++++ src/policy/client/__init__.py | 14 +++ 10 files changed, 398 insertions(+), 6 deletions(-) create mode 100644 src/common/tools/object_factory/PolicyRule.py create mode 100644 src/context/service/database/PolicyRuleModel.py create mode 100644 src/policy/client/PolicyClient.py create mode 100644 src/policy/client/__init__.py diff --git a/src/common/tools/object_factory/PolicyRule.py b/src/common/tools/object_factory/PolicyRule.py new file mode 100644 index 000000000..4157a3f06 --- /dev/null +++ b/src/common/tools/object_factory/PolicyRule.py @@ -0,0 +1,45 @@ +# 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 logging +LOGGER = logging.getLogger(__name__) + +def json_policy_rule_id(policy_rule_uuid: str): + result = {'uuid': {'uuid': policy_rule_uuid}} + return result + + +def json_policy_rule(policy_rule_uuid: str, policy_rule_type: str): + result = {} + basic = { + "policyRuleId": json_policy_rule_id(policy_rule_uuid), + "priority": 1, + "conditionList": [], + "booleanOperator": bool(), + "actionList": [] + } + + if policy_rule_type == 'service': + result["service"] = {} + result["service"]["policyRuleBasic"] = basic + result["service"]["serviceId"] = { + "service_uuid": {"uuid": "uuid-service"}, + "context_id": {"context_uuid": {"uuid": "uuid-context"}}, + } + + else: + result["device"] = {} + result["device"]["policyRuleBasic"] = basic + + return result diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py index da907341f..7b7a039f3 100644 --- a/src/context/client/ContextClient.py +++ b/src/context/client/ContextClient.py @@ -28,6 +28,8 @@ from common.proto.context_pb2 import ( Slice, SliceEvent, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) from common.proto.context_pb2_grpc import ContextServiceStub +from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub +from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) LOGGER = logging.getLogger(__name__) MAX_RETRIES = 15 @@ -42,17 +44,52 @@ class ContextClient: LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) self.channel = None self.stub = None + self.policy_stub = None self.connect() LOGGER.debug('Channel created') def connect(self): self.channel = grpc.insecure_channel(self.endpoint) self.stub = ContextServiceStub(self.channel) + self.policy_stub = ContextPolicyServiceStub(self.channel) def close(self): if self.channel is not None: self.channel.close() self.channel = None self.stub = None + self.policy_stub = None + + + @RETRY_DECORATOR + def ListPolicyRuleIds(self, request: Empty) -> PolicyRuleIdList: + LOGGER.debug('ListPolicyRuleIds request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.ListPolicyRuleIds(request) + LOGGER.debug('ListPolicyRuleIds result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def ListPolicyRules(self, request: Empty) -> PolicyRuleList: + LOGGER.debug('ListPolicyRules request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.ListPolicyRules(request) + LOGGER.debug('ListPolicyRules result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def GetPolicyRule(self, request: PolicyRuleId) -> PolicyRule: + LOGGER.info('GetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.GetPolicyRule(request) + LOGGER.info('GetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def SetPolicyRule(self, request: PolicyRule) -> PolicyRuleId: + LOGGER.debug('SetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.SetPolicyRule(request) + LOGGER.debug('SetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def RemovePolicyRule(self, request: PolicyRuleId) -> Empty: + LOGGER.debug('RemovePolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.RemovePolicyRule(request) + LOGGER.debug('RemovePolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response @RETRY_DECORATOR def ListContextIds(self, request: Empty) -> ContextIdList: diff --git a/src/context/service/database/PolicyRuleModel.py b/src/context/service/database/PolicyRuleModel.py new file mode 100644 index 000000000..02adbfa07 --- /dev/null +++ b/src/context/service/database/PolicyRuleModel.py @@ -0,0 +1,35 @@ +# 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 logging +import json +from typing import Dict, List, Optional, Tuple +from common.orm.fields.PrimaryKeyField import PrimaryKeyField +from common.orm.fields.StringField import StringField +from common.orm.model.Model import Model + +LOGGER = logging.getLogger(__name__) + + +class PolicyRuleModel(Model): + pk = PrimaryKeyField() + value = StringField(required=True, allow_empty=False) + + def dump_id(self) -> Dict: + return { + "uuid": {"uuid": self.pk} + } + + def dump(self) -> Dict: + return json.loads(self.value) diff --git a/src/context/service/grpc_server/Constants.py b/src/context/service/grpc_server/Constants.py index 9d7c886c7..25a2fce40 100644 --- a/src/context/service/grpc_server/Constants.py +++ b/src/context/service/grpc_server/Constants.py @@ -19,7 +19,9 @@ TOPIC_DEVICE = 'device' TOPIC_LINK = 'link' TOPIC_SERVICE = 'service' TOPIC_SLICE = 'slice' +TOPIC_POLICY = 'policy' -TOPICS = {TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_TOPOLOGY, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE} +TOPICS = {TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_TOPOLOGY, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, + TOPIC_POLICY} CONSUME_TIMEOUT = 0.5 # seconds diff --git a/src/context/service/grpc_server/ContextService.py b/src/context/service/grpc_server/ContextService.py index 1b54ec540..5d4dd8bb9 100644 --- a/src/context/service/grpc_server/ContextService.py +++ b/src/context/service/grpc_server/ContextService.py @@ -17,6 +17,7 @@ from common.Settings import get_service_port_grpc from common.message_broker.MessageBroker import MessageBroker from common.orm.Database import Database from common.proto.context_pb2_grpc import add_ContextServiceServicer_to_server +from common.proto.context_policy_pb2_grpc import add_ContextPolicyServiceServicer_to_server from common.tools.service.GenericGrpcService import GenericGrpcService from .ContextServiceServicerImpl import ContextServiceServicerImpl @@ -31,3 +32,4 @@ class ContextService(GenericGrpcService): def install_servicers(self): add_ContextServiceServicer_to_server(self.context_servicer, self.server) + add_ContextPolicyServiceServicer_to_server(self.context_servicer, self.server) diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index 88f7bd8af..3cd8aff5c 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -28,13 +28,16 @@ from common.proto.context_pb2 import ( Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) +from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) from common.proto.context_pb2_grpc import ContextServiceServicer +from common.proto.context_policy_pb2_grpc import ContextPolicyServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException from context.service.database.ConfigModel import update_config from context.service.database.ConnectionModel import ConnectionModel, set_path from context.service.database.ConstraintModel import set_constraints from context.service.database.ContextModel import ContextModel +from context.service.database.PolicyRuleModel import PolicyRuleModel from context.service.database.DeviceModel import DeviceModel, grpc_to_enum__device_operational_status, set_drivers from context.service.database.EndPointModel import EndPointModel, set_kpi_sample_types from context.service.database.Events import notify_event @@ -48,7 +51,8 @@ from context.service.database.SliceModel import SliceModel, grpc_to_enum__slice_ from context.service.database.TopologyModel import TopologyModel from .Constants import ( CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, - TOPIC_TOPOLOGY) + TOPIC_TOPOLOGY, TOPIC_POLICY) +from common.tools.grpc.Tools import grpc_message_to_json_string, grpc_message_to_json LOGGER = logging.getLogger(__name__) @@ -61,11 +65,12 @@ METHOD_NAMES = [ 'ListLinkIds', 'ListLinks', 'GetLink', 'SetLink', 'RemoveLink', 'GetLinkEvents', 'ListServiceIds', 'ListServices', 'GetService', 'SetService', 'RemoveService', 'GetServiceEvents', 'ListSliceIds', 'ListSlices', 'GetSlice', 'SetSlice', 'RemoveSlice', 'GetSliceEvents', + 'ListPolicyRuleIds', 'ListPolicyRules', 'GetPolicyRule', 'SetPolicyRule', 'RemovePolicyRule', 'UnsetService', 'UnsetSlice', ] METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES) -class ContextServiceServicerImpl(ContextServiceServicer): +class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceServicer): def __init__(self, database : Database, messagebroker : MessageBroker): LOGGER.debug('Creating Servicer...') self.lock = threading.Lock() @@ -811,3 +816,58 @@ class ContextServiceServicerImpl(ContextServiceServicer): def GetConnectionEvents(self, request: Empty, context : grpc.ServicerContext) -> Iterator[ConnectionEvent]: for message in self.messagebroker.consume({TOPIC_CONNECTION}, consume_timeout=CONSUME_TIMEOUT): yield ConnectionEvent(**json.loads(message.content)) + + + # ----- Policy ---------------------------------------------------------------------------------------------------- + @safe_and_metered_rpc_method(METRICS, LOGGER) + def ListPolicyRuleIds(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleIdList: + with self.lock: + db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) + db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) + return PolicyRuleIdList(policyRuleIdList=[db_policy_rule.dump_id() for db_policy_rule in db_policy_rules]) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def ListPolicyRules(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleList: + with self.lock: + db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) + db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) + res = PolicyRuleList(policyRules=[db_policy_rule.dump_id() for db_policy_rule in db_policy_rules]) + return res + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def GetPolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> PolicyRule: + with self.lock: + policy_rule_uuid = request.uuid.uuid + db_policy_rule: PolicyRuleModel = get_object(self.database, PolicyRuleModel, policy_rule_uuid) + return PolicyRule(**db_policy_rule.dump()) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def SetPolicyRule(self, request: PolicyRule, context: grpc.ServicerContext) -> PolicyRuleId: + with self.lock: + policy_rule_type = request.WhichOneof('policy_rule') + policy_rule_json = grpc_message_to_json(request) + policy_rule_uuid = policy_rule_json[policy_rule_type]["policyRuleBasic"]["policyRuleId"]["uuid"]["uuid"] + result: Tuple[PolicyRuleModel, bool] = update_or_create_object( + self.database, PolicyRuleModel, policy_rule_uuid, {"value": json.dumps(policy_rule_json)}) + db_policy, updated = result + + event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + dict_policy_id = db_policy.dump_id() + notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) + + return PolicyRuleId(**dict_policy_id) + + @safe_and_metered_rpc_method(METRICS, LOGGER) + def RemovePolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> Empty: + with self.lock: + policy_uuid = request.uuid.uuid + db_policy = PolicyRuleModel(self.database, policy_uuid, auto_load=False) + found = db_policy.load() + if not found: + return Empty() + + dict_policy_id = db_policy.dump_id() + db_policy.delete() + event_type = EventTypeEnum.EVENTTYPE_REMOVE + notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) + return Empty() diff --git a/src/context/tests/Objects.py b/src/context/tests/Objects.py index 140cbff68..4b435528b 100644 --- a/src/context/tests/Objects.py +++ b/src/context/tests/Objects.py @@ -23,6 +23,7 @@ from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id from common.tools.object_factory.Link import json_link, json_link_id from common.tools.object_factory.Service import json_service_id, json_service_l3nm_planned from common.tools.object_factory.Topology import json_topology, json_topology_id +from common.tools.object_factory.PolicyRule import json_policy_rule, json_policy_rule_id # ----- Context -------------------------------------------------------------------------------------------------------- @@ -197,3 +198,10 @@ CONNECTION_R1_R3_SVCIDS = [SERVICE_R1_R2_ID, SERVICE_R2_R3_ID] CONNECTION_R1_R3 = json_connection( CONNECTION_R1_R3_UUID, service_id=SERVICE_R1_R3_ID, path_hops_endpoint_ids=CONNECTION_R1_R3_EPIDS, sub_service_ids=CONNECTION_R1_R3_SVCIDS) + + +# ----- PolicyRule ------------------------------------------------------------------------------------------------------- +POLICY_RULE_UUID = '56380225-3e40-4f74-9162-529f8dcb96a1' +POLICY_RULE_ID = json_policy_rule_id(POLICY_RULE_UUID) +POLICY_RULE = json_policy_rule(POLICY_RULE_UUID, policy_rule_type='POLICYTYPE_DEVICE') + diff --git a/src/context/tests/test_unitary.py b/src/context/tests/test_unitary.py index 3109ef13d..d37436677 100644 --- a/src/context/tests/test_unitary.py +++ b/src/context/tests/test_unitary.py @@ -27,6 +27,7 @@ from common.proto.context_pb2 import ( Connection, ConnectionEvent, ConnectionId, Context, ContextEvent, ContextId, Device, DeviceEvent, DeviceId, DeviceOperationalStatusEnum, Empty, EventTypeEnum, Link, LinkEvent, LinkId, Service, ServiceEvent, ServiceId, ServiceStatusEnum, ServiceTypeEnum, Topology, TopologyEvent, TopologyId) +from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) from common.type_checkers.Assertions import ( validate_connection, validate_connection_ids, validate_connections, validate_context, validate_context_ids, validate_contexts, validate_device, validate_device_ids, validate_devices, validate_link, validate_link_ids, @@ -44,7 +45,8 @@ from .Objects import ( CONNECTION_R1_R3, CONNECTION_R1_R3_ID, CONNECTION_R1_R3_UUID, CONTEXT, CONTEXT_ID, DEVICE_R1, DEVICE_R1_ID, DEVICE_R1_UUID, DEVICE_R2, DEVICE_R2_ID, DEVICE_R2_UUID, DEVICE_R3, DEVICE_R3_ID, DEVICE_R3_UUID, LINK_R1_R2, LINK_R1_R2_ID, LINK_R1_R2_UUID, SERVICE_R1_R2, SERVICE_R1_R2_ID, SERVICE_R1_R2_UUID, SERVICE_R1_R3, - SERVICE_R1_R3_ID, SERVICE_R1_R3_UUID, SERVICE_R2_R3, SERVICE_R2_R3_ID, SERVICE_R2_R3_UUID, TOPOLOGY, TOPOLOGY_ID) + SERVICE_R1_R3_ID, SERVICE_R1_R3_UUID, SERVICE_R2_R3, SERVICE_R2_R3_ID, SERVICE_R2_R3_UUID, TOPOLOGY, TOPOLOGY_ID, + POLICY_RULE, POLICY_RULE_ID, POLICY_RULE_UUID) LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) @@ -68,8 +70,8 @@ REDIS_CONFIG = { } SCENARIOS = [ - ('all_inmemory', DatabaseBackendEnum.INMEMORY, {}, MessageBrokerBackendEnum.INMEMORY, {} ), - ('all_redis', DatabaseBackendEnum.REDIS, REDIS_CONFIG, MessageBrokerBackendEnum.REDIS, REDIS_CONFIG), + ('all_inmemory', DatabaseBackendEnum.INMEMORY, {}, MessageBrokerBackendEnum.INMEMORY, {} ) +# ('all_redis', DatabaseBackendEnum.REDIS, REDIS_CONFIG, MessageBrokerBackendEnum.REDIS, REDIS_CONFIG), ] @pytest.fixture(scope='session', ids=[str(scenario[0]) for scenario in SCENARIOS], params=SCENARIOS) @@ -1169,6 +1171,104 @@ def test_grpc_connection( assert len(db_entries) == 0 +def test_grpc_policy( + context_client_grpc : ContextClient, # pylint: disable=redefined-outer-name + context_db_mb : Tuple[Database, MessageBroker]): # pylint: disable=redefined-outer-name + context_database = context_db_mb[0] + + # ----- Clean the database ----------------------------------------------------------------------------------------- + context_database.clear_all() + + # ----- Initialize the EventsCollector ----------------------------------------------------------------------------- + events_collector = EventsCollector(context_client_grpc) + events_collector.start() + + # ----- Get when the object does not exist ------------------------------------------------------------------------- + POLICY_ID = 'no-uuid' + DEFAULT_POLICY_ID = {'uuid': {'uuid': POLICY_ID}} + + with pytest.raises(grpc.RpcError) as e: + context_client_grpc.GetPolicyRule(PolicyRuleId(**DEFAULT_POLICY_ID)) + + assert e.value.code() == grpc.StatusCode.NOT_FOUND + assert e.value.details() == 'PolicyRule({:s}) not found'.format(POLICY_ID) + + # ----- List when the object does not exist ------------------------------------------------------------------------ + response = context_client_grpc.ListPolicyRuleIds(Empty()) + assert len(response.policyRuleIdList) == 0 + + response = context_client_grpc.ListPolicyRules(Empty()) + assert len(response.policyRules) == 0 + + # ----- Dump state of database before create the object ------------------------------------------------------------ + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 0 + + # ----- Create the object ------------------------------------------------------------------------------------------ + response = context_client_grpc.SetPolicyRule(PolicyRule(**POLICY_RULE)) + assert response.uuid.uuid == POLICY_RULE_UUID + + # ----- Check create event ----------------------------------------------------------------------------------------- + # events = events_collector.get_events(block=True, count=2) + # assert isinstance(events[0], TopologyEvent) + # assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_CREATE + # assert events[0].policy_id.uuid.uuid == POLICY_RULE_UUID + # + # assert isinstance(events[1], ContextEvent) + # assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_CREATE + + # ----- Update the object ------------------------------------------------------------------------------------------ + response = context_client_grpc.SetPolicyRule(PolicyRule(**POLICY_RULE)) + assert response.uuid.uuid == POLICY_RULE_UUID + + # ----- Dump state of database after create/update the object ------------------------------------------------------ + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 2 + + # ----- Get when the object exists --------------------------------------------------------------------------------- + response = context_client_grpc.GetPolicyRule(PolicyRuleId(**POLICY_RULE_ID)) + assert response.device.policyRuleBasic.policyRuleId.uuid.uuid == POLICY_RULE_UUID + + # ----- List when the object exists -------------------------------------------------------------------------------- + response = context_client_grpc.ListPolicyRuleIds(Empty()) + assert len(response.policyRuleIdList) == 1 + assert response.policyRuleIdList[0].uuid.uuid == POLICY_RULE_UUID + + response = context_client_grpc.ListPolicyRules(Empty()) + assert len(response.policyRules) == 1 + + # ----- Remove the object ------------------------------------------------------------------------------------------ + context_client_grpc.RemovePolicyRule(PolicyRuleId(**POLICY_RULE_ID)) + + # ----- Check remove event ----------------------------------------------------------------------------------------- + # events = events_collector.get_events(block=True, count=2) + # + # assert isinstance(events[0], TopologyEvent) + # assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE + # assert events[0].policy_id.uuid.uuid == POLICY_RULE_UUID + + + # ----- Stop the EventsCollector ----------------------------------------------------------------------------------- + # events_collector.stop() + + # ----- Dump state of database after remove the object ------------------------------------------------------------- + db_entries = context_database.dump() + LOGGER.info('----- Database Dump [{:3d} entries] -------------------------'.format(len(db_entries))) + for db_entry in db_entries: + LOGGER.info(' [{:>4s}] {:40s} :: {:s}'.format(*db_entry)) # pragma: no cover + LOGGER.info('-----------------------------------------------------------') + assert len(db_entries) == 0 + + + # ----- Test REST API methods ------------------------------------------------------------------------------------------ def test_rest_populate_database( diff --git a/src/policy/client/PolicyClient.py b/src/policy/client/PolicyClient.py new file mode 100644 index 000000000..2532a35ca --- /dev/null +++ b/src/policy/client/PolicyClient.py @@ -0,0 +1,89 @@ +# 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 grpc, logging +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_grpc +from common.tools.client.RetryDecorator import retry, delay_exponential +from common.tools.grpc.Tools import grpc_message_to_json_string +from common.proto.context_pb2 import ( + Connection, ConnectionEvent, ConnectionId, ConnectionIdList, ConnectionList, + Context, ContextEvent, ContextId, ContextIdList, ContextList, + Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, + Empty, + Link, LinkEvent, LinkId, LinkIdList, LinkList, + Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, + Slice, SliceEvent, SliceId, SliceIdList, SliceList, + Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) +from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) +from common.proto.context_pb2_grpc import ContextServiceStub + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 15 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') + +class PolicyClient: + def __init__(self, host=None, port=None): + if not host: + host = get_service_host(ServiceNameEnum.POLICY) + if not port: + port = get_service_port_grpc(ServiceNameEnum.POLICY) + self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) + LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) + self.channel = None + self.stub = None + self.connect() + LOGGER.debug('Channel created') + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = ContextServiceStub(self.channel) + + def close(self): + if self.channel is not None: + self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def ListPolicyRuleIds(self, request: Empty) -> PolicyRuleIdList: + LOGGER.debug('ListPolicyRuleIds request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListPolicyRuleIds(request) + LOGGER.debug('ListPolicyRuleIds result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def ListPolicyRules(self, request: Empty) -> PolicyRuleList: + LOGGER.debug('ListPolicyRules request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListPolicyRules(request) + LOGGER.debug('ListPolicyRules result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def GetPolicyRule(self, request: PolicyRuleId) -> PolicyRule: + LOGGER.debug('GetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetPolicyRule(request) + LOGGER.debug('GetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def SetPolicyRule(self, request: PolicyRule) -> PolicyRuleId: + LOGGER.debug('SetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SetPolicyRule(request) + LOGGER.debug('SetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def RemovePolicyRule(self, request: PolicyRuleId) -> Empty: + LOGGER.debug('RemovePolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.RemovePolicyRule(request) + LOGGER.debug('RemovePolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/policy/client/__init__.py b/src/policy/client/__init__.py new file mode 100644 index 000000000..70a332512 --- /dev/null +++ b/src/policy/client/__init__.py @@ -0,0 +1,14 @@ +# 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. + -- GitLab From 7dd26fcd11a4dca3894f891e0532edf16e86fc7e Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 28 Nov 2022 17:00:47 +0000 Subject: [PATCH 4/5] Context component: - pre-merge cleanup --- src/common/tools/object_factory/PolicyRule.py | 45 +++++----- src/policy/client/PolicyClient.py | 89 ------------------- src/policy/client/__init__.py | 14 --- 3 files changed, 24 insertions(+), 124 deletions(-) delete mode 100644 src/policy/client/PolicyClient.py delete mode 100644 src/policy/client/__init__.py diff --git a/src/common/tools/object_factory/PolicyRule.py b/src/common/tools/object_factory/PolicyRule.py index 4157a3f06..8702f931d 100644 --- a/src/common/tools/object_factory/PolicyRule.py +++ b/src/common/tools/object_factory/PolicyRule.py @@ -13,33 +13,36 @@ # limitations under the License. import logging -LOGGER = logging.getLogger(__name__) +from typing import Dict, List, Optional +from common.proto.policy_condition_pb2 import BooleanOperator -def json_policy_rule_id(policy_rule_uuid: str): - result = {'uuid': {'uuid': policy_rule_uuid}} - return result +LOGGER = logging.getLogger(__name__) +def json_policy_rule_id(policy_rule_uuid : str) -> Dict: + return {'uuid': {'uuid': policy_rule_uuid}} -def json_policy_rule(policy_rule_uuid: str, policy_rule_type: str): - result = {} +def json_policy_rule( + policy_rule_uuid : str, policy_priority : int = 1, + boolean_operator : BooleanOperator = BooleanOperator.POLICYRULE_CONDITION_BOOLEAN_AND, + condition_list : List[Dict] = [], action_list : List[Dict] = [], + service_id : Optional[Dict] = None, device_id_list : List[Dict] = [] +) -> Dict: basic = { - "policyRuleId": json_policy_rule_id(policy_rule_uuid), - "priority": 1, - "conditionList": [], - "booleanOperator": bool(), - "actionList": [] + 'policyRuleId': json_policy_rule_id(policy_rule_uuid), + 'priority': policy_priority, + 'conditionList': condition_list, + 'booleanOperator': boolean_operator, + 'actionList': action_list, } - if policy_rule_type == 'service': - result["service"] = {} - result["service"]["policyRuleBasic"] = basic - result["service"]["serviceId"] = { - "service_uuid": {"uuid": "uuid-service"}, - "context_id": {"context_uuid": {"uuid": "uuid-context"}}, - } - + result = {} + if service_id is not None: + policy_rule_type = 'service' + result[policy_rule_type] = {'policyRuleBasic': basic} + result[policy_rule_type]['serviceId'] = service_id else: - result["device"] = {} - result["device"]["policyRuleBasic"] = basic + policy_rule_type = 'device' + result[policy_rule_type] = {'policyRuleBasic': basic} + result[policy_rule_type]['deviceList'] = device_id_list return result diff --git a/src/policy/client/PolicyClient.py b/src/policy/client/PolicyClient.py deleted file mode 100644 index 2532a35ca..000000000 --- a/src/policy/client/PolicyClient.py +++ /dev/null @@ -1,89 +0,0 @@ -# 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 grpc, logging -from common.Constants import ServiceNameEnum -from common.Settings import get_service_host, get_service_port_grpc -from common.tools.client.RetryDecorator import retry, delay_exponential -from common.tools.grpc.Tools import grpc_message_to_json_string -from common.proto.context_pb2 import ( - Connection, ConnectionEvent, ConnectionId, ConnectionIdList, ConnectionList, - Context, ContextEvent, ContextId, ContextIdList, ContextList, - Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, - Empty, - Link, LinkEvent, LinkId, LinkIdList, LinkList, - Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, - Slice, SliceEvent, SliceId, SliceIdList, SliceList, - Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) -from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) -from common.proto.context_pb2_grpc import ContextServiceStub - -LOGGER = logging.getLogger(__name__) -MAX_RETRIES = 15 -DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) -RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') - -class PolicyClient: - def __init__(self, host=None, port=None): - if not host: - host = get_service_host(ServiceNameEnum.POLICY) - if not port: - port = get_service_port_grpc(ServiceNameEnum.POLICY) - self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) - LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint))) - self.channel = None - self.stub = None - self.connect() - LOGGER.debug('Channel created') - - def connect(self): - self.channel = grpc.insecure_channel(self.endpoint) - self.stub = ContextServiceStub(self.channel) - - def close(self): - if self.channel is not None: - self.channel.close() - self.channel = None - self.stub = None - - @RETRY_DECORATOR - def ListPolicyRuleIds(self, request: Empty) -> PolicyRuleIdList: - LOGGER.debug('ListPolicyRuleIds request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.stub.ListPolicyRuleIds(request) - LOGGER.debug('ListPolicyRuleIds result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def ListPolicyRules(self, request: Empty) -> PolicyRuleList: - LOGGER.debug('ListPolicyRules request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.stub.ListPolicyRules(request) - LOGGER.debug('ListPolicyRules result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def GetPolicyRule(self, request: PolicyRuleId) -> PolicyRule: - LOGGER.debug('GetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.stub.GetPolicyRule(request) - LOGGER.debug('GetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def SetPolicyRule(self, request: PolicyRule) -> PolicyRuleId: - LOGGER.debug('SetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.stub.SetPolicyRule(request) - LOGGER.debug('SetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def RemovePolicyRule(self, request: PolicyRuleId) -> Empty: - LOGGER.debug('RemovePolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.stub.RemovePolicyRule(request) - LOGGER.debug('RemovePolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response diff --git a/src/policy/client/__init__.py b/src/policy/client/__init__.py deleted file mode 100644 index 70a332512..000000000 --- a/src/policy/client/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# 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. - -- GitLab From 6fc3ba23c29fd32d4a8240c523ec9b254aef80d2 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Mon, 28 Nov 2022 17:39:53 +0000 Subject: [PATCH 5/5] Context component: - pre-merge cleanup of policy persistence --- src/context/client/ContextClient.py | 69 ++++++++++--------- .../service/database/PolicyRuleModel.py | 7 +- src/context/service/grpc_server/Constants.py | 4 +- .../grpc_server/ContextServiceServicerImpl.py | 28 ++++---- src/context/service/rest_server/Resources.py | 22 ++++++ src/context/tests/Objects.py | 3 +- src/context/tests/test_unitary.py | 44 +++++++++--- 7 files changed, 110 insertions(+), 67 deletions(-) diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py index 7b7a039f3..f91f36cf5 100644 --- a/src/context/client/ContextClient.py +++ b/src/context/client/ContextClient.py @@ -29,7 +29,7 @@ from common.proto.context_pb2 import ( Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) from common.proto.context_pb2_grpc import ContextServiceStub from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub -from common.proto.policy_pb2 import (PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule) +from common.proto.policy_pb2 import PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule LOGGER = logging.getLogger(__name__) MAX_RETRIES = 15 @@ -59,38 +59,6 @@ class ContextClient: self.stub = None self.policy_stub = None - - @RETRY_DECORATOR - def ListPolicyRuleIds(self, request: Empty) -> PolicyRuleIdList: - LOGGER.debug('ListPolicyRuleIds request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.policy_stub.ListPolicyRuleIds(request) - LOGGER.debug('ListPolicyRuleIds result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def ListPolicyRules(self, request: Empty) -> PolicyRuleList: - LOGGER.debug('ListPolicyRules request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.policy_stub.ListPolicyRules(request) - LOGGER.debug('ListPolicyRules result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def GetPolicyRule(self, request: PolicyRuleId) -> PolicyRule: - LOGGER.info('GetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.policy_stub.GetPolicyRule(request) - LOGGER.info('GetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def SetPolicyRule(self, request: PolicyRule) -> PolicyRuleId: - LOGGER.debug('SetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.policy_stub.SetPolicyRule(request) - LOGGER.debug('SetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR - def RemovePolicyRule(self, request: PolicyRuleId) -> Empty: - LOGGER.debug('RemovePolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) - response = self.policy_stub.RemovePolicyRule(request) - LOGGER.debug('RemovePolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) - return response - @RETRY_DECORATOR def ListContextIds(self, request: Empty) -> ContextIdList: LOGGER.debug('ListContextIds request: {:s}'.format(grpc_message_to_json_string(request))) @@ -398,3 +366,38 @@ class ContextClient: response = self.stub.GetConnectionEvents(request) LOGGER.debug('GetConnectionEvents result: {:s}'.format(grpc_message_to_json_string(response))) return response + + @RETRY_DECORATOR + def ListPolicyRuleIds(self, request: Empty) -> PolicyRuleIdList: + LOGGER.debug('ListPolicyRuleIds request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.ListPolicyRuleIds(request) + LOGGER.debug('ListPolicyRuleIds result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def ListPolicyRules(self, request: Empty) -> PolicyRuleList: + LOGGER.debug('ListPolicyRules request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.ListPolicyRules(request) + LOGGER.debug('ListPolicyRules result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetPolicyRule(self, request: PolicyRuleId) -> PolicyRule: + LOGGER.info('GetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.GetPolicyRule(request) + LOGGER.info('GetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def SetPolicyRule(self, request: PolicyRule) -> PolicyRuleId: + LOGGER.debug('SetPolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.SetPolicyRule(request) + LOGGER.debug('SetPolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def RemovePolicyRule(self, request: PolicyRuleId) -> Empty: + LOGGER.debug('RemovePolicyRule request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.policy_stub.RemovePolicyRule(request) + LOGGER.debug('RemovePolicyRule result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/context/service/database/PolicyRuleModel.py b/src/context/service/database/PolicyRuleModel.py index 02adbfa07..7c84ea940 100644 --- a/src/context/service/database/PolicyRuleModel.py +++ b/src/context/service/database/PolicyRuleModel.py @@ -14,22 +14,19 @@ import logging import json -from typing import Dict, List, Optional, Tuple +from typing import Dict from common.orm.fields.PrimaryKeyField import PrimaryKeyField from common.orm.fields.StringField import StringField from common.orm.model.Model import Model LOGGER = logging.getLogger(__name__) - class PolicyRuleModel(Model): pk = PrimaryKeyField() value = StringField(required=True, allow_empty=False) def dump_id(self) -> Dict: - return { - "uuid": {"uuid": self.pk} - } + return {'uuid': {'uuid': self.pk}} def dump(self) -> Dict: return json.loads(self.value) diff --git a/src/context/service/grpc_server/Constants.py b/src/context/service/grpc_server/Constants.py index 25a2fce40..9d7c886c7 100644 --- a/src/context/service/grpc_server/Constants.py +++ b/src/context/service/grpc_server/Constants.py @@ -19,9 +19,7 @@ TOPIC_DEVICE = 'device' TOPIC_LINK = 'link' TOPIC_SERVICE = 'service' TOPIC_SLICE = 'slice' -TOPIC_POLICY = 'policy' -TOPICS = {TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_TOPOLOGY, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, - TOPIC_POLICY} +TOPICS = {TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_TOPOLOGY, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE} CONSUME_TIMEOUT = 0.5 # seconds diff --git a/src/context/service/grpc_server/ContextServiceServicerImpl.py b/src/context/service/grpc_server/ContextServiceServicerImpl.py index 4a45e4f62..f8dd18819 100644 --- a/src/context/service/grpc_server/ContextServiceServicerImpl.py +++ b/src/context/service/grpc_server/ContextServiceServicerImpl.py @@ -33,6 +33,7 @@ from common.proto.context_pb2_grpc import ContextServiceServicer from common.proto.context_policy_pb2_grpc import ContextPolicyServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.rpc_method_wrapper.ServiceExceptions import InvalidArgumentException +from common.tools.grpc.Tools import grpc_message_to_json from context.service.database.ConfigModel import update_config from context.service.database.ConnectionModel import ConnectionModel, set_path from context.service.database.ConstraintModel import set_constraints @@ -51,8 +52,7 @@ from context.service.database.SliceModel import SliceModel, grpc_to_enum__slice_ from context.service.database.TopologyModel import TopologyModel from .Constants import ( CONSUME_TIMEOUT, TOPIC_CONNECTION, TOPIC_CONTEXT, TOPIC_DEVICE, TOPIC_LINK, TOPIC_SERVICE, TOPIC_SLICE, - TOPIC_TOPOLOGY, TOPIC_POLICY) -from common.tools.grpc.Tools import grpc_message_to_json_string, grpc_message_to_json + TOPIC_TOPOLOGY) LOGGER = logging.getLogger(__name__) @@ -820,7 +820,8 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer yield ConnectionEvent(**json.loads(message.content)) - # ----- Policy ---------------------------------------------------------------------------------------------------- + # ----- Policy ----------------------------------------------------------------------------------------------------- + @safe_and_metered_rpc_method(METRICS, LOGGER) def ListPolicyRuleIds(self, request: Empty, context: grpc.ServicerContext) -> PolicyRuleIdList: with self.lock: @@ -833,8 +834,7 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer with self.lock: db_policy_rules: List[PolicyRuleModel] = get_all_objects(self.database, PolicyRuleModel) db_policy_rules = sorted(db_policy_rules, key=operator.attrgetter('pk')) - res = PolicyRuleList(policyRules=[db_policy_rule.dump_id() for db_policy_rule in db_policy_rules]) - return res + return PolicyRuleList(policyRules=[db_policy_rule.dump() for db_policy_rule in db_policy_rules]) @safe_and_metered_rpc_method(METRICS, LOGGER) def GetPolicyRule(self, request: PolicyRuleId, context: grpc.ServicerContext) -> PolicyRule: @@ -848,15 +848,14 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer with self.lock: policy_rule_type = request.WhichOneof('policy_rule') policy_rule_json = grpc_message_to_json(request) - policy_rule_uuid = policy_rule_json[policy_rule_type]["policyRuleBasic"]["policyRuleId"]["uuid"]["uuid"] + policy_rule_uuid = policy_rule_json[policy_rule_type]['policyRuleBasic']['policyRuleId']['uuid']['uuid'] result: Tuple[PolicyRuleModel, bool] = update_or_create_object( - self.database, PolicyRuleModel, policy_rule_uuid, {"value": json.dumps(policy_rule_json)}) - db_policy, updated = result + self.database, PolicyRuleModel, policy_rule_uuid, {'value': json.dumps(policy_rule_json)}) + db_policy, updated = result # pylint: disable=unused-variable - event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE + #event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE dict_policy_id = db_policy.dump_id() - notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) - + #notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) return PolicyRuleId(**dict_policy_id) @safe_and_metered_rpc_method(METRICS, LOGGER) @@ -865,11 +864,10 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer policy_uuid = request.uuid.uuid db_policy = PolicyRuleModel(self.database, policy_uuid, auto_load=False) found = db_policy.load() - if not found: - return Empty() + if not found: return Empty() dict_policy_id = db_policy.dump_id() db_policy.delete() - event_type = EventTypeEnum.EVENTTYPE_REMOVE - notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) + #event_type = EventTypeEnum.EVENTTYPE_REMOVE + #notify_event(self.messagebroker, TOPIC_POLICY, event_type, {"policy_id": dict_policy_id}) return Empty() diff --git a/src/context/service/rest_server/Resources.py b/src/context/service/rest_server/Resources.py index d1738edb2..5f03132a3 100644 --- a/src/context/service/rest_server/Resources.py +++ b/src/context/service/rest_server/Resources.py @@ -17,6 +17,7 @@ from flask.json import jsonify from flask_restful import Resource from common.orm.Database import Database from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, Empty, LinkId, ServiceId, SliceId, TopologyId +from common.proto.policy_pb2 import PolicyRuleId from common.tools.grpc.Tools import grpc_message_to_json from context.service.grpc_server.ContextServiceServicerImpl import ContextServiceServicerImpl @@ -61,6 +62,11 @@ def grpc_topology_id(context_uuid, topology_uuid): 'topology_uuid': {'uuid': topology_uuid} }) +def grpc_policy_rule_id(policy_rule_uuid): + return PolicyRuleId(**{ + 'uuid': {'uuid': policy_rule_uuid} + }) + class _Resource(Resource): def __init__(self, database : Database) -> None: super().__init__() @@ -151,6 +157,18 @@ class Connection(_Resource): def get(self, connection_uuid : str): return format_grpc_to_json(self.servicer.GetConnection(grpc_connection_id(connection_uuid), None)) +class PolicyRuleIds(_Resource): + def get(self): + return format_grpc_to_json(self.servicer.ListPolicyRuleIds(Empty(), None)) + +class PolicyRules(_Resource): + def get(self): + return format_grpc_to_json(self.servicer.ListPolicyRules(Empty(), None)) + +class PolicyRule(_Resource): + def get(self, policy_rule_uuid : str): + return format_grpc_to_json(self.servicer.GetPolicyRule(grpc_policy_rule_id(policy_rule_uuid), None)) + class DumpText(Resource): def __init__(self, database : Database) -> None: super().__init__() @@ -219,6 +237,10 @@ RESOURCES = [ ('api.connections', Connections, '/context//service//connections'), ('api.connection', Connection, '/connection/'), + ('api.policyrule_ids', PolicyRuleIds, '/policyrule_ids'), + ('api.policyrules', PolicyRules, '/policyrules'), + ('api.policyrule', PolicyRule, '/policyrule/'), + ('api.dump.text', DumpText, '/dump/text'), ('api.dump.html', DumpHtml, '/dump/html'), ] diff --git a/src/context/tests/Objects.py b/src/context/tests/Objects.py index 4b435528b..1cf929cfa 100644 --- a/src/context/tests/Objects.py +++ b/src/context/tests/Objects.py @@ -203,5 +203,4 @@ CONNECTION_R1_R3 = json_connection( # ----- PolicyRule ------------------------------------------------------------------------------------------------------- POLICY_RULE_UUID = '56380225-3e40-4f74-9162-529f8dcb96a1' POLICY_RULE_ID = json_policy_rule_id(POLICY_RULE_UUID) -POLICY_RULE = json_policy_rule(POLICY_RULE_UUID, policy_rule_type='POLICYTYPE_DEVICE') - +POLICY_RULE = json_policy_rule(POLICY_RULE_UUID) diff --git a/src/context/tests/test_unitary.py b/src/context/tests/test_unitary.py index d37436677..9ad978a41 100644 --- a/src/context/tests/test_unitary.py +++ b/src/context/tests/test_unitary.py @@ -1180,8 +1180,8 @@ def test_grpc_policy( context_database.clear_all() # ----- Initialize the EventsCollector ----------------------------------------------------------------------------- - events_collector = EventsCollector(context_client_grpc) - events_collector.start() + #events_collector = EventsCollector(context_client_grpc) + #events_collector.start() # ----- Get when the object does not exist ------------------------------------------------------------------------- POLICY_ID = 'no-uuid' @@ -1213,13 +1213,10 @@ def test_grpc_policy( assert response.uuid.uuid == POLICY_RULE_UUID # ----- Check create event ----------------------------------------------------------------------------------------- - # events = events_collector.get_events(block=True, count=2) - # assert isinstance(events[0], TopologyEvent) + # events = events_collector.get_events(block=True, count=1) + # assert isinstance(events[0], PolicyEvent) # assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_CREATE # assert events[0].policy_id.uuid.uuid == POLICY_RULE_UUID - # - # assert isinstance(events[1], ContextEvent) - # assert events[1].event.event_type == EventTypeEnum.EVENTTYPE_CREATE # ----- Update the object ------------------------------------------------------------------------------------------ response = context_client_grpc.SetPolicyRule(PolicyRule(**POLICY_RULE)) @@ -1250,8 +1247,8 @@ def test_grpc_policy( # ----- Check remove event ----------------------------------------------------------------------------------------- # events = events_collector.get_events(block=True, count=2) - # - # assert isinstance(events[0], TopologyEvent) + + # assert isinstance(events[0], PolicyEvent) # assert events[0].event.event_type == EventTypeEnum.EVENTTYPE_REMOVE # assert events[0].policy_id.uuid.uuid == POLICY_RULE_UUID @@ -1324,6 +1321,22 @@ def test_rest_get_service(context_service_rest : RestServer): # pylint: disable= reply = do_rest_request('/context/{:s}/service/{:s}'.format(context_uuid, service_uuid)) validate_service(reply) +def test_rest_get_slice_ids(context_slice_rest : RestServer): # pylint: disable=redefined-outer-name + context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID) + reply = do_rest_request('/context/{:s}/slice_ids'.format(context_uuid)) + #validate_slice_ids(reply) + +def test_rest_get_slices(context_slice_rest : RestServer): # pylint: disable=redefined-outer-name + context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID) + reply = do_rest_request('/context/{:s}/slices'.format(context_uuid)) + #validate_slices(reply) + +#def test_rest_get_slice(context_slice_rest : RestServer): # pylint: disable=redefined-outer-name +# context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_UUID) +# slice_uuid = urllib.parse.quote(SLICE_R1_R2_UUID, safe='') +# reply = do_rest_request('/context/{:s}/slice/{:s}'.format(context_uuid, slice_uuid)) +# #validate_slice(reply) + def test_rest_get_device_ids(context_service_rest : RestServer): # pylint: disable=redefined-outer-name reply = do_rest_request('/device_ids') validate_device_ids(reply) @@ -1367,6 +1380,19 @@ def test_rest_get_connection(context_service_rest : RestServer): # pylint: disab reply = do_rest_request('/connection/{:s}'.format(connection_uuid)) validate_connection(reply) +def test_rest_get_policyrule_ids(context_service_rest : RestServer): # pylint: disable=redefined-outer-name + reply = do_rest_request('/policyrule_ids') + #validate_policyrule_ids(reply) + +def test_rest_get_policyrules(context_service_rest : RestServer): # pylint: disable=redefined-outer-name + reply = do_rest_request('/policyrules') + #validate_policyrules(reply) + +#def test_rest_get_policyrule(context_service_rest : RestServer): # pylint: disable=redefined-outer-name +# policyrule_uuid = urllib.parse.quote(POLICYRULE_UUID, safe='') +# reply = do_rest_request('/policyrule/{:s}'.format(policyrule_uuid)) +# #validate_policyrule(reply) + # ----- Test misc. Context internal tools ------------------------------------------------------------------------------ -- GitLab