diff --git a/src/context/service/database/Constraint.py b/src/context/service/database/Constraint.py index 6869b7b71c9913a46b09135cce0c588dc7092adb..2ca49338a6ac0ba2d57ec57dffa26555b9fa6507 100644 --- a/src/context/service/database/Constraint.py +++ b/src/context/service/database/Constraint.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import datetime, logging, json +import datetime, json, logging from sqlalchemy import delete #from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import insert @@ -38,11 +38,12 @@ def compose_constraints_data( dict_constraint = { 'position' : position, 'kind' : kind, + 'action' : grpc_to_enum__constraint_action(constraint.action), 'data' : grpc_message_to_json_string(getattr(constraint, str_kind, {})), 'created_at': now, 'updated_at': now, - 'action' : grpc_to_enum__constraint_action(constraint.action) } + parent_kind,parent_uuid = '',None if service_uuid is not None: dict_constraint['service_uuid'] = service_uuid @@ -51,7 +52,8 @@ def compose_constraints_data( dict_constraint['slice_uuid'] = slice_uuid parent_kind,parent_uuid = 'slice',slice_uuid else: - MSG = 'Parent for Constraint({:s}) cannot be identified (service_uuid={:s}, slice_uuid={:s})' + MSG = 'Parent for Constraint({:s}) cannot be identified '+\ + '(service_uuid={:s}, slice_uuid={:s})' str_constraint = grpc_message_to_json_string(constraint) raise Exception(MSG.format(str_constraint, str(service_uuid), str(slice_uuid))) @@ -71,7 +73,8 @@ def compose_constraints_data( }: constraint_name = '{:s}:{:s}:'.format(parent_kind, kind.value) else: - MSG = 'Name for Constraint({:s}) cannot be inferred (service_uuid={:s}, slice_uuid={:s})' + MSG = 'Name for Constraint({:s}) cannot be inferred '+\ + '(service_uuid={:s}, slice_uuid={:s})' str_constraint = grpc_message_to_json_string(constraint) raise Exception(MSG.format(str_constraint, str(service_uuid), str(slice_uuid))) @@ -79,7 +82,6 @@ def compose_constraints_data( dict_constraint['constraint_uuid'] = constraint_uuid dict_constraints.append(dict_constraint) - return dict_constraints def upsert_constraints( @@ -93,13 +95,12 @@ def upsert_constraints( else: MSG = 'DataModel cannot be identified (service_uuid={:s}, slice_uuid={:s})' raise Exception(MSG.format(str(service_uuid), str(slice_uuid))) + uuids_to_delete : Set[str] = set() uuids_to_upsert : Dict[str, int] = dict() rules_to_upsert : List[Dict] = list() - uuids_to_delete : Set[str] = set() for constraint in constraints: constraint_uuid = constraint['constraint_uuid'] constraint_action = constraint['action'] - if is_delete or constraint_action == ORM_ConstraintActionEnum.DELETE: uuids_to_delete.add(constraint_uuid) elif constraint_action == ORM_ConstraintActionEnum.SET: @@ -121,7 +122,7 @@ def upsert_constraints( stmt = delete(klass) if service_uuid is not None: stmt = stmt.where(klass.service_uuid == service_uuid) if slice_uuid is not None: stmt = stmt.where(klass.slice_uuid == slice_uuid ) - stmt = stmt.where(klass.constraint_uuid.not_in(set(uuids_to_upsert.keys()))) + stmt = stmt.where(klass.constraint_uuid.in_(uuids_to_delete) #str_stmt = stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}) #LOGGER.warning('delete stmt={:s}'.format(str(str_stmt))) constraint_deletes = session.execute(stmt) @@ -135,6 +136,7 @@ def upsert_constraints( index_elements=[klass.constraint_uuid], set_=dict( position = stmt.excluded.position, + action = stmt.excluded.action, data = stmt.excluded.data, updated_at = stmt.excluded.updated_at, ) diff --git a/src/context/service/database/models/ConstraintModel.py b/src/context/service/database/models/ConstraintModel.py index bf5c9077af316f337b1c8fbab9cc716ba92a6fca..112a5f35c8d23f4b4b84f5472c14dc3b1bc7fbec 100644 --- a/src/context/service/database/models/ConstraintModel.py +++ b/src/context/service/database/models/ConstraintModel.py @@ -15,8 +15,8 @@ import enum, json from sqlalchemy import CheckConstraint, Column, DateTime, Enum, ForeignKey, Integer, String from sqlalchemy.dialects.postgresql import UUID -from .enums.ConstraintAction import ORM_ConstraintActionEnum from typing import Dict +from .enums.ConstraintAction import ORM_ConstraintActionEnum from ._Base import _Base # Enum values should match name of field in Constraint message @@ -40,10 +40,10 @@ class ServiceConstraintModel(_Base): service_uuid = Column(ForeignKey('service.service_uuid', ondelete='CASCADE'), nullable=False) #, index=True position = Column(Integer, nullable=False) kind = Column(Enum(ConstraintKindEnum), nullable=False) + action = Column(Enum(ORM_ConstraintActionEnum), nullable=False) data = Column(String, nullable=False) created_at = Column(DateTime, nullable=False) updated_at = Column(DateTime, nullable=False) - action = Column(Enum(ORM_ConstraintActionEnum), nullable=False) __table_args__ = ( CheckConstraint(position >= 0, name='check_position_value'), @@ -51,7 +51,10 @@ class ServiceConstraintModel(_Base): ) def dump(self) -> Dict: - return {self.kind.value: json.loads(self.data)} + return { + 'action': self.action.value, + self.kind.value: json.loads(self.data), + } class SliceConstraintModel(_Base): __tablename__ = 'slice_constraint' @@ -60,6 +63,7 @@ class SliceConstraintModel(_Base): slice_uuid = Column(ForeignKey('slice.slice_uuid', ondelete='CASCADE'), nullable=False) #, index=True position = Column(Integer, nullable=False) kind = Column(Enum(ConstraintKindEnum), nullable=False) + action = Column(Enum(ORM_ConstraintActionEnum), nullable=False) data = Column(String, nullable=False) created_at = Column(DateTime, nullable=False) updated_at = Column(DateTime, nullable=False) @@ -70,4 +74,7 @@ class SliceConstraintModel(_Base): ) def dump(self) -> Dict: - return {self.kind.value: json.loads(self.data)} + return { + 'action': self.action.value, + self.kind.value: json.loads(self.data), + } diff --git a/src/context/service/database/models/EndPointModel.py b/src/context/service/database/models/EndPointModel.py index f5be89b5a9af5ef41378230f6e1b19ac7fd8f67c..9bb2adb2d4209bde8cee4299d10521887f371428 100644 --- a/src/context/service/database/models/EndPointModel.py +++ b/src/context/service/database/models/EndPointModel.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json from sqlalchemy import Column, DateTime, Enum, ForeignKey, String from sqlalchemy.dialects.postgresql import ARRAY, UUID from sqlalchemy.orm import relationship from typing import Dict from .enums.KpiSampleType import ORM_KpiSampleTypeEnum from ._Base import _Base -import json class EndPointModel(_Base): __tablename__ = 'endpoint' diff --git a/src/service/tests/CommonObjects.py b/src/service/tests/CommonObjects.py index 6b7fa86f1e6aadb27533a92bbc0c78525a70a304..4cd233349ae4f0e7b39b5597fdbd6ff9d00e5189 100644 --- a/src/service/tests/CommonObjects.py +++ b/src/service/tests/CommonObjects.py @@ -16,7 +16,6 @@ from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME from common.proto.kpi_sample_types_pb2 import KpiSampleType from common.tools.object_factory.Context import json_context, json_context_id from common.tools.object_factory.Topology import json_topology, json_topology_id -from context.service.database.uuids._Builder import get_uuid_from_string # ----- Context -------------------------------------------------------------------------------------------------------- CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_NAME) diff --git a/src/service/tests/ServiceHandler_L3NM_EMU.py b/src/service/tests/ServiceHandler_L3NM_EMU.py index f3e3e0eca387d4cc8ca178384f2fc8b5f18bc991..2618e204c00a1bb956812daeb6f831275cac7b5a 100644 --- a/src/service/tests/ServiceHandler_L3NM_EMU.py +++ b/src/service/tests/ServiceHandler_L3NM_EMU.py @@ -53,7 +53,10 @@ ALBACETE_GPS = (38.998249, -1.858145) # ----- Devices -------------------------------------------------------------------------------------------------------- DEVICE_R1_UUID = 'R1' -DEVICE_R1_ENDPOINT_DEFS = [('EP1', 'optical', json_location(gps_position=json_gps_position(*BARCELONA_GPS))), ('EP100', 'copper', json_location(gps_position=json_gps_position(*BARCELONA_GPS)))] +DEVICE_R1_ENDPOINT_DEFS = [ + ('EP1', 'optical', json_location(gps_position=json_gps_position(*BARCELONA_GPS))), + ('EP100', 'copper', json_location(gps_position=json_gps_position(*BARCELONA_GPS))) +] DEVICE_R1_ID = json_device_id(DEVICE_R1_UUID) DEVICE_R1_ENDPOINTS = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS) DEVICE_R1_ENDPOINT_IDS = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS) @@ -62,7 +65,10 @@ ENDPOINT_ID_R1_EP1 = DEVICE_R1_ENDPOINT_IDS[0] ENDPOINT_ID_R1_EP100 = DEVICE_R1_ENDPOINT_IDS[1] DEVICE_R2_UUID = 'R2' -DEVICE_R2_ENDPOINT_DEFS = [('EP1', 'optical', json_location(gps_position=json_gps_position(*MADRID_GPS))), ('EP100', 'copper', json_location(gps_position=json_gps_position(*MADRID_GPS)))] +DEVICE_R2_ENDPOINT_DEFS = [ + ('EP1', 'optical', json_location(gps_position=json_gps_position(*MADRID_GPS))), + ('EP100', 'copper', json_location(gps_position=json_gps_position(*MADRID_GPS))) +] DEVICE_R2_ID = json_device_id(DEVICE_R2_UUID) DEVICE_R2_ENDPOINTS = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS) DEVICE_R2_ENDPOINT_IDS = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS) @@ -71,7 +77,10 @@ ENDPOINT_ID_R2_EP1 = DEVICE_R2_ENDPOINT_IDS[0] ENDPOINT_ID_R2_EP100 = DEVICE_R2_ENDPOINT_IDS[1] DEVICE_R3_UUID = 'R3' -DEVICE_R3_ENDPOINT_DEFS = [('EP1', 'optical', json_location(gps_position=json_gps_position(*MALAGA_GPS))), ('EP100', 'copper', json_location(gps_position=json_gps_position(*MALAGA_GPS)))] +DEVICE_R3_ENDPOINT_DEFS = [ + ('EP1', 'optical', json_location(gps_position=json_gps_position(*MALAGA_GPS))), + ('EP100', 'copper', json_location(gps_position=json_gps_position(*MALAGA_GPS))) +] DEVICE_R3_ID = json_device_id(DEVICE_R3_UUID) DEVICE_R3_ENDPOINTS = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS) DEVICE_R3_ENDPOINT_IDS = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS) @@ -80,7 +89,11 @@ ENDPOINT_ID_R3_EP1 = DEVICE_R3_ENDPOINT_IDS[0] ENDPOINT_ID_R3_EP100 = DEVICE_R3_ENDPOINT_IDS[1] DEVICE_O1_UUID = 'O1' -DEVICE_O1_ENDPOINT_DEFS = [('EP1', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS))), ('EP2', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS))), ('EP3', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS)))] +DEVICE_O1_ENDPOINT_DEFS = [ + ('EP1', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS))), + ('EP2', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS))), + ('EP3', 'optical', json_location(gps_position=json_gps_position(*PONFERRADA_GPS))) +] DEVICE_O1_ID = json_device_id(DEVICE_O1_UUID) DEVICE_O1_ENDPOINTS = json_endpoints(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS) DEVICE_O1_ENDPOINT_IDS = json_endpoint_ids(DEVICE_O1_ID, DEVICE_O1_ENDPOINT_DEFS) diff --git a/src/service/tests/test_unitary.py b/src/service/tests/test_unitary.py index 0779a1f3cff287f68ed4752e6f86d067cadc96c1..aa44714af081307377fe52106cb715f5e0774c73 100644 --- a/src/service/tests/test_unitary.py +++ b/src/service/tests/test_unitary.py @@ -37,7 +37,8 @@ class TestServiceHandlers: scenarios = SERVICE_HANDLERS_TO_TEST def test_prepare_environment( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -50,7 +51,8 @@ class TestServiceHandlers: def test_service_create_error_cases( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -91,7 +93,8 @@ class TestServiceHandlers: def test_service_create_correct( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -101,7 +104,8 @@ class TestServiceHandlers: def test_service_get_created( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -112,7 +116,8 @@ class TestServiceHandlers: def test_service_update_configure( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -131,7 +136,8 @@ class TestServiceHandlers: str(device_id), i, grpc_message_to_json_string(config_rule))) def test_service_update_deconfigure( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -150,7 +156,8 @@ class TestServiceHandlers: def test_service_get_updated( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -161,7 +168,8 @@ class TestServiceHandlers: def test_service_update_configure_loc( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -181,7 +189,8 @@ class TestServiceHandlers: def test_service_get_updated_1( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -192,7 +201,8 @@ class TestServiceHandlers: def test_service_update_configure_loc_new( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -212,7 +222,8 @@ class TestServiceHandlers: def test_service_get_updated_2( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -222,7 +233,8 @@ class TestServiceHandlers: LOGGER.info('service_data = {:s}'.format(grpc_message_to_json_string(service_data))) def test_service_delete_loc( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name @@ -231,7 +243,8 @@ class TestServiceHandlers: service_client.DeleteService(ServiceId(**service_id)) def test_cleanup_environment( - self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, service_constraints_location, service_constraints_location_new, + self, service_id, service_descriptor, service_endpoint_ids, service_config_rules, service_constraints, + service_constraints_location, service_constraints_location_new, contexts, topologies, devices, links, context_client : ContextClient, # pylint: disable=redefined-outer-name device_client : DeviceClient, # pylint: disable=redefined-outer-name