You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by mx...@apache.org on 2017/03/26 08:37:11 UTC

[1/2] incubator-ariatosca git commit: ARIA-83 Support ARIA profile for TOSCA [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-120-Builtin-workflows-relationship-operations-execution-order b63947ffa -> 6bd69d7c3 (forced update)


ARIA-83 Support ARIA profile for TOSCA


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/b3cf69ae
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/b3cf69ae
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/b3cf69ae

Branch: refs/heads/ARIA-120-Builtin-workflows-relationship-operations-execution-order
Commit: b3cf69ae3c555569088e60c78678f5c34d09d8c4
Parents: aa7b967
Author: Tal Liron <ta...@gmail.com>
Authored: Wed Mar 22 15:07:57 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Thu Mar 23 12:25:58 2017 -0500

----------------------------------------------------------------------
 aria/cli/commands.py                            |  9 +-
 aria/modeling/orchestration.py                  | 50 +++++++++--
 aria/modeling/service_common.py                 | 47 ++++++----
 aria/modeling/service_instance.py               | 10 +--
 aria/modeling/service_template.py               | 11 +--
 .../profiles/aria-1.0/aria-1.0.yaml             | 59 +++++++++++++
 .../simple_nfv_v1_0/presenter.py                | 11 +--
 .../simple_v1_0/modeling/__init__.py            | 10 +--
 .../simple_v1_0/presenter.py                    |  4 +-
 setup.py                                        |  3 +-
 tests/end2end/test_orchestrator.py              |  7 +-
 tests/mock/models.py                            | 20 ++---
 tests/modeling/test_models.py                   | 23 ++---
 tests/orchestrator/context/test_operation.py    |  1 -
 tests/orchestrator/context/test_serialize.py    |  1 -
 tests/orchestrator/workflows/api/test_task.py   | 19 ++--
 tests/orchestrator/workflows/core/test_task.py  | 16 +---
 .../node-cellar/node-cellar.yaml                | 40 ++++-----
 .../node-cellar/types/aria.yaml                 | 93 --------------------
 .../node-cellar/types/mongodb.yaml              | 25 +++---
 .../node-cellar/types/nginx.yaml                | 25 +++---
 .../node-cellar/types/nodejs.yaml               | 25 +++---
 .../node-cellar/types/openstack.yaml            | 25 +++---
 .../tosca-simple-1.0/node-cellar/types/os.yaml  | 25 +++---
 24 files changed, 259 insertions(+), 300 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/aria/cli/commands.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands.py b/aria/cli/commands.py
index 1eef61d..ee329e7 100644
--- a/aria/cli/commands.py
+++ b/aria/cli/commands.py
@@ -206,7 +206,7 @@ class WorkflowCommand(BaseCommand):
     :code:`workflow` command.
     """
 
-    WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('function', 'implementation', 'dependencies')
+    WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('implementation', 'dependencies')
     
     def __call__(self, args_namespace, unknown_args):
         super(WorkflowCommand, self).__call__(args_namespace, unknown_args)
@@ -241,12 +241,9 @@ class WorkflowCommand(BaseCommand):
             if workflow.type.role != 'workflow':
                 raise AttributeError('policy is not a workflow: "{0}"'.format(workflow_name))
 
-            try:
-                sys.path.append(workflow.properties['implementation'].value)
-            except KeyError:
-                pass
+            sys.path.append(os.path.dirname(str(context.presentation.location)))
     
-            workflow_fn = import_fullname(workflow.properties['function'].value)
+            workflow_fn = import_fullname(workflow.properties['implementation'].value)
     
             for k in workflow.properties:
                 if k in WORKFLOW_DECORATOR_RESERVED_ARGUMENTS:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 0277756..2d58671 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -39,9 +39,12 @@ from sqlalchemy.ext.associationproxy import association_proxy
 from sqlalchemy.ext.declarative import declared_attr
 
 from ..orchestrator.exceptions import (TaskAbortException, TaskRetryException)
-from .types import (List, Dict)
+from .types import Dict
 from .mixins import ModelMixin
-from . import relationship
+from . import (
+    relationship,
+    types as modeling_types
+)
 
 
 class ExecutionBase(ModelMixin):
@@ -140,7 +143,44 @@ class ExecutionBase(ModelMixin):
 
 class PluginBase(ModelMixin):
     """
-    Plugin model representation.
+    An installed plugin.
+
+    Plugins are usually packaged as `wagons <https://github.com/cloudify-cosmo/wagon>`__, which
+    are archives of one or more `wheels <https://packaging.python.org/distributing/#wheels>`__.
+    Most of these fields are indeed extracted from the installed wagon's metadata.
+
+    :ivar archive_name: Filename (not the full path) of the wagon's archive, often with a ".wgn"
+                        extension
+    :vartype archive_name: basestring
+    :ivar distribution: The name of the operating system on which the wagon was installed (e.g.
+                        "ubuntu")
+    :vartype distribution: basestring
+    :ivar distribution_release: The release of the operating system on which the wagon was installed
+                                (e.g. "trusty")
+    :vartype distribution_release: basestring
+    :ivar distribution_version: The version of the operating system on which the wagon was installed
+                                (e.g. "14.04")
+    :vartype distribution_version: basestring
+    :ivar package_name: The primary Python package name used when the wagon was installed, which is
+                        one of the wheels in the wagon (e.g. "cloudify-script-plugin")
+    :vartype package_name: basestring
+    :ivar package_source: The full install string for the primary Python package name used when the
+                          wagon was installed (e.g. "cloudify-script-plugin==1.2")
+    :vartype package_source: basestring
+    :ivar package_version: The version for the primary Python package name used when the wagon was
+                           installed (e.g. "1.2")
+    :vartype package_version: basestring
+    :ivar supported_platform: If the wheels are *all* pure Python then this would be "any",
+                              otherwise it would be the installed platform name (e.g.
+                              "linux_x86_64")
+    :vartype supported_platform: basestring
+    :ivar supported_py_versions: The Python versions supported by all the wheels (e.g. ["py26",
+                                 "py27"])
+    :vartype supported_py_versions: [basestring]
+    :ivar wheels: The filenames of the wheels archived in the wagon, often with a ".whl" extension
+    :vartype wheels: [basestring]
+    :ivar uploaded_at: Timestamp for when the wagon was installed
+    :vartype uploaded_at: basestring
     """
 
     __tablename__ = 'plugin'
@@ -153,9 +193,9 @@ class PluginBase(ModelMixin):
     package_source = Column(Text)
     package_version = Column(Text)
     supported_platform = Column(Text)
-    supported_py_versions = Column(List)
+    supported_py_versions = Column(modeling_types.StrictList(basestring))
+    wheels = Column(modeling_types.StrictList(basestring), nullable=False)
     uploaded_at = Column(DateTime, nullable=False, index=True)
-    wheels = Column(List, nullable=False)
 
 
 class TaskBase(ModelMixin):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 3f49645..d6b1f33 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -25,7 +25,6 @@ from sqlalchemy.ext.declarative import declared_attr
 from ..parser.consumption import ConsumptionContext
 from ..utils import collections, formatting, console
 from .mixins import InstanceModelMixin, TemplateModelMixin
-from .types import List
 from . import (
     relationship,
     utils
@@ -39,9 +38,12 @@ class ParameterBase(TemplateModelMixin):
     This model is used by both service template and service instance elements.
 
     :ivar name: Name
+    :vartype name: basestring
     :ivar type_name: Type name
+    :vartype type_name: basestring
     :ivar value: Value
     :ivar description: Description
+    :vartype description: basestring
     """
 
     __tablename__ = 'parameter'
@@ -218,7 +220,9 @@ class MetadataBase(TemplateModelMixin):
     This model is used by both service template and service instance elements.
 
     :ivar name: Name
+    :vartype name: basestring
     :ivar value: Value
+    :vartype value: basestring
     """
 
     __tablename__ = 'metadata'
@@ -246,24 +250,21 @@ class MetadataBase(TemplateModelMixin):
             context.style.literal(self.value)))
 
 
-class PluginSpecificationBase(InstanceModelMixin):
+class PluginSpecificationBase(TemplateModelMixin):
     """
-    Plugin specification model representation.
+    Plugin specification.
+
+    :ivar name: Required plugin name
+    :vartype name: basestring
+    :ivar version: Minimum plugin version
+    :vartype version: basestring
     """
 
     __tablename__ = 'plugin_specification'
 
     __private_fields__ = ['service_template_fk']
 
-    archive_name = Column(Text, nullable=False, index=True)
-    distribution = Column(Text)
-    distribution_release = Column(Text)
-    distribution_version = Column(Text)
-    package_name = Column(Text, nullable=False, index=True)
-    package_source = Column(Text)
-    package_version = Column(Text)
-    supported_platform = Column(Text)
-    supported_py_versions = Column(List)
+    version = Column(Text, nullable=True)
 
     # region foreign keys
 
@@ -274,12 +275,28 @@ class PluginSpecificationBase(InstanceModelMixin):
 
     # endregion
 
+    @property
+    def as_raw(self):
+        return collections.OrderedDict((
+            ('name', self.name),
+            ('version', self.version)))
+
     def coerce_values(self, container, report_issues):
         pass
 
+    def instantiate(self, container):
+        from . import models
+        return models.PluginSpecification(name=self.name,
+                                          version=self.version)
+
     def find_plugin(self, plugins):
-        # TODO: this should check versions/distribution and other specification
+        matching_plugins = []
         for plugin in plugins:
-            if plugin.name == self.name:
-                return plugin
+            # TODO: we need to use a version comparator
+            if (plugin.name == self.name) and \
+                ((self.version is None) or (plugin.package_version >= self.version)):
+                matching_plugins.append(plugin)
+        if matching_plugins:
+            # Return highest version of plugin
+            return sorted(matching_plugins, key=lambda plugin: plugin.package_version)[-1]
         return None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index b97c148..f120734 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -64,7 +64,7 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
     :vartype outputs: {basestring: :class:`Parameter`}
     :ivar workflows: Custom workflows that can be performed on the service
     :vartype workflows: {basestring: :class:`Operation`}
-    :ivar plugin_specifications: Plugins required to be installed
+    :ivar plugin_specifications: Plugins used by the service
     :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
     :ivar created_at: Creation timestamp
     :vartype created_at: :class:`datetime.datetime`
@@ -131,7 +131,7 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
 
     @declared_attr
     def plugin_specifications(cls):
-        return relationship.many_to_many(cls, 'plugin_specification')
+        return relationship.many_to_many(cls, 'plugin_specification', dict_key='name')
 
     created_at = Column(DateTime, nullable=False, index=True)
     updated_at = Column(DateTime)
@@ -315,8 +315,6 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
     :vartype outbound_relationships: [:class:`Relationship`]
     :ivar inbound_relationships: Relationships from other nodes
     :vartype inbound_relationships: [:class:`Relationship`]
-    :ivar plugin_specifications: Plugins required to be installed on the node's host
-    :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
     :ivar host: Host node (can be self)
     :vartype host: :class:`Node`
 
@@ -386,10 +384,6 @@ class NodeBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
                                         child_property='target_node')
 
     @declared_attr
-    def plugin_specifications(cls):
-        return relationship.many_to_many(cls, 'plugin_specification', dict_key='name')
-
-    @declared_attr
     def host(cls):
         return relationship.one_to_one_self(cls, 'host_fk')
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 5d667e3..7246ff1 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -70,7 +70,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
     :vartype outputs: {basestring: :class:`Parameter`}
     :ivar workflow_templates: Custom workflows that can be performed on the service
     :vartype workflow_templates: {basestring: :class:`OperationTemplate`}
-    :ivar plugin_specifications: Plugins required by services
+    :ivar plugin_specifications: Plugins used by the service
     :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
     :ivar node_types: Base for the node type hierarchy
     :vartype node_types: :class:`Type`
@@ -86,8 +86,6 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
     :vartype interface_types: :class:`Type`
     :ivar artifact_types: Base for the artifact type hierarchy
     :vartype artifact_types: :class:`Type`
-    :ivar plugin_specifications: Plugins required to be installed
-    :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
     :ivar created_at: Creation timestamp
     :vartype created_at: :class:`datetime.datetime`
     :ivar updated_at: Update timestamp
@@ -274,6 +272,7 @@ class ServiceTemplateBase(TemplateModelMixin): # pylint: disable=too-many-public
         utils.instantiate_dict(self, service.groups, self.group_templates)
         utils.instantiate_dict(self, service.policies, self.policy_templates)
         utils.instantiate_dict(self, service.workflows, self.workflow_templates)
+        utils.instantiate_dict(self, service.plugin_specifications, self.plugin_specifications)
 
         if self.substitution_template is not None:
             service.substitution = self.substitution_template.instantiate(container)
@@ -395,8 +394,6 @@ class NodeTemplateBase(TemplateModelMixin):
     :vartype requirement_templates: [:class:`RequirementTemplate`]
     :ivar target_node_template_constraints: Constraints for filtering relationship targets
     :vartype target_node_template_constraints: [:class:`FunctionType`]
-    :ivar plugin_specifications: Plugins required to be installed on the node's host
-    :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
 
     :ivar service_template: Containing service template
     :vartype service_template: :class:`ServiceTemplate`
@@ -448,10 +445,6 @@ class NodeTemplateBase(TemplateModelMixin):
 
     target_node_template_constraints = Column(modeling_types.StrictList(FunctionType))
 
-    @declared_attr
-    def plugin_specifications(cls):
-        return relationship.many_to_many(cls, 'plugin_specification', dict_key='name')
-
     # region foreign_keys
 
     @declared_attr

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
new file mode 100644
index 0000000..09cef57
--- /dev/null
+++ b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
@@ -0,0 +1,59 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+policy_types:
+
+  aria.Plugin:
+    _extensions:
+      role: plugin
+    description: >-
+      Policy used to specify plugins used by services. For an operation to be able to use a plugin
+      it must have a matching policy. The name of the policy must be the name of the plugin. The
+      optional properties can be used to further specify plugin selection by the orchestrator.
+    derived_from: tosca.policies.Root
+    properties:
+      version:
+        description: >-
+          Minimum plugin version.
+        type: version
+        required: false
+
+  aria.Workflow:
+    _extensions:
+      role: workflow
+    description: >-
+      Policy used to specify custom workflows. A workflow is usually a workload of interconnected
+      calls to operations on nodes and relationships in the service topology. The name of the policy
+      is used as the name of the workflow. Note that it can be the same name as one of the normative
+      lifecycle workflows ("install", "uninstall", etc.), in which case it would be considered an
+      override of the default behavior. If the workflow requires parameters then this base type
+      should be inherited and extended with additional properties.
+    derived_from: tosca.policies.Root
+    properties:
+      implementation:
+        description: >-
+          The interpretation of the implementation string depends on the orchestrator. In ARIA it is
+          the full path to a Python @workflow function that generates a task graph based on the
+          service topology.
+        type: string
+        required: true
+      dependencies:
+        description: >-
+          The optional ordered list of one or more dependent or secondary implementation artifact
+          name which are referenced by the primary implementation artifact (e.g., a library the
+          script installs or a secondary script).
+        type: list
+        entry_schema: string
+        required: false

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
index 8098ccf..0ce918e 100644
--- a/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
+++ b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from aria.utils.collections import FrozenList, EMPTY_READ_ONLY_LIST
+from aria.utils.collections import FrozenList
 from aria.utils.caching import cachedmethod
 
 from ..simple_v1_0 import ToscaSimplePresenter1_0
@@ -37,10 +37,7 @@ class ToscaSimpleNfvPresenter1_0(ToscaSimplePresenter1_0): # pylint: disable=inv
 
     @cachedmethod
     def _get_import_locations(self, context):
-        import_locations = []
+        import_locations = super(ToscaSimpleNfvPresenter1_0, self)._get_import_locations(context)
         if context.presentation.import_profile:
-            import_locations += (self.SIMPLE_PROFILE_LOCATION, self.SIMPLE_PROFILE_FOR_NFV_LOCATION)
-        imports = self._get('service_template', 'imports')
-        if imports:
-            import_locations += [i.file for i in imports]
-        return FrozenList(import_locations) if import_locations else EMPTY_READ_ONLY_LIST
+            return FrozenList([self.SIMPLE_PROFILE_FOR_NFV_LOCATION] + import_locations)
+        return import_locations

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 4477732..d0a39e6 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -441,15 +441,7 @@ def create_plugin_specification_model(context, policy):
         return prop.value if prop is not None else None
 
     model = PluginSpecification(name=policy._name,
-                                archive_name=get('archive_name') or '',
-                                distribution=get('distribution'),
-                                distribution_release=get('distribution_release'),
-                                distribution_version=get('distribution_version'),
-                                package_name=get('package_name') or '',
-                                package_source=get('package_source'),
-                                package_version=get('package_version'),
-                                supported_platform=get('supported_platform'),
-                                supported_py_versions=get('supported_py_versions'))
+                                version=get('version'))
 
     return model
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/extensions/aria_extension_tosca/simple_v1_0/presenter.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
index eee5769..96cc763 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presenter.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presenter.py
@@ -35,6 +35,8 @@ class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name
     DSL_VERSIONS = ('tosca_simple_yaml_1_0',)
     ALLOWED_IMPORTED_DSL_VERSIONS = ('tosca_simple_yaml_1_0',)
     SIMPLE_PROFILE_LOCATION = 'tosca-simple-1.0/tosca-simple-1.0.yaml'
+    SPECIAL_IMPORTS = {
+        'aria-1.0': 'aria-1.0/aria-1.0.yaml'}
 
     @property
     @cachedmethod
@@ -71,7 +73,7 @@ class ToscaSimplePresenter1_0(Presenter): # pylint: disable=invalid-name
             import_locations.append(self.SIMPLE_PROFILE_LOCATION)
         imports = self._get('service_template', 'imports')
         if imports:
-            import_locations += [i.file for i in imports]
+            import_locations += [self.SPECIAL_IMPORTS.get(i.file, i.file) for i in imports]
         return FrozenList(import_locations) if import_locations else EMPTY_READ_ONLY_LIST
 
     @cachedmethod

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index ff1f5a6..7be5275 100644
--- a/setup.py
+++ b/setup.py
@@ -105,7 +105,8 @@ setup(
     package_data={
         'aria_extension_tosca': [
             'profiles/tosca-simple-1.0/**',
-            'profiles/tosca-simple-nfv-1.0/**'
+            'profiles/tosca-simple-nfv-1.0/**',
+            'profiles/aria-1.0/**'
         ]
     },
     zip_safe=False,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/end2end/test_orchestrator.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_orchestrator.py b/tests/end2end/test_orchestrator.py
index 7b8dc97..4dfca44 100644
--- a/tests/end2end/test_orchestrator.py
+++ b/tests/end2end/test_orchestrator.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 import sys
+import os
 
 from aria.orchestrator.runner import Runner
 from aria.orchestrator.workflows.builtin import BUILTIN_WORKFLOWS
@@ -24,7 +25,7 @@ from aria.cli.dry import convert_to_dry
 from tests.parser.service_templates import consume_node_cellar
 
 
-WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('function', 'implementation', 'dependencies')
+WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('implementation', 'dependencies')
 
 
 def test_install():
@@ -47,8 +48,8 @@ def _workflow(workflow_name):
         inputs = {}
     else:
         workflow = context.modeling.instance.policies[workflow_name]
-        sys.path.append(workflow.properties['implementation'].value)
-        workflow_fn = import_fullname(workflow.properties['function'].value)
+        sys.path.append(os.path.dirname(str(context.presentation.location)))
+        workflow_fn = import_fullname(workflow.properties['implementation'].value)
         inputs = OrderedDict([
             (k, v.value) for k, v in workflow.properties.iteritems()
             if k not in WORKFLOW_POLICY_INTERNAL_PROPERTIES

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index bf43a75..a60b35e 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -191,14 +191,14 @@ def create_execution(service):
     )
 
 
-def create_plugin(package_name='package', package_version='0.1'):
+def create_plugin(name='test_plugin', package_version='0.1'):
     return models.Plugin(
-        name='test_plugin',
+        name=name,
         archive_name='archive_name',
         distribution='distribution',
         distribution_release='dist_release',
         distribution_version='dist_version',
-        package_name=package_name,
+        package_name='package',
         package_source='source',
         package_version=package_version,
         supported_platform='any',
@@ -208,18 +208,10 @@ def create_plugin(package_name='package', package_version='0.1'):
     )
 
 
-def create_plugin_specification(package_name='package', package_version='0.1'):
+def create_plugin_specification(name='test_plugin', version='0.1'):
     return models.PluginSpecification(
-        name='test_plugin',
-        archive_name='archive_name',
-        distribution='distribution',
-        distribution_release='dist_release',
-        distribution_version='dist_version',
-        package_name=package_name,
-        package_source='source',
-        package_version=package_version,
-        supported_platform='any',
-        supported_py_versions=['python27']
+        name=name,
+        version=version
     )
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/modeling/test_models.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py
index 8c5e23a..c3b98c1 100644
--- a/tests/modeling/test_models.py
+++ b/tests/modeling/test_models.py
@@ -513,22 +513,19 @@ class TestServiceModification(object):
 
 class TestNodeTemplate(object):
     @pytest.mark.parametrize(
-        'is_valid, name, default_instances, max_instances, min_instances, plugin_specifications, '
-        'properties',
+        'is_valid, name, default_instances, max_instances, min_instances, properties',
         [
-            (False, m_cls, 1, 1, 1, {}, {}),
-            (False, 'name', m_cls, 1, 1, {}, {}),
-            (False, 'name', 1, m_cls, 1, {}, {}),
-            (False, 'name', 1, 1, m_cls, {}, {}),
-            (False, 'name', 1, 1, 1, m_cls, {}),
-            (False, 'name', 1, 1, 1, None, {}),
-
-            (True, 'name', 1, 1, 1, {}, {}),
+            (False, m_cls, 1, 1, 1, {}),
+            (False, 'name', m_cls, 1, 1, {}),
+            (False, 'name', 1, m_cls, 1, {}),
+            (False, 'name', 1, 1, m_cls, {}),
+            (False, 'name', 1, 1, 1, m_cls),
+
+            (True, 'name', 1, 1, 1, {}),
         ]
     )
     def test_node_template_model_creation(self, service_storage, is_valid, name, default_instances,
-                                          max_instances, min_instances, plugin_specifications,
-                                          properties):
+                                          max_instances, min_instances, properties):
         node_template = _test_model(
             is_valid=is_valid,
             storage=service_storage,
@@ -539,7 +536,6 @@ class TestNodeTemplate(object):
                 default_instances=default_instances,
                 max_instances=max_instances,
                 min_instances=min_instances,
-                plugin_specifications=plugin_specifications,
                 properties=properties,
                 service_template=service_storage.service_template.list()[0]
             ))
@@ -852,4 +848,3 @@ class TestType(object):
 
         assert super_type.hierarchy == [super_type, additional_type]
         assert sub_type.hierarchy == [sub_type, super_type, additional_type]
-

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index f8a79c5..6721b29 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -241,7 +241,6 @@ def test_plugin_workdir(ctx, thread_executor, tmpdir):
             plugin_specification=plugin_specification)
     )
     node.interfaces[interface.name] = interface
-    node.plugin_specifications[plugin_specification.name] = plugin_specification
     ctx.model.node.update(node)
 
     filename = 'test_file'

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/orchestrator/context/test_serialize.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_serialize.py b/tests/orchestrator/context/test_serialize.py
index 9a1250e..db45e8e 100644
--- a/tests/orchestrator/context/test_serialize.py
+++ b/tests/orchestrator/context/test_serialize.py
@@ -54,7 +54,6 @@ def _mock_workflow(ctx, graph):
                               plugin_specification=plugin_specification)
     )
     node.interfaces[interface.name] = interface
-    node.plugin_specifications[plugin_specification.name] = plugin_specification
     task = api.task.OperationTask.for_node(node=node, interface_name='test', operation_name='op')
     graph.add_tasks(task)
     return graph

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/orchestrator/workflows/api/test_task.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/api/test_task.py b/tests/orchestrator/workflows/api/test_task.py
index b635a88..80d2351 100644
--- a/tests/orchestrator/workflows/api/test_task.py
+++ b/tests/orchestrator/workflows/api/test_task.py
@@ -42,10 +42,10 @@ class TestOperationTask(object):
         interface_name = 'test_interface'
         operation_name = 'create'
 
-        plugin = mock.models.create_plugin('package', '0.1')
+        plugin = mock.models.create_plugin('test_plugin', '0.1')
         ctx.model.node.update(plugin)
 
-        plugin_specification = mock.models.create_plugin_specification('package', '0.1')
+        plugin_specification = mock.models.create_plugin_specification('test_plugin', '0.1')
 
         interface = mock.models.create_interface(
             ctx.service,
@@ -56,7 +56,6 @@ class TestOperationTask(object):
 
         node = ctx.model.node.get_by_name(mock.models.DEPENDENT_NODE_NAME)
         node.interfaces[interface_name] = interface
-        node.plugin_specifications[plugin_specification.name] = plugin_specification
         ctx.model.node.update(node)
         inputs = {'test_input': True}
         max_attempts = 10
@@ -92,10 +91,10 @@ class TestOperationTask(object):
         interface_name = 'test_interface'
         operation_name = 'preconfigure'
 
-        plugin = mock.models.create_plugin('package', '0.1')
-        ctx.model.node.update(plugin)
+        plugin = mock.models.create_plugin('test_plugin', '0.1')
+        ctx.model.plugin.update(plugin)
 
-        plugin_specification = mock.models.create_plugin_specification('package', '0.1')
+        plugin_specification = mock.models.create_plugin_specification('test_plugin', '0.1')
 
         interface = mock.models.create_interface(
             ctx.service,
@@ -107,8 +106,6 @@ class TestOperationTask(object):
 
         relationship = ctx.model.relationship.list()[0]
         relationship.interfaces[interface.name] = interface
-        relationship.source_node.plugin_specifications[plugin_specification.name] = \
-            plugin_specification
         inputs = {'test_input': True}
         max_attempts = 10
         retry_interval = 10
@@ -140,10 +137,10 @@ class TestOperationTask(object):
         interface_name = 'test_interface'
         operation_name = 'preconfigure'
 
-        plugin = mock.models.create_plugin('package', '0.1')
+        plugin = mock.models.create_plugin('test_plugin', '0.1')
         ctx.model.node.update(plugin)
 
-        plugin_specification = mock.models.create_plugin_specification('package', '0.1')
+        plugin_specification = mock.models.create_plugin_specification('test_plugin', '0.1')
 
         interface = mock.models.create_interface(
             ctx.service,
@@ -155,8 +152,6 @@ class TestOperationTask(object):
 
         relationship = ctx.model.relationship.list()[0]
         relationship.interfaces[interface.name] = interface
-        relationship.target_node.plugin_specifications[plugin_specification.name] = \
-            plugin_specification
         inputs = {'test_input': True}
         max_attempts = 10
         retry_interval = 10

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/orchestrator/workflows/core/test_task.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_task.py b/tests/orchestrator/workflows/core/test_task.py
index f3ce92f..18ca056 100644
--- a/tests/orchestrator/workflows/core/test_task.py
+++ b/tests/orchestrator/workflows/core/test_task.py
@@ -83,19 +83,12 @@ class TestOperationTask(object):
         return api_task, core_task
 
     def test_node_operation_task_creation(self, ctx):
-        storage_plugin = mock.models.create_plugin(
-            package_name='p1', package_version='0.1')
-        storage_plugin_specification = mock.models.create_plugin_specification(
-            package_name='p1', package_version='0.1')
-        storage_plugin_specification_other = mock.models.create_plugin(
-            package_name='p0', package_version='0.0')
+        storage_plugin = mock.models.create_plugin('p1', '0.1')
+        storage_plugin_other = mock.models.create_plugin('p0', '0.0')
         ctx.model.plugin.put(storage_plugin)
-        ctx.model.plugin_specification.put(storage_plugin_specification_other)
-        ctx.model.plugin_specification.put(storage_plugin_specification)
+        ctx.model.plugin.put(storage_plugin_other)
         node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
-        node_template = node.node_template
-        node_template.plugin_specifications[storage_plugin_specification.name] = \
-            storage_plugin_specification
+        storage_plugin_specification = mock.models.create_plugin_specification('p1', '0.1')
         interface = mock.models.create_interface(
             node.service,
             NODE_INTERFACE_NAME,
@@ -103,7 +96,6 @@ class TestOperationTask(object):
             operation_kwargs=dict(plugin_specification=storage_plugin_specification)
         )
         node.interfaces[interface.name] = interface
-        ctx.model.node_template.update(node_template)
         ctx.model.node.update(node)
         api_task, core_task = self._create_node_operation_task(ctx, node)
         storage_task = ctx.model.task.get_by_name(core_task.name)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
index 3afcf5f..b950fa4 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 # NFV is not used here, but we are using it just to validate the imports
 tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
@@ -33,7 +32,7 @@ imports:
   - types/nodejs.yaml
   - types/mongodb.yaml
   - types/nginx.yaml
-  - types/aria.yaml
+  - aria-1.0
 
 dsl_definitions:
 
@@ -254,9 +253,8 @@ topology_template:
         Juju plugin executes charms.
       type: aria.Plugin
       properties:
-        executor: host_agent
-        install: false
-    
+        version: 1.0
+
     maintenance_on:
       type: MaintenanceWorkflow
       properties:
@@ -284,16 +282,10 @@ policy_types:
       client connections cleanly and shut down services. 
     derived_from: aria.Workflow
     properties:
-      function: # @override
-        type: string
-        default: workflows.maintenance
       implementation:
         type: string
-        default: tests/resources/service-templates/tosca-simple-1.0/node-cellar
+        default: workflows.maintenance
       enabled:
         description: >-
           Whether to turn maintenance mode on or off.
         type: boolean
-      #ctx:
-      #  type: string
-      #  default: abc

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/aria.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/aria.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/aria.yaml
deleted file mode 100644
index 2ddb238..0000000
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/aria.yaml
+++ /dev/null
@@ -1,93 +0,0 @@
-
-policy_types:
-
-  aria.Plugin:
-    _extensions:
-      role: plugin
-    description: >-
-      ARIA Plugin definition.
-    derived_from: tosca.policies.Root
-    properties:
-      executor:
-        description: >-
-          Where to execute the plugin's operations.
-        type: string
-        constraints:
-          - valid_values: [ central_deployment_agent, host_agent ]
-      source:
-        description: >-
-          Where to execute the plugin's operations. Where to retrieve the plugin from. Could be
-          either a path relative to the plugins dir inside the blueprint's root dir or a url. If
-          install is false, source is redundant. If install is true, source (or package_name) is
-          mandatory.
-        type: string
-        required: false
-      install_arguments:
-        description: >-
-          Optional arguments passed to the 'pip install' command created for the plugin
-          installation.
-        type: string
-        required: false
-      install:
-        description: >-
-          Whether to install the plugin or not as it might already be installed as part of the
-          agent.
-        type: boolean
-        default: true
-      package_name:
-        description: >-
-          Managed plugin package name. If install is false, package_name is redundant. If install is
-          true, package_name (or source) is mandatory.
-        type: string
-        required: false
-      package_version:
-        description: >-
-          Managed plugin package version.
-        type: string
-        required: false
-      supported_platform:
-        description: >-
-          Managed plugin supported platform (e.g. linux_x86_64).
-        type: string
-        required: false
-      supported_distribution:
-        description: >-
-          Managed plugin distribution.
-        type: string
-        required: false
-      distribution_version:
-        description: >-
-          Managed plugin distribution version.
-        type: string
-        required: false
-      distribution_release:
-        description: >-
-          Managed plugin distribution release.
-        type: string
-        required: false
-
-  aria.Workflow:
-    _extensions:
-      role: workflow
-    description: >-
-      ARIA Workflow definition.
-    derived_from: tosca.policies.Root
-    properties:
-      function:
-        description: >-
-          Python workflow function.
-        type: string
-      implementation:
-        description: >-
-          The implementation artifact name (i.e., the primary script file name within a TOSCA CSAR
-          file).
-        type: string
-        required: false
-      dependencies:
-        description: >-
-          The optional ordered list of one or more dependent or secondary implementation artifact
-          name which are referenced by the primary implementation artifact (e.g., a library the
-          script installs or a secondary script).
-        type: list
-        entry_schema: string
-        required: false

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
index 612dbcb..34d0a9d 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 imports:
   - os.yaml

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml
index 8986a21..eab130f 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 node_types:
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
index ec8dd83..4fd4e72 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 imports:
   - os.yaml

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
index a18da53..de5fb47 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 imports:
   - os.yaml

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/b3cf69ae/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml
index 43ea78c..adc6363 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml
@@ -1,18 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
 #
-# Copyright (c) 2016 GigaSpaces Technologies Ltd. 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.
+#     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.
 
 dsl_definitions:
 


[2/2] incubator-ariatosca git commit: ARIA-120-Builtin-workflows-relationship-operations-execution-order

Posted by mx...@apache.org.
ARIA-120-Builtin-workflows-relationship-operations-execution-order


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/6bd69d7c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/6bd69d7c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/6bd69d7c

Branch: refs/heads/ARIA-120-Builtin-workflows-relationship-operations-execution-order
Commit: 6bd69d7c36c4f67fa9553188af1d8331f51d251a
Parents: b3cf69a
Author: max-orlov <ma...@gigaspaces.com>
Authored: Mon Mar 13 16:35:10 2017 +0200
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Sun Mar 26 11:37:04 2017 +0300

----------------------------------------------------------------------
 aria/modeling/relationship.py                   |   2 +-
 aria/orchestrator/workflows/api/task.py         |   3 +
 aria/orchestrator/workflows/builtin/utils.py    |  75 ++++++++---
 .../orchestrator/workflows/builtin/workflows.py | 100 +++++----------
 tests/mock/context.py                           |   7 +-
 tests/mock/models.py                            | 123 ++++++++++++++-----
 tests/mock/topology.py                          |  41 +++++--
 tests/modeling/test_models.py                   |  30 +++--
 .../orchestrator/workflows/builtin/__init__.py  |  69 +++++++++--
 .../orchestrator/workflows/builtin/test_heal.py |   7 +-
 .../workflows/builtin/test_install.py           |  15 ++-
 .../workflows/builtin/test_uninstall.py         |  15 ++-
 12 files changed, 315 insertions(+), 172 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index ef2bcdd..70691b3 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -308,7 +308,7 @@ def many_to_many(model_class,
     if prefix is not None:
         secondary_table = '{0}_{1}'.format(prefix, secondary_table)
         if other_property is None:
-            other_property = '{0}_{1}'.format(prefix, this_table)
+            other_property = '{0}_{1}'.format(prefix, formatting.pluralize(this_table))
 
     backref_kwargs = backref_kwargs or {}
     backref_kwargs.setdefault('uselist', True)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index 009b81c..25d631d 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -123,6 +123,9 @@ class OperationTask(BaseTask):
                                                      interface=interface_name,
                                                      operation=operation_name)
 
+    def __repr__(self):
+        return self.name
+
     @classmethod
     def for_node(cls,
                  node,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/aria/orchestrator/workflows/builtin/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/utils.py b/aria/orchestrator/workflows/builtin/utils.py
index 8efa889..79d02ab 100644
--- a/aria/orchestrator/workflows/builtin/utils.py
+++ b/aria/orchestrator/workflows/builtin/utils.py
@@ -12,12 +12,13 @@
 # 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.
+from itertools import groupby
 
 from ..api.task import OperationTask
 from .. import exceptions
 
 
-def create_node_task(interface_name, operation_name, node):
+def create_node_task(node, interface_name, operation_name):
     """
     Returns a new operation task if the operation exists in the node, otherwise returns None.
     """
@@ -31,24 +32,59 @@ def create_node_task(interface_name, operation_name, node):
         return None
 
 
-def create_relationship_tasks(interface_name, operation_name, runs_on, node):
+def create_relationships_tasks(
+        node, interface_name, source_operation_name=None, target_operation_name=None):
     """
-    Returns a list of operation tasks for each outbound relationship of the node if the operation
-    exists there.
+    Creates a relationship task (source and target) for all of a node_instance relationships.
+    :param basestring source_operation_name: the relationship operation name.
+    :param source_operation_name:
+    :param target_operation_name:
+    :param NodeInstance node: the source_node
+    :return:
     """
+    relationships_groups = groupby(node.outbound_relationships,
+                                   key=lambda relationship: relationship.target_node.id)
 
-    sequence = []
-    for relationship in node.outbound_relationships:
-        try:
-            sequence.append(
-                OperationTask.for_relationship(relationship=relationship,
-                                               interface_name=interface_name,
-                                               operation_name=operation_name,
-                                               runs_on=runs_on))
-        except exceptions.OperationNotFoundException:
-            # We will skip relationships which do not have the operation
-            pass
-    return sequence
+    sub_tasks = []
+    for _, (_, relationship_group) in enumerate(relationships_groups):
+        for relationship in relationship_group:
+            relationship_operations = relationship_tasks(
+                relationship,
+                interface_name,
+                source_operation_name=source_operation_name,
+                target_operation_name=target_operation_name)
+            sub_tasks.append(relationship_operations)
+
+    return sub_tasks
+
+
+def relationship_tasks(
+        relationship, interface_name, source_operation_name=None, target_operation_name=None):
+    """
+    Creates a relationship task source and target.
+    :param Relationship relationship: the relationship instance itself
+    :param source_operation_name:
+    :param target_operation_name:
+
+    :return:
+    """
+    operations = []
+    if source_operation_name and _has_operation(relationship.interfaces, source_operation_name):
+        operations.append(
+            OperationTask.for_relationship(relationship=relationship,
+                                           interface_name=interface_name,
+                                           operation_name=source_operation_name,
+                                           runs_on='source')
+        )
+    if target_operation_name and _has_operation(relationship.interfaces, target_operation_name):
+        operations.append(
+            OperationTask.for_relationship(relationship=relationship,
+                                           interface_name=interface_name,
+                                           operation_name=target_operation_name,
+                                           runs_on='target')
+        )
+
+    return operations
 
 
 def create_node_task_dependencies(graph, tasks_and_nodes, reverse=False):
@@ -74,3 +110,10 @@ def create_node_task_dependencies(graph, tasks_and_nodes, reverse=False):
                     graph.add_dependency(dependency, task)
             else:
                 graph.add_dependency(task, dependencies)
+
+
+def _has_operation(interfaces, operation_name):
+    for interface in interfaces.values():
+        if operation_name in interface.operations:
+            return True
+    return False

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/aria/orchestrator/workflows/builtin/workflows.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/workflows.py b/aria/orchestrator/workflows/builtin/workflows.py
index 6065343..67badcf 100644
--- a/aria/orchestrator/workflows/builtin/workflows.py
+++ b/aria/orchestrator/workflows/builtin/workflows.py
@@ -18,8 +18,10 @@ TSOCA normative lifecycle workflows.
 """
 
 from ... import workflow
-from ....modeling.models import Task
-from .utils import (create_node_task, create_relationship_tasks)
+from .utils import (
+    create_node_task,
+    create_relationships_tasks
+)
 
 
 NORMATIVE_STANDARD_INTERFACE = 'Standard' # 'tosca.interfaces.node.lifecycle.Standard'
@@ -39,6 +41,7 @@ NORMATIVE_POST_CONFIGURE_TARGET = 'post_configure_target'
 NORMATIVE_ADD_SOURCE = 'add_source'
 NORMATIVE_ADD_TARGET = 'add_target'
 NORMATIVE_REMOVE_TARGET = 'remove_target'
+NORMATIVE_REMOVE_SOURCE = 'remove_source'
 NORMATIVE_TARGET_CHANGED = 'target_changed'
 
 
@@ -56,6 +59,7 @@ __all__ = (
     'NORMATIVE_POST_CONFIGURE_TARGET',
     'NORMATIVE_ADD_SOURCE',
     'NORMATIVE_ADD_TARGET',
+    'NORMATIVE_REMOVE_SOURCE',
     'NORMATIVE_REMOVE_TARGET',
     'NORMATIVE_TARGET_CHANGED',
     'install_node',
@@ -67,40 +71,20 @@ __all__ = (
 
 @workflow(suffix_template='{node.name}')
 def install_node(graph, node, **kwargs):
-    sequence = []
-
     # Create
-    sequence.append(
-        create_node_task(
-            NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CREATE,
-            node))
+    sequence = [create_node_task(node,
+                                 NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CREATE)]
 
     # Configure
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_SOURCE,
-            Task.RUNS_ON_SOURCE,
-            node)
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_TARGET,
-            Task.RUNS_ON_TARGET,
-            node)
-    sequence.append(
-        create_node_task(
-            NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CONFIGURE,
-            node))
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_SOURCE,
-            Task.RUNS_ON_SOURCE,
-            node)
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_TARGET,
-            Task.RUNS_ON_TARGET,
-            node)
-
+    sequence += create_relationships_tasks(node,
+                                           NORMATIVE_CONFIGURE_INTERFACE,
+                                           NORMATIVE_PRE_CONFIGURE_SOURCE,
+                                           NORMATIVE_PRE_CONFIGURE_TARGET)
+    sequence.append(create_node_task(node, NORMATIVE_STANDARD_INTERFACE, NORMATIVE_CONFIGURE))
+    sequence += create_relationships_tasks(node,
+                                           NORMATIVE_CONFIGURE_INTERFACE,
+                                           NORMATIVE_POST_CONFIGURE_SOURCE,
+                                           NORMATIVE_POST_CONFIGURE_TARGET)
     # Start
     sequence += _create_start_tasks(node)
 
@@ -113,10 +97,9 @@ def uninstall_node(graph, node, **kwargs):
     sequence = _create_stop_tasks(node)
 
     # Delete
-    sequence.append(
-        create_node_task(
-            NORMATIVE_STANDARD_INTERFACE, NORMATIVE_DELETE,
-            node))
+    sequence.append(create_node_task(node,
+                                     NORMATIVE_STANDARD_INTERFACE,
+                                     NORMATIVE_DELETE))
 
     graph.sequence(*sequence)
 
@@ -132,43 +115,16 @@ def stop_node(graph, node, **kwargs):
 
 
 def _create_start_tasks(node):
-    sequence = []
-    sequence.append(
-        create_node_task(
-            NORMATIVE_STANDARD_INTERFACE, NORMATIVE_START,
-            node))
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_SOURCE,
-            Task.RUNS_ON_SOURCE,
-            node)
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_TARGET,
-            Task.RUNS_ON_TARGET,
-            node)
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
-            Task.RUNS_ON_TARGET,
-            node)
+    sequence = [create_node_task(node, NORMATIVE_STANDARD_INTERFACE, NORMATIVE_START)]
+    sequence += create_relationships_tasks(node,
+                                           NORMATIVE_CONFIGURE_INTERFACE,
+                                           NORMATIVE_ADD_SOURCE, NORMATIVE_ADD_TARGET)
     return sequence
 
 
 def _create_stop_tasks(node):
-    sequence = []
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_REMOVE_TARGET,
-            Task.RUNS_ON_TARGET,
-            node)
-    sequence += \
-        create_relationship_tasks(
-            NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
-            Task.RUNS_ON_TARGET,
-            node)
-    sequence.append(
-        create_node_task(
-            NORMATIVE_STANDARD_INTERFACE, NORMATIVE_STOP,
-            node))
+    sequence = [create_node_task(node, NORMATIVE_STANDARD_INTERFACE, NORMATIVE_STOP)]
+    sequence += create_relationships_tasks(node,
+                                           NORMATIVE_CONFIGURE_INTERFACE,
+                                           NORMATIVE_REMOVE_SOURCE, NORMATIVE_REMOVE_TARGET)
     return sequence

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/mock/context.py
----------------------------------------------------------------------
diff --git a/tests/mock/context.py b/tests/mock/context.py
index 3de3133..f943d7e 100644
--- a/tests/mock/context.py
+++ b/tests/mock/context.py
@@ -27,9 +27,10 @@ from ..storage import init_inmemory_model_storage
 from .topology import create_simple_topology_two_nodes
 
 
-def simple(tmpdir, inmemory=False, context_kwargs=None):
+def simple(tmpdir, inmemory=False, context_kwargs=None, topology=None):
     initiator = init_inmemory_model_storage if inmemory else None
     initiator_kwargs = {} if inmemory else dict(base_dir=tmpdir)
+    topology = topology or create_simple_topology_two_nodes
 
     model_storage = aria.application_model_storage(
         sql_mapi.SQLAlchemyModelAPI, initiator=initiator, initiator_kwargs=initiator_kwargs)
@@ -38,13 +39,11 @@ def simple(tmpdir, inmemory=False, context_kwargs=None):
         api_kwargs=dict(directory=os.path.join(tmpdir, 'resources'))
     )
 
-    service_id = create_simple_topology_two_nodes(model_storage)
-
     final_kwargs = dict(
         name='simple_context',
         model_storage=model_storage,
         resource_storage=resource_storage,
-        service_id=service_id,
+        service_id=topology(model_storage),
         workflow_name=models.WORKFLOW_NAME,
         task_max_attempts=models.TASK_MAX_ATTEMPTS,
         task_retry_interval=models.TASK_RETRY_INTERVAL

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index a60b35e..5c5f7f0 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -16,7 +16,26 @@
 from datetime import datetime
 
 from aria.modeling import models
-from . import operations
+from aria.orchestrator import decorators
+from aria.orchestrator.workflows.builtin.workflows import (
+    NORMATIVE_STANDARD_INTERFACE,
+    NORMATIVE_CREATE,
+    NORMATIVE_START,
+    NORMATIVE_STOP,
+    NORMATIVE_DELETE,
+    NORMATIVE_CONFIGURE,
+
+    NORMATIVE_CONFIGURE_INTERFACE,
+    NORMATIVE_PRE_CONFIGURE_SOURCE,
+    NORMATIVE_PRE_CONFIGURE_TARGET,
+    NORMATIVE_POST_CONFIGURE_SOURCE,
+    NORMATIVE_POST_CONFIGURE_TARGET,
+
+    NORMATIVE_ADD_SOURCE,
+    NORMATIVE_ADD_TARGET,
+    NORMATIVE_REMOVE_TARGET,
+    NORMATIVE_REMOVE_SOURCE
+)
 
 SERVICE_NAME = 'test_service_name'
 SERVICE_TEMPLATE_NAME = 'test_service_template_name'
@@ -62,7 +81,7 @@ def create_service(service_template):
     )
 
 
-def create_dependency_node_template(service_template):
+def create_dependency_node_template(name, service_template):
     node_type = service_template.node_types.get_descendant('test_node_type')
     capability_type = service_template.capability_types.get_descendant('test_capability_type')
 
@@ -72,7 +91,7 @@ def create_dependency_node_template(service_template):
     )
 
     node_template = models.NodeTemplate(
-        name=DEPENDENCY_NODE_TEMPLATE_NAME,
+        name=name,
         type=node_type,
         capability_templates=_dictify(capability_template),
         default_instances=1,
@@ -84,29 +103,21 @@ def create_dependency_node_template(service_template):
     return node_template
 
 
-def create_dependent_node_template(service_template, dependency_node_template):
+def create_dependent_node_template(name, service_template, dependency_node_template):
     the_type = service_template.node_types.get_descendant('test_node_type')
 
-    operation_templates = dict((op, models.OperationTemplate(
-        name=op,
-        implementation='test'))
-                               for _, op in operations.NODE_OPERATIONS)
-    interface_template = models.InterfaceTemplate(
-        type=service_template.interface_types.get_descendant('test_interface_type'),
-        operation_templates=operation_templates)
-
     requirement_template = models.RequirementTemplate(
         name='requirement',
         target_node_template=dependency_node_template
     )
 
     node_template = models.NodeTemplate(
-        name=DEPENDENT_NODE_TEMPLATE_NAME,
+        name=name,
         type=the_type,
         default_instances=1,
         min_instances=1,
         max_instances=1,
-        interface_templates=_dictify(interface_template),
+        interface_templates=_dictify(get_standard_interface_template(service_template)),
         requirement_templates=[requirement_template],
         service_template=service_template
     )
@@ -114,31 +125,17 @@ def create_dependent_node_template(service_template, dependency_node_template):
     return node_template
 
 
-def create_dependency_node(dependency_node_template, service):
+def create_node(name, dependency_node_template, service):
     node = models.Node(
-        name=DEPENDENCY_NODE_NAME,
+        name=name,
         type=dependency_node_template.type,
         runtime_properties={'ip': '1.1.1.1'},
         version=None,
         node_template=dependency_node_template,
         state='',
         scaling_groups=[],
-        service=service
-    )
-    service.nodes[node.name] = node
-    return node
-
-
-def create_dependent_node(dependent_node_template, service):
-    node = models.Node(
-        name=DEPENDENT_NODE_NAME,
-        type=dependent_node_template.type,
-        runtime_properties={},
-        version=None,
-        node_template=dependent_node_template,
-        state='',
-        scaling_groups=[],
-        service=service
+        service=service,
+        interfaces=get_standard_interface(service),
     )
     service.nodes[node.name] = node
     return node
@@ -147,7 +144,8 @@ def create_dependent_node(dependent_node_template, service):
 def create_relationship(source, target):
     return models.Relationship(
         source_node=source,
-        target_node=target
+        target_node=target,
+        interfaces=get_configure_interfaces(service=source.service),
     )
 
 
@@ -217,3 +215,62 @@ def create_plugin_specification(name='test_plugin', version='0.1'):
 
 def _dictify(item):
     return dict(((item.name, item),))
+
+
+def get_standard_interface_template(service_template):
+    the_type = service_template.interface_types.get_descendant('test_interface_type')
+
+    op_templates = dict(
+        (op_name, models.OperationTemplate(
+            name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
+        for op_name in [NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
+                        NORMATIVE_STOP, NORMATIVE_DELETE]
+    )
+    return models.InterfaceTemplate(name=NORMATIVE_STANDARD_INTERFACE,
+                                    operation_templates=op_templates,
+                                    type=the_type)
+
+
+def get_standard_interface(service):
+    the_type = service.service_template.interface_types.get_descendant('test_interface_type')
+
+    ops = dict(
+        (op_name, models.Operation(
+            name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
+        for op_name in [NORMATIVE_CREATE, NORMATIVE_CONFIGURE, NORMATIVE_START,
+                        NORMATIVE_STOP, NORMATIVE_DELETE]
+    )
+    return {
+        NORMATIVE_STANDARD_INTERFACE:
+            models.Interface(name=NORMATIVE_STANDARD_INTERFACE, operations=ops, type=the_type)
+    }
+
+
+def get_configure_interfaces(service):
+    the_type = service.service_template.interface_types.get_descendant('test_interface_type')
+
+    operations = dict(
+        (op_name, models.Operation(
+            name=op_name, implementation='{0}.{1}'.format(__file__, mock_operation.__name__)))
+        for op_name in [NORMATIVE_PRE_CONFIGURE_SOURCE,
+                        NORMATIVE_POST_CONFIGURE_SOURCE,
+                        NORMATIVE_ADD_SOURCE,
+                        NORMATIVE_REMOVE_SOURCE,
+
+                        NORMATIVE_PRE_CONFIGURE_TARGET,
+                        NORMATIVE_POST_CONFIGURE_TARGET,
+                        NORMATIVE_ADD_TARGET,
+                        NORMATIVE_REMOVE_TARGET
+                       ]
+    )
+    interface = {
+        NORMATIVE_CONFIGURE_INTERFACE: models.Interface(
+            name=NORMATIVE_CONFIGURE_INTERFACE, operations=operations, type=the_type)
+    }
+
+    return interface
+
+
+@decorators.operation
+def mock_operation(*args, **kwargs):
+    pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/mock/topology.py
----------------------------------------------------------------------
diff --git a/tests/mock/topology.py b/tests/mock/topology.py
index 7ccc885..edf6b7d 100644
--- a/tests/mock/topology.py
+++ b/tests/mock/topology.py
@@ -22,7 +22,8 @@ def create_simple_topology_single_node(model_storage, create_operation):
     service_template = models.create_service_template()
     service = models.create_service(service_template)
 
-    node_template = models.create_dependency_node_template(service_template)
+    node_template = models.create_dependency_node_template(
+        models.DEPENDENCY_NODE_TEMPLATE_NAME, service_template)
     interface_template = models.create_interface_template(
         service_template,
         'Standard', 'create',
@@ -33,7 +34,7 @@ def create_simple_topology_single_node(model_storage, create_operation):
     )
     node_template.interface_templates[interface_template.name] = interface_template                 # pylint: disable=unsubscriptable-object
 
-    node = models.create_dependency_node(node_template, service)
+    node = models.create_node(models.DEPENDENCY_NODE_NAME, node_template, service)
     interface = models.create_interface(
         service,
         'Standard', 'create',
@@ -54,12 +55,15 @@ def create_simple_topology_two_nodes(model_storage):
 
     # Creating a simple service with node -> node as a graph
 
-    dependency_node_template = models.create_dependency_node_template(service_template)
-    dependent_node_template = models.create_dependent_node_template(service_template,
-                                                                    dependency_node_template)
+    dependency_node_template = models.create_dependency_node_template(
+        models.DEPENDENCY_NODE_TEMPLATE_NAME, service_template)
+    dependent_node_template = models.create_dependent_node_template(
+        models.DEPENDENT_NODE_TEMPLATE_NAME, service_template, dependency_node_template)
 
-    dependency_node = models.create_dependency_node(dependency_node_template, service)
-    dependent_node = models.create_dependent_node(dependent_node_template, service)
+    dependency_node = models.create_node(
+        models.DEPENDENCY_NODE_NAME, dependency_node_template, service)
+    dependent_node = models.create_node(
+        models.DEPENDENT_NODE_NAME, dependent_node_template, service)
 
     dependent_node.outbound_relationships.append(models.create_relationship(                        # pylint: disable=no-member
         source=dependent_node,
@@ -70,3 +74,26 @@ def create_simple_topology_two_nodes(model_storage):
     model_storage.service.put(service)
 
     return service.id
+
+
+def create_simple_topology_three_nodes(model_storage):
+    #################################################################################
+    # Creating a simple deployment with the following topology:
+    #               node1    <----|
+    #                             | <- node0
+    #               node2    <----|
+    # meaning node0 has two relationships: node1 and node2 (one each).
+
+    service_id = create_simple_topology_two_nodes(model_storage)
+    service = model_storage.service.get(service_id)
+    third_node_template = models.create_dependency_node_template(
+        'another_dependency_node_template', service.service_template)
+    third_node = models.create_node(
+        'another_dependency_node', third_node_template, service)
+    new_relationship = models.create_relationship(
+        source=model_storage.node.get_by_name(models.DEPENDENT_NODE_NAME),
+        target=third_node,
+    )
+    model_storage.relationship.put(new_relationship)
+
+    return service_id

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/modeling/test_models.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py
index c3b98c1..e76ac7b 100644
--- a/tests/modeling/test_models.py
+++ b/tests/modeling/test_models.py
@@ -89,21 +89,27 @@ def _service_update_storage():
 def _node_template_storage():
     storage = _service_storage()
     service_template = storage.service_template.list()[0]
-    dependency_node_template = mock.models.create_dependency_node_template(service_template)
-    mock.models.create_dependent_node_template(service_template, dependency_node_template)
+    dependency_node_template = mock.models.create_dependency_node_template(
+        mock.models.DEPENDENCY_NODE_TEMPLATE_NAME, service_template)
+    mock.models.create_dependent_node_template(
+        mock.models.DEPENDENCY_NODE_NAME, service_template, dependency_node_template)
     storage.service_template.update(service_template)
     return storage
 
 
-def _node_storage():
+def _nodes_storage():
     storage = _node_template_storage()
     service = storage.service.get_by_name(mock.models.SERVICE_NAME)
     dependency_node_template = storage.node_template.get_by_name(
         mock.models.DEPENDENCY_NODE_TEMPLATE_NAME)
-    dependent_node_template = storage.node_template.get_by_name(
-        mock.models.DEPENDENT_NODE_TEMPLATE_NAME)
-    mock.models.create_dependency_node(dependency_node_template, service)
-    mock.models.create_dependent_node(dependent_node_template, service)
+    mock.models.create_node(mock.models.DEPENDENCY_NODE_NAME, dependency_node_template, service)
+
+    dependent_node_template = \
+        mock.models.create_dependent_node_template(mock.models.DEPENDENT_NODE_TEMPLATE_NAME,
+                                                   service.service_template,
+                                                   dependency_node_template)
+
+    mock.models.create_node(mock.models.DEPENDENT_NODE_NAME, dependent_node_template, service)
     storage.service.update(service)
     return storage
 
@@ -148,8 +154,8 @@ def node_template_storage():
 
 
 @pytest.fixture
-def node_storage():
-    with sql_storage(_node_storage) as storage:
+def nodes_storage():
+    with sql_storage(_nodes_storage) as storage:
         yield storage
 
 
@@ -671,13 +677,13 @@ class TestRelationship(object):
             (True, 0, None),
         ]
     )
-    def test_relationship_model_creation(self, node_storage, is_valid, source_position,
+    def test_relationship_model_creation(self, nodes_storage, is_valid, source_position,
                                          target_position):
-        nodes = node_storage.node
+        nodes = nodes_storage.node
         source_node = nodes.get_by_name(mock.models.DEPENDENT_NODE_NAME)
         target_node = nodes.get_by_name(mock.models.DEPENDENCY_NODE_NAME)
         _test_model(is_valid=is_valid,
-                    storage=node_storage,
+                    storage=nodes_storage,
                     model_cls=Relationship,
                     model_kwargs=dict(
                         source_node=source_node,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/orchestrator/workflows/builtin/__init__.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/builtin/__init__.py b/tests/orchestrator/workflows/builtin/__init__.py
index 9f60e55..5ea761c 100644
--- a/tests/orchestrator/workflows/builtin/__init__.py
+++ b/tests/orchestrator/workflows/builtin/__init__.py
@@ -13,18 +13,65 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from tests import mock
+from aria.orchestrator.workflows.builtin import workflows
 
 
-def assert_node_install_operations(operations, with_relationships=False):
-    all_operations = mock.operations.OPERATIONS_INSTALL if with_relationships else \
-                     mock.operations.NODE_OPERATIONS_INSTALL
-    for i, operation in enumerate(operations):
-        assert operation.name.startswith(all_operations[i] + '.')
+def _assert_relationships(operations, expected_op_full_name, relationships=0):
+    """
 
+    :param operations: and iterable of operations
+    :param expected_op_full_name: Note that source/target doesn't really matter since they are
+    dropped
+    :param relationships: the number of relationships
+    :return:
+    """
+    expected_op_name = expected_op_full_name.rsplit('_', 1)[0]
+    for _ in xrange(relationships):
+        # Since the target and source operations start of the same way, we only need to retrieve the
+        # suffix once
+        operation = next(operations)
+        relationship_id_1 = operation.actor.id
+        edge1 = operation.runs_on
+        _assert_cfg_interface_op(operation, expected_op_name)
 
-def assert_node_uninstall_operations(operations, with_relationships=False):
-    all_operations = mock.operations.OPERATIONS_UNINSTALL if with_relationships else \
-                     mock.operations.NODE_OPERATIONS_UNINSTALL
-    for i, operation in enumerate(operations):
-        assert operation.name.startswith(all_operations[i] + '.')
+        operation = next(operations)
+        relationship_id_2 = operation.actor.id
+        edge2 = operation.runs_on
+        _assert_cfg_interface_op(operation, expected_op_name)
+
+        assert relationship_id_1 == relationship_id_2
+        print '++++' + edge1, edge2
+        assert edge1 != edge2
+
+
+def assert_node_install_operations(operations, relationships=0):
+    operations = iter(operations)
+
+    _assert_std_interface_op(next(operations), workflows.NORMATIVE_CREATE)
+    _assert_relationships(operations, workflows.NORMATIVE_PRE_CONFIGURE_SOURCE, relationships)
+    _assert_std_interface_op(next(operations), workflows.NORMATIVE_CONFIGURE)
+    _assert_relationships(operations, workflows.NORMATIVE_POST_CONFIGURE_SOURCE, relationships)
+    _assert_std_interface_op(next(operations), workflows.NORMATIVE_START)
+    _assert_relationships(operations, workflows.NORMATIVE_ADD_SOURCE, relationships)
+
+
+def assert_node_uninstall_operations(operations, relationships=0):
+    operations = iter(operations)
+
+    _assert_std_interface_op(next(operations), workflows.NORMATIVE_STOP)
+    _assert_relationships(operations, workflows.NORMATIVE_REMOVE_SOURCE, relationships)
+    _assert_std_interface_op(next(operations), workflows.NORMATIVE_DELETE)
+
+
+def _assert_cfg_interface_op(op, operation_name):
+    op = op.name.split('@', 1)[0].rsplit('_', 1)[0].lower()
+    predicted_name = \
+        '{0}:{1}'.format(workflows.NORMATIVE_CONFIGURE_INTERFACE, operation_name).lower()
+    assert op == predicted_name
+
+
+def _assert_std_interface_op(op, operation_name):
+    op = op.name.split('@', 1)[0].lower()
+    predicted_name = '{0}:{1}'\
+        .format(workflows.NORMATIVE_STANDARD_INTERFACE, operation_name).lower()
+    assert op == predicted_name

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/orchestrator/workflows/builtin/test_heal.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/builtin/test_heal.py b/tests/orchestrator/workflows/builtin/test_heal.py
index 92fa7ea..0a422bd 100644
--- a/tests/orchestrator/workflows/builtin/test_heal.py
+++ b/tests/orchestrator/workflows/builtin/test_heal.py
@@ -20,8 +20,7 @@ from aria.orchestrator.workflows.builtin.heal import heal
 
 from tests import mock, storage
 
-from . import (assert_node_install_operations,
-               assert_node_uninstall_operations)
+from . import (assert_node_install_operations, assert_node_uninstall_operations)
 
 
 @pytest.fixture
@@ -57,8 +56,8 @@ def test_heal_dependent_node(ctx):
         list(dependent_node_subgraph_install.topological_order(reverse=True))
     assert isinstance(dependency_node_subgraph_install, task.StubTask)
 
-    assert_node_uninstall_operations(dependent_node_uninstall_tasks, with_relationships=True)
-    assert_node_install_operations(dependent_node_install_tasks, with_relationships=True)
+    assert_node_uninstall_operations(dependent_node_uninstall_tasks, relationships=1)
+    assert_node_install_operations(dependent_node_install_tasks, relationships=1)
 
 
 @pytest.mark.skip(reason='heal is not implemented for now')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/orchestrator/workflows/builtin/test_install.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/builtin/test_install.py b/tests/orchestrator/workflows/builtin/test_install.py
index 1791719..1a4e1f9 100644
--- a/tests/orchestrator/workflows/builtin/test_install.py
+++ b/tests/orchestrator/workflows/builtin/test_install.py
@@ -25,7 +25,8 @@ from . import assert_node_install_operations
 
 @pytest.fixture
 def ctx(tmpdir):
-    context = mock.context.simple(str(tmpdir))
+    context = mock.context.simple(str(tmpdir),
+                                  topology=mock.topology.create_simple_topology_three_nodes)
     yield context
     storage.release_sqlite_storage(context.model)
 
@@ -34,10 +35,12 @@ def test_install(ctx):
 
     install_tasks = list(task.WorkflowTask(install, ctx=ctx).topological_order(True))
 
-    assert len(install_tasks) == 2
-    dependency_node_subgraph, dependent_node_subgraph = install_tasks
+    assert len(install_tasks) == 3
+    dependency_node_subgraph1, dependency_node_subgraph2, dependent_node_subgraph = install_tasks
     dependent_node_tasks = list(dependent_node_subgraph.topological_order(reverse=True))
-    dependency_node_tasks = list(dependency_node_subgraph.topological_order(reverse=True))
+    dependency_node1_tasks = list(dependency_node_subgraph1.topological_order(reverse=True))
+    dependency_node2_tasks = list(dependency_node_subgraph2.topological_order(reverse=True))
 
-    assert_node_install_operations(dependency_node_tasks)
-    assert_node_install_operations(dependent_node_tasks, with_relationships=True)
+    assert_node_install_operations(dependency_node1_tasks)
+    assert_node_install_operations(dependency_node2_tasks)
+    assert_node_install_operations(dependent_node_tasks, relationships=2)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/6bd69d7c/tests/orchestrator/workflows/builtin/test_uninstall.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/builtin/test_uninstall.py b/tests/orchestrator/workflows/builtin/test_uninstall.py
index 791291f..aa04c38 100644
--- a/tests/orchestrator/workflows/builtin/test_uninstall.py
+++ b/tests/orchestrator/workflows/builtin/test_uninstall.py
@@ -26,7 +26,8 @@ from . import assert_node_uninstall_operations
 
 @pytest.fixture
 def ctx(tmpdir):
-    context = mock.context.simple(str(tmpdir))
+    context = mock.context.simple(str(tmpdir),
+                                  topology=mock.topology.create_simple_topology_three_nodes)
     yield context
     storage.release_sqlite_storage(context.model)
 
@@ -35,10 +36,12 @@ def test_uninstall(ctx):
 
     uninstall_tasks = list(task.WorkflowTask(uninstall, ctx=ctx).topological_order(True))
 
-    assert len(uninstall_tasks) == 2
-    dependent_node_subgraph, dependency_node_subgraph = uninstall_tasks
+    assert len(uninstall_tasks) == 3
+    dependent_node_subgraph, dependency_node_subgraph1, dependency_node_subgraph2 = uninstall_tasks
     dependent_node_tasks = list(dependent_node_subgraph.topological_order(reverse=True))
-    dependency_node_tasks = list(dependency_node_subgraph.topological_order(reverse=True))
+    dependency_node1_tasks = list(dependency_node_subgraph1.topological_order(reverse=True))
+    dependency_node2_tasks = list(dependency_node_subgraph2.topological_order(reverse=True))
 
-    assert_node_uninstall_operations(operations=dependency_node_tasks)
-    assert_node_uninstall_operations(operations=dependent_node_tasks, with_relationships=True)
+    assert_node_uninstall_operations(operations=dependency_node1_tasks)
+    assert_node_uninstall_operations(operations=dependency_node2_tasks)
+    assert_node_uninstall_operations(operations=dependent_node_tasks, relationships=2)