diff options
20 files changed, 609 insertions, 90 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/workflow_runner.py b/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/workflow_runner.py index 0c52e32..eb4efeb 100644 --- a/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/workflow_runner.py +++ b/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/workflow_runner.py @@ -30,6 +30,7 @@ from ..modeling import models from ..modeling import utils as modeling_utils from ..utils.imports import import_fullname + DEFAULT_TASK_MAX_ATTEMPTS = 30 DEFAULT_TASK_RETRY_INTERVAL = 30 @@ -68,30 +69,24 @@ class WorkflowRunner(object): self._resource_storage = resource_storage # the IDs are stored rather than the models themselves, so this module could be used - # by several threads without raising errors on model objects shared between threadsF + # by several threads without raising errors on model objects shared between threads if self._is_resume: - self._service_id = service_id - # self._service_id = self.execution.service.id - # self._workflow_name = model_storage.execution.get(self._execution_id).workflow_name - self._workflow_name = workflow_name - self._validate_workflow_exists_for_service() self._execution_id = execution_id - + self._service_id = self.execution.service.id + self._workflow_name = model_storage.execution.get(self._execution_id).workflow_name else: self._service_id = service_id self._workflow_name = workflow_name self._validate_workflow_exists_for_service() self._execution_id = self._create_execution_model(inputs).id - self._create_execution_model(inputs, execution_id) - self._workflow_context = WorkflowContext( name=self.__class__.__name__, model_storage=self._model_storage, resource_storage=resource_storage, service_id=service_id, - execution_id=execution_id, + execution_id=self._execution_id, workflow_name=self._workflow_name, task_max_attempts=task_max_attempts, task_retry_interval=task_retry_interval) @@ -100,13 +95,13 @@ class WorkflowRunner(object): executor = executor or ProcessExecutor(plugin_manager=plugin_manager) # transforming the execution inputs to dict, to pass them to the workflow function - # execution_inputs_dict = dict(inp.unwrapped for inp in self.execution.inputs.itervalues()) + execution_inputs_dict = dict(inp.unwrapped for inp in self.execution.inputs.itervalues()) - # if not self._is_resume: - # workflow_fn = self._get_workflow_fn() - # self._tasks_graph = workflow_fn(ctx=self._workflow_context, **execution_inputs_dict) - # compiler = graph_compiler.GraphCompiler(self._workflow_context, executor.__class__) - # compiler.compile(self._tasks_graph) + if not self._is_resume: + workflow_fn = self._get_workflow_fn() + self._tasks_graph = workflow_fn(ctx=self._workflow_context, **execution_inputs_dict) + compiler = graph_compiler.GraphCompiler(self._workflow_context, executor.__class__) + compiler.compile(self._tasks_graph) self._engine = engine.Engine(executors={executor.__class__: executor}) @@ -116,7 +111,7 @@ class WorkflowRunner(object): @property def execution(self): - return self._model_storage.execution.get(self._execution_id) + return self._model_storage.execution.get(self.execution_id) @property def service(self): @@ -130,7 +125,7 @@ class WorkflowRunner(object): def cancel(self): self._engine.cancel_execution(ctx=self._workflow_context) - def _create_execution_model(self, inputs, execution_id): + def _create_execution_model(self, inputs): execution = models.Execution( created_at=datetime.utcnow(), service=self.service, @@ -148,7 +143,6 @@ class WorkflowRunner(object): supplied_inputs=inputs or {}) execution.inputs = modeling_utils.merge_parameter_values( inputs, workflow_inputs, model_cls=models.Input) - execution.id = execution_id # TODO: these two following calls should execute atomically self._validate_no_active_executions(execution) self._model_storage.execution.put(execution) @@ -156,17 +150,17 @@ class WorkflowRunner(object): def _validate_workflow_exists_for_service(self): if self._workflow_name not in self.service.workflows and \ - self._workflow_name not in builtin.BUILTIN_WORKFLOWS: + self._workflow_name not in builtin.BUILTIN_WORKFLOWS: raise exceptions.UndeclaredWorkflowError( 'No workflow policy {0} declared in service {1}' - .format(self._workflow_name, self.service.name)) + .format(self._workflow_name, self.service.name)) def _validate_no_active_executions(self, execution): active_executions = [e for e in self.service.executions if e.is_active()] if active_executions: raise exceptions.ActiveExecutionsError( "Can't start execution; Service {0} has an active execution with ID {1}" - .format(self.service.name, active_executions[0].id)) + .format(self.service.name, active_executions[0].id)) def _get_workflow_fn(self): if self._workflow_name in builtin.BUILTIN_WORKFLOWS: diff --git a/azure/aria/aria-rest-server/VERSION b/azure/aria/aria-rest-server/VERSION new file mode 100644 index 0000000..f755149 --- /dev/null +++ b/azure/aria/aria-rest-server/VERSION @@ -0,0 +1 @@ +1.0.0-SNAPSHOT diff --git a/azure/aria/aria-rest-server/build.py b/azure/aria/aria-rest-server/build.py new file mode 100644 index 0000000..cd2bcbf --- /dev/null +++ b/azure/aria/aria-rest-server/build.py @@ -0,0 +1,95 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + +import subprocess +import os +import sys +import glob +import xml.etree.ElementTree as etree + +# create and enter venv +def create_venv( name): + if subprocess.call("virtualenv {}".format(name), shell = True): + raise Exception("virtualenv create failed") + ret = subprocess.call(". {}/bin/activate && python {} run". \ + format(name,__file__), shell = True) + sys.exit(ret) + +def init_venv(): + subprocess.call("pip install -U pip", shell = True) + subprocess.call("pip install -U setuptools", shell = True) + subprocess.call("pip install wheel", shell = True) + subprocess.call("pip install twine", shell = True) + + +if len(sys.argv) == 1: + create_venv ("mavenvenv") +else: + init_venv() + + if os.environ['MVN_PHASE'] == 'package': + wheelname = os.environ['WHEEL_NAME'] + inputdir = os.environ['INPUT_DIR'] + outputdir = os.environ['OUTPUT_DIR'] + savedir = os.getcwd() + os.chdir(inputdir) + + if subprocess.call( [ "python", + "setup.py", + "bdist_wheel", + "-d", + outputdir + ]): + sys.stderr("wheel create failed") + sys.exit(1) + f = glob.glob(outputdir+"/*.whl")[0] + os.rename(f , outputdir+"/"+ wheelname) + + elif os.environ['MVN_PHASE'] == 'deploy': + + it = etree.iterparse(os.environ['SETTINGS_FILE']) + for _, el in it: + el.tag = el.tag.split('}', 1)[1] # strip namespace + settings = it.root + + username = settings.find('.//server[id="{}"]/username'.format( + os.environ['PYPI_SERVERID'])).text + password = settings.find('.//server[id="{}"]/password'.format( + os.environ['PYPI_SERVERID'])).text + + try: + if subprocess.call( [ "twine", + "upload", + "--username", + username, + "--password", + password, + "--repository-url", + os.environ["PYPI_SERVER_BASEURL"], + os.environ["WHEEL_PATH"] + ] ): + sys.stderr.write("pypi upload failed") + sys.exit(1) + finally: + subprocess.call("rm -rf mavenvenv", shell = True) + + sys.exit(0) + else: + sys.stderr.write("Unrecognized phase '{}'\n".format( + os.environ('MVN_PHASE'))) + sys.exit(1) diff --git a/azure/aria/aria-rest-server/pom.xml b/azure/aria/aria-rest-server/pom.xml new file mode 100644 index 0000000..6bfa5c2 --- /dev/null +++ b/azure/aria/aria-rest-server/pom.xml @@ -0,0 +1,114 @@ +<?xml version="1.0"?> +<!-- + /* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs. All rights reserved. + * =================================================================== + * 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. + * ============LICENSE_END==================================================== + */ + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.onap.multicloud.aria</groupId> + <artifactId>ariarest</artifactId> + <name>ariarest</name> + <version>0.1.0-SNAPSHOT</version> + <description>ARIA REST API wheel build</description> + <parent> + <groupId>org.onap.multicloud.azure</groupId> + <artifactId>multicloud-azure</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <properties> + <python_version>2</python_version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <wheel.name>${project.artifactId}-${project.version}-py${python_version}-none-any.whl</wheel.name> + <python.sourceDirectory>${project.basedir}/src/main/python/aria-rest</python.sourceDirectory> + <onap.nexus.pypiserver.baseurl>http://192.168.33.1:8081/repository/pypi-internal/</onap.nexus.pypiserver.baseurl> + <onap.nexus.pypiserver.serverid>ecomp-snapshots</onap.nexus.pypiserver.serverid> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.0.0</version> + <executions> + <execution> + <id>write-python-version</id> + <goals> + <goal>regex-property</goal> + </goals> + <phase>initialize</phase> + <configuration> + <name>python_version</name> + <regex>-SNAPSHOT</regex> + <value>${project.version}</value> + <replacement>\.dev0</replacement> + <failIfNoMatch>false</failIfNoMatch> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.6.0</version> + <executions> + <execution> + <id>package</id> + <phase>package</phase> + <goals><goal>exec</goal></goals> + <configuration> + <executable>python</executable> + <arguments> + <argument>${project.basedir}/build.py</argument> + </arguments> + <environmentVariables> + <MVN_PHASE>package</MVN_PHASE> + <WHEEL_NAME>${wheel.name}</WHEEL_NAME> + <INPUT_DIR>${project.basedir}/src/main/python/aria-rest</INPUT_DIR> + <OUTPUT_DIR>${project.build.directory}</OUTPUT_DIR> + </environmentVariables> + </configuration> + </execution> + <execution> + <id>deploy</id> + <phase>deploy</phase> + <goals><goal>exec</goal></goals> + <configuration> + <executable>python</executable> + <arguments> + <argument>${project.basedir}/build.py</argument> + </arguments> + <environmentVariables> + <MVN_PHASE>deploy</MVN_PHASE> + <PROJECT_VERSION>${project.version}</PROJECT_VERSION> + <DOCKERREGISTRY_SNAPSHOT>${onap.nexus.dockerregistry.snapshot}</DOCKERREGISTRY_SNAPSHOT> + <DOCKERREGISTRY_RELEASE>${onap.nexus.dockerregistry.release}</DOCKERREGISTRY_RELEASE> + <PYPI_SERVER_BASEURL>${onap.nexus.pypiserver.baseurl}</PYPI_SERVER_BASEURL> + <PYPI_SERVERID>${onap.nexus.pypiserver.serverid}</PYPI_SERVERID> + <WHEEL_PATH>${project.build.directory}/${wheel.name}</WHEEL_PATH> + </environmentVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> + diff --git a/azure/aria/aria-rest-server/setup.py b/azure/aria/aria-rest-server/setup.py new file mode 100644 index 0000000..1f68901 --- /dev/null +++ b/azure/aria/aria-rest-server/setup.py @@ -0,0 +1,41 @@ +# org.onap.dcae +# ============LICENSE_START==================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# ============================================================================= +# 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. +# ============LICENSE_END====================================================== +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. + +from setuptools import setup, find_packages + +try: + with open('VERSION') as v_file: + version = v_file.read().strip() +except IOError: + print "There was a problem parsing the VERSION file." + +setup( + name='aria-rest-server', + version=version, + packages=find_packages(), + author = '', + author_email = '', + description = ('Library for ...'), + license = 'Apache 2.0', + keywords = '', + url = '', + zip_safe = True, + install_requires=[], + entry_points = {} +) diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/LICENSE b/azure/aria/aria-rest-server/src/main/python/aria-rest/LICENSE new file mode 100644 index 0000000..48bef24 --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/LICENSE @@ -0,0 +1,18 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/__init__.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/__init__.py new file mode 100644 index 0000000..adb446c --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/__init__.py @@ -0,0 +1,19 @@ + +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/__init__.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/__init__.py new file mode 100644 index 0000000..adb446c --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/__init__.py @@ -0,0 +1,19 @@ + +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/rest.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/rest.py new file mode 100644 index 0000000..ecddff6 --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/rest.py @@ -0,0 +1,90 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + +from flask import Flask, request, jsonify +from flask_autodoc.autodoc import Autodoc +from aria import install_aria_extensions +from aria.cli.core import aria +from aria.utils import threading +from aria.orchestrator.workflow_runner import WorkflowRunner +from aria.orchestrator.workflows.executor.dry import DryExecutor +import util + +version_id = "v0" +route_base = "/api/multicloud-azure/" + version_id + "/" +app = Flask("onap-aria-rest") +auto = Autodoc(app) + +execution_state = util.SafeDict() + + +def main(): + install_aria_extensions() + app.run(host='0.0.0.0', port=5000, threaded=True) + + +# start execution +@app.route( + route_base + + "services/<service_id>/executions/<workflow_name>", + methods=['POST']) +@auto.doc() +@aria.pass_model_storage +@aria.pass_resource_storage +@aria.pass_plugin_manager +@aria.pass_logger +def start_execution( + service_id, + workflow_name, + model_storage, + resource_storage, + plugin_manager, + logger): + """ + Start an execution for the specified service + """ + body = request.json or {} + executor = DryExecutor( + ) if 'executor' in body and body['executor'] == 'dry' else None + + inputs = body['inputs'] if 'inputs' in body else None + task_max_attempts = (body['task_max_attempts'] + if 'task_max_attempts' in body else 30) + task_retry_interval = (body['task_retry_interval'] + if 'task_retry_interval' in body else 30) + + runner = WorkflowRunner(model_storage, resource_storage, plugin_manager, + service_id=service_id, + workflow_name=workflow_name, + inputs=inputs, + executor=executor, + task_max_attempts=task_max_attempts, + task_retry_interval=task_retry_interval) + + service = model_storage.service.get(service_id) + tname = '{}_{}_{}'.format(service.name, workflow_name, runner.execution_id) + thread = threading.ExceptionThread(target=runner.execute, + name=tname) + thread.start() + execution_state[str(runner.execution_id)] = [runner, thread] + logger.info("execution {} started".format(runner.execution_id)) + return jsonify({"id": runner.execution_id}), 202 + + +if __name__ == "__main__": + app.run(host='0.0.0.0', port=5000, threaded=True) diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/templates/index.html b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/templates/index.html new file mode 100644 index 0000000..932a6b1 --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/templates/index.html @@ -0,0 +1,23 @@ +<!-- +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# +--> + +<body> +<h1>Not Implemented</h1> +</body> diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/util.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/util.py new file mode 100644 index 0000000..ecd46b1 --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/aria_rest/util.py @@ -0,0 +1,48 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + + +import threading + + +def make_template_name(user, template_name): + return "{}.{}".format(user, template_name) + + +class SafeDict(dict): + def __init__(self, *args): + self._lockobj = threading.Lock() + dict.__init__(self, args) + + def __getitem__(self, key): + try: + self._lockobj.acquire() + val = dict.__getitem__(self, key) + except: + raise + finally: + self._lockobj.release() + + def __setitem__(self, key, value): + try: + self._lockobj.acquire() + dict.__setitem__(self, key, value) + except: + raise + finally: + self._lockobj.release() diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/rest.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/rest.py new file mode 100644 index 0000000..c0858bf --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/rest.py @@ -0,0 +1,57 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + +from flask import Flask, render_template +from aria.exceptions import AriaException + +version_id = "0.1" +route_base = "/api/" + version_id + "/" +app = Flask("onap-aria-rest") + +@app.route("/") +def index(): + return render_template('index.html') + + +@app.route(route_base + "templates/", methods = ['GET']) +def list_templates(): + +@app.route(route_base + "templates/<template_id>", methods = ['POST']) +def install_template( template_id ): + + # GET CSAR FROM SDC + + # DEPLOY CSAR + + # UPDATE A&AI? + + return "template {} instantiated" + +@app.route(route_base + "templates/<template_id>", methods = ['DELETE']) +def delete_template( template_id ): + + # RUN UNINSTALL + + # DELETE TEMPLATE + + # UPDATE A&AI? + + return "template {} deleted" + +if __name__ == "__main__": + app.run() diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/setup.py b/azure/aria/aria-rest-server/src/main/python/aria-rest/setup.py new file mode 100644 index 0000000..86fd5a0 --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/setup.py @@ -0,0 +1,42 @@ +# +# ============LICENSE_START=================================================== +# Copyright (c) 2018 Amdocs. All rights reserved. +# =================================================================== +# 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. +# ============LICENSE_END==================================================== +# + + +from setuptools import setup + +setup( + zip_safe=True, + name='aria-rest', + version='0.1', + author='dewayne', + author_email='dewayne@cloudify.co', + packages=[ + 'aria_rest' + ], + entry_points = { + 'console_scripts' : ['aria-rest=aria_rest.rest:main'] + }, + license='LICENSE', + description='Aria REST API for ONAP', + install_requires=[ + 'distribute', + 'Flask==0.12.2', + 'flask-autodoc==0.1.2', + 'apache-ariatosca==0.2.0' + ] +) diff --git a/azure/aria/aria-rest-server/src/main/python/aria-rest/templates/index.html b/azure/aria/aria-rest-server/src/main/python/aria-rest/templates/index.html new file mode 100644 index 0000000..6d74cfc --- /dev/null +++ b/azure/aria/aria-rest-server/src/main/python/aria-rest/templates/index.html @@ -0,0 +1,3 @@ +<body> +<h1>Not Implemented</h1> +</body> diff --git a/azure/docker/Dockerfile b/azure/docker/Dockerfile index 70924e3..e7bb479 100644 --- a/azure/docker/Dockerfile +++ b/azure/docker/Dockerfile @@ -10,7 +10,7 @@ ENV AAI_PASSWORD "AAI" ENV MR_ADDR "127.0.0.1" ENV MR_PORT "3904" -EXPOSE 9004 +EXPOSE 9008 RUN apt-get update && \ apt-get install -y unzip && \ @@ -27,6 +27,9 @@ RUN pip install . WORKDIR /tmp/aria-extension-cloudify RUN pip install . +WORKDIR /tmp/aria-rest-server/src/main/python/aria-rest +RUN pip install . + RUN pip install --force-reinstall pip==9.0.1 WORKDIR /tmp ADD docker/cloudify_azure_plugin-1.4.2-py27-none-linux_x86_64.wgn /tmp/ @@ -40,7 +43,6 @@ RUN cd /opt/ && \ rm -rf multicloud-azure.zip && \ pip install -r multicloud_azure/requirements.txt - WORKDIR /opt RUN chmod +x multicloud_azure/docker/*.sh && chmod +x multicloud_azure/*.sh ENTRYPOINT multicloud_azure/docker/docker-entrypoint.sh diff --git a/azure/multicloud_azure/pub/aria/service.py b/azure/multicloud_azure/pub/aria/service.py index 637858a..2c99611 100644 --- a/azure/multicloud_azure/pub/aria/service.py +++ b/azure/multicloud_azure/pub/aria/service.py @@ -17,13 +17,12 @@ import time import os from multicloud_azure.pub.aria import util +from multicloud_azure.pub.utils.restcall import call_aria_rest from aria.cli.core import aria from aria.cli import utils from aria.core import Core from aria.cli import service_template_utils from aria.storage import exceptions as storage_exceptions -from aria.utils import threading -from aria.orchestrator.workflow_runner import WorkflowRunner as Runner LOG = logging.getLogger(__name__) @@ -48,12 +47,10 @@ class AriaServiceImpl(object): status, template_name + time.strftime('%Y%m%d%H%M%S'), inputs) if (status[1] != 200): return status[0], status[1] - execution_id = time.strftime('%Y%m%d%H%M%S') - thread = threading.ExceptionThread(target=self.start_execution, - args=(status[2].id, execution_id, - inputs, 'install')) - thread.start() - return execution_id, 200 + status = call_aria_rest(status[2].id, 'install') + if (status[2] != "202"): + return status[1], status[2] + return json.loads(status[1])['id'], 200 @aria.pass_model_storage @aria.pass_resource_storage @@ -112,35 +109,6 @@ class AriaServiceImpl(object): return "service {} created".format(service.name), 200, service @aria.pass_model_storage - @aria.pass_resource_storage - @aria.pass_plugin_manager - @aria.pass_logger - def start_execution(self, service_id, execution_id, input, workflow_name, - model_storage, - resource_storage, - plugin_manager, - logger): - """ - Start an execution for the specified service - """ - input = input['sdnc_directives'] if'sdnc_directives'in input else None - runner = Runner(model_storage, resource_storage, plugin_manager, - execution_id=execution_id, - service_id=service_id, - workflow_name=workflow_name, - inputs=input) - - service = model_storage.service.get(service_id) - tname = '{}_{}_{}'.format(service.name, workflow_name, - runner.execution_id) - thread = threading.ExceptionThread(target=runner.execute, - name=tname) - thread.start() - execution_state[str(runner.execution_id)] = [runner, thread] - logger.info("execution {} started".format(runner.execution_id)) - return json.dumps({"id": runner.execution_id}), 202 - - @aria.pass_model_storage @aria.pass_logger def show_execution(self, execution_id, model_storage, logger): """ diff --git a/azure/multicloud_azure/pub/config/config.py b/azure/multicloud_azure/pub/config/config.py index db09fd6..511f0ca 100644 --- a/azure/multicloud_azure/pub/config/config.py +++ b/azure/multicloud_azure/pub/config/config.py @@ -39,3 +39,6 @@ FORWARDED_FOR_FIELDS = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST", # [Local Config] API_SERVER_PORT = 9004 + +# [ARIA] +ARIA_SERVER_URL = 'http://127.0.0.1:5000/api/multicloud-azure/v0' diff --git a/azure/multicloud_azure/pub/utils/restcall.py b/azure/multicloud_azure/pub/utils/restcall.py index ff5ca6a..0b0ef33 100644 --- a/azure/multicloud_azure/pub/utils/restcall.py +++ b/azure/multicloud_azure/pub/utils/restcall.py @@ -23,6 +23,7 @@ from multicloud_azure.pub.config.config import AAI_SERVICE_URL from multicloud_azure.pub.config.config import AAI_USERNAME from multicloud_azure.pub.config.config import AAI_PASSWORD from multicloud_azure.pub.config.config import MSB_SERVICE_IP, MSB_SERVICE_PORT +from multicloud_azure.pub.config.config import ARIA_SERVER_URL from multicloud_azure.pub.exceptions import VimDriverAzureException @@ -341,3 +342,12 @@ class AAIClient(object): {'value': cloud_dpdk_info.get("libversion")}) }) return ovsdpdk_capability + + +def call_aria_rest(service_id, workflow_name): + base_url = "%s" % (ARIA_SERVER_URL) + resource = ("/services/%s/executions/%s" % (service_id, workflow_name)) + headers = {} + headers['content-type'] = 'text/plain' + return call_req(base_url, "", "", rest_no_auth, resource, "POST", + headers=headers) diff --git a/azure/multicloud_azure/tests/test_aria_view.py b/azure/multicloud_azure/tests/test_aria_view.py index 69c18e7..3bbd105 100644 --- a/azure/multicloud_azure/tests/test_aria_view.py +++ b/azure/multicloud_azure/tests/test_aria_view.py @@ -136,35 +136,6 @@ class WorkoadViewTest(unittest.TestCase): plugin_manager, logger)) - @mock.patch.object(AriaServiceImpl, 'start_execution') - @aria.pass_model_storage - @aria.pass_resource_storage - @aria.pass_plugin_manager - @aria.pass_logger - def test_start_execution(self, mock_template_info, model_storage, - resource_storage, plugin_manager, logger): - class Workload: - def __init__(self, status_id, execution_id, name, input): - self.status_id = status_id - self.execution_id = execution_id - self.input = input - self.name = name - - service = Workload(1, 2, "a", "w") - mock_template_info.return_value = service - - class Request: - def __init__(self, query_params): - self.query_params = query_params - - req = Request({'k': 'v'}) - self.assertNotEqual(200, - self.fsv.start_execution(req, 123, 456, "a1", "b1", - model_storage, - resource_storage, - plugin_manager, - logger)) - def test_show_execution(self): service_op = AriaServiceImpl() self.assertNotEqual(200, diff --git a/azure/run.sh b/azure/run.sh index babf0c9..e781063 100644 --- a/azure/run.sh +++ b/azure/run.sh @@ -31,6 +31,7 @@ then python multivimbroker/scripts/api.py else # nohup python manage.py runserver 0.0.0.0:9008 2>&1 & + nohup aria-rest 2>&1 & nohup uwsgi --http :9008 --module multicloud_azure.wsgi --master --processes 4 & nohup python -m multicloud_azure.event_listener.server 2>&1 & |