diff options
Diffstat (limited to 'conductor/conductor/data/plugins/inventory_provider/hpa_utils.py')
-rw-r--r-- | conductor/conductor/data/plugins/inventory_provider/hpa_utils.py | 171 |
1 files changed, 149 insertions, 22 deletions
diff --git a/conductor/conductor/data/plugins/inventory_provider/hpa_utils.py b/conductor/conductor/data/plugins/inventory_provider/hpa_utils.py index bd7e44c..1d4a2d7 100644 --- a/conductor/conductor/data/plugins/inventory_provider/hpa_utils.py +++ b/conductor/conductor/data/plugins/inventory_provider/hpa_utils.py @@ -18,29 +18,30 @@ # ------------------------------------------------------------------------- # -'''Utility functions for - Hardware Platform Awareness (HPA) constraint plugin''' +"""Utility functions for + Hardware Platform Awareness (HPA) constraint plugin""" import operator +import yaml + +from oslo_log import log import conductor.common.prometheus_metrics as PC -# python imports -import yaml +from conductor.i18n import _LE from conductor.i18n import _LI -# Third-party library imports -from oslo_log import log +from conductor.i18n import _LW + LOG = log.getLogger(__name__) -def match_all_operator(big_list, small_list): - ''' - Match ALL operator for HPA - Check if smaller list is a subset of bigger list +def match_all_operator(big_list, small_list): + """Match ALL operator for HPA Check if smaller list is a subset of bigger list + :param big_list: bigger list :param small_list: smaller list :return: True or False - ''' + """ if not big_list or not small_list: return False @@ -50,6 +51,134 @@ def match_all_operator(big_list, small_list): return small_set.issubset(big_set) +def get_candidates_with_hpa(arg): + """RPC for getting candidates flavor mapping for matching hpa + + :param ctx: context + :param arg: contains input passed from client side for RPC call + :return: response candidate_list with matching label to flavor mapping + """ + candidate_list = arg["candidate_list"] + id = arg["id"] + type = arg["type"] + directives = arg["directives"] + attr = directives[0].get("attributes") + label_name = attr[0].get("attribute_name") + flavorProperties = arg["flavorProperties"] + discard_set = set() + for i in range(len(candidate_list)): + # perform this check only for cloud candidates + if candidate_list[i]["inventory_type"] != "cloud": + continue + + # Check if flavor mapping for current label_name already + # exists. This is an invalid condition. + if candidate_list[i].get("directives") and attr[0].get( + "attribute_value") != "": + LOG.error(_LE("Flavor mapping for label name {} already" + "exists").format(label_name)) + continue + + # RPC call to inventory provider for matching hpa capabilities + result = match_hpa(candidate=candidate_list[i], features=flavorProperties) + + flavor_name = None + if result: + LOG.debug("Find results {}".format(result)) + flavor_info = result.get("flavor_map") + req_directives = result.get("directives") + LOG.debug("Get directives {}".format(req_directives)) + + else: + flavor_info = None + LOG.info( + _LW("No flavor mapping returned" + " for candidate: {}").format( + candidate_list[i].get("candidate_id"))) + + # Metrics to Prometheus + m_vim_id = candidate_list[i].get("vim-id") + if not flavor_info: + discard_set.add(candidate_list[i].get("candidate_id")) + PC.HPA_CLOUD_REGION_UNSUCCESSFUL.labels('ONAP', 'N/A', + m_vim_id).inc() + else: + if not flavor_info.get("flavor-name"): + discard_set.add(candidate_list[i].get("candidate_id")) + PC.HPA_CLOUD_REGION_UNSUCCESSFUL.labels('ONAP', 'N/A', + m_vim_id).inc() + else: + if not candidate_list[i].get("flavor_map"): + candidate_list[i]["flavor_map"] = {} + # Create flavor mapping for label_name to flavor + flavor_name = flavor_info.get("flavor-name") + flavor_id = flavor_info.get("flavor-id") + candidate_list[i]["flavor_map"][label_name] = flavor_name + candidate_list[i]["flavor_map"]["flavorId"] = flavor_id + # Create directives if not exist already + if not candidate_list[i].get("all_directives"): + candidate_list[i]["all_directives"] = {} + candidate_list[i]["all_directives"]["directives"] = [] + # Create flavor mapping and merge directives + merge_directives(candidate_list, i, id, type, directives, req_directives) + if not candidate_list[i].get("hpa_score"): + candidate_list[i]["hpa_score"] = 0 + candidate_list[i]["hpa_score"] += flavor_info.get("score") + + # Metrics to Prometheus + PC.HPA_CLOUD_REGION_SUCCESSFUL.labels('ONAP', 'N/A', + m_vim_id).inc() + + # return candidates not in discard set + candidate_list[:] = [c for c in candidate_list + if c['candidate_id'] not in discard_set] + LOG.info(_LI( + "Candidates with matching hpa capabilities: {}").format(candidate_list)) + return candidate_list + + +def merge_directives(candidate_list, index, id, type, directives, feature_directives): + """Merge the flavor_directives with other diectives listed under hpa capabilities in the policy + + :param candidate_list: all candidates + :param index: index number + :param id: vfc name + :param type: vfc type + :param directives: directives for each vfc + :param feature_directives: directives for hpa-features + :return: + """ + directive = {"id": id, + "type": type, + "directives": ""} + flavor_id_attributes = {"attribute_name": "flavorId", "attribute_value": ""} + for ele in directives: + if "flavor_directives" in ele.get("type"): + flag = True + if len(ele.get("attributes")) <= 1: + ele.get("attributes").append(flavor_id_attributes) + break + else: + flag = False + if not flag: + LOG.error("No flavor directives found in {}".format(id)) + for item in feature_directives: + if item and item not in directives: + directives.append(item) + directive["directives"] = directives + candidate_list[index]["all_directives"]["directives"].append(directive) + + +def match_hpa(candidate, features): + """Match HPA features requirement with the candidate flavors """ + hpa_provider = HpaMatchProvider(candidate, features) + if hpa_provider.init_verify(): + directives = hpa_provider.match_flavor() + else: + directives = None + return directives + + class HpaMatchProvider(object): def __init__(self, candidate, req_cap_list): @@ -75,7 +204,7 @@ class HpaMatchProvider(object): for capability in CapabilityDataParser.get_item(self.req_cap_list, None): if capability.item['mandatory'].lower() == 'true': - hpa_list = {k: capability.item[k] \ + hpa_list = {k: capability.item[k] for k in hpa_keys if k in capability.item} if hpa_list not in req_filter_list: req_filter_list.append(hpa_list) @@ -90,13 +219,13 @@ class HpaMatchProvider(object): # Metrics to Prometheus m_flavor_name = flavor['flavor-name'] PC.HPA_FLAVOR_MATCH_UNSUCCESSFUL.labels('ONAP', 'N/A', 'N/A', - 'N/A', self.m_vim_id, - m_flavor_name).inc() + 'N/A', self.m_vim_id, + m_flavor_name).inc() continue for capability in CapabilityDataParser.get_item(flavor_cap_list, 'hpa-capability'): - hpa_list = {k: capability.item[k] \ - for k in hpa_keys if k in capability.item} + hpa_list = {k: capability.item[k] + for k in hpa_keys if k in capability.item} flavor_filter_list.append(hpa_list) # if flavor has the matching capability compare attributes if self._is_cap_supported(flavor_filter_list, req_filter_list): @@ -132,7 +261,6 @@ class HpaMatchProvider(object): m_flavor_name).inc() return directives - def _is_cap_supported(self, flavor, cap): try: for elem in cap: @@ -174,7 +302,7 @@ class HpaMatchProvider(object): def _get_flavor_attribute(self, flavor_attr): try: attrib_value = yaml.load(flavor_attr['hpa-attribute-value']) - except: + except Exception: return None f_unit = None @@ -210,7 +338,6 @@ class HpaMatchProvider(object): return op - def _compare_attribute(self, flavor_attr, req_attr): req_value, req_op = self._get_req_attribute(req_attr) @@ -240,7 +367,7 @@ class HpaMatchProvider(object): # Only integers left to compare if req_op in ['<', '>', '<=', '>=', '=']: - return op(int(flavor_value), int(req_value)) + return op(int(flavor_value), int(req_value)) return False @@ -279,11 +406,11 @@ class HpaMatchProvider(object): # filter to get the attribute being compared flavor_feature_attr = \ filter(lambda ele: ele['hpa-attribute-key'] == - req_attr_key, flavor_cfa) + req_attr_key, flavor_cfa) if not flavor_feature_attr: flavor_flag = False elif not self._compare_attribute(list(flavor_feature_attr)[0], - req_feature_attr): + req_feature_attr): flavor_flag = False if not flavor_flag: continue |