diff options
Diffstat (limited to 'osdf/adapters/policy/interface.py')
-rw-r--r-- | osdf/adapters/policy/interface.py | 124 |
1 files changed, 72 insertions, 52 deletions
diff --git a/osdf/adapters/policy/interface.py b/osdf/adapters/policy/interface.py index 7c3118c..6799c6b 100644 --- a/osdf/adapters/policy/interface.py +++ b/osdf/adapters/policy/interface.py @@ -1,4 +1,4 @@ - # ------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # Copyright (c) 2015-2017 AT&T Intellectual Property # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,21 +17,23 @@ # import base64 -import itertools import json -import yaml import os +from requests import RequestException import uuid +import yaml - -from requests import RequestException -from osdf.operation.exceptions import BusinessException from osdf.adapters.local_data.local_policies import get_local_policies -from osdf.adapters.policy.utils import policy_name_as_regex, retrieve_node -from osdf.utils.programming_utils import list_flatten, dot_notation +from osdf.adapters.policy.utils import policy_name_as_regex from osdf.config.base import osdf_config -from osdf.logging.osdf_logging import audit_log, MH, metrics_log, debug_log +from osdf.logging.osdf_logging import audit_log +from osdf.logging.osdf_logging import debug_log +from osdf.logging.osdf_logging import metrics_log +from osdf.logging.osdf_logging import MH +from osdf.operation.exceptions import BusinessException from osdf.utils.interfaces import RestClient +from osdf.utils.programming_utils import dot_notation +from osdf.utils.programming_utils import list_flatten def get_by_name(rest_client, policy_name_list, wildcards=True): @@ -49,7 +51,8 @@ def get_by_name(rest_client, policy_name_list, wildcards=True): def get_by_scope(rest_client, req, config_local, type_service): - """ Get policies by scopes as defined in the configuration file. + """Get policies by scopes as defined in the configuration file. + :param rest_client: a rest client object to make a call. :param req: an optimization request. :param config_local: application configuration file. @@ -58,28 +61,39 @@ def get_by_scope(rest_client, req, config_local, type_service): """ scope_policies = [] references = config_local.get('references', {}) - pscope = config_local.get('policy_info', {}).get(type_service, {}).get('policy_scope', {}) - service_name = dot_notation(req, references.get('service_name', {}).get('value', None)) - primary_scope = pscope['{}_scope'.format(service_name.lower() if pscope.get(service_name + "_scope", None) - else "default")] - for sec_scope in pscope.get('secondary_scopes', []): - policies, scope_fields = [], [] - for field in sec_scope: - scope_fields.extend([get_scope_fields(field, references, req, list_flatten(scope_policies)) - if 'get_param' in field else field]) - scope_fields = set(list_flatten(scope_fields)) - scope_fields = set([x.lower() for x in scope_fields]) - for scope in scope_fields: - policies.extend(policy_api_call(rest_client, primary_scope, scope)) - scope_policies.append([policy for policy in policies - if scope_fields <= set(json.loads(policy['config'])['content']['policyScope'])]) + pscope = config_local.get('policy_info', {}).get(type_service, {}).get('policy_scope', []) + scope_fields = {} + policies = {} + for scopes in pscope: + for key in scopes.keys(): + for field in scopes[key]: + scope_fields[key] = list_flatten([get_scope_fields(field, references, req, policies) + if 'get_param' in field else field]) + if scope_fields.get('resources') and len(scope_fields['resources']) > 1: + for s in scope_fields['resources']: + scope_fields['resources'] = [s] + policies.update(policy_api_call(rest_client, scope_fields).get('policies', {})) + else: + policies.update(policy_api_call(rest_client, scope_fields).get('policies', {})) + for policyName in policies.keys(): + keys = scope_fields.keys() & policies[policyName]['properties'].keys() + policy = {} + policy[policyName] = policies[policyName] + for k in keys: + if set(policies.get(policyName, {}).get('properties', {}).get(k)) >= set(scope_fields[k]) \ + and policy not in scope_policies: + scope_policies.append(policy) + return scope_policies -def get_scope_fields(field, references, req, policy_info): - """ Retrieve the values for scope fields from a request and policies as per the configuration - and references defined in a configuration file. If the value of a scope field missing in a request or +def get_scope_fields(field, references, req, policies): + """Retrieve the values for scope fields from a request and policies + + They are derived as per the configuration and references defined in a + configuration file. If the value of a scope field missing in a request or policies, throw an exception since correct policies cannot be retrieved. + :param field: details on a scope field from a configuration file. :param references: references defined in a configuration file. :param req: an optimization request. @@ -95,9 +109,9 @@ def get_scope_fields(field, references, req, policy_info): raise BusinessException("Field {} is missing a value in a request".format(ref_value.split('.')[-1])) else: scope_fields = [] - for policy in policy_info: - policy_content = json.loads(policy.get('config', "{}")) - if policy_content.get('content', {}).get('policyType', "invalid_policy") == ref_source: + for policyName in policies.keys(): + policy_content = policies.get(policyName) + if policy_content.get('type', "invalid_policy") == ref_source: scope_fields.append(dot_notation(policy_content, ref_value)) scope_values = list_flatten(scope_fields) if len(scope_values) > 0: @@ -106,31 +120,35 @@ def get_scope_fields(field, references, req, policy_info): ref_value.split('.')[-1], ref_source)) -def policy_api_call(rest_client, primary_scope, scope_field): - """ Makes a getConfig API call to the policy system to retrieve policies matching a scope. - :param rest_client: rest client object to make a call - :param primary_scope: the primary scope of policies, which is a folder in the policy system - where policies are stored. - :param scope_field: the secondary scope of policies, which is a collection of domain values. - :return: a list of policies matching both primary and secondary scopes. +def policy_api_call(rest_client, scope_fields): + """Makes the api call to policy and return the response if policies are present + + :param rest_client: rest client to make a call + :param scope_fields: a collection of scopes to be used for filtering + :return: a list of policies matching all filters """ - api_call_body = {"policyName": "{}.*".format(primary_scope), - "configAttributes": {"policyScope": "{}".format(scope_field)}} - return rest_client.request(json=api_call_body) + api_call_body = {"ONAPName": "OOF", + "ONAPComponent": "OOF_Component", + "ONAPInstance": "OOF_Component_Instance", + "action": "optimize", + "resource": scope_fields} + response = rest_client.request(json=api_call_body) + if not response.get("policies"): + raise Exception("Policies not found for the scope {}".format(scope_fields)) + return response def remote_api(req_json, osdf_config, service_type="placement"): """Make a request to policy and return response -- it accounts for multiple requests that be needed + :param req_json: policy request object (can have multiple policy names) :param osdf_config: main config that will have credential information :param service_type: the type of service to call: "placement", "scheduling" :return: all related policies and provStatus retrieved from Subscriber policy """ config = osdf_config.deployment + headers = {"Content-type": "application/json"} uid, passwd = config['policyPlatformUsername'], config['policyPlatformPassword'] - pcuid, pcpasswd = config['policyClientUsername'], config['policyClientPassword'] - headers = {"ClientAuth": base64.b64encode(bytes("{}:{}".format(pcuid, pcpasswd), "ascii"))} - headers.update({'Environment': config['policyPlatformEnv']}) url = config['policyPlatformUrl'] rc = RestClient(userid=uid, passwd=passwd, headers=headers, url=url, log_func=debug_log.debug) @@ -142,17 +160,17 @@ def remote_api(req_json, osdf_config, service_type="placement"): policies = get_by_scope(rc, req_json, osdf_config.core, service_type) formatted_policies = [] - for x in itertools.chain(*policies): - if x['config'] is None: - raise BusinessException("Config not found for policy with name %s" % x['policyName']) + for x in policies: + if x[list(x.keys())[0]].get('properties') is None: + raise BusinessException("Properties not found for policy with name %s" % x[list(x.keys()[0])]) else: - formatted_policies.append(json.loads(x['config'])) + formatted_policies.append(x) return formatted_policies def local_policies_location(req_json, osdf_config, service_type): - """ - Get folder and list of policy_files if "local policies" option is enabled + """Get folder and list of policy_files if "local policies" option is enabled + :param service_type: placement supported for now, but can be any other service :return: a tuple (folder, file_list) or None """ @@ -164,15 +182,16 @@ def local_policies_location(req_json, osdf_config, service_type): if service_type == "scheduling": return lp.get('{}_policy_dir'.format(service_type)), lp.get('{}_policy_files'.format(service_type)) else: - service_name = req_json['serviceInfo']['serviceName'] # TODO: data_mapping.get_service_type(model_name) + service_name = req_json['serviceInfo']['serviceName'] debug_log.debug('Loading local policies for service name: {}'.format(service_name)) return lp.get('{}_policy_dir_{}'.format(service_type, service_name.lower())), \ - lp.get('{}_policy_files_{}'.format(service_type, service_name.lower())) + lp.get('{}_policy_files_{}'.format(service_type, service_name.lower())) return None def get_policies(request_json, service_type): """Validate the request and get relevant policies + :param request_json: Request object :param service_type: the type of service to call: "placement", "scheduling" :return: policies associated with this request and provStatus retrieved from Subscriber policy @@ -194,6 +213,7 @@ def get_policies(request_json, service_type): return policies + def upload_policy_models(): """Upload all the policy models reside in the folder""" requestId = uuid.uuid4() |