From e01f70617a2f22b71cfce912b72a1dbb77f3f969 Mon Sep 17 00:00:00 2001 From: Moshe Date: Sun, 11 Mar 2018 16:18:20 +0200 Subject: add checkin+submit vlm steps to test case Issue-ID: VNFSDK-195 Change-Id: I92dbf0c3abfbde2d6667588289c7a4ca2ccb4726 Signed-off-by: Moshe --- dist/vnftest-0.1.dev0-py2.7.egg | Bin 189020 -> 189028 bytes etc/vnftest/vnftest.yaml | 20 +++++------ tests/onap/test_cases/onap_vnftest_tc001.yaml | 25 +++++++++++++ vnftest/common/exceptions.py | 40 ++++++--------------- vnftest/onap/contexts/base.py | 1 + vnftest/onap/core/task.py | 5 ++- vnftest/onap/runners/base.py | 6 ++-- vnftest/onap/runners/iteration.py | 38 ++++++++++++-------- vnftest/onap/steps/onap_api_call.py | 49 +++++++++++++++++--------- vnftest/onap/steps/onboard/checkin_vlm.yaml | 24 +++++++++++++ vnftest/onap/steps/onboard/submit_vlm.yaml | 24 +++++++++++++ 11 files changed, 156 insertions(+), 76 deletions(-) create mode 100644 vnftest/onap/steps/onboard/checkin_vlm.yaml create mode 100644 vnftest/onap/steps/onboard/submit_vlm.yaml diff --git a/dist/vnftest-0.1.dev0-py2.7.egg b/dist/vnftest-0.1.dev0-py2.7.egg index ab2a2dc..eaf52c6 100644 Binary files a/dist/vnftest-0.1.dev0-py2.7.egg and b/dist/vnftest-0.1.dev0-py2.7.egg differ diff --git a/etc/vnftest/vnftest.yaml b/etc/vnftest/vnftest.yaml index b7d42c9..781540b 100644 --- a/etc/vnftest/vnftest.yaml +++ b/etc/vnftest/vnftest.yaml @@ -13,23 +13,21 @@ ############################################################################## dir: - config: "/a/b" -# conf: /etc/nvftest -# repos: /home/vnftest/repos/vnftest -# log: /tmp/vnftest + conf: /etc/nvftest + repos: /home/vnftest/repos/vnftest + log: /tmp/vnftest file: - out: "a/b" -# output_file: /tmp/vnftest.out -# html_file: /tmp/vnftest.htm -# reporting_file: /tmp/report.html + output_file: /tmp/vnftest.out + html_file: /tmp/vnftest.htm + reporting_file: /tmp/report.html component: - aai_ip: 10.247.159.158 + aai_ip: 10.247.43.140 aai_port: 30202 aai_ssl_port: 30233 - mso_ip: 10.247.159.144 - sdc_ip: 10.247.159.182 + mso_ip: 10.247.43.140 + sdc_ip: 10.247.43.140 sdc_port: 30205 sdc_catalog_port: 30206 sdc_designer_user: cs0008 diff --git a/tests/onap/test_cases/onap_vnftest_tc001.yaml b/tests/onap/test_cases/onap_vnftest_tc001.yaml index c6cc411..d309826 100644 --- a/tests/onap/test_cases/onap_vnftest_tc001.yaml +++ b/tests/onap/test_cases/onap_vnftest_tc001.yaml @@ -34,6 +34,31 @@ steps: - parameter_name: "vendor_id" path: "value" + runner: + type: Iteration + run_step: "setup,run" +- + type: OnapApiCall + options: + file: "onboard/checkin_vlm.yaml" + input: + - + parameter_name: "vendor_id" + source: prev_step + runner: + type: Iteration + run_step: "setup,run" +- + type: OnapApiCall + options: + file: "onboard/submit_vlm.yaml" + input: + - + parameter_name: "vendor_id" + source: prev_step + runner: + type: Iteration + run_step: "setup,run" context: type: CSAR diff --git a/vnftest/common/exceptions.py b/vnftest/common/exceptions.py index 9dc1ead..85cb203 100644 --- a/vnftest/common/exceptions.py +++ b/vnftest/common/exceptions.py @@ -14,8 +14,6 @@ # vnftest comment: this is a modified copy of # yardstick/common/exceptions.py -from oslo_utils import excutils - class ProcessExecutionError(RuntimeError): def __init__(self, message, returncode): @@ -24,42 +22,24 @@ class ProcessExecutionError(RuntimeError): class VnftestException(Exception): - """Base Vnftest Exception. - - To correctly use this class, inherit from it and define - a 'message' property. That message will get printf'd - with the keyword arguments provided to the constructor. - - Based on NeutronException class. - """ - message = "An unknown exception occurred." + message_tmplate = "An unknown exception occurred." def __init__(self, **kwargs): - try: - super(VnftestException, self).__init__(self.message % kwargs) - self.msg = self.message % kwargs - except Exception: # pylint: disable=broad-except - with excutils.save_and_reraise_exception() as ctxt: - if not self.use_fatal_exceptions(): - ctxt.reraise = False - # at least get the core message out if something happened - super(VnftestException, self).__init__(self.message) + self.msg = self.message_tmplate.format(**kwargs) + super(VnftestException, self).__init__() def __str__(self): return self.msg - def use_fatal_exceptions(self): - """Is the instance using fatal exceptions. - - :returns: Always returns False. - """ - return False - class FunctionNotImplemented(VnftestException): - message = ('The function "%(function_name)s" is not implemented in ' - '"%(class_name)" class.') + message_tmplate = ('The function "{function_name}" is not implemented in ' + '"{class_name}" class.') class MandatoryKeyException(VnftestException): - message = 'No value found for key %(key_name)" in "%(dict_str)"' + message_tmplate = 'No value found for key "{key_name}" in "{dict_str}"' + + +class InputParameterMissing(VnftestException): + message_tmplate = 'No value found for parameter "{param_name}" in "{source}"' diff --git a/vnftest/onap/contexts/base.py b/vnftest/onap/contexts/base.py index 03c3e1f..a6ddb56 100644 --- a/vnftest/onap/contexts/base.py +++ b/vnftest/onap/contexts/base.py @@ -20,6 +20,7 @@ import vnftest.common.utils as utils class Context(object): """Class that represents a context in the logical model""" list = [] + params = {} @staticmethod def split_name(name, sep='.'): diff --git a/vnftest/onap/core/task.py b/vnftest/onap/core/task.py index 8e34665..32d61f5 100644 --- a/vnftest/onap/core/task.py +++ b/vnftest/onap/core/task.py @@ -22,6 +22,7 @@ import sys import os from collections import OrderedDict +import copy import yaml import atexit import ipaddress @@ -338,7 +339,9 @@ class Task(object): # pragma: no cover runner = base_runner.Runner.get(runner_cfg) LOG.info("Starting runner of type '%s'", runner_cfg["type"]) - runner.run(step_cfg, self.context) + # Previous steps output is the input of the next step. + input_params = copy.deepcopy(self.outputs) + runner.run(step_cfg, self.context, input_params) return runner diff --git a/vnftest/onap/runners/base.py b/vnftest/onap/runners/base.py index 5170bbe..15d8a8d 100755 --- a/vnftest/onap/runners/base.py +++ b/vnftest/onap/runners/base.py @@ -154,10 +154,10 @@ class Runner(object): log.debug("post-stop data: \n%s", data) self.result_queue.put({'post-stop-action-data': data}) - def _run_step(self, cls, method_name, step_cfg, context_cfg): + def _run_step(self, cls, method_name, step_cfg, context_cfg, input_params): raise NotImplementedError - def run(self, step_cfg, context_cfg): + def run(self, step_cfg, context_cfg, input_params): step_type = step_cfg["type"] class_name = base_step.Step.get(step_type) path_split = class_name.split(".") @@ -198,7 +198,7 @@ class Runner(object): self.result_queue)) self.periodic_action_process.start() - self._run_step(cls, "run", step_cfg, context_cfg) + self._run_step(cls, "run", step_cfg, context_cfg, input_params) def abort(self): """Abort the execution of a step""" diff --git a/vnftest/onap/runners/iteration.py b/vnftest/onap/runners/iteration.py index c0bd74f..9c9ab2c 100644 --- a/vnftest/onap/runners/iteration.py +++ b/vnftest/onap/runners/iteration.py @@ -25,6 +25,7 @@ import time import traceback import os +from vnftest.common.exceptions import VnftestException from vnftest.onap.runners import base @@ -34,8 +35,8 @@ LOG = logging.getLogger(__name__) QUEUE_PUT_TIMEOUT = 10 -def _worker_process(queue, cls, method_name, step_cfg, - context_cfg, aborted, output_queue): +def _worker_process(result_queue, cls, method_name, step_cfg, + context_cfg, input_params, aborted, output_queue): sequence = 1 @@ -50,7 +51,7 @@ def _worker_process(queue, cls, method_name, step_cfg, runner_cfg['runner_id'] = os.getpid() - step = cls(step_cfg, context_cfg) + step = cls(step_cfg, context_cfg, input_params) if "setup" in run_step: step.setup() @@ -66,15 +67,16 @@ def _worker_process(queue, cls, method_name, step_cfg, {"runner": runner_cfg["runner_id"], "sequence": sequence}) - data = {} + results = {} errors = [] + fatal_error = False try: - result = method(data) - if result: + output = method(results) + if output: # add timeout for put so we don't block test # if we do timeout we don't care about dropping individual KPIs - output_queue.put(result, True, QUEUE_PUT_TIMEOUT) + output_queue.put(output, True, QUEUE_PUT_TIMEOUT) except AssertionError as assertion: # SLA validation failed in step, determine what to do now if sla_action == "assert": @@ -92,20 +94,26 @@ def _worker_process(queue, cls, method_name, step_cfg, step_cfg['options']['rate'] -= delta sequence = 1 continue + except VnftestException: + errors.append(traceback.format_exc()) + LOG.exception("") + LOG.info("Abort the task") + fatal_error = True + except Exception: errors.append(traceback.format_exc()) LOG.exception("") time.sleep(interval) - step_output = { + step_results = { 'timestamp': time.time(), 'sequence': sequence, - 'data': data, + 'data': results, 'errors': errors } - queue.put(step_output, True, QUEUE_PUT_TIMEOUT) + result_queue.put(step_results, True, QUEUE_PUT_TIMEOUT) LOG.debug("runner=%(runner)s seq=%(sequence)s END", {"runner": runner_cfg["runner_id"], @@ -114,7 +122,7 @@ def _worker_process(queue, cls, method_name, step_cfg, sequence += 1 if (errors and sla_action is None) or \ - (sequence > iterations or aborted.is_set()): + (sequence > iterations or aborted.is_set()) or fatal_error: LOG.info("worker END") break if "teardown" in run_step: @@ -128,8 +136,10 @@ def _worker_process(queue, cls, method_name, step_cfg, LOG.exception("") raise SystemExit(1) - LOG.debug("queue.qsize() = %s", queue.qsize()) + LOG.debug("queue.qsize() = %s", result_queue.qsize()) LOG.debug("output_queue.qsize() = %s", output_queue.qsize()) + if fatal_error: + raise SystemExit(1) class IterationRunner(base.Runner): @@ -149,11 +159,11 @@ If the step ends before the time has elapsed, it will be started again. """ __execution_type__ = 'Iteration' - def _run_step(self, cls, method, step_cfg, context_cfg): + def _run_step(self, cls, method, step_cfg, context_cfg, input_params): name = "{}-{}-{}".format(self.__execution_type__, step_cfg.get("type"), os.getpid()) self.process = multiprocessing.Process( name=name, target=_worker_process, args=(self.result_queue, cls, method, step_cfg, - context_cfg, self.aborted, self.output_queue)) + context_cfg, input_params, self.aborted, self.output_queue)) self.process.start() diff --git a/vnftest/onap/steps/onap_api_call.py b/vnftest/onap/steps/onap_api_call.py index ec53455..e03e00a 100644 --- a/vnftest/onap/steps/onap_api_call.py +++ b/vnftest/onap/steps/onap_api_call.py @@ -19,10 +19,11 @@ import os import yaml import copy -from vnftest.common.exceptions import MandatoryKeyException +from vnftest.common.exceptions import MandatoryKeyException, InputParameterMissing from vnftest.onap.steps import base from vnftest.common import rest_client from vnftest.common import constants as consts +from vnftest.onap.contexts.csar import CSARContext LOG = logging.getLogger(__name__) @@ -31,11 +32,12 @@ class OnapApiCall(base.Step): __step_type__ = "OnapApiCall" - def __init__(self, step_cfg, context_cfg): + def __init__(self, step_cfg, context_cfg, input_params): self.step_cfg = step_cfg self.context_cfg = context_cfg - self.input = None - self.output = None + self.input_params = input_params + self.input_cfg = None + self.output_cfg = None self.rest_def_file = None self.setup_done = False self.curr_path = os.path.dirname(os.path.abspath(__file__)) @@ -43,22 +45,36 @@ class OnapApiCall(base.Step): def setup(self): options = self.step_cfg['options'] self.rest_def_file = options.get("file") - self.input = options.get("input") - self.output = options.get("output") + self.input_cfg = options.get("input", {}) + self.output_cfg = options.get("output", {}) self.setup_done = True + def eval_input(self, params): + for input_parameter in self.input_cfg: + param_name = input_parameter['parameter_name'] + value = None + if 'value' in input_parameter: + value = input_parameter['value'] + elif 'source' in input_parameter: + source = input_parameter['source'] + if source == 'prev_step': + if param_name in self.input_params: + value = self.input_params[param_name] + else: + raise InputParameterMissing(param_name=param_name, source='input parameters') + if value is None: + raise InputParameterMissing(param_name=param_name, source="task configuration") + params[param_name] = value + def run(self, result): if not self.setup_done: self.setup() - result['output'] = {} + output = {} params = copy.deepcopy(consts.component_constants) - for input_parameter in self.input: - param_name = input_parameter['parameter_name'] - param_value = input_parameter['value'] - params[param_name] = param_value + self.eval_input(params) execution_result = self.execute_operation(params) result_body = execution_result['body'] - for output_parameter in self.output: + for output_parameter in self.output_cfg: param_name = output_parameter['parameter_name'] param_path = output_parameter['path'] path_list = param_path.split("|") @@ -66,11 +82,10 @@ class OnapApiCall(base.Step): for path_element in path_list: param_value = param_value[path_element] if param_value is None: - raise MandatoryKeyException( - key_name='param_path', class_name=str(result_body)) - self.context_cfg[param_name] = param_value - result['output'][param_name] = param_value - result['status'] = 'PASS' + raise MandatoryKeyException(key_name='param_path', class_name=str(result_body)) + result[param_name] = param_value + output[param_name] = param_value + return output def execute_operation(self, params, attempt=0): try: diff --git a/vnftest/onap/steps/onboard/checkin_vlm.yaml b/vnftest/onap/steps/onboard/checkin_vlm.yaml new file mode 100644 index 0000000..93fdd07 --- /dev/null +++ b/vnftest/onap/steps/onboard/checkin_vlm.yaml @@ -0,0 +1,24 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## + +--- +method: "PUT" +url: "http://{sdc_ip}:{sdc_port}/onboarding-api/v1.0/vendor-license-models/{vendor_id}/versions/0.1/actions" +headers: { + "Content-Type": "application/json", + "Authorization": "Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==", + "USER_ID": "{sdc_designer_user}", + "Accept": "application/json" + } +body: {"action":"Checkin"} diff --git a/vnftest/onap/steps/onboard/submit_vlm.yaml b/vnftest/onap/steps/onboard/submit_vlm.yaml new file mode 100644 index 0000000..eb1683a --- /dev/null +++ b/vnftest/onap/steps/onboard/submit_vlm.yaml @@ -0,0 +1,24 @@ +############################################################################## +# Copyright 2018 EuropeanSoftwareMarketingLtd. +# =================================================================== +# Licensed under the ApacheLicense, Version2.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 +# +# 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 +############################################################################## + +--- +method: "PUT" +url: "http://{sdc_ip}:{sdc_port}/onboarding-api/v1.0/vendor-license-models/{vendor_id}/versions/0.1/actions" +headers: { + "Content-Type": "application/json", + "Authorization": "Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==", + "USER_ID": "{sdc_designer_user}", + "Accept": "application/json" + } +body: {"action":"Submit"} -- cgit 1.2.3-korg