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/02/19 17:03:19 UTC

[1/7] incubator-ariatosca git commit: ARIA-88 Add TOSCA use-case examples [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-106-Create-sqla-logging-handler d483195bd -> a9bd63da2 (forced update)


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/simple_v1_0/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/functions.py b/extensions/aria_extension_tosca/simple_v1_0/functions.py
index d17a960..e385817 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/functions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/functions.py
@@ -171,15 +171,20 @@ class GetProperty(Function):
     def _evaluate(self, context, container):
         modelable_entities = get_modelable_entities(context, container, self.locator,
                                                     self.modelable_entity_name)
-
         req_or_cap_name = self.nested_property_name_or_index[0]
 
         for modelable_entity in modelable_entities:
+            properties = None
+            
             if hasattr(modelable_entity, 'requirement_templates') \
                 and modelable_entity.requirement_templates \
-                and (req_or_cap_name in modelable_entity.requirement_templates):
-                # First argument refers to a requirement
-                properties = modelable_entity.requirement_templates[req_or_cap_name].properties
+                and (req_or_cap_name in [v.name for v in modelable_entity.requirement_templates]):
+                for requirement_template in modelable_entity.requirement_templates:
+                    if requirement_template.name == req_or_cap_name:
+                        # First argument refers to a requirement
+                        # TODO: should follow to matched capability in other node...
+                        raise CannotEvaluateFunctionException()
+                        break
                 nested_property_name_or_index = self.nested_property_name_or_index[1:]
             elif hasattr(modelable_entity, 'capability_templates') \
                 and modelable_entity.capability_templates \
@@ -501,8 +506,7 @@ def get_host(context, container): # pylint: disable=unused-argument
     ends.
     """
 
-    print container.relationships
-    exit()
+    return []
 
 def get_source(context, container): # pylint: disable=unused-argument
     """
@@ -510,6 +514,8 @@ def get_source(context, container): # pylint: disable=unused-argument
     source end of the relationship that contains the referencing function.
     """
 
+    return []
+
 def get_target(context, container): # pylint: disable=unused-argument
     """
     A TOSCA orchestrator will interpret this keyword as the Node Template instance that is at the

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/simple_v1_0/misc.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/misc.py b/extensions/aria_extension_tosca/simple_v1_0/misc.py
index 4453c7a..42fc1ad 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/misc.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py
@@ -85,6 +85,7 @@ class MetaData(ExtensiblePresentation):
         :rtype: dict
         """
 
+@short_form_field('url')
 @has_fields
 @dsl_specification('3.5.5', 'tosca-simple-1.0')
 class Repository(ExtensiblePresentation):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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 811da19..f340954 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -22,6 +22,7 @@ from aria.parser.modeling import (Type, RelationshipType, PolicyType, ServiceMod
                                   ArtifactTemplate, Metadata, Parameter)
 
 from ..data_types import coerce_value
+from platform import node
 
 def create_service_model(context): # pylint: disable=too-many-locals,too-many-branches
     model = ServiceModel()
@@ -106,7 +107,8 @@ def create_service_model(context): # pylint: disable=too-many-locals,too-many-br
     return model
 
 def create_node_template(context, node_template):
-    model = NodeTemplate(name=node_template._name, type_name=node_template.type)
+    node_type = node_template._get_type(context)
+    model = NodeTemplate(name=node_template._name, type_name=node_type._name)
 
     if node_template.description:
         model.description = node_template.description.value
@@ -137,12 +139,11 @@ def create_node_template(context, node_template):
     return model
 
 def create_interface_template(context, interface):
-    the_type = interface._get_type(context)
+    interface_type = interface._get_type(context)
+    model = InterfaceTemplate(name=interface._name, type_name=interface_type._name)
 
-    model = InterfaceTemplate(name=interface._name, type_name=the_type._name)
-
-    if the_type.description:
-        model.description = the_type.description.value
+    if interface_type.description:
+        model.description = interface_type.description.value
 
     inputs = interface.inputs
     if inputs:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
index 97e30ee..2a68da2 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/requirements.py
@@ -171,7 +171,8 @@ def convert_requirement_from_definition_to_assignment(context, requirement_defin
         # Make sure the type is derived
         if not definition_relationship_type._is_descendant(context, relationship_type):
             context.validation.report(
-                'assigned relationship type "%s" is not a descendant of declared relationship type "%s"'
+                'assigned relationship type "%s" is not a descendant of declared relationship type'
+                ' "%s"' \
                 % (relationship_type._name, definition_relationship_type._name),
                 locator=container._locator, level=Issue.BETWEEN_TYPES)
 
@@ -189,11 +190,11 @@ def convert_requirement_from_definition_to_assignment(context, requirement_defin
 
         if relationship_template is not None:
             # Property values from template
-            raw['properties'] = relationship_template._get_property_values(context)
+            raw['relationship']['properties'] = relationship_template._get_property_values(context)
         else:
             if relationship_property_definitions:
                 # Convert property definitions to values
-                raw['properties'] = \
+                raw['relationship']['properties'] = \
                     convert_property_definitions_to_values(context,
                                                            relationship_property_definitions)
 
@@ -210,9 +211,9 @@ def convert_requirement_from_definition_to_assignment(context, requirement_defin
         if relationship_definition:
             # Merge extra interface definitions
             # InterfaceDefinition:
-            relationship_interface_definitions = relationship_definition.interfaces
+            definition_interface_definitions = relationship_definition.interfaces
             merge_interface_definitions(context, relationship_interface_definitions,
-                                        relationship_interface_definitions, requirement_definition,
+                                        definition_interface_definitions, requirement_definition,
                                         container)
 
         if relationship_template is not None:
@@ -272,15 +273,10 @@ def merge_requirement_assignment(context, relationship_property_definitions,
         requirement._raw['node_filter'] = deepcopy_with_locators(our_node_filter._raw)
 
     our_relationship = our_requirement.relationship # RelationshipAssignment
-    if our_relationship is not None:
+    if (our_relationship is not None) and (our_relationship.type is None):
         # Make sure we have a dict
         if 'relationship' not in requirement._raw:
             requirement._raw['relationship'] = OrderedDict()
-        elif not isinstance(requirement._raw['relationship'], dict):
-            # Convert existing short form to long form
-            the_type = requirement._raw['relationship']
-            requirement._raw['relationship'] = OrderedDict()
-            requirement._raw['relationship']['type'] = deepcopy_with_locators(the_type)
 
         merge_requirement_assignment_relationship(context, our_relationship,
                                                   relationship_property_definitions,
@@ -289,11 +285,6 @@ def merge_requirement_assignment(context, relationship_property_definitions,
 
 def merge_requirement_assignment_relationship(context, presentation, property_definitions,
                                               interface_definitions, requirement, our_relationship):
-    the_type = our_relationship.type
-    if the_type is not None:
-        # Could be a type or a template:
-        requirement._raw['relationship']['type'] = deepcopy_with_locators(the_type)
-
     our_relationship_properties = our_relationship._raw.get('properties')
     if our_relationship_properties:
         # Make sure we have a dict
@@ -310,7 +301,7 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
                 context.validation.report(
                     'relationship property "%s" not declared at definition of requirement "%s"'
                     ' in "%s"'
-                    % (property_name, presentation._fullname,
+                    % (property_name, requirement._fullname,
                        presentation._container._container._fullname),
                     locator=our_relationship._get_child_locator('properties', property_name),
                     level=Issue.BETWEEN_TYPES)
@@ -333,9 +324,9 @@ def merge_requirement_assignment_relationship(context, presentation, property_de
                                 interface_definition, interface_name)
             else:
                 context.validation.report(
-                    'interface definition "%s" not declared at definition of requirement "%s"'
+                    'relationship interface "%s" not declared at definition of requirement "%s"'
                     ' in "%s"'
-                    % (interface_name, presentation._fullname,
+                    % (interface_name, requirement._fullname,
                        presentation._container._container._fullname),
                     locator=our_relationship._locator, level=Issue.BETWEEN_TYPES)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
index f1b0a20..6ff4384 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/field_validators.py
@@ -332,8 +332,8 @@ def node_template_or_type_validator(field, presentation, context):
         node_templates = \
             context.presentation.get('service_template', 'topology_template', 'node_templates') \
             or {}
-        node_types = context.presentation.get('service_template', 'node_types') or {}
-        if (value not in node_templates) and (value not in node_types):
+        if (value not in node_templates) and \
+            (get_type_by_full_or_shorthand_name(context, value, 'node_types') is None):
             report_issue_for_unknown_type(context, presentation, 'node template or node type',
                                           field.name)
 
@@ -358,8 +358,7 @@ def capability_definition_or_type_validator(field, presentation, context):
             if value in capabilities:
                 return
 
-        capability_types = context.presentation.get('service_template', 'capability_types')
-        if (capability_types is not None) and (value in capability_types):
+        if get_type_by_full_or_shorthand_name(context, value, 'capability_types') is not None:
             if node is not None:
                 context.validation.report(
                     '"%s" refers to a capability type even though "node" has a value in "%s"'
@@ -419,9 +418,8 @@ def relationship_template_or_type_validator(field, presentation, context):
             context.presentation.get('service_template', 'topology_template',
                                      'relationship_templates') \
             or {}
-        relationship_types = \
-            context.presentation.get('service_template', 'relationship_types') or {}
-        if (value not in relationship_templates) and (value not in relationship_types):
+        if (value not in relationship_templates) and \
+            (get_type_by_full_or_shorthand_name(context, value, 'relationship_types') is None):
             report_issue_for_unknown_type(context, presentation,
                                           'relationship template or relationship type', field.name)
 
@@ -442,9 +440,9 @@ def list_node_type_or_group_type_validator(field, presentation, context):
     values = getattr(presentation, field.name)
     if values is not None:
         for value in values:
-            node_types = context.presentation.get('service_template', 'node_types') or {}
-            group_types = context.presentation.get('service_template', 'group_types') or {}
-            if (value not in node_types) and (value not in group_types):
+            if \
+                (get_type_by_full_or_shorthand_name(context, value, 'node_types') is None) and \
+                (get_type_by_full_or_shorthand_name(context, value, 'group_types') is None):
                 report_issue_for_unknown_type(context, presentation, 'node type or group type',
                                               field.name, value)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/end2end/test_parser.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_parser.py b/tests/end2end/test_parser.py
deleted file mode 100644
index 7c243ab..0000000
--- a/tests/end2end/test_parser.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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.
-
-from tests.parser.service_templates import consume_node_cellar
-
-
-def test_validation():
-    consume_node_cellar('validate')
-
-
-def test_validation_no_cache():
-    consume_node_cellar('validate', False)
-
-
-def test_presentation():
-    consume_node_cellar('presentation')
-
-
-def test_model():
-    consume_node_cellar('model')
-
-
-def test_types():
-    consume_node_cellar('types')
-
-
-def test_instance():
-    consume_node_cellar('instance')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/end2end/test_tosca_simple_v1_0.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_tosca_simple_v1_0.py b/tests/end2end/test_tosca_simple_v1_0.py
new file mode 100644
index 0000000..f2a41ce
--- /dev/null
+++ b/tests/end2end/test_tosca_simple_v1_0.py
@@ -0,0 +1,112 @@
+# 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.
+
+from tests.parser.service_templates import (consume_use_case, consume_node_cellar)
+
+
+# Use Cases
+
+def test_use_case_compute_1():
+    consume_use_case('compute-1', 'instance')
+
+
+def test_use_case_software_component_1():
+    consume_use_case('software-component-1', 'instance')
+
+
+def test_use_case_block_storage_1():
+    consume_use_case('block-storage-1', 'instance')
+
+
+def test_use_case_block_storage_2():
+    consume_use_case('block-storage-2', 'instance')
+
+
+def test_use_case_block_storage_3():
+    consume_use_case('block-storage-3', 'instance')
+
+
+def test_use_case_block_storage_4():
+    consume_use_case('block-storage-4', 'instance')
+
+
+def test_use_case_block_storage_5():
+    consume_use_case('block-storage-5', 'instance')
+
+
+def test_use_case_block_storage_6():
+    consume_use_case('block-storage-6', 'instance')
+
+
+def test_use_case_object_storage_1():
+    consume_use_case('object-storage-1', 'instance')
+
+
+def test_use_case_network_1():
+    consume_use_case('network-1', 'instance')
+
+
+def test_use_case_network_2():
+    consume_use_case('network-2', 'instance')
+
+
+def test_use_case_network_3():
+    consume_use_case('network-3', 'instance')
+
+
+def test_use_case_network_4():
+    consume_use_case('network-4', 'instance')
+
+
+def test_use_case_webserver_dbms_1():
+    consume_use_case('webserver-dbms-1', 'model')
+
+
+def test_use_case_webserver_dbms_2():
+    consume_use_case('webserver-dbms-2', 'instance')
+
+
+def test_use_case_multi_tier_1():
+    consume_use_case('multi-tier-1', 'instance')
+
+
+def test_use_case_container_1():
+    consume_use_case('container-1', 'model')
+
+
+# NodeCellar
+
+def test_node_cellar_validation():
+    consume_node_cellar('validate')
+
+
+def test_node_cellar_validation_no_cache():
+    consume_node_cellar('validate', False)
+
+
+def test_node_cellar_presentation():
+    consume_node_cellar('presentation')
+
+
+def test_node_cellar_model():
+    consume_node_cellar('model')
+
+
+def test_node_cellar_types():
+    consume_node_cellar('types')
+
+
+def test_node_cellar_instance():
+    consume_node_cellar('instance')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/parser/service_templates.py
----------------------------------------------------------------------
diff --git a/tests/parser/service_templates.py b/tests/parser/service_templates.py
index 8c361e6..a07fba8 100644
--- a/tests/parser/service_templates.py
+++ b/tests/parser/service_templates.py
@@ -15,14 +15,28 @@
 
 from aria.utils.caching import cachedmethod
 
-from .utils import (get_uri, create_context, create_consumer)
+from .utils import (get_example_uri, get_test_uri, create_context, create_consumer)
+
+
+def consume_use_case(use_case_name, consumer_class_name='instance', cache=True):
+    cachedmethod.ENABLED = cache
+    uri = get_example_uri('tosca-simple-1.0', 'use-cases', use_case_name,
+                          '{0}.yaml'.format(use_case_name))
+    context = create_context(uri)
+    #context.args.append('--inputs=' + get_example_uri('node-cellar', 'inputs.yaml'))
+    consumer, dumper = create_consumer(context, consumer_class_name)
+    consumer.consume()
+    context.validation.dump_issues()
+    assert not context.validation.has_issues
+    return context, dumper
 
 
 def consume_node_cellar(consumer_class_name='instance', cache=True):
     cachedmethod.ENABLED = cache
-    uri = get_uri('node-cellar', 'node-cellar.yaml')
+    uri = get_test_uri('tosca-simple-1.0', 'node-cellar', 'node-cellar.yaml')
     context = create_context(uri)
-    context.args.append('--inputs=' + get_uri('node-cellar', 'inputs.yaml'))
+    context.args.append('--inputs=' + get_test_uri('tosca-simple-1.0', 'node-cellar',
+                                                   'inputs.yaml'))
     consumer, dumper = create_consumer(context, consumer_class_name)
     consumer.consume()
     context.validation.dump_issues()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/parser/utils.py
----------------------------------------------------------------------
diff --git a/tests/parser/utils.py b/tests/parser/utils.py
index e55e6e5..994aac6 100644
--- a/tests/parser/utils.py
+++ b/tests/parser/utils.py
@@ -28,13 +28,18 @@ from aria.parser.consumption import (
 )
 from aria.utils.imports import import_fullname
 
+from tests import ROOT_DIR
 from tests.resources import DIR
 
 
-SERVICE_TEMPLATES_DIR = os.path.join(DIR, 'service_templates')
+SERVICE_TEMPLATES_DIR = os.path.join(DIR, 'service-templates')
 
 
-def get_uri(*args):
+def get_example_uri(*args):
+    return os.path.join(ROOT_DIR, 'examples', *args)
+
+
+def get_test_uri(*args):
     return os.path.join(SERVICE_TEMPLATES_DIR, *args)
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service-templates/tosca-simple-1.0/node-cellar/inputs.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/inputs.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/inputs.yaml
new file mode 100644
index 0000000..37ab9ea
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/inputs.yaml
@@ -0,0 +1,3 @@
+openstack_credential:
+    user: username
+    token: password

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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
new file mode 100644
index 0000000..3afcf5f
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -0,0 +1,299 @@
+#
+# 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.
+#
+
+# 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
+#tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  Node Cellar TOSCA blueprint.
+  Here is some Unicode: \u4e2d\u570b.
+
+metadata:
+  template_name: node-cellar
+  template_author: ARIA
+  template_version: '1.0.0'
+  aria_version: '0.0'
+
+imports:
+  - types/openstack.yaml
+  - types/nodejs.yaml
+  - types/mongodb.yaml
+  - types/nginx.yaml
+  - types/aria.yaml
+
+dsl_definitions:
+
+  default_openstack_credential: &DEFAULT_OPENSTACK_CREDENTIAL
+    user: openstackadmin
+    token: { concat: [ openstack, 123 ] }
+
+repositories:
+
+  node_cellar:
+    description: >-
+      The repository for the Node Cellar application and its dependencies.
+    url: https://github.com/ccoenraets/nodecellar/archive/
+    credential:
+      user: guest
+      token: ''
+
+interface_types:
+
+  Maintenance:
+    derived_from: tosca.interfaces.Root
+    enable: {}
+    disable: {}
+
+node_types:
+
+  NodeMongoApplication:
+    derived_from: nodejs.Application
+    interfaces:
+      Maintenance:
+        type: Maintenance
+    requirements:
+      - database:
+          capability: tosca.capabilities.Endpoint.Database
+          node: mongodb.Database
+
+topology_template:
+
+  inputs:
+    openstack_credential:
+      type: openstack.Credential
+      value: *DEFAULT_OPENSTACK_CREDENTIAL
+
+  node_templates:
+  
+    # Application
+
+    node_cellar:
+      description: >-
+        Node Cellar Node.js web application.
+      type: NodeMongoApplication
+      artifacts:
+        node_cellar:
+          description: >-
+            The Node Cellar application package.
+          type: os.Archive
+          file: master.zip
+          repository: node_cellar
+          deploy_path: /opt/nodejs/applications/node-cellar
+          properties:
+            unpack_credential:
+              user: gigaspaces
+              token: { get_property: [ SELF, app_endpoint, protocol ] }
+              #token: { get_property: [ HOST, flavor_name ] }
+      interfaces:
+        Maintenance:
+          enable: juju > charm.maintenance_on
+          disable: juju > charm.maintenance_off
+      requirements:
+        - database: node_cellar_database
+      capabilities:
+        app_endpoint:
+          properties:
+            protocol: udp
+            url_path: /nodecellar
+    
+    node_cellar_database:
+      description: >-
+        Node Cellar MongoDB database.
+      type: mongodb.Database
+      properties:
+        name: node_cellar
+      artifacts:
+        initial:
+          description: >-
+            The Node Cellar initial database.
+          type: mongodb.DatabaseDump
+          file: node-cellar.json
+          repository: node_cellar
+
+    # Server software
+    
+    nodejs:
+      description: >-
+        Node.js instance.
+      type: nodejs.Server
+      requirements:
+        - host: application_host
+      node_filter: # cannot be validated
+        properties:
+          #- flavor_name: { valid_values: [ {concat:[m1,.,small]} ] } # won't work because not validated :/
+          - flavor_name: { valid_values: [ m1.small ] }
+        capabilities:
+          - scalable:
+              properties:
+                - max_instances: { greater_or_equal: 8 }
+
+    mongodb:
+      description: >-
+        MongoDB instance.
+      type: mongodb.Server
+      requirements:
+        - host:
+            node: openstack.Instance
+            node_filter:
+              properties:
+                - flavor_name: { valid_values: [ m1.medium, { concat: [ { concat: [ m1, . ] }, large ] } ] }
+                #- flavor_name: { valid_values: [ m1.medium, m1.large ] }
+              capabilities:
+                - scalable:
+                    properties:
+                      - max_instances: { greater_or_equal: 8 }
+    
+    loadbalancer:
+      type: nginx.LoadBalancer
+      properties:
+        algorithm: round-robin      
+      requirements:
+        - host: loadbalancer_host
+    
+    # Hosts
+
+    loadbalancer_host:
+      description: >-
+        Host for the loadbalancer.
+      type: openstack.Instance
+      properties:
+        flavor_name: m1.small
+        os_users: # map of os.UserInfo
+          root:
+            password: admin123
+      interfaces:
+        Standard:
+          inputs:
+            openstack_credential: { get_input: openstack_credential }
+          configure: juju > charm.loadbalancer
+
+    application_host:
+      copy: loadbalancer_host
+      description: >-
+        Host for applications.
+      properties:
+        flavor_name: m1.small
+        os_users: # map of os.UserInfo
+          nodejs:
+            password: nodejs123
+            groups:
+              - www-data
+      capabilities:
+        scalable:
+          properties:
+            max_instances: 10
+
+    data_host:
+      copy: loadbalancer_host
+      description: >-
+        Host for data.
+      properties:
+        flavor_name: m1.large
+        flavor_id: 5d62e82c-924e-4fa9-b1e4-c133867596f7
+        os_users: # map of os.UserInfo
+          mongodb:
+            password: mongo123
+      requirements:
+        - local_storage:
+            node: data_volume
+            relationship:
+              properties:
+                location: /mnt/volume
+      capabilities:
+        scalable:
+          properties:
+            max_instances: 10
+
+    data_volume:
+      type: openstack.Volume
+      properties:
+        size: 10 GB
+      interfaces:
+        Standard:
+          inputs:
+            openstack_credential: { get_input: openstack_credential }
+
+  groups:
+  
+    node_cellar_group:
+      type: openstack.Secured
+      members:
+        - loadbalancer
+        - application_host
+        - data_host
+      interfaces:
+        Standard:
+          inputs:
+            openstack_credential: { get_input: openstack_credential }
+
+  policies:
+  
+    scaling:
+      type: openstack.Scaling
+      properties:
+        bandwidth_threshold: 2 GB
+      targets: # node templates or groups
+        - node_cellar_group
+    
+    juju:
+      description: >-
+        Juju plugin executes charms.
+      type: aria.Plugin
+      properties:
+        executor: host_agent
+        install: false
+    
+    maintenance_on:
+      type: MaintenanceWorkflow
+      properties:
+        enabled: true
+
+    maintenance_off:
+      type: MaintenanceWorkflow
+      properties:
+        enabled: false
+
+  substitution_mappings:
+
+    node_type: tosca.nodes.WebApplication
+    requirements:
+      host: [ node_cellar, host ] # doesn't really make sense; just for testing
+    capabilities:
+      app_endpoint: [ loadbalancer, client ]
+
+policy_types:
+
+  MaintenanceWorkflow:
+    description: >-
+      Workflow to put all nodes in/out of maintenance mode. For web servers, this will show a "this
+      site is under maintenance and we'll be back soon" web page. Database nodes will then close all
+      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
+      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/787d7e7e/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
new file mode 100644
index 0000000..2ddb238
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/aria.yaml
@@ -0,0 +1,93 @@
+
+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/787d7e7e/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
new file mode 100644
index 0000000..612dbcb
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
@@ -0,0 +1,73 @@
+#
+# 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.
+#
+
+imports:
+  - os.yaml
+
+node_types:
+
+  mongodb.Server:
+    description: >-
+      MongoDB server application.
+    derived_from: tosca.nodes.DBMS
+    properties:
+      root_password: # @override
+        type: string
+        default: admin
+      port: # @override
+        type: integer
+        default: 27017
+    artifacts:
+      mongodb:
+        description: >-
+          MongoDB application package.
+        type: os.Archive
+        file: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.8.tgz
+        deploy_path: /opt/mongodb
+    capabilities:
+      host: # @override
+        type: tosca.capabilities.Container
+        valid_source_types: [ mongodb.Database ]
+
+  mongodb.Database:
+    description: >-
+      MongoDB database.
+      
+      Supports importing database data if a mongodb.DatabaseDump is provided.
+    derived_from: tosca.nodes.Database
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: mongodb/create_and_import_database.sh
+            dependencies:
+              - mongodb/utils/api.sh
+              - utils/os.sh
+    requirements:
+      - host: # @override
+          capability: tosca.capabilities.Container
+          node: mongodb.Server
+          relationship: tosca.relationships.HostedOn
+
+artifact_types:
+
+  mongodb.DatabaseDump:
+    description: >-
+      Dump of a MongoDB database.
+    derived_from: tosca.artifacts.Root
+    file_ext:
+      - json

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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
new file mode 100644
index 0000000..8986a21
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nginx.yaml
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+node_types:
+
+  nginx.LoadBalancer:
+    description: >-
+      Nginx as a loadbalancer.
+    derived_from: tosca.nodes.LoadBalancer
+    requirements:
+      - host:
+          capability: tosca.capabilities.Container
+          node: tosca.nodes.Compute
+          relationship: tosca.relationships.HostedOn

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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
new file mode 100644
index 0000000..ec8dd83
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
@@ -0,0 +1,69 @@
+#
+# 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.
+#
+
+imports:
+  - os.yaml
+
+node_types:
+
+  nodejs.Server:
+    description: >-
+      Node.js server application.
+    derived_from: tosca.nodes.WebServer
+    artifacts:
+      nodejs:
+        description: >-
+          Node.js application package.
+        type: os.Archive
+        file: https://nodejs.org/dist/v4.4.7/node-v4.4.7-linux-x64.tar.xz
+        deploy_path: /opt/nodejs
+    capabilities:
+      data_endpoint: # @override 
+        type: tosca.capabilities.Endpoint
+        properties:
+          port:
+            type: tosca.datatypes.network.PortDef
+            default: 8080
+          url_path:
+            type: string
+            default: /
+      admin_endpoint: # @override
+        type: tosca.capabilities.Endpoint.Admin
+        properties:
+          port:
+            type: tosca.datatypes.network.PortDef
+            default: 8080
+          url_path:
+            type: string
+            default: /admin
+      host: # @override
+        type: tosca.capabilities.Container
+        valid_source_types: [ nodejs.Application ]
+
+  nodejs.Application:
+    derived_from: tosca.nodes.WebApplication
+    capabilities:
+      app_endpoint: # @override
+        type: tosca.capabilities.Endpoint
+        properties:
+          port:
+            type: tosca.datatypes.network.PortDef
+            default: 8080
+    requirements:
+      - host: # @override
+          capability: tosca.capabilities.Container
+          node: nodejs.Server
+          relationship: tosca.relationships.HostedOn

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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
new file mode 100644
index 0000000..a18da53
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
@@ -0,0 +1,201 @@
+#
+# 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.
+#
+
+imports:
+  - os.yaml
+
+dsl_definitions:
+
+  openstack:
+    uuid_constraints: &OPENSTACK_UUID_CONSTRAINTS
+      - pattern: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'
+
+node_types:
+
+  openstack.Instance:
+    description: >-
+      OpenStack instance.
+
+      You may assign an image_id or attach an openstack.Image artifact (the artifact
+      will take precedence).
+    
+      You may assign either flavor_id or flavor_name (flavor_id will take precedence).
+      If neither are assigned, flavor_name has a default value.
+    derived_from: tosca.nodes.Compute
+    properties:
+      image_id:
+        description: >-
+          See: https://s3itwiki.uzh.ch/display/clouddoc/Supported+Images
+        type: openstack.UUID
+        default: 5d62e82c-924e-4fa9-b1e4-c133867596f7
+      flavor_id:
+        type: openstack.UUID
+        required: false
+      flavor_name:
+        type: string
+        default: m1.medium
+        required: false
+      availability_zone:
+        description: >-
+          OpenStack availability zone.
+        type: string
+        required: false
+      os_users:
+        type: map
+        entry_schema: os.UserInfo
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        inputs:
+          openstack_credential:
+            description: The OpenStack API credential for all operations.
+            type: openstack.Credential
+        create:
+          implementation:
+            primary: openstack/create_instance.sh
+            dependencies:
+              - openstack/utils/api.sh
+              - utils/os.sh
+    requirements:
+      - local_storage: # @override
+          capability: tosca.capabilities.Attachment
+          node: openstack.Volume
+          relationship: tosca.relationships.AttachesTo
+#          relationship:
+#            type: tosca.relationships.AttachesTo
+#            interfaces:
+#              Standard:
+#                inputs:
+#                  xxx:
+#                    type: string
+#                    default: { concat: [ a, b ] }
+          occurrences: [ 0, UNBOUNDED ]
+
+  openstack.Volume:
+    description: >-
+      OpenStack volume.
+      
+      See: http://developer.openstack.org/api-ref-blockstorage-v2.html
+    derived_from: tosca.nodes.BlockStorage
+    properties:
+      tenant_id:
+        type: openstack.UUID
+        required: false
+      availability_zone:
+        type: string
+        required: false
+      source_volid:
+        type: openstack.UUID
+        required: false
+      description:
+        type: string
+        required: false
+      multiattach:
+        type: boolean
+        default: false
+      #snapshot_id: # @override
+      #  type: openstack.UUID
+      #  required: false
+      name:
+        type: string
+        required: false
+      volume_type:
+        type: string
+        required: false
+      metadata:
+        type: map
+        entry_schema: string
+        required: false
+      source_replica:
+        type: openstack.UUID
+        required: false
+      consistencygroup_id:
+        type: openstack.UUID
+        required: false
+      scheduler_hints:
+        type: map
+        entry_schema: string
+        required: false
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        inputs:
+          openstack_credential:
+            description: The OpenStack API credential for all operations.
+            type: openstack.Credential
+        create:
+          implementation:
+            primary: openstack/create_volume.sh
+            dependencies:
+              - openstack/utils/api.sh
+              - utils/os.sh
+
+group_types:
+
+  openstack.Secured:
+    description: >-
+      OpenStack secured group.
+    derived_from: tosca.groups.Root
+    members:
+      - openstack.Instance
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        inputs:
+          openstack_credential:
+            description: The OpenStack API credential for all operations.
+            type: openstack.Credential
+        create:
+          implementation:
+            primary: openstack/create_secured_group.sh
+            dependencies:
+              - openstack/utils/api.sh
+              - utils/os.sh
+
+policy_types:
+
+  openstack.Scaling:
+    description: >-
+      OpenStack scaling policy.
+    derived_from: tosca.policies.Scaling
+    properties:
+      bandwidth_threshold:
+        type: scalar-unit.size
+        default: 1 GB
+    targets:
+      - openstack.Instance
+      - openstack.Secured
+
+data_types:
+
+  openstack.Credential:
+    derived_from: tosca.datatypes.Credential
+
+  openstack.UUID:
+    description: >-
+      OpenStack UUID (in GUID format).
+    derived_from: string
+    constraints: *OPENSTACK_UUID_CONSTRAINTS
+
+artifact_types:
+
+  openstack.Image:
+    description: >-
+      OpenStack image artifact.
+    derived_from: tosca.artifacts.Deployment.Image.VM
+    file_ext:
+      - img
+      - iso

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/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
new file mode 100644
index 0000000..43ea78c
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/os.yaml
@@ -0,0 +1,75 @@
+#
+# 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.
+#
+
+dsl_definitions:
+
+  os:
+    user_and_group_name_constraints: &OS_USER_AND_GROUP_NAME_CONSTRAINTS
+      - pattern: '^[a-z0-9_-]{3,16}$'
+    password_constraints: &OS_PASSWORD_CONSTRAINTS
+      - pattern: '^[a-z0-9_-]{6,18}$'
+
+artifact_types:
+
+  os.Package:
+    description: >-
+      Generic application package.
+    derived_from: tosca.artifacts.Root
+
+  os.Archive:
+    description: >-
+      Application package in an archive.
+    derived_from: os.Package
+    file_ext:
+      - zip
+      - tar
+      - tar.gz
+      - tar.xz
+    properties:
+      unpack_credential:
+        type: tosca.datatypes.Credential
+        required: false
+
+  os.Deb:
+    description: >-
+      Debian application package.
+    derived_from: os.Package
+    file_ext:
+      - deb
+
+  os.RPM:
+    description: >-
+      RPM application package.
+    derived_from: os.Package
+    file_ext:
+      - rpm
+
+data_types:
+
+  os.UserInfo:
+    description: >-
+      Information about an operating system user.
+    derived_from: tosca.datatypes.Root
+    properties:
+      password:
+        type: string
+        constraints: *OS_PASSWORD_CONSTRAINTS
+      groups:
+        type: list
+        entry_schema:
+          type: string
+          constraints: *OS_USER_AND_GROUP_NAME_CONSTRAINTS
+        required: false

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py
new file mode 100644
index 0000000..fff78bf
--- /dev/null
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/workflows.py
@@ -0,0 +1,16 @@
+
+from aria import workflow
+from aria.orchestrator.workflows.api.task import OperationTask
+
+
+@workflow
+def maintenance(ctx, graph, enabled):
+    """
+    Custom workflow to call the operations on the Maintenance interface.
+    """
+
+    operation = 'Maintenance.enable' if enabled else 'Maintenance.disable'
+
+    for node in ctx.model.node.iter():
+        for interface in node.interfaces.filter_by(name='Maintenance', type_name='Maintenance'):
+            graph.add_tasks(OperationTask.node(instance=node, name=operation))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/inputs.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/inputs.yaml b/tests/resources/service_templates/node-cellar/inputs.yaml
deleted file mode 100644
index 37ab9ea..0000000
--- a/tests/resources/service_templates/node-cellar/inputs.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-openstack_credential:
-    user: username
-    token: password

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/node-cellar.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/node-cellar.yaml b/tests/resources/service_templates/node-cellar/node-cellar.yaml
deleted file mode 100644
index 3e579bd..0000000
--- a/tests/resources/service_templates/node-cellar/node-cellar.yaml
+++ /dev/null
@@ -1,299 +0,0 @@
-#
-# 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.
-#
-
-# 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
-#tosca_definitions_version: tosca_simple_yaml_1_0
-
-description: >-
-  Node Cellar TOSCA blueprint.
-  Here is some Unicode: \u4e2d\u570b.
-
-metadata:
-  template_name: node-cellar
-  template_author: ARIA
-  template_version: '1.0.0'
-  aria_version: '0.0'
-
-imports:
-  - types/openstack.yaml
-  - types/nodejs.yaml
-  - types/mongodb.yaml
-  - types/nginx.yaml
-  - types/aria.yaml
-
-dsl_definitions:
-
-  default_openstack_credential: &DEFAULT_OPENSTACK_CREDENTIAL
-    user: openstackadmin
-    token: { concat: [ openstack, 123 ] }
-
-repositories:
-
-  node_cellar:
-    description: >-
-      The repository for the Node Cellar application and its dependencies.
-    url: https://github.com/ccoenraets/nodecellar/archive/
-    credential:
-      user: guest
-      token: ''
-
-interface_types:
-
-  Maintenance:
-    derived_from: tosca.interfaces.Root
-    enable: {}
-    disable: {}
-
-node_types:
-
-  NodeMongoApplication:
-    derived_from: nodejs.Application
-    interfaces:
-      Maintenance:
-        type: Maintenance
-    requirements:
-      - database:
-          capability: tosca.capabilities.Endpoint.Database
-          node: mongodb.Database
-
-topology_template:
-
-  inputs:
-    openstack_credential:
-      type: openstack.Credential
-      value: *DEFAULT_OPENSTACK_CREDENTIAL
-
-  node_templates:
-  
-    # Application
-
-    node_cellar:
-      description: >-
-        Node Cellar Node.js web application.
-      type: NodeMongoApplication
-      artifacts:
-        node_cellar:
-          description: >-
-            The Node Cellar application package.
-          type: os.Archive
-          file: master.zip
-          repository: node_cellar
-          deploy_path: /opt/nodejs/applications/node-cellar
-          properties:
-            unpack_credential:
-              user: gigaspaces
-              token: { get_property: [ SELF, app_endpoint, protocol ] }
-              #token: { get_property: [ HOST, flavor_name ] }
-      interfaces:
-        Maintenance:
-          enable: juju > charm.maintenance_on
-          disable: juju > charm.maintenance_off
-      requirements:
-        - database: node_cellar_database
-      capabilities:
-        app_endpoint:
-          properties:
-            protocol: udp
-            url_path: /nodecellar
-    
-    node_cellar_database:
-      description: >-
-        Node Cellar MongoDB database.
-      type: mongodb.Database
-      properties:
-        name: node_cellar
-      artifacts:
-        initial:
-          description: >-
-            The Node Cellar initial database.
-          type: mongodb.DatabaseDump
-          file: node-cellar.json
-          repository: node_cellar
-
-    # Server software
-    
-    nodejs:
-      description: >-
-        Node.js instance.
-      type: nodejs.Server
-      requirements:
-        - host: application_host
-      node_filter: # cannot be validated
-        properties:
-          #- flavor_name: { valid_values: [ {concat:[m1,.,small]} ] } # won't work because not validated :/
-          - flavor_name: { valid_values: [ m1.small ] }
-        capabilities:
-          - scalable:
-              properties:
-                - max_instances: { greater_or_equal: 8 }
-
-    mongodb:
-      description: >-
-        MongoDB instance.
-      type: mongodb.Server
-      requirements:
-        - host:
-            node: openstack.Instance
-            node_filter:
-              properties:
-                - flavor_name: { valid_values: [ m1.medium, { concat: [ { concat: [ m1, . ] }, large ] } ] }
-                #- flavor_name: { valid_values: [ m1.medium, m1.large ] }
-              capabilities:
-                - scalable:
-                    properties:
-                      - max_instances: { greater_or_equal: 8 }
-    
-    loadbalancer:
-      type: nginx.LoadBalancer
-      properties:
-        algorithm: round-robin      
-      requirements:
-        - host: loadbalancer_host
-    
-    # Hosts
-
-    loadbalancer_host:
-      description: >-
-        Host for the loadbalancer.
-      type: openstack.Instance
-      properties:
-        flavor_name: m1.small
-        os_users: # map of os.UserInfo
-          root:
-            password: admin123
-      interfaces:
-        Standard:
-          inputs:
-            openstack_credential: { get_input: openstack_credential }
-          configure: juju > charm.loadbalancer
-
-    application_host:
-      copy: loadbalancer_host
-      description: >-
-        Host for applications.
-      properties:
-        flavor_name: m1.small
-        os_users: # map of os.UserInfo
-          nodejs:
-            password: nodejs123
-            groups:
-              - www-data
-      capabilities:
-        scalable:
-          properties:
-            max_instances: 10
-
-    data_host:
-      copy: loadbalancer_host
-      description: >-
-        Host for data.
-      properties:
-        flavor_name: m1.large
-        flavor_id: 5d62e82c-924e-4fa9-b1e4-c133867596f7
-        os_users: # map of os.UserInfo
-          mongodb:
-            password: mongo123
-      requirements:
-        - local_storage:
-            node: data_volume
-            relationship:
-              properties:
-                location: /mnt/volume
-      capabilities:
-        scalable:
-          properties:
-            max_instances: 10
-
-    data_volume:
-      type: openstack.Volume
-      properties:
-        size: 10 GB
-      interfaces:
-        Standard:
-          inputs:
-            openstack_credential: { get_input: openstack_credential }
-
-  groups:
-  
-    node_cellar_group:
-      type: openstack.Secured
-      members:
-        - loadbalancer
-        - application_host
-        - data_host
-      interfaces:
-        Standard:
-          inputs:
-            openstack_credential: { get_input: openstack_credential }
-
-  policies:
-  
-    scaling:
-      type: openstack.Scaling
-      properties:
-        bandwidth_threshold: 2 GB
-      targets: # node templates or groups
-        - node_cellar_group
-    
-    juju:
-      description: >-
-        Juju plugin executes charms.
-      type: aria.Plugin
-      properties:
-        executor: host_agent
-        install: false
-    
-    maintenance_on:
-      type: MaintenanceWorkflow
-      properties:
-        enabled: true
-
-    maintenance_off:
-      type: MaintenanceWorkflow
-      properties:
-        enabled: false
-
-  substitution_mappings:
-
-    node_type: tosca.nodes.WebApplication
-    requirements:
-      host: [ node_cellar, host ] # doesn't really make sense; just for testing
-    capabilities:
-      app_endpoint: [ loadbalancer, client ]
-
-policy_types:
-
-  MaintenanceWorkflow:
-    description: >-
-      Workflow to put all nodes in/out of maintenance mode. For web servers, this will show a "this
-      site is under maintenance and we'll be back soon" web page. Database nodes will then close all
-      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/node-cellar
-      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/787d7e7e/tests/resources/service_templates/node-cellar/types/aria.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/aria.yaml b/tests/resources/service_templates/node-cellar/types/aria.yaml
deleted file mode 100644
index 2ddb238..0000000
--- a/tests/resources/service_templates/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/787d7e7e/tests/resources/service_templates/node-cellar/types/mongodb.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/mongodb.yaml b/tests/resources/service_templates/node-cellar/types/mongodb.yaml
deleted file mode 100644
index 612dbcb..0000000
--- a/tests/resources/service_templates/node-cellar/types/mongodb.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# 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.
-#
-
-imports:
-  - os.yaml
-
-node_types:
-
-  mongodb.Server:
-    description: >-
-      MongoDB server application.
-    derived_from: tosca.nodes.DBMS
-    properties:
-      root_password: # @override
-        type: string
-        default: admin
-      port: # @override
-        type: integer
-        default: 27017
-    artifacts:
-      mongodb:
-        description: >-
-          MongoDB application package.
-        type: os.Archive
-        file: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.8.tgz
-        deploy_path: /opt/mongodb
-    capabilities:
-      host: # @override
-        type: tosca.capabilities.Container
-        valid_source_types: [ mongodb.Database ]
-
-  mongodb.Database:
-    description: >-
-      MongoDB database.
-      
-      Supports importing database data if a mongodb.DatabaseDump is provided.
-    derived_from: tosca.nodes.Database
-    interfaces:
-      Standard:
-        type: tosca.interfaces.node.lifecycle.Standard
-        create:
-          implementation:
-            primary: mongodb/create_and_import_database.sh
-            dependencies:
-              - mongodb/utils/api.sh
-              - utils/os.sh
-    requirements:
-      - host: # @override
-          capability: tosca.capabilities.Container
-          node: mongodb.Server
-          relationship: tosca.relationships.HostedOn
-
-artifact_types:
-
-  mongodb.DatabaseDump:
-    description: >-
-      Dump of a MongoDB database.
-    derived_from: tosca.artifacts.Root
-    file_ext:
-      - json

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/types/nginx.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/nginx.yaml b/tests/resources/service_templates/node-cellar/types/nginx.yaml
deleted file mode 100644
index 8986a21..0000000
--- a/tests/resources/service_templates/node-cellar/types/nginx.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-node_types:
-
-  nginx.LoadBalancer:
-    description: >-
-      Nginx as a loadbalancer.
-    derived_from: tosca.nodes.LoadBalancer
-    requirements:
-      - host:
-          capability: tosca.capabilities.Container
-          node: tosca.nodes.Compute
-          relationship: tosca.relationships.HostedOn

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/types/nodejs.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/nodejs.yaml b/tests/resources/service_templates/node-cellar/types/nodejs.yaml
deleted file mode 100644
index ec8dd83..0000000
--- a/tests/resources/service_templates/node-cellar/types/nodejs.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
-#
-# 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.
-#
-
-imports:
-  - os.yaml
-
-node_types:
-
-  nodejs.Server:
-    description: >-
-      Node.js server application.
-    derived_from: tosca.nodes.WebServer
-    artifacts:
-      nodejs:
-        description: >-
-          Node.js application package.
-        type: os.Archive
-        file: https://nodejs.org/dist/v4.4.7/node-v4.4.7-linux-x64.tar.xz
-        deploy_path: /opt/nodejs
-    capabilities:
-      data_endpoint: # @override 
-        type: tosca.capabilities.Endpoint
-        properties:
-          port:
-            type: tosca.datatypes.network.PortDef
-            default: 8080
-          url_path:
-            type: string
-            default: /
-      admin_endpoint: # @override
-        type: tosca.capabilities.Endpoint.Admin
-        properties:
-          port:
-            type: tosca.datatypes.network.PortDef
-            default: 8080
-          url_path:
-            type: string
-            default: /admin
-      host: # @override
-        type: tosca.capabilities.Container
-        valid_source_types: [ nodejs.Application ]
-
-  nodejs.Application:
-    derived_from: tosca.nodes.WebApplication
-    capabilities:
-      app_endpoint: # @override
-        type: tosca.capabilities.Endpoint
-        properties:
-          port:
-            type: tosca.datatypes.network.PortDef
-            default: 8080
-    requirements:
-      - host: # @override
-          capability: tosca.capabilities.Container
-          node: nodejs.Server
-          relationship: tosca.relationships.HostedOn

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/types/openstack.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/openstack.yaml b/tests/resources/service_templates/node-cellar/types/openstack.yaml
deleted file mode 100644
index a18da53..0000000
--- a/tests/resources/service_templates/node-cellar/types/openstack.yaml
+++ /dev/null
@@ -1,201 +0,0 @@
-#
-# 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.
-#
-
-imports:
-  - os.yaml
-
-dsl_definitions:
-
-  openstack:
-    uuid_constraints: &OPENSTACK_UUID_CONSTRAINTS
-      - pattern: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'
-
-node_types:
-
-  openstack.Instance:
-    description: >-
-      OpenStack instance.
-
-      You may assign an image_id or attach an openstack.Image artifact (the artifact
-      will take precedence).
-    
-      You may assign either flavor_id or flavor_name (flavor_id will take precedence).
-      If neither are assigned, flavor_name has a default value.
-    derived_from: tosca.nodes.Compute
-    properties:
-      image_id:
-        description: >-
-          See: https://s3itwiki.uzh.ch/display/clouddoc/Supported+Images
-        type: openstack.UUID
-        default: 5d62e82c-924e-4fa9-b1e4-c133867596f7
-      flavor_id:
-        type: openstack.UUID
-        required: false
-      flavor_name:
-        type: string
-        default: m1.medium
-        required: false
-      availability_zone:
-        description: >-
-          OpenStack availability zone.
-        type: string
-        required: false
-      os_users:
-        type: map
-        entry_schema: os.UserInfo
-    interfaces:
-      Standard:
-        type: tosca.interfaces.node.lifecycle.Standard
-        inputs:
-          openstack_credential:
-            description: The OpenStack API credential for all operations.
-            type: openstack.Credential
-        create:
-          implementation:
-            primary: openstack/create_instance.sh
-            dependencies:
-              - openstack/utils/api.sh
-              - utils/os.sh
-    requirements:
-      - local_storage: # @override
-          capability: tosca.capabilities.Attachment
-          node: openstack.Volume
-          relationship: tosca.relationships.AttachesTo
-#          relationship:
-#            type: tosca.relationships.AttachesTo
-#            interfaces:
-#              Standard:
-#                inputs:
-#                  xxx:
-#                    type: string
-#                    default: { concat: [ a, b ] }
-          occurrences: [ 0, UNBOUNDED ]
-
-  openstack.Volume:
-    description: >-
-      OpenStack volume.
-      
-      See: http://developer.openstack.org/api-ref-blockstorage-v2.html
-    derived_from: tosca.nodes.BlockStorage
-    properties:
-      tenant_id:
-        type: openstack.UUID
-        required: false
-      availability_zone:
-        type: string
-        required: false
-      source_volid:
-        type: openstack.UUID
-        required: false
-      description:
-        type: string
-        required: false
-      multiattach:
-        type: boolean
-        default: false
-      #snapshot_id: # @override
-      #  type: openstack.UUID
-      #  required: false
-      name:
-        type: string
-        required: false
-      volume_type:
-        type: string
-        required: false
-      metadata:
-        type: map
-        entry_schema: string
-        required: false
-      source_replica:
-        type: openstack.UUID
-        required: false
-      consistencygroup_id:
-        type: openstack.UUID
-        required: false
-      scheduler_hints:
-        type: map
-        entry_schema: string
-        required: false
-    interfaces:
-      Standard:
-        type: tosca.interfaces.node.lifecycle.Standard
-        inputs:
-          openstack_credential:
-            description: The OpenStack API credential for all operations.
-            type: openstack.Credential
-        create:
-          implementation:
-            primary: openstack/create_volume.sh
-            dependencies:
-              - openstack/utils/api.sh
-              - utils/os.sh
-
-group_types:
-
-  openstack.Secured:
-    description: >-
-      OpenStack secured group.
-    derived_from: tosca.groups.Root
-    members:
-      - openstack.Instance
-    interfaces:
-      Standard:
-        type: tosca.interfaces.node.lifecycle.Standard
-        inputs:
-          openstack_credential:
-            description: The OpenStack API credential for all operations.
-            type: openstack.Credential
-        create:
-          implementation:
-            primary: openstack/create_secured_group.sh
-            dependencies:
-              - openstack/utils/api.sh
-              - utils/os.sh
-
-policy_types:
-
-  openstack.Scaling:
-    description: >-
-      OpenStack scaling policy.
-    derived_from: tosca.policies.Scaling
-    properties:
-      bandwidth_threshold:
-        type: scalar-unit.size
-        default: 1 GB
-    targets:
-      - openstack.Instance
-      - openstack.Secured
-
-data_types:
-
-  openstack.Credential:
-    derived_from: tosca.datatypes.Credential
-
-  openstack.UUID:
-    description: >-
-      OpenStack UUID (in GUID format).
-    derived_from: string
-    constraints: *OPENSTACK_UUID_CONSTRAINTS
-
-artifact_types:
-
-  openstack.Image:
-    description: >-
-      OpenStack image artifact.
-    derived_from: tosca.artifacts.Deployment.Image.VM
-    file_ext:
-      - img
-      - iso

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/types/os.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/types/os.yaml b/tests/resources/service_templates/node-cellar/types/os.yaml
deleted file mode 100644
index 43ea78c..0000000
--- a/tests/resources/service_templates/node-cellar/types/os.yaml
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# 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.
-#
-
-dsl_definitions:
-
-  os:
-    user_and_group_name_constraints: &OS_USER_AND_GROUP_NAME_CONSTRAINTS
-      - pattern: '^[a-z0-9_-]{3,16}$'
-    password_constraints: &OS_PASSWORD_CONSTRAINTS
-      - pattern: '^[a-z0-9_-]{6,18}$'
-
-artifact_types:
-
-  os.Package:
-    description: >-
-      Generic application package.
-    derived_from: tosca.artifacts.Root
-
-  os.Archive:
-    description: >-
-      Application package in an archive.
-    derived_from: os.Package
-    file_ext:
-      - zip
-      - tar
-      - tar.gz
-      - tar.xz
-    properties:
-      unpack_credential:
-        type: tosca.datatypes.Credential
-        required: false
-
-  os.Deb:
-    description: >-
-      Debian application package.
-    derived_from: os.Package
-    file_ext:
-      - deb
-
-  os.RPM:
-    description: >-
-      RPM application package.
-    derived_from: os.Package
-    file_ext:
-      - rpm
-
-data_types:
-
-  os.UserInfo:
-    description: >-
-      Information about an operating system user.
-    derived_from: tosca.datatypes.Root
-    properties:
-      password:
-        type: string
-        constraints: *OS_PASSWORD_CONSTRAINTS
-      groups:
-        type: list
-        entry_schema:
-          type: string
-          constraints: *OS_USER_AND_GROUP_NAME_CONSTRAINTS
-        required: false

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/tests/resources/service_templates/node-cellar/workflows.py
----------------------------------------------------------------------
diff --git a/tests/resources/service_templates/node-cellar/workflows.py b/tests/resources/service_templates/node-cellar/workflows.py
deleted file mode 100644
index fff78bf..0000000
--- a/tests/resources/service_templates/node-cellar/workflows.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-from aria import workflow
-from aria.orchestrator.workflows.api.task import OperationTask
-
-
-@workflow
-def maintenance(ctx, graph, enabled):
-    """
-    Custom workflow to call the operations on the Maintenance interface.
-    """
-
-    operation = 'Maintenance.enable' if enabled else 'Maintenance.disable'
-
-    for node in ctx.model.node.iter():
-        for interface in node.interfaces.filter_by(name='Maintenance', type_name='Maintenance'):
-            graph.add_tasks(OperationTask.node(instance=node, name=operation))


[2/7] incubator-ariatosca git commit: ARIA-88 Add TOSCA use-case examples

Posted by mx...@apache.org.
ARIA-88 Add TOSCA use-case examples


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: 787d7e7e6d210adba96dc0057fdf43f4c0034658
Parents: b619335
Author: Tal Liron <ta...@gmail.com>
Authored: Wed Feb 15 12:48:56 2017 -0600
Committer: Tal Liron <ta...@gmail.com>
Committed: Thu Feb 16 08:49:52 2017 -0600

----------------------------------------------------------------------
 MANIFEST.in                                     |   1 +
 aria/parser/modeling/instance_elements.py       |   4 +-
 aria/parser/modeling/model_elements.py          |  10 +-
 .../block-storage-1/block-storage-1.yaml        |  68 +++++
 .../block-storage-2/block-storage-2.yaml        |  75 +++++
 .../block-storage-3/block-storage-3.yaml        |  68 +++++
 .../block-storage-4/block-storage-4.yaml        |  96 ++++++
 .../block-storage-5/block-storage-5.yaml        | 109 +++++++
 .../block-storage-6/block-storage-6.yaml        | 102 +++++++
 .../use-cases/compute-1/compute-1.yaml          |  42 +++
 .../use-cases/container-1/container-1.yaml      |  68 +++++
 .../multi-tier-1/custom_types/collectd.yaml     |  10 +
 .../custom_types/elasticsearch.yaml             |   6 +
 .../multi-tier-1/custom_types/kibana.yaml       |  10 +
 .../multi-tier-1/custom_types/logstash.yaml     |  10 +
 .../multi-tier-1/custom_types/rsyslog.yaml      |  10 +
 .../use-cases/multi-tier-1/multi-tier-1.yaml    | 237 +++++++++++++++
 .../use-cases/network-1/network-1.yaml          |  49 +++
 .../use-cases/network-2/network-2.yaml          |  46 +++
 .../use-cases/network-3/network-3.yaml          |  81 +++++
 .../use-cases/network-4/network-4.yaml          |  70 +++++
 .../use-cases/non-normative-types.yaml          | 177 +++++++++++
 .../object-storage-1/object-storage-1.yaml      |  24 ++
 .../software-component-1.yaml                   |  54 ++++
 .../webserver-dbms-1/webserver-dbms-1.yaml      | 122 ++++++++
 .../paypalpizzastore_nodejs_app.yaml            |  15 +
 .../webserver-dbms-2/webserver-dbms-2.yaml      | 115 +++++++
 .../profiles/tosca-simple-1.0/artifacts.yaml    |  12 +-
 .../profiles/tosca-simple-1.0/capabilities.yaml |   4 +-
 .../profiles/tosca-simple-1.0/data.yaml         |   4 +-
 .../profiles/tosca-simple-1.0/groups.yaml       |   2 +-
 .../profiles/tosca-simple-1.0/interfaces.yaml   |   2 +-
 .../profiles/tosca-simple-1.0/nodes.yaml        |  11 +-
 .../profiles/tosca-simple-1.0/policies.yaml     |  10 +-
 .../tosca-simple-1.0/relationships.yaml         |   4 +-
 .../tosca-simple-nfv-1.0/capabilities.yaml      |   3 +-
 .../profiles/tosca-simple-nfv-1.0/data.yaml     |   2 +-
 .../profiles/tosca-simple-nfv-1.0/groups.yaml   |   2 +-
 .../profiles/tosca-simple-nfv-1.0/nodes.yaml    |  12 +-
 .../simple_v1_0/assignments.py                  |   2 +-
 .../simple_v1_0/functions.py                    |  18 +-
 .../aria_extension_tosca/simple_v1_0/misc.py    |   1 +
 .../simple_v1_0/modeling/__init__.py            |  13 +-
 .../simple_v1_0/modeling/requirements.py        |  29 +-
 .../presentation/field_validators.py            |  18 +-
 tests/end2end/test_parser.py                    |  40 ---
 tests/end2end/test_tosca_simple_v1_0.py         | 112 +++++++
 tests/parser/service_templates.py               |  20 +-
 tests/parser/utils.py                           |   9 +-
 .../tosca-simple-1.0/node-cellar/inputs.yaml    |   3 +
 .../node-cellar/node-cellar.yaml                | 299 +++++++++++++++++++
 .../node-cellar/types/aria.yaml                 |  93 ++++++
 .../node-cellar/types/mongodb.yaml              |  73 +++++
 .../node-cellar/types/nginx.yaml                |  27 ++
 .../node-cellar/types/nodejs.yaml               |  69 +++++
 .../node-cellar/types/openstack.yaml            | 201 +++++++++++++
 .../tosca-simple-1.0/node-cellar/types/os.yaml  |  75 +++++
 .../tosca-simple-1.0/node-cellar/workflows.py   |  16 +
 .../service_templates/node-cellar/inputs.yaml   |   3 -
 .../node-cellar/node-cellar.yaml                | 299 -------------------
 .../node-cellar/types/aria.yaml                 |  93 ------
 .../node-cellar/types/mongodb.yaml              |  73 -----
 .../node-cellar/types/nginx.yaml                |  27 --
 .../node-cellar/types/nodejs.yaml               |  69 -----
 .../node-cellar/types/openstack.yaml            | 201 -------------
 .../service_templates/node-cellar/types/os.yaml |  75 -----
 .../service_templates/node-cellar/workflows.py  |  16 -
 67 files changed, 2737 insertions(+), 984 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/MANIFEST.in
----------------------------------------------------------------------
diff --git a/MANIFEST.in b/MANIFEST.in
index f9bd145..d934e18 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1,2 @@
 include requirements.txt
+recursive-include examples *

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/aria/parser/modeling/instance_elements.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/instance_elements.py b/aria/parser/modeling/instance_elements.py
index 523de0b..8310d62 100644
--- a/aria/parser/modeling/instance_elements.py
+++ b/aria/parser/modeling/instance_elements.py
@@ -451,8 +451,8 @@ class Relationship(Element):
                  template_name=None):
         if name is not None and not isinstance(name, basestring):
             raise ValueError('name must be a string or None')
-        if (source_requirement_index is not None and
-                (not isinstance(source_requirement_index, int) or (source_requirement_index < 0))):
+        if source_requirement_index is not None and \
+                (not isinstance(source_requirement_index, int) or (source_requirement_index < 0)):
             raise ValueError('source_requirement_index must be int > 0')
         if type_name is not None and not isinstance(type_name, basestring):
             raise ValueError('type_name must be a string or None')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/aria/parser/modeling/model_elements.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/model_elements.py b/aria/parser/modeling/model_elements.py
index 7346a54..69da60e 100644
--- a/aria/parser/modeling/model_elements.py
+++ b/aria/parser/modeling/model_elements.py
@@ -296,9 +296,8 @@ class RequirementTemplate(ModelElement):
         if target_capability_name is not None and not isinstance(target_capability_name,
                                                                  basestring):
             raise ValueError('target_capability_name must be a string or None')
-        if target_node_type_name is not None and target_node_template_name is not None \
-                or target_node_type_name is None and target_node_template_name is None:
-            raise ValueError('must set either target_node_type_name or target_node_template_name')
+        if target_node_type_name is not None and target_node_template_name is not None:
+            raise ValueError('can set either target_node_type_name or target_node_template_name')
         if target_capability_type_name is not None and target_capability_name is not None:
             raise ValueError('can set either target_capability_type_name or target_capability_name')
 
@@ -552,8 +551,7 @@ class RelationshipTemplate(ModelElement):
             raise ValueError('type_name must be a string or None')
         if (template_name is not None) and (not isinstance(template_name, basestring)):
             raise ValueError('template_name must be a string or None')
-        if type_name is not None and template_name is not None \
-                or type_name is None and template_name is None:
+        if (type_name is None) and (template_name is None):
             raise ValueError('must set either type_name or template_name')
 
         self.type_name = type_name
@@ -576,7 +574,7 @@ class RelationshipTemplate(ModelElement):
             ('target_interface_templates', as_raw_list(self.target_interface_templates))))
 
     def instantiate(self, context, container):
-        relationship = Relationship(self.type_name, self.template_name)
+        relationship = Relationship(name=self.template_name, type_name=self.type_name)
         instantiate_dict(context, container,
                          relationship.properties, self.properties)
         instantiate_dict(context, container,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-1/block-storage-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-1/block-storage-1.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-1/block-storage-1.yaml
new file mode 100644
index 0000000..ff6dc92
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-1/block-storage-1.yaml
@@ -0,0 +1,68 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with server and attached block storage using the normative AttachesTo
+  Relationship Type.
+
+metadata:
+  template_name: block-storage-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      description: Size of the storage to be created.
+      default: 1 GB
+    storage_snapshot_id:
+      type: string
+      description: >-
+        Optional identifier for an existing snapshot to use when creating storage.    
+    storage_location:
+      type: string
+      description: Block storage mount point (filesystem path).
+
+  node_templates:
+
+    my_server:
+      type: Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 1 GB
+        os:
+          properties:
+            architecture: x86_64
+            type: linux 
+            distribution: fedora 
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            relationship:
+              type: AttachesTo
+              properties:
+                location: { get_input: storage_location }
+
+    my_storage:
+      type: BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+  outputs:
+    private_ip:
+      description: The private IP address of the newly created compute instance.
+      value: { get_attribute: [ my_server, private_address ] }
+    volume_id:
+      description: The volume id of the block storage instance.
+      value: { get_attribute: [ my_storage, volume_id ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-2/block-storage-2.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-2/block-storage-2.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-2/block-storage-2.yaml
new file mode 100644
index 0000000..09c30a7
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-2/block-storage-2.yaml
@@ -0,0 +1,75 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with server and attached block storage using a custom AttachesTo Relationship
+  Type.
+
+metadata:
+  template_name: block-storage-2
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+relationship_types:
+
+  MyCustomAttachesTo:
+     derived_from: AttachesTo
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      description: Size of the storage to be created.
+      default: 1 GB
+    storage_snapshot_id:
+      type: string
+      description: >-
+        Optional identifier for an existing snapshot to use when creating storage.    
+    storage_location:
+      type: string
+      description: Block storage mount point (filesystem path).
+
+  node_templates:
+
+    my_server:
+      type: Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4 GB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux 
+            distribution: Fedora 
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            # Declare custom AttachesTo type using the 'relationship' keyword
+            relationship:
+              type: MyCustomAttachesTo
+              properties:
+                location: { get_input: storage_location }
+
+    my_storage:
+      type: BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+  outputs:
+    private_ip:
+      description: The private IP address of the newly created compute instance.
+      value: { get_attribute: [ my_server, private_address ] }
+
+    volume_id:
+      description: The volume id of the block storage instance.
+      value: { get_attribute: [ my_storage, volume_id ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-3/block-storage-3.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-3/block-storage-3.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-3/block-storage-3.yaml
new file mode 100644
index 0000000..3018fe9
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-3/block-storage-3.yaml
@@ -0,0 +1,68 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with server and attached block storage using a named Relationship Template
+  for the storage attachment.
+
+metadata:
+  template_name: block-storage-3
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      description: Size of the storage to be created.
+      default: 1 GB
+    storage_location:
+      type: string
+      description: Block storage mount point (filesystem path).
+
+  node_templates:
+
+    my_server:
+      type: Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4 GB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux 
+            distribution: Fedora 
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            # Declare template to use with 'relationship' keyword
+            relationship: storage_attachment
+
+    my_storage:
+      type: BlockStorage
+      properties:
+        size: { get_input: storage_size }
+
+  relationship_templates:
+
+    storage_attachment:
+      type: AttachesTo
+      properties:
+        location: { get_input: storage_location }
+
+  outputs:
+    private_ip:
+      description: The private IP address of the newly created compute instance.
+      value: { get_attribute: [ my_server, private_address ] }
+    volume_id:
+      description: The volume id of the block storage instance.
+      value: { get_attribute: [ my_storage, volume_id ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-4/block-storage-4.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-4/block-storage-4.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-4/block-storage-4.yaml
new file mode 100644
index 0000000..0693ddd
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-4/block-storage-4.yaml
@@ -0,0 +1,96 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with a Single Block Storage node shared by 2-Tier Application with custom
+  AttachesTo Type and implied relationships.
+
+metadata:
+  template_name: block-storage-4
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+relationship_types:
+
+  MyAttachesTo:
+    derived_from: tosca.relationships.AttachesTo
+    properties:
+      location:
+        type: string
+        default: /default_location
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      default: 1 GB
+      description: Size of the storage to be created.
+    storage_snapshot_id:
+      type: string
+      description: >-
+        Optional identifier for an existing snapshot to use when creating storage.    
+
+  node_templates:
+
+    my_web_app_tier_1:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            relationship: MyAttachesTo
+
+    my_web_app_tier_2:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            relationship:
+              type: MyAttachesTo
+              properties:
+                location: /some_other_data_location
+
+    my_storage:
+      type: tosca.nodes.BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+  outputs:
+    private_ip_1:
+      description: The private IP address of the application's first tier.
+      value: { get_attribute: [ my_web_app_tier_1, private_address ] }
+    private_ip_2:
+      description: The private IP address of the application's second tier.
+      value: { get_attribute: [ my_web_app_tier_2, private_address ] }
+    volume_id:
+      description: The volume id of the block storage instance.
+      value: { get_attribute: [ my_storage, volume_id ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-5/block-storage-5.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-5/block-storage-5.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-5/block-storage-5.yaml
new file mode 100644
index 0000000..5f5cf71
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-5/block-storage-5.yaml
@@ -0,0 +1,109 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with a single Block Storage node shared by 2-Tier Application with custom
+  AttachesTo Type and explicit Relationship Templates.
+
+metadata:
+  template_name: block-storage-5
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+relationship_types:
+
+  MyAttachesTo:
+    derived_from: tosca.relationships.AttachesTo
+    properties:
+      location:
+        type: string
+        default: /default_location
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      default: 1 GB
+      description: Size of the storage to be created.
+    storage_snapshot_id:
+      type: string
+      description: >-
+        Optional identifier for an existing snapshot to use when creating storage.
+    storage_location:
+      type: string
+      description: >-
+        Block storage mount point (filesystem path).
+
+  node_templates:
+
+    my_web_app_tier_1:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            relationship: storage_attachesto_1
+
+    my_web_app_tier_2:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+        - local_storage:
+            node: my_storage
+            relationship: storage_attachesto_2
+
+    my_storage:
+      type: tosca.nodes.BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+  relationship_templates:
+
+    storage_attachesto_1:
+      type: MyAttachesTo
+      properties:
+        location: /my_data_location
+
+    storage_attachesto_2:
+      type: MyAttachesTo
+      properties:
+        location: /some_other_data_location
+
+  outputs:
+    private_ip_1:
+      description: The private IP address of the application's first tier.
+      value: { get_attribute: [my_web_app_tier_1, private_address] }
+    private_ip_2:
+      description: The private IP address of the application's second tier.
+      value: { get_attribute: [my_web_app_tier_2, private_address] }
+    volume_id:
+      description: The volume id of the block storage instance.
+      value: { get_attribute: [my_storage, volume_id] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/block-storage-6/block-storage-6.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/block-storage-6/block-storage-6.yaml b/examples/tosca-simple-1.0/use-cases/block-storage-6/block-storage-6.yaml
new file mode 100644
index 0000000..808245b
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/block-storage-6/block-storage-6.yaml
@@ -0,0 +1,102 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with 2 servers each with different attached block storage.
+
+metadata:
+  template_name: block-storage-6
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    storage_size:
+      type: scalar-unit.size
+      default: 1 GB
+      description: Size of the storage to be created.
+    storage_snapshot_id:
+      type: string
+      description: >-
+        Optional identifier for an existing snapshot to use when creating storage.
+    storage_location:
+      type: string
+      description: >-
+        Block storage mount point (filesystem path).
+
+  node_templates:
+
+    my_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+         - local_storage:
+             node: my_storage
+             relationship:
+               type: AttachesTo
+               properties:
+                 location: { get_input: storage_location }
+
+    my_storage:
+      type: tosca.nodes.BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+    my_server2:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: Fedora
+            version: 18.0
+      requirements:
+         - local_storage:
+             node: my_storage2
+             relationship:
+               type: AttachesTo
+               properties:
+                 location: { get_input: storage_location }
+
+    my_storage2:
+      type: tosca.nodes.BlockStorage
+      properties:
+        size: { get_input: storage_size }
+        snapshot_id: { get_input: storage_snapshot_id }
+
+  outputs:
+    server_ip_1:
+      description: The private IP address of the application's first server.
+      value: { get_attribute: [ my_server, private_address ] }
+    server_ip_2:
+      description: The private IP address of the application's second server.
+      value: { get_attribute: [ my_server2, private_address ] }
+    volume_id_1:
+      description: The volume id of the first block storage instance.
+      value: { get_attribute: [my_storage, volume_id] }
+    volume_id_2:
+      description: The volume id of the second block storage instance.
+      value: { get_attribute: [ my_storage2, volume_id ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/compute-1/compute-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/compute-1/compute-1.yaml b/examples/tosca-simple-1.0/use-cases/compute-1/compute-1.yaml
new file mode 100644
index 0000000..254d2b6
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/compute-1/compute-1.yaml
@@ -0,0 +1,42 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile that just defines a single compute instance and selects a (guest) host
+  Operating System from the Compute node's properties. Note, this example does not include default
+  values on inputs properties.
+
+metadata:
+  template_name: compute-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+
+  node_templates:
+
+    my_server:
+      type: Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 1 GB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: ubuntu
+            version: 12.04
+
+  outputs:
+    private_ip:
+      description: The private IP address of the deployed server instance.
+      value: { get_attribute: [ my_server, private_address ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/container-1/container-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/container-1/container-1.yaml b/examples/tosca-simple-1.0/use-cases/container-1/container-1.yaml
new file mode 100644
index 0000000..f6f69fc
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/container-1/container-1.yaml
@@ -0,0 +1,68 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with wordpress, web server and mysql on the same server.
+
+metadata:
+  template_name: compute-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+imports:
+  - ../non-normative-types.yaml
+
+# Repositories to retrieve code artifacts from
+
+repositories:
+
+  docker_hub: https://registry.hub.docker.com/
+
+topology_template:
+
+  inputs:
+    wp_host_port:
+      type: integer
+      description: The host port that maps to port 80 of the WordPress container.
+    db_root_pwd:
+      type: string
+      description: Root password for MySQL.
+
+  node_templates:
+
+    # The MYSQL container based on official MySQL image in Docker hub
+
+    mysql_container:
+      type: tosca.nodes.Container.Application.Docker
+      # ARIA NOTE: moved to a requirement in the node type
+      #capabilities:
+      #  # This is a capability that would mimic the Docker \u2013link feature
+      #  database_link: tosca.capabilities.Docker.Link
+      artifacts:
+        my_image:
+          file: mysql
+          type: tosca.artifacts.Deployment.Image.Container.Docker
+          repository: docker_hub
+      interfaces:
+        Standard:
+          create:
+            implementation: my_image
+            inputs:
+              db_root_password: { get_input: db_root_pwd }
+
+    # The WordPress container based on official WordPress image in Docker hub
+
+    wordpress_container:
+      type: tosca.nodes.Container.Application.Docker
+      requirements:
+        - database_link: mysql_container
+      artifacts:
+        my_image:
+          file: wordpress
+          type: tosca.artifacts.Deployment.Image.Container.Docker
+          repository: docker_hub
+      interfaces:
+        Standard:
+          create:
+            implementation: my_image
+            inputs:
+              host_port: { get_input: wp_host_port }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/collectd.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/collectd.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/collectd.yaml
new file mode 100644
index 0000000..6d28899
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/collectd.yaml
@@ -0,0 +1,10 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.SoftwareComponent.Collectd:
+    derived_from: tosca.nodes.SoftwareComponent
+    requirements:
+      - collectd_endpoint:
+          capability: tosca.capabilities.Endpoint
+          relationship: tosca.relationships.ConnectsTo

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/elasticsearch.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/elasticsearch.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/elasticsearch.yaml
new file mode 100644
index 0000000..32623d1
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/elasticsearch.yaml
@@ -0,0 +1,6 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.SoftwareComponent.Elasticsearch:
+    derived_from: tosca.nodes.SoftwareComponent

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/kibana.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/kibana.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/kibana.yaml
new file mode 100644
index 0000000..7af00d0
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/kibana.yaml
@@ -0,0 +1,10 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.SoftwareComponent.Kibana:
+    derived_from: tosca.nodes.SoftwareComponent
+    requirements:
+      - search_endpoint:
+          capability: tosca.capabilities.Endpoint
+          relationship: tosca.relationships.ConnectsTo

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/logstash.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/logstash.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/logstash.yaml
new file mode 100644
index 0000000..a3eebbe
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/logstash.yaml
@@ -0,0 +1,10 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.SoftwareComponent.Logstash:
+    derived_from: tosca.nodes.SoftwareComponent
+    requirements:
+      - search_endpoint:
+          capability: tosca.capabilities.Endpoint
+          relationship: tosca.relationships.ConnectsTo

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/rsyslog.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/rsyslog.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/rsyslog.yaml
new file mode 100644
index 0000000..3bd7c2b
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/custom_types/rsyslog.yaml
@@ -0,0 +1,10 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.SoftwareComponent.Rsyslog:
+    derived_from: tosca.nodes.SoftwareComponent
+    requirements:
+      - rsyslog_endpoint:
+          capability: tosca.capabilities.Endpoint
+          relationship: tosca.relationships.ConnectsTo

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/multi-tier-1/multi-tier-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/multi-tier-1/multi-tier-1.yaml b/examples/tosca-simple-1.0/use-cases/multi-tier-1/multi-tier-1.yaml
new file mode 100644
index 0000000..3485e49
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/multi-tier-1/multi-tier-1.yaml
@@ -0,0 +1,237 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  This TOSCA simple profile deploys nodejs, mongodb, elasticsearch, logstash and kibana each on a
+  separate server with monitoring enabled for nodejs server where a sample nodejs application is
+  running. The syslog and collectd are installed on a nodejs server.
+
+metadata:
+  template_name: multi-tier-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+imports:
+  - ../webserver-dbms-2/custom_types/paypalpizzastore_nodejs_app.yaml # ARIA NOTE: moved
+  - custom_types/elasticsearch.yaml
+  - custom_types/logstash.yaml
+  - custom_types/kibana.yaml
+  - custom_types/collectd.yaml
+  - custom_types/rsyslog.yaml
+
+dsl_definitions:
+
+  host_capabilities: &host_capabilities
+    # container properties (flavor)
+    disk_size: 10 GB
+    num_cpus: { get_input: my_cpus }
+    mem_size: 4096 MB
+  os_capabilities: &os_capabilities
+    architecture: x86_64
+    type: Linux
+    distribution: Ubuntu
+    version: 14.04
+
+topology_template:
+
+  inputs:
+    my_cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+    github_url:
+       type: string
+       description: The URL to download nodejs.
+       default: https://github.com/sample.git
+
+  node_templates:
+
+    paypal_pizzastore:
+      type: tosca.nodes.WebApplication.PayPalPizzaStore
+      properties:
+        github_url: { get_input: github_url }
+      requirements:
+        - host: nodejs
+        - database_connection: mongo_db
+      interfaces:
+        Standard:
+           configure:
+             implementation: scripts/nodejs/configure.sh
+             inputs:
+               github_url: { get_property: [ SELF, github_url ] }
+               mongodb_ip: { get_attribute: [mongo_server, private_address] }
+           start: scripts/nodejs/start.sh
+
+    nodejs:
+      type: tosca.nodes.WebServer.Nodejs
+      requirements:
+        - host: app_server
+      interfaces:
+        Standard:
+          create: scripts/nodejs/create.sh
+
+    mongo_db:
+      type: tosca.nodes.Database
+      properties:
+        name: 'pizzastore' # ARIA NOTE: missing in spec
+      requirements:
+        - host: mongo_dbms
+      interfaces:
+        Standard:
+         create: create_database.sh
+
+    mongo_dbms:
+      type: tosca.nodes.DBMS
+      requirements:
+        - host: mongo_server
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/mongodb/create.sh
+          configure:
+            implementation: scripts/mongodb/config.sh
+            inputs:
+              mongodb_ip: { get_attribute: [mongo_server, ip_address] }
+          start: scripts/mongodb/start.sh
+
+    elasticsearch:
+      type: tosca.nodes.SoftwareComponent.Elasticsearch
+      requirements:
+        - host: elasticsearch_server
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/elasticsearch/create.sh
+          start: scripts/elasticsearch/start.sh
+
+    logstash:
+      type: tosca.nodes.SoftwareComponent.Logstash
+      requirements:
+        - host: logstash_server
+        # ARIA NOTE: mangled in the spec
+        - search_endpoint:
+            node: elasticsearch
+            relationship:
+              interfaces:
+                Configure:
+                  pre_configure_source:
+                    implementation: python/logstash/configure_elasticsearch.py
+                    inputs:
+                      elasticsearch_ip: { get_attribute: [elasticsearch_server, ip_address] }
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/lostash/create.sh
+          configure: scripts/logstash/config.sh
+          start: scripts/logstash/start.sh
+
+    kibana:
+      type: tosca.nodes.SoftwareComponent.Kibana
+      requirements:
+        - host: kibana_server
+        - search_endpoint: elasticsearch
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/kibana/create.sh
+          configure:
+            implementation: scripts/kibana/config.sh
+            inputs:
+              elasticsearch_ip: { get_attribute: [ elasticsearch_server, ip_address ] }
+              kibana_ip: { get_attribute: [ kibana_server, ip_address ] }
+          start: scripts/kibana/start.sh
+
+    app_collectd:
+      type: tosca.nodes.SoftwareComponent.Collectd
+      requirements:
+        - host: app_server
+        # ARIA NOTE: mangled in the spec
+        - collectd_endpoint:
+            node: logstash
+            relationship:
+              interfaces:
+                Configure:
+                  pre_configure_target:
+                    implementation: python/logstash/configure_collectd.py
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/collectd/create.sh
+          configure:
+            implementation: python/collectd/config.py
+            inputs:
+              logstash_ip: { get_attribute: [ logstash_server, ip_address ] }
+          start: scripts/collectd/start.sh
+
+    app_rsyslog:
+      type: tosca.nodes.SoftwareComponent.Rsyslog
+      requirements:
+        - host: app_server
+        # ARIA NOTE: mangled in the spec
+        - rsyslog_endpoint:
+            node: logstash
+            relationship:
+              interfaces:
+                Configure:
+                  pre_configure_target:
+                    implementation: python/logstash/configure_rsyslog.py
+      interfaces:
+        Standard: # ARIA NOTE: wrong in spec
+          create: scripts/rsyslog/create.sh
+          configure:
+            implementation: scripts/rsyslog/config.sh
+            inputs:
+              logstash_ip: { get_attribute: [ logstash_server, ip_address ] }
+          start: scripts/rsyslog/start.sh
+
+    app_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties: *host_capabilities
+        os:
+          properties: *os_capabilities
+
+    mongo_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties: *host_capabilities
+        os:
+          properties: *os_capabilities
+
+    elasticsearch_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties: *host_capabilities
+        os:
+          properties: *os_capabilities
+
+    logstash_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties: *host_capabilities
+        os:
+          properties: *os_capabilities
+
+    kibana_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties: *host_capabilities
+        os:
+          properties: *os_capabilities
+
+  outputs:
+    nodejs_url:
+      description: URL for the nodejs server.
+      value: { get_attribute: [ app_server, private_address ] }
+    mongodb_url:
+      description: URL for the mongodb server.
+      value: { get_attribute: [ mongo_server, private_address ] }
+    elasticsearch_url:
+      description: URL for the elasticsearch server.
+      value: { get_attribute: [ elasticsearch_server, private_address ] }
+    logstash_url:
+      description: URL for the logstash server.
+      value: { get_attribute: [ logstash_server, private_address ] }
+    kibana_url:
+      description: URL for the kibana server.
+      value: { get_attribute: [ kibana_server, private_address ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/network-1/network-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/network-1/network-1.yaml b/examples/tosca-simple-1.0/use-cases/network-1/network-1.yaml
new file mode 100644
index 0000000..c66964f
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/network-1/network-1.yaml
@@ -0,0 +1,49 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with 1 server bound to a new network.
+
+metadata:
+  template_name: network-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    network_name:
+      type: string
+      description: Network name
+
+  node_templates:
+
+    my_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: 1
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: CirrOS
+            version: 0.3.2
+
+    my_network:
+      type: tosca.nodes.network.Network
+      properties:
+        network_name: { get_input: network_name }
+        ip_version: 4
+        cidr: '192.168.0.0/24'
+        start_ip: '192.168.0.50'
+        end_ip: '192.168.0.200'
+        gateway_ip: '192.168.0.1'
+
+    my_port:
+      type: tosca.nodes.network.Port
+      requirements:
+        - binding: my_server
+        - link: my_network

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/network-2/network-2.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/network-2/network-2.yaml b/examples/tosca-simple-1.0/use-cases/network-2/network-2.yaml
new file mode 100644
index 0000000..017950d
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/network-2/network-2.yaml
@@ -0,0 +1,46 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with 1 server bound to an existing network.
+
+metadata:
+  template_name: network-2
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    network_name:
+      type: string
+      description: Network name
+
+  node_templates:
+
+    my_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: 1
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: CirrOS
+            version: 0.3.2
+
+    my_network:
+      type: tosca.nodes.network.Network
+      properties:
+        network_name: { get_input: network_name }
+
+    my_port:
+      type: tosca.nodes.network.Port
+      requirements:
+        - binding:
+            node: my_server
+        - link:
+            node: my_network

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/network-3/network-3.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/network-3/network-3.yaml b/examples/tosca-simple-1.0/use-cases/network-3/network-3.yaml
new file mode 100644
index 0000000..5fa40b7
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/network-3/network-3.yaml
@@ -0,0 +1,81 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with 2 servers bound to the 1 network.
+
+metadata:
+  template_name: network-3
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    network_name:
+      type: string
+      description: Network name
+    network_cidr:
+      type: string
+      default: 10.0.0.0/24
+      description: CIDR for the network
+    network_start_ip:
+      type: string
+      default: 10.0.0.100
+      description: Start IP for the allocation pool
+    network_end_ip:
+      type: string
+      default: 10.0.0.150
+      description: End IP for the allocation pool
+
+  node_templates:
+
+    my_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: 1
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: CirrOS
+            version: 0.3.2
+
+    my_server2:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: 1
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: CirrOS
+            version: 0.3.2
+
+    my_network:
+      type: tosca.nodes.network.Network
+      properties:
+        ip_version: 4
+        cidr: { get_input: network_cidr }
+        network_name: { get_input: network_name }
+        start_ip: { get_input: network_start_ip }
+        end_ip: { get_input: network_end_ip }
+
+    my_port:
+      type: tosca.nodes.network.Port
+      requirements:
+        - binding: my_server
+        - link: my_network
+
+    my_port2:
+      type: tosca.nodes.network.Port
+      requirements:
+        - binding: my_server2
+        - link: my_network

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/network-4/network-4.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/network-4/network-4.yaml b/examples/tosca-simple-1.0/use-cases/network-4/network-4.yaml
new file mode 100644
index 0000000..5b51117
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/network-4/network-4.yaml
@@ -0,0 +1,70 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with 1 server bound to 3 networks.
+
+metadata:
+  template_name: network-4
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  node_templates:
+
+    my_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: 1
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: Linux
+            distribution: CirrOS
+            version: 0.3.2
+
+    my_network1:
+      type: tosca.nodes.network.Network
+      properties:
+        cidr: '192.168.1.0/24'
+        network_name: net1
+
+    my_network2:
+      type: tosca.nodes.network.Network
+      properties:
+        cidr: '192.168.2.0/24'
+        network_name: net2
+
+    my_network3:
+      type: tosca.nodes.network.Network
+      properties:
+        cidr: '192.168.3.0/24'
+        network_name: net3
+
+    my_port1:
+      type: tosca.nodes.network.Port
+      properties:
+        order: 0
+      requirements:
+        - binding: my_server
+        - link: my_network1
+
+    my_port2:
+      type: tosca.nodes.network.Port
+      properties:
+        order: 1
+      requirements:
+        - binding: my_server
+        - link: my_network2
+
+    my_port3:
+      type: tosca.nodes.network.Port
+      properties:
+        order: 2
+      requirements:
+        - binding: my_server
+        - link: my_network3

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml b/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml
new file mode 100644
index 0000000..fa826f5
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml
@@ -0,0 +1,177 @@
+
+artifact_types:
+
+  tosca.artifacts.Deployment.Image.Container.Docker:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.1.1
+    derived_from: tosca.artifacts.Deployment.Image
+    description: Docker Container Image
+
+  tosca.artifacts.Deployment.Image.VM.ISO:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.1.2
+    derived_from: tosca.artifacts.Deployment.Image.VM
+    description: Virtual Machine (VM) image in ISO disk format
+    mime_type: application/octet-stream
+    file_ext: [ iso ]
+
+  tosca.artifacts.Deployment.Image.VM.QCOW2:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.1.3
+    derived_from: tosca.artifacts.Deployment.Image.VM
+    description: Virtual Machine (VM) image in QCOW v2 standard disk format
+    mime_type: application/octet-stream
+    file_ext: [ qcow2 ]
+
+capability_types:
+
+  tosca.capabilities.Container.Docker:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.2.1
+    derived_from: tosca.capabilities.Container
+    description: The type indicates capabilities of a Docker runtime environment (client).
+    properties:
+      version:
+        description: >-
+          The Docker version capability (i.e., the versions supported by the capability).
+        type: list
+        required: false
+        entry_schema: version
+      publish_all:
+        description: >-
+          Indicates that all ports (ranges) listed in the dockerfile using the EXPOSE keyword be
+          published.
+        type: boolean
+        default: false
+        required: false
+      publish_ports:
+        description: >-
+          List of ports mappings from source (Docker container) to target (host) ports to publish. 
+        type: list
+        entry_schema: PortSpec
+        required: false
+      expose_ports:
+        description: >-
+          List of ports mappings from source (Docker container) to expose to other Docker containers
+          (not accessible outside host).
+        type: list
+        entry_schema: PortSpec
+        required: false
+      volumes:
+        description: >-
+          The dockerfile VOLUME command which is used to enable access from the Docker container to
+          a directory on the host machine.
+        type: list
+        entry_schema: string
+        required: false
+      # ARIA NOTE: these are missing in the spec
+      host_id:
+        description: >-
+          The optional identifier of an existing host resource that should be used to run this
+          container on.
+        type: string
+        required: false
+      volume_id:
+        description: >-
+          The optional identifier of an existing storage volume (resource) that should be used to
+          create the container's mount point(s) on.
+        type: string
+        required: false
+
+  # ARIA NOTE: missing in spec
+  tosca.capabilities.Docker.Link:
+    derived_from: tosca.capabilities.Root
+    description: This is a capability that would mimic the Docker \u2013link feature
+
+node_types:
+
+  tosca.nodes.Database.MySQL:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.1
+    derived_from: tosca.nodes.Database
+    requirements:
+      - host:
+          capability: tosca.capabilities.Container # ARIA NOTE: missing in spec
+          node: tosca.nodes.DBMS.MySQL
+
+  tosca.nodes.DBMS.MySQL:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.2
+    derived_from: tosca.nodes.DBMS
+    properties:
+      port:
+        description: reflect the default MySQL server port
+        type: integer # AIRA NOTE: missing in spec
+        default: 3306
+      root_password:
+        # MySQL requires a root_password for configuration
+        # Override parent DBMS definition to make this property required
+        type: string # AIRA NOTE: missing in spec
+        required: true
+    capabilities:
+      # Further constrain the 'host' capability to only allow MySQL databases
+      host:
+        type: tosca.capabilities.Container # ARIA NOTE: missing in spec
+        valid_source_types: [ tosca.nodes.Database.MySQL ] 
+
+  tosca.nodes.WebServer.Apache:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.3
+    derived_from: tosca.nodes.WebServer
+
+  tosca.nodes.WebApplication.WordPress:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.4
+    derived_from: tosca.nodes.WebApplication
+    properties:
+      admin_user:
+        type: string
+        required: false # ARIA NOTE: missing in spec
+      admin_password:
+        type: string
+        required: false # ARIA NOTE: missing in spec
+      db_host:
+        type: string
+        required: false # ARIA NOTE: missing in spec
+    requirements:
+      - database_endpoint:
+          capability: tosca.capabilities.Endpoint.Database  
+          node: tosca.nodes.Database
+          relationship: tosca.relationships.ConnectsTo
+
+  tosca.nodes.WebServer.Nodejs:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.5
+    derived_from: tosca.nodes.WebServer
+    properties:
+      # Property to supply the desired implementation in the Github repository
+      github_url:
+        required: no
+        type: string
+        description: location of the application on the github.
+        default: https://github.com/mmm/testnode.git
+    interfaces:
+      Standard:
+        inputs:
+          github_url:
+            type: string
+
+  tosca.nodes.Container.Application.Docker:
+    _extensions:
+      specification: tosca-simple-1.0
+      specification_section: 8.3.6
+    derived_from: tosca.nodes.Container.Application
+    requirements:
+      - host:
+          capability: tosca.capabilities.Container.Docker
+      - database_link: # ARIA NOTE: missing in spec
+          capability: tosca.capabilities.Docker.Link

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/object-storage-1/object-storage-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/object-storage-1/object-storage-1.yaml b/examples/tosca-simple-1.0/use-cases/object-storage-1/object-storage-1.yaml
new file mode 100644
index 0000000..c55a4db
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/object-storage-1/object-storage-1.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+    TOSCA template for creating an object storage service.
+
+metadata:
+  template_name: object-storage-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+topology_template:
+
+  inputs:
+    objectstore_name:
+      type: string
+
+  node_templates:
+
+    obj_store_server:
+      type: tosca.nodes.ObjectStorage
+      properties:
+        name: { get_input: objectstore_name }
+        size: 4096 MB
+        maxsize: 20 GB

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/software-component-1/software-component-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/software-component-1/software-component-1.yaml b/examples/tosca-simple-1.0/use-cases/software-component-1/software-component-1.yaml
new file mode 100644
index 0000000..fc1cfd7
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/software-component-1/software-component-1.yaml
@@ -0,0 +1,54 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA Simple Profile with a SoftwareComponent node with a declared Virtual machine (VM) deployment
+  artifact that automatically deploys to its host Compute node.
+
+metadata:
+  template_name: software-component-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+imports:
+  - ../non-normative-types.yaml
+
+topology_template:
+
+  # ARIA NOTE: missing in spec
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+
+  node_templates:
+
+    my_virtual_machine:
+      type: SoftwareComponent
+      artifacts:
+        my_vm_image:
+          file: images/fedora-18-x86_64.qcow2
+          type: tosca.artifacts.Deployment.Image.VM.QCOW2
+      requirements:
+        - host: my_server
+      # Automatically deploy the VM image referenced on the create operation
+      interfaces:
+        Standard:
+          create: my_vm_image
+
+    # Compute instance with no Operating System guest host
+    my_server:
+      type: Compute
+      capabilities:
+        # Note: no guest OperatingSystem requirements as these are in the image.
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4 GB
+
+  outputs:
+    private_ip:
+      description: The private IP address of the deployed server instance.
+      value: { get_attribute: [ my_server, private_address ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/webserver-dbms-1/webserver-dbms-1.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/webserver-dbms-1/webserver-dbms-1.yaml b/examples/tosca-simple-1.0/use-cases/webserver-dbms-1/webserver-dbms-1.yaml
new file mode 100644
index 0000000..faf109d
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/webserver-dbms-1/webserver-dbms-1.yaml
@@ -0,0 +1,122 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with WordPress, a web server, a MySQL DBMS hosting the application's database
+  content on the same server. Does not have input defaults or constraints.
+
+metadata:
+  template_name: webserver-dbms-1
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+imports:
+  - ../non-normative-types.yaml
+
+topology_template:
+
+  inputs:
+    cpus:
+      type: integer
+      description: Number of CPUs for the server.
+    db_name:
+      type: string
+      description: The name of the database.
+    db_user:
+      type: string
+      description: The username of the DB user.
+    db_pwd:
+      type: string
+      description: The WordPress database admin account password.
+    db_root_pwd:
+      type: string
+      description: Root password for MySQL.
+    db_port:
+      type: PortDef
+      description: Port for the MySQL database
+    # ARIA NOTE: missing in spec
+    context_root:
+      type: string
+      description: Context root for WordPress.
+
+  node_templates:
+
+    wordpress:
+      type: tosca.nodes.WebApplication.WordPress
+      properties:
+        context_root: { get_input: context_root }
+      requirements:
+        - host: webserver
+        - database_endpoint: mysql_database
+      interfaces:
+        Standard:
+          create: wordpress_install.sh
+          configure:
+            implementation: wordpress_configure.sh           
+            inputs:
+              wp_db_name: { get_property: [ mysql_database, name ] }
+              wp_db_user: { get_property: [ mysql_database, user ] }
+              wp_db_password: { get_property: [ mysql_database, password ] }  
+              # In my own template, find requirement/capability, find port property
+              wp_db_port: { get_property: [ SELF, database_endpoint, port ] }
+
+    mysql_database:
+      type: Database
+      properties:
+        name: { get_input: db_name }
+        user: { get_input: db_user }
+        password: { get_input: db_pwd }
+        port: { get_input: db_port }
+      capabilities:
+        database_endpoint:
+          properties:
+            port: { get_input: db_port }
+      requirements:
+        - host: mysql_dbms
+      interfaces:
+        Standard:
+          configure: mysql_database_configure.sh
+
+    mysql_dbms:
+      type: DBMS
+      properties:
+        root_password: { get_input: db_root_pwd }
+        port: { get_input: db_port }
+      requirements:
+        - host: server
+      interfaces:
+        Standard:
+          # ARIA NOTE: not declared in spec              
+          #inputs:
+          #  db_root_password: { get_property: [ mysql_dbms, root_password ] }
+          create: mysql_dbms_install.sh
+          start: mysql_dbms_start.sh
+          configure: mysql_dbms_configure.sh
+
+    webserver:
+      type: WebServer
+      requirements:
+        - host: server
+      interfaces:
+        Standard:
+          create: webserver_install.sh
+          start: webserver_start.sh
+
+    server:
+      type: Compute
+      capabilities:
+        host:
+          properties:
+            disk_size: 10 GB
+            num_cpus: { get_input: cpus }
+            mem_size: 4096 MB
+        os:
+          properties:
+            architecture: x86_64
+            type: linux 
+            distribution: fedora 
+            version: 17.0
+
+  outputs:
+    website_url:
+      description: URL for Wordpress wiki.
+      value: { get_attribute: [ server, public_address ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/custom_types/paypalpizzastore_nodejs_app.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/custom_types/paypalpizzastore_nodejs_app.yaml b/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/custom_types/paypalpizzastore_nodejs_app.yaml
new file mode 100644
index 0000000..4723a3f
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/custom_types/paypalpizzastore_nodejs_app.yaml
@@ -0,0 +1,15 @@
+# ARIA NOTE: missing in spec
+
+node_types:
+
+  tosca.nodes.WebApplication.PayPalPizzaStore:
+    derived_from: tosca.nodes.WebApplication
+    properties:
+      github_url:
+        type: string
+    requirements:
+      - database_connection:
+          capability: tosca.capabilities.Container
+
+  tosca.nodes.WebServer.Nodejs:
+    derived_from: tosca.nodes.WebServer

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/webserver-dbms-2.yaml
----------------------------------------------------------------------
diff --git a/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/webserver-dbms-2.yaml b/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/webserver-dbms-2.yaml
new file mode 100644
index 0000000..66eab8e
--- /dev/null
+++ b/examples/tosca-simple-1.0/use-cases/webserver-dbms-2/webserver-dbms-2.yaml
@@ -0,0 +1,115 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  TOSCA simple profile with a nodejs web server hosting a PayPal sample application which connects
+  to a mongodb database.
+
+metadata:
+  template_name: webserver-dbms-2
+  template_author: TOSCA Simple Profile in YAML
+  template_version: '1.0'
+
+imports:
+  - custom_types/paypalpizzastore_nodejs_app.yaml
+
+dsl_definitions:
+
+  ubuntu_node: &ubuntu_node
+    disk_size: 10 GB
+    num_cpus: { get_input: my_cpus }
+    mem_size: 4096 MB
+  os_capabilities: &os_capabilities
+    architecture: x86_64
+    type: Linux
+    distribution: Ubuntu
+    version: 14.04
+
+topology_template:
+
+  inputs:
+    my_cpus:
+      type: integer
+      description: Number of CPUs for the server.
+      constraints:
+        - valid_values: [ 1, 2, 4, 8 ]
+      default: 1
+    github_url:
+      type: string
+      description: The URL to download nodejs.
+      default:  https://github.com/sample.git
+
+  node_templates:
+
+    paypal_pizzastore:
+      type: tosca.nodes.WebApplication.PayPalPizzaStore
+      properties:
+          github_url: { get_input: github_url }
+      requirements:
+        - host: nodejs
+        - database_connection: mongo_db
+      interfaces:
+        Standard:
+           configure:
+             implementation: scripts/nodejs/configure.sh
+             inputs:
+               github_url: { get_property: [ SELF, github_url ] }
+               mongodb_ip: { get_attribute: [mongo_server, private_address] }
+           start: scripts/nodejs/start.sh
+
+    nodejs:
+      type: tosca.nodes.WebServer.Nodejs
+      requirements:
+        - host: app_server
+      interfaces:
+        Standard:
+          create: scripts/nodejs/create.sh
+
+    mongo_db:
+      type: tosca.nodes.Database
+      properties:
+        name: 'pizzastore' # ARIA NOTE: missing in spec
+      requirements:
+        - host: mongo_dbms
+      interfaces:
+        Standard:
+         create: create_database.sh
+
+    mongo_dbms:
+      type: tosca.nodes.DBMS
+      requirements:
+        - host: mongo_server
+      properties:
+        port: 27017
+      interfaces:
+        Standard: # ARIA NOTE: mistaken in spec
+          create: mongodb/create.sh
+          configure:
+            implementation: mongodb/config.sh
+            inputs:
+              mongodb_ip: { get_attribute: [mongo_server, private_address] }
+          start: mongodb/start.sh
+
+    mongo_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        os:
+          properties: *os_capabilities
+        host:
+          properties: *ubuntu_node
+
+    app_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        os:
+          properties: *os_capabilities
+        host:
+          properties: *ubuntu_node
+
+  outputs:
+
+    nodejs_url:
+      description: URL for the nodejs server, http://<IP>:3000
+      value: { get_attribute: [app_server, private_address] }
+    mongodb_url:
+      description: URL for the mongodb server.
+      value: { get_attribute: [ mongo_server, private_address ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/artifacts.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/artifacts.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/artifacts.yaml
index ef9e5f2..af99340 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/artifacts.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/artifacts.yaml
@@ -17,7 +17,7 @@ artifact_types:
 
   tosca.artifacts.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.3.1
@@ -41,7 +41,7 @@ artifact_types:
   
   tosca.artifacts.Deployment:
     _extensions:
-      shorthand_name: Deployment # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Deployment # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Deployment
       specification: tosca-simple-1.0
       specification_section: 5.3.3.1
@@ -67,7 +67,7 @@ artifact_types:
   
   tosca.artifacts.Deployment.Image.VM:
     _extensions:
-      shorthand_name: Deployment.VM # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Deployment.VM # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Deployment.VM
       specification: tosca-simple-1.0
       specification_section: 5.3.3.4
@@ -85,7 +85,7 @@ artifact_types:
   
   tosca.artifacts.Implementation:
     _extensions:
-      shorthand_name: Implementation # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Implementation # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Implementation
       specification: tosca-simple-1.0
       specification_section: 5.3.4.1
@@ -97,7 +97,7 @@ artifact_types:
   
   tosca.artifacts.Implementation.Bash:
     _extensions:
-      shorthand_name: Implementation.Bash # mistake in spec? shouldn't we have "Implementation." as prefix?
+      shorthand_name: Implementation.Bash # ARIA NOTE: mistake in spec? shouldn't we have "Implementation." as prefix?
       type_qualified_name: tosca:Implementation.Bash
       specification: tosca-simple-1.0
       specification_section: 5.3.4.3
@@ -109,7 +109,7 @@ artifact_types:
   
   tosca.artifacts.Implementation.Python:
     _extensions:
-      shorthand_name: Implementation.Python # mistake in spec? shouldn't we have "Implementation." as prefix?
+      shorthand_name: Implementation.Python # ARIA NOTE: mistake in spec? shouldn't we have "Implementation." as prefix?
       type_qualified_name: tosca:Implementation.Python
       specification: tosca-simple-1.0
       specification_section: 5.3.4.4

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/capabilities.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/capabilities.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/capabilities.yaml
index 2578799..72f6f0e 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/capabilities.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/capabilities.yaml
@@ -17,7 +17,7 @@ capability_types:
 
   tosca.capabilities.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.4.1
@@ -296,7 +296,7 @@ capability_types:
 
   tosca.capabilities.network.Bindable:
     _extensions:
-      shorthand_name: Bindable # mistake in spec? has "network." as a prefix 
+      shorthand_name: Bindable # ARIA NOTE: mistake in spec? has "network." as a prefix 
       type_qualified_name: tosca:Bindable
       specification: tosca-simple-1.0
       specification_section: 5.4.11

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/data.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/data.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/data.yaml
index ef787b7..5210aa0 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/data.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/data.yaml
@@ -95,7 +95,7 @@ data_types:
 
   tosca.datatypes.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.2.1
@@ -220,7 +220,7 @@ data_types:
       specification_url: 'http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html#TYPE_TOSCA_DATA_PORTDEF'
     description: >-
       The PortDef type is a TOSCA data Type used to define a network port.
-    derived_from: integer # ARIA allows deriving from primitives; it's unclear if the TOSCA spec does
+    derived_from: integer # ARIA NOTE: we allow deriving from primitives
     constraints:
       - in_range: [ 1, 65535 ]
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/groups.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/groups.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/groups.yaml
index a252a7c..31cfc55 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/groups.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/groups.yaml
@@ -17,7 +17,7 @@ group_types:
 
   tosca.groups.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.9.1

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/interfaces.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/interfaces.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/interfaces.yaml
index dd84d43..de1d34f 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/interfaces.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/interfaces.yaml
@@ -17,7 +17,7 @@ interface_types:
 
   tosca.interfaces.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.7.3

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/nodes.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/nodes.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/nodes.yaml
index 2d1b407..414a388 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/nodes.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/nodes.yaml
@@ -126,7 +126,7 @@ node_types:
         description: >-
           The Floating (IP) client's on the public network can connect to.
         type: tosca.capabilities.Endpoint.Public
-        occurrences: [ 0, UNBOUNDED ] # Note: it seems unnecessary to specify this, as it is the implied default
+        occurrences: [ 0, UNBOUNDED ] # ARIA NOTE: it seems unnecessary to specify this, as it is the implied default
     requirements:
       - application:
           capability: tosca.capabilities.Endpoint
@@ -195,7 +195,7 @@ node_types:
     description: >-
       The TOSCA WebApplication node represents a software application that can be managed and run by a TOSCA WebServer node.
       Specific types of web applications such as Java, etc. could be derived from this type.
-    derived_from: tosca.nodes.SoftwareComponent # the spec says tosca.nodes.Root, but this seems to be a mistake
+    derived_from: tosca.nodes.SoftwareComponent # ARIA NOTE: the spec says tosca.nodes.Root
     properties:
       context_root:
         description: >-
@@ -213,7 +213,7 @@ node_types:
   
   tosca.nodes.DBMS:
     _extensions:
-      shorthand_name: DBMS # ommitted in the spec (seems to be a mistake)
+      shorthand_name: DBMS # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:DBMS
       specification: tosca-simple-1.0
       specification_section: 5.8.6
@@ -246,7 +246,7 @@ node_types:
       specification_url: 'http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html#DEFN_TYPE_NODES_DATABASE'
     description: >-
       The TOSCA Database node represents a logical database that can be managed and hosted by a TOSCA DBMS node.
-    derived_from: tosca.nodes.Root # note, it's *not* a SoftwareComponent
+    derived_from: tosca.nodes.Root # ARIA NOTE: it's *not* a SoftwareComponent
     properties:
       name:
         description: >-
@@ -310,7 +310,8 @@ node_types:
     requirements:
       - host:
           capability: tosca.capabilities.Container
-          #node: tosca.nodes.Container # seems to be a mistake in the spec
+          # ARIA NOTE: seems a mistake in the spec
+          #node: tosca.nodes.Container
           relationship: tosca.relationships.HostedOn
 
   #

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/policies.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/policies.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/policies.yaml
index d840b14..015d2b0 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/policies.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/policies.yaml
@@ -17,7 +17,7 @@ policy_types:
 
   tosca.policies.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.10.1
@@ -27,7 +27,7 @@ policy_types:
   
   tosca.policies.Placement:
     _extensions:
-      shorthand_name: Placement # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Placement # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Placement
       specification: tosca-simple-1.0
       specification_section: 5.10.2
@@ -38,7 +38,7 @@ policy_types:
   
   tosca.policies.Scaling:
     _extensions:
-      shorthand_name: Scaling # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Scaling # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Scaling
       specification: tosca-simple-1.0
       specification_section: 5.10.3
@@ -49,7 +49,7 @@ policy_types:
   
   tosca.policies.Update:
     _extensions:
-      shorthand_name: Update # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Update # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Update
       specification: tosca-simple-1.0
       specification_section: 5.10.4
@@ -60,7 +60,7 @@ policy_types:
   
   tosca.policies.Performance:
     _extensions:
-      shorthand_name: Performance # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Performance # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Performance
       specification: tosca-simple-1.0
       specification_section: 5.10.5

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/relationships.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/relationships.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/relationships.yaml
index 212ccfa..6ea4d12 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/relationships.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-1.0/relationships.yaml
@@ -17,7 +17,7 @@ relationship_types:
 
   tosca.relationships.Root:
     _extensions:
-      shorthand_name: Root # ommitted in the spec (seems to be a mistake)
+      shorthand_name: Root # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:Root
       specification: tosca-simple-1.0
       specification_section: 5.6.1
@@ -147,7 +147,7 @@ relationship_types:
   
   tosca.relationships.network.BindsTo:
     _extensions:
-      shorthand_name: network.BindsTo # mistake in spec? this seems different than the usual shorthand convention
+      shorthand_name: BindsTo # ARIA NOTE: the spec says "network.BindsTo" which seems wrong
       type_qualified_name: tosca:BindsTo
       specification: tosca-simple-1.0
       specification_section: 7.5.5

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/capabilities.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/capabilities.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/capabilities.yaml
index 7be18a6..6bc6b67 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/capabilities.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/capabilities.yaml
@@ -35,7 +35,8 @@ capability_types:
           * any page size maps to system default
           * custom MB value: sets TLB size to this specific value
         type: string
-        #constraints: # seems wrong in the spec
+        # ARIA NOTE: seems wrong in the spec
+        #constraints:
         #  - [ normal, huge ]
       cpu_allocation:
         description: >-

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml
index 97467ba..89e3565 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml
@@ -57,7 +57,7 @@ data_types:
 
   tosca.datatypes.compute.Container.Architecture.NUMA:
     _extensions:
-      shorthand_name: Container.Architecture.NUMA # seems to be a mistake in the spec; the norm is to add a "Container.Architecture." prefix
+      shorthand_name: Container.Architecture.NUMA # ARIA NOTE: seems to be a mistake in the spec; the norm is to add a "Container.Architecture." prefix
       type_qualified_name: tosca:Container.Architecture.NUMA
       specification: tosca-simple-nfv-1.0
       specification_section: 8.3.2

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml
index 4a01519..5eb87c8 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml
@@ -17,7 +17,7 @@ group_types:
 
   tosca.groups.nfv.VNFFG:
     _extensions:
-      shorthand_name: VNFFG # the spec must be mistaken here, says "VL"
+      shorthand_name: VNFFG # ARIA NOTE: the spec must be mistaken here, says "VL"
       type_qualified_name: tosca:VNFFG
       specification: tosca-simple-nfv-1.0
       specification_section: 10.6.1

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml
index 5b9a653..0dfe38d 100644
--- a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml
+++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml
@@ -17,7 +17,7 @@ node_types:
 
   tosca.nodes.nfv.VNF:
     _extensions:
-      shorthand_name: VNF # ommitted in the spec (seems to be a mistake)
+      shorthand_name: VNF # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:VNF
       specification: tosca-simple-nfv-1.0
       specification_section: 8.5.1
@@ -103,7 +103,7 @@ node_types:
 
   tosca.nodes.nfv.FP:
     _extensions:
-      shorthand_name: FP # the spec must be mistaken here, says "VL"
+      shorthand_name: FP # ARIA NOTE: the spec must be mistaken here, says "VL"
       type_qualified_name: tosca:FP
       specification: tosca-simple-nfv-1.0
       specification_section: 10.5.1
@@ -147,7 +147,7 @@ node_types:
 
   tosca.nodes.nfv.VL.ELine:
     _extensions:
-      shorthand_name: VL.ELine # ommitted in the spec (seems to be a mistake)
+      shorthand_name: VL.ELine # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:VL.ELine
       specification: tosca-simple-nfv-1.0
       specification_section: 9.2
@@ -158,11 +158,11 @@ node_types:
     capabilities:
       virtual_linkable:
         type: tosca.capabilities.nfv.VirtualLinkable
-        occurrences: [ 2, UNBOUNDED ] # the spec is wrong here, must be a range
+        occurrences: [ 2, UNBOUNDED ] # ARIA NOTE: the spec is wrong here, must be a range
 
   tosca.nodes.nfv.VL.ELAN:
     _extensions:
-      shorthand_name: VL.ELAN # ommitted in the spec (seems to be a mistake)
+      shorthand_name: VL.ELAN # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:VL.ELAN
       specification: tosca-simple-nfv-1.0
       specification_section: 9.3
@@ -173,7 +173,7 @@ node_types:
 
   tosca.nodes.nfv.VL.ETree:
     _extensions:
-      shorthand_name: VL.ETree # ommitted in the spec (seems to be a mistake)
+      shorthand_name: VL.ETree # ARIA NOTE: ommitted in the spec
       type_qualified_name: tosca:VL.ETree
       specification: tosca-simple-nfv-1.0
       specification_section: 9.4

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/787d7e7e/extensions/aria_extension_tosca/simple_v1_0/assignments.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/assignments.py b/extensions/aria_extension_tosca/simple_v1_0/assignments.py
index 14fee96..2a39ed9 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/assignments.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/assignments.py
@@ -232,7 +232,7 @@ class RequirementAssignment(ExtensiblePresentation):
         * Relationship Type that the provider will use to select a type-compatible relationship
           template to relate the source node to the target node at runtime.
 
-        :rtype: :class:`RequirementRelationshipAssignment`
+        :rtype: :class:`RelationshipAssignment`
         """
 
     @field_validator(node_filter_validator)



[6/7] incubator-ariatosca git commit: added source to log

Posted by mx...@apache.org.
added source to log


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: c3f4501d45006b207211fd8b957f12ca966b395d
Parents: f881d0b
Author: mxmrlv <mx...@gmail.com>
Authored: Mon Feb 13 23:03:54 2017 +0200
Committer: mxmrlv <mx...@gmail.com>
Committed: Sun Feb 19 10:38:30 2017 +0200

----------------------------------------------------------------------
 aria/logger.py                                 | 14 +++++++-------
 aria/orchestrator/context/common.py            | 17 +++++++++++++++--
 aria/orchestrator/context/operation.py         |  8 ++++++++
 aria/orchestrator/context/workflow.py          |  1 +
 aria/storage/modeling/orchestrator_elements.py |  4 +++-
 tests/orchestrator/context/test_operation.py   | 19 ++++++++++---------
 6 files changed, 44 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index ebe01ba..6940d43 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -138,7 +138,11 @@ def create_file_log_handler(
 
 
 class SQLAlchemyHandler(logging.Handler):
+
     def __init__(self, session, engine, log_cls, **kwargs):
+        from aria.storage.modeling import instance_elements
+
+        self._instance_elements = instance_elements
         self._session = session
         self._engine = engine
         self._cls = log_cls
@@ -146,10 +150,11 @@ class SQLAlchemyHandler(logging.Handler):
 
     def emit(self, record):
         log = self._cls(
+            prefix=record.prefix,
             logger=record.name,
             level=record.levelname,
             msg=record.msg,
-            created_at=datetime.utcnow()
+            created_at=datetime.utcnow(),
         )
         self._session.add(log)
         self._session.commit()
@@ -163,15 +168,10 @@ class _SQLAlchemyHandlerFactory(object):
         self._handler = None
 
     def __call__(self, session, engine, model_cls=Log, level=logging.DEBUG):
-        if self._handler is None or not self._is_eq(session, engine, model_cls):
+        if not self._handler:
             self._handler = SQLAlchemyHandler(session, engine, model_cls, level=level)
         return self._handler
 
-    def _is_eq(self, session, engine, model_cls):
-        return all([self._handler._session == session,
-                    self._handler._engine == engine,
-                    self._handler._cls == model_cls])
-
 create_sqla_log_handler = _SQLAlchemyHandlerFactory()
 
 _default_file_formatter = logging.Formatter(

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index d5ef42c..7e84c0c 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -15,6 +15,7 @@
 """
 A common context for both workflow and operation
 """
+from functools import partial
 from uuid import uuid4
 
 import logging
@@ -25,6 +26,18 @@ from aria import logger
 from aria.storage import exceptions
 
 
+class _Logger(object):
+    def __init__(self, logger):
+        self._logger = logger
+        self._prefix = ''
+
+    def set_prefix(self, prefix):
+        self._prefix = prefix
+
+    def __getattr__(self, item):
+        return partial(getattr(self._logger, item), extra={'prefix': self._prefix})
+
+
 class BaseContext(object):
     """
     Base context object for workflow and operation
@@ -45,7 +58,7 @@ class BaseContext(object):
         self._model = model_storage
         self._resource = resource_storage
         self._service_instance_id = service_instance_id
-        self._logger = self._init_logger(ctx_logger)
+        self._logger = self._init_logger(ctx_logger=ctx_logger)
         self._workdir = workdir
 
     def _init_logger(self, ctx_logger=None):
@@ -58,7 +71,7 @@ class BaseContext(object):
 
         ctx_logger.setLevel(logging.DEBUG)
 
-        return ctx_logger
+        return _Logger(ctx_logger)
 
     def __repr__(self):
         return (

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py b/aria/orchestrator/context/operation.py
index c5ac8f0..efe62ab 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -105,6 +105,10 @@ class NodeOperationContext(BaseOperationContext):
     """
     Context for node based operations.
     """
+    def __init__(self, **kwargs):
+        super(NodeOperationContext, self).__init__(**kwargs)
+        self.logger.set_prefix(str(self.node))
+
     @property
     def node_template(self):
         """
@@ -126,6 +130,10 @@ class RelationshipOperationContext(BaseOperationContext):
     """
     Context for relationship based operations.
     """
+    def __init__(self, **kwargs):
+        super(RelationshipOperationContext, self).__init__(**kwargs)
+        self.logger.set_prefix(str(self.relationship))
+
     @property
     def source_node_template(self):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/aria/orchestrator/context/workflow.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/workflow.py b/aria/orchestrator/context/workflow.py
index 00ed974..297e1bc 100644
--- a/aria/orchestrator/context/workflow.py
+++ b/aria/orchestrator/context/workflow.py
@@ -46,6 +46,7 @@ class WorkflowContext(BaseContext):
         # TODO: execution creation should happen somewhere else
         # should be moved there, when such logical place exists
         self._execution_id = self._create_execution() if execution_id is None else execution_id
+        self.logger.set_prefix(str(self.execution))
 
     def __repr__(self):
         return (

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/aria/storage/modeling/orchestrator_elements.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/orchestrator_elements.py b/aria/storage/modeling/orchestrator_elements.py
index 8efc147..edd40b9 100644
--- a/aria/storage/modeling/orchestrator_elements.py
+++ b/aria/storage/modeling/orchestrator_elements.py
@@ -475,6 +475,8 @@ class LogBase(ModelMixin):
     level = Column(String)
     msg = Column(String)
     created_at = Column(DateTime, index=True)
+    prefix = Column(String)
 
     def __repr__(self):
-        return "<Log: {0} - {1}>".format(self.created_at, self.msg[:50])
+        return "<Log [{self.prefix}]: {self.created_at} - {msg}>".format(
+            self=self, msg=self.msg[:50])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/c3f4501d/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index 08d360c..c216a16 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -47,7 +47,9 @@ def ctx(tmpdir):
 
 @pytest.fixture
 def executor():
-    result = thread.ThreadExecutor()
+    from aria.orchestrator.workflows.executor import process
+    result = process.ProcessExecutor()
+    # result = thread.ThreadExecutor()
     try:
         yield result
     finally:
@@ -242,25 +244,24 @@ def test_operation_logging(ctx, executor):
 
     execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
 
-    op_start_log = ctx.model.log.list(filters=dict(msg=inputs['op_start']))
+    logs = ctx.model.log.list()
+    assert len(logs) == 6
+
+    op_start_log = [l for l in logs if inputs['op_start'] in l.msg and l.level.lower() == 'info']
     assert len(op_start_log) == 1
     op_start_log = op_start_log[0]
-    assert op_start_log.level.lower() == 'info'
 
-    op_end_log = ctx.model.log.list(filters=dict(msg=inputs['op_end']))
+    op_end_log = [l for l in logs if inputs['op_end'] in l.msg and l.level.lower() == 'debug']
     assert len(op_end_log) == 1
     op_end_log = op_end_log[0]
-    assert op_end_log.level.lower() == 'debug'
 
-    wf_start_log = ctx.model.log.list(filters=dict(msg=wf_start))
+    wf_start_log = [l for l in logs if wf_start in l.msg and l.level.lower() == 'info']
     assert len(wf_start_log) == 1
     wf_start_log = wf_start_log[0]
-    assert wf_start_log.level.lower() == 'info'
 
-    wf_end_log = ctx.model.log.list(filters=dict(msg=wf_end))
+    wf_end_log = [l for l in logs if wf_end in l.msg and l.level.lower() == 'debug']
     assert len(wf_end_log) == 1
     wf_end_log = wf_end_log[0]
-    assert wf_end_log.level.lower() == 'debug'
 
     assert (wf_start_log.created_at <
             wf_end_log.created_at <


[3/7] incubator-ariatosca git commit: ARIA-79-concurrent-modifications

Posted by mx...@apache.org.
ARIA-79-concurrent-modifications


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: 96581d9f9b00736d3c83ecda20d2e9f81073d4da
Parents: 787d7e7
Author: Dan Kilman <da...@gigaspaces.com>
Authored: Mon Jan 30 16:49:00 2017 +0200
Committer: mxmrlv <mx...@gmail.com>
Committed: Fri Feb 17 21:12:36 2017 +0200

----------------------------------------------------------------------
 aria/.pylintrc                                  |   2 +-
 aria/orchestrator/workflows/executor/process.py | 162 +++++++++++-------
 aria/storage/instrumentation.py                 |  73 +++++++--
 aria/storage/modeling/instance_elements.py      |   5 +-
 aria/storage/sql_mapi.py                        |   4 +
 aria/storage_initializer.py                     |   1 -
 tests/mock/models.py                            |   2 -
 ...process_executor_concurrent_modifications.py | 164 +++++++++++++++++++
 tests/requirements.txt                          |   3 +-
 tests/storage/test_structures.py                |   1 -
 10 files changed, 338 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/.pylintrc
----------------------------------------------------------------------
diff --git a/aria/.pylintrc b/aria/.pylintrc
index ee4d0ef..b7656a3 100644
--- a/aria/.pylintrc
+++ b/aria/.pylintrc
@@ -250,7 +250,7 @@ docstring-min-length=-1
 [ELIF]
 
 # Maximum number of nested blocks for function / method body
-max-nested-blocks=5
+max-nested-blocks=7
 
 
 [SIMILARITIES]

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/orchestrator/workflows/executor/process.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/process.py b/aria/orchestrator/workflows/executor/process.py
index 560ac43..75bbbce 100644
--- a/aria/orchestrator/workflows/executor/process.py
+++ b/aria/orchestrator/workflows/executor/process.py
@@ -53,6 +53,8 @@ _IS_WIN = os.name == 'nt'
 
 _INT_FMT = 'I'
 _INT_SIZE = struct.calcsize(_INT_FMT)
+UPDATE_TRACKED_CHANGES_FAILED_STR = \
+    'Some changes failed writing to storage. For more info refer to the log.'
 
 
 class ProcessExecutor(base.BaseExecutor):
@@ -74,6 +76,13 @@ class ProcessExecutor(base.BaseExecutor):
         # Contains reference to all currently running tasks
         self._tasks = {}
 
+        self._request_handlers = {
+            'started': self._handle_task_started_request,
+            'succeeded': self._handle_task_succeeded_request,
+            'failed': self._handle_task_failed_request,
+            'apply_tracked_changes': self._handle_apply_tracked_changes_request
+        }
+
         # Server socket used to accept task status messages from subprocesses
         self._server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         self._server_socket.bind(('localhost', 0))
@@ -131,58 +140,6 @@ class ProcessExecutor(base.BaseExecutor):
     def _remove_task(self, task_id):
         return self._tasks.pop(task_id)
 
-    def _listener(self):
-        # Notify __init__ method this thread has actually started
-        self._listener_started.put(True)
-        while not self._stopped:
-            try:
-                # Accept messages written to the server socket
-                with contextlib.closing(self._server_socket.accept()[0]) as connection:
-                    message = self._recv_message(connection)
-                    message_type = message['type']
-                    if message_type == 'closed':
-                        break
-                    task_id = message['task_id']
-                    if message_type == 'started':
-                        self._task_started(self._tasks[task_id])
-                    elif message_type == 'apply_tracked_changes':
-                        task = self._tasks[task_id]
-                        instrumentation.apply_tracked_changes(
-                            tracked_changes=message['tracked_changes'],
-                            model=task.context.model)
-                    elif message_type == 'succeeded':
-                        task = self._remove_task(task_id)
-                        instrumentation.apply_tracked_changes(
-                            tracked_changes=message['tracked_changes'],
-                            model=task.context.model)
-                        self._task_succeeded(task)
-                    elif message_type == 'failed':
-                        task = self._remove_task(task_id)
-                        instrumentation.apply_tracked_changes(
-                            tracked_changes=message['tracked_changes'],
-                            model=task.context.model)
-                        self._task_failed(task, exception=message['exception'])
-                    else:
-                        raise RuntimeError('Invalid state')
-            except BaseException as e:
-                self.logger.debug('Error in process executor listener: {0}'.format(e))
-
-    def _recv_message(self, connection):
-        message_len, = struct.unpack(_INT_FMT, self._recv_bytes(connection, _INT_SIZE))
-        return jsonpickle.loads(self._recv_bytes(connection, message_len))
-
-    @staticmethod
-    def _recv_bytes(connection, count):
-        result = io.BytesIO()
-        while True:
-            if not count:
-                return result.getvalue()
-            read = connection.recv(count)
-            if not read:
-                return result.getvalue()
-            result.write(read)
-            count -= len(read)
-
     def _check_closed(self):
         if self._stopped:
             raise RuntimeError('Executor closed')
@@ -231,6 +188,90 @@ class ProcessExecutor(base.BaseExecutor):
                 os.pathsep,
                 env.get('PYTHONPATH', ''))
 
+    def _listener(self):
+        # Notify __init__ method this thread has actually started
+        self._listener_started.put(True)
+        while not self._stopped:
+            try:
+                with self._accept_request() as (request, response):
+                    request_type = request['type']
+                    if request_type == 'closed':
+                        break
+                    request_handler = self._request_handlers.get(request_type)
+                    if not request_handler:
+                        raise RuntimeError('Invalid request type: {0}'.format(request_type))
+                    request_handler(task_id=request['task_id'], request=request, response=response)
+            except BaseException as e:
+                self.logger.debug('Error in process executor listener: {0}'.format(e))
+
+    @contextlib.contextmanager
+    def _accept_request(self):
+        with contextlib.closing(self._server_socket.accept()[0]) as connection:
+            message = _recv_message(connection)
+            response = {}
+            yield message, response
+            _send_message(connection, response)
+
+    def _handle_task_started_request(self, task_id, **kwargs):
+        self._task_started(self._tasks[task_id])
+
+    def _handle_task_succeeded_request(self, task_id, request, **kwargs):
+        task = self._remove_task(task_id)
+        try:
+            self._apply_tracked_changes(task, request)
+        except BaseException as e:
+            e.message += UPDATE_TRACKED_CHANGES_FAILED_STR
+            self._task_failed(task, exception=e)
+        else:
+            self._task_succeeded(task)
+
+    def _handle_task_failed_request(self, task_id, request, **kwargs):
+        task = self._remove_task(task_id)
+        try:
+            self._apply_tracked_changes(task, request)
+        except BaseException as e:
+            e.message += 'Task failed due to {0}.'.format(request['exception']) + \
+                         UPDATE_TRACKED_CHANGES_FAILED_STR
+            self._task_failed(task, exception=e)
+        else:
+            self._task_failed(task, exception=request['exception'])
+
+    def _handle_apply_tracked_changes_request(self, task_id, request, response):
+        task = self._tasks[task_id]
+        try:
+            self._apply_tracked_changes(task, request)
+        except BaseException as e:
+            response['exception'] = exceptions.wrap_if_needed(e)
+
+    @staticmethod
+    def _apply_tracked_changes(task, request):
+        instrumentation.apply_tracked_changes(
+            tracked_changes=request['tracked_changes'],
+            model=task.context.model)
+
+
+def _send_message(connection, message):
+    data = jsonpickle.dumps(message)
+    connection.send(struct.pack(_INT_FMT, len(data)))
+    connection.sendall(data)
+
+
+def _recv_message(connection):
+    message_len, = struct.unpack(_INT_FMT, _recv_bytes(connection, _INT_SIZE))
+    return jsonpickle.loads(_recv_bytes(connection, message_len))
+
+
+def _recv_bytes(connection, count):
+    result = io.BytesIO()
+    while True:
+        if not count:
+            return result.getvalue()
+        read = connection.recv(count)
+        if not read:
+            return result.getvalue()
+        result.write(read)
+        count -= len(read)
+
 
 class _Messenger(object):
 
@@ -261,17 +302,16 @@ class _Messenger(object):
         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         sock.connect(('localhost', self.port))
         try:
-            data = jsonpickle.dumps({
+            _send_message(sock, {
                 'type': type,
                 'task_id': self.task_id,
                 'exception': exceptions.wrap_if_needed(exception),
                 'tracked_changes': tracked_changes
             })
-            sock.send(struct.pack(_INT_FMT, len(data)))
-            sock.sendall(data)
-            # send message will block until the server side closes the connection socket
-            # because we want it to be synchronous
-            sock.recv(1)
+            response = _recv_message(sock)
+            response_exception = response.get('exception')
+            if response_exception:
+                raise response_exception
         finally:
             sock.close()
 
@@ -294,12 +334,17 @@ def _patch_session(ctx, messenger, instrument):
         messenger.apply_tracked_changes(instrument.tracked_changes)
         instrument.clear()
 
+    def patched_rollback():
+        # Rollback is performed on parent process when commit fails
+        pass
+
     # when autoflush is set to true (the default), refreshing an object will trigger
     # an auto flush by sqlalchemy, this autoflush will attempt to commit changes made so
     # far on the session. this is not the desired behavior in the subprocess
     session.autoflush = False
 
     session.commit = patched_commit
+    session.rollback = patched_rollback
     session.refresh = patched_refresh
 
 
@@ -324,7 +369,6 @@ def _main():
     # This is required for the instrumentation work properly.
     # See docstring of `remove_mutable_association_listener` for further details
     storage_type.remove_mutable_association_listener()
-
     with instrumentation.track_changes() as instrument:
         try:
             ctx = context_dict['context_cls'].deserialize_from_dict(**context_dict['context'])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/storage/instrumentation.py
----------------------------------------------------------------------
diff --git a/aria/storage/instrumentation.py b/aria/storage/instrumentation.py
index 57fe9bd..8fb9d82 100644
--- a/aria/storage/instrumentation.py
+++ b/aria/storage/instrumentation.py
@@ -14,11 +14,16 @@
 # limitations under the License.
 
 import copy
+import json
 
+import sqlalchemy
 import sqlalchemy.event
 
+from . import exceptions
+
 from .modeling import model as _model
 
+_VERSION_ID_COL = 'version'
 _STUB = object()
 _INSTRUMENTED = {
     _model.Node.runtime_properties: dict
@@ -92,6 +97,11 @@ class _Instrumentation(object):
             mapi_name = instrumented_class.__modelname__
             tracked_instances = self.tracked_changes.setdefault(mapi_name, {})
             tracked_attributes = tracked_instances.setdefault(target.id, {})
+            if hasattr(target, _VERSION_ID_COL):
+                # We want to keep track of the initial version id so it can be compared
+                # with the committed version id when the tracked changes are applied
+                tracked_attributes.setdefault(_VERSION_ID_COL,
+                                              _Value(_STUB, getattr(target, _VERSION_ID_COL)))
             for attribute_name, attribute_type in instrumented_attributes.items():
                 if attribute_name not in tracked_attributes:
                     initial = getattr(target, attribute_name)
@@ -143,7 +153,11 @@ class _Value(object):
         return self.initial == other.initial and self.current == other.current
 
     def __hash__(self):
-        return hash(self.initial) ^ hash(self.current)
+        return hash((self.initial, self.current))
+
+    @property
+    def dict(self):
+        return {'initial': self.initial, 'current': self.current}.copy()
 
 
 def apply_tracked_changes(tracked_changes, model):
@@ -153,14 +167,49 @@ def apply_tracked_changes(tracked_changes, model):
                             returned by calling ``track_changes()``
     :param model: The model storage used to actually apply the changes
     """
-    for mapi_name, tracked_instances in tracked_changes.items():
-        mapi = getattr(model, mapi_name)
-        for instance_id, tracked_attributes in tracked_instances.items():
-            instance = None
-            for attribute_name, value in tracked_attributes.items():
-                if value.initial != value.current:
-                    if not instance:
-                        instance = mapi.get(instance_id)
-                    setattr(instance, attribute_name, value.current)
-            if instance:
-                mapi.update(instance)
+    successfully_updated_changes = dict()
+    try:
+        for mapi_name, tracked_instances in tracked_changes.items():
+            successfully_updated_changes[mapi_name] = dict()
+            mapi = getattr(model, mapi_name)
+            for instance_id, tracked_attributes in tracked_instances.items():
+                successfully_updated_changes[mapi_name][instance_id] = dict()
+                instance = None
+                for attribute_name, value in tracked_attributes.items():
+                    if value.initial != value.current:
+                        if not instance:
+                            instance = mapi.get(instance_id)
+                        setattr(instance, attribute_name, value.current)
+                if instance:
+                    _validate_version_id(instance, mapi)
+                    mapi.update(instance)
+                    successfully_updated_changes[mapi_name][instance_id] = [
+                        v.dict for v in tracked_attributes.values()]
+    except BaseException:
+        for key, value in successfully_updated_changes.items():
+            if not value:
+                del successfully_updated_changes[key]
+        model.logger.error(
+            'Registering all the changes to the storage has failed. \n'
+            'The successful updates were: \n '
+            '{0}'.format(json.dumps(successfully_updated_changes, indent=4)))
+
+        raise
+
+
+def _validate_version_id(instance, mapi):
+    version_id = sqlalchemy.inspect(instance).committed_state.get(_VERSION_ID_COL)
+    # There are two version conflict code paths:
+    # 1. The instance committed state loaded already holds a newer version,
+    #    in this case, we manually raise the error
+    # 2. The UPDATE statement is executed with version validation and sqlalchemy
+    #    will raise a StateDataError if there is a version mismatch.
+    if version_id and getattr(instance, _VERSION_ID_COL) != version_id:
+        object_version_id = getattr(instance, _VERSION_ID_COL)
+        mapi._session.rollback()
+        raise exceptions.StorageError(
+            'Version conflict: committed and object {0} differ '
+            '[committed {0}={1}, object {0}={2}]'
+            .format(_VERSION_ID_COL,
+                    version_id,
+                    object_version_id))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/storage/modeling/instance_elements.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/instance_elements.py b/aria/storage/modeling/instance_elements.py
index 0666c8a..2b102f1 100644
--- a/aria/storage/modeling/instance_elements.py
+++ b/aria/storage/modeling/instance_elements.py
@@ -553,7 +553,7 @@ class PolicyBase(structure.ModelMixin):
 
     # region many-to-one relationships
     @declared_attr
-    def service_instnce(cls):
+    def service_instance(cls):
         return cls.many_to_one_relationship('service_instance')
 
     # region many-to-many relationships
@@ -851,6 +851,8 @@ class NodeBase(structure.ModelMixin):
     * :code:`relationships`: List of :class:`Relationship`
     """
     __tablename__ = 'node'
+    version = Column(Integer, nullable=False)
+    __mapper_args__ = {'version_id_col': version}
 
     __private_fields__ = ['service_instance_fk',
                           'host_fk',
@@ -878,7 +880,6 @@ class NodeBase(structure.ModelMixin):
     runtime_properties = Column(aria_types.Dict)
     scaling_groups = Column(aria_types.List)
     state = Column(Text, nullable=False)
-    version = Column(Integer, default=1)
 
     @declared_attr
     def plugins(cls):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/storage/sql_mapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/sql_mapi.py b/aria/storage/sql_mapi.py
index b80ac8e..2711aee 100644
--- a/aria/storage/sql_mapi.py
+++ b/aria/storage/sql_mapi.py
@@ -23,6 +23,7 @@ from sqlalchemy import (
     orm,
 )
 from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy.orm.exc import StaleDataError
 
 from aria.utils.collections import OrderedDict
 from . import (
@@ -162,6 +163,9 @@ class SQLAlchemyModelAPI(api.ModelAPI):
         """
         try:
             self._session.commit()
+        except StaleDataError as e:
+            self._session.rollback()
+            raise exceptions.StorageError('Version conflict: {0}'.format(str(e)))
         except (SQLAlchemyError, ValueError) as e:
             self._session.rollback()
             raise exceptions.StorageError('SQL Storage error: {0}'.format(str(e)))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/aria/storage_initializer.py
----------------------------------------------------------------------
diff --git a/aria/storage_initializer.py b/aria/storage_initializer.py
index aea5ec8..175ec22 100644
--- a/aria/storage_initializer.py
+++ b/aria/storage_initializer.py
@@ -95,7 +95,6 @@ def _create_node_instance(service_instance, node, node_model):
         service_instance=service_instance,
         name=node_model.id,
         runtime_properties={},
-        version=None,
         node_template=node,
         state='',
         scaling_groups=[]

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/tests/mock/models.py
----------------------------------------------------------------------
diff --git a/tests/mock/models.py b/tests/mock/models.py
index 047526a..301fc01 100644
--- a/tests/mock/models.py
+++ b/tests/mock/models.py
@@ -50,7 +50,6 @@ def get_dependency_node_instance(dependency_node, deployment):
         name=DEPENDENCY_NODE_INSTANCE_NAME,
         service_instance=deployment,
         runtime_properties={'ip': '1.1.1.1'},
-        version=None,
         node_template=dependency_node,
         state='',
         scaling_groups=[]
@@ -96,7 +95,6 @@ def get_dependent_node_instance(dependent_node, deployment):
         name=DEPENDENT_NODE_INSTANCE_NAME,
         service_instance=deployment,
         runtime_properties={},
-        version=None,
         node_template=dependent_node,
         state='',
         scaling_groups=[],

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py b/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py
new file mode 100644
index 0000000..ad3cb76
--- /dev/null
+++ b/tests/orchestrator/workflows/executor/test_process_executor_concurrent_modifications.py
@@ -0,0 +1,164 @@
+# 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.
+import time
+
+import fasteners
+import pytest
+
+from aria.storage.exceptions import StorageError
+from aria.orchestrator import events
+from aria.orchestrator.workflows.exceptions import ExecutorException
+from aria.orchestrator.workflows import api
+from aria.orchestrator.workflows.executor import process
+from aria.orchestrator import workflow, operation
+
+import tests
+from tests.orchestrator.context import execute as execute_workflow
+from tests.orchestrator.workflows.helpers import events_collector
+from tests import mock
+from tests import storage
+
+
+def test_concurrent_modification_on_task_succeeded(context, executor, lock_files):
+    _test(context, executor, lock_files, _test_task_succeeded, expected_failure=True)
+
+
+@operation
+def _test_task_succeeded(ctx, lock_files, key, first_value, second_value):
+    _concurrent_update(lock_files, ctx.node, key, first_value, second_value)
+
+
+def test_concurrent_modification_on_task_failed(context, executor, lock_files):
+    _test(context, executor, lock_files, _test_task_failed, expected_failure=True)
+
+
+@operation
+def _test_task_failed(ctx, lock_files, key, first_value, second_value):
+    first = _concurrent_update(lock_files, ctx.node, key, first_value, second_value)
+    if not first:
+        raise RuntimeError('MESSAGE')
+
+
+def test_concurrent_modification_on_update_and_refresh(context, executor, lock_files):
+    _test(context, executor, lock_files, _test_update_and_refresh, expected_failure=False)
+
+
+@operation
+def _test_update_and_refresh(ctx, lock_files, key, first_value, second_value):
+    node = ctx.node
+    first = _concurrent_update(lock_files, node, key, first_value, second_value)
+    if not first:
+        try:
+            ctx.model.node.update(node)
+        except StorageError as e:
+            assert 'Version conflict' in str(e)
+            ctx.model.node.refresh(node)
+        else:
+            raise RuntimeError('Unexpected')
+
+
+def _test(context, executor, lock_files, func, expected_failure):
+    def _node(ctx):
+        return ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
+
+    op_name = mock.operations.NODE_OPERATIONS_INSTALL[0]
+
+    key = 'key'
+    first_value = 'value1'
+    second_value = 'value2'
+    inputs = {
+        'lock_files': lock_files,
+        'key': key,
+        'first_value': first_value,
+        'second_value': second_value
+    }
+
+    node = _node(context)
+    node.interfaces = [mock.models.get_interface(
+        op_name,
+        operation_kwargs=dict(implementation='{0}.{1}'.format(__name__, func.__name__))
+    )]
+    context.model.node.update(node)
+
+    @workflow
+    def mock_workflow(graph, **_):
+        graph.add_tasks(
+            api.task.OperationTask.node(instance=node, name=op_name, inputs=inputs),
+            api.task.OperationTask.node(instance=node, name=op_name, inputs=inputs)
+        )
+
+    signal = events.on_failure_task_signal
+    with events_collector(signal) as collected:
+        try:
+            execute_workflow(mock_workflow, context, executor)
+        except ExecutorException:
+            pass
+
+    props = _node(context).runtime_properties
+    assert props[key] == first_value
+
+    exceptions = [event['kwargs']['exception'] for event in collected.get(signal, [])]
+    if expected_failure:
+        assert exceptions
+        exception = exceptions[-1]
+        assert isinstance(exception, StorageError)
+        assert 'Version conflict' in str(exception)
+    else:
+        assert not exceptions
+
+
+@pytest.fixture
+def executor():
+    result = process.ProcessExecutor(python_path=[tests.ROOT_DIR])
+    yield result
+    result.close()
+
+
+@pytest.fixture
+def context(tmpdir):
+    result = mock.context.simple(str(tmpdir))
+    yield result
+    storage.release_sqlite_storage(result.model)
+
+
+@pytest.fixture
+def lock_files(tmpdir):
+    return str(tmpdir.join('first_lock_file')), str(tmpdir.join('second_lock_file'))
+
+
+def _concurrent_update(lock_files, node, key, first_value, second_value):
+
+    locker1 = fasteners.InterProcessLock(lock_files[0])
+    locker2 = fasteners.InterProcessLock(lock_files[1])
+
+    first = locker1.acquire(blocking=False)
+
+    if first:
+        # Give chance for both processes to acquire locks
+        while locker2.acquire(blocking=False):
+            locker2.release()
+            time.sleep(0.01)
+    else:
+        locker2.acquire()
+
+    node.runtime_properties[key] = first_value if first else second_value
+
+    if first:
+        locker1.release()
+    else:
+        with locker1:
+            locker2.release()
+
+    return first

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/tests/requirements.txt
----------------------------------------------------------------------
diff --git a/tests/requirements.txt b/tests/requirements.txt
index 0e4740f..2f0245a 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -11,8 +11,9 @@
 # limitations under the License.
 
 testtools
+fasteners==0.13.0
 mock==1.0.1
 pylint==1.6.4
 pytest==3.0.2
 pytest-cov==2.3.1
-pytest-mock==1.2
\ No newline at end of file
+pytest-mock==1.2

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/96581d9f/tests/storage/test_structures.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_structures.py b/tests/storage/test_structures.py
index 30f0064..666256e 100644
--- a/tests/storage/test_structures.py
+++ b/tests/storage/test_structures.py
@@ -125,7 +125,6 @@ def test_relationship_model_ordering(context):
         name='new_node_instance',
         runtime_properties={},
         service_instance=service_instance,
-        version=None,
         node_template=new_node_template,
         state='',
         scaling_groups=[]


[5/7] incubator-ariatosca git commit: wip

Posted by mx...@apache.org.
wip


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: f881d0be04500893e2a0650e5927062858f37314
Parents: d347212
Author: mxmrlv <mx...@gmail.com>
Authored: Mon Feb 13 12:28:27 2017 +0200
Committer: mxmrlv <mx...@gmail.com>
Committed: Sun Feb 19 10:38:30 2017 +0200

----------------------------------------------------------------------
 aria/__init__.py                                |  3 +-
 aria/logger.py                                  | 43 +++++++++++-
 aria/orchestrator/context/common.py             | 22 +++++-
 aria/orchestrator/workflows/core/engine.py      |  5 ++
 aria/storage/__init__.py                        |  6 --
 aria/storage/core.py                            | 16 +++--
 aria/storage/modeling/model.py                  |  4 ++
 aria/storage/modeling/orchestrator_elements.py  | 12 ++++
 tests/mock/topology.py                          |  2 +-
 tests/orchestrator/context/test_operation.py    | 74 ++++++++++++++++++--
 .../execution_plugin/test_common.py             |  2 +-
 tests/orchestrator/execution_plugin/test_ssh.py |  2 +-
 .../workflows/executor/test_process_executor.py |  6 +-
 tests/storage/__init__.py                       | 23 +++---
 tests/storage/test_instrumentation.py           |  6 +-
 tests/storage/test_structures.py                |  2 +-
 16 files changed, 182 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/__init__.py
----------------------------------------------------------------------
diff --git a/aria/__init__.py b/aria/__init__.py
index 18eaa56..43529f0 100644
--- a/aria/__init__.py
+++ b/aria/__init__.py
@@ -97,7 +97,8 @@ def application_model_storage(api, api_kwargs=None, initiator=None, initiator_kw
         storage.modeling.model.ServiceInstanceUpdateStep,
         storage.modeling.model.ServiceInstanceModification,
         storage.modeling.model.Plugin,
-        storage.modeling.model.Task
+        storage.modeling.model.Task,
+        storage.modeling.model.Log
     ]
     return storage.ModelStorage(api_cls=api,
                                 api_kwargs=api_kwargs,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index 0002cb5..ebe01ba 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -17,8 +17,10 @@
 Logging related mixins and functions
 """
 
+
 import logging
-from logging.handlers import RotatingFileHandler
+from logging import handlers as logging_handlers
+from datetime import datetime
 
 _base_logger = logging.getLogger('aria')
 
@@ -124,7 +126,7 @@ def create_file_log_handler(
     """
     Create a logging.handlers.RotatingFileHandler
     """
-    rotating_file = RotatingFileHandler(
+    rotating_file = logging_handlers.RotatingFileHandler(
         filename=file_path,
         maxBytes=max_bytes,
         backupCount=backup_count,
@@ -135,5 +137,42 @@ def create_file_log_handler(
     return rotating_file
 
 
+class SQLAlchemyHandler(logging.Handler):
+    def __init__(self, session, engine, log_cls, **kwargs):
+        self._session = session
+        self._engine = engine
+        self._cls = log_cls
+        super(SQLAlchemyHandler, self).__init__(**kwargs)
+
+    def emit(self, record):
+        log = self._cls(
+            logger=record.name,
+            level=record.levelname,
+            msg=record.msg,
+            created_at=datetime.utcnow()
+        )
+        self._session.add(log)
+        self._session.commit()
+
+
+class _SQLAlchemyHandlerFactory(object):
+    # prevents circular imports
+    from aria.storage.modeling.model import Log
+
+    def __init__(self):
+        self._handler = None
+
+    def __call__(self, session, engine, model_cls=Log, level=logging.DEBUG):
+        if self._handler is None or not self._is_eq(session, engine, model_cls):
+            self._handler = SQLAlchemyHandler(session, engine, model_cls, level=level)
+        return self._handler
+
+    def _is_eq(self, session, engine, model_cls):
+        return all([self._handler._session == session,
+                    self._handler._engine == engine,
+                    self._handler._cls == model_cls])
+
+create_sqla_log_handler = _SQLAlchemyHandlerFactory()
+
 _default_file_formatter = logging.Formatter(
     '%(asctime)s [%(name)s:%(levelname)s] %(message)s <%(pathname)s:%(lineno)d>')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index 37482cf..d5ef42c 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -17,13 +17,15 @@ A common context for both workflow and operation
 """
 from uuid import uuid4
 
+import logging
+
 import jinja2
 
 from aria import logger
 from aria.storage import exceptions
 
 
-class BaseContext(logger.LoggerMixin):
+class BaseContext(object):
     """
     Base context object for workflow and operation
     """
@@ -34,6 +36,7 @@ class BaseContext(logger.LoggerMixin):
             service_instance_id,
             model_storage,
             resource_storage,
+            ctx_logger=None,
             workdir=None,
             **kwargs):
         super(BaseContext, self).__init__(**kwargs)
@@ -42,8 +45,21 @@ class BaseContext(logger.LoggerMixin):
         self._model = model_storage
         self._resource = resource_storage
         self._service_instance_id = service_instance_id
+        self._logger = self._init_logger(ctx_logger)
         self._workdir = workdir
 
+    def _init_logger(self, ctx_logger=None):
+        ctx_logger = ctx_logger or logging.getLogger('aria_ctx')
+
+        # A handler should be registered only once.
+        sqla_handler = logger.create_sqla_log_handler(**self._model.all_api_kwargs)
+        if sqla_handler not in ctx_logger.handlers:
+            ctx_logger.addHandler(sqla_handler)
+
+        ctx_logger.setLevel(logging.DEBUG)
+
+        return ctx_logger
+
     def __repr__(self):
         return (
             '{name}(name={self.name}, '
@@ -51,6 +67,10 @@ class BaseContext(logger.LoggerMixin):
             .format(name=self.__class__.__name__, self=self))
 
     @property
+    def logger(self):
+        return self._logger
+
+    @property
     def model(self):
         """
         Access to the model storage

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/orchestrator/workflows/core/engine.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/engine.py b/aria/orchestrator/workflows/core/engine.py
index 55b4159..7148dd1 100644
--- a/aria/orchestrator/workflows/core/engine.py
+++ b/aria/orchestrator/workflows/core/engine.py
@@ -71,6 +71,11 @@ class Engine(logger.LoggerMixin):
         except BaseException as e:
             events.on_failure_workflow_signal.send(self._workflow_context, exception=e)
             raise
+        finally:
+            # Each context creates its own handlers an assign them to the logger.
+            # This enables easy serialization. In order the handlers would not overlap, we
+            # need to clear them each execution.
+            self._workflow_context.logger.handlers = []
 
     def cancel_execution(self):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/storage/__init__.py
----------------------------------------------------------------------
diff --git a/aria/storage/__init__.py b/aria/storage/__init__.py
index eaadc7e..b76bdf2 100644
--- a/aria/storage/__init__.py
+++ b/aria/storage/__init__.py
@@ -42,12 +42,6 @@ from .core import (
     ModelStorage,
     ResourceStorage,
 )
-from .modeling import (
-    structure,
-    model,
-    model_base,
-    type
-)
 from . import (
     exceptions,
     api,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/storage/core.py
----------------------------------------------------------------------
diff --git a/aria/storage/core.py b/aria/storage/core.py
index 0e189e6..7d70070 100644
--- a/aria/storage/core.py
+++ b/aria/storage/core.py
@@ -84,6 +84,12 @@ class Storage(LoggerMixin):
         self.logger.debug('{name} object is ready: {0!r}'.format(
             self, name=self.__class__.__name__))
 
+    @property
+    def all_api_kwargs(self):
+        kwargs = self._api_kwargs.copy()
+        kwargs.update(self._additional_api_kwargs)
+        return kwargs
+
     def __repr__(self):
         return '{name}(api={self.api})'.format(name=self.__class__.__name__, self=self)
 
@@ -121,9 +127,7 @@ class ResourceStorage(Storage):
         :param name:
         :return:
         """
-        kwargs = self._api_kwargs.copy()
-        kwargs.update(self._additional_api_kwargs)
-        self.registered[name] = self.api(name=name, **kwargs)
+        self.registered[name] = self.api(name=name, **self.all_api_kwargs)
         self.registered[name].create()
         self.logger.debug('setup {name} in storage {self!r}'.format(name=name, self=self))
 
@@ -148,9 +152,9 @@ class ModelStorage(Storage):
             self.logger.debug('{name} in already storage {self!r}'.format(name=model_name,
                                                                           self=self))
             return
-        kwargs = self._api_kwargs.copy()
-        kwargs.update(self._additional_api_kwargs)
-        self.registered[model_name] = self.api(name=model_name, model_cls=model_cls, **kwargs)
+        self.registered[model_name] = self.api(name=model_name,
+                                               model_cls=model_cls,
+                                               **self.all_api_kwargs)
         self.registered[model_name].create()
         self.logger.debug('setup {name} in storage {self!r}'.format(name=model_name, self=self))
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/storage/modeling/model.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/model.py b/aria/storage/modeling/model.py
index 62b90b3..cf7d933 100644
--- a/aria/storage/modeling/model.py
+++ b/aria/storage/modeling/model.py
@@ -216,4 +216,8 @@ class Plugin(aria_declarative_base, orchestrator_elements.PluginBase):
 
 class Task(aria_declarative_base, orchestrator_elements.TaskBase):
     pass
+
+
+class Log(aria_declarative_base, orchestrator_elements.LogBase):
+    pass
 # endregion

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/aria/storage/modeling/orchestrator_elements.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/orchestrator_elements.py b/aria/storage/modeling/orchestrator_elements.py
index 5f7a3f2..8efc147 100644
--- a/aria/storage/modeling/orchestrator_elements.py
+++ b/aria/storage/modeling/orchestrator_elements.py
@@ -466,3 +466,15 @@ class TaskBase(ModelMixin):
     @staticmethod
     def retry(message=None, retry_interval=None):
         raise TaskRetryException(message, retry_interval=retry_interval)
+
+
+class LogBase(ModelMixin):
+    __tablename__ = 'log'
+
+    logger = Column(String)
+    level = Column(String)
+    msg = Column(String)
+    created_at = Column(DateTime, index=True)
+
+    def __repr__(self):
+        return "<Log: {0} - {1}>".format(self.created_at, self.msg[:50])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/mock/topology.py
----------------------------------------------------------------------
diff --git a/tests/mock/topology.py b/tests/mock/topology.py
index b04fb46..d3e8b7b 100644
--- a/tests/mock/topology.py
+++ b/tests/mock/topology.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from aria.storage import model
+from aria.storage.modeling import model
 
 from . import models
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index 3f39979..08d360c 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -38,8 +38,7 @@ global_test_holder = {}
 @pytest.fixture
 def ctx(tmpdir):
     context = mock.context.simple(
-        str(tmpdir.join('workdir')),
-        inmemory=True,
+        str(tmpdir),
         context_kwargs=dict(workdir=str(tmpdir.join('workdir')))
     )
     yield context
@@ -61,7 +60,7 @@ def test_node_operation_task_execution(ctx, executor):
     node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
     interface = mock.models.get_interface(
         operation_name,
-        operation_kwargs=dict(implementation=op_path(my_operation, module_path=__name__))
+        operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__))
     )
     node.interfaces = [interface]
     ctx.model.node.update(node)
@@ -102,7 +101,7 @@ def test_relationship_operation_task_execution(ctx, executor):
 
     interface = mock.models.get_interface(
         operation_name=operation_name,
-        operation_kwargs=dict(implementation=op_path(my_operation, module_path=__name__)),
+        operation_kwargs=dict(implementation=op_path(basic_operation, module_path=__name__)),
         edge='source'
     )
 
@@ -210,8 +209,73 @@ def test_plugin_workdir(ctx, executor, tmpdir):
     assert expected_file.read() == content
 
 
+def test_operation_logging(ctx, executor):
+    operation_name = 'aria.interfaces.lifecycle.create'
+
+    node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
+    interface = mock.models.get_interface(
+        operation_name,
+        operation_kwargs=dict(implementation=op_path(logged_operation, module_path=__name__))
+    )
+    node.interfaces = [interface]
+    ctx.model.node.update(node)
+
+    wf_start = 'wf_start'
+    wf_end = 'wf_end'
+
+    inputs = {
+        'op_start': 'op_start',
+        'op_end': 'op_end',
+    }
+
+    @workflow
+    def basic_workflow(graph, ctx, **_):
+        ctx.logger.info(wf_start)
+        graph.add_tasks(
+            api.task.OperationTask.node(
+                name=operation_name,
+                instance=node,
+                inputs=inputs
+            )
+        )
+        ctx.logger.debug(wf_end)
+
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+
+    op_start_log = ctx.model.log.list(filters=dict(msg=inputs['op_start']))
+    assert len(op_start_log) == 1
+    op_start_log = op_start_log[0]
+    assert op_start_log.level.lower() == 'info'
+
+    op_end_log = ctx.model.log.list(filters=dict(msg=inputs['op_end']))
+    assert len(op_end_log) == 1
+    op_end_log = op_end_log[0]
+    assert op_end_log.level.lower() == 'debug'
+
+    wf_start_log = ctx.model.log.list(filters=dict(msg=wf_start))
+    assert len(wf_start_log) == 1
+    wf_start_log = wf_start_log[0]
+    assert wf_start_log.level.lower() == 'info'
+
+    wf_end_log = ctx.model.log.list(filters=dict(msg=wf_end))
+    assert len(wf_end_log) == 1
+    wf_end_log = wf_end_log[0]
+    assert wf_end_log.level.lower() == 'debug'
+
+    assert (wf_start_log.created_at <
+            wf_end_log.created_at <
+            op_start_log.created_at <
+            op_end_log.created_at)
+
+
+@operation
+def logged_operation(ctx, **_):
+    ctx.logger.info(ctx.task.inputs['op_start'])
+    ctx.logger.debug(ctx.task.inputs['op_end'])
+
+
 @operation
-def my_operation(ctx, **_):
+def basic_operation(ctx, **_):
     global_test_holder[ctx.name] = ctx
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/orchestrator/execution_plugin/test_common.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_common.py b/tests/orchestrator/execution_plugin/test_common.py
index 1048c27..151b996 100644
--- a/tests/orchestrator/execution_plugin/test_common.py
+++ b/tests/orchestrator/execution_plugin/test_common.py
@@ -18,7 +18,7 @@ from collections import namedtuple
 import requests
 import pytest
 
-from aria.storage import model
+from aria.storage.modeling import model
 from aria.orchestrator import exceptions
 from aria.orchestrator.execution_plugin import common
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/orchestrator/execution_plugin/test_ssh.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_ssh.py b/tests/orchestrator/execution_plugin/test_ssh.py
index 2e270bb..0981b61 100644
--- a/tests/orchestrator/execution_plugin/test_ssh.py
+++ b/tests/orchestrator/execution_plugin/test_ssh.py
@@ -24,7 +24,7 @@ import fabric.api
 from fabric.contrib import files
 from fabric import context_managers
 
-from aria.storage import model
+from aria.storage.modeling import model
 from aria.orchestrator import events
 from aria.orchestrator import workflow
 from aria.orchestrator.workflows import api

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/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 e904eb3..1bdc1e4 100644
--- a/tests/orchestrator/workflows/executor/test_process_executor.py
+++ b/tests/orchestrator/workflows/executor/test_process_executor.py
@@ -22,10 +22,8 @@ from contextlib import contextmanager
 import pytest
 
 from aria import application_model_storage
-from aria.storage import (
-    model as aria_model,
-    sql_mapi
-)
+from aria.storage import sql_mapi
+from aria.storage.modeling import model as aria_model
 from aria.orchestrator import (
     events,
     plugin

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/storage/__init__.py
----------------------------------------------------------------------
diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py
index 4278831..5323d01 100644
--- a/tests/storage/__init__.py
+++ b/tests/storage/__init__.py
@@ -12,8 +12,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-import os
-import platform
+
 from shutil import rmtree
 from tempfile import mkdtemp
 
@@ -23,19 +22,19 @@ from sqlalchemy import (
     Column,
     Text,
     Integer,
-    pool
+    pool,
+    MetaData
 )
 
 
-from aria.storage import (
+from aria.storage.modeling import (
     model,
-    type as aria_type,
     structure,
-    modeling
+    type as aria_type
 )
 
 
-class MockModel(model.aria_declarative_base, structure.ModelMixin): #pylint: disable=abstract-method
+class MockModel(structure.ModelMixin, model.aria_declarative_base): #pylint: disable=abstract-method
     __tablename__ = 'mock_model'
     model_dict = Column(aria_type.Dict)
     model_list = Column(aria_type.List)
@@ -58,14 +57,8 @@ def release_sqlite_storage(storage):
     :param storage:
     :return:
     """
-    mapis = storage.registered.values()
-
-    if mapis:
-        for session in set(mapi._session for mapi in mapis):
-            session.rollback()
-            session.close()
-        for engine in set(mapi._engine for mapi in mapis):
-            model.aria_declarative_base.metadata.drop_all(engine)
+    storage.all_api_kwargs['session'].close()
+    MetaData(bind=storage.all_api_kwargs['engine']).drop_all()
 
 
 def init_inmemory_model_storage():

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/storage/test_instrumentation.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_instrumentation.py b/tests/storage/test_instrumentation.py
index 08d5ae0..7f0eb02 100644
--- a/tests/storage/test_instrumentation.py
+++ b/tests/storage/test_instrumentation.py
@@ -17,13 +17,15 @@ import pytest
 from sqlalchemy import Column, Text, Integer, event
 
 from aria.storage import (
-    structure,
     ModelStorage,
     sql_mapi,
     instrumentation,
     exceptions,
+)
+from aria.storage.modeling import (
+    model,
     type as aria_type,
-    model
+    structure,
 )
 from ..storage import release_sqlite_storage, init_inmemory_model_storage
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f881d0be/tests/storage/test_structures.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_structures.py b/tests/storage/test_structures.py
index 666256e..27e99d7 100644
--- a/tests/storage/test_structures.py
+++ b/tests/storage/test_structures.py
@@ -21,9 +21,9 @@ from aria.storage import (
     ModelStorage,
     sql_mapi,
     exceptions,
-    type,
     modeling,
 )
+from aria.storage.modeling import type
 
 from ..storage import release_sqlite_storage, structure, init_inmemory_model_storage
 from . import MockModel


[4/7] incubator-ariatosca git commit: ARIA-108 Add API for deleting a resource for resource storage

Posted by mx...@apache.org.
ARIA-108 Add API for deleting a resource for resource storage


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: d347212289e0427f06a6d08097a453c3f0449e4b
Parents: 96581d9
Author: Ran Ziv <ra...@gigaspaces.com>
Authored: Thu Feb 16 16:38:51 2017 +0200
Committer: Ran Ziv <ra...@gigaspaces.com>
Committed: Sat Feb 18 13:01:13 2017 +0200

----------------------------------------------------------------------
 aria/storage/api.py                    | 15 ++++-
 aria/storage/filesystem_rapi.py        | 41 ++++++++-----
 tests/storage/test_resource_storage.py | 90 ++++++++++++++++++++++++++++-
 3 files changed, 129 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d3472122/aria/storage/api.py
----------------------------------------------------------------------
diff --git a/aria/storage/api.py b/aria/storage/api.py
index 09a4dd9..ed8a2ff 100644
--- a/aria/storage/api.py
+++ b/aria/storage/api.py
@@ -135,7 +135,7 @@ class ResourceAPI(StorageAPI):
         """
         return self._name
 
-    def read(self, entry_id, path=None, **kwargs):
+    def read(self, entry_id, path, **kwargs):
         """
         Get a bytesteam from the storage.
 
@@ -144,7 +144,18 @@ class ResourceAPI(StorageAPI):
         :param kwargs:
         :return:
         """
-        raise NotImplementedError('Subclass must implement abstract data method')
+        raise NotImplementedError('Subclass must implement abstract read method')
+
+    def delete(self, entry_id, path, **kwargs):
+        """
+        Delete a resource from the storage.
+
+        :param entry_id:
+        :param path:
+        :param kwargs:
+        :return:
+        """
+        raise NotImplementedError('Subclass must implement abstract delete method')
 
     def download(self, entry_id, destination, path=None, **kwargs):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d3472122/aria/storage/filesystem_rapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/filesystem_rapi.py b/aria/storage/filesystem_rapi.py
index 6693dbd..3ddc520 100644
--- a/aria/storage/filesystem_rapi.py
+++ b/aria/storage/filesystem_rapi.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-SQLalchemy based RAPI
+File system based RAPI
 """
 import os
 import shutil
@@ -92,14 +92,13 @@ class FileSystemResourceAPI(api.ResourceAPI):
         except (OSError, IOError):
             pass
 
-    def read(self, entry_id, path=None, **_):
+    def read(self, entry_id, path, **_):
         """
         Retrieve the content of a file system storage resource.
 
-        :param str entry_type: the type of the entry.
         :param str entry_id: the id of the entry.
-        :param str path: a path to a specific resource.
-        :return: the content of the file
+        :param str path: a path to the specific resource to read.
+        :return: the content of the file.
         :rtype: bytes
         """
         resource_relative_path = os.path.join(self.name, entry_id, path or '')
@@ -110,7 +109,9 @@ class FileSystemResourceAPI(api.ResourceAPI):
         if not os.path.isfile(resource):
             resources = os.listdir(resource)
             if len(resources) != 1:
-                raise exceptions.StorageError('No resource in path: {0}'.format(resource))
+                raise exceptions.StorageError(
+                    'Failed to read {0}; Reading a directory is '
+                    'only allowed when it contains a single resource'.format(resource))
             resource = os.path.join(resource, resources[0])
         with open(resource, 'rb') as resource_file:
             return resource_file.read()
@@ -119,10 +120,9 @@ class FileSystemResourceAPI(api.ResourceAPI):
         """
         Download a specific file or dir from the file system resource storage.
 
-        :param str entry_type: the name of the entry.
-        :param str entry_id: the id of the entry
-        :param str destination: the destination of the files.
-        :param str path: a path on the remote machine relative to the root of the entry.
+        :param str entry_id: the id of the entry.
+        :param str destination: the destination to download to
+        :param str path: the path to download relative to the root of the entry (otherwise all).
         """
         resource_relative_path = os.path.join(self.name, entry_id, path or '')
         resource = os.path.join(self.directory, resource_relative_path)
@@ -138,9 +138,8 @@ class FileSystemResourceAPI(api.ResourceAPI):
         """
         Uploads a specific file or dir to the file system resource storage.
 
-        :param str entry_type: the name of the entry.
-        :param str entry_id: the id of the entry
-        :param source: the source of  the files to upload.
+        :param str entry_id: the id of the entry.
+        :param source: the source of the files to upload.
         :param path: the destination of the file/s relative to the entry root dir.
         """
         resource_directory = os.path.join(self.directory, self.name, entry_id)
@@ -151,3 +150,19 @@ class FileSystemResourceAPI(api.ResourceAPI):
             shutil.copy2(source, destination)
         else:
             dir_util.copy_tree(source, destination)                                       # pylint: disable=no-member
+
+    def delete(self, entry_id, path=None, **_):
+        """
+        Deletes a file system storage resource.
+
+        :param str entry_id: the id of the entry.
+        :param str path: a path to delete relative to the root of the entry (otherwise all).
+        """
+        destination = os.path.join(self.directory, self.name, entry_id, path or '')
+        if os.path.exists(destination):
+            if os.path.isfile(destination):
+                os.remove(destination)
+            else:
+                shutil.rmtree(destination)
+            return True
+        return False

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d3472122/tests/storage/test_resource_storage.py
----------------------------------------------------------------------
diff --git a/tests/storage/test_resource_storage.py b/tests/storage/test_resource_storage.py
index 9b5f782..4d01a88 100644
--- a/tests/storage/test_resource_storage.py
+++ b/tests/storage/test_resource_storage.py
@@ -111,7 +111,9 @@ class TestResourceStorage(TestFileSystem):
         tmpfile_path = tempfile.mkstemp(suffix=self.__class__.__name__, dir=self.path)[1]
         self._upload(storage, tmpfile_path, 'blueprint_id')
 
-        assert storage.blueprint.read(entry_id='blueprint_id') == 'fake context'
+        assert storage.blueprint.read(
+            entry_id='blueprint_id',
+            path=os.path.basename(tmpfile_path)) == 'fake context'
 
     def test_upload_dir(self):
         storage = self._create_storage()
@@ -188,4 +190,88 @@ class TestResourceStorage(TestFileSystem):
         storage.blueprint.upload(entry_id='blueprint_id', source=tmp_dir)
 
         with pytest.raises(exceptions.StorageError):
-            storage.blueprint.read(entry_id='blueprint_id')
+            storage.blueprint.read(entry_id='blueprint_id', path='')
+
+    def test_delete_resource(self):
+        storage = self._create_storage()
+        self._create(storage)
+        tmpfile_path = tempfile.mkstemp(suffix=self.__class__.__name__, dir=self.path)[1]
+        self._upload(storage, tmpfile_path, 'blueprint_id')
+        tmpfile2_path = tempfile.mkstemp(suffix=self.__class__.__name__, dir=self.path)[1]
+        self._upload(storage, tmpfile2_path, 'blueprint_id')
+
+        # deleting the first resource and expecting an error on read
+        storage.blueprint.delete(entry_id='blueprint_id', path=os.path.basename(tmpfile_path))
+        with pytest.raises(exceptions.StorageError):
+            storage.blueprint.read(entry_id='blueprint_id', path=os.path.basename(tmpfile_path))
+        # the second resource should still be available for reading
+        assert storage.blueprint.read(
+            entry_id='blueprint_id',
+            path=os.path.basename(tmpfile2_path)) == 'fake context'
+
+    def test_delete_directory(self):
+        storage = self._create_storage()
+        self._create(storage)
+        temp_destination_dir = tempfile.mkdtemp(dir=self.path)
+
+        tmp_dir = tempfile.mkdtemp(suffix=self.__class__.__name__, dir=self.path)
+        second_level_tmp_dir = tempfile.mkdtemp(dir=tmp_dir)
+        tmp_filename = tempfile.mkstemp(dir=second_level_tmp_dir)[1]
+        self._upload_dir(storage, tmp_dir, tmp_filename, id='blueprint_id')
+        file_path_in_dir = os.path.join(
+            os.path.basename(second_level_tmp_dir),
+            os.path.basename(tmp_filename))
+
+        # should be able to read the file and download the directory..
+        assert storage.blueprint.read(
+            entry_id='blueprint_id',
+            path=file_path_in_dir) == 'fake context'
+        storage.blueprint.download(
+            entry_id='blueprint_id',
+            path=os.path.basename(second_level_tmp_dir),
+            destination=temp_destination_dir)
+
+        # after deletion, the file and directory should both be gone
+        storage.blueprint.delete(
+            entry_id='blueprint_id',
+            path=os.path.basename(second_level_tmp_dir))
+        with pytest.raises(exceptions.StorageError):
+            assert storage.blueprint.read(
+                entry_id='blueprint_id',
+                path=file_path_in_dir) == 'fake context'
+        with pytest.raises(exceptions.StorageError):
+            storage.blueprint.download(
+                entry_id='blueprint_id',
+                path=os.path.basename(second_level_tmp_dir),
+                destination=temp_destination_dir)
+
+    def test_delete_all_resources(self):
+        storage = self._create_storage()
+        self._create(storage)
+        temp_destination_dir = tempfile.mkdtemp(dir=self.path)
+
+        tmp_dir = tempfile.mkdtemp(suffix=self.__class__.__name__, dir=self.path)
+        second_level_tmp_dir = tempfile.mkdtemp(dir=tmp_dir)
+        tmp_filename = tempfile.mkstemp(dir=second_level_tmp_dir)[1]
+        self._upload_dir(storage, tmp_dir, tmp_filename, id='blueprint_id')
+        file_path_in_dir = os.path.join(
+            os.path.basename(second_level_tmp_dir),
+            os.path.basename(tmp_filename))
+
+        # deleting without specifying a path - delete all resources of this entry
+        storage.blueprint.delete(entry_id='blueprint_id')
+        with pytest.raises(exceptions.StorageError):
+            assert storage.blueprint.read(
+                entry_id='blueprint_id',
+                path=file_path_in_dir) == 'fake context'
+        with pytest.raises(exceptions.StorageError):
+            storage.blueprint.download(
+                entry_id='blueprint_id',
+                path=os.path.basename(second_level_tmp_dir),
+                destination=temp_destination_dir)
+
+    def test_delete_nonexisting_resource(self):
+        storage = self._create_storage()
+        self._create(storage)
+        # deleting a nonexisting resource - no effect is expected to happen
+        assert storage.blueprint.delete(entry_id='blueprint_id', path='fake-file') is False


[7/7] incubator-ariatosca git commit: wip

Posted by mx...@apache.org.
wip


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

Branch: refs/heads/ARIA-106-Create-sqla-logging-handler
Commit: a9bd63da29ac846a892a6758a790dfd26b627db7
Parents: c3f4501
Author: mxmrlv <mx...@gmail.com>
Authored: Sun Feb 19 19:03:01 2017 +0200
Committer: mxmrlv <mx...@gmail.com>
Committed: Sun Feb 19 19:03:01 2017 +0200

----------------------------------------------------------------------
 aria/logger.py                                  | 25 +++----
 aria/orchestrator/context/common.py             | 70 +++++++++++---------
 aria/orchestrator/context/operation.py          | 17 +++--
 aria/orchestrator/context/workflow.py           |  5 +-
 aria/orchestrator/decorators.py                 | 10 +--
 .../orchestrator/execution_plugin/operations.py |  4 +-
 aria/orchestrator/runner.py                     |  4 --
 aria/orchestrator/workflows/core/engine.py      |  5 --
 aria/orchestrator/workflows/core/task.py        | 11 ++-
 aria/orchestrator/workflows/executor/thread.py  | 17 ++---
 aria/storage/__init__.py                        |  1 -
 aria/storage/core.py                            |  4 +-
 aria/storage/modeling/orchestrator_elements.py  |  3 +-
 aria/storage/sql_mapi.py                        |  1 +
 aria/storage_initializer.py                     |  2 +-
 tests/orchestrator/context/test_operation.py    | 48 ++++++++------
 tests/orchestrator/context/test_serialize.py    |  2 +-
 .../orchestrator/execution_plugin/test_local.py |  3 -
 tests/orchestrator/execution_plugin/test_ssh.py |  6 ++
 .../workflows/executor/test_executor.py         |  4 ++
 20 files changed, 133 insertions(+), 109 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index 6940d43..ef5e904 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -140,15 +140,15 @@ def create_file_log_handler(
 class SQLAlchemyHandler(logging.Handler):
 
     def __init__(self, session, engine, log_cls, **kwargs):
-        from aria.storage.modeling import instance_elements
-
-        self._instance_elements = instance_elements
         self._session = session
         self._engine = engine
         self._cls = log_cls
         super(SQLAlchemyHandler, self).__init__(**kwargs)
 
     def emit(self, record):
+        # CHECK: why is this needed?
+        self._cls.__table__.create(bind=self._engine, checkfirst=True)
+
         log = self._cls(
             prefix=record.prefix,
             logger=record.name,
@@ -157,22 +157,13 @@ class SQLAlchemyHandler(logging.Handler):
             created_at=datetime.utcnow(),
         )
         self._session.add(log)
-        self._session.commit()
-
 
-class _SQLAlchemyHandlerFactory(object):
-    # prevents circular imports
-    from aria.storage.modeling.model import Log
-
-    def __init__(self):
-        self._handler = None
-
-    def __call__(self, session, engine, model_cls=Log, level=logging.DEBUG):
-        if not self._handler:
-            self._handler = SQLAlchemyHandler(session, engine, model_cls, level=level)
-        return self._handler
+        try:
+            self._session.commit()
+        except BaseException:
+            self._session.rollback()
+            raise
 
-create_sqla_log_handler = _SQLAlchemyHandlerFactory()
 
 _default_file_formatter = logging.Formatter(
     '%(asctime)s [%(name)s:%(levelname)s] %(message)s <%(pathname)s:%(lineno)d>')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index 7e84c0c..0c8c2f0 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -15,41 +15,39 @@
 """
 A common context for both workflow and operation
 """
+from contextlib import contextmanager
 from functools import partial
 from uuid import uuid4
 
 import logging
-
 import jinja2
 
-from aria import logger
-from aria.storage import exceptions
-
-
-class _Logger(object):
-    def __init__(self, logger):
-        self._logger = logger
-        self._prefix = ''
+from aria import logger as aria_logger
+from aria.storage import exceptions, modeling
 
-    def set_prefix(self, prefix):
-        self._prefix = prefix
 
-    def __getattr__(self, item):
-        return partial(getattr(self._logger, item), extra={'prefix': self._prefix})
-
-
-class BaseContext(object):
+class BaseContext(aria_logger.LoggerMixin):
     """
     Base context object for workflow and operation
     """
 
+    class PrefixedLogger(object):
+        def __init__(self, logger, prefix=''):
+            self._logger = logger
+            self._prefix = prefix
+
+        def __getattr__(self, item):
+            if item.upper() in logging._levelNames:
+                return partial(getattr(self._logger, item), extra={'prefix': self._prefix})
+            else:
+                return getattr(self._logger, item)
+
     def __init__(
             self,
             name,
             service_instance_id,
             model_storage,
             resource_storage,
-            ctx_logger=None,
             workdir=None,
             **kwargs):
         super(BaseContext, self).__init__(**kwargs)
@@ -58,20 +56,13 @@ class BaseContext(object):
         self._model = model_storage
         self._resource = resource_storage
         self._service_instance_id = service_instance_id
-        self._logger = self._init_logger(ctx_logger=ctx_logger)
+        # self._logger = self._init_logger(ctx_logger)
         self._workdir = workdir
 
-    def _init_logger(self, ctx_logger=None):
-        ctx_logger = ctx_logger or logging.getLogger('aria_ctx')
-
-        # A handler should be registered only once.
-        sqla_handler = logger.create_sqla_log_handler(**self._model.all_api_kwargs)
-        if sqla_handler not in ctx_logger.handlers:
-            ctx_logger.addHandler(sqla_handler)
-
-        ctx_logger.setLevel(logging.DEBUG)
-
-        return _Logger(ctx_logger)
+    def _get_sqla_handler(self):
+        api_kwargs = self._model._initiator(**self._model._initiator_kwargs)
+        api_kwargs.update(**self._model._api_kwargs)
+        return aria_logger.SQLAlchemyHandler(log_cls=modeling.model.Log, **api_kwargs)
 
     def __repr__(self):
         return (
@@ -79,9 +70,26 @@ class BaseContext(object):
             'deployment_id={self._service_instance_id}, '
             .format(name=self.__class__.__name__, self=self))
 
+    @contextmanager
+    def self_logging(self, logger=None):
+        if not logger:
+            sqla_handler = self._get_sqla_handler()
+            console_handler = aria_logger.create_console_log_handler()
+            if sqla_handler not in self.logger.handlers:
+                # self.logger.addHandler(aria_logger.create_console_log_handler())
+                self.logger.addHandler(sqla_handler)
+            self.logger = self.PrefixedLogger(self.logger, self.logging_id)
+            yield self.logger
+            sqla_handler._session.close()
+            self.logger.removeHandler(sqla_handler)
+            self.logger.removeHandler(console_handler)
+        else:
+            self.logger = logger
+            yield self.logger
+
     @property
-    def logger(self):
-        return self._logger
+    def logging_id(self):
+        raise NotImplementedError
 
     @property
     def model(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py b/aria/orchestrator/context/operation.py
index efe62ab..766ebb5 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -46,7 +46,7 @@ class BaseOperationContext(BaseContext):
         self._task = None
 
     def __repr__(self):
-        details = 'operation_mapping={task.operation_mapping}; ' \
+        details = 'implementation={task.implementation}; ' \
                   'operation_inputs={task.inputs}'\
             .format(task=self.task)
         return '{name}({0})'.format(details, name=self.name)
@@ -105,9 +105,10 @@ class NodeOperationContext(BaseOperationContext):
     """
     Context for node based operations.
     """
-    def __init__(self, **kwargs):
-        super(NodeOperationContext, self).__init__(**kwargs)
-        self.logger.set_prefix(str(self.node))
+
+    @property
+    def logging_id(self):
+        return self.node.name or self.node.id
 
     @property
     def node_template(self):
@@ -130,9 +131,11 @@ class RelationshipOperationContext(BaseOperationContext):
     """
     Context for relationship based operations.
     """
-    def __init__(self, **kwargs):
-        super(RelationshipOperationContext, self).__init__(**kwargs)
-        self.logger.set_prefix(str(self.relationship))
+
+    @property
+    def logging_id(self):
+        return '{0}:{1}'.format(self.source_node.name or self.source_node.id,
+                                self.target_node.name or self.target_node.id)
 
     @property
     def source_node_template(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/context/workflow.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/workflow.py b/aria/orchestrator/context/workflow.py
index 297e1bc..63ece3a 100644
--- a/aria/orchestrator/context/workflow.py
+++ b/aria/orchestrator/context/workflow.py
@@ -46,7 +46,6 @@ class WorkflowContext(BaseContext):
         # TODO: execution creation should happen somewhere else
         # should be moved there, when such logical place exists
         self._execution_id = self._create_execution() if execution_id is None else execution_id
-        self.logger.set_prefix(str(self.execution))
 
     def __repr__(self):
         return (
@@ -66,6 +65,10 @@ class WorkflowContext(BaseContext):
         return execution.id
 
     @property
+    def logging_id(self):
+        return self._workflow_name
+
+    @property
     def execution(self):
         """
         The execution model

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/decorators.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/decorators.py b/aria/orchestrator/decorators.py
index bbe43f4..1cc97db 100644
--- a/aria/orchestrator/decorators.py
+++ b/aria/orchestrator/decorators.py
@@ -29,7 +29,7 @@ from .workflows.api import task_graph
 WORKFLOW_DECORATOR_RESERVED_ARGUMENTS = ('ctx', 'graph')
 
 
-def workflow(func=None, suffix_template=''):
+def workflow(func=None, suffix_template='', logger=None):
     """
     Workflow decorator
     """
@@ -49,12 +49,13 @@ def workflow(func=None, suffix_template=''):
         workflow_parameters.setdefault('graph', task_graph.TaskGraph(workflow_name))
         validate_function_arguments(func, workflow_parameters)
         with context.workflow.current.push(ctx):
-            func(**workflow_parameters)
+            with ctx.self_logging(logger):
+                func(**workflow_parameters)
         return workflow_parameters['graph']
     return _wrapper
 
 
-def operation(func=None, toolbelt=False, suffix_template=''):
+def operation(func=None, toolbelt=False, suffix_template='', logger=False):
     """
     Operation decorator
     """
@@ -67,7 +68,8 @@ def operation(func=None, toolbelt=False, suffix_template=''):
             operation_toolbelt = context.toolbelt(func_kwargs['ctx'])
             func_kwargs.setdefault('toolbelt', operation_toolbelt)
         validate_function_arguments(func, func_kwargs)
-        return func(**func_kwargs)
+        with func_kwargs['ctx'].self_logging(logger):
+            return func(**func_kwargs)
     return _wrapper
 
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/execution_plugin/operations.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/operations.py b/aria/orchestrator/execution_plugin/operations.py
index 5effa8a..c86f697 100644
--- a/aria/orchestrator/execution_plugin/operations.py
+++ b/aria/orchestrator/execution_plugin/operations.py
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import logging
+
 from aria.orchestrator import operation
 from . import local as local_operations
 from .ssh import operations as ssh_operations
@@ -48,7 +50,7 @@ def run_script_with_ssh(ctx,
         **kwargs)
 
 
-@operation
+@operation(logger=logging.getLogger())
 def run_commands_with_ssh(ctx,
                           commands,
                           fabric_env=None,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/runner.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/runner.py b/aria/orchestrator/runner.py
index 8927de9..bb92d1c 100644
--- a/aria/orchestrator/runner.py
+++ b/aria/orchestrator/runner.py
@@ -33,9 +33,6 @@ from .. import (
 )
 
 
-SQLITE_IN_MEMORY = 'sqlite:///:memory:'
-
-
 class Runner(object):
     """
     Runs workflows on a deployment. By default uses temporary storage (either on disk or in memory)
@@ -97,7 +94,6 @@ class Runner(object):
             task_max_attempts=1,
             task_retry_interval=1)
 
-
     def cleanup(self):
         if (self._is_storage_temporary and (self._storage_path is not None) and
                 os.path.isfile(self._storage_path)):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/workflows/core/engine.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/engine.py b/aria/orchestrator/workflows/core/engine.py
index 7148dd1..55b4159 100644
--- a/aria/orchestrator/workflows/core/engine.py
+++ b/aria/orchestrator/workflows/core/engine.py
@@ -71,11 +71,6 @@ class Engine(logger.LoggerMixin):
         except BaseException as e:
             events.on_failure_workflow_signal.send(self._workflow_context, exception=e)
             raise
-        finally:
-            # Each context creates its own handlers an assign them to the logger.
-            # This enables easy serialization. In order the handlers would not overlap, we
-            # need to clear them each execution.
-            self._workflow_context.logger.handlers = []
 
     def cancel_execution(self):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/workflows/core/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/task.py b/aria/orchestrator/workflows/core/task.py
index d0e1363..e9a6d94 100644
--- a/aria/orchestrator/workflows/core/task.py
+++ b/aria/orchestrator/workflows/core/task.py
@@ -23,7 +23,6 @@ from functools import (
     wraps,
 )
 
-from aria import logger
 from aria.storage.modeling import model
 from aria.orchestrator.context import operation as operation_context
 
@@ -42,7 +41,7 @@ def _locked(func=None):
     return _wrapper
 
 
-class BaseTask(logger.LoggerMixin):
+class BaseTask(object):
     """
     Base class for Task objects
     """
@@ -151,6 +150,14 @@ class OperationTask(BaseTask):
         self._task_id = operation_task.id
         self._update_fields = None
 
+    @property
+    def self_logging(self):
+        return self._ctx.self_logging
+
+    @property
+    def logger(self):
+        return self._ctx.logger
+
     @contextmanager
     def _update(self):
         """

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/orchestrator/workflows/executor/thread.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/executor/thread.py b/aria/orchestrator/workflows/executor/thread.py
index 7ae0217..359513e 100644
--- a/aria/orchestrator/workflows/executor/thread.py
+++ b/aria/orchestrator/workflows/executor/thread.py
@@ -55,13 +55,14 @@ class ThreadExecutor(BaseExecutor):
         while not self._stopped:
             try:
                 task = self._queue.get(timeout=1)
-                self._task_started(task)
-                try:
-                    task_func = imports.load_attribute(task.implementation)
-                    task_func(ctx=task.context, **task.inputs)
-                    self._task_succeeded(task)
-                except BaseException as e:
-                    self._task_failed(task, exception=e)
+                with task.self_logging():
+                    self._task_started(task)
+                    try:
+                        task_func = imports.load_attribute(task.implementation)
+                        task_func(ctx=task.context, **task.inputs)
+                        self._task_succeeded(task)
+                    except BaseException as e:
+                        self._task_failed(task, exception=e)
             # Daemon threads
-            except BaseException:
+            except BaseException as e:
                 pass

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/storage/__init__.py
----------------------------------------------------------------------
diff --git a/aria/storage/__init__.py b/aria/storage/__init__.py
index b76bdf2..5500358 100644
--- a/aria/storage/__init__.py
+++ b/aria/storage/__init__.py
@@ -60,6 +60,5 @@ __all__ = (
     'sql_mapi',
     'api',
     'model',
-    'model_base',
     'type',
 )

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/storage/core.py
----------------------------------------------------------------------
diff --git a/aria/storage/core.py b/aria/storage/core.py
index 7d70070..eaf2bac 100644
--- a/aria/storage/core.py
+++ b/aria/storage/core.py
@@ -141,7 +141,7 @@ class ModelStorage(Storage):
             kwargs['initiator'] = sql_mapi.init_storage
         super(ModelStorage, self).__init__(*args, **kwargs)
 
-    def register(self, model_cls):
+    def register(self, model_cls, create_all=True):
         """
         Register the model into the model storage.
         :param model_cls: the model to register.
@@ -155,7 +155,7 @@ class ModelStorage(Storage):
         self.registered[model_name] = self.api(name=model_name,
                                                model_cls=model_cls,
                                                **self.all_api_kwargs)
-        self.registered[model_name].create()
+        self.registered[model_name].create(create_all=create_all)
         self.logger.debug('setup {name} in storage {self!r}'.format(name=model_name, self=self))
 
     def drop(self):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/storage/modeling/orchestrator_elements.py
----------------------------------------------------------------------
diff --git a/aria/storage/modeling/orchestrator_elements.py b/aria/storage/modeling/orchestrator_elements.py
index edd40b9..366defc 100644
--- a/aria/storage/modeling/orchestrator_elements.py
+++ b/aria/storage/modeling/orchestrator_elements.py
@@ -476,7 +476,8 @@ class LogBase(ModelMixin):
     msg = Column(String)
     created_at = Column(DateTime, index=True)
     prefix = Column(String)
+    description = Column(String)
 
     def __repr__(self):
-        return "<Log [{self.prefix}]: {self.created_at} - {msg}>".format(
+        return "<[{self.level}] {self.created_at}@{self.prefix}> {msg}".format(
             self=self, msg=self.msg[:50])

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/storage/sql_mapi.py
----------------------------------------------------------------------
diff --git a/aria/storage/sql_mapi.py b/aria/storage/sql_mapi.py
index 2711aee..8bbec54 100644
--- a/aria/storage/sql_mapi.py
+++ b/aria/storage/sql_mapi.py
@@ -145,6 +145,7 @@ class SQLAlchemyModelAPI(api.ModelAPI):
 
     def create(self, checkfirst=True, create_all=True, **kwargs):
         self.model_cls.__table__.create(self._engine, checkfirst=checkfirst)
+
         if create_all:
             # In order to create any models created dynamically (e.g. many-to-many helper tables are
             # created at runtime).

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/aria/storage_initializer.py
----------------------------------------------------------------------
diff --git a/aria/storage_initializer.py b/aria/storage_initializer.py
index 175ec22..8c154df 100644
--- a/aria/storage_initializer.py
+++ b/aria/storage_initializer.py
@@ -16,7 +16,7 @@
 from datetime import datetime
 from threading import RLock
 
-from .storage import model
+from .storage.modeling import model
 from .orchestrator import operation
 from .utils.formatting import safe_repr
 from .utils.console import puts, Colored

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/tests/orchestrator/context/test_operation.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_operation.py b/tests/orchestrator/context/test_operation.py
index c216a16..f6cc499 100644
--- a/tests/orchestrator/context/test_operation.py
+++ b/tests/orchestrator/context/test_operation.py
@@ -16,6 +16,7 @@
 import os
 
 import pytest
+from aria.orchestrator.workflows.executor import process, thread
 
 from aria import (
     workflow,
@@ -23,7 +24,6 @@ from aria import (
 )
 from aria.orchestrator import context
 from aria.orchestrator.workflows import api
-from aria.orchestrator.workflows.executor import thread
 
 from tests import mock, storage
 from . import (
@@ -46,17 +46,24 @@ def ctx(tmpdir):
 
 
 @pytest.fixture
-def executor():
-    from aria.orchestrator.workflows.executor import process
+def thread_executor():
+    result = thread.ThreadExecutor()
+    try:
+        yield result
+    finally:
+        result.close()
+
+
+@pytest.fixture
+def process_executor():
     result = process.ProcessExecutor()
-    # result = thread.ThreadExecutor()
     try:
         yield result
     finally:
         result.close()
 
 
-def test_node_operation_task_execution(ctx, executor):
+def test_node_operation_task_execution(ctx, thread_executor):
     operation_name = 'aria.interfaces.lifecycle.create'
 
     node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
@@ -78,7 +85,7 @@ def test_node_operation_task_execution(ctx, executor):
             )
         )
 
-    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=thread_executor)
 
     operation_context = global_test_holder[op_name(node, operation_name)]
 
@@ -97,7 +104,7 @@ def test_node_operation_task_execution(ctx, executor):
     assert operation_context.node == node
 
 
-def test_relationship_operation_task_execution(ctx, executor):
+def test_relationship_operation_task_execution(ctx, thread_executor):
     operation_name = 'aria.interfaces.relationship_lifecycle.post_configure'
     relationship = ctx.model.relationship.list()[0]
 
@@ -122,7 +129,7 @@ def test_relationship_operation_task_execution(ctx, executor):
             )
         )
 
-    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=thread_executor)
 
     operation_context = global_test_holder[op_name(relationship,
                                                    operation_name)]
@@ -149,12 +156,12 @@ def test_relationship_operation_task_execution(ctx, executor):
     assert operation_context.source_node == dependent_node
 
 
-def test_invalid_task_operation_id(ctx, executor):
+def test_invalid_task_operation_id(ctx, thread_executor):
     """
     Checks that the right id is used. The task created with id == 1, thus running the task on
     node_instance with id == 2. will check that indeed the node_instance uses the correct id.
     :param ctx:
-    :param executor:
+    :param thread_executor:
     :return:
     """
     operation_name = 'aria.interfaces.lifecycle.create'
@@ -175,14 +182,14 @@ def test_invalid_task_operation_id(ctx, executor):
             api.task.OperationTask.node(name=operation_name, instance=node)
         )
 
-    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=thread_executor)
 
     op_node_instance_id = global_test_holder[op_name(node, operation_name)]
     assert op_node_instance_id == node.id
     assert op_node_instance_id != other_node.id
 
 
-def test_plugin_workdir(ctx, executor, tmpdir):
+def test_plugin_workdir(ctx, thread_executor, tmpdir):
     op = 'test.op'
     plugin_name = 'mock_plugin'
     node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
@@ -204,14 +211,14 @@ def test_plugin_workdir(ctx, executor, tmpdir):
         graph.add_tasks(api.task.OperationTask.node(
             name=op, instance=node, inputs=inputs))
 
-    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=thread_executor)
     expected_file = tmpdir.join('workdir', 'plugins', str(ctx.service_instance.id),
                                 plugin_name,
                                 filename)
     assert expected_file.read() == content
 
 
-def test_operation_logging(ctx, executor):
+def test_operation_logging(ctx, process_executor):
     operation_name = 'aria.interfaces.lifecycle.create'
 
     node = ctx.model.node.get_by_name(mock.models.DEPENDENCY_NODE_INSTANCE_NAME)
@@ -240,18 +247,19 @@ def test_operation_logging(ctx, executor):
                 inputs=inputs
             )
         )
-        ctx.logger.debug(wf_end)
+        ctx.logger.info(wf_end)
 
-    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=executor)
+    execute(workflow_func=basic_workflow, workflow_context=ctx, executor=process_executor)
 
     logs = ctx.model.log.list()
-    assert len(logs) == 6
+
+    assert len(logs) == 4
 
     op_start_log = [l for l in logs if inputs['op_start'] in l.msg and l.level.lower() == 'info']
     assert len(op_start_log) == 1
     op_start_log = op_start_log[0]
 
-    op_end_log = [l for l in logs if inputs['op_end'] in l.msg and l.level.lower() == 'debug']
+    op_end_log = [l for l in logs if inputs['op_end'] in l.msg and l.level.lower() == 'info']
     assert len(op_end_log) == 1
     op_end_log = op_end_log[0]
 
@@ -259,7 +267,7 @@ def test_operation_logging(ctx, executor):
     assert len(wf_start_log) == 1
     wf_start_log = wf_start_log[0]
 
-    wf_end_log = [l for l in logs if wf_end in l.msg and l.level.lower() == 'debug']
+    wf_end_log = [l for l in logs if wf_end in l.msg and l.level.lower() == 'info']
     assert len(wf_end_log) == 1
     wf_end_log = wf_end_log[0]
 
@@ -272,7 +280,7 @@ def test_operation_logging(ctx, executor):
 @operation
 def logged_operation(ctx, **_):
     ctx.logger.info(ctx.task.inputs['op_start'])
-    ctx.logger.debug(ctx.task.inputs['op_end'])
+    ctx.logger.info(ctx.task.inputs['op_end'])
 
 
 @operation

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/tests/orchestrator/context/test_serialize.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/context/test_serialize.py b/tests/orchestrator/context/test_serialize.py
index 1fdcb1a..03f9529 100644
--- a/tests/orchestrator/context/test_serialize.py
+++ b/tests/orchestrator/context/test_serialize.py
@@ -58,7 +58,7 @@ def _mock_workflow(ctx, graph):
 def _mock_operation(ctx):
     # We test several things in this operation
     # ctx.task, ctx.node, etc... tell us that the model storage was properly re-created
-    # a correct ctx.task.operation_mapping tells us we kept the correct task_id
+    # a correct ctx.task.implementation tells us we kept the correct task_id
     assert ctx.task.implementation == _operation_mapping()
     # a correct ctx.node.name tells us we kept the correct actor_id
     assert ctx.node.name == mock.models.DEPENDENCY_NODE_INSTANCE_NAME

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/tests/orchestrator/execution_plugin/test_local.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_local.py b/tests/orchestrator/execution_plugin/test_local.py
index 9e9540f..5224496 100644
--- a/tests/orchestrator/execution_plugin/test_local.py
+++ b/tests/orchestrator/execution_plugin/test_local.py
@@ -483,9 +483,6 @@ if __name__ == '__main__':
                     operations.__name__,
                     operations.run_script_locally.__name__))
             )]
-            # node.operations[op] = {
-            #     'operation': '{0}.{1}'.format(operations.__name__,
-            #                                   operations.run_script_locally.__name__)}
             graph.add_tasks(api.task.OperationTask.node(
                 instance=node,
                 name=op,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/tests/orchestrator/execution_plugin/test_ssh.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_ssh.py b/tests/orchestrator/execution_plugin/test_ssh.py
index 0981b61..cf4c7e1 100644
--- a/tests/orchestrator/execution_plugin/test_ssh.py
+++ b/tests/orchestrator/execution_plugin/test_ssh.py
@@ -413,6 +413,12 @@ class TestFabricEnvHideGroupsAndRunCommands(object):
         task.runs_on = Stub
         logger = logging.getLogger()
 
+    @staticmethod
+    @contextlib.contextmanager
+    def _mock_self_logging(*args, **kwargs):
+        yield
+    _Ctx.self_logging = _mock_self_logging
+
     @pytest.fixture(autouse=True)
     def _setup(self, mocker):
         self.default_fabric_env = {

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a9bd63da/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 580bf8b..953efb2 100644
--- a/tests/orchestrator/workflows/executor/test_executor.py
+++ b/tests/orchestrator/workflows/executor/test_executor.py
@@ -124,6 +124,10 @@ class MockTask(object):
     def _update(self):
         yield self
 
+    @contextmanager
+    def self_logging(self):
+        yield self.logger
+
 
 @pytest.fixture(params=[
     (thread.ThreadExecutor, {'pool_size': 1}),