You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by em...@apache.org on 2017/07/28 03:10:40 UTC

[1/3] incubator-ariatosca git commit: ARIA-324 Refactor ctx proxy access [Forced Update!]

Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-321-clearwater 80bae440b -> a638acdf1 (forced update)


ARIA-324 Refactor ctx proxy access

Our previous use of "." to delimit nested dict keys was wrong (keys
could have a ".") and inflexible. The new implementation uses subsequent
args to move into the dict. The same format can now be used to access
object attributes.

This commit also changes how to support setting values: we must now use
"=" as the penultimate argument with the new value following.

Also fixed: callables will now "grab" the number of args they need
instead of all remaining args, making it possible to do further
inspection on the returned value from the callable. To allow for this,
kwargs are now expected as the first arg rather than the last.

Relatedly, this commit instruments all parameter fields from all models
and fixes related bugs in the instrumentation implementation.

Furthmore, this commit fixes a bad null check in the ctx client, and
also allows it to retrieve Unicode data.


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

Branch: refs/heads/ARIA-321-clearwater
Commit: ddb85e240de400ef81b140240f8bc2036cd24b80
Parents: c2b8e65
Author: Tal Liron <ta...@gmail.com>
Authored: Thu Jul 27 17:58:17 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Thu Jul 27 21:50:50 2017 -0500

----------------------------------------------------------------------
 aria/orchestrator/context/common.py             |  19 ++-
 aria/orchestrator/context/operation.py          |  46 +++---
 .../execution_plugin/ctx_proxy/client.py        |   7 +-
 .../execution_plugin/ctx_proxy/server.py        | 144 +++++++++----------
 aria/orchestrator/workflows/api/task.py         |  13 +-
 aria/storage/collection_instrumentation.py      |  88 ++++++------
 aria/storage/core.py                            |   6 +-
 .../execution_plugin/test_ctx_proxy_server.py   |  96 ++-----------
 .../orchestrator/execution_plugin/test_local.py |  34 ++---
 9 files changed, 193 insertions(+), 260 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index f400142..3c5f618 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -38,10 +38,27 @@ class BaseContext(object):
     """
 
     INSTRUMENTATION_FIELDS = (
+        modeling.models.Service.inputs,
+        modeling.models.ServiceTemplate.inputs,
+        modeling.models.Policy.properties,
+        modeling.models.PolicyTemplate.properties,
         modeling.models.Node.attributes,
         modeling.models.Node.properties,
         modeling.models.NodeTemplate.attributes,
-        modeling.models.NodeTemplate.properties
+        modeling.models.NodeTemplate.properties,
+        modeling.models.Group.properties,
+        modeling.models.GroupTemplate.properties,
+        modeling.models.Capability.properties,
+        # TODO ARIA-279: modeling.models.Capability.attributes,
+        modeling.models.CapabilityTemplate.properties,
+        # TODO ARIA-279: modeling.models.CapabilityTemplate.attributes
+        modeling.models.Relationship.properties,
+        modeling.models.Artifact.properties,
+        modeling.models.ArtifactTemplate.properties,
+        modeling.models.Interface.inputs,
+        modeling.models.InterfaceTemplate.inputs,
+        modeling.models.Operation.inputs,
+        modeling.models.OperationTemplate.inputs
     )
 
     class PrefixedLogger(object):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/context/operation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/operation.py b/aria/orchestrator/context/operation.py
index 7d5f40c..8613ec3 100644
--- a/aria/orchestrator/context/operation.py
+++ b/aria/orchestrator/context/operation.py
@@ -48,8 +48,7 @@ class BaseOperationContext(common.BaseContext):
     @property
     def task(self):
         """
-        The task in the model storage
-        :return: Task model
+        The task in the model storage.
         """
         # SQLAlchemy prevents from accessing an object which was created on a different thread.
         # So we retrieve the object from the storage if the current thread isn't the same as the
@@ -62,7 +61,7 @@ class BaseOperationContext(common.BaseContext):
     @property
     def plugin_workdir(self):
         """
-        A work directory that is unique to the plugin and the deployment id
+        A work directory that is unique to the plugin and the service ID.
         """
         if self.task.plugin is None:
             return None
@@ -120,20 +119,18 @@ class NodeOperationContext(BaseOperationContext):
     """
 
     @property
-    def node_template(self):
+    def node(self):
         """
-        the node of the current operation
-        :return:
+        The node of the current operation.
         """
-        return self.node.node_template
+        return self.model.node.get(self._actor_id)
 
     @property
-    def node(self):
+    def node_template(self):
         """
-        The node instance of the current operation
-        :return:
+        The node template of the current operation.
         """
-        return self.model.node.get(self._actor_id)
+        return self.node.node_template
 
 
 class RelationshipOperationContext(BaseOperationContext):
@@ -142,41 +139,36 @@ class RelationshipOperationContext(BaseOperationContext):
     """
 
     @property
-    def source_node_template(self):
+    def relationship(self):
         """
-        The source node
-        :return:
+        The relationship instance of the current operation.
         """
-        return self.source_node.node_template
+        return self.model.relationship.get(self._actor_id)
 
     @property
     def source_node(self):
         """
-        The source node instance
-        :return:
+        The relationship source node.
         """
         return self.relationship.source_node
 
     @property
-    def target_node_template(self):
+    def source_node_template(self):
         """
-        The target node
-        :return:
+        The relationship source node template.
         """
-        return self.target_node.node_template
+        return self.source_node.node_template
 
     @property
     def target_node(self):
         """
-        The target node instance
-        :return:
+        The relationship target node.
         """
         return self.relationship.target_node
 
     @property
-    def relationship(self):
+    def target_node_template(self):
         """
-        The relationship instance of the current operation
-        :return:
+        The relationship target node template.
         """
-        return self.model.relationship.get(self._actor_id)
+        return self.target_node.node_template

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/execution_plugin/ctx_proxy/client.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/client.py b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
index 1310c21..84d66f1 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/client.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/client.py
@@ -102,9 +102,12 @@ def main(args=None):
     if args.json_output:
         response = json.dumps(response)
     else:
-        if not response:
+        if response is None:
             response = ''
-        response = str(response)
+        try:
+            response = str(response)
+        except UnicodeEncodeError:
+            response = unicode(response).encode('utf8')
     sys.stdout.write(response)
 
 if __name__ == '__main__':

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/execution_plugin/ctx_proxy/server.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/ctx_proxy/server.py b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
index ca910e0..09cc234 100644
--- a/aria/orchestrator/execution_plugin/ctx_proxy/server.py
+++ b/aria/orchestrator/execution_plugin/ctx_proxy/server.py
@@ -17,14 +17,13 @@
 ``ctx`` proxy server implementation.
 """
 
-import collections
 import json
-import re
 import socket
 import threading
 import traceback
 import Queue
 import StringIO
+import inspect
 import wsgiref.simple_server
 
 import bottle
@@ -150,43 +149,77 @@ class CtxProxy(object):
         self.close()
 
 
-def _process_ctx_request(ctx, args):
+def _process_ctx_request(ctx, args): # pylint: disable=too-many-branches,too-many-statements
     current = ctx
-    num_args = len(args)
     index = 0
+
+    try:
+        equals_index = args.index('=')
+        if equals_index == 0:
+            raise RuntimeError('The "=" argument cannot be first')
+        if equals_index != len(args) - 2:
+            raise RuntimeError('The "=" argument must be penultimate')
+        equals = True
+        equals_key = args[-3]
+        equals_value = args[-1]
+        args = args[:-3]
+    except ValueError:
+        equals = False
+        equals_key = None
+        equals_value = None
+
+    num_args = len(args)
+
     while index < num_args:
         arg = args[index]
         attr = _desugar_attr(current, arg)
-        if attr:
+
+        if attr is not None:
             current = getattr(current, attr)
-        elif isinstance(current, collections.MutableMapping):
-            key = arg
-            path_dict = _PathDictAccess(current)
-            if index + 1 == num_args:
-                # read dict prop by path
-                value = path_dict.get(key)
-                current = value
-            elif index + 2 == num_args:
-                # set dict prop by path
-                value = args[index + 1]
-                path_dict.set(key, value)
-                current = None
-            else:
-                raise RuntimeError('Illegal argument while accessing dict')
-            break
+        elif isinstance(current, list) and _is_int(arg):
+            current = current[int(arg)]
+        elif hasattr(current, '__getitem__'):
+            if equals and (not arg in current):
+                current[arg] = {}
+            current = current[arg]
         elif callable(current):
-            kwargs = {}
-            remaining_args = args[index:]
-            if isinstance(remaining_args[-1], collections.MutableMapping):
-                kwargs = remaining_args[-1]
-                remaining_args = remaining_args[:-1]
-            current = current(*remaining_args, **kwargs)
-            break
+            if isinstance(arg, dict):
+                # Treat the first arg as our kwargs
+                callable_kwargs = arg
+                index += 1
+            else:
+                callable_kwargs = {}
+
+            argspec = inspect.getargspec(current)
+            if argspec.varargs is not None:
+                # Gobble the rest of the args
+                callable_args = args[index:]
+            else:
+                # Take only what we need
+                args_count = len(argspec.args)
+                if inspect.ismethod(current):
+                    # Don't count "self" argument
+                    args_count -= 1
+                callable_args = args[index:index + args_count]
+
+            args_count = len(callable_args)
+            if args_count > 1:
+                index += args_count - 1
+
+            current = current(*callable_args, **callable_kwargs)
         else:
-            raise RuntimeError('{0} cannot be processed in {1}'.format(arg, args))
+            raise RuntimeError('`{0}` cannot be processed in {1}'.format(arg, args))
         index += 1
+
     if callable(current):
         current = current()
+
+    if equals:
+        if hasattr(current, '__setitem__'):
+            current[equals_key] = equals_value
+        else:
+            setattr(current, equals_key, equals_value)
+
     return current
 
 
@@ -201,55 +234,12 @@ def _desugar_attr(obj, attr):
     return None
 
 
-class _PathDictAccess(object):
-    pattern = re.compile(r"(.+)\[(\d+)\]")
-
-    def __init__(self, obj):
-        self.obj = obj
-
-    def set(self, prop_path, value):
-        obj, prop_name = self._get_parent_obj_prop_name_by_path(prop_path)
-        obj[prop_name] = value
-
-    def get(self, prop_path):
-        value = self._get_object_by_path(prop_path)
-        return value
-
-    def _get_object_by_path(self, prop_path, fail_on_missing=True):
-        # when setting a nested object, make sure to also set all the
-        # intermediate path objects
-        current = self.obj
-        for prop_segment in prop_path.split('.'):
-            match = self.pattern.match(prop_segment)
-            if match:
-                index = int(match.group(2))
-                property_name = match.group(1)
-                if property_name not in current:
-                    self._raise_illegal(prop_path)
-                if not isinstance(current[property_name], list):
-                    self._raise_illegal(prop_path)
-                current = current[property_name][index]
-            else:
-                if prop_segment not in current:
-                    if fail_on_missing:
-                        self._raise_illegal(prop_path)
-                    else:
-                        current[prop_segment] = {}
-                current = current[prop_segment]
-        return current
-
-    def _get_parent_obj_prop_name_by_path(self, prop_path):
-        split = prop_path.split('.')
-        if len(split) == 1:
-            return self.obj, prop_path
-        parent_path = '.'.join(split[:-1])
-        parent_obj = self._get_object_by_path(parent_path, fail_on_missing=False)
-        prop_name = split[-1]
-        return parent_obj, prop_name
-
-    @staticmethod
-    def _raise_illegal(prop_path):
-        raise RuntimeError('illegal path: {0}'.format(prop_path))
+def _is_int(arg):
+    try:
+        int(arg)
+    except ValueError:
+        return False
+    return True
 
 
 def _get_unused_port():

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index 4c518fc..ec96d27 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -140,13 +140,18 @@ class OperationTask(BaseTask):
         self.arguments = modeling_utils.merge_parameter_values(arguments,
                                                                operation.arguments,
                                                                model_cls=models.Argument)
-        if getattr(self.actor, 'outbound_relationships', None) is not None:
+
+        actor = self.actor
+        if hasattr(actor, '_wrapped'):
+            # Unwrap instrumented model
+            actor = actor._wrapped
+        if isinstance(actor, models.Node):
             self._context_cls = context.operation.NodeOperationContext
-        elif getattr(self.actor, 'source_node', None) is not None:
+        elif isinstance(actor, models.Relationship):
             self._context_cls = context.operation.RelationshipOperationContext
         else:
-            raise exceptions.TaskCreationException('Could not locate valid context for '
-                                                   '{actor.__class__}'.format(actor=self.actor))
+            raise exceptions.TaskCreationException('Could not create valid context for '
+                                                   '{actor.__class__}'.format(actor=actor))
 
     def __repr__(self):
         return self.name

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/storage/collection_instrumentation.py
----------------------------------------------------------------------
diff --git a/aria/storage/collection_instrumentation.py b/aria/storage/collection_instrumentation.py
index c90cb18..e04865e 100644
--- a/aria/storage/collection_instrumentation.py
+++ b/aria/storage/collection_instrumentation.py
@@ -146,14 +146,14 @@ class _InstrumentedDict(_InstrumentedCollection, dict):
     def _load(self, dict_=None, **kwargs):
         dict.__init__(
             self,
-            tuple((key, self._raw_value(value)) for key, value in (dict_ or {}).items()),
+            tuple((key, self._raw_value(value)) for key, value in (dict_ or {}).iteritems()),
             **kwargs)
 
     def update(self, dict_=None, **kwargs):
         dict_ = dict_ or {}
-        for key, value in dict_.items():
+        for key, value in dict_.iteritems():
             self[key] = value
-        for key, value in kwargs.items():
+        for key, value in kwargs.iteritems():
             self[key] = value
 
     def __getitem__(self, key):
@@ -202,9 +202,31 @@ class _InstrumentedList(_InstrumentedCollection, list):
 
 class _WrappedBase(object):
 
-    def __init__(self, wrapped, instrumentation):
+    def __init__(self, wrapped, instrumentation, instrumentation_kwargs=None):
+        """
+        :param wrapped: model to be instrumented
+        :param instrumentation: instrumentation dict
+        :param instrumentation_kwargs: arguments for instrumentation class
+        """
         self._wrapped = wrapped
         self._instrumentation = instrumentation
+        self._instrumentation_kwargs = instrumentation_kwargs or {}
+
+    def _wrap(self, value):
+        if value.__class__ in set(class_.class_ for class_ in self._instrumentation):
+            return _create_instrumented_model(
+                value, instrumentation=self._instrumentation, **self._instrumentation_kwargs)
+        # Check that the value is a SQLAlchemy model (it should have metadata) or a collection
+        elif hasattr(value, 'metadata') or isinstance(value, (dict, list)):
+            return _create_wrapped_model(
+                value, instrumentation=self._instrumentation, **self._instrumentation_kwargs)
+        return value
+
+    def __getattr__(self, item):
+        if hasattr(self, '_wrapped'):
+            return self._wrap(getattr(self._wrapped, item))
+        else:
+            super(_WrappedBase, self).__getattribute__(item)
 
 
 class _InstrumentedModel(_WrappedBase):
@@ -213,32 +235,32 @@ class _InstrumentedModel(_WrappedBase):
         """
         The original model.
 
-        :param wrapped: model to be instrumented
         :param mapi: MAPI for the wrapped model
+        :param wrapped: model to be instrumented
+        :param instrumentation: instrumentation dict
+        :param instrumentation_kwargs: arguments for instrumentation class
         """
-        super(_InstrumentedModel, self).__init__(*args, **kwargs)
+        super(_InstrumentedModel, self).__init__(instrumentation_kwargs=dict(mapi=mapi),
+                                                 *args, **kwargs)
         self._mapi = mapi
         self._apply_instrumentation()
 
-    def __getattr__(self, item):
-        return_value = getattr(self._wrapped, item)
-        if isinstance(return_value, self._wrapped.__class__):
-            return _create_instrumented_model(return_value, self._mapi, self._instrumentation)
-        if isinstance(return_value, (list, dict)):
-            return _create_wrapped_model(return_value, self._mapi, self._instrumentation)
-        return return_value
-
     def _apply_instrumentation(self):
         for field in self._instrumentation:
+            if field.parent.class_ != type(self._wrapped):
+                # Only apply to fields of our class
+                continue
+
             field_name = field.key
             field_cls = field.mapper.class_
+
             field = getattr(self._wrapped, field_name)
 
-            # Preserve the original value. e.g. original attributes would be located under
-            # _attributes
+            # Preserve the original field, e.g. original "attributes" would be located under
+            # "_attributes"
             setattr(self, '_{0}'.format(field_name), field)
 
-            # set instrumented value
+            # Set instrumented value
             if isinstance(field, dict):
                 instrumentation_cls = _InstrumentedDict
             elif isinstance(field, list):
@@ -247,7 +269,7 @@ class _InstrumentedModel(_WrappedBase):
                 # TODO: raise proper error
                 raise exceptions.StorageError(
                     "ARIA supports instrumentation for dict and list. Field {field} of the "
-                    "class {model} is of {type} type.".format(
+                    "class `{model}` is of type `{type}`.".format(
                         field=field,
                         model=self._wrapped,
                         type=type(field)))
@@ -262,35 +284,13 @@ class _InstrumentedModel(_WrappedBase):
 
 class _WrappedModel(_WrappedBase):
 
-    def __init__(self, instrumentation_kwargs, *args, **kwargs):
-        """
-        :param instrumented_cls: class to be instrumented
-        :param instrumentation_cls: instrumentation cls
-        :param wrapped: currently wrapped instance
-        :param kwargs: passed to the instrumented class
-        """
-        super(_WrappedModel, self).__init__(*args, **kwargs)
-        self._kwargs = instrumentation_kwargs
-
-    def _wrap(self, value):
-        if value.__class__ in (class_.class_ for class_ in self._instrumentation):
-            return _create_instrumented_model(
-                value, instrumentation=self._instrumentation, **self._kwargs)
-        elif hasattr(value, 'metadata') or isinstance(value, (dict, list)):
-            # Basically checks that the value is indeed an sqlmodel (it should have metadata)
-            return _create_wrapped_model(
-                value, instrumentation=self._instrumentation, **self._kwargs)
-        return value
-
-    def __getattr__(self, item):
-        if hasattr(self, '_wrapped'):
-            return self._wrap(getattr(self._wrapped, item))
-        else:
-            super(_WrappedModel, self).__getattribute__(item)
-
     def __getitem__(self, item):
         return self._wrap(self._wrapped[item])
 
+    def __iter__(self):
+        for item in self._wrapped.__iter__():
+            yield self._wrap(item)
+
 
 def _create_instrumented_model(original_model, mapi, instrumentation):
     return type('Instrumented{0}'.format(original_model.__class__.__name__),

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/aria/storage/core.py
----------------------------------------------------------------------
diff --git a/aria/storage/core.py b/aria/storage/core.py
index 2a5745e..7e9b201 100644
--- a/aria/storage/core.py
+++ b/aria/storage/core.py
@@ -130,7 +130,7 @@ class ModelStorage(Storage):
         """
         model_name = model_cls.__modelname__
         if model_name in self.registered:
-            self.logger.debug('{name} in already storage {self!r}'.format(name=model_name,
+            self.logger.debug('{name} already in storage {self!r}'.format(name=model_name,
                                                                           self=self))
             return
         self.registered[model_name] = self.api(name=model_name,
@@ -151,10 +151,10 @@ class ModelStorage(Storage):
         original_instrumentation = {}
 
         try:
-            for mapi in self.registered.values():
+            for mapi in self.registered.itervalues():
                 original_instrumentation[mapi] = copy.copy(mapi._instrumentation)
                 mapi._instrumentation.extend(instrumentation)
             yield self
         finally:
-            for mapi in self.registered.values():
+            for mapi in self.registered.itervalues():
                 mapi._instrumentation[:] = original_instrumentation[mapi]

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
index 7ab1bdb..40ffd50 100644
--- a/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
+++ b/tests/orchestrator/execution_plugin/test_ctx_proxy_server.py
@@ -39,26 +39,26 @@ class TestCtxProxy(object):
         assert response == 'value1'
 
     def test_dict_prop_access_get_key_nested(self, server):
-        response = self.request(server, 'node', 'properties', 'prop2.nested_prop1')
+        response = self.request(server, 'node', 'properties', 'prop2', 'nested_prop1')
         assert response == 'nested_value1'
 
     def test_dict_prop_access_get_with_list_index(self, server):
-        response = self.request(server, 'node', 'properties', 'prop3[2].value')
+        response = self.request(server, 'node', 'properties', 'prop3', 2, 'value')
         assert response == 'value_2'
 
     def test_dict_prop_access_set(self, server, ctx):
-        self.request(server, 'node', 'properties', 'prop4.key', 'new_value')
-        self.request(server, 'node', 'properties', 'prop3[2].value', 'new_value_2')
-        self.request(server, 'node', 'properties', 'prop4.some.new.path',
+        self.request(server, 'node', 'properties', 'prop4', 'key', '=', 'new_value')
+        self.request(server, 'node', 'properties', 'prop3', 2, 'value', '=', 'new_value_2')
+        self.request(server, 'node', 'properties', 'prop4', 'some', 'new', 'path', '=',
                      'some_new_value')
         assert ctx.node.properties['prop4']['key'] == 'new_value'
         assert ctx.node.properties['prop3'][2]['value'] == 'new_value_2'
         assert ctx.node.properties['prop4']['some']['new']['path'] == 'some_new_value'
 
     def test_illegal_dict_access(self, server):
-        self.request(server, 'node', 'properties', 'prop4.key', 'new_value')
+        self.request(server, 'node', 'properties', 'prop4', 'key', '=', 'new_value')
         with pytest.raises(RuntimeError):
-            self.request(server, 'node', 'properties', 'prop4.key', 'new_value', 'what')
+            self.request(server, 'node', 'properties', 'prop4', 'key', '=', 'new_value', 'what')
 
     def test_method_invocation(self, server):
         args = ['arg1', 'arg2', 'arg3']
@@ -77,7 +77,7 @@ class TestCtxProxy(object):
         kwargs = dict(
             arg4=arg4,
             arg5=arg5)
-        response = self.request(server, 'stub_args', arg1, arg2, kwargs)
+        response = self.request(server, 'stub_args', kwargs, arg1, arg2)
         assert response == dict(
             arg1=arg1,
             arg2=arg2,
@@ -236,10 +236,10 @@ class TestArgumentParsing(object):
         self.assert_valid_output({'key': 1},
                                  "{'key': 1}",
                                  '{"key": 1}')
-        self.assert_valid_output(False, '', 'false')
+        self.assert_valid_output(False, 'False', 'false')
         self.assert_valid_output(True, 'True', 'true')
-        self.assert_valid_output([], '', '[]')
-        self.assert_valid_output({}, '', '{}')
+        self.assert_valid_output([], '[]', '[]')
+        self.assert_valid_output({}, '{}', '{}')
 
     def assert_valid_output(self, response, ex_typed_output, ex_json_output):
         self.mock_response = response
@@ -285,77 +285,3 @@ class TestCtxEntryPoint(object):
                              stderr=subprocess.PIPE)
         p.communicate()
         assert not p.wait()
-
-
-class TestPathDictAccess(object):
-    def test_simple_set(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo', 42)
-        assert obj == {'foo': 42}
-
-    def test_nested_set(self):
-        obj = {'foo': {}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar', 42)
-        assert obj == {'foo': {'bar': 42}}
-
-    def test_set_index(self):
-        obj = {'foo': [None, {'bar': 0}]}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo[1].bar', 42)
-        assert obj == {'foo': [None, {'bar': 42}]}
-
-    def test_set_nonexistent_parent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar', 42)
-        assert obj == {'foo': {'bar': 42}}
-
-    def test_set_nonexistent_parent_nested(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        path_dict.set('foo.bar.baz', 42)
-        assert obj == {'foo': {'bar': {'baz': 42}}}
-
-    def test_simple_get(self):
-        obj = {'foo': 42}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo')
-        assert result == 42
-
-    def test_nested_get(self):
-        obj = {'foo': {'bar': 42}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo.bar')
-        assert result == 42
-
-    def test_nested_get_shadows_dotted_name(self):
-        obj = {'foo': {'bar': 42}, 'foo.bar': 58}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo.bar')
-        assert result == 42
-
-    def test_index_get(self):
-        obj = {'foo': [0, 1]}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        result = path_dict.get('foo[1]')
-        assert result == 1
-
-    def test_get_nonexistent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo')
-
-    def test_get_by_index_not_list(self):
-        obj = {'foo': {0: 'not-list'}}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo[0]')
-
-    def test_get_by_index_nonexistent_parent(self):
-        obj = {}
-        path_dict = ctx_proxy.server._PathDictAccess(obj)
-        with pytest.raises(RuntimeError):
-            path_dict.get('foo[1]')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/ddb85e24/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 e64e998..f091194 100644
--- a/tests/orchestrator/execution_plugin/test_local.py
+++ b/tests/orchestrator/execution_plugin/test_local.py
@@ -43,10 +43,10 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.key value
+            ctx node attributes map key = value
             ''',
             windows_script='''
-            ctx node attributes map.key value
+            ctx node attributes map key = value
         ''')
         props = self._run(
             executor, workflow_context,
@@ -57,12 +57,12 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.key1 $key1
-            ctx node attributes map.key2 $key2
+            ctx node attributes map key1 = $key1
+            ctx node attributes map key2 = $key2
             ''',
             windows_script='''
-            ctx node attributes map.key1 %key1%
-            ctx node attributes map.key2 %key2%
+            ctx node attributes map key1 = %key1%
+            ctx node attributes map key2 = %key2%
         ''')
         props = self._run(
             executor, workflow_context,
@@ -81,10 +81,10 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.cwd $PWD
+            ctx node attributes map cwd = $PWD
             ''',
             windows_script='''
-            ctx node attributes map.cwd %CD%
+            ctx node attributes map cwd = %CD%
             ''')
         tmpdir = str(tmpdir)
         props = self._run(
@@ -97,7 +97,7 @@ class TestLocalRunScript(object):
         assert p_map['cwd'] == tmpdir
 
     def test_process_command_prefix(self, executor, workflow_context, tmpdir):
-        use_ctx = 'ctx node attributes map.key value'
+        use_ctx = 'ctx node attributes map key = value'
         python_script = ['import subprocess',
                          'subprocess.Popen("{0}".split(' ')).communicate()[0]'.format(use_ctx)]
         python_script = '\n'.join(python_script)
@@ -121,12 +121,12 @@ class TestLocalRunScript(object):
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes map.arg1 "$1"
-            ctx node attributes map.arg2 $2
+            ctx node attributes map arg1 = "$1"
+            ctx node attributes map arg2 = $2
             ''',
             windows_script='''
-            ctx node attributes map.arg1 %1
-            ctx node attributes map.arg2 %2
+            ctx node attributes map arg1 = %1
+            ctx node attributes map arg2 = %2
             ''')
         props = self._run(
             executor, workflow_context,
@@ -209,10 +209,10 @@ if __name__ == '__main__':
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes key "${input_as_env_var}"
+            ctx node attributes key = "${input_as_env_var}"
             ''',
             windows_script='''
-            ctx node attributes key "%input_as_env_var%"
+            ctx node attributes key = "%input_as_env_var%"
         ''')
         props = self._run(
             executor, workflow_context,
@@ -228,10 +228,10 @@ if __name__ == '__main__':
         script_path = self._create_script(
             tmpdir,
             linux_script='''#! /bin/bash -e
-            ctx node attributes key "${input_as_env_var}"
+            ctx node attributes key = "${input_as_env_var}"
             ''',
             windows_script='''
-            ctx node attributes key "%input_as_env_var%"
+            ctx node attributes key = "%input_as_env_var%"
         ''')
 
         props = self._run(


[3/3] incubator-ariatosca git commit: ARIA-321 Provide Clearwater IMS example

Posted by em...@apache.org.
ARIA-321 Provide Clearwater IMS example

* Allows capabilities, interfaces, and properties to override parent
definition types only if the new type is a descendant of the overridden
type
* Fix bugs in model instrumentation (to allow ctx access to capability
properties and complex values)
* Fix to get_property intrinsic function
* Don't let scalar values be negative
* Doc fixes related to ARIA-277


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

Branch: refs/heads/ARIA-321-clearwater
Commit: a638acdf1ff46bbe8b6ddfd9a619fa13b8b263f3
Parents: ddb85e2
Author: Tal Liron <ta...@gmail.com>
Authored: Tue Jul 18 17:25:27 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Thu Jul 27 22:09:20 2017 -0500

----------------------------------------------------------------------
 README.rst                                      |   2 +-
 aria/modeling/functions.py                      |   4 +-
 aria/modeling/service_common.py                 |   4 +-
 aria/modeling/service_instance.py               |  43 +-
 .../clearwater/clearwater-single-static.yaml    | 111 +++
 examples/clearwater/scripts/bono/create.sh      |   4 +
 examples/clearwater/scripts/bono/delete.sh      |   0
 examples/clearwater/scripts/dime/create.sh      |   5 +
 examples/clearwater/scripts/dime/delete.sh      |   0
 examples/clearwater/scripts/ellis/configure.sh  |  14 +
 examples/clearwater/scripts/ellis/create.sh     |   4 +
 examples/clearwater/scripts/ellis/delete.sh     |   0
 examples/clearwater/scripts/homer/create.sh     |  12 +
 examples/clearwater/scripts/homer/delete.sh     |   0
 examples/clearwater/scripts/homestead/create.sh |  10 +
 examples/clearwater/scripts/homestead/delete.sh |   0
 examples/clearwater/scripts/host/configure.sh   | 157 +++++
 examples/clearwater/scripts/memento/create.sh   |   4 +
 examples/clearwater/scripts/memento/delete.sh   |   0
 examples/clearwater/scripts/ralf/create.sh      |   0
 examples/clearwater/scripts/ralf/delete.sh      |   0
 examples/clearwater/scripts/sprout/create.sh    |   4 +
 examples/clearwater/scripts/sprout/delete.sh    |   0
 examples/clearwater/scripts/vellum/create.sh    |   8 +
 examples/clearwater/scripts/vellum/delete.sh    |   0
 examples/clearwater/types/cassandra.yaml        |  16 +
 examples/clearwater/types/clearwater.yaml       | 683 +++++++++++++++++++
 examples/clearwater/types/ims.yaml              | 431 ++++++++++++
 examples/clearwater/types/smtp.yaml             |  21 +
 examples/hello-world/hello-world.yaml           |  38 ++
 examples/hello-world/helloworld.yaml            |  38 --
 .../block-storage-1/block-storage-1.yaml        |   6 +-
 .../block-storage-2/block-storage-2.yaml        |   6 +-
 .../block-storage-3/block-storage-3.yaml        |   4 +-
 .../block-storage-4/block-storage-4.yaml        |   2 +-
 .../use-cases/non-normative-types.yaml          |   6 +-
 .../webserver-dbms-1/webserver-dbms-1.yaml      |  10 +-
 .../profiles/tosca-simple-1.0/artifacts.yaml    |  18 +-
 .../profiles/tosca-simple-1.0/capabilities.yaml |   8 +-
 .../profiles/tosca-simple-1.0/data.yaml         |  10 +-
 .../profiles/tosca-simple-1.0/interfaces.yaml   |   2 +-
 .../profiles/tosca-simple-1.0/nodes.yaml        |  18 +-
 .../profiles/tosca-simple-1.0/policies.yaml     |   8 +-
 .../tosca-simple-1.0/relationships.yaml         |  16 +-
 .../profiles/tosca-simple-nfv-1.0/nodes.yaml    |   4 +-
 .../simple_v1_0/data_types.py                   |  15 +-
 .../simple_v1_0/modeling/capabilities.py        |  14 +-
 .../simple_v1_0/modeling/data_types.py          |   4 -
 .../simple_v1_0/modeling/functions.py           |  18 +-
 .../simple_v1_0/modeling/interfaces.py          |  14 +-
 .../simple_v1_0/modeling/parameters.py          |  27 +-
 .../simple_v1_0/presentation/types.py           |   8 +-
 .../aria_extension_tosca/simple_v1_0/types.py   |  19 +
 tests/end2end/test_hello_world.py               |   2 +-
 .../node-cellar/node-cellar.yaml                |  18 +-
 .../node-cellar/types/mongodb.yaml              |   2 +-
 .../node-cellar/types/nodejs.yaml               |   2 +-
 .../node-cellar/types/openstack.yaml            |   4 +-
 .../types/shorthand-1/shorthand-1.yaml          |   6 +-
 .../types/typequalified-1/typequalified-1.yaml  |   6 +-
 60 files changed, 1722 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/README.rst
----------------------------------------------------------------------
diff --git a/README.rst b/README.rst
index b9a8213..1284808 100644
--- a/README.rst
+++ b/README.rst
@@ -91,7 +91,7 @@ This section will describe how to run a simple "Hello World" example.
 First, provide ARIA with the ARIA "hello world" service-template and name it (e.g.
 ``my-service-template``)::
 
-    aria service-templates store examples/hello-world/helloworld.yaml my-service-template
+    aria service-templates store examples/hello-world/hello-world.yaml my-service-template
 
 Now create a service based on this service-template and name it (e.g. ``my-service``)::
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index 6544adf..d0ec0cf 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -20,6 +20,7 @@ Mechanism for evaluating intrinsic functions.
 from ..parser.consumption import ConsumptionContext
 from ..parser.exceptions import InvalidValueError
 from ..utils.collections import OrderedDict
+from ..utils.type import full_type_name
 from . import exceptions
 
 
@@ -89,7 +90,8 @@ def evaluate(value, container_holder, report_issues=False): # pylint: disable=to
             if (evaluation is None) \
                 or (not hasattr(evaluation, 'value')) \
                 or (not hasattr(evaluation, 'final')):
-                raise InvalidValueError('bad __evaluate__ implementation')
+                raise InvalidValueError('bad __evaluate__ implementation: {0}'
+                                        .format(full_type_name(value)))
 
             evaluated = True
             value = evaluation.value

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index b533a88..0ab9a2c 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -21,7 +21,7 @@ ARIA modeling service common module
 
 from sqlalchemy import (
     Column,
-    Text,
+    Text
 )
 from sqlalchemy.ext.declarative import declared_attr
 
@@ -29,7 +29,7 @@ from ..parser.consumption import ConsumptionContext
 from ..utils import (
     collections,
     formatting,
-    console,
+    console
 )
 from .mixins import InstanceModelMixin, TemplateModelMixin, ParameterMixin
 from . import relationship

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index 889465c..5e5ef14 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -232,6 +232,36 @@ class ServiceBase(InstanceModelMixin):
     :type: :class:`~datetime.datetime`
     """)
 
+    def get_node_by_type(self, type_name):
+        """
+        Finds the first node of a type (or descendent type).
+        """
+        service_template = self.service_template
+
+        if service_template is not None:
+            node_types = service_template.node_types
+            if node_types is not None:
+                for node in self.nodes.itervalues():
+                    if node_types.is_descendant(type_name, node.type.name):
+                        return node
+
+        return None
+
+    def get_policy_by_type(self, type_name):
+        """
+        Finds the first policy of a type (or descendent type).
+        """
+        service_template = self.service_template
+
+        if service_template is not None:
+            policy_types = service_template.policy_types
+            if policy_types is not None:
+                for policy in self.policies.itervalues():
+                    if policy_types.is_descendant(type_name, policy.type.name):
+                        return policy
+
+        return None
+
     def satisfy_requirements(self):
         satisfied = True
         for node in self.nodes.itervalues():
@@ -591,14 +621,15 @@ class NodeBase(InstanceModelMixin):
 
     @classmethod
     def determine_state(cls, op_name, is_transitional):
-        """ :returns the state the node should be in as a result of running the
-            operation on this node.
+        """
+        :returns the state the node should be in as a result of running the operation on this node.
 
-            e.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
-            the resulting state should either 'creating' (if the task just started) or 'created'
-            (if the task ended).
+        E.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
+        the resulting state should either 'creating' (if the task just started) or 'created'
+        (if the task ended).
 
-            If the operation is not a standard tosca lifecycle operation, then we return None"""
+        If the operation is not a standard TOSCA lifecycle operation, then we return None.
+        """
 
         state_type = 'transitional' if is_transitional else 'finished'
         try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/clearwater-single-static.yaml
----------------------------------------------------------------------
diff --git a/examples/clearwater/clearwater-single-static.yaml b/examples/clearwater/clearwater-single-static.yaml
new file mode 100644
index 0000000..79ea020
--- /dev/null
+++ b/examples/clearwater/clearwater-single-static.yaml
@@ -0,0 +1,111 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: >-
+  Project Clearwater is an open-source IMS core, developed by Metaswitch Networks and released under
+  the GNU GPLv3.
+
+metadata:
+  template_name: clearwater-single-static
+  template_author: ARIA
+  template_version: '1.0'
+  aria_version: '0.1.2'
+
+imports:
+  - types/clearwater.yaml
+  - aria-1.0
+
+topology_template:
+
+  inputs:
+    hosts.ssh.user:
+      type: string
+      default: ubuntu
+    hosts.ssh.password:
+      type: string
+      default: ubuntu
+    static_host.public_address:
+      type: string
+      default: 192.168.1.170
+    static_host.private_address:
+      type: string
+      default: { get_input: static_host.public_address }
+
+  node_templates:
+    bono:
+      type: clearwater.Bono
+      requirements:
+        - sip_downstream: clearwater.Sprout
+        - sip_secure_downstream: clearwater.Sprout
+
+    i-cscf:
+      type: clearwater.I-CSCF
+
+    s-cscf:
+      type: clearwater.S-CSCF
+
+    sprout:
+      type: clearwater.Sprout
+#      requirements:
+#        - sip_upstream: clearwater.Bono
+
+    dime:
+      type: clearwater.Dime
+
+    homestead:
+      type: clearwater.Homestead
+
+    ralf:
+      type: clearwater.Ralf
+
+    vellum:
+      type: clearwater.Vellum
+
+    homer:
+      type: clearwater.Homer
+
+    ellis:
+      type: clearwater.Ellis
+      properties:
+        provision_numbers_count: 1000
+
+    static_host:
+      type: clearwater.Host
+      attributes:
+        public_address: { get_input: static_host.public_address }
+        private_address: { get_input: static_host.private_address }
+      capabilities:
+        host:
+          properties:
+            ssh.user: { get_input: hosts.ssh.user }
+            ssh.password: { get_input: hosts.ssh.password }
+            max_log_directory_size: 50 MiB
+            reduce_cassandra_mem_usage: true
+
+    smtp:
+      type: smtp.SMTP
+      properties:
+          # TODO: not validating required :(
+        address: 127.0.0.1
+      capabilities:
+        smtp:
+          properties:
+            # TODO: not validating required :(
+            username: username
+            password: password
+
+  policies:
+    configuration:
+      type: clearwater.Configuration
+      properties:
+        zone: example.com
+        secret: secret
+
+  substitution_mappings:
+    node_type: ims.nodes.IMS
+    capabilities:
+       p-cscf: [ bono, p-cscf ]
+       i-cscf: [ i-cscf, i-cscf ]
+       s-cscf: [ s-cscf, s-cscf ]
+       hss: [ homestead, hss ]
+       ctf: [ ralf, ctf ]
+       xdms: [ homer, xdms ]

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/bono/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/bono/create.sh b/examples/clearwater/scripts/bono/create.sh
new file mode 100644
index 0000000..7eb94b1
--- /dev/null
+++ b/examples/clearwater/scripts/bono/create.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install bono restund

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/bono/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/bono/delete.sh b/examples/clearwater/scripts/bono/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/dime/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/dime/create.sh b/examples/clearwater/scripts/dime/create.sh
new file mode 100644
index 0000000..04b2d2d
--- /dev/null
+++ b/examples/clearwater/scripts/dime/create.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -e
+
+# Installs Homestead and Ralf
+yes | aptdcon --hide-terminal --install dime clearwater-prov-tools

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/dime/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/dime/delete.sh b/examples/clearwater/scripts/dime/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/ellis/configure.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/ellis/configure.sh b/examples/clearwater/scripts/ellis/configure.sh
new file mode 100644
index 0000000..7ed387d
--- /dev/null
+++ b/examples/clearwater/scripts/ellis/configure.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -e
+
+PROVISION_NUMBERS_START=$(ctx node properties provision_numbers_start)
+PROVISION_NUMBERS_COUNT=$(ctx node properties provision_numbers_count)
+
+if [ "$PROVISION_NUMBERS_COUNT" != 0 ]; then
+	cd /usr/share/clearwater/ellis
+	. env/bin/activate
+	python src/metaswitch/ellis/tools/create_numbers.py \
+		--start "$PROVISION_NUMBERS_START" \
+		--count "$PROVISION_NUMBERS_COUNT"
+	deactivate
+fi

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/ellis/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/ellis/create.sh b/examples/clearwater/scripts/ellis/create.sh
new file mode 100644
index 0000000..93d3fb4
--- /dev/null
+++ b/examples/clearwater/scripts/ellis/create.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install ellis

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/ellis/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/ellis/delete.sh b/examples/clearwater/scripts/ellis/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/homer/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/homer/create.sh b/examples/clearwater/scripts/homer/create.sh
new file mode 100644
index 0000000..74510ab
--- /dev/null
+++ b/examples/clearwater/scripts/homer/create.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install homer
+
+# ARIA fix to avoid warnings by Twisted for missing service_identity library
+# (Crest is used by both Homer and Homestead-prov)
+cd /usr/share/clearwater/crest
+. env/bin/activate
+pip install service_identity
+deactivate
+service homer restart

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/homer/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/homer/delete.sh b/examples/clearwater/scripts/homer/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/homestead/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/homestead/create.sh b/examples/clearwater/scripts/homestead/create.sh
new file mode 100644
index 0000000..b130bd2
--- /dev/null
+++ b/examples/clearwater/scripts/homestead/create.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+
+# ARIA fix to avoid warnings by Twisted for missing service_identity library
+# (Crest is used by both Homer and Homestead-prov)
+cd /usr/share/clearwater/crest
+. env/bin/activate
+pip install service_identity
+deactivate
+service homer restart

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/homestead/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/homestead/delete.sh b/examples/clearwater/scripts/homestead/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/host/configure.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/host/configure.sh b/examples/clearwater/scripts/host/configure.sh
new file mode 100644
index 0000000..0bc5e99
--- /dev/null
+++ b/examples/clearwater/scripts/host/configure.sh
@@ -0,0 +1,157 @@
+#!/bin/bash
+set -e
+
+ZONE=$(ctx service get_policy_by_type clearwater.Configuration properties zone)
+GEOGRAPHICALLY_REDUNDANT=$(ctx service get_policy_by_type clearwater.Configuration properties geographically_redundant)
+SITE_NAME=$(ctx service get_policy_by_type clearwater.Configuration properties site_name)
+SECRET=$(ctx service get_policy_by_type clearwater.Configuration properties secret)
+
+SMTP_HOSTNAME=$(ctx service get_node_by_type smtp.SMTP properties address)
+SMTP_USERNAME=$(ctx service get_node_by_type smtp.SMTP capabilities smtp properties username)
+SMTP_PASSWORD=$(ctx service get_node_by_type smtp.SMTP capabilities smtp properties password)
+
+MAX_LOG_DIRECTORY_SIZE=$(ctx node capabilities host properties max_log_directory_size value)
+REDUCE_CASSANDRA_MEM_USAGE=$(ctx node capabilities host properties reduce_cassandra_mem_usage)
+
+PRIVATE_IP=$(ctx node attributes private_address)
+PUBLIC_IP=$(ctx node attributes public_address)
+PUBLIC_HOSTNAME=$(hostname)
+# TODO: comma-separated list of all private IP addresses in group
+ETCD_CLUSTER=$PRIVATE_IP
+
+REPO_FILE=/etc/apt/sources.list.d/clearwater.list
+REPO_LINE='deb http://repo.cw-ngv.com/stable binary/'
+KEY_URL=http://repo.cw-ngv.com/repo_key
+
+
+#
+# Repository
+#
+
+if [ ! -f "$REPO_FILE" ]; then
+	echo "$REPO_LINE" > "$REPO_FILE"
+	curl --location "$KEY_URL" | apt-key add -
+	apt update
+fi
+
+if ! type aptdcon > /dev/null; then
+	# This will allow us to do concurrent installs
+	apt install aptdaemon --yes
+fi
+
+yes | aptdcon --hide-terminal --install clearwater-management
+
+
+#
+# DNS
+#
+
+S_CSCF_HOST="$PRIVATE_IP scscf.$HOSTNAME # ARIA"
+grep --quiet --fixed-strings "$S_CSCF_HOST" /etc/hosts || echo "$S_CSCF_HOST" >> /etc/hosts
+
+
+#
+# Local configuration
+#
+
+mkdir --parents /etc/clearwater
+CONFIG_FILE=/etc/clearwater/local_config
+echo "# Created by ARIA on $(date -u)" > "$CONFIG_FILE"
+
+echo >> "$CONFIG_FILE"
+echo "# Local IP configuration" >> "$CONFIG_FILE"
+echo "local_ip=$PRIVATE_IP" >> "$CONFIG_FILE"
+echo "public_ip=$PUBLIC_IP" >> "$CONFIG_FILE"
+echo "public_hostname=$PUBLIC_HOSTNAME" >> "$CONFIG_FILE"
+echo "etcd_cluster=$ETCD_CLUSTER" >> "$CONFIG_FILE"
+
+if [ "$MAX_LOG_DIRECTORY_SIZE" != 0 ]; then
+	echo >> "$CONFIG_FILE"
+	echo "max_log_directory_size=$MAX_LOG_DIRECTORY_SIZE" >> "$CONFIG_FILE"
+fi
+
+if [ "$GEOGRAPHICALLY_REDUNDANT" = True ]; then
+	echo >> "$CONFIG_FILE"
+	echo "# Geographically redundant" >> "$CONFIG_FILE"
+	echo "local_site_name=$SITE_NAME" >> "$CONFIG_FILE"
+
+	# On the first Vellum node in the second site, you should set remote_cassandra_seeds to the
+	# IP address of a Vellum node in the first site.
+	#echo "remote_cassandra_seeds=" >> "$CONFIG_FILE"
+fi
+
+
+#
+# Shared configuration
+#
+
+if [ "$GEOGRAPHICALLY_REDUNDANT" = True ]; then
+	SPROUT_HOSTNAME=sprout.$SITE_NAME.$ZONE
+	SPROUT_REGISTRATION_STORE=vellum.$SITE_NAME.$ZONE
+	HS_HOSTNAME=hs.$SITE_NAME.$ZONE:8888
+	HS_PROVISIONING_HOSTNAME=hs.$SITE_NAME.$ZONE:8889
+	RALF_HOSTNAME=ralf.$SITE_NAME.$ZONE:10888
+	RALF_SESSION_STORE=vellum.$ZONE
+	XDMS_HOSTNAME=homer.$SITE_NAME.$ZONE:7888
+	CHRONOS_HOSTNAME=vellum.$SITE_NAME.$ZONE
+	CASSANDRA_HOSTNAME=vellum.$SITE_NAME.$ZONE
+else
+	VELLUM_IP=$PRIVATE_IP
+	HOMESTEAD_IP=$PRIVATE_IP
+	HOMER_IP=$PRIVATE_IP
+
+	SPROUT_HOSTNAME=$PUBLIC_HOSTNAME
+	SPROUT_REGISTRATION_STORE=$VELLUM_IP
+	HS_HOSTNAME=$HOMESTEAD_IP:8888
+	HS_PROVISIONING_HOSTNAME=$HOMESTEAD_IP:8889
+	RALF_HOSTNAME=
+	RALF_SESSION_STORE=
+	XDMS_HOSTNAME=$HOMER_IP:7888
+	CHRONOS_HOSTNAME=
+	CASSANDRA_HOSTNAME=
+fi
+
+mkdir --parents /etc/clearwater
+CONFIG_FILE=/etc/clearwater/shared_config
+echo "# Created by ARIA on $(date -u)" > "$CONFIG_FILE"
+
+echo >> "$CONFIG_FILE"
+echo "# Deployment definitions" >> "$CONFIG_FILE"
+echo "home_domain=$ZONE" >> "$CONFIG_FILE"
+echo "sprout_hostname=$SPROUT_HOSTNAME" >> "$CONFIG_FILE"
+echo "sprout_registration_store=$SPROUT_REGISTRATION_STORE" >> "$CONFIG_FILE"
+echo "hs_hostname=$HS_HOSTNAME" >> "$CONFIG_FILE"
+echo "hs_provisioning_hostname=$HS_PROVISIONING_HOSTNAME" >> "$CONFIG_FILE"
+echo "ralf_hostname=$RALF_HOSTNAME" >> "$CONFIG_FILE"
+echo "ralf_session_store=$RALF_SESSION_STORE" >> "$CONFIG_FILE"
+echo "xdms_hostname=$XDMS_HOSTNAME" >> "$CONFIG_FILE"
+echo "chronos_hostname=$CHRONOS_HOSTNAME" >> "$CONFIG_FILE"
+echo "cassandra_hostname=$CASSANDRA_HOSTNAME" >> "$CONFIG_FILE"
+
+echo >> "$CONFIG_FILE"
+echo "# Email server configuration" >> "$CONFIG_FILE"
+echo "smtp_smarthost=$SMTP_HOSTNAME" >> "$CONFIG_FILE"
+echo "smtp_username=$SMTP_USERNAME" >> "$CONFIG_FILE"
+echo "smtp_password=$SMTP_PASSWORD" >> "$CONFIG_FILE"
+echo "email_recovery_sender=clearwater@$ZONE" >> "$CONFIG_FILE"
+
+echo >> "$CONFIG_FILE"
+echo "# I-CSCF/S-CSCF configuration (used by Bono to proxy to Sprout)" >> "$CONFIG_FILE"
+echo "upstream_hostname=scscf.$HOSTNAME" >> "$CONFIG_FILE"
+
+echo >> "$CONFIG_FILE"
+echo "# Keys" >> "$CONFIG_FILE"
+echo "signup_key=$SECRET" >> "$CONFIG_FILE"
+echo "turn_workaround=$SECRET" >> "$CONFIG_FILE"
+echo "ellis_api_key=$SECRET" >> "$CONFIG_FILE"
+echo "ellis_cookie_key=$SECRET" >> "$CONFIG_FILE"
+
+if [ "$REDUCE_CASSANDRA_MEM_USAGE" = True ]; then
+	echo >> "$CONFIG_FILE"
+	echo "# $REDUCE_CASSANDRA_MEM_USAGE" >> "$CONFIG_FILE"
+	echo "reduce_cassandra_mem_usage=Y" >> "$CONFIG_FILE"
+fi
+
+# Copy to other hosts in etcd group
+#yes | aptdcon --hide-terminal --install clearwater-config-manager
+#cw-upload_shared_config

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/memento/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/memento/create.sh b/examples/clearwater/scripts/memento/create.sh
new file mode 100644
index 0000000..6894015
--- /dev/null
+++ b/examples/clearwater/scripts/memento/create.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install memento-as memento-nginx

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/memento/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/memento/delete.sh b/examples/clearwater/scripts/memento/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/ralf/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/ralf/create.sh b/examples/clearwater/scripts/ralf/create.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/ralf/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/ralf/delete.sh b/examples/clearwater/scripts/ralf/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/sprout/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/sprout/create.sh b/examples/clearwater/scripts/sprout/create.sh
new file mode 100644
index 0000000..c8161e7
--- /dev/null
+++ b/examples/clearwater/scripts/sprout/create.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install sprout

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/sprout/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/sprout/delete.sh b/examples/clearwater/scripts/sprout/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/vellum/create.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/vellum/create.sh b/examples/clearwater/scripts/vellum/create.sh
new file mode 100644
index 0000000..98b9d42
--- /dev/null
+++ b/examples/clearwater/scripts/vellum/create.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+yes | aptdcon --hide-terminal --install vellum
+
+# Memento
+# TODO: see if there is a Memento node
+#yes | aptdcon --hide-terminal --install memento-cassandra

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/scripts/vellum/delete.sh
----------------------------------------------------------------------
diff --git a/examples/clearwater/scripts/vellum/delete.sh b/examples/clearwater/scripts/vellum/delete.sh
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/types/cassandra.yaml
----------------------------------------------------------------------
diff --git a/examples/clearwater/types/cassandra.yaml b/examples/clearwater/types/cassandra.yaml
new file mode 100644
index 0000000..10ad34f
--- /dev/null
+++ b/examples/clearwater/types/cassandra.yaml
@@ -0,0 +1,16 @@
+
+capability_types:
+
+  cassandra.Endpoint:
+    derived_from: tosca.capabilities.Endpoint.Database
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 7000
+
+  cassandra.Endpoint.Thrift:
+    derived_from: tosca.capabilities.Endpoint.Database
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 9160

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/types/clearwater.yaml
----------------------------------------------------------------------
diff --git a/examples/clearwater/types/clearwater.yaml b/examples/clearwater/types/clearwater.yaml
new file mode 100644
index 0000000..7aab82c
--- /dev/null
+++ b/examples/clearwater/types/clearwater.yaml
@@ -0,0 +1,683 @@
+
+imports:
+  - ims.yaml
+  - smtp.yaml
+  - cassandra.yaml
+
+dsl_definitions:
+
+  clearwater_operation_dependencies: &CLEARWATER_OPERATION_DEPENDENCIES
+    - "ssh.user > { get_property: [ HOST, host, ssh.user ] }"
+    - "ssh.password > { get_property: [ HOST, host, ssh.password ] }"
+    - "ssh.address > { get_attribute: [ HOST, public_address ] }"
+    - "ssh.use_sudo > true"
+
+policy_types:
+
+  clearwater.Configuration:
+    derived_from: tosca.policies.Root
+    properties:
+      zone:
+        description: >-
+          The domain name for SIP addresses, for example if its "example.com" then a SIP address
+          could be "6505550243@example.com".
+        type: string
+      geographically_redundant:
+        description: >-
+          Enable a geographically redundant deployment.
+        
+          See: http://clearwater.readthedocs.io/en/stable/Geographic_redundancy.html
+        type: boolean
+        default: false
+      site_name:
+        description: >-
+          Used by geographically redundant deployments.
+        type: string
+      secret:
+        description: >-
+          Used for registration via Ellis.
+        type: string
+
+capability_types:
+
+  clearwater.Container:
+    description: >-
+      Clearwater container capability.
+    derived_from: tosca.capabilities.Container
+    properties:
+      ssh.user:
+        type: string
+      ssh.password:
+        type: string
+      max_log_directory_size:
+        type: scalar-unit.size
+        default: 0 B # 0 means no max size
+      reduce_cassandra_mem_usage:
+        type: boolean
+        default: false
+
+  # http://clearwater.readthedocs.io/en/stable/Clearwater_IP_Port_Usage.html
+
+  # SIP endpoints
+
+  clearwater.Endpoint.SIP.Upstream:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 5052
+
+  clearwater.Endpoint.SIP.Upstream.Secure:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 5054
+      secure: # override
+        type: boolean
+        default: true
+
+  clearwater.Endpoint.SIP.Proxy:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 5058
+
+  clearwater.Endpoint.SIP.Public:
+    derived_from: tosca.capabilities.Endpoint.Public
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 5060
+
+  clearwater.Endpoint.SIP.Public.Secure:
+    derived_from: tosca.capabilities.Endpoint.Public
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 5062
+      secure: # override
+        type: boolean
+        default: true
+
+  # STUN endpoints
+
+  clearwater.Endpoint.STUN:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: stun
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 3478
+
+  # Diameter endpoints
+
+  clearwater.Endpoint.Diameter.HSS:
+    description: >-
+      In shared_config: hs_listen_port
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: diameter
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 3868
+
+  clearwater.Endpoint.Diameter.CTF:
+    description: >-
+      In shared_config: ralf_listen_port
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: diameter
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 3869
+
+  # Management endpoints
+
+  clearwater.Endpoint.Management.Homer:
+    derived_from: ims.interfaces.HTTP
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 7888
+
+  clearwater.Endpoint.Management.Homestead:
+    derived_from: ims.interfaces.HTTP
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 8888
+
+  clearwater.Endpoint.Management.Homestead.Provisioning:
+    description: >-
+      In shared_config: homestead_provisioning_port
+    derived_from: ims.interfaces.HTTP
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 8889
+
+  clearwater.Endpoint.Management.Sprout:
+    derived_from: ims.interfaces.HTTP
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 9886
+
+  clearwater.Endpoint.Management.Ralf:
+    derived_from: ims.interfaces.HTTP
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 9888 # note: some documentation shows 10888
+
+  # Web endpoints
+
+  clearwater.Endpoint.Public.Web:
+    derived_from: tosca.capabilities.Endpoint.Public
+    properties:
+      protocol: # override
+        type: string
+        default: http
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 80
+      url_path: # override
+        type: string
+        default: /
+
+  clearwater.Endpoint.Public.Web.Secure:
+    derived_from: tosca.capabilities.Endpoint.Public
+    properties:
+      protocol: # override
+        type: string
+        default: https
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 443
+      secure: # override
+        type: boolean
+        default: true
+      url_path: # override
+        type: string
+        default: /        
+
+  # Other endpoints
+
+  clearwater.Endpoint.Chronos:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 7253
+
+  clearwater.Endpoint.Memcached:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 11211
+
+  clearwater.Endpoint.Astaire:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      port: # override
+        type: tosca.datatypes.network.PortDef
+        default: 11311
+
+data_types:
+
+  clearwater.Number:
+    derived_from: string
+    constraints:
+      - pattern: '^\d{10}$'
+
+node_types:
+
+  # http://clearwater.readthedocs.io/en/stable/Clearwater_Architecture.html
+
+  clearwater.SoftwareComponent:
+    description: >-
+      Clearwater software components must be installed in a Clearwater-capable compute node.
+    derived_from: tosca.nodes.SoftwareComponent
+    requirements:
+      - host: # override
+          capability: clearwater.Container
+          node: tosca.nodes.Compute # TODO: we shouldn't need this, see comment in ARIA-174
+          relationship: tosca.relationships.HostedOn
+
+  clearwater.Bono:
+    description: >-
+      Clearwater edge proxy.
+
+      The Bono nodes form a horizontally scalable SIP edge proxy providing both a SIP IMS Gm
+      compliant interface and a WebRTC interface to clients. Client connections are load balanced
+      across the nodes. The Bono node provides the anchor point for the client's connection to the
+      Clearwater system, including support for various NAT traversal mechanisms. A client is
+      therefore anchored to a particular Bono node for the duration of its registration, but can
+      move to another Bono node if the connection or client fails.
+
+      Clients can connect to Bono using SIP/UDP or SIP/TCP. Bono supports any WebRTC client that
+      performs call setup signaling using SIP over WebSocket.
+
+      Alternatively, Clearwater can be deployed with a third party P-CSCF or Session Border
+      Controller implementing P-CSCF. In this case Bono nodes are not required.
+    derived_from: clearwater.SoftwareComponent
+    capabilities:
+      p-cscf: ims.functions.P-CSCF
+      gm: ims.interfaces.Gm
+      sip_endpoint: clearwater.Endpoint.SIP.Public
+      sip_secure_endpoint: clearwater.Endpoint.SIP.Public.Secure
+      sip_proxy: clearwater.Endpoint.SIP.Proxy # open to Sprout
+      stun_endoint: clearwater.Endpoint.STUN
+    requirements:
+      - sip_downstream:
+          capability: clearwater.Endpoint.SIP.Upstream
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+          occurrences: [ 0, UNBOUNDED ]       
+      - sip_secure_downstream:
+          capability: clearwater.Endpoint.SIP.Upstream.Secure
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+          occurrences: [ 0, UNBOUNDED ]       
+      - ralf: # for billable events
+          capability: clearwater.Endpoint.Management.Ralf
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/bono/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/bono/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Sprout:
+    description: >-
+      Clearwater SIP router.
+
+      The Sprout nodes act as a horizontally scalable, combined SIP registrar and authoritative
+      routing proxy, and handle client authentication and the ISC interface to application servers.
+      The Sprout nodes also contain the in-built MMTEL application server. SIP transactions are load
+      balanced across the Sprout cluster, so there is no long-lived association between a client and
+      a particular Sprout node. Sprout does not store any long-lived data itself and instead uses
+      web service interfaces to Homestead and Homer to retrieve HSS configuration such as
+      authentication data/user profiles and MMTEL service settings APIs to Vellum for storing
+      subscriber registration data and for running timers.
+
+      Sprout is where the bulk of the I-CSCF and S-CSCF function resides, with the remainder
+      provided by Dime (and backed by the long-lived data stores on Vellum).            
+    derived_from: clearwater.SoftwareComponent
+    capabilities:
+      sip_endpoint: clearwater.Endpoint.SIP.Upstream # open to Bono
+      sip_secure_endpoint: clearwater.Endpoint.SIP.Upstream.Secure # open to Bono
+      management_endpoint: clearwater.Endpoint.Management.Sprout
+      memento:
+        type: tosca.capabilities.Container
+        valid_source_types: [ clearwater.Memento ]
+    requirements:
+#      - sip_upstream: # cyclical!
+#          capability: clearwater.Endpoint.SIP.Proxy      
+#          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+#          occurrences: [ 0, UNBOUNDED ]       
+      - homer: # for subscriber profiles
+          capability: clearwater.Endpoint.Management.Homer
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+      - ralf: # for billable events
+          capability: clearwater.Endpoint.Management.Ralf
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+      - chronos:
+          capability: clearwater.Endpoint.Chronos
+          node: clearwater.Vellum
+      - astaire:
+          capability: clearwater.Endpoint.Astaire
+          node: clearwater.Vellum
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/sprout/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/sprout/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Memento:
+    derived_from: tosca.nodes.Root
+    capabilities:
+      sip-as: ims.functions.SIP-AS
+      web_secure_endpoint: clearwater.Endpoint.Public.Web.Secure
+    requirements:
+      - host:
+          capability: tosca.capabilities.Container
+          node: clearwater.Sprout
+      - cassandra_thrift:
+          capability: cassandra.Endpoint.Thrift
+          node: clearwater.Vellum
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/memento/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/memento/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Dime:
+    description: >-
+      Clearwater Diameter gateway.
+
+      Dime nodes run Clearwater's Homestead and Ralf components.
+    derived_from: clearwater.SoftwareComponent
+    capabilities:
+      host:
+         type: tosca.capabilities.Container
+         valid_source_types: [ clearwater.DimeSoftwareComponent ]
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/dime/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/dime/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.DimeSoftwareComponent:
+    description: >-
+      Base type for Dime software components.
+    derived_from: clearwater.SoftwareComponent
+    requirements:
+      - host: # override
+          capability: tosca.capabilities.Container
+          node: clearwater.Dime
+
+  clearwater.Homestead:
+    description: >-
+      Clearwater HSS cache.
+
+      Homestead provides a web services interface to Sprout for retrieving authentication
+      credentials and user profile information. It can either master the data (in which case it
+      exposes a web services provisioning interface) or can pull the data from an IMS compliant HSS
+      over the Cx interface. The Homestead nodes themselves are stateless - the mastered / cached
+      subscriber data is all stored on Vellum (via Cassandra's Thrift interface).
+
+      In the IMS architecture, the HSS mirror function is considered to be part of the I-CSCF and
+      S-CSCF components, so in Clearwater I-CSCF and S-CSCF function is implemented with a
+      combination of Sprout and Dime clusters.
+    derived_from: clearwater.DimeSoftwareComponent
+    capabilities:
+      hss: ims.functions.HSS
+      cx: ims.interfaces.Cx
+      diameter_endpoint: clearwater.Endpoint.Diameter.HSS
+      management_endpoint: clearwater.Endpoint.Management.Homestead # open to Ellis
+      provisioning_management_endpoint: clearwater.Endpoint.Management.Homestead.Provisioning # open to Ellis
+    requirements:
+      - cassandra_thrift:
+          capability: cassandra.Endpoint.Thrift
+          node: clearwater.Vellum
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/homestead/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/homestead/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Ralf:
+    description: >-
+      Clearwater CTF.
+
+      Ralf provides an HTTP API that both Bono and Sprout can use to report billable events that
+      should be passed to the CDF (Charging Data Function) over the Rf billing interface. Ralf is
+      stateless, using Vellum to maintain the long lived session state and run the timers necessary
+      to enable it to conform to the Rf protocol.
+    derived_from: clearwater.DimeSoftwareComponent
+    capabilities:
+      ctf: ims.functions.CTF
+      rf: ims.interfaces.Rf
+      diameter_endpoint: clearwater.Endpoint.Diameter.CTF
+      management_endpoint: clearwater.Endpoint.Management.Ralf # open to Sprout, Bono, Vellum
+    requirements:
+      - chronos:
+          capability: clearwater.Endpoint.Chronos
+          node: clearwater.Vellum
+      - astaire:
+          capability: clearwater.Endpoint.Astaire
+          node: clearwater.Vellum
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/ralf/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/ralf/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Vellum:
+    description: >-
+      Clearwater state store.
+
+      Vellum is used to maintain all long-lived state in the deployment. It does this by running a
+      number of cloud optimized, distributed storage clusters.
+
+      - Cassandra. Cassandra is used by Homestead to store authentication credentials and profile
+      information, and is used by Homer to store MMTEL service settings. Vellum exposes Cassandra's
+      Thrift API.
+
+      - etcd. etcd is used by Vellum itself to share clustering information between Vellum nodes and
+      by other nodes in the deployment for shared configuration.
+
+      - Chronos. Chronos is a distributed, redundant, reliable timer service developed by
+      Clearwater. It is used by Sprout and Ralf nodes to enable timers to be run (e.g. for SIP
+      Registration expiry) without pinning operations to a specific node (one node can set the timer
+      and another act on it when it pops). Chronos is accessed via an HTTP API.
+
+      - Memcached / Astaire. Vellum also runs a Memcached cluster fronted by Astaire. Astaire is a
+      service developed by Clearwater that enabled more rapid scale up and scale down of memcached
+      clusters. This cluster is used by Sprout and Ralf for storing registration and session state.
+    derived_from: clearwater.SoftwareComponent
+    capabilities:
+      cassandra_endpoint: cassandra.Endpoint # open to other Vellum
+      cassandra_thrift_endpoint: cassandra.Endpoint.Thrift # open to Homer, Dime (Homestead), Sprout (Memento)
+      chronos_endpoint: clearwater.Endpoint.Chronos # open to other Vellum, Sprout, Dime (Ralf)
+      memcached_endpoint: clearwater.Endpoint.Memcached # open to other Vellum
+      astaire_endpoint: clearwater.Endpoint.Astaire # open to Sprout, Dime (Ralf)
+#    requirements: # cyclical!
+#      - ralf:
+#          capability: clearwater.Endpoint.Management.Ralf
+#          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/vellum/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/vellum/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Homer:
+    description: >-
+      Clearwater XDMS.
+
+      Homer is a standard XDMS used to store MMTEL service settings documents for each user of the
+      system. Documents are created, read, updated and deleted using a standard XCAP interface. As
+      with Homestead, the Homer nodes use Vellum as the data store for all long lived data.
+    derived_from: clearwater.SoftwareComponent
+    capabilities:
+      xdms: ims.functions.XDMS
+      management_endpoint: clearwater.Endpoint.Management.Homer # open to Sprout, Ellis
+    requirements:
+      - cassandra_thrift:
+          capability: cassandra.Endpoint.Thrift
+          node: clearwater.Vellum
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/homer/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/homer/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.Ellis:
+    description: >-
+      Ellis is a sample provisioning portal providing self sign-up, password management, line
+      management and control of MMTEL service settings. It is not intended to be a part of
+      production Clearwater deployments (it is not easy to horizontally scale because of the MySQL
+      underpinnings for one thing) but to make the system easy to use out of the box.
+    derived_from: clearwater.SoftwareComponent
+    properties:
+      provision_numbers_start:
+        type: clearwater.Number
+        default: '6505550000'
+      provision_numbers_count:
+        type: integer
+        default: 0 # 0 means do not provision numbers
+        constraints:
+          - greater_or_equal: 0
+    capabilities:
+      web_endpoint: clearwater.Endpoint.Public.Web
+      web_secure_endpoint: clearwater.Endpoint.Public.Web.Secure
+    requirements:
+      - homer: # for subscriber profiles
+          capability: clearwater.Endpoint.Management.Homer
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+      - homestead: # for subscriber authentication
+          capability: clearwater.Endpoint.Management.Homestead
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+      - homestead_provisioning:
+          capability: clearwater.Endpoint.Management.Homestead.Provisioning
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+      - ralf: # TODO: really?
+          capability: clearwater.Endpoint.Management.Ralf
+          node: tosca.nodes.Root # TODO: we shouldn't need this, see comment in ARIA-174
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        create:
+          implementation:
+            primary: scripts/ellis/create.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        configure:
+          implementation:
+            primary: scripts/ellis/configure.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+        delete:
+          implementation:
+            primary: scripts/ellis/delete.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+
+  clearwater.I-CSCF:
+    description: >-
+      Clearwater I-CSCF.
+
+      Logical node encompassing Sprout and Homestead. Required only if you need to expose the I-CSCF
+      function.
+    derived_from: tosca.nodes.Root
+    capabilities:
+      i-cscf: ims.functions.I-CSCF
+    requirements:
+      - sprout:
+          capability: tosca.capabilities.Node
+          node: clearwater.Sprout
+      - homestead:
+          capability: tosca.capabilities.Node
+          node: clearwater.Homestead
+
+  clearwater.S-CSCF:
+    description: >-
+      Clearwater S-CSCF.
+
+      Logical node encompassing Sprout and Homestead. Required only if you need to expose the S-CSCF
+      function.
+    derived_from: tosca.nodes.Root
+    capabilities:
+      s-cscf: ims.functions.S-CSCF
+    requirements:
+      - sprout:
+          capability: tosca.capabilities.Node
+          node: clearwater.Sprout
+      - homestead:
+          capability: tosca.capabilities.Node
+          node: clearwater.Homestead
+
+  clearwater.Host:
+    description: >-
+      Default Clearwater host.
+
+      Note that any node can function as a Clearwater host as long as it has a clearwater.Container
+      capability.
+    derived_from: tosca.nodes.Compute
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+        configure:
+          implementation:
+            primary: scripts/host/configure.sh
+            dependencies: *CLEARWATER_OPERATION_DEPENDENCIES
+    capabilities:
+      host: # override
+        type: clearwater.Container
+        valid_source_types: [ tosca.nodes.SoftwareComponent ]
+      os: # override
+        type: tosca.capabilities.OperatingSystem
+        properties:
+          architecture:
+            type: string
+            default: x86_64
+          type:
+            type: string
+            default: linux
+          distribution:
+            type: string
+            default: ubuntu
+          version:
+            type: version
+            default: 14.04
+      smtp:
+        type: smtp.SMTP

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/types/ims.yaml
----------------------------------------------------------------------
diff --git a/examples/clearwater/types/ims.yaml b/examples/clearwater/types/ims.yaml
new file mode 100644
index 0000000..6a64e6e
--- /dev/null
+++ b/examples/clearwater/types/ims.yaml
@@ -0,0 +1,431 @@
+capability_types:
+
+  # https://en.wikipedia.org/wiki/IP_Multimedia_Subsystem#Core_network
+
+  ims.functions.Root:
+    derived_from: tosca.capabilities.Root
+
+  ims.functions.CTF: # not mentioned in Wikipedia
+    description: >-
+      Charging Trigger Function.
+    derived_from: ims.functions.Root
+
+  ims.functions.XDMS: # not mentioned in Wikipedia
+    description: >-
+      XML Document Management Server
+    derived_from: ims.functions.Root
+
+  ims.functions.HSS:
+    description: >-
+      The home subscriber server (HSS), or user profile server function (UPSF), is a master user
+      database that supports the IMS network entities that actually handle calls. It contains the
+      subscription-related information (subscriber profiles), performs authentication and
+      authorization of the user, and can provide information about the subscriber's location and IP
+      information. It is similar to the GSM home location register (HLR) and Authentication centre
+      (AuC).
+
+      A subscriber location function (SLF) is needed to map user addresses when multiple HSSs are
+      used.
+    derived_from: ims.functions.Root
+
+  ims.functions.CSCF:
+    description: >-
+      Several roles of SIP servers or proxies, collectively called Call Session Control Function
+      (CSCF), are used to process SIP signalling packets in the IMS.
+    derived_from: ims.functions.Root
+
+  ims.functions.P-CSCF:
+    description: >-
+      A Proxy-CSCF (P-CSCF) is a SIP proxy that is the first point of contact for the IMS terminal.
+      It can be located either in the visited network (in full IMS networks) or in the home network
+      (when the visited network is not IMS compliant yet). Some networks may use a Session Border
+      Controller (SBC) for this function. The P-CSCF is at its core a specialized SBC for the
+      User–network interface which not only protects the network, but also the IMS terminal. The use
+      of an additional SBC between the IMS terminal and the P-CSCF is unnecessary and infeasible due
+      to the signaling being encrypted on this leg. The terminal discovers its P-CSCF with either
+      DHCP, or it may be configured (e.g. during initial provisioning or via a 3GPP IMS Management
+      Object (MO)) or in the ISIM or assigned in the PDP Context (in General Packet Radio Service
+      (GPRS)).
+    derived_from: ims.functions.CSCF
+
+  ims.functions.I-CSCF:
+    description: >-
+      An Interrogating-CSCF (I-CSCF) is another SIP function located at the edge of an
+      administrative domain. Its IP address is published in the Domain Name System (DNS) of the
+      domain (using NAPTR and SRV type of DNS records), so that remote servers can find it, and use
+      it as a forwarding point (e.g., registering) for SIP packets to this domain.
+    derived_from: ims.functions.CSCF
+
+  ims.functions.S-CSCF:
+    description: >-
+      A Serving-CSCF (S-CSCF) is the central node of the signalling plane. It is a SIP server, but
+      performs session control too. It is always located in the home network. It uses Diameter Cx
+      and Dx interfaces to the HSS to download user profiles and upload user-to-S-CSCF associations
+      (the user profile is only cached locally for processing reasons only and is not changed). All
+      necessary subscriber profile information is loaded from the HSS.
+    derived_from: ims.functions.CSCF
+
+  ims.functions.AS:
+    description: >-
+      SIP Application servers (AS) host and execute services, and interface with the S-CSCF using
+      SIP. An example of an application server that is being developed in 3GPP is the Voice call
+      continuity Function (VCC Server). Depending on the actual service, the AS can operate in SIP
+      proxy mode, SIP UA (user agent) mode or SIP B2BUA mode. An AS can be located in the home
+      network or in an external third-party network. If located in the home network, it can query
+      the HSS with the Diameter Sh or Si interfaces (for a SIP-AS).
+    derived_from: ims.functions.Root
+
+  ims.functions.SIP-AS:
+    description: >-
+      Host and execute IMS specific services.
+    derived_from: ims.functions.AS
+
+  ims.functions.IM-SSF:
+    description: >-
+      IP Multimedia Service Switching Function. Interfaces SIP to CAP to communicate with CAMEL
+      Application Servers.
+    derived_from: ims.functions.AS
+
+  ims.functions.OSA-SCS:
+    description: >-
+      OSA service capability server. Interfaces SIP to the OSA framework.
+    derived_from: ims.functions.AS
+
+  ims.functions.AS-ILCM:
+    description: >-
+      The AS-ILCM (Application Server - Incoming Leg Control Model) stores transaction state, and
+      may optionally store session state depending on the specific service being executed. The
+      AS-ILCM interfaces to the S-CSCF (ILCM) for an incoming leg. Application Logic provides the
+      service(s) and interacts between the AS-ILCM and AS-OLCM.
+    derived_from: ims.functions.AS
+
+  ims.functions.AS-OLCM:
+    description: >-
+      The AS-OLCM (Application Server - Outgoing Leg Control Model) stores transaction state, and
+      may optionally store session state depending on the specific service being executed. The
+      AS-OLCM interfaces to the S-CSCF (OLCM) for an outgoing leg. Application Logic provides the
+      service(s) and interacts between the AS-ILCM and AS-OLCM.
+    derived_from: ims.functions.AS
+
+  ims.functions.MRF:
+    description: >-
+      The Media Resource Function (MRF) provides media related functions such as media manipulation
+      (e.g. voice stream mixing) and playing of tones and announcements.
+
+      Each MRF is further divided into a media resource function controller (MRFC) and a media
+      resource function processor (MRFP).
+    derived_from: ims.functions.Root
+
+  ims.functions.MRFC:
+    description: >-
+      The MRFC is a signalling plane node that interprets information coming from an AS and S-CSCF
+      to control the MRFP.
+    derived_from: ims.functions.Root
+
+  ims.functions.MRFP:
+    description: >-
+      The MRFP is a media plane node used to mix, source or process media streams. It can also
+      manage access right to shared resources.
+    derived_from: ims.functions.Root
+
+  ims.functions.MRB:
+    description: >-
+      The Media Resource Broker (MRB) is a functional entity that is responsible for both collection
+      of appropriate published MRF information and supplying of appropriate MRF information to
+      consuming entities such as the AS. MRB can be used in two modes:
+      * Query mode: AS queries the MRB for media and sets up the call using the response of MRB
+      * In-Line Mode: AS sends a SIP INVITE to the MRB. The MRB sets up the call
+    derived_from: ims.functions.Root
+
+  ims.functions.BGCF:
+    description: >-
+      A Breakout Gateway Control Function (BGCF) is a SIP proxy which processes requests for routing
+      from an S-CSCF when the S-CSCF has determined that the session cannot be routed using DNS or
+      ENUM/DNS. It includes routing functionality based on telephone numbers.
+    derived_from: ims.functions.Root
+
+  ims.functions.PTSNGateway:
+    description: >-
+      A PSTN/CS gateway interfaces with PSTN circuit switched (CS) networks. For signalling, CS
+      networks use ISDN User Part (ISUP) (or BICC) over Message Transfer Part (MTP), while IMS uses
+      SIP over IP. For media, CS networks use Pulse-code modulation (PCM), while IMS uses Real-time
+      Transport Protocol (RTP).
+    derived_from: ims.functions.Root
+
+  ims.functions.SGW:
+    description: >-
+      A signalling gateway (SGW) interfaces with the signalling plane of the CS. It transforms lower
+      layer protocols as Stream Control Transmission Protocol (SCTP, an IP protocol) into Message
+      Transfer Part (MTP, an Signalling System 7 (SS7) protocol), to pass ISDN User Part (ISUP) from
+      the MGCF to the CS network.
+    derived_from: ims.functions.PTSNGateway
+
+  ims.functions.MGCF:
+    description: >-
+      A media gateway controller function (MGCF) is a SIP endpoint that does call control protocol
+      conversion between SIP and ISUP/BICC and interfaces with the SGW over SCTP. It also controls
+      the resources in a Media Gateway (MGW) across an H.248 interface.
+    derived_from: ims.functions.PTSNGateway
+
+  ims.functions.MGW:
+    description: >-
+      A media gateway (MGW) interfaces with the media plane of the CS network, by converting between
+      RTP and PCM. It can also transcode when the codecs don't match (e.g., IMS might use AMR, PSTN
+      might use G.711).
+    derived_from: ims.functions.PTSNGateway
+
+  # https://en.wikipedia.org/wiki/IP_Multimedia_Subsystem#Interfaces_description
+
+  ims.interfaces.Diameter:
+    derived_from: tosca.capabilities.Endpoint
+
+  ims.interfaces.TCP:
+    derived_from: tosca.capabilities.Endpoint
+
+  ims.interfaces.SIP:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: sip
+
+  ims.interfaces.RTP:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: rtp
+
+  ims.interfaces.H248:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: h248
+
+  ims.interfaces.HTTP:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: http
+
+  ims.interfaces.MAP:
+    derived_from: tosca.capabilities.Endpoint
+    properties:
+      protocol: # override
+        type: string
+        default: map
+
+  ims.interfaces.Cr:
+    description: >-
+      Used by MRFC to fetch documents (e.g. scripts, announcement files, and other resources) from
+      an AS. Also used for media control related commands.
+    derived_from: ims.interfaces.TCP
+
+  ims.interfaces.Cx:
+    description: >-
+      Used to send subscriber data to the S-CSCF; including filter criteria and their priority. Also
+      used to furnish CDF and/or OCF addresses.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Dh:
+    description: >-
+      Used by AS to find the HSS holding the user profile information in a multi-HSS environment.
+      DH_SLF_QUERY indicates an IMPU and DX_SLF_RESP return the HSS name.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Dx:
+    description: >-
+      Used by I-CSCF or S-CSCF to find a correct HSS in a multi-HSS environment. DX_SLF_QUERY
+      indicates an IMPU and DX_SLF_RESP return the HSS name.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Gm:
+    description: >-
+      Used to exchange messages between SIP user equipment (UE) or Voip gateway and P-CSCF.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Go:
+    description: >-
+      Allows operators to control QoS in a user plane and exchange charging correlation
+      information between IMS and GPRS network.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Gq:
+    description: >-
+      Used to exchange policy decisions-related information between P-CSCF and PDF.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Gx:
+    description: >-
+      Used to exchange policy decisions-related information between PCEF and PCRF.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Gy:
+    description: >-
+      Used for online flow-based bearer charging. Functionally equivalent to Ro interface.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.ISC:
+    description: >-
+      Reference point between S-CSCF and AS. Main functions are to:
+      * Notify the AS of the registered IMPU, registration state and UE capabilities
+      * Supply the AS with information to allow it to execute multiple services
+      * Convey charging function addresses
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Ici:
+    description: >-
+      Used to exchange messages between an IBCF and another IBCF belonging to a different IMS
+      network.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Izi:
+    description: >-
+      Used to forward media streams from a TrGW to another TrGW belonging to a different IMS
+      network.
+    derived_from: ims.interfaces.RTP
+
+  ims.interfaces.Ma:
+    description: >-
+      Main functions are to:
+      * Forward SIP requests which are destined to a public service identity hosted by the AS
+      * Originate a session on behalf of a user or public service identity, if the AS has no
+        knowledge of a S-CSCF assigned to that user or public service identity
+      * Convey charging function addresses
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mg:
+    description: >-
+      ISUP signalling to SIP signalling and forwards SIP signalling to I-CSCF.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mi:
+    description: >-
+      Used to exchange messages between S-CSCF and BGCF.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mj:
+    description: >-
+      Used for the interworking with the PSTN/CS domain, when the BGCF has determined that a
+      breakout should occur in the same IMS network to send SIP message from BGCF to MGCF.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mk:
+    description: >-
+      Used for the interworking with the PSTN/CS domain, when the BGCF has determined that a
+      breakout should occur in another IMS network to send SIP message from BGCF to the BGCF in the
+      other network.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mm:
+    description: >-
+      Used for exchanging messages between IMS and external IP networks.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mn:
+    description: >-
+      Allows control of user-plane resources.
+    derived_from: ims.interfaces.H248
+
+  ims.interfaces.Mp:
+    description: >-
+      Allows an MRFC to control media stream resources provided by an MRFP.
+    derived_from: ims.interfaces.H248
+
+  ims.interfaces.Mr:
+    description: >-
+      Used to exchange information between S-CSCF and MRFC.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mr2:
+    description: >-
+      Used to exchange session controls between AS and MRFC.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mw:
+    description: >-
+      Used to exchange messages between CSCFs. AGCF appears as a P-CSCF to the other CSCFs.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Mx:
+    description: >-
+      Used for the interworking with another IMS network, when the BGCF has determined that a
+      breakout should occur in the other IMS network to send SIP message from BGCF to the IBCF in
+      the other network.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.P1:
+    description: >-
+      Used for call control services by AGCF to control H.248 A-MGW and residential gateways.
+    derived_from: ims.interfaces.H248
+
+  ims.interfaces.P2:
+    description: >-
+      Reference point between AGCF and CSCF.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Rc:
+    description: >-
+      Used by the AS to request that media resources be assigned to a call when using MRB in-line
+      mode or in query mode.
+    derived_from: ims.interfaces.SIP
+
+  ims.interfaces.Rf:
+    description: >-
+      Used to exchange offline charging information with CDF.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Ro:
+    description: >-
+        Used to exchange online charging information with OCF.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Rx:
+    description: >-
+      Used to exchange policy and charging related information between P-CSCF and PCRF. Replacement
+      for the Gq reference point.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Sh:
+    description: >-
+      Used to exchange User Profile information (e.g., user-related data, group lists,
+      user-service-related information or user location information or charging function addresses
+      (used when the AS has not received the third-party REGISTER for a user)) between an AS (SIP
+      AS or OSA SCS) and HSS. Also allow AS to activate/deactivate filter criteria stored in the HSS
+      on a per-subscriber basis.
+    derived_from: ims.interfaces.Diameter
+
+  ims.interfaces.Si:
+    description: >-
+      Transports CAMEL subscription information, including triggers for use by CAMEL-based
+      application services information.
+    derived_from: ims.interfaces.MAP
+
+  ims.interfaces.Sr:
+    description: >-
+      Used by MRFC to fetch documents (scripts and other resources) from an AS.
+    derived_from: ims.interfaces.HTTP
+
+  ims.interfaces.Ut:
+    description: >-
+      Facilitates the management of subscriber information related to services and settings.
+    derived_from: ims.interfaces.HTTP
+
+  ims.interfaces.Z:
+    description: >-
+      Conversion of POTS services to SIP messages.
+    derived_from: tosca.capabilities.Root
+
+node_types:
+
+  ims.nodes.IMS:
+    derived_from: tosca.nodes.Root
+    capabilities:
+      p-cscf: ims.functions.P-CSCF
+      i-cscf: ims.functions.I-CSCF
+      s-cscf: ims.functions.S-CSCF
+      hss: ims.functions.HSS
+      ctf: ims.functions.CTF
+      xdms: ims.functions.XDMS

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/clearwater/types/smtp.yaml
----------------------------------------------------------------------
diff --git a/examples/clearwater/types/smtp.yaml b/examples/clearwater/types/smtp.yaml
new file mode 100644
index 0000000..b79d9d2
--- /dev/null
+++ b/examples/clearwater/types/smtp.yaml
@@ -0,0 +1,21 @@
+
+capability_types:
+
+  smtp.SMTP:
+    derived_from: tosca.capabilities.Root
+    properties:
+      username:
+        type: string
+      password:
+        type: string
+
+node_types:
+
+  smtp.SMTP:
+    derived_from: tosca.nodes.SoftwareComponent
+    properties:
+      address:
+        type: string
+    capabilities:
+      smtp:
+        type: smtp.SMTP

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/hello-world/hello-world.yaml
----------------------------------------------------------------------
diff --git a/examples/hello-world/hello-world.yaml b/examples/hello-world/hello-world.yaml
new file mode 100644
index 0000000..86e2ad0
--- /dev/null
+++ b/examples/hello-world/hello-world.yaml
@@ -0,0 +1,38 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+node_types:
+
+  WebServer:
+    derived_from: tosca:Root
+    capabilities:
+      host:
+        type: tosca:Container
+
+  WebApp:
+    derived_from: tosca:WebApplication
+    properties:
+      port:
+        type: integer
+
+topology_template:
+
+  node_templates:
+    web_server:
+      type: WebServer
+
+    web_app:
+      type: WebApp
+      properties:
+        port: 9090
+      requirements:
+        - host: web_server
+      interfaces:
+        Standard:
+          configure: scripts/configure.sh
+          start: scripts/start.sh
+          stop: scripts/stop.sh
+
+  outputs:
+    port:
+      type: integer
+      value: { get_property: [ web_app, port ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/examples/hello-world/helloworld.yaml
----------------------------------------------------------------------
diff --git a/examples/hello-world/helloworld.yaml b/examples/hello-world/helloworld.yaml
deleted file mode 100644
index 2fdc4d4..0000000
--- a/examples/hello-world/helloworld.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_0
-
-node_types:
-
-  WebServer:
-    derived_from: tosca:Root
-    capabilities:
-      host:
-        type: tosca.capabilities.Container
-
-  WebApp:
-    derived_from: tosca.nodes.WebApplication
-    properties:
-      port:
-        type: integer
-
-topology_template:
-
-  node_templates:
-    web_server:
-      type: WebServer
-
-    web_app:
-      type: WebApp
-      properties:
-        port: 9090
-      requirements:
-        - host: web_server
-      interfaces:
-        Standard:
-          configure: scripts/configure.sh
-          start: scripts/start.sh
-          stop: scripts/stop.sh
-
-  outputs:
-    port:
-      type: integer
-      value: { get_property: [ web_app, port ] }

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index b912fb2..8b3bab3 100644
--- 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
@@ -24,7 +24,7 @@ topology_template:
     storage_snapshot_id:
       type: string
       description: >-
-        Optional identifier for an existing snapshot to use when creating storage.    
+        Optional identifier for an existing snapshot to use when creating storage.
     storage_location:
       type: string
       description: Block storage mount point (filesystem path).
@@ -42,8 +42,8 @@ topology_template:
         os:
           properties:
             architecture: x86_64
-            type: linux 
-            distribution: fedora 
+            type: linux
+            distribution: fedora
             version: 18.0
       requirements:
         - local_storage:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index ac475cf..9a2c0b0 100644
--- 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
@@ -29,7 +29,7 @@ topology_template:
     storage_snapshot_id:
       type: string
       description: >-
-        Optional identifier for an existing snapshot to use when creating storage.    
+        Optional identifier for an existing snapshot to use when creating storage.
     storage_location:
       type: string
       description: Block storage mount point (filesystem path).
@@ -47,8 +47,8 @@ topology_template:
         os:
           properties:
             architecture: x86_64
-            type: Linux 
-            distribution: Fedora 
+            type: Linux
+            distribution: Fedora
             version: 18.0
       requirements:
         - local_storage:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index c3f183e..0b09b34 100644
--- 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
@@ -38,8 +38,8 @@ topology_template:
         os:
           properties:
             architecture: x86_64
-            type: Linux 
-            distribution: Fedora 
+            type: Linux
+            distribution: Fedora
             version: 18.0
       requirements:
         - local_storage:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index e2bdb9f..d3c2614 100644
--- 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
@@ -33,7 +33,7 @@ topology_template:
     storage_snapshot_id:
       type: string
       description: >-
-        Optional identifier for an existing snapshot to use when creating storage.    
+        Optional identifier for an existing snapshot to use when creating storage.
 
   node_templates:
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index 24f22a3..da89dcb 100644
--- a/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml
+++ b/examples/tosca-simple-1.0/use-cases/non-normative-types.yaml
@@ -50,7 +50,7 @@ capability_types:
         required: false
       publish_ports:
         description: >-
-          List of ports mappings from source (Docker container) to target (host) ports to publish. 
+          List of ports mappings from source (Docker container) to target (host) ports to publish.
         type: list
         entry_schema: PortSpec
         required: false
@@ -118,7 +118,7 @@ node_types:
       # 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 ] 
+        valid_source_types: [ tosca.nodes.Database.MySQL ]
 
   tosca.nodes.WebServer.Apache:
     _extensions:
@@ -143,7 +143,7 @@ node_types:
         required: false # ARIA NOTE: missing in spec
     requirements:
       - database_endpoint:
-          capability: tosca.capabilities.Endpoint.Database  
+          capability: tosca.capabilities.Endpoint.Database
           node: tosca.nodes.Database
           relationship: tosca.relationships.ConnectsTo
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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
index faf109d..daa24df 100644
--- 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
@@ -51,11 +51,11 @@ topology_template:
         Standard:
           create: wordpress_install.sh
           configure:
-            implementation: wordpress_configure.sh           
+            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 ] }  
+              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 ] }
 
@@ -85,7 +85,7 @@ topology_template:
         - host: server
       interfaces:
         Standard:
-          # ARIA NOTE: not declared in spec              
+          # ARIA NOTE: not declared in spec
           #inputs:
           #  db_root_password: { get_property: [ mysql_dbms, root_password ] }
           create: mysql_dbms_install.sh
@@ -112,8 +112,8 @@ topology_template:
         os:
           properties:
             architecture: x86_64
-            type: linux 
-            distribution: fedora 
+            type: linux
+            distribution: fedora
             version: 17.0
 
   outputs:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 cfb0df5..945622f 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
@@ -24,7 +24,7 @@ artifact_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_ARTIFACTS_ROOT'
     description: >-
       This is the default (root) TOSCA Artifact Type definition that all other TOSCA base Artifact Types derive from.
-  
+
   tosca.artifacts.File:
     _extensions:
       shorthand_name: File
@@ -34,11 +34,11 @@ artifact_types:
     description: >-
       This artifact type is used when an artifact definition needs to have its associated file simply treated as a file and no special handling/handlers are invoked (i.e., it is not treated as either an implementation or deployment artifact type).
     derived_from: tosca.artifacts.Root
-  
+
   #
   # Deployments
   #
-  
+
   tosca.artifacts.Deployment:
     _extensions:
       shorthand_name: Deployment # ARIA NOTE: omitted in the spec
@@ -51,7 +51,7 @@ artifact_types:
       represents a binary packaging of an application or service that is used to install/create or deploy it as part of a node's
       lifecycle.
     derived_from: tosca.artifacts.Root
-    
+
   tosca.artifacts.Deployment.Image:
     _extensions:
       shorthand_name: Deployment.Image
@@ -64,7 +64,7 @@ artifact_types:
       (whether real or virtual) whose contents are typically already installed and pre-configured (i.e., "stateful") and prepared
       to be run on a known target container.
     derived_from: tosca.artifacts.Deployment
-  
+
   tosca.artifacts.Deployment.Image.VM:
     _extensions:
       shorthand_name: Deployment.VM # ARIA NOTE: omitted in the spec
@@ -78,11 +78,11 @@ artifact_types:
       with any configurations and can be run on another machine using a hypervisor which virtualizes typical server (i.e.,
       hardware) resources.
     derived_from: tosca.artifacts.Deployment
-  
+
   #
   # Implementations
   #
-  
+
   tosca.artifacts.Implementation:
     _extensions:
       shorthand_name: Implementation # ARIA NOTE: omitted in the spec
@@ -94,7 +94,7 @@ artifact_types:
       This artifact type represents the parent type for all implementation artifacts in TOSCA. These artifacts are used to
       implement operations of TOSCA interfaces either directly (e.g., scripts) or indirectly (e.g., config. files).
     derived_from: tosca.artifacts.Root
-  
+
   tosca.artifacts.Implementation.Bash:
     _extensions:
       shorthand_name: Implementation.Bash # ARIA NOTE: mistake in spec? shouldn't we have "Implementation." as prefix?
@@ -106,7 +106,7 @@ artifact_types:
     derived_from: tosca.artifacts.Implementation
     mime_type: application/x-sh
     file_ext: [ sh ]
-  
+
   tosca.artifacts.Implementation.Python:
     _extensions:
       shorthand_name: Implementation.Python # ARIA NOTE: mistake in spec? shouldn't we have "Implementation." as prefix?

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 b705d47..66a4046 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
@@ -51,7 +51,7 @@ capability_types:
     derived_from: tosca.capabilities.Root
     properties:
       num_cpus:
-        description: >-    
+        description: >-
           Number of (actual or virtual) CPUs associated with the Compute node.
         type: integer
         constraints:
@@ -239,7 +239,7 @@ capability_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_CAPABILITIES_ENDPOINT_PUBLIC'
     description: >-
       This capability represents a public endpoint which is accessible to the general internet (and its public IP address ranges).
-  
+
       This public endpoint capability also can be used to create a floating (IP) address that the underlying network assigns from a
       pool allocated from the application's underlying public network. This floating address is managed by the underlying network
       such that can be routed an application's private address and remains reliable to internet clients.
@@ -292,14 +292,14 @@ capability_types:
     description: >-
       This is the default TOSCA type that should be used or extended to define a specialized database endpoint capability.
     derived_from: tosca.capabilities.Endpoint
-  
+
   #
   # Network
   #
 
   tosca.capabilities.network.Bindable:
     _extensions:
-      shorthand_name: Bindable # ARIA NOTE: 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



[2/3] incubator-ariatosca git commit: ARIA-321 Provide Clearwater IMS example

Posted by em...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 771a969..61d4186 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
@@ -18,7 +18,7 @@ data_types:
   #
   # Primitive
   #
-  
+
   timestamp:
     _extensions:
       coerce_value: aria_extension_tosca.simple_v1_0.data_types.coerce_timestamp
@@ -60,7 +60,7 @@ data_types:
       specification: tosca-simple-1.0
       specification_section: 3.2.5
       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_MAP'
-  
+
   #
   # Scalar
   #
@@ -142,7 +142,7 @@ data_types:
           The optional user (name or ID) used for non-token based credentials.
         type: string
         required: false
-  
+
   tosca.datatypes.network.NetworkInfo:
     _extensions:
       shorthand_name: NetworkInfo
@@ -171,7 +171,7 @@ data_types:
         entry_schema:
           type: string
         required: false
-  
+
   tosca.datatypes.network.PortInfo:
     _extensions:
       shorthand_name: PortInfo
@@ -210,7 +210,7 @@ data_types:
         entry_schema:
           type: string
         required: false
-  
+
   tosca.datatypes.network.PortDef:
     _extensions:
       shorthand_name: PortDef

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 473bd98..29cc8dd 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
@@ -24,7 +24,7 @@ interface_types:
       specification_url: 'http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Ref384391055'
     description: >-
       This is the default (root) TOSCA Interface Type definition that all other TOSCA Interface Types derive from.
-  
+
   tosca.interfaces.node.lifecycle.Standard:
     _extensions:
       shorthand_name: Standard

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 1d2fe90..05963b7 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
@@ -45,14 +45,14 @@ node_types:
         type: tosca.interfaces.node.lifecycle.Standard
     capabilities:
       feature:
-        type: tosca.capabilities.Node  
+        type: tosca.capabilities.Node
     requirements:
       - dependency:
           capability: tosca.capabilities.Node
           node: tosca.nodes.Root
           relationship: tosca.relationships.DependsOn
           occurrences: [ 0, UNBOUNDED ]
-  
+
   tosca.nodes.Compute:
     _extensions:
       shorthand_name: Compute
@@ -133,11 +133,11 @@ node_types:
           capability: tosca.capabilities.Endpoint
           relationship: tosca.relationships.RoutesTo
           occurrences: [ 0, UNBOUNDED ]
-  
+
   #
   # Software
   #
-  
+
   tosca.nodes.SoftwareComponent:
     _extensions:
       shorthand_name: SoftwareComponent
@@ -211,7 +211,7 @@ node_types:
           capability: tosca.capabilities.Container
           node: tosca.nodes.WebServer
           relationship: tosca.relationships.HostedOn
-  
+
   tosca.nodes.DBMS:
     _extensions:
       shorthand_name: DBMS # ARIA NOTE: omitted in the spec
@@ -276,7 +276,7 @@ node_types:
           capability: tosca.capabilities.Container
           node: tosca.nodes.DBMS
           relationship: tosca.relationships.HostedOn
-  
+
   #
   # Container
   #
@@ -351,7 +351,7 @@ node_types:
     capabilities:
       storage_endpoint:
         type: tosca.capabilities.Endpoint
-  
+
   tosca.nodes.BlockStorage:
     _extensions:
       shorthand_name: BlockStorage
@@ -463,7 +463,7 @@ node_types:
     capabilities:
       link:
         type: tosca.capabilities.network.Linkable
-  
+
   tosca.nodes.network.Port:
     _extensions:
       shorthand_name: Port
@@ -472,7 +472,7 @@ node_types:
       specification_section: 7.5.2
     description: >-
       The TOSCA Port node represents a logical entity that associates between Compute and Network normative types.
-      
+
       The Port node type effectively represents a single virtual NIC on the Compute node instance.
     derived_from: tosca.nodes.Root
     properties:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 c65e38b..7b35bb9 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
@@ -24,7 +24,7 @@ policy_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_POLICIES_ROOT'
     description: >-
       This is the default (root) TOSCA Policy Type definition that all other TOSCA base Policy Types derive from.
-  
+
   tosca.policies.Placement:
     _extensions:
       shorthand_name: Placement # ARIA NOTE: omitted in the spec
@@ -35,7 +35,7 @@ policy_types:
     description: >-
       This is the default (root) TOSCA Policy Type definition that is used to govern placement of TOSCA nodes or groups of nodes.
     derived_from: tosca.policies.Root
-  
+
   tosca.policies.Scaling:
     _extensions:
       shorthand_name: Scaling # ARIA NOTE: omitted in the spec
@@ -46,7 +46,7 @@ policy_types:
     description: >-
       This is the default (root) TOSCA Policy Type definition that is used to govern scaling of TOSCA nodes or groups of nodes.
     derived_from: tosca.policies.Root
-  
+
   tosca.policies.Update:
     _extensions:
       shorthand_name: Update # ARIA NOTE: omitted in the spec
@@ -57,7 +57,7 @@ policy_types:
     description: >-
       This is the default (root) TOSCA Policy Type definition that is used to govern update of TOSCA nodes or groups of nodes.
     derived_from: tosca.policies.Root
-  
+
   tosca.policies.Performance:
     _extensions:
       shorthand_name: Performance # ARIA NOTE: omitted in the spec

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 b9d3176..9f2c32c 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
@@ -43,7 +43,7 @@ relationship_types:
     interfaces:
       Configure:
         type: tosca.interfaces.relationship.Configure
-  
+
   tosca.relationships.DependsOn:
     _extensions:
       shorthand_name: DependsOn
@@ -55,7 +55,7 @@ relationship_types:
       This type represents a general dependency relationship between two nodes.
     derived_from: tosca.relationships.Root
     valid_target_types: [ tosca.capabilities.Node ]
-  
+
   tosca.relationships.HostedOn:
     _extensions:
       shorthand_name: HostedOn
@@ -67,7 +67,7 @@ relationship_types:
       This type represents a hosting relationship between two nodes.
     derived_from: tosca.relationships.Root
     valid_target_types: [ tosca.capabilities.Container ]
-  
+
   tosca.relationships.ConnectsTo:
     _extensions:
       shorthand_name: ConnectsTo
@@ -83,7 +83,7 @@ relationship_types:
       credential:
         type: tosca.datatypes.Credential
         required: false
-  
+
   tosca.relationships.AttachesTo:
     _extensions:
       shorthand_name: AttachesTo
@@ -116,7 +116,7 @@ relationship_types:
           The logical name of the device as exposed to the instance.
           Note: A runtime property that gets set when the model gets instantiated by the orchestrator.
         type: string
-  
+
   tosca.relationships.RoutesTo:
     _extensions:
       shorthand_name: RoutesTo
@@ -128,11 +128,11 @@ relationship_types:
       This type represents an intentional network routing between two Endpoints in different networks.
     derived_from: tosca.relationships.ConnectsTo
     valid_target_types: [ tosca.capabilities.Endpoint ]
-  
+
   #
   # Network
   #
-  
+
   tosca.relationships.network.LinksTo:
     _extensions:
       shorthand_name: LinksTo
@@ -144,7 +144,7 @@ relationship_types:
       This relationship type represents an association relationship between Port and Network node types.
     derived_from: tosca.relationships.DependsOn
     valid_target_types: [ tosca.capabilities.network.Linkable ]
-  
+
   tosca.relationships.network.BindsTo:
     _extensions:
       shorthand_name: BindsTo # ARIA NOTE: the spec says "network.BindsTo" which seems wrong

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/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 73f0ecd..8d1f0a2 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
@@ -98,11 +98,11 @@ node_types:
         # ARIA NOTE: commented out in 5.9.2.5
         description: >-
           Monitoring parameter, which can be tracked for a VNFC based on this VDU. Examples include:
-          memory-consumption, CPU-utilisation, bandwidth-consumption, VNFC downtime, etc.        
+          memory-consumption, CPU-utilisation, bandwidth-consumption, VNFC downtime, etc.
         type: tosca.capabilities.nfv.Metric
     #requirements:
       # ARIA NOTE: virtual_storage is TBD
-      
+
       # ARIA NOTE: csd04 attempts to deprecate the inherited local_storage requirement, but this
       # is not possible in TOSCA
     artifacts:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/data_types.py
index 513b517..216f1e4 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/data_types.py
@@ -163,7 +163,7 @@ class Version(object):
     #TYPE_TOSCA_VERSION>`__
     """
 
-    REGULAR = \
+    REGEX = \
         r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<fix>\d+)' + \
         r'((\.(?P<qualifier>\d+))(\-(?P<build>\d+))?)?)?$'
 
@@ -176,7 +176,7 @@ class Version(object):
 
     def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
         str_value = str(value)
-        match = re.match(Version.REGULAR, str_value)
+        match = re.match(Version.REGEX, str_value)
         if match is None:
             raise ValueError(
                 'version must be formatted as <major_version>.<minor_version>'
@@ -376,11 +376,14 @@ class Scalar(object):
 
     def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument
         str_value = str(value)
-        match = re.match(self.REGULAR, str_value) # pylint: disable=no-member
+        match = re.match(self.REGEX, str_value) # pylint: disable=no-member
         if match is None:
             raise ValueError('scalar must be formatted as <scalar> <unit>: %s' % safe_repr(value))
 
         self.factor = float(match.group('scalar'))
+        if self.factor < 0:
+            raise ValueError('scalar is negative: %s' % safe_repr(self.factor))
+
         self.unit = match.group('unit')
 
         unit_lower = self.unit.lower()
@@ -435,7 +438,7 @@ class ScalarSize(Scalar):
     """
 
     # See: http://www.regular-expressions.info/floatingpoint.html
-    REGULAR = \
+    REGEX = \
         r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>B|kB|KiB|MB|MiB|GB|GiB|TB|TiB)$'
 
     UNITS = {
@@ -464,7 +467,7 @@ class ScalarTime(Scalar):
     """
 
     # See: http://www.regular-expressions.info/floatingpoint.html
-    REGULAR = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>ns|us|ms|s|m|h|d)$'
+    REGEX = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>ns|us|ms|s|m|h|d)$'
 
     UNITS = {
         'ns':     0.000000001,
@@ -490,7 +493,7 @@ class ScalarFrequency(Scalar):
     """
 
     # See: http://www.regular-expressions.info/floatingpoint.html
-    REGULAR = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>Hz|kHz|MHz|GHz)$'
+    REGEX = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>Hz|kHz|MHz|GHz)$'
 
     UNITS = {
         'Hz':           1.0,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
index 5427c7e..1b95bec 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/capabilities.py
@@ -68,12 +68,14 @@ def get_inherited_capability_definitions(context, presentation, for_presentation
                 capability_definition = capability_definitions[capability_name]
 
                 # Check if we changed the type
-                type1 = capability_definition.type
-                type2 = our_capability_definition.type
-                if type1 != type2:
+                type1 = capability_definition._get_type(context)
+                type2 = our_capability_definition._get_type(context)
+
+                if not type1._is_descendant(context, type2):
                     context.validation.report(
-                        'capability definition changes type from "{0}" to "{1}" in "{2}"'
-                        .format(type1, type2, presentation._fullname),
+                        'capability definition type "{0}" is not a descendant of overridden '
+                        'capability definition type "{1}"' \
+                        .format(type1._name, type2._name),
                         locator=our_capability_definition._locator, level=Issue.BETWEEN_TYPES)
 
                 merge_capability_definition(context, presentation, capability_definition,
@@ -168,6 +170,8 @@ def merge_capability_definition(context, presentation, capability_definition,
                                 from_capability_definition):
     raw_properties = OrderedDict()
 
+    capability_definition._raw['type'] = from_capability_definition.type
+
     # Merge properties from type
     from_property_defintions = from_capability_definition.properties
     merge_raw_parameter_definitions(context, presentation, raw_properties, from_property_defintions,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
index fbb8280..5bdbb43 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/data_types.py
@@ -159,10 +159,6 @@ def get_data_type(context, presentation, field_name, allow_none=False):
         else:
             return str
 
-    # Make sure not derived from self
-    if type_name == presentation._name:
-        return None
-
     # Avoid circular definitions
     container_data_type = get_container_data_type(presentation)
     if (container_data_type is not None) and (container_data_type._name == type_name):

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
index 590c6a0..ecbfde9 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/functions.py
@@ -200,20 +200,24 @@ class GetProperty(Function):
         for modelable_entity in modelable_entities:
             properties = None
 
+            # First argument refers to a requirement template?
             if hasattr(modelable_entity, 'requirement_templates') \
                 and modelable_entity.requirement_templates \
                 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...
+                for requirement in modelable_entity.requirement_templates:
+                    if requirement.name == req_or_cap_name:
+                        # TODO
                         raise CannotEvaluateFunctionException()
-                        # break
+            # First argument refers to a capability?
+            elif hasattr(modelable_entity, 'capabilities') \
+                and modelable_entity.capabilities \
+                and (req_or_cap_name in modelable_entity.capabilities):
+                properties = modelable_entity.capabilities[req_or_cap_name].properties
                 nested_property_name_or_index = self.nested_property_name_or_index[1:]
+            # First argument refers to a capability template?
             elif hasattr(modelable_entity, 'capability_templates') \
                 and modelable_entity.capability_templates \
                 and (req_or_cap_name in modelable_entity.capability_templates):
-                # First argument refers to a capability
                 properties = modelable_entity.capability_templates[req_or_cap_name].properties
                 nested_property_name_or_index = self.nested_property_name_or_index[1:]
             else:
@@ -640,7 +644,7 @@ def get_target(container_holder, name, locator):
 
 def get_modelable_entity_parameter(modelable_entity, parameters, nested_parameter_name_or_index):
     if not parameters:
-        return False, True, None
+        return Evaluation(None, True)
 
     found = True
     final = True

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
index d5f447c..d41aa81 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/interfaces.py
@@ -400,13 +400,15 @@ def merge_raw_operation_definitions(context, raw_operations, our_operations, int
 def merge_interface_definition(context, interface, our_source, presentation, type_name):
     if hasattr(our_source, 'type'):
         # Check if we changed the interface type
-        input_type1 = interface.type
-        input_type2 = our_source.type
-        if (input_type1 is not None) and (input_type2 is not None) and (input_type1 != input_type2):
+        type1 = interface._get_type(context)
+        type2 = our_source._get_type(context)
+
+        if (type2 is not None) and not type1._is_descendant(context, type2):
             context.validation.report(
-                'interface definition "%s" changes type from "%s" to "%s" in "%s"'
-                % (interface._name, input_type1, input_type2, presentation._fullname),
-                locator=input_type2._locator, level=Issue.BETWEEN_TYPES)
+                'interface definition type "{0}" is not a descendant of overridden '
+                'interface definition type "{1}"' \
+                .format(type1._name, type2._name),
+                locator=our_source._locator, level=Issue.BETWEEN_TYPES)
 
     # Add/merge inputs
     our_interface_inputs = our_source._get_inputs(context) \

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
index 87c1a3b..bc884e2 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/parameters.py
@@ -18,7 +18,8 @@ from aria.utils.formatting import pluralize
 from aria.parser.presentation import Value
 from aria.parser.validation import Issue
 
-from .data_types import coerce_value
+from .data_types import (coerce_value, get_primitive_data_type)
+from ..presentation.types import get_type_by_name
 
 
 #
@@ -149,16 +150,22 @@ def validate_required_values(context, presentation, values, definitions):
 
 def merge_raw_parameter_definition(context, presentation, raw_property_definition,
                                    our_property_definition, field_name, property_name):
-    # Check if we changed the type
-    # TODO: allow a sub-type?
-    type1 = raw_property_definition.get('type')
-    type2 = our_property_definition.type
+    # Check if we changed the parameter type
+    type1_name = raw_property_definition.get('type')
+    type1 = get_type_by_name(context, type1_name, 'data_types')
+    if type1 is None:
+        type1 = get_primitive_data_type(type1_name)
+    our_property_definition._reset_method_cache()
+    type2 = our_property_definition._get_type(context)
+
     if type1 != type2:
-        context.validation.report(
-            'override changes type from "%s" to "%s" for property "%s" in "%s"'
-            % (type1, type2, property_name, presentation._fullname),
-            locator=presentation._get_child_locator(field_name, property_name),
-            level=Issue.BETWEEN_TYPES)
+        if not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2):
+            context.validation.report(
+                'property definition type "{0}" is not a descendant of overridden '
+                'property definition type "{1}"' \
+                .format(type1_name, type2._name),
+                locator=presentation._get_child_locator(field_name, property_name),
+                level=Issue.BETWEEN_TYPES)
 
     merge(raw_property_definition, our_property_definition._raw)
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
index 920ebed..5f9750e 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/presentation/types.py
@@ -18,7 +18,8 @@ def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable
     """
     Converts a type name to its full type name, or else returns it unchanged.
 
-    Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also
+    Works by checking for ``shorthand_name`` and ``type_qualified_name`` in the types'
+    ``_extensions`` field. See also
     :class:`aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`.
 
     Can be used as the conversion function argument in ``type_validator`` and
@@ -36,9 +37,10 @@ def convert_name_to_full_type_name(context, name, types_dict): # pylint: disable
 
 def get_type_by_name(context, name, *types_dict_names):
     """
-    Gets a type either by its full name or its shorthand name or typequalified name.
+    Gets a type either by its full name or its shorthand name or type-qualified name.
 
-    Works by checking for ``shorthand_name`` in the types' ``_extensions`` field. See also
+    Works by checking for ``shorthand_name`` and ``type_qualified_name`` in the types'
+    ``_extensions`` field. See also
     :class:`~aria_extension_tosca.v1_0.presentation.extensible.ExtensiblePresentation`.
 
     The arguments from the third onwards are used to locate a nested field under

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/extensions/aria_extension_tosca/simple_v1_0/types.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/types.py b/extensions/aria_extension_tosca/simple_v1_0/types.py
index 787aac2..b662a20 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/types.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/types.py
@@ -193,6 +193,17 @@ class DataType(ExtensiblePresentation):
         return get_data_type(context, self, 'derived_from', allow_none=True)
 
     @cachedmethod
+    def _is_descendant(self, context, the_type):
+        if the_type is None:
+            return False
+        if not hasattr(the_type, '_name'):
+            # Must be a primitive type
+            return self._get_primitive_ancestor(context) == the_type
+        if the_type._name == self._name:
+            return True
+        return self._is_descendant(context, the_type._get_parent(context))
+
+    @cachedmethod
     def _get_primitive_ancestor(self, context):
         parent = self._get_parent(context)
         if parent is not None:
@@ -387,6 +398,14 @@ class InterfaceType(ExtensiblePresentation):
                                        'interface_types')
 
     @cachedmethod
+    def _is_descendant(self, context, the_type):
+        if the_type is None:
+            return False
+        elif the_type._name == self._name:
+            return True
+        return self._is_descendant(context, the_type._get_parent(context))
+
+    @cachedmethod
     def _get_inputs(self, context):
         return FrozenDict(get_inherited_parameter_definitions(context, self, 'inputs'))
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/end2end/test_hello_world.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_hello_world.py b/tests/end2end/test_hello_world.py
index 5e4d7fd..094ffc3 100644
--- a/tests/end2end/test_hello_world.py
+++ b/tests/end2end/test_hello_world.py
@@ -20,7 +20,7 @@ from .. import helpers
 
 
 def test_hello_world(testenv):
-    hello_world_template_uri = helpers.get_example_uri('hello-world', 'helloworld.yaml')
+    hello_world_template_uri = helpers.get_example_uri('hello-world', 'hello-world.yaml')
     service_name = testenv.install_service(hello_world_template_uri)
 
     try:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
index 5a46532..260f0bf 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -89,7 +89,7 @@ topology_template:
       value: *DEFAULT_OPENSTACK_CREDENTIAL
 
   node_templates:
-  
+
     # Application
 
     node_cellar:
@@ -135,7 +135,7 @@ topology_template:
           properties:
             protocol: udp
             url_path: /nodecellar
-    
+
     node_cellar_database:
       description: >-
         Node Cellar MongoDB database.
@@ -151,7 +151,7 @@ topology_template:
           repository: node_cellar
 
     # Server software
-    
+
     nodejs:
       description: >-
         Node.js instance.
@@ -202,7 +202,7 @@ topology_template:
     loadbalancer:
       type: nginx.LoadBalancer
       properties:
-        algorithm: round-robin   
+        algorithm: round-robin
 
     # Hosts
 
@@ -273,7 +273,7 @@ topology_template:
           create: create_data_volume.sh
 
   groups:
-  
+
     node_cellar_group:
       type: openstack.Secured
       members:
@@ -286,7 +286,7 @@ topology_template:
             openstack_credential: { get_input: openstack_credential }
 
   policies:
-  
+
     app_scaling:
       type: aria.Scaling
       properties:
@@ -295,7 +295,7 @@ topology_template:
       targets:
         - node_cellar
         - nodejs
-  
+
     host_scaling:
       type: openstack.Scaling
       properties:
@@ -304,7 +304,7 @@ topology_template:
         default_instances: 2
       targets: # node templates or groups
         - node_cellar_group
-    
+
     juju:
       description: >-
         Juju plugin executes charms.
@@ -345,7 +345,7 @@ policy_types:
     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. 
+      client connections cleanly and shut down services.
     derived_from: aria.Workflow
     properties:
       implementation:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
index 34d0a9d..7031252 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/mongodb.yaml
@@ -44,7 +44,7 @@ node_types:
   mongodb.Database:
     description: >-
       MongoDB database.
-      
+
       Supports importing database data if a mongodb.DatabaseDump is provided.
     derived_from: tosca.nodes.Database
     interfaces:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
index 19cc7b9..2b4d451 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/nodejs.yaml
@@ -30,7 +30,7 @@ node_types:
         file: https://nodejs.org/dist/v4.4.7/node-v4.4.7-linux-x64.tar.xz
         deploy_path: /opt/nodejs
     capabilities:
-      data_endpoint: # @override 
+      data_endpoint: # @override
         type: tosca.capabilities.Endpoint
         properties:
           port:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
index 99ee902..6941c1a 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/types/openstack.yaml
@@ -31,7 +31,7 @@ node_types:
 
       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
@@ -87,7 +87,7 @@ node_types:
   openstack.Volume:
     description: >-
       OpenStack volume.
-      
+
       See: http://developer.openstack.org/api-ref-blockstorage-v2.html
     derived_from: tosca.nodes.BlockStorage
     properties:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/types/shorthand-1/shorthand-1.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/types/shorthand-1/shorthand-1.yaml b/tests/resources/service-templates/tosca-simple-1.0/types/shorthand-1/shorthand-1.yaml
index b295f95..bb5a84e 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/types/shorthand-1/shorthand-1.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/types/shorthand-1/shorthand-1.yaml
@@ -6,17 +6,17 @@ description: >-
 topology_template:
 
   node_templates:
-  
+
     my_server:
       type: Compute
       requirements:
         - local_storage:
-            node: my_block_storage           
+            node: my_block_storage
             relationship:
               type: AttachesTo
               properties:
                 location: /path1/path2
-  
+
     my_block_storage:
       type: BlockStorage
       properties:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a638acdf/tests/resources/service-templates/tosca-simple-1.0/types/typequalified-1/typequalified-1.yaml
----------------------------------------------------------------------
diff --git a/tests/resources/service-templates/tosca-simple-1.0/types/typequalified-1/typequalified-1.yaml b/tests/resources/service-templates/tosca-simple-1.0/types/typequalified-1/typequalified-1.yaml
index 5f11fd4..b54604f 100644
--- a/tests/resources/service-templates/tosca-simple-1.0/types/typequalified-1/typequalified-1.yaml
+++ b/tests/resources/service-templates/tosca-simple-1.0/types/typequalified-1/typequalified-1.yaml
@@ -6,17 +6,17 @@ description: >-
 topology_template:
 
   node_templates:
-  
+
     my_server:
       type: tosca:Compute
       requirements:
         - local_storage:
-            node: my_block_storage           
+            node: my_block_storage
             relationship:
               type: AttachesTo
               properties:
                 location: /path1/path2
-  
+
     my_block_storage:
       type: tosca:BlockStorage
       properties: