Newer
Older
# 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, json, logging
from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method
from context.client.ContextClient import ContextClient
from context.proto.context_pb2 import (
ConfigActionEnum, Empty, Service, ServiceStatusEnum, ServiceTypeEnum, Slice, SliceId, SliceStatusEnum)
from interdomain.client.InterdomainClient import InterdomainClient
from service.client.ServiceClient import ServiceClient
from slice.proto.slice_pb2_grpc import SliceServiceServicer
LOGGER = logging.getLogger(__name__)
SERVICE_NAME = 'Slice'
METHOD_NAMES = ['CreateSlice', 'UpdateSlice', 'DeleteSlice']
METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES)
class SliceServiceServicerImpl(SliceServiceServicer):
LOGGER.debug('Creating Servicer...')
LOGGER.debug('Servicer Created')
def create_update(self, request : Slice) -> SliceId:
context_client = ContextClient()
slice_id = context_client.SetSlice(request)
if len(request.slice_endpoint_ids) != 2: return slice_id
domains = set()
for slice_endpoint_id in request.slice_endpoint_ids:
device_uuid = slice_endpoint_id.device_id.device_uuid.uuid
domains.add(device_uuid.split('@')[1])
is_multi_domain = len(domains) == 2
if is_multi_domain:
interdomain_client = InterdomainClient()
slice_id = interdomain_client.RequestSlice(request)
else:
# pylint: disable=no-member
service_request = Service()
service_request.service_id.context_id.context_uuid.uuid = request.slice_id.context_id.context_uuid.uuid
service_request.service_id.service_uuid.uuid = request.slice_id.slice_uuid.uuid
service_request.service_type = ServiceTypeEnum.SERVICETYPE_L3NM
service_request.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED
service_client = ServiceClient()
service_reply = service_client.CreateService(service_request)
if service_reply != service_request.service_id: # pylint: disable=no-member
raise Exception('Service creation failed. Wrong Service Id was returned')
config_rule = service_request.service_config.config_rules.add()
config_rule.action = ConfigActionEnum.CONFIGACTION_SET
config_rule.resource_key = '/settings'
config_rule.resource_value = json.dumps(
{'mtu': 1512, 'address_families': ['IPV4'], 'bgp_as': 65000, 'bgp_route_target': '65000:333'},
sort_keys=True)
for slice_endpoint_id in request.slice_endpoint_ids:
device_uuid = slice_endpoint_id.device_id.device_uuid.uuid
endpoint_uuid = slice_endpoint_id.endpoint_uuid.uuid
endpoint_id = service_request.service_endpoint_ids.add()
endpoint_id.device_id.device_uuid.uuid = device_uuid
endpoint_id.endpoint_uuid.uuid = endpoint_uuid
config_rule = service_request.service_config.config_rules.add()
config_rule.action = ConfigActionEnum.CONFIGACTION_SET
config_rule.resource_key = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid)
config_rule.resource_value = json.dumps(
{'router_id': '0.0.0.0', 'route_distinguisher': '0:0', 'sub_interface_index': 0, 'vlan_id': 0,
'address_ip': '0.0.0.0', 'address_prefix': 0},
sort_keys=True)
service_reply = service_client.UpdateService(service_request)
if service_reply != service_request.service_id: # pylint: disable=no-member
raise Exception('Service update failed. Wrong Service Id was returned')
reply = Slice()
reply.CopyFrom(request)
slice_service_id = reply.slice_service_ids.add()
slice_service_id.CopyFrom(service_reply)
slice_id = reply.slice_id
slice_active = Slice()
slice_active.CopyFrom(slice_)
slice_active.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_ACTIVE
return slice_id
@safe_and_metered_rpc_method(METRICS, LOGGER)
def CreateSlice(self, request : Slice, context : grpc.ServicerContext) -> SliceId:
#try:
# slice_ = context_client.GetSlice(request.slice_id)
# slice_id = slice_.slice_id
#except grpc.RpcError:
#return slice_id
return self.create_update(request)
@safe_and_metered_rpc_method(METRICS, LOGGER)
def UpdateSlice(self, request : Slice, context : grpc.ServicerContext) -> SliceId:
#if len(request.slice_endpoint_ids) != 2: return slice_id
#
#domains = set()
#for slice_endpoint_id in request.slice_endpoint_ids:
# device_uuid = slice_endpoint_id.device_id.device_uuid.uuid
# domains.add(device_uuid.split('@')[0])
#
#is_multi_domain = len(domains) == 2
#if is_multi_domain:
# interdomain_client = InterdomainClient()
# return interdomain_client.LookUpSlice(request)
#else:
# raise NotImplementedError('Slice should create local services for single domain slice')
return self.create_update(request)
@safe_and_metered_rpc_method(METRICS, LOGGER)
def DeleteSlice(self, request : SliceId, context : grpc.ServicerContext) -> Empty:
return Empty()