Loading proto/context.proto +16 −9 Original line number Diff line number Diff line Loading @@ -494,6 +494,12 @@ message ConfigRule { // ----- Constraint ---------------------------------------------------------------------------------------------------- enum ConstraintActionEnum { CONSTRAINTACTION_UNDEFINED = 0; CONSTRAINTACTION_SET = 1; CONSTRAINTACTION_DELETE = 2; } message Constraint_Custom { string constraint_type = 1; string constraint_value = 2; Loading Loading @@ -564,16 +570,17 @@ message Constraint_Exclusions { } message Constraint { ConstraintActionEnum action = 1; oneof constraint { Constraint_Custom custom = 1; Constraint_Schedule schedule = 2; Constraint_EndPointLocation endpoint_location = 3; Constraint_EndPointPriority endpoint_priority = 4; Constraint_SLA_Capacity sla_capacity = 5; Constraint_SLA_Latency sla_latency = 6; Constraint_SLA_Availability sla_availability = 7; Constraint_SLA_Isolation_level sla_isolation = 8; Constraint_Exclusions exclusions = 9; Constraint_Custom custom = 2; Constraint_Schedule schedule = 3; Constraint_EndPointLocation endpoint_location = 4; Constraint_EndPointPriority endpoint_priority = 5; Constraint_SLA_Capacity sla_capacity = 6; Constraint_SLA_Latency sla_latency = 7; Constraint_SLA_Availability sla_availability = 8; Constraint_SLA_Isolation_level sla_isolation = 9; Constraint_Exclusions exclusions = 10; } } Loading src/common/tests/MockServicerImpl_Context.py +100 −7 Original line number Diff line number Diff line Loading @@ -13,15 +13,14 @@ # limitations under the License. import grpc, json, logging from typing import Any, Dict, Iterator, List from typing import Any, Dict, Iterator, List, Set from common.proto.context_pb2 import ( Connection, ConnectionEvent, ConnectionId, ConnectionIdList, ConnectionList, Context, ContextEvent, ContextId, ContextIdList, ContextList, Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceId, SliceIdList, SliceList, Device, DeviceEvent, DeviceFilter, DeviceId, DeviceIdList, DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) from common.proto.context_pb2_grpc import ContextServiceServicer from common.tests.MockMessageBroker import ( Loading Loading @@ -68,10 +67,19 @@ def del_entry( del container[entry_uuid] return Empty() def select_entries(database : Dict[str, Dict[str, Any]], container_name : str, entry_uuids : Set[str]) -> List[Any]: if len(entry_uuids) == 0: return get_entries(database, container_name) container = get_container(database, container_name) return [ container[entry_uuid] for entry_uuid in sorted(container.keys()) if entry_uuid in entry_uuids ] class MockServicerImpl_Context(ContextServiceServicer): def __init__(self): LOGGER.info('[__init__] Creating Servicer...') self.database : Dict[str, Any] = {} self.database : Dict[str, Dict[str, Any]] = {} self.msg_broker = MockMessageBroker() LOGGER.info('[__init__] Servicer Created') Loading Loading @@ -210,6 +218,33 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetDeviceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_DEVICE}): yield DeviceEvent(**json.loads(message.content)) def SelectDevice(self, request : DeviceFilter, context : grpc.ServicerContext) -> DeviceList: LOGGER.info('[SelectDevice] request={:s}'.format(grpc_message_to_json_string(request))) container_entry_uuids : Dict[str, Set[str]] = {} container_name = 'device' for device_id in request.device_ids: device_uuid = device_id.device_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(device_uuid) exclude_endpoints = not request.include_endpoints exclude_config_rules = not request.include_config_rules exclude_components = not request.include_components devices = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for device in select_entries(self.database, container_name, entry_uuids): reply_device = Device() reply_device.CopyFrom(device) if exclude_endpoints: del reply_device.device_endpoints [:] # pylint: disable=no-member if exclude_config_rules: del reply_device.device_config.config_rules[:] # pylint: disable=no-member if exclude_components: del reply_device.component[:] # pylint: disable=no-member devices.append(reply_device) reply = DeviceList(devices=devices) LOGGER.info('[SelectDevice] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Link ------------------------------------------------------------------------------------------------------- Loading Loading @@ -291,6 +326,37 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetSliceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_SLICE}): yield SliceEvent(**json.loads(message.content)) def SelectSlice(self, request : SliceFilter, context : grpc.ServicerContext) -> SliceList: LOGGER.info('[SelectSlice] request={:s}'.format(grpc_message_to_json_string(request))) container_entry_uuids : Dict[str, Set[str]] = {} for slice_id in request.slice_ids: container_name = 'slice[{:s}]'.format(str(slice_id.context_id.context_uuid.uuid)) slice_uuid = slice_id.slice_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(slice_uuid) exclude_endpoint_ids = not request.include_endpoint_ids exclude_constraints = not request.include_constraints exclude_service_ids = not request.include_service_ids exclude_subslice_ids = not request.include_subslice_ids exclude_config_rules = not request.include_config_rules slices = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for eslice in select_entries(self.database, container_name, entry_uuids): reply_slice = Slice() reply_slice.CopyFrom(eslice) if exclude_endpoint_ids: del reply_slice.service_endpoint_ids[:] # pylint: disable=no-member if exclude_constraints : del reply_slice.service_constraints[:] # pylint: disable=no-member if exclude_service_ids : del reply_slice.slice_service_ids[:] # pylint: disable=no-member if exclude_subslice_ids : del reply_slice.slice_subslice_ids[:] # pylint: disable=no-member if exclude_config_rules: del reply_slice.slice_config .config_rules[:] # pylint: disable=no-member slices.append(reply_slice) reply = SliceList(slices=slices) LOGGER.info('[SelectSlice] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Service ---------------------------------------------------------------------------------------------------- Loading Loading @@ -335,6 +401,33 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetServiceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_SERVICE}): yield ServiceEvent(**json.loads(message.content)) def SelectService(self, request : ServiceFilter, context : grpc.ServicerContext) -> ServiceList: LOGGER.info('[SelectService] request={:s}'.format(grpc_message_to_json_string(request))) LOGGER.warning('type: {}'.format(type(request))) container_entry_uuids : Dict[str, Set[str]] = {} for service_id in request.service_ids.service_ids: container_name = 'service[{:s}]'.format(str(service_id.context_id.context_uuid.uuid)) service_uuid = service_id.service_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(service_uuid) exclude_endpoint_ids = not request.include_endpoint_ids exclude_constraints = not request.include_constraints exclude_config_rules = not request.include_config_rules services = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for service in select_entries(self.database, container_name, entry_uuids): reply_service = Service() reply_service.CopyFrom(service) if exclude_endpoint_ids: del reply_service.service_endpoint_ids[:] # pylint: disable=no-member if exclude_constraints : del reply_service.service_constraints[:] # pylint: disable=no-member if exclude_config_rules: del reply_service.service_config.config_rules[:] # pylint: disable=no-member services.append(reply_service) reply = ServiceList(services=services) LOGGER.info('[SelectService] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Connection ------------------------------------------------------------------------------------------------- Loading src/compute/service/rest_server/nbi_plugins/debug_api/Resources.py +26 −2 Original line number Diff line number Diff line Loading @@ -12,18 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. from flask_restful import Resource from flask_restful import Resource, request from common.proto.context_pb2 import Empty from context.client.ContextClient import ContextClient from service.client.ServiceClient import ServiceClient import logging from .Tools import ( format_grpc_to_json, grpc_connection_id, grpc_context_id, grpc_device_id, grpc_link_id, grpc_policy_rule_id, grpc_service_id, grpc_slice_id, grpc_topology_id) grpc_service_id, grpc_service, grpc_slice_id, grpc_topology_id) LOGGER = logging.getLogger(__name__) class _Resource(Resource): def __init__(self) -> None: super().__init__() self.client = ContextClient() self.service_client = ServiceClient() class ContextIds(_Resource): def get(self): Loading Loading @@ -60,6 +64,26 @@ class Services(_Resource): class Service(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.client.GetService(grpc_service_id(context_uuid, service_uuid))) def post(self, context_uuid : str, service_uuid : str): service = request.get_json()['services'][0] return format_grpc_to_json(self.service_client.CreateService(grpc_service( service_uuid = service['service_id']['service_uuid']['uuid'], service_type = service['service_type'], context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], ))) def put(self, context_uuid : str, service_uuid : str): service = request.get_json()['services'][0] return format_grpc_to_json(self.service_client.UpdateService(grpc_service( service_uuid = service['service_id']['service_uuid']['uuid'], service_type = service['service_type'], context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], status = service['service_status']['service_status'], endpoint_ids = service['service_endpoint_ids'], constraints = service['service_constraints'], config_rules = service['service_config']['config_rules'] ))) class SliceIds(_Resource): def get(self, context_uuid : str): Loading src/compute/service/rest_server/nbi_plugins/debug_api/Tools.py +15 −2 Original line number Diff line number Diff line Loading @@ -13,17 +13,21 @@ # limitations under the License. from flask.json import jsonify from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, LinkId, ServiceId, SliceId, TopologyId from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, LinkId, ServiceId, SliceId, TopologyId, Service from common.proto.policy_pb2 import PolicyRuleId from common.tools.grpc.Tools import grpc_message_to_json from common.tools.object_factory.Connection import json_connection_id from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.ConfigRule import json_config_rule from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.EndPoint import json_endpoint_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.Link import json_link_id from common.tools.object_factory.PolicyRule import json_policyrule_id from common.tools.object_factory.Service import json_service_id from common.tools.object_factory.Service import json_service_id, json_service from common.tools.object_factory.Slice import json_slice_id from common.tools.object_factory.Topology import json_topology_id from common.proto.context_pb2 import ServiceStatusEnum def format_grpc_to_json(grpc_reply): Loading @@ -44,6 +48,15 @@ def grpc_link_id(link_uuid): def grpc_service_id(context_uuid, service_uuid): return ServiceId(**json_service_id(service_uuid, context_id=json_context_id(context_uuid))) def grpc_service(service_uuid, service_type, context_uuid, status=None, endpoint_ids=None, constraints=None, config_rules=None): json_context = json_context_id(context_uuid) json_status = status if status else ServiceStatusEnum.SERVICESTATUS_PLANNED json_endpoints_ids = [json_endpoint_id(json_device_id(endpoint_id['device_id']['device_uuid']['uuid']), endpoint_id['endpoint_uuid']['uuid']) for endpoint_id in endpoint_ids] if endpoint_ids else [] json_constraints = [json_constraint_custom(constraint['custom']['constraint_type'], constraint['custom']['constraint_value']) for constraint in constraints] if constraints else [] json_config_rules = [json_config_rule(config_rule['action'], config_rule['custom']['resource_key'],config_rule['custom']['resource_value']) for config_rule in config_rules] if config_rules else [] return Service(**json_service(service_uuid, service_type, json_context, json_status, json_endpoints_ids, json_constraints, json_config_rules)) def grpc_slice_id(context_uuid, slice_uuid): return SliceId(**json_slice_id(slice_uuid, context_id=json_context_id(context_uuid))) Loading src/context/service/database/Constraint.py +25 −14 Original line number Diff line number Diff line Loading @@ -17,12 +17,14 @@ 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 typing import Dict, List, Optional, Set from common.proto.context_pb2 import Constraint from common.tools.grpc.Tools import grpc_message_to_json_string from .models.ConstraintModel import ConstraintKindEnum, ServiceConstraintModel, SliceConstraintModel from .models.enums.ConstraintAction import ORM_ConstraintActionEnum, grpc_to_enum__constraint_action from .uuids._Builder import get_uuid_from_string from .uuids.EndPoint import endpoint_get_uuid import json LOGGER = logging.getLogger(__name__) Loading @@ -40,8 +42,8 @@ def compose_constraints_data( '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 Loading @@ -58,9 +60,9 @@ def compose_constraints_data( 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) _, _, 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, '', location_kind) 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) Loading @@ -78,6 +80,7 @@ def compose_constraints_data( dict_constraint['constraint_uuid'] = constraint_uuid dict_constraints.append(dict_constraint) return dict_constraints def upsert_constraints( Loading @@ -91,11 +94,16 @@ 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_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: position = uuids_to_upsert.get(constraint_uuid) if position is None: # if not added, add it Loading @@ -104,10 +112,13 @@ def upsert_constraints( else: # if already added, update occurrence rules_to_upsert[position] = constraint else: MSG = 'Action for ConstraintRule({:s}) is not supported (service_uuid={:s}, slice_uuid={:s})' LOGGER.warning(MSG.format(str(constraint), str(service_uuid), str(slice_uuid))) # raise Exception(MSG.format(str_constraint, str(service_uuid), str(slice_uuid))) # Delete all constraints not in uuids_to_upsert delete_affected = False if len(uuids_to_upsert) > 0: if len(uuids_to_delete) > 0: 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 ) Loading Loading
proto/context.proto +16 −9 Original line number Diff line number Diff line Loading @@ -494,6 +494,12 @@ message ConfigRule { // ----- Constraint ---------------------------------------------------------------------------------------------------- enum ConstraintActionEnum { CONSTRAINTACTION_UNDEFINED = 0; CONSTRAINTACTION_SET = 1; CONSTRAINTACTION_DELETE = 2; } message Constraint_Custom { string constraint_type = 1; string constraint_value = 2; Loading Loading @@ -564,16 +570,17 @@ message Constraint_Exclusions { } message Constraint { ConstraintActionEnum action = 1; oneof constraint { Constraint_Custom custom = 1; Constraint_Schedule schedule = 2; Constraint_EndPointLocation endpoint_location = 3; Constraint_EndPointPriority endpoint_priority = 4; Constraint_SLA_Capacity sla_capacity = 5; Constraint_SLA_Latency sla_latency = 6; Constraint_SLA_Availability sla_availability = 7; Constraint_SLA_Isolation_level sla_isolation = 8; Constraint_Exclusions exclusions = 9; Constraint_Custom custom = 2; Constraint_Schedule schedule = 3; Constraint_EndPointLocation endpoint_location = 4; Constraint_EndPointPriority endpoint_priority = 5; Constraint_SLA_Capacity sla_capacity = 6; Constraint_SLA_Latency sla_latency = 7; Constraint_SLA_Availability sla_availability = 8; Constraint_SLA_Isolation_level sla_isolation = 9; Constraint_Exclusions exclusions = 10; } } Loading
src/common/tests/MockServicerImpl_Context.py +100 −7 Original line number Diff line number Diff line Loading @@ -13,15 +13,14 @@ # limitations under the License. import grpc, json, logging from typing import Any, Dict, Iterator, List from typing import Any, Dict, Iterator, List, Set from common.proto.context_pb2 import ( Connection, ConnectionEvent, ConnectionId, ConnectionIdList, ConnectionList, Context, ContextEvent, ContextId, ContextIdList, ContextList, Device, DeviceEvent, DeviceId, DeviceIdList, DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceId, SliceIdList, SliceList, Device, DeviceEvent, DeviceFilter, DeviceId, DeviceIdList, DeviceList, Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyEvent, TopologyId, TopologyIdList, TopologyList) from common.proto.context_pb2_grpc import ContextServiceServicer from common.tests.MockMessageBroker import ( Loading Loading @@ -68,10 +67,19 @@ def del_entry( del container[entry_uuid] return Empty() def select_entries(database : Dict[str, Dict[str, Any]], container_name : str, entry_uuids : Set[str]) -> List[Any]: if len(entry_uuids) == 0: return get_entries(database, container_name) container = get_container(database, container_name) return [ container[entry_uuid] for entry_uuid in sorted(container.keys()) if entry_uuid in entry_uuids ] class MockServicerImpl_Context(ContextServiceServicer): def __init__(self): LOGGER.info('[__init__] Creating Servicer...') self.database : Dict[str, Any] = {} self.database : Dict[str, Dict[str, Any]] = {} self.msg_broker = MockMessageBroker() LOGGER.info('[__init__] Servicer Created') Loading Loading @@ -210,6 +218,33 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetDeviceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_DEVICE}): yield DeviceEvent(**json.loads(message.content)) def SelectDevice(self, request : DeviceFilter, context : grpc.ServicerContext) -> DeviceList: LOGGER.info('[SelectDevice] request={:s}'.format(grpc_message_to_json_string(request))) container_entry_uuids : Dict[str, Set[str]] = {} container_name = 'device' for device_id in request.device_ids: device_uuid = device_id.device_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(device_uuid) exclude_endpoints = not request.include_endpoints exclude_config_rules = not request.include_config_rules exclude_components = not request.include_components devices = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for device in select_entries(self.database, container_name, entry_uuids): reply_device = Device() reply_device.CopyFrom(device) if exclude_endpoints: del reply_device.device_endpoints [:] # pylint: disable=no-member if exclude_config_rules: del reply_device.device_config.config_rules[:] # pylint: disable=no-member if exclude_components: del reply_device.component[:] # pylint: disable=no-member devices.append(reply_device) reply = DeviceList(devices=devices) LOGGER.info('[SelectDevice] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Link ------------------------------------------------------------------------------------------------------- Loading Loading @@ -291,6 +326,37 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetSliceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_SLICE}): yield SliceEvent(**json.loads(message.content)) def SelectSlice(self, request : SliceFilter, context : grpc.ServicerContext) -> SliceList: LOGGER.info('[SelectSlice] request={:s}'.format(grpc_message_to_json_string(request))) container_entry_uuids : Dict[str, Set[str]] = {} for slice_id in request.slice_ids: container_name = 'slice[{:s}]'.format(str(slice_id.context_id.context_uuid.uuid)) slice_uuid = slice_id.slice_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(slice_uuid) exclude_endpoint_ids = not request.include_endpoint_ids exclude_constraints = not request.include_constraints exclude_service_ids = not request.include_service_ids exclude_subslice_ids = not request.include_subslice_ids exclude_config_rules = not request.include_config_rules slices = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for eslice in select_entries(self.database, container_name, entry_uuids): reply_slice = Slice() reply_slice.CopyFrom(eslice) if exclude_endpoint_ids: del reply_slice.service_endpoint_ids[:] # pylint: disable=no-member if exclude_constraints : del reply_slice.service_constraints[:] # pylint: disable=no-member if exclude_service_ids : del reply_slice.slice_service_ids[:] # pylint: disable=no-member if exclude_subslice_ids : del reply_slice.slice_subslice_ids[:] # pylint: disable=no-member if exclude_config_rules: del reply_slice.slice_config .config_rules[:] # pylint: disable=no-member slices.append(reply_slice) reply = SliceList(slices=slices) LOGGER.info('[SelectSlice] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Service ---------------------------------------------------------------------------------------------------- Loading Loading @@ -335,6 +401,33 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.info('[GetServiceEvents] request={:s}'.format(grpc_message_to_json_string(request))) for message in self.msg_broker.consume({TOPIC_SERVICE}): yield ServiceEvent(**json.loads(message.content)) def SelectService(self, request : ServiceFilter, context : grpc.ServicerContext) -> ServiceList: LOGGER.info('[SelectService] request={:s}'.format(grpc_message_to_json_string(request))) LOGGER.warning('type: {}'.format(type(request))) container_entry_uuids : Dict[str, Set[str]] = {} for service_id in request.service_ids.service_ids: container_name = 'service[{:s}]'.format(str(service_id.context_id.context_uuid.uuid)) service_uuid = service_id.service_uuid.uuid container_entry_uuids.setdefault(container_name, set()).add(service_uuid) exclude_endpoint_ids = not request.include_endpoint_ids exclude_constraints = not request.include_constraints exclude_config_rules = not request.include_config_rules services = list() for container_name in sorted(container_entry_uuids.keys()): entry_uuids = container_entry_uuids[container_name] for service in select_entries(self.database, container_name, entry_uuids): reply_service = Service() reply_service.CopyFrom(service) if exclude_endpoint_ids: del reply_service.service_endpoint_ids[:] # pylint: disable=no-member if exclude_constraints : del reply_service.service_constraints[:] # pylint: disable=no-member if exclude_config_rules: del reply_service.service_config.config_rules[:] # pylint: disable=no-member services.append(reply_service) reply = ServiceList(services=services) LOGGER.info('[SelectService] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply # ----- Connection ------------------------------------------------------------------------------------------------- Loading
src/compute/service/rest_server/nbi_plugins/debug_api/Resources.py +26 −2 Original line number Diff line number Diff line Loading @@ -12,18 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. from flask_restful import Resource from flask_restful import Resource, request from common.proto.context_pb2 import Empty from context.client.ContextClient import ContextClient from service.client.ServiceClient import ServiceClient import logging from .Tools import ( format_grpc_to_json, grpc_connection_id, grpc_context_id, grpc_device_id, grpc_link_id, grpc_policy_rule_id, grpc_service_id, grpc_slice_id, grpc_topology_id) grpc_service_id, grpc_service, grpc_slice_id, grpc_topology_id) LOGGER = logging.getLogger(__name__) class _Resource(Resource): def __init__(self) -> None: super().__init__() self.client = ContextClient() self.service_client = ServiceClient() class ContextIds(_Resource): def get(self): Loading Loading @@ -60,6 +64,26 @@ class Services(_Resource): class Service(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.client.GetService(grpc_service_id(context_uuid, service_uuid))) def post(self, context_uuid : str, service_uuid : str): service = request.get_json()['services'][0] return format_grpc_to_json(self.service_client.CreateService(grpc_service( service_uuid = service['service_id']['service_uuid']['uuid'], service_type = service['service_type'], context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], ))) def put(self, context_uuid : str, service_uuid : str): service = request.get_json()['services'][0] return format_grpc_to_json(self.service_client.UpdateService(grpc_service( service_uuid = service['service_id']['service_uuid']['uuid'], service_type = service['service_type'], context_uuid = service['service_id']['context_id']['context_uuid']['uuid'], status = service['service_status']['service_status'], endpoint_ids = service['service_endpoint_ids'], constraints = service['service_constraints'], config_rules = service['service_config']['config_rules'] ))) class SliceIds(_Resource): def get(self, context_uuid : str): Loading
src/compute/service/rest_server/nbi_plugins/debug_api/Tools.py +15 −2 Original line number Diff line number Diff line Loading @@ -13,17 +13,21 @@ # limitations under the License. from flask.json import jsonify from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, LinkId, ServiceId, SliceId, TopologyId from common.proto.context_pb2 import ConnectionId, ContextId, DeviceId, LinkId, ServiceId, SliceId, TopologyId, Service from common.proto.policy_pb2 import PolicyRuleId from common.tools.grpc.Tools import grpc_message_to_json from common.tools.object_factory.Connection import json_connection_id from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.ConfigRule import json_config_rule from common.tools.object_factory.Constraint import json_constraint_custom from common.tools.object_factory.EndPoint import json_endpoint_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.Link import json_link_id from common.tools.object_factory.PolicyRule import json_policyrule_id from common.tools.object_factory.Service import json_service_id from common.tools.object_factory.Service import json_service_id, json_service from common.tools.object_factory.Slice import json_slice_id from common.tools.object_factory.Topology import json_topology_id from common.proto.context_pb2 import ServiceStatusEnum def format_grpc_to_json(grpc_reply): Loading @@ -44,6 +48,15 @@ def grpc_link_id(link_uuid): def grpc_service_id(context_uuid, service_uuid): return ServiceId(**json_service_id(service_uuid, context_id=json_context_id(context_uuid))) def grpc_service(service_uuid, service_type, context_uuid, status=None, endpoint_ids=None, constraints=None, config_rules=None): json_context = json_context_id(context_uuid) json_status = status if status else ServiceStatusEnum.SERVICESTATUS_PLANNED json_endpoints_ids = [json_endpoint_id(json_device_id(endpoint_id['device_id']['device_uuid']['uuid']), endpoint_id['endpoint_uuid']['uuid']) for endpoint_id in endpoint_ids] if endpoint_ids else [] json_constraints = [json_constraint_custom(constraint['custom']['constraint_type'], constraint['custom']['constraint_value']) for constraint in constraints] if constraints else [] json_config_rules = [json_config_rule(config_rule['action'], config_rule['custom']['resource_key'],config_rule['custom']['resource_value']) for config_rule in config_rules] if config_rules else [] return Service(**json_service(service_uuid, service_type, json_context, json_status, json_endpoints_ids, json_constraints, json_config_rules)) def grpc_slice_id(context_uuid, slice_uuid): return SliceId(**json_slice_id(slice_uuid, context_id=json_context_id(context_uuid))) Loading
src/context/service/database/Constraint.py +25 −14 Original line number Diff line number Diff line Loading @@ -17,12 +17,14 @@ 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 typing import Dict, List, Optional, Set from common.proto.context_pb2 import Constraint from common.tools.grpc.Tools import grpc_message_to_json_string from .models.ConstraintModel import ConstraintKindEnum, ServiceConstraintModel, SliceConstraintModel from .models.enums.ConstraintAction import ORM_ConstraintActionEnum, grpc_to_enum__constraint_action from .uuids._Builder import get_uuid_from_string from .uuids.EndPoint import endpoint_get_uuid import json LOGGER = logging.getLogger(__name__) Loading @@ -40,8 +42,8 @@ def compose_constraints_data( '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 Loading @@ -58,9 +60,9 @@ def compose_constraints_data( 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) _, _, 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, '', location_kind) 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) Loading @@ -78,6 +80,7 @@ def compose_constraints_data( dict_constraint['constraint_uuid'] = constraint_uuid dict_constraints.append(dict_constraint) return dict_constraints def upsert_constraints( Loading @@ -91,11 +94,16 @@ 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_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: position = uuids_to_upsert.get(constraint_uuid) if position is None: # if not added, add it Loading @@ -104,10 +112,13 @@ def upsert_constraints( else: # if already added, update occurrence rules_to_upsert[position] = constraint else: MSG = 'Action for ConstraintRule({:s}) is not supported (service_uuid={:s}, slice_uuid={:s})' LOGGER.warning(MSG.format(str(constraint), str(service_uuid), str(slice_uuid))) # raise Exception(MSG.format(str_constraint, str(service_uuid), str(slice_uuid))) # Delete all constraints not in uuids_to_upsert delete_affected = False if len(uuids_to_upsert) > 0: if len(uuids_to_delete) > 0: 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 ) Loading