Newer
Older
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# 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.
from typing import Dict, List, Optional, Set, Tuple
from common.Constants import DEFAULT_CONTEXT_NAME
from common.Settings import get_setting
from common.method_wrappers.ServiceExceptions import NotFoundException
from common.proto.context_pb2 import IsolationLevelEnum, Slice, SliceId, SliceStatusEnum
from common.tools.context_queries.Context import create_context
from common.tools.context_queries.Slice import get_slice_by_uuid
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from context.client.ContextClient import ContextClient
from slice.service.slice_grouper.MetricsExporter import MetricsExporter
SETTING_NAME_SLICE_GROUPING = 'SLICE_GROUPING'
TRUE_VALUES = {'Y', 'YES', 'TRUE', 'T', 'E', 'ENABLE', 'ENABLED'}
NO_ISOLATION = IsolationLevelEnum.NO_ISOLATION
def is_slice_grouping_enabled() -> bool:
is_enabled = get_setting(SETTING_NAME_SLICE_GROUPING, default=None)
if is_enabled is None: return False
str_is_enabled = str(is_enabled).upper()
return str_is_enabled in TRUE_VALUES
def create_slice_group(
context_uuid : str, slice_name : str, capacity_gbps : float, availability : float
) -> Slice:
slice_group_obj = Slice()
slice_group_obj.slice_id.context_id.context_uuid.uuid = context_uuid # pylint: disable=no-member
slice_group_obj.slice_id.slice_uuid.uuid = slice_name # pylint: disable=no-member
slice_group_obj.name = slice_name
slice_group_obj.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_ACTIVE # pylint: disable=no-member
#del slice_group_obj.slice_endpoint_ids[:] # no endpoints initially
#del slice_group_obj.slice_service_ids[:] # no sub-services
#del slice_group_obj.slice_subslice_ids[:] # no sub-slices
#del slice_group_obj.slice_config.config_rules[:] # no config rules
slice_group_obj.slice_owner.owner_uuid.uuid = 'TeraFlowSDN' # pylint: disable=no-member
slice_group_obj.slice_owner.owner_string = 'TeraFlowSDN' # pylint: disable=no-member
constraint_sla_capacity = slice_group_obj.slice_constraints.add() # pylint: disable=no-member
constraint_sla_capacity.sla_capacity.capacity_gbps = capacity_gbps
constraint_sla_availability = slice_group_obj.slice_constraints.add() # pylint: disable=no-member
constraint_sla_availability.sla_availability.num_disjoint_paths = 1
constraint_sla_availability.sla_availability.all_active = True
constraint_sla_availability.sla_availability.availability = availability
constraint_sla_isolation = slice_group_obj.slice_constraints.add() # pylint: disable=no-member
constraint_sla_isolation.sla_isolation.isolation_level.append(NO_ISOLATION)
return slice_group_obj
def create_slice_groups(
slice_groups : List[Tuple[str, float, float]], context_uuid : str = DEFAULT_CONTEXT_NAME
) -> Dict[str, SliceId]:
context_client = ContextClient()
create_context(context_client, context_uuid)
slice_group_ids : Dict[str, SliceId] = dict()
for slice_group in slice_groups:
slice_group_name = slice_group[0]
slice_group_obj = get_slice_by_uuid(context_client, slice_group_name, DEFAULT_CONTEXT_NAME)
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
if slice_group_obj is None:
slice_group_obj = create_slice_group(
DEFAULT_CONTEXT_NAME, slice_group_name, slice_group[2], slice_group[1])
slice_group_id = context_client.SetSlice(slice_group_obj)
slice_group_ids[slice_group_name] = slice_group_id
else:
slice_group_ids[slice_group_name] = slice_group_obj.slice_id
return slice_group_ids
def get_slice_grouping_parameters(slice_obj : Slice) -> Optional[Tuple[float, float]]:
isolation_levels : Set[int] = set()
availability : Optional[float] = None
capacity_gbps : Optional[float] = None
for constraint in slice_obj.slice_constraints:
kind = constraint.WhichOneof('constraint')
if kind == 'sla_isolation':
isolation_levels.update(constraint.sla_isolation.isolation_level)
elif kind == 'sla_capacity':
capacity_gbps = constraint.sla_capacity.capacity_gbps
elif kind == 'sla_availability':
availability = constraint.sla_availability.availability
else:
continue
no_isolation_level = len(isolation_levels) == 0
single_isolation_level = len(isolation_levels) == 1
has_no_isolation_level = NO_ISOLATION in isolation_levels
can_be_grouped = no_isolation_level or (single_isolation_level and has_no_isolation_level)
if not can_be_grouped: return None
if availability is None: return None
if capacity_gbps is None: return None
return availability, capacity_gbps
def add_slice_to_group(slice_obj : Slice, selected_group : Tuple[str, float, float]) -> bool:
group_name, availability, capacity_gbps = selected_group
slice_uuid = slice_obj.slice_id.slice_uuid.uuid
context_client = ContextClient()
slice_group_obj = get_slice_by_uuid(context_client, group_name, DEFAULT_CONTEXT_NAME, rw_copy=True)
if slice_group_obj is None:
raise NotFoundException('Slice', group_name, extra_details='while adding to group')
del slice_group_obj.slice_endpoint_ids[:]
for endpoint_id in slice_obj.slice_endpoint_ids:
slice_group_obj.slice_endpoint_ids.add().CopyFrom(endpoint_id)
del slice_group_obj.slice_constraints[:]
del slice_group_obj.slice_service_ids[:]
del slice_group_obj.slice_subslice_ids[:]
slice_group_obj.slice_subslice_ids.add().CopyFrom(slice_obj.slice_id)
del slice_group_obj.slice_config.config_rules[:]
for config_rule in slice_obj.slice_config.config_rules:
group_config_rule = slice_group_obj.slice_config.config_rules.add()
group_config_rule.CopyFrom(config_rule)
if config_rule.WhichOneof('config_rule') != 'custom': continue
TEMPLATE = '/subslice[{:s}]{:s}'
slice_resource_key = config_rule.custom.resource_key
group_resource_key = TEMPLATE.format(slice_uuid, slice_resource_key)
group_config_rule.custom.resource_key = group_resource_key
metrics_exporter = MetricsExporter()
metrics_exporter.export_point(
slice_uuid, group_name, availability, capacity_gbps, is_center=False)
return True
def remove_slice_from_group(slice_obj : Slice, selected_group : Tuple[str, float, float]) -> bool:
group_name, _, _ = selected_group
slice_uuid = slice_obj.slice_id.slice_uuid.uuid
context_client = ContextClient()
slice_group_obj = get_slice_by_uuid(context_client, group_name, DEFAULT_CONTEXT_NAME, rw_copy=True)
if slice_group_obj is None:
raise NotFoundException('Slice', group_name, extra_details='while removing from group')
if slice_obj.slice_id in slice_group_obj.slice_subslice_ids:
tmp_slice_group_obj.slice_id.CopyFrom(slice_group_obj.slice_id) # pylint: disable=no-member
tmp_slice_group_obj.slice_subslice_ids.add().CopyFrom(slice_obj.slice_id) # pylint: disable=no-member
for endpoint_id in slice_obj.slice_endpoint_ids:
tmp_slice_group_obj.slice_endpoint_ids.add().CopyFrom(endpoint_id) # pylint: disable=no-member
for config_rule in slice_obj.slice_config.config_rules:
group_config_rule = tmp_slice_group_obj.slice_config.config_rules.add() # pylint: disable=no-member
group_config_rule.CopyFrom(config_rule)
if group_config_rule.WhichOneof('config_rule') != 'custom': continue
TEMPLATE = '/subslice[{:s}]{:s}'
slice_resource_key = group_config_rule.custom.resource_key
group_resource_key = TEMPLATE.format(slice_uuid, slice_resource_key)
group_config_rule.custom.resource_key = group_resource_key
metrics_exporter = MetricsExporter()
metrics_exporter.delete_point(slice_uuid)
return True