2 # -------------------------------------------------------------------------
3 # Copyright (C) 2020 Wipro Limited.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # -------------------------------------------------------------------------
21 from operator import eq
22 from operator import ge
23 from operator import le
26 from oslo_log import log
28 from conductor.data.plugins.inventory_provider import base
29 from conductor.data.plugins.inventory_provider.candidates.candidate import Candidate
30 from conductor.data.plugins.inventory_provider.candidates.slice_profiles_candidate import get_slice_requirements
31 from conductor.data.plugins.inventory_provider.candidates.slice_profiles_candidate import SliceProfilesCandidate
32 from conductor.data.plugins.inventory_provider.cps import CPS
34 LOG = log.getLogger(__name__)
37 OPERATORS = {'gte': ge,
42 class Generator(base.InventoryProviderBase):
45 """Initialize variables"""
52 """Return human-readable name."""
55 def resolve_demands(self, demands, plan_info, triage_translator_data):
56 """Resolve demands into candidate list"""
58 for name, requirements in demands.items():
59 resolved_demands[name] = []
60 for requirement in requirements:
61 inventory_type = requirement.get('inventory_type').lower()
62 candidate_uniqueness = requirement.get('unique', 'true')
63 filtering_attributes = requirement.get('filtering_attributes')
64 default_fields = requirement.get('default_attributes')
65 resolved_demands[name].extend(self.generate_candidates(inventory_type,
70 return resolved_demands
72 def generate_candidates(self, inventory_type, filtering_attributes, candidate_uniqueness, default_fields):
74 if inventory_type == "slice_profiles":
75 return self.generate_slice_profile_candidates(filtering_attributes, inventory_type,
76 candidate_uniqueness, default_fields)
78 LOG.debug("No functionality implemented for \
79 generating candidates for inventory_type {}".format(inventory_type))
82 def generate_slice_profile_candidates(self, filtering_attributes, inventory_type,
83 candidate_uniqueness, default_fields):
84 """Generates a list of slice profile candidate based on the filtering attributes,
86 A sample filtering attribute is given below
87 filtering_attributes = {'core': {'latency': {'min': 15, 'max': 20, 'steps': 1},
88 'reliability': {'values': [99.999]}},
89 'ran': {'latency': {'min': 10, 'max': 20, 'steps': 1},
90 'reliability': {'values': [99.99]},
91 'coverage_area_ta_list': {"derive_from":{"method":"get_tracking_area",
93 "coverage_area": {"get_param": "coverageArea"}
96 It will generate slice profile combination from the attributes for each subnet and
97 generates combination of slice profile tuples from the each subnet.
99 subnet_combinations = {}
100 for subnet, attributes in filtering_attributes['subnets'].items():
101 attribute_names, attribute_combinations = generate_combinations(attributes)
102 subnet_combinations[subnet] = organize_combinations(attribute_names, attribute_combinations)
104 subnet_names, slice_profile_combinations = get_combinations_from_dict(subnet_combinations)
105 organized_combinations = organize_combinations(subnet_names, slice_profile_combinations)
107 for combination in organized_combinations:
108 if is_valid(get_slice_requirements(combination), filtering_attributes['service_profile']):
109 info = Candidate.build_candidate_info(self.name(), inventory_type, 1.0, candidate_uniqueness,
111 coverage_area = filtering_attributes['service_profile'].get("coverage_area").get("value")
112 candidate = SliceProfilesCandidate(info=info, subnet_requirements=combination,
113 default_fields=default_fields, coverage_area=coverage_area)
114 converted_candidate = candidate.convert_nested_dict_to_dict()
115 candidates.append(converted_candidate)
120 def is_valid(converted_candidate, service_profile):
121 for attr, attr_value in service_profile.items():
122 if attr == "coverage_area":
125 if not OPERATORS[attr_value['operator']](converted_candidate[attr], attr_value['value']):
130 def get_tracking_area(args):
132 coverage_area_zones_list = args.split("-")
133 zone_id_list = coverage_area_zones_list[1].split(",")
134 for zone_id in zone_id_list:
135 values = CPS().get_coveragearea_ta(zone_id)
137 if not x.get("nRTAC") in coverage_list:
138 coverage_list.append(x.get("nRTAC"))
142 def generate_combinations(attributes):
143 """Generates all combination of the given attribute values.
145 The params can have a values list or range(min, max)
146 from which the combinations are generated.
151 for attribute, attr_params in attributes.items():
152 if attr_params.get('values'):
153 values = attr_params.get('values')
154 elif attr_params.get('derive_from'):
155 derive_from = attr_params.get("derive_from")
156 method_name = derive_from.get("method")
157 args = derive_from.get("args").get("coverage_area")
158 ta_list = (eval(method_name)(args))
161 values = range(attr_params.get('min', 1), attr_params.get('max'),
162 attr_params.get('steps', 1))
163 attr[attribute] = values
164 return get_combinations_from_dict(attr)
167 def get_combinations_from_dict(attr):
168 """Generates combinations from a dictionary containing lists
171 attr = {"latency": [1,2,3],
172 "reliability": [99.99, 99.9]
175 attribute_name: ["latency", "reliability"]
176 attribute_combinations: [[1,99.99], [2,99.99], [3,99.99], [1,99.9], [2,99.9], [3,99.9]]
178 attribute_names = list(attr.keys())
179 attribute_combinations = list(itertools.product(*attr.values()))
180 return attribute_names, attribute_combinations
183 def organize_combinations(attribute_names, attribute_combinations):
184 """Organise the generated combinations into list of dicts.
187 attribute_name: ["latency", "reliability"]
188 attribute_combinations: [[1,99.99], [2,99.99], [3,99.99], [1,99.9], [2,99.9], [3,99.9]]
190 combinations = [{'latency': 1, 'reliability': 99.99},
191 {'latency': 2, 'reliability': 99.99},
192 {'latency': 3, 'reliability': 99.99},
193 {'latency': 1, 'reliability': 99.9},
194 {'latency': 2, 'reliability': 99.9},
195 {'latency': 3, 'reliability': 99.9}
199 for combination in attribute_combinations:
201 for (name, value) in zip(attribute_names, combination):
203 combinations.append(comb)