diff --git a/src/context/service/database/ConfigRule.py b/src/context/service/database/ConfigRule.py index 0f0e9668cf8748ae6b8bb2a8003f7ba664e0ff75..7e4a383c787af0a35eb08a014e9464c9e7384c3b 100644 --- a/src/context/service/database/ConfigRule.py +++ b/src/context/service/database/ConfigRule.py @@ -14,7 +14,7 @@ import datetime, json, logging from sqlalchemy import delete -from sqlalchemy.dialects import postgresql +#from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import insert from sqlalchemy.orm import Session from typing import Dict, List, Optional, Set @@ -44,29 +44,29 @@ def compose_config_rules_data( 'updated_at': now, } - parent_uuid = None + parent_kind,parent_uuid = '',None if device_uuid is not None: dict_config_rule['device_uuid'] = device_uuid - parent_uuid = device_uuid + parent_kind,parent_uuid = 'device',device_uuid elif service_uuid is not None: dict_config_rule['service_uuid'] = service_uuid - parent_uuid = service_uuid + parent_kind,parent_uuid = 'service',service_uuid elif slice_uuid is not None: dict_config_rule['slice_uuid'] = slice_uuid - parent_uuid = slice_uuid + parent_kind,parent_uuid = 'slice',slice_uuid else: MSG = 'Parent for ConfigRule({:s}) cannot be identified '+\ '(device_uuid={:s}, service_uuid={:s}, slice_uuid={:s})' str_config_rule = grpc_message_to_json_string(config_rule) raise Exception(MSG.format(str_config_rule, str(device_uuid), str(service_uuid), str(slice_uuid))) - + configrule_name = None if kind == ConfigRuleKindEnum.CUSTOM: - configrule_name = config_rule.custom.resource_key + configrule_name = '{:s}:{:s}:{:s}'.format(parent_kind, kind.value, config_rule.custom.resource_key) elif kind == ConfigRuleKindEnum.ACL: - endpoint_uuid = endpoint_get_uuid(config_rule.acl.endpoint_id, allow_random=False) + _, _, endpoint_uuid = endpoint_get_uuid(config_rule.acl.endpoint_id, allow_random=False) rule_set_name = config_rule.acl.rule_set.name - configrule_name = '{:s}/{:s}'.format(endpoint_uuid, rule_set_name) + configrule_name = '{:s}:{:s}:{:s}:{:s}'.format(parent_kind, kind.value, endpoint_uuid, rule_set_name) else: MSG = 'Name for ConfigRule({:s}) cannot be inferred '+\ '(device_uuid={:s}, service_uuid={:s}, slice_uuid={:s})' @@ -87,49 +87,39 @@ def upsert_config_rules( uuids_to_upsert : Dict[str, int] = dict() rules_to_upsert : List[Dict] = list() for config_rule in config_rules: - if config_rule['action'] == ORM_ConfigActionEnum.SET: - configrule_uuid = config_rule['configrule_uuid'] + configrule_uuid = config_rule['configrule_uuid'] + configrule_action = config_rule['action'] + if configrule_action == ORM_ConfigActionEnum.SET: position = uuids_to_upsert.get(configrule_uuid) if position is None: # if not added, add it rules_to_upsert.append(config_rule) - uuids_to_upsert[config_rule['configrule_uuid']] = len(rules_to_upsert) - 1 + uuids_to_upsert[configrule_uuid] = len(rules_to_upsert) - 1 else: # if already added, update occurrence rules_to_upsert[position] = config_rule - elif config_rule['action'] == ORM_ConfigActionEnum.DELETE: - uuids_to_delete.add(config_rule['configrule_uuid']) + elif configrule_action == ORM_ConfigActionEnum.DELETE: + uuids_to_delete.add(configrule_uuid) else: MSG = 'Action for ConfigRule({:s}) is not supported '+\ '(device_uuid={:s}, service_uuid={:s}, slice_uuid={:s})' str_config_rule = json.dumps(config_rule) raise Exception(MSG.format(str_config_rule, str(device_uuid), str(service_uuid), str(slice_uuid))) - LOGGER.warning('device_uuid={:s}'.format(str(device_uuid))) - LOGGER.warning('service_uuid={:s}'.format(str(service_uuid))) - LOGGER.warning('slice_uuid={:s}'.format(str(slice_uuid))) - LOGGER.warning('uuids_to_delete={:s}'.format(str(uuids_to_delete))) - LOGGER.warning('rules_to_upsert={:s}'.format(str(rules_to_upsert))) - delete_affected = False - upsert_affected = False - if len(uuids_to_delete) > 0: stmt = delete(ConfigRuleModel) if device_uuid is not None: stmt = stmt.where(ConfigRuleModel.device_uuid == device_uuid ) if service_uuid is not None: stmt = stmt.where(ConfigRuleModel.service_uuid == service_uuid) if slice_uuid is not None: stmt = stmt.where(ConfigRuleModel.slice_uuid == slice_uuid ) stmt = stmt.where(ConfigRuleModel.configrule_uuid.in_(uuids_to_delete)) - - str_stmt = stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}) - LOGGER.warning('raw delete stmt={:s}'.format(str(str_stmt))) - + #str_stmt = stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}) + #LOGGER.warning('delete stmt={:s}'.format(str(str_stmt))) configrule_deletes = session.execute(stmt) - - LOGGER.warning('configrule_deletes.rowcount={:s}'.format(str(configrule_deletes.rowcount))) - + #LOGGER.warning('configrule_deletes.rowcount={:s}'.format(str(configrule_deletes.rowcount))) delete_affected = int(configrule_deletes.rowcount) > 0 + upsert_affected = False if len(rules_to_upsert) > 0: stmt = insert(ConfigRuleModel).values(rules_to_upsert) stmt = stmt.on_conflict_do_update( @@ -142,6 +132,8 @@ def upsert_config_rules( ) ) stmt = stmt.returning(ConfigRuleModel.created_at, ConfigRuleModel.updated_at) + #str_stmt = stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}) + #LOGGER.warning('upsert stmt={:s}'.format(str(str_stmt))) configrule_updates = session.execute(stmt).fetchall() upsert_affected = any([(updated_at > created_at) for created_at,updated_at in configrule_updates]) diff --git a/src/context/service/database/Constraint.py b/src/context/service/database/Constraint.py index 82629b25c8453a8b499635a538ba776189b6116b..cf6e11ac9b0b58e5dc84bbb81b5d25f819ada6f7 100644 --- a/src/context/service/database/Constraint.py +++ b/src/context/service/database/Constraint.py @@ -14,13 +14,15 @@ import datetime, logging from sqlalchemy import delete +#from sqlalchemy.dialects import postgresql from sqlalchemy.dialects.postgresql import insert from sqlalchemy.orm import Session from typing import Dict, List, Optional from common.proto.context_pb2 import Constraint from common.tools.grpc.Tools import grpc_message_to_json_string from .models.ConstraintModel import ConstraintKindEnum, ConstraintModel -from .uuids._Builder import get_uuid_random +from .uuids._Builder import get_uuid_from_string +from .uuids.EndPoint import endpoint_get_uuid LOGGER = logging.getLogger(__name__) @@ -31,16 +33,50 @@ def compose_constraints_data( dict_constraints : List[Dict] = list() for position,constraint in enumerate(constraints): str_kind = constraint.WhichOneof('constraint') + kind = ConstraintKindEnum._member_map_.get(str_kind.upper()) # pylint: disable=no-member dict_constraint = { - 'constraint_uuid': get_uuid_random(), - 'position' : position, - 'kind' : ConstraintKindEnum._member_map_.get(str_kind.upper()), # pylint: disable=no-member - 'data' : grpc_message_to_json_string(getattr(constraint, str_kind, {})), - 'created_at' : now, - 'updated_at' : now, + 'position' : position, + 'kind' : kind, + 'data' : grpc_message_to_json_string(getattr(constraint, str_kind, {})), + 'created_at': now, + 'updated_at': now, } - if service_uuid is not None: dict_constraint['service_uuid'] = service_uuid - if slice_uuid is not None: dict_constraint['slice_uuid' ] = slice_uuid + + parent_kind,parent_uuid = '',None + if service_uuid is not None: + dict_constraint['service_uuid'] = service_uuid + parent_kind,parent_uuid = 'service',service_uuid + elif slice_uuid is not None: + 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})' + str_constraint = grpc_message_to_json_string(constraint) + raise Exception(MSG.format(str_constraint, str(service_uuid), str(slice_uuid))) + + constraint_name = None + if kind == ConstraintKindEnum.CUSTOM: + constraint_name = '{:s}:{:s}:{:s}'.format(parent_kind, kind.value, constraint.custom.constraint_type) + elif kind == ConstraintKindEnum.ENDPOINT_LOCATION: + _, _, endpoint_uuid = endpoint_get_uuid(constraint.endpoint_location.endpoint_id, allow_random=False) + location_kind = constraint.endpoint_location.location.WhichOneof('location') + constraint_name = '{:s}:{:s}:{:s}:{:s}'.format(parent_kind, kind.value, endpoint_uuid, location_kind) + elif kind == ConstraintKindEnum.ENDPOINT_PRIORITY: + _, _, endpoint_uuid = endpoint_get_uuid(constraint.endpoint_priority.endpoint_id, allow_random=False) + constraint_name = '{:s}:{:s}:{:s}'.format(parent_kind, kind.value, endpoint_uuid) + elif kind in { + ConstraintKindEnum.SCHEDULE, ConstraintKindEnum.SLA_CAPACITY, ConstraintKindEnum.SLA_LATENCY, + ConstraintKindEnum.SLA_AVAILABILITY, ConstraintKindEnum.SLA_ISOLATION_LEVEL + }: + constraint_name = '{:s}:{:s}:'.format(parent_kind, kind.value) + else: + 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))) + + constraint_uuid = get_uuid_from_string(constraint_name, prefix_for_name=parent_uuid) + dict_constraint['constraint_uuid'] = constraint_uuid + dict_constraints.append(dict_constraint) return dict_constraints @@ -48,84 +84,47 @@ def upsert_constraints( session : Session, constraints : List[Dict], service_uuid : Optional[str] = None, slice_uuid : Optional[str] = None ) -> bool: - # TODO: do not delete all constraints; just add-remove as needed - stmt = delete(ConstraintModel) - if service_uuid is not None: stmt = stmt.where(ConstraintModel.service_uuid == service_uuid) - if slice_uuid is not None: stmt = stmt.where(ConstraintModel.slice_uuid == slice_uuid ) - session.execute(stmt) + uuids_to_upsert : Dict[str, int] = dict() + rules_to_upsert : List[Dict] = list() + for constraint in constraints: + constraint_uuid = constraint['constraint_uuid'] + position = uuids_to_upsert.get(constraint_uuid) + if position is None: + # if not added, add it + rules_to_upsert.append(constraint) + uuids_to_upsert[constraint_uuid] = len(rules_to_upsert) - 1 + else: + # if already added, update occurrence + rules_to_upsert[position] = constraint + + # Delete all constraints not in uuids_to_upsert + delete_affected = False + if len(uuids_to_upsert) > 0: + stmt = delete(ConstraintModel) + if service_uuid is not None: stmt = stmt.where(ConstraintModel.service_uuid == service_uuid) + if slice_uuid is not None: stmt = stmt.where(ConstraintModel.slice_uuid == slice_uuid ) + stmt = stmt.where(ConstraintModel.constraint_uuid.not_in(set(uuids_to_upsert.keys()))) + #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) + LOGGER.warning('constraint_deletes.rowcount={:s}'.format(str(constraint_deletes.rowcount))) + delete_affected = int(constraint_deletes.rowcount) > 0 - changed = False + upsert_affected = False if len(constraints) > 0: stmt = insert(ConstraintModel).values(constraints) - #stmt = stmt.on_conflict_do_update( - # index_elements=[ConstraintModel.configrule_uuid], - # set_=dict( - # updated_at = stmt.excluded.updated_at, - # ) - #) + stmt = stmt.on_conflict_do_update( + index_elements=[ConstraintModel.constraint_uuid], + set_=dict( + position = stmt.excluded.position, + data = stmt.excluded.data, + updated_at = stmt.excluded.updated_at, + ) + ) stmt = stmt.returning(ConstraintModel.created_at, ConstraintModel.updated_at) + #str_stmt = stmt.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}) + #LOGGER.warning('upsert stmt={:s}'.format(str(str_stmt))) constraint_updates = session.execute(stmt).fetchall() - changed = any([(updated_at > created_at) for created_at,updated_at in constraint_updates]) + upsert_affected = any([(updated_at > created_at) for created_at,updated_at in constraint_updates]) - return changed - - -# def set_constraint(self, db_constraints: ConstraintsModel, grpc_constraint: Constraint, position: int -# ) -> Tuple[Union_ConstraintModel, bool]: -# with self.session() as session: -# -# grpc_constraint_kind = str(grpc_constraint.WhichOneof('constraint')) -# -# parser = CONSTRAINT_PARSERS.get(grpc_constraint_kind) -# if parser is None: -# raise NotImplementedError('Constraint of kind {:s} is not implemented: {:s}'.format( -# grpc_constraint_kind, grpc_message_to_json_string(grpc_constraint))) -# -# # create specific constraint -# constraint_class, str_constraint_id, constraint_data, constraint_kind = parser(grpc_constraint) -# str_constraint_id = str(uuid.uuid4()) -# LOGGER.info('str_constraint_id: {}'.format(str_constraint_id)) -# # str_constraint_key_hash = fast_hasher(':'.join([constraint_kind.value, str_constraint_id])) -# # str_constraint_key = key_to_str([db_constraints.pk, str_constraint_key_hash], separator=':') -# -# # result : Tuple[Union_ConstraintModel, bool] = update_or_create_object( -# # database, constraint_class, str_constraint_key, constraint_data) -# constraint_data[constraint_class.main_pk_name()] = str_constraint_id -# db_new_constraint = constraint_class(**constraint_data) -# result: Tuple[Union_ConstraintModel, bool] = self.database.create_or_update(db_new_constraint) -# db_specific_constraint, updated = result -# -# # create generic constraint -# # constraint_fk_field_name = 'constraint_uuid'.format(constraint_kind.value) -# constraint_data = { -# 'constraints_uuid': db_constraints.constraints_uuid, 'position': position, 'kind': constraint_kind -# } -# -# db_new_constraint = ConstraintModel(**constraint_data) -# result: Tuple[Union_ConstraintModel, bool] = self.database.create_or_update(db_new_constraint) -# db_constraint, updated = result -# -# return db_constraint, updated -# -# def set_constraints(self, service_uuid: str, constraints_name : str, grpc_constraints -# ) -> List[Tuple[Union[ConstraintsModel, ConstraintModel], bool]]: -# with self.session() as session: -# # str_constraints_key = key_to_str([db_parent_pk, constraints_name], separator=':') -# # result : Tuple[ConstraintsModel, bool] = get_or_create_object(database, ConstraintsModel, str_constraints_key) -# result = session.query(ConstraintsModel).filter_by(constraints_uuid=service_uuid).one_or_none() -# created = None -# if result: -# created = True -# session.query(ConstraintsModel).filter_by(constraints_uuid=service_uuid).one_or_none() -# db_constraints = ConstraintsModel(constraints_uuid=service_uuid) -# session.add(db_constraints) -# -# db_objects = [(db_constraints, created)] -# -# for position,grpc_constraint in enumerate(grpc_constraints): -# result : Tuple[ConstraintModel, bool] = self.set_constraint( -# db_constraints, grpc_constraint, position) -# db_constraint, updated = result -# db_objects.append((db_constraint, updated)) -# -# return db_objects + return delete_affected or upsert_affected diff --git a/src/context/service/database/models/ConstraintModel.py b/src/context/service/database/models/ConstraintModel.py index 51fc0b91df07a2c86c5e84692b3dd5edd21fb761..e7767b4b2dfed578f6a2a3ceef19cd2d00a8dfd6 100644 --- a/src/context/service/database/models/ConstraintModel.py +++ b/src/context/service/database/models/ConstraintModel.py @@ -20,11 +20,14 @@ from ._Base import _Base # Enum values should match name of field in Constraint message class ConstraintKindEnum(enum.Enum): - CUSTOM = 'custom' - ENDPOINT_LOCATION_REGION = 'ep_loc_region' - ENDPOINT_LOCATION_GPSPOSITION = 'ep_loc_gpspos' - ENDPOINT_PRIORITY = 'ep_priority' - SLA_AVAILABILITY = 'sla_avail' + CUSTOM = 'custom' + SCHEDULE = 'schedule' + ENDPOINT_LOCATION = 'endpoint_location' + ENDPOINT_PRIORITY = 'endpoint_priority' + SLA_CAPACITY = 'sla_capacity' + SLA_LATENCY = 'sla_latency' + SLA_AVAILABILITY = 'sla_availability' + SLA_ISOLATION_LEVEL = 'sla_isolation' class ConstraintModel(_Base): __tablename__ = 'constraint' @@ -46,354 +49,3 @@ class ConstraintModel(_Base): def dump(self) -> Dict: return {self.kind.value: json.loads(self.data)} - - -#import logging, operator -#from typing import Dict, List, Optional, Tuple, Type, Union -#from common.orm.HighLevel import get_object, get_or_create_object, update_or_create_object -#from common.orm.backend.Tools import key_to_str -#from common.proto.context_pb2 import Constraint -#from common.tools.grpc.Tools import grpc_message_to_json_string -#from .EndPointModel import EndPointModel -#from .Tools import fast_hasher -#from sqlalchemy import Column, ForeignKey, String, Float, CheckConstraint, Integer, Boolean, Enum -#from sqlalchemy.dialects.postgresql import UUID -#from context.service.database.models._Base import Base -#import enum -# -#LOGGER = logging.getLogger(__name__) -# -#def remove_dict_key(dictionary : Dict, key : str): -# dictionary.pop(key, None) -# return dictionary -# -#class ConstraintsModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'Constraints' -# constraints_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# -# @staticmethod -# def main_pk_name(): -# return 'constraints_uuid' -# -# -# def dump(self, constraints) -> List[Dict]: -# constraints = sorted(constraints, key=operator.itemgetter('position')) -# return [remove_dict_key(constraint, 'position') for constraint in constraints] -# -# -#class ConstraintCustomModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'ConstraintCustom' -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# constraint_type = Column(String, nullable=False) -# constraint_value = Column(String, nullable=False) -# -# @staticmethod -# def main_pk_name(): -# return 'constraint_uuid' -# -# -# def dump(self) -> Dict: # pylint: disable=arguments-differ -# return {'custom': {'constraint_type': self.constraint_type, 'constraint_value': self.constraint_value}} -# -# -#Union_ConstraintEndpoint = Union[ -# 'ConstraintEndpointLocationGpsPositionModel', 'ConstraintEndpointLocationRegionModel', -# 'ConstraintEndpointPriorityModel' -#] -# -#class ConstraintEndpointLocationRegionModel(Model): # pylint: disable=abstract-method -# endpoint_fk = ForeignKeyField(EndPointModel) -# region = StringField(required=True, allow_empty=False) -# -# def dump(self) -> Dict: # pylint: disable=arguments-differ -# json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() -# return {'endpoint_location': {'endpoint_id': json_endpoint_id, 'location': {'region': self.region}}} -# -## def dump_endpoint_id(endpoint_constraint: Union_ConstraintEndpoint): -## db_endpoints_pks = list(endpoint_constraint.references(EndPointModel)) -## num_endpoints = len(db_endpoints_pks) -## if num_endpoints != 1: -## raise Exception('Wrong number({:d}) of associated Endpoints with constraint'.format(num_endpoints)) -## db_endpoint = EndPointModel(endpoint_constraint.database, db_endpoints_pks[0]) -## return db_endpoint.dump_id() -# -# -#class ConstraintEndpointLocationRegionModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'ConstraintEndpointLocationRegion' -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid")) -# region = Column(String, nullable=False) -# -# @staticmethod -# def main_pk_name(): -# return 'constraint_uuid' -# -# def dump(self, endpoint) -> Dict: # pylint: disable=arguments-differ -# return {'endpoint_location': {'endpoint_id': endpoint.dump_id(), 'region': self.region}} -# -# def dump(self) -> Dict: # pylint: disable=arguments-differ -# gps_position = {'latitude': self.latitude, 'longitude': self.longitude} -# json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() -# return {'endpoint_location': {'endpoint_id': json_endpoint_id, 'location': {'gps_position': gps_position}}} -# -#class ConstraintEndpointPriorityModel(Model): # pylint: disable=abstract-method -# endpoint_fk = ForeignKeyField(EndPointModel) -# priority = IntegerField(required=True, min_value=0) -# -# def dump(self) -> Dict: # pylint: disable=arguments-differ -# json_endpoint_id = EndPointModel(self.database, self.endpoint_fk).dump_id() -# return {'endpoint_priority': {'endpoint_id': json_endpoint_id, 'priority': self.priority}} -# -#class ConstraintEndpointLocationGpsPositionModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'ConstraintEndpointLocationGpsPosition' -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid")) -# latitude = Column(Float, CheckConstraint('latitude > -90.0 AND latitude < 90.0'), nullable=False) -# longitude = Column(Float, CheckConstraint('longitude > -90.0 AND longitude < 90.0'), nullable=False) -# -# def dump(self, endpoint) -> Dict: # pylint: disable=arguments-differ -# gps_position = {'latitude': self.latitude, 'longitude': self.longitude} -# return {'endpoint_location': {'endpoint_id': endpoint.dump_id(), 'gps_position': gps_position}} -# -# -#class ConstraintEndpointPriorityModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'ConstraintEndpointPriority' -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid")) -# # endpoint_fk = ForeignKeyField(EndPointModel) -# # priority = FloatField(required=True) -# priority = Column(Float, nullable=False) -# @staticmethod -# def main_pk_name(): -# return 'constraint_uuid' -# -# def dump(self, endpoint) -> Dict: # pylint: disable=arguments-differ -# return {'endpoint_priority': {'endpoint_id': endpoint.dump_id(), 'priority': self.priority}} -# -# -#class ConstraintSlaAvailabilityModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'ConstraintSlaAvailability' -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# # num_disjoint_paths = IntegerField(required=True, min_value=1) -# num_disjoint_paths = Column(Integer, CheckConstraint('num_disjoint_paths > 1'), nullable=False) -# # all_active = BooleanField(required=True) -# all_active = Column(Boolean, nullable=False) -# @staticmethod -# def main_pk_name(): -# return 'constraint_uuid' -# -# def dump(self) -> Dict: # pylint: disable=arguments-differ -# return {'sla_availability': {'num_disjoint_paths': self.num_disjoint_paths, 'all_active': self.all_active}} -# -#Union_SpecificConstraint = Union[ -# ConstraintCustomModel, ConstraintEndpointLocationRegionModel, ConstraintEndpointLocationGpsPositionModel, -# ConstraintEndpointPriorityModel, ConstraintSlaAvailabilityModel, -#] -# -#class ConstraintModel(Base): # pylint: disable=abstract-method -# __tablename__ = 'Constraint' -# # pk = PrimaryKeyField() -# # constraints_fk = ForeignKeyField(ConstraintsModel) -# constraint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True) -# constraints_uuid = Column(UUID(as_uuid=False), ForeignKey("Constraints.constraints_uuid"), primary_key=True) -# # kind = EnumeratedField(ConstraintKindEnum) -# kind = Column(Enum(ConstraintKindEnum, create_constraint=False, native_enum=False)) -# # position = IntegerField(min_value=0, required=True) -# position = Column(Integer, CheckConstraint('position >= 0'), nullable=False) -# # constraint_custom_fk = ForeignKeyField(ConstraintCustomModel, required=False) -# constraint_custom = Column(UUID(as_uuid=False), ForeignKey("ConstraintCustom.constraint_uuid")) -# # constraint_ep_loc_region_fk = ForeignKeyField(ConstraintEndpointLocationRegionModel, required=False) -# constraint_ep_loc_region = Column(UUID(as_uuid=False), ForeignKey("ConstraintEndpointLocationRegion.constraint_uuid")) -# # constraint_ep_loc_gpspos_fk = ForeignKeyField(ConstraintEndpointLocationGpsPositionModel, required=False) -# constraint_ep_loc_gpspos = Column(UUID(as_uuid=False), ForeignKey("ConstraintEndpointLocationGpsPosition.constraint_uuid")) -# # constraint_ep_priority_fk = ForeignKeyField(ConstraintEndpointPriorityModel, required=False) -# constraint_ep_priority = Column(UUID(as_uuid=False), ForeignKey("ConstraintEndpointPriority.constraint_uuid"),) -# # constraint_sla_avail_fk = ForeignKeyField(ConstraintSlaAvailabilityModel, required=False) -# constraint_sla_avail = Column(UUID(as_uuid=False), ForeignKey("ConstraintSlaAvailability.constraint_uuid")) -# -# @staticmethod -# def main_pk_name(): -# return 'constraint_uuid' -# -# # def delete(self) -> None: -# # field_name = 'constraint_{:s}_fk'.format(str(self.kind.value)) -# # specific_fk_value : Optional[ForeignKeyField] = getattr(self, field_name, None) -# # if specific_fk_value is None: -# # raise Exception('Unable to find constraint key for field_name({:s})'.format(field_name)) -# # specific_fk_class = getattr(ConstraintModel, field_name, None) -# # foreign_model_class : Model = specific_fk_class.foreign_model -# # super().delete() -# # get_object(self.database, foreign_model_class, str(specific_fk_value)).delete() -# -# def dump(self, include_position=True) -> Dict: # pylint: disable=arguments-differ -# field_name = 'constraint_{:s}'.format(str(self.kind.value)) -# specific_fk_value = getattr(self, field_name, None) -# if specific_fk_value is None: -# raise Exception('Unable to find constraint key for field_name({:s})'.format(field_name)) -# specific_fk_class = getattr(ConstraintModel, field_name, None) -# foreign_model_class: Base = specific_fk_class.foreign_model -# constraint: Union_SpecificConstraint = get_object(self.database, foreign_model_class, str(specific_fk_value)) -# result = constraint.dump() -# if include_position: -# result['position'] = self.position -# return result -# -#Tuple_ConstraintSpecs = Tuple[Type, str, Dict, ConstraintKindEnum] -# -#def parse_constraint_custom(grpc_constraint) -> Tuple_ConstraintSpecs: -# constraint_class = ConstraintCustomModel -# str_constraint_id = grpc_constraint.custom.constraint_type -# constraint_data = { -# 'constraint_type' : grpc_constraint.custom.constraint_type, -# 'constraint_value': grpc_constraint.custom.constraint_value, -# } -# return constraint_class, str_constraint_id, constraint_data, ConstraintKindEnum.CUSTOM -# -#def parse_constraint_endpoint_location(db_endpoint, grpc_constraint) -> Tuple_ConstraintSpecs: -# grpc_endpoint_id = grpc_constraint.endpoint_location.endpoint_id -# # str_endpoint_key, db_endpoint = get_endpoint(database, grpc_endpoint_id) -# -# str_constraint_id = db_endpoint.endpoint_uuid -# constraint_data = {'endpoint_fk': db_endpoint} -# -# grpc_location = grpc_constraint.endpoint_location.location -# location_kind = str(grpc_location.WhichOneof('location')) -# if location_kind == 'region': -# constraint_class = ConstraintEndpointLocationRegionModel -# constraint_data.update({'region': grpc_location.region}) -# return constraint_class, str_constraint_id, constraint_data, ConstraintKindEnum.ENDPOINT_LOCATION_REGION -# elif location_kind == 'gps_position': -# constraint_class = ConstraintEndpointLocationGpsPositionModel -# gps_position = grpc_location.gps_position -# constraint_data.update({'latitude': gps_position.latitude, 'longitude': gps_position.longitude}) -# return constraint_class, str_constraint_id, constraint_data, ConstraintKindEnum.ENDPOINT_LOCATION_GPSPOSITION -# else: -# MSG = 'Location kind {:s} in Constraint of kind endpoint_location is not implemented: {:s}' -# raise NotImplementedError(MSG.format(location_kind, grpc_message_to_json_string(grpc_constraint))) -# -#def parse_constraint_endpoint_priority(db_endpoint, grpc_constraint) -> Tuple_ConstraintSpecs: -# grpc_endpoint_id = grpc_constraint.endpoint_priority.endpoint_id -# # str_endpoint_key, db_endpoint = get_endpoint(database, grpc_endpoint_id) -# -# constraint_class = ConstraintEndpointPriorityModel -# str_constraint_id = db_endpoint.endpoint_uuid -# priority = grpc_constraint.endpoint_priority.priority -# constraint_data = {'endpoint_fk': db_endpoint, 'priority': priority} -# -# return constraint_class, str_constraint_id, constraint_data, ConstraintKindEnum.ENDPOINT_PRIORITY -# -#def parse_constraint_sla_availability(grpc_constraint) -> Tuple_ConstraintSpecs: -# constraint_class = ConstraintSlaAvailabilityModel -# str_constraint_id = '' -# constraint_data = { -# 'num_disjoint_paths' : grpc_constraint.sla_availability.num_disjoint_paths, -# 'all_active': grpc_constraint.sla_availability.all_active, -# } -# return constraint_class, str_constraint_id, constraint_data, ConstraintKindEnum.SLA_AVAILABILITY -# -#CONSTRAINT_PARSERS = { -# 'custom' : parse_constraint_custom, -# 'endpoint_location' : parse_constraint_endpoint_location, -# 'endpoint_priority' : parse_constraint_endpoint_priority, -# 'sla_availability' : parse_constraint_sla_availability, -#} -# -#Union_ConstraintModel = Union[ -# ConstraintCustomModel, ConstraintEndpointLocationGpsPositionModel, ConstraintEndpointLocationRegionModel, -# ConstraintEndpointPriorityModel, ConstraintSlaAvailabilityModel -#] -# -## def set_constraint( -## db_constraints : ConstraintsModel, grpc_constraint : Constraint, position : int -## ) -> Tuple[Union_ConstraintModel, bool]: -## grpc_constraint_kind = str(grpc_constraint.WhichOneof('constraint')) -## -## parser = CONSTRAINT_PARSERS.get(grpc_constraint_kind) -## if parser is None: -## raise NotImplementedError('Constraint of kind {:s} is not implemented: {:s}'.format( -## grpc_constraint_kind, grpc_message_to_json_string(grpc_constraint))) -## -## # create specific constraint -## constraint_class, str_constraint_id, constraint_data, constraint_kind = parser(database, grpc_constraint) -## str_constraint_key_hash = fast_hasher(':'.join([constraint_kind.value, str_constraint_id])) -## str_constraint_key = key_to_str([db_constraints.pk, str_constraint_key_hash], separator=':') -## result : Tuple[Union_ConstraintModel, bool] = update_or_create_object( -## database, constraint_class, str_constraint_key, constraint_data) -## db_specific_constraint, updated = result -## -## # create generic constraint -## constraint_fk_field_name = 'constraint_{:s}_fk'.format(constraint_kind.value) -## constraint_data = { -## 'constraints_fk': db_constraints, 'position': position, 'kind': constraint_kind, -## constraint_fk_field_name: db_specific_constraint -## } -## result : Tuple[ConstraintModel, bool] = update_or_create_object( -## database, ConstraintModel, str_constraint_key, constraint_data) -## db_constraint, updated = result -## -## return db_constraint, updated -## -## def set_constraints( -## database : Database, db_parent_pk : str, constraints_name : str, grpc_constraints -## ) -> List[Tuple[Union[ConstraintsModel, ConstraintModel], bool]]: -## -## str_constraints_key = key_to_str([db_parent_pk, constraints_name], separator=':') -## result : Tuple[ConstraintsModel, bool] = get_or_create_object(database, ConstraintsModel, str_constraints_key) -## db_constraints, created = result -## -## db_objects = [(db_constraints, created)] -## -## for position,grpc_constraint in enumerate(grpc_constraints): -## result : Tuple[ConstraintModel, bool] = set_constraint( -## database, db_constraints, grpc_constraint, position) -## db_constraint, updated = result -## db_objects.append((db_constraint, updated)) -## -## return db_objects -#def set_constraint( -# database : Database, db_constraints : ConstraintsModel, grpc_constraint : Constraint, position : int -#) -> Tuple[Union_ConstraintModel, bool]: -# grpc_constraint_kind = str(grpc_constraint.WhichOneof('constraint')) -# -# parser = CONSTRAINT_PARSERS.get(grpc_constraint_kind) -# if parser is None: -# raise NotImplementedError('Constraint of kind {:s} is not implemented: {:s}'.format( -# grpc_constraint_kind, grpc_message_to_json_string(grpc_constraint))) -# -# # create specific constraint -# constraint_class, str_constraint_id, constraint_data, constraint_kind = parser(database, grpc_constraint) -# str_constraint_key_hash = fast_hasher(':'.join([constraint_kind.value, str_constraint_id])) -# str_constraint_key = key_to_str([db_constraints.pk, str_constraint_key_hash], separator=':') -# result : Tuple[Union_ConstraintModel, bool] = update_or_create_object( -# database, constraint_class, str_constraint_key, constraint_data) -# db_specific_constraint, updated = result -# -# # create generic constraint -# constraint_fk_field_name = 'constraint_{:s}_fk'.format(constraint_kind.value) -# constraint_data = { -# 'constraints_fk': db_constraints, 'position': position, 'kind': constraint_kind, -# constraint_fk_field_name: db_specific_constraint -# } -# result : Tuple[ConstraintModel, bool] = update_or_create_object( -# database, ConstraintModel, str_constraint_key, constraint_data) -# db_constraint, updated = result -# -# return db_constraint, updated -# -#def set_constraints( -# database : Database, db_parent_pk : str, constraints_name : str, grpc_constraints -#) -> List[Tuple[Union[ConstraintsModel, ConstraintModel], bool]]: -# -# str_constraints_key = key_to_str([constraints_name, db_parent_pk], separator=':') -# result : Tuple[ConstraintsModel, bool] = get_or_create_object(database, ConstraintsModel, str_constraints_key) -# db_constraints, created = result -# -# db_objects = [(db_constraints, created)] -# -# for position,grpc_constraint in enumerate(grpc_constraints): -# result : Tuple[ConstraintModel, bool] = set_constraint( -# database, db_constraints, grpc_constraint, position) -# db_constraint, updated = result -# db_objects.append((db_constraint, updated)) -# -# return db_objects