From ad29f38cbcb164a7f328b26daf789dbff90deb98 Mon Sep 17 00:00:00 2001 From: Ankitkumar Patel Date: Wed, 28 Mar 2018 14:27:53 -0400 Subject: Update the SO sync and async responses. Updated the sync and async responses and addes testcases related to policy adaptors. Issue-ID: OPTFRA-208 Change-Id: Ia0f88df1b897b6158674f3c3a7ef239f2328dcfc Signed-off-by: Ankitkumar Patel --- config/common_config.yaml | 3 +- osdf/__init__.py | 4 ++- osdf/adapters/policy/interface.py | 7 ++-- osdf/adapters/policy/utils.py | 6 ++-- osdf/operation/responses.py | 12 ++++--- .../optimizers/placementopt/conductor/conductor.py | 4 +-- osdf/templates/plc_opt_response.jsont | 12 +++---- osdfapp.py | 6 ++-- test/config/common_config.yaml | 3 +- test/policy-local-files/QueryPolicy_vCPE_2.json | 23 ++++++++++++++ test/policy-local-files/meta-valid-policies.txt | 1 + test/test_ConductorApiBuilder.py | 1 - test/test_getPolicy.py | 37 ++++++++++++++++++++++ 13 files changed, 90 insertions(+), 29 deletions(-) create mode 100644 test/policy-local-files/QueryPolicy_vCPE_2.json create mode 100644 test/test_getPolicy.py diff --git a/config/common_config.yaml b/config/common_config.yaml index 24278d1..67fd8be 100644 --- a/config/common_config.yaml +++ b/config/common_config.yaml @@ -11,15 +11,16 @@ osdf_temp: # special configuration required for "workarounds" or testing local_policies: global_disabled: True local_placement_policies_enabled: True + placement_policy_dir_vcpe: "../test/policy-local-files/" placement_policy_files_vcpe: # workaroud for policy platform glitches (or "work-arounds" for other components) - Affinity_vCPE_1.json - Capacity_vGMuxInfra.json - Capacity_vG_1.json - Distance_vGMuxInfra_1.json - Distance_vG_1.json - - Min_Guarantee_vGMuxInfra_1.json - Placement_Optimization_1.json - QueryPolicy_vCPE.json + - QueryPolicy_vCPE_2.json - hpa_policy_vGMuxInfra_1.json - hpa_policy_vG_1.json - vnfPolicy_vG.json diff --git a/osdf/__init__.py b/osdf/__init__.py index 6529b0a..5d15a85 100755 --- a/osdf/__init__.py +++ b/osdf/__init__.py @@ -40,6 +40,8 @@ ERROR_TEMPLATE = Template(""" ACCEPTED_MESSAGE_TEMPLATE = Template(""" { "requestId": "{{ request_id }}", - "text": "{{ description }}" + "transactionId": "{{ transaction_id }}", + "requestStatus": "{{ request_status }}", + "statusMessage": "{{ status_message }}" } """) diff --git a/osdf/adapters/policy/interface.py b/osdf/adapters/policy/interface.py index a3b5881..016ac44 100644 --- a/osdf/adapters/policy/interface.py +++ b/osdf/adapters/policy/interface.py @@ -159,9 +159,7 @@ 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: - required_node = osdf_config.core['policy_info'][service_type]['policy_scope']['service_name'] - model_name = retrieve_node(req_json, required_node) - service_name = model_name # TODO: data_mapping.get_service_type(model_name) + service_name = req_json['serviceInfo']['serviceName'] # TODO: data_mapping.get_service_type(model_name) return lp.get('{}_policy_dir_{}'.format(service_type, service_name.lower())), \ lp.get('{}_policy_files_{}'.format(service_type, service_name.lower())) return None @@ -173,7 +171,6 @@ def get_policies(request_json, service_type): :param service_type: the type of service to call: "placement", "scheduling" :return: policies associated with this request and provStatus retrieved from Subscriber policy """ - prov_status = [] req_info = request_json['requestInfo'] req_id = req_info['requestId'] metrics_log.info(MH.requesting("policy", req_id)) @@ -187,4 +184,4 @@ def get_policies(request_json, service_type): else: policies = remote_api(request_json, osdf_config, service_type) - return policies, prov_status + return policies diff --git a/osdf/adapters/policy/utils.py b/osdf/adapters/policy/utils.py index 95d03af..f165079 100644 --- a/osdf/adapters/policy/utils.py +++ b/osdf/adapters/policy/utils.py @@ -103,8 +103,6 @@ def retrieve_node(req_json, reference): For placement and other requests, there are encoded JSONs inside the request or policy, so we need to expand it and then do a search over the parent plus expanded JSON. """ - req_json_copy = copy.deepcopy(req_json) # since we expand the JSON in place, we work on a copy - if 'orderInfo' in req_json_copy['placementInfo']: - req_json_copy['placementInfo']['orderInfo'] = json.loads(req_json_copy['placementInfo']['orderInfo']) + req_json_copy = copy.deepcopy(req_json) info = dot_notation(req_json_copy, reference) - return list_flatten(info) if isinstance(info, list) else info \ No newline at end of file + return list_flatten(info) if isinstance(info, list) else info diff --git a/osdf/operation/responses.py b/osdf/operation/responses.py index 22a94f7..84bb2cc 100644 --- a/osdf/operation/responses.py +++ b/osdf/operation/responses.py @@ -21,15 +21,19 @@ from flask import Response from osdf import ACCEPTED_MESSAGE_TEMPLATE -def osdf_response_for_request_accept(req_id="", text="", response_code=202, as_http=True): +def osdf_response_for_request_accept(request_id="", transaction_id="", request_status="", status_message="", + response_code=202, as_http=True): """Helper method to create a response object for request acceptance, so that the object can be sent to a client - :param req_id: request ID provided by the caller - :param text: extra text description about accepting the request (e.g. "Request accepted") + :param request_id: request ID provided by the caller + :param transaction_id: transaction ID provided by the caller + :param request_status: the status of a request + :param status_message: details on the status of a request :param response_code: the HTTP status code to send -- default is 202 (accepted) :param as_http: whether to send response as HTTP response object or as a string :return: if as_http is True, return a HTTP Response object. Otherwise, return json-encoded-message """ - response_message = ACCEPTED_MESSAGE_TEMPLATE.render(description=text, request_id=req_id) + response_message = ACCEPTED_MESSAGE_TEMPLATE.render(request_id=request_id, transaction_id=transaction_id, + request_status=request_status, status_message=status_message) if not as_http: return response_message diff --git a/osdf/optimizers/placementopt/conductor/conductor.py b/osdf/optimizers/placementopt/conductor/conductor.py index 8f286ec..41b901c 100644 --- a/osdf/optimizers/placementopt/conductor/conductor.py +++ b/osdf/optimizers/placementopt/conductor/conductor.py @@ -186,8 +186,8 @@ def conductor_no_solution_processor(conductor_response, raw_response, request_id """ status_message = conductor_response["plans"][0].get("message") templ = Template(open(template_placement_response).read()) - return json.loads(templ.render(composite_solutions=[], requestId=request_id, + return json.loads(templ.render(composite_solutions=[], requestId=request_id, license_solutions=[], transactionId=raw_response.headers.get('transaction_id', ""), - statusMessage=status_message, json=json)) + requestState="completed", statusMessage=status_message, json=json)) diff --git a/osdf/templates/plc_opt_response.jsont b/osdf/templates/plc_opt_response.jsont index aa678b5..2bd9f71 100755 --- a/osdf/templates/plc_opt_response.jsont +++ b/osdf/templates/plc_opt_response.jsont @@ -1,14 +1,10 @@ { "requestId": "{{requestId}}", "transactionId": "{{transacationId}}", - "startTime": "{{startTime}}", - "responseTime": "{{responseTime}}", - "requestType": "{{requestType}}", "requestState": "{{requestState}}", - "statusMessage": "{{statusMessage}}", - "percentProgress": "{{percentProgress}}", - "solutionInfo": { - "placement": {{ json.dumps(composite_solutions) }}, - "licenseInfo":{ "featureGroupId": "{{featureGroupId}}" } + "statusMessage": "{{statusMessage}}" + "solutions": { + "placementSolutions": {{ json.dumps(composite_solutions) }}, + "licenseSolutions":{{ json.dumps(license_solutions) }} } } diff --git a/osdfapp.py b/osdfapp.py index 047ef63..62062fc 100755 --- a/osdfapp.py +++ b/osdfapp.py @@ -116,8 +116,10 @@ def do_placement_opt(): t = Thread(target=process_placement_opt, args=(request_json, policies, osdf_config)) t.start() audit_log.info(MH.accepted_valid_request(req_id, request)) - return osdf.operation.responses.osdf_response_for_request_accept( - req_id=req_id, text="Accepted placement request. Response will be posted to callback URL") + return osdf.operation.responses.osdf_response_for_request_accept(request_id=req_id, + transaction_id=request_json['transactionId'], + request_status="accepted", + status_message="") @app.errorhandler(500) diff --git a/test/config/common_config.yaml b/test/config/common_config.yaml index 2461fd8..a3ef82e 100644 --- a/test/config/common_config.yaml +++ b/test/config/common_config.yaml @@ -11,15 +11,16 @@ osdf_temp: # special configuration required for "workarounds" or testing local_policies: global_disabled: False local_placement_policies_enabled: True + placement_policy_dir_vcpe: "../test/policy-local-files/" placement_policy_files_vcpe: # workaroud for policy platform glitches (or "work-arounds" for other components) - Affinity_vCPE_1.json - Capacity_vGMuxInfra.json - Capacity_vG_1.json - Distance_vGMuxInfra_1.json - Distance_vG_1.json - - Min_Guarantee_vGMuxInfra_1.json - Placement_Optimization_1.json - QueryPolicy_vCPE.json + - QueryPolicy_vCPE_2.json - hpa_policy_vGMuxInfra_1.json - hpa_policy_vG_1.json - vnfPolicy_vG.json diff --git a/test/policy-local-files/QueryPolicy_vCPE_2.json b/test/policy-local-files/QueryPolicy_vCPE_2.json new file mode 100644 index 0000000..7f1db83 --- /dev/null +++ b/test/policy-local-files/QueryPolicy_vCPE_2.json @@ -0,0 +1,23 @@ +{ + "service": "optimizationQueryPolicy", + "policyName": "oofBeijing.queryPolicy_vCPE", + "description": "Optimization query policy for vCPE", + "templateVersion": "0.0.1", + "version": "oofBeijing", + "priority": "5", + "riskType": "test", + "riskLevel": "2", + "guard": "False", + "content": { + "queryProperties": [ + {"attribute":"locationId", "attribute_location": "customerLocation", "value": ""}, + {"attribute":"id", "attribute_location": "vpnInfo.vpnId", "value": ""}, + {"attribute":"upstreamBW", "attribute_location": "vpnInfo.upstreamBW", "value": ""}, + {"attribute":"customerLatitude", "attribute_location": "customerLatitude", "value": 1.1}, + {"attribute":"customerLongitude", "attribute_location": "customerLongitude", "value": 2.2} + ], + "serviceName": "vCPE", + "policyScope": ["vCPE", "US", "INTERNATIONAL", "ip", "vGMuxInfra", "vG", "optimizationQueryPolicy"], + "policyType": "optimizationQueryPolicy" + } +} diff --git a/test/policy-local-files/meta-valid-policies.txt b/test/policy-local-files/meta-valid-policies.txt index 7fc72ea..772ec1a 100644 --- a/test/policy-local-files/meta-valid-policies.txt +++ b/test/policy-local-files/meta-valid-policies.txt @@ -5,6 +5,7 @@ Distance_vGMuxInfra_1.json Distance_vG_1.json Placement_Optimization_1.json QueryPolicy_vCPE.json +QueryPolicy_vCPE_2.json hpa_policy_vGMuxInfra_1.json hpa_policy_vG_1.json vnfPolicy_vG.json diff --git a/test/test_ConductorApiBuilder.py b/test/test_ConductorApiBuilder.py index d13a6a5..f8683a3 100644 --- a/test/test_ConductorApiBuilder.py +++ b/test/test_ConductorApiBuilder.py @@ -39,7 +39,6 @@ class TestConductorApiBuilder(unittest.TestCase): self.request_json = json_from_file(parameter_data_file) self.policies = [json_from_file(policy_data_path + '/' + name) for name in valid_policies_files] - def test_conductor_api_call_builder(self): main_dir = self.main_dir conductor_api_template = main_dir + "osdf/templates/conductor_interface.json" # "osdf/templates/conductor_interface.json" diff --git a/test/test_getPolicy.py b/test/test_getPolicy.py new file mode 100644 index 0000000..07ffd8a --- /dev/null +++ b/test/test_getPolicy.py @@ -0,0 +1,37 @@ +# ------------------------------------------------------------------------- +# Copyright (c) 2017-2018 AT&T Intellectual Property +# +# 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. +# +# ------------------------------------------------------------------------- +# +import json +import unittest + +from osdf.adapters.policy.interface import get_policies +from osdf.utils.interfaces import json_from_file +from mock import patch + + +class TestGetPolicy(unittest.TestCase): + + def setUp(self): + main_dir = "" + parameter_data_file = main_dir + "test/placement-tests/request.json" # "test/placement-tests/request.json" + self.request_json = json_from_file(parameter_data_file) + + def test_get_policy_function(self): + with patch('osdf.adapters.policy.interface.remote_api', return_value=[{"x: y"}]): + policy_list = get_policies(self.request_json, "placement") + policy_exist = True if len(policy_list) > 0 else False + self.assertEqual(policy_exist, True) -- cgit 1.2.3-korg