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/28 08:18:54 UTC

incubator-ariatosca git commit: ARIA-120-Builtin-workflows-relationship-operations-execution-order

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/master 0e107933e -> 07cbfcdab


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/07cbfcda
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/07cbfcda
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/07cbfcda

Branch: refs/heads/master
Commit: 07cbfcdabc207452acda33fa9f1ababf97e5d260
Parents: 0e10793
Author: max-orlov <ma...@gigaspaces.com>
Authored: Mon Mar 13 16:35:10 2017 +0200
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Tue Mar 28 11:18:19 2017 +0300

----------------------------------------------------------------------
 aria/modeling/relationship.py                   |   2 +-
 aria/orchestrator/workflows/api/task.py         |  29 +++--
 aria/orchestrator/workflows/builtin/utils.py    |  60 +++++++--
 .../orchestrator/workflows/builtin/workflows.py | 102 +++++----------
 .../workflows/core/events_handler.py            |   7 +-
 aria/orchestrator/workflows/core/task.py        |   2 +
 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  |  65 ++++++++--
 .../orchestrator/workflows/builtin/test_heal.py |   7 +-
 .../workflows/builtin/test_install.py           |  15 ++-
 .../workflows/builtin/test_uninstall.py         |  15 ++-
 .../workflows/executor/test_executor.py         |   2 +
 .../workflows/executor/test_process_executor.py |   2 +
 16 files changed, 323 insertions(+), 186 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/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/07cbfcda/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index 009b81c..f49ec2e 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -90,6 +90,8 @@ class OperationTask(BaseTask):
         self.ignore_failure = (self.workflow_context._task_ignore_failure
                                if ignore_failure is None else ignore_failure)
         self.runs_on = runs_on
+        self.interface_name = interface_name
+        self.operation_name = operation_name
 
         # Wrap inputs
         inputs = copy.deepcopy(inputs) if inputs else {}
@@ -101,11 +103,11 @@ class OperationTask(BaseTask):
         # model, because they are different from the operation inputs. If we do this, then the two
         # kinds of inputs should *not* be merged here.
 
-        operation = self._get_operation(interface_name, operation_name)
+        operation = self._get_operation()
         if operation is None:
             raise exceptions.OperationNotFoundException(
                 'Could not find operation "{0}" on interface "{1}" for {2} "{3}"'
-                .format(operation_name, interface_name, actor_type, actor.name))
+                .format(self.operation_name, self.interface_name, actor_type, actor.name))
 
         self.plugin = None
         if operation.plugin_specification:
@@ -113,15 +115,26 @@ class OperationTask(BaseTask):
             if self.plugin is None:
                 raise exceptions.PluginNotFoundException(
                     'Could not find plugin of operation "{0}" on interface "{1}" for {2} "{3}"'
-                    .format(operation_name, interface_name, actor_type, actor.name))
+                    .format(self.operation_name, self.interface_name, actor_type, actor.name))
 
         self.implementation = operation.implementation
         self.inputs = OperationTask._merge_inputs(operation.inputs, inputs)
 
         self.name = OperationTask.NAME_FORMAT.format(type=actor_type,
                                                      name=actor.name,
-                                                     interface=interface_name,
-                                                     operation=operation_name)
+                                                     interface=self.interface_name,
+                                                     operation=self.operation_name)
+
+    def __repr__(self):
+        return self.name
+
+    def _get_operation(self):
+        interface = self.actor.interfaces.get(self.interface_name)
+        if interface:
+            return interface.operations.get(self.operation_name)
+        return None
+
+
 
     @classmethod
     def for_node(cls,
@@ -198,12 +211,6 @@ class OperationTask(BaseTask):
             ignore_failure=ignore_failure,
             inputs=inputs)
 
-    def _get_operation(self, interface_name, operation_name):
-        interface = self.actor.interfaces.get(interface_name)
-        if interface is not None:
-            return interface.operations.get(operation_name)
-        return None
-
     @staticmethod
     def _find_plugin(plugin_specification):
         workflow_context = context.workflow.current.get()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/aria/orchestrator/workflows/builtin/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/utils.py b/aria/orchestrator/workflows/builtin/utils.py
index 8efa889..d79318f 100644
--- a/aria/orchestrator/workflows/builtin/utils.py
+++ b/aria/orchestrator/workflows/builtin/utils.py
@@ -12,12 +12,11 @@
 # 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 ..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 +30,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 basestring interface_name: the name of the interface.
+    :param source_operation_name:
+    :param target_operation_name:
+    :param NodeInstance node: the source_node
+    :return:
     """
-
-    sequence = []
+    sub_tasks = []
     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))
+            relationship_operations = relationship_tasks(
+                relationship,
+                interface_name,
+                source_operation_name=source_operation_name,
+                target_operation_name=target_operation_name)
+            sub_tasks.append(relationship_operations)
         except exceptions.OperationNotFoundException:
             # We will skip relationships which do not have the operation
             pass
-    return sequence
+    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:
+        operations.append(
+            OperationTask.for_relationship(relationship=relationship,
+                                           interface_name=interface_name,
+                                           operation_name=source_operation_name,
+                                           runs_on='source')
+        )
+    if 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):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/aria/orchestrator/workflows/builtin/workflows.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/workflows.py b/aria/orchestrator/workflows/builtin/workflows.py
index 6065343..60f14ed 100644
--- a/aria/orchestrator/workflows/builtin/workflows.py
+++ b/aria/orchestrator/workflows/builtin/workflows.py
@@ -18,19 +18,21 @@ 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'
 NORMATIVE_CONFIGURE_INTERFACE = 'Configure' # 'tosca.interfaces.relationship.Configure'
 
 NORMATIVE_CREATE = 'create'
+NORMATIVE_CONFIGURE = 'configure'
 NORMATIVE_START = 'start'
 NORMATIVE_STOP = 'stop'
 NORMATIVE_DELETE = 'delete'
 
-NORMATIVE_CONFIGURE = 'configure'
 NORMATIVE_PRE_CONFIGURE_SOURCE = 'pre_configure_source'
 NORMATIVE_PRE_CONFIGURE_TARGET = 'pre_configure_target'
 NORMATIVE_POST_CONFIGURE_SOURCE = 'post_configure_source'
@@ -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/07cbfcda/aria/orchestrator/workflows/core/events_handler.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/events_handler.py b/aria/orchestrator/workflows/core/events_handler.py
index 4ac4b64..8534aae 100644
--- a/aria/orchestrator/workflows/core/events_handler.py
+++ b/aria/orchestrator/workflows/core/events_handler.py
@@ -20,7 +20,6 @@ Path: aria.events.storage_event_handler
 Implementation of storage handlers for workflow and operation events.
 """
 
-import re
 from datetime import (
     datetime,
     timedelta,
@@ -126,11 +125,9 @@ def _workflow_cancelling(workflow_context, *args, **kwargs):
 
 
 def _update_node_state_if_necessary(task, is_transitional=False):
-    match = re.search(r'^(?:tosca.interfaces.node.lifecycle.Standard|Standard):(\S+)@node',
-                      task.name)
-    if match:
+    if task.interface_name in ['tosca.interfaces.node.lifecycle.Standard', 'Standard']:
         node = task.runs_on
-        state = node.determine_state(op_name=match.group(1), is_transitional=is_transitional)
+        state = node.determine_state(op_name=task.operation_name, is_transitional=is_transitional)
         if state:
             node.state = state
             task.context.model.node.update(node)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/aria/orchestrator/workflows/core/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/task.py b/aria/orchestrator/workflows/core/task.py
index f23312d..1e13588 100644
--- a/aria/orchestrator/workflows/core/task.py
+++ b/aria/orchestrator/workflows/core/task.py
@@ -106,6 +106,8 @@ class OperationTask(BaseTask):
     def __init__(self, api_task, *args, **kwargs):
         super(OperationTask, self).__init__(id=api_task.id, **kwargs)
         self._workflow_context = api_task._workflow_context
+        self.interface_name = api_task.interface_name
+        self.operation_name = api_task.operation_name
         model_storage = api_task._workflow_context.model
         plugin = api_task.plugin
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/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/07cbfcda/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 9ae2815..457e7cb 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=models.Node.INITIAL,
         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=models.Node.INITIAL,
-        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/07cbfcda/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/07cbfcda/tests/modeling/test_models.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py
index 84200d5..35ae09f 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/07cbfcda/tests/orchestrator/workflows/builtin/__init__.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/builtin/__init__.py b/tests/orchestrator/workflows/builtin/__init__.py
index 9f60e55..8a67247 100644
--- a/tests/orchestrator/workflows/builtin/__init__.py
+++ b/tests/orchestrator/workflows/builtin/__init__.py
@@ -13,18 +13,61 @@
 # 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
+        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):
+    # We need to remove the source/target
+    assert op.operation_name.rsplit('_', 1)[0] == operation_name
+    assert op.interface_name == workflows.NORMATIVE_CONFIGURE_INTERFACE
+
+
+def _assert_std_interface_op(op, operation_name):
+    assert op.operation_name == operation_name
+    assert op.interface_name == workflows.NORMATIVE_STANDARD_INTERFACE

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/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/07cbfcda/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/07cbfcda/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)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/tests/orchestrator/workflows/executor/test_executor.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_executor.py b/tests/orchestrator/workflows/executor/test_executor.py
index 0a2280d..9dde1ce 100644
--- a/tests/orchestrator/workflows/executor/test_executor.py
+++ b/tests/orchestrator/workflows/executor/test_executor.py
@@ -118,6 +118,8 @@ class MockTask(object):
         self.max_attempts = 1
         self.plugin_fk = None
         self.ignore_failure = False
+        self.interface_name = 'interface_name'
+        self.operation_name = 'operation_name'
 
         for state in models.Task.STATES:
             setattr(self, state.upper(), state)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/07cbfcda/tests/orchestrator/workflows/executor/test_process_executor.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor.py b/tests/orchestrator/workflows/executor/test_process_executor.py
index 3cd1c47..0edd0a5 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor.py
@@ -140,6 +140,8 @@ class MockTask(object):
         self.plugin_fk = plugin.id
         self.plugin = plugin
         self.ignore_failure = False
+        self.interface_name = 'interface_name'
+        self.operation_name = 'operation_name'
 
         for state in aria_models.Task.STATES:
             setattr(self, state.upper(), state)