Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
73
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
114
115
116
117
# 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
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(context_client, slice_group_name, DEFAULT_CONTEXT_NAME)
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(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(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