# 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, uuid from common.proto.context_pb2 import AuthenticationResult, Slice, SliceId, TeraFlowController from common.proto.interdomain_pb2_grpc import InterdomainServiceServicer from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method from common.tools.context_queries.InterDomain import ( compute_interdomain_path, compute_traversed_domains, is_multi_domain) from common.tools.grpc.Tools import grpc_message_to_json_string from context.client.ContextClient import ContextClient from pathcomp.frontend.client.PathCompClient import PathCompClient from slice.client.SliceClient import SliceClient from .RemoteDomainClients import RemoteDomainClients from .Tools import compose_slice, compute_slice_owner LOGGER = logging.getLogger(__name__) SERVICE_NAME = 'Interdomain' METHOD_NAMES = ['RequestSlice', 'Authenticate', 'LookUpSlice', 'OrderSliceFromCatalog', 'CreateSliceAndAddToCatalog'] METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES) class InterdomainServiceServicerImpl(InterdomainServiceServicer): def __init__(self, remote_domain_clients : RemoteDomainClients): LOGGER.debug('Creating Servicer...') self.remote_domain_clients = remote_domain_clients LOGGER.debug('Servicer Created') @safe_and_metered_rpc_method(METRICS, LOGGER) def RequestSlice(self, request : Slice, context : grpc.ServicerContext) -> SliceId: context_client = ContextClient() pathcomp_client = PathCompClient() slice_client = SliceClient() if not is_multi_domain(context_client, request.slice_endpoint_ids): str_slice = grpc_message_to_json_string(request) raise Exception('InterDomain can only handle inter-domain slice requests: {:s}'.format(str_slice)) interdomain_path = compute_interdomain_path(pathcomp_client, request) traversed_domains = compute_traversed_domains(context_client, interdomain_path) slice_owner_uuid = compute_slice_owner(context_client, traversed_domains) if slice_owner_uuid is None: raise Exception('Unable to identify slice owner') reply = Slice() reply.CopyFrom(request) for domain_uuid, _, is_local_domain, endpoint_ids in traversed_domains: slice_uuid = str(uuid.uuid4()) if is_local_domain: context_uuid = request.slice_id.context_id.context_uuid.uuid sub_slice = compose_slice(context_uuid, slice_uuid, endpoint_ids) sub_slice_id = slice_client.CreateSlice(sub_slice) else: sub_slice = compose_slice(domain_uuid, slice_uuid, endpoint_ids, slice_owner_uuid) sub_slice_id = context_client.SetSlice(sub_slice) reply.slice_subslice_ids.add().CopyFrom(sub_slice_id) # pylint: disable=no-member slice_id = context_client.SetSlice(reply) return slice_id @safe_and_metered_rpc_method(METRICS, LOGGER) def Authenticate(self, request : TeraFlowController, context : grpc.ServicerContext) -> AuthenticationResult: auth_result = AuthenticationResult() auth_result.context_id.CopyFrom(request.context_id) # pylint: disable=no-member auth_result.authenticated = True return auth_result @safe_and_metered_rpc_method(METRICS, LOGGER) def LookUpSlice(self, request : Slice, context : grpc.ServicerContext) -> SliceId: try: context_client = ContextClient() slice_ = context_client.GetSlice(request.slice_id) return slice_.slice_id except grpc.RpcError: #LOGGER.exception('Unable to get slice({:s})'.format(grpc_message_to_json_string(request.slice_id))) return SliceId() @safe_and_metered_rpc_method(METRICS, LOGGER) def OrderSliceFromCatalog(self, request : Slice, context : grpc.ServicerContext) -> Slice: raise NotImplementedError('OrderSliceFromCatalog') #return Slice() @safe_and_metered_rpc_method(METRICS, LOGGER) def CreateSliceAndAddToCatalog(self, request : Slice, context : grpc.ServicerContext) -> Slice: context_client = ContextClient() slice_client = SliceClient() reply = slice_client.CreateSlice(request) if reply != request.slice_id: # pylint: disable=no-member raise Exception('Slice creation failed. Wrong Slice Id was returned') return context_client.GetSlice(request.slice_id)