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

[22/30] incubator-ariatosca git commit: ARIA-174 Refactor instantiation phase

ARIA-174 Refactor instantiation phase

The main issue this PR addressed was the consolidation
of instantiation mechanism into a single package - `topology`.

The code itself got additional refactoring:
1. `dump` no longer prints onto the console but rather returns a string representation to be printed.
2. The service related consumers use the new `topology` package.

These additional issues were fixed as part of this PR:
* Req-Cap mechanism is now trying to satisfy requirements for a specific capability type.
* Issue with resuming workflows - accessing a non existing attribute.


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

Branch: refs/heads/new_wagon_setuptools
Commit: df2b916e624719e5f77e29c1e893c55f88e15862
Parents: a43bc6b
Author: max-orlov <ma...@gigaspaces.com>
Authored: Thu Jul 13 16:49:15 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Wed Aug 9 15:52:08 2017 +0300

----------------------------------------------------------------------
 aria/cli/commands/executions.py                 |   2 +-
 aria/cli/commands/service_templates.py          |   7 +-
 aria/cli/commands/services.py                   |   6 +-
 aria/core.py                                    |  36 +-
 aria/modeling/functions.py                      |   3 +-
 aria/modeling/mixins.py                         |  42 +-
 aria/modeling/service_common.py                 |  27 -
 aria/modeling/service_instance.py               | 535 +-------------
 aria/modeling/service_template.py               | 740 +------------------
 aria/modeling/utils.py                          |  85 +--
 .../execution_plugin/instantiation.py           | 113 ++-
 aria/orchestrator/topology/__init__.py          |  16 +
 aria/orchestrator/topology/common.py            |  69 ++
 aria/orchestrator/topology/instance_handler.py  | 671 +++++++++++++++++
 aria/orchestrator/topology/template_handler.py  | 606 +++++++++++++++
 aria/orchestrator/topology/topology.py          | 223 ++++++
 aria/orchestrator/topology/utils.py             |  48 ++
 aria/orchestrator/workflow_runner.py            |   5 +-
 aria/orchestrator/workflows/api/task.py         |   5 +-
 aria/parser/consumption/__init__.py             |   3 -
 aria/parser/consumption/consumer.py             |   7 +
 aria/parser/consumption/context.py              |   4 +-
 aria/parser/consumption/modeling.py             |  32 +-
 aria/parser/consumption/style.py                |  54 --
 aria/parser/modeling/context.py                 |   6 +-
 aria/parser/presentation/fields.py              |  16 +-
 aria/parser/presentation/presentation.py        |  14 +-
 aria/parser/reading/__init__.py                 |   6 +-
 aria/parser/reading/locator.py                  |  35 -
 aria/parser/validation/context.py               |  59 +-
 aria/parser/validation/issue.py                 |  72 +-
 aria/utils/__init__.py                          |  47 ++
 aria/utils/console.py                           |  49 +-
 .../aria_extension_tosca/simple_v1_0/misc.py    |   2 +-
 .../simple_v1_0/modeling/__init__.py            |   9 +-
 tests/parser/service_templates.py               |  18 +-
 tests/parser/test_reqs_caps.py                  |  29 +
 .../tosca-simple-1.0/reqs_caps/reqs_caps1.yaml  |  40 +
 tests/storage/__init__.py                       |   2 -
 39 files changed, 2069 insertions(+), 1674 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/cli/commands/executions.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/executions.py b/aria/cli/commands/executions.py
index 4783442..f130d95 100644
--- a/aria/cli/commands/executions.py
+++ b/aria/cli/commands/executions.py
@@ -181,7 +181,7 @@ def resume(execution_id,
     executor = DryExecutor() if dry else None  # use WorkflowRunner's default executor
 
     execution = model_storage.execution.get(execution_id)
-    if execution.status != execution.status.CANCELLED:
+    if execution.status != execution.CANCELLED:
         logger.info("Can't resume execution {execution.id} - "
                     "execution is in status {execution.status}. "
                     "Can only resume executions in status {valid_status}"

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/cli/commands/service_templates.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/service_templates.py b/aria/cli/commands/service_templates.py
index f567aa8..5a7039c 100644
--- a/aria/cli/commands/service_templates.py
+++ b/aria/cli/commands/service_templates.py
@@ -28,7 +28,7 @@ from ...core import Core
 from ...storage import exceptions as storage_exceptions
 from ...parser import consumption
 from ...utils import (formatting, collections, console)
-
+from ... orchestrator import topology
 
 DESCRIPTION_FIELD_LENGTH_LIMIT = 20
 SERVICE_TEMPLATE_COLUMNS = \
@@ -73,10 +73,9 @@ def show(service_template_name, model_storage, mode_full, mode_types, format_jso
         elif format_yaml:
             console.puts(formatting.yaml_dumps(collections.prune(service_template.as_raw)))
         else:
-            service_template.dump()
+            console.puts(topology.Topology().dump(service_template))
     elif mode_types:
-        consumption.ConsumptionContext()
-        service_template.dump_types()
+        console.puts(topology.Topology().dump_types(service_template=service_template))
     else:
         logger.info('Showing service template {0}...'.format(service_template_name))
         service_template_dict = service_template.to_dict()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/cli/commands/services.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands/services.py b/aria/cli/commands/services.py
index a99f5b3..6752899 100644
--- a/aria/cli/commands/services.py
+++ b/aria/cli/commands/services.py
@@ -30,6 +30,7 @@ from ...modeling import exceptions as modeling_exceptions
 from ...storage import exceptions as storage_exceptions
 from ...parser import consumption
 from ...utils import (formatting, collections, console)
+from ...orchestrator import topology
 
 
 DESCRIPTION_FIELD_LENGTH_LIMIT = 20
@@ -73,10 +74,9 @@ def show(service_name, model_storage, mode_full, mode_graph, format_json, format
         elif format_yaml:
             console.puts(formatting.yaml_dumps(collections.prune(service.as_raw)))
         else:
-            service.dump()
+            console.puts(topology.Topology().dump(service))
     elif mode_graph:
-        consumption.ConsumptionContext()
-        service.dump_graph()
+        console.puts(topology.Topology().dump_graph(service))
     else:
         logger.info('Showing service {0}...'.format(service_name))
         service_dict = service.to_dict()

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/core.py
----------------------------------------------------------------------
diff --git a/aria/core.py b/aria/core.py
index e214b1a..e3b3b36 100644
--- a/aria/core.py
+++ b/aria/core.py
@@ -20,6 +20,7 @@ ARIA core module.
 from . import exceptions
 from .parser import consumption
 from .parser.loading.location import UriLocation
+from .orchestrator import topology
 
 
 class Core(object):
@@ -67,31 +68,26 @@ class Core(object):
         self.resource_storage.service_template.delete(entry_id=str(service_template.id))
 
     def create_service(self, service_template_id, inputs, service_name=None):
-
         service_template = self.model_storage.service_template.get(service_template_id)
 
-        # creating an empty ConsumptionContext, initiating a threadlocal context
-        context = consumption.ConsumptionContext()
-
         storage_session = self.model_storage._all_api_kwargs['session']
         # setting no autoflush for the duration of instantiation - this helps avoid dependency
         # constraints as they're being set up
         with storage_session.no_autoflush:
-            service = service_template.instantiate(None, self.model_storage, inputs=inputs)
-
-            consumption.ConsumerChain(
-                context,
-                (
-                    consumption.CoerceServiceInstanceValues,
-                    consumption.ValidateServiceInstance,
-                    consumption.SatisfyRequirements,
-                    consumption.CoerceServiceInstanceValues,
-                    consumption.ValidateCapabilities,
-                    consumption.FindHosts,
-                    consumption.ConfigureOperations,
-                    consumption.CoerceServiceInstanceValues
-                )).consume()
-            if context.validation.dump_issues():
+            topology_ = topology.Topology()
+            service = topology_.instantiate(
+                service_template, inputs=inputs, plugins=self.model_storage.plugin.list())
+            topology_.coerce(service, report_issues=True)
+
+            topology_.validate(service)
+            topology_.satisfy_requirements(service)
+            topology_.coerce(service, report_issues=True)
+
+            topology_.validate_capabilities(service)
+            topology_.assign_hosts(service)
+            topology_.configure_operations(service)
+            topology_.coerce(service, report_issues=True)
+            if topology_.dump_issues():
                 raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
                                                     .format(service_template.name))
 
@@ -122,6 +118,8 @@ class Core(object):
     def _parse_service_template(service_template_path):
         context = consumption.ConsumptionContext()
         context.presentation.location = UriLocation(service_template_path)
+        # Most of the parser uses the topology package in order to manipulate the models.
+        # However, here we use the Consumer mechanism, but this should change in the future.
         consumption.ConsumerChain(
             context,
             (

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index 6544adf..31c3839 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -16,9 +16,8 @@
 """
 Mechanism for evaluating intrinsic functions.
 """
-
-from ..parser.consumption import ConsumptionContext
 from ..parser.exceptions import InvalidValueError
+from ..parser.consumption import ConsumptionContext
 from ..utils.collections import OrderedDict
 from . import exceptions
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index 4acbe6e..d58c25a 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -25,8 +25,7 @@ from sqlalchemy import (
     PickleType
 )
 
-from ..parser.consumption import ConsumptionContext
-from ..utils import console, collections, caching, formatting
+from ..utils import collections, caching
 from ..utils.type import canonical_type_name, full_type_name
 from . import utils, functions
 
@@ -132,26 +131,17 @@ class InstanceModelMixin(ModelMixin):
     def as_raw(self):
         raise NotImplementedError
 
-    def validate(self):
-        pass
-
     def coerce_values(self, report_issues):
         pass
 
-    def dump(self):
-        pass
-
 
-class TemplateModelMixin(InstanceModelMixin):
+class TemplateModelMixin(InstanceModelMixin):                                                       # pylint: disable=abstract-method
     """
     Mix-in for service template models.
 
     All model models can be instantiated into service instance models.
     """
 
-    def instantiate(self, container):
-        raise NotImplementedError
-
 
 class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):                                 #pylint: disable=abstract-method
     """
@@ -306,34 +296,6 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
             ('value', self.value),
             ('description', self.description)))
 
-    def instantiate(self, container):
-        return self.__class__(name=self.name,  # pylint: disable=unexpected-keyword-arg
-                              type_name=self.type_name,
-                              _value=self._value,
-                              description=self.description)
-
-    def coerce_values(self, report_issues):
-        value = self._value
-        if value is not None:
-            evaluation = functions.evaluate(value, self, report_issues)
-            if (evaluation is not None) and evaluation.final:
-                # A final evaluation can safely replace the existing value
-                self._value = evaluation.value
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type_name is not None:
-            console.puts('{0}: {1} ({2})'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value)),
-                context.style.type(self.type_name)))
-        else:
-            console.puts('{0}: {1}'.format(
-                context.style.property(self.name),
-                context.style.literal(formatting.as_raw(self.value))))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-
     @property
     def unwrapped(self):
         return self.name, self.value

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 4ce9dae..478e530 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -26,11 +26,9 @@ from sqlalchemy import (
 )
 from sqlalchemy.ext.declarative import declared_attr
 
-from ..parser.consumption import ConsumptionContext
 from ..utils import (
     collections,
     formatting,
-    console,
 )
 from .mixins import InstanceModelMixin, TemplateModelMixin, ParameterMixin
 from . import relationship
@@ -563,17 +561,6 @@ class TypeBase(InstanceModelMixin):
         self._append_raw_children(types)
         return types
 
-    def coerce_values(self, report_issues):
-        pass
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.type(self.name))
-        with context.style.indent:
-            for child in self.children:
-                child.dump()
-
     def _append_raw_children(self, types):
         for child in self.children:
             raw_child = formatting.as_raw(child)
@@ -612,17 +599,3 @@ class MetadataBase(TemplateModelMixin):
         return collections.OrderedDict((
             ('name', self.name),
             ('value', self.value)))
-
-    def coerce_values(self, report_issues):
-        pass
-
-    def instantiate(self, container):
-        from . import models
-        return models.Metadata(name=self.name,
-                               value=self.value)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('{0}: {1}'.format(
-            context.style.property(self.name),
-            context.style.literal(self.value)))

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index ae6a0a0..daeb0a4 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -30,19 +30,15 @@ from sqlalchemy import DateTime
 from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.ext.orderinglist import ordering_list
 
+from . import (
+    relationship,
+    types as modeling_types
+)
 from .mixins import InstanceModelMixin
-from ..orchestrator import execution_plugin
-from ..parser import validation
-from ..parser.consumption import ConsumptionContext
+
 from ..utils import (
     collections,
     formatting,
-    console
-)
-from . import (
-    relationship,
-    utils,
-    types as modeling_types
 )
 
 
@@ -232,50 +228,6 @@ class ServiceBase(InstanceModelMixin):
     :type: :class:`~datetime.datetime`
     """)
 
-    def satisfy_requirements(self):
-        satisfied = True
-        for node in self.nodes.itervalues():
-            if not node.satisfy_requirements():
-                satisfied = False
-        return satisfied
-
-    def validate_capabilities(self):
-        satisfied = True
-        for node in self.nodes.itervalues():
-            if not node.validate_capabilities():
-                satisfied = False
-        return satisfied
-
-    def find_hosts(self):
-        for node in self.nodes.itervalues():
-            node.find_host()
-
-    def configure_operations(self):
-        for node in self.nodes.itervalues():
-            node.configure_operations()
-        for group in self.groups.itervalues():
-            group.configure_operations()
-        for operation in self.workflows.itervalues():
-            operation.configure()
-
-    def is_node_a_target(self, target_node):
-        for node in self.nodes.itervalues():
-            if self._is_node_a_target(node, target_node):
-                return True
-        return False
-
-    def _is_node_a_target(self, source_node, target_node):
-        if source_node.outbound_relationships:
-            for relationship_model in source_node.outbound_relationships:
-                if relationship_model.target_node.name == target_node.name:
-                    return True
-                else:
-                    node = relationship_model.target_node
-                    if node is not None:
-                        if self._is_node_a_target(node, target_node):
-                            return True
-        return False
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -289,70 +241,6 @@ class ServiceBase(InstanceModelMixin):
             ('outputs', formatting.as_raw_dict(self.outputs)),
             ('workflows', formatting.as_raw_list(self.workflows))))
 
-    def validate(self):
-        utils.validate_dict_values(self.meta_data)
-        utils.validate_dict_values(self.nodes)
-        utils.validate_dict_values(self.groups)
-        utils.validate_dict_values(self.policies)
-        if self.substitution is not None:
-            self.substitution.validate()
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.outputs)
-        utils.validate_dict_values(self.workflows)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.meta_data, report_issues)
-        utils.coerce_dict_values(self.nodes, report_issues)
-        utils.coerce_dict_values(self.groups, report_issues)
-        utils.coerce_dict_values(self.policies, report_issues)
-        if self.substitution is not None:
-            self.substitution.coerce_values(report_issues)
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.outputs, report_issues)
-        utils.coerce_dict_values(self.workflows, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.description is not None:
-            console.puts(context.style.meta(self.description))
-        utils.dump_dict_values(self.meta_data, 'Metadata')
-        for node in self.nodes.itervalues():
-            node.dump()
-        for group in self.groups.itervalues():
-            group.dump()
-        for policy in self.policies.itervalues():
-            policy.dump()
-        if self.substitution is not None:
-            self.substitution.dump()
-        utils.dump_dict_values(self.inputs, 'Inputs')
-        utils.dump_dict_values(self.outputs, 'Outputs')
-        utils.dump_dict_values(self.workflows, 'Workflows')
-
-    def dump_graph(self):
-        for node in self.nodes.itervalues():
-            if not self.is_node_a_target(node):
-                self._dump_graph_node(node)
-
-    def _dump_graph_node(self, node, capability=None):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(node.name))
-        if capability is not None:
-            console.puts('{0} ({1})'.format(context.style.property(capability.name),
-                                            context.style.type(capability.type.name)))
-        if node.outbound_relationships:
-            with context.style.indent:
-                for relationship_model in node.outbound_relationships:
-                    relationship_name = context.style.property(relationship_model.name)
-                    if relationship_model.type is not None:
-                        console.puts('-> {0} ({1})'.format(relationship_name,
-                                                           context.style.type(
-                                                               relationship_model.type.name)))
-                    else:
-                        console.puts('-> {0}'.format(relationship_name))
-                    with console.indent(3):
-                        self._dump_graph_node(relationship_model.target_node,
-                                              relationship_model.target_capability)
-
 
 class NodeBase(InstanceModelMixin):
     """
@@ -616,118 +504,6 @@ class NodeBase(InstanceModelMixin):
             return attribute.value if attribute else None
         return None
 
-    def satisfy_requirements(self):
-        node_template = self.node_template
-        satisfied = True
-        for requirement_template in node_template.requirement_templates:
-            # Find target template
-            target_node_template, target_node_capability = \
-                requirement_template.find_target(node_template)
-            if target_node_template is not None:
-                satisfied = self._satisfy_capability(target_node_capability,
-                                                     target_node_template,
-                                                     requirement_template)
-            else:
-                context = ConsumptionContext.get_thread_local()
-                context.validation.report('requirement "{0}" of node "{1}" has no target node '
-                                          'template'.format(requirement_template.name, self.name),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
-                satisfied = False
-        return satisfied
-
-    def _satisfy_capability(self, target_node_capability, target_node_template,
-                            requirement_template):
-        from . import models
-        context = ConsumptionContext.get_thread_local()
-        # Find target nodes
-        target_nodes = target_node_template.nodes
-        if target_nodes:
-            target_node = None
-            target_capability = None
-
-            if target_node_capability is not None:
-                # Relate to the first target node that has capacity
-                for node in target_nodes:
-                    a_target_capability = node.capabilities.get(target_node_capability.name)
-                    if a_target_capability.relate():
-                        target_node = node
-                        target_capability = a_target_capability
-                        break
-            else:
-                # Use first target node
-                target_node = target_nodes[0]
-
-            if target_node is not None:
-                if requirement_template.relationship_template is not None:
-                    relationship_model = \
-                        requirement_template.relationship_template.instantiate(self)
-                else:
-                    relationship_model = models.Relationship()
-                relationship_model.name = requirement_template.name
-                relationship_model.requirement_template = requirement_template
-                relationship_model.target_node = target_node
-                relationship_model.target_capability = target_capability
-                self.outbound_relationships.append(relationship_model)
-                return True
-            else:
-                context.validation.report('requirement "{0}" of node "{1}" targets node '
-                                          'template "{2}" but its instantiated nodes do not '
-                                          'have enough capacity'.format(
-                                              requirement_template.name,
-                                              self.name,
-                                              target_node_template.name),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
-                return False
-        else:
-            context.validation.report('requirement "{0}" of node "{1}" targets node template '
-                                      '"{2}" but it has no instantiated nodes'.format(
-                                          requirement_template.name,
-                                          self.name,
-                                          target_node_template.name),
-                                      level=validation.Issue.BETWEEN_INSTANCES)
-            return False
-
-    def validate_capabilities(self):
-        context = ConsumptionContext.get_thread_local()
-        satisfied = False
-        for capability in self.capabilities.itervalues():
-            if not capability.has_enough_relationships:
-                context.validation.report('capability "{0}" of node "{1}" requires at least {2:d} '
-                                          'relationships but has {3:d}'.format(
-                                              capability.name,
-                                              self.name,
-                                              capability.min_occurrences,
-                                              capability.occurrences),
-                                          level=validation.Issue.BETWEEN_INSTANCES)
-                satisfied = False
-        return satisfied
-
-    def find_host(self):
-        def _find_host(node):
-            if node.type.role == 'host':
-                return node
-            for the_relationship in node.outbound_relationships:
-                if (the_relationship.target_capability is not None) and \
-                    the_relationship.target_capability.type.role == 'host':
-                    host = _find_host(the_relationship.target_node)
-                    if host is not None:
-                        return host
-            for the_relationship in node.inbound_relationships:
-                if (the_relationship.target_capability is not None) and \
-                    the_relationship.target_capability.type.role == 'feature':
-                    host = _find_host(the_relationship.source_node)
-                    if host is not None:
-                        return host
-            return None
-
-        self.host = _find_host(self)
-
-    def configure_operations(self):
-        for interface in self.interfaces.itervalues():
-            interface.configure_operations()
-        for the_relationship in self.outbound_relationships:
-            the_relationship.configure_operations()
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -740,46 +516,6 @@ class NodeBase(InstanceModelMixin):
             ('capabilities', formatting.as_raw_list(self.capabilities)),
             ('relationships', formatting.as_raw_list(self.outbound_relationships))))
 
-    def validate(self):
-        context = ConsumptionContext.get_thread_local()
-        if len(self.name) > context.modeling.id_max_length:
-            context.validation.report('"{0}" has an ID longer than the limit of {1:d} characters: '
-                                      '{2:d}'.format(
-                                          self.name,
-                                          context.modeling.id_max_length,
-                                          len(self.name)),
-                                      level=validation.Issue.BETWEEN_INSTANCES)
-
-        # TODO: validate that node template is of type?
-
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.attributes)
-        utils.validate_dict_values(self.interfaces)
-        utils.validate_dict_values(self.artifacts)
-        utils.validate_dict_values(self.capabilities)
-        utils.validate_list_values(self.outbound_relationships)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.attributes, report_issues)
-        utils.coerce_dict_values(self.interfaces, report_issues)
-        utils.coerce_dict_values(self.artifacts, report_issues)
-        utils.coerce_dict_values(self.capabilities, report_issues)
-        utils.coerce_list_values(self.outbound_relationships, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Node: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Template: {0}'.format(context.style.node(self.node_template.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_dict_values(self.attributes, 'Attributes')
-            utils.dump_interfaces(self.interfaces)
-            utils.dump_dict_values(self.artifacts, 'Artifacts')
-            utils.dump_dict_values(self.capabilities, 'Capabilities')
-            utils.dump_list_values(self.outbound_relationships, 'Relationships')
-
 
 class GroupBase(InstanceModelMixin):
     """
@@ -885,10 +621,6 @@ class GroupBase(InstanceModelMixin):
     :type: :obj:`basestring`
     """)
 
-    def configure_operations(self):
-        for interface in self.interfaces.itervalues():
-            interface.configure_operations()
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -896,27 +628,6 @@ class GroupBase(InstanceModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interfaces', formatting.as_raw_list(self.interfaces))))
 
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interfaces)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interfaces, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Group: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interfaces)
-            if self.nodes:
-                console.puts('Member nodes:')
-                with context.style.indent:
-                    for node in self.nodes:
-                        console.puts(context.style.node(node.name))
-
 
 class PolicyBase(InstanceModelMixin):
     """
@@ -1030,29 +741,6 @@ class PolicyBase(InstanceModelMixin):
             ('type_name', self.type.name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Policy: {0}'.format(context.style.node(self.name)))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            if self.nodes:
-                console.puts('Target nodes:')
-                with context.style.indent:
-                    for node in self.nodes:
-                        console.puts(context.style.node(node.name))
-            if self.groups:
-                console.puts('Target groups:')
-                with context.style.indent:
-                    for group in self.groups:
-                        console.puts(context.style.node(group.name))
-
 
 class SubstitutionBase(InstanceModelMixin):
     """
@@ -1130,19 +818,6 @@ class SubstitutionBase(InstanceModelMixin):
             ('node_type_name', self.node_type.name),
             ('mappings', formatting.as_raw_dict(self.mappings))))
 
-    def validate(self):
-        utils.validate_dict_values(self.mappings)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.mappings, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Substitution:')
-        with context.style.indent:
-            console.puts('Node type: {0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(self.mappings, 'Mappings')
-
 
 class SubstitutionMappingBase(InstanceModelMixin):
     """
@@ -1238,31 +913,6 @@ class SubstitutionMappingBase(InstanceModelMixin):
         return collections.OrderedDict((
             ('name', self.name),))
 
-    def coerce_values(self, report_issues):
-        pass
-
-    def validate(self):
-        context = ConsumptionContext.get_thread_local()
-        if (self.capability is None) and (self.requirement_template is None):
-            context.validation.report('mapping "{0}" refers to neither capability nor a requirement'
-                                      ' in node: {1}'.format(
-                                          self.name,
-                                          formatting.safe_repr(self.node.name)),
-                                      level=validation.Issue.BETWEEN_TYPES)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.capability is not None:
-            console.puts('{0} -> {1}.{2}'.format(
-                context.style.node(self.name),
-                context.style.node(self.capability.node.name),
-                context.style.node(self.capability.name)))
-        else:
-            console.puts('{0} -> {1}.{2}'.format(
-                context.style.node(self.name),
-                context.style.node(self.node.name),
-                context.style.node(self.requirement_template.name)))
-
 
 class RelationshipBase(InstanceModelMixin):
     """
@@ -1436,10 +1086,6 @@ class RelationshipBase(InstanceModelMixin):
     :type: :obj:`int`
     """)
 
-    def configure_operations(self):
-        for interface in self.interfaces.itervalues():
-            interface.configure_operations()
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1452,33 +1098,6 @@ class RelationshipBase(InstanceModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interfaces', formatting.as_raw_list(self.interfaces))))
 
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interfaces)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interfaces, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts('{0} ->'.format(context.style.node(self.name)))
-        else:
-            console.puts('->')
-        with context.style.indent:
-            console.puts('Node: {0}'.format(context.style.node(self.target_node.name)))
-            if self.target_capability:
-                console.puts('Capability: {0}'.format(context.style.node(
-                    self.target_capability.name)))
-            if self.type is not None:
-                console.puts('Relationship type: {0}'.format(context.style.type(self.type.name)))
-            if (self.relationship_template is not None) and self.relationship_template.name:
-                console.puts('Relationship template: {0}'.format(
-                    context.style.node(self.relationship_template.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interfaces, 'Interfaces')
-
 
 class CapabilityBase(InstanceModelMixin):
     """
@@ -1595,25 +1214,6 @@ class CapabilityBase(InstanceModelMixin):
             ('type_name', self.type.name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Occurrences: {0:d} ({1:d}{2})'.format(
-                self.occurrences,
-                self.min_occurrences or 0,
-                ' to {0:d}'.format(self.max_occurrences)
-                if self.max_occurrences is not None
-                else ' or more'))
-            utils.dump_dict_values(self.properties, 'Properties')
-
 
 class InterfaceBase(InstanceModelMixin):
     """
@@ -1738,10 +1338,6 @@ class InterfaceBase(InstanceModelMixin):
     :type: :obj:`basestring`
     """)
 
-    def configure_operations(self):
-        for operation in self.operations.itervalues():
-            operation.configure()
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1751,24 +1347,6 @@ class InterfaceBase(InstanceModelMixin):
             ('inputs', formatting.as_raw_dict(self.inputs)),
             ('operations', formatting.as_raw_list(self.operations))))
 
-    def validate(self):
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.operations)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.operations, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            utils.dump_dict_values(self.operations, 'Operations')
-
 
 class OperationBase(InstanceModelMixin):
     """
@@ -1944,45 +1522,6 @@ class OperationBase(InstanceModelMixin):
     :type: :obj:`float`
     """)
 
-    def configure(self):
-        if (self.implementation is None) and (self.function is None):
-            return
-
-        if (self.interface is not None) and (self.plugin is None) and (self.function is None):
-            # ("interface" is None for workflow operations, which do not currently use "plugin")
-            # The default (None) plugin is the execution plugin
-            execution_plugin.instantiation.configure_operation(self)
-        else:
-            # In the future plugins may be able to add their own "configure_operation" hook that
-            # can validate the configuration and otherwise create specially derived arguments. For
-            # now, we just send all configuration parameters as arguments without validation.
-            utils.instantiate_dict(self, self.arguments,
-                                   utils.dict_as_arguments(self.configurations))
-
-        if self.interface is not None:
-            # Send all interface inputs as extra arguments
-            # ("interface" is None for workflow operations)
-            # Note that they will override existing arguments of the same names
-            utils.instantiate_dict(self, self.arguments,
-                                   utils.dict_as_arguments(self.interface.inputs))
-
-        # Send all inputs as extra arguments
-        # Note that they will override existing arguments of the same names
-        utils.instantiate_dict(self, self.arguments, utils.dict_as_arguments(self.inputs))
-
-        # Check for reserved arguments
-        from ..orchestrator.decorators import OPERATION_DECORATOR_RESERVED_ARGUMENTS
-        used_reserved_names = \
-            OPERATION_DECORATOR_RESERVED_ARGUMENTS.intersection(self.arguments.keys())
-        if used_reserved_names:
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('using reserved arguments in operation "{0}": {1}'
-                                      .format(
-                                          self.name,
-                                          formatting.string_list_as_string(used_reserved_names)),
-                                      level=validation.Issue.EXTERNAL)
-
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1992,46 +1531,6 @@ class OperationBase(InstanceModelMixin):
             ('dependencies', self.dependencies),
             ('inputs', formatting.as_raw_dict(self.inputs))))
 
-    def validate(self):
-        # TODO must be associated with either interface or service
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.configurations)
-        utils.validate_dict_values(self.arguments)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.configurations, report_issues)
-        utils.coerce_dict_values(self.arguments, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            if self.implementation is not None:
-                console.puts('Implementation: {0}'.format(
-                    context.style.literal(self.implementation)))
-            if self.dependencies:
-                console.puts(
-                    'Dependencies: {0}'.format(
-                        ', '.join((str(context.style.literal(v)) for v in self.dependencies))))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            if self.executor is not None:
-                console.puts('Executor: {0}'.format(context.style.literal(self.executor)))
-            if self.max_attempts is not None:
-                console.puts('Max attempts: {0}'.format(context.style.literal(self.max_attempts)))
-            if self.retry_interval is not None:
-                console.puts('Retry interval: {0}'.format(
-                    context.style.literal(self.retry_interval)))
-            if self.plugin is not None:
-                console.puts('Plugin: {0}'.format(
-                    context.style.literal(self.plugin.name)))
-            utils.dump_dict_values(self.configurations, 'Configuration')
-            if self.function is not None:
-                console.puts('Function: {0}'.format(context.style.literal(self.function)))
-            utils.dump_dict_values(self.arguments, 'Arguments')
-
 
 class ArtifactBase(InstanceModelMixin):
     """
@@ -2150,27 +1649,3 @@ class ArtifactBase(InstanceModelMixin):
             ('repository_url', self.repository_url),
             ('repository_credential', formatting.as_agnostic(self.repository_credential)),
             ('properties', formatting.as_raw_dict(self.properties))))
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Artifact type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Source path: {0}'.format(context.style.literal(self.source_path)))
-            if self.target_path is not None:
-                console.puts('Target path: {0}'.format(context.style.literal(self.target_path)))
-            if self.repository_url is not None:
-                console.puts('Repository URL: {0}'.format(
-                    context.style.literal(self.repository_url)))
-            if self.repository_credential:
-                console.puts('Repository credential: {0}'.format(
-                    context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(self.properties, 'Properties')

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/df2b916e/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 2246340..d988d21 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -21,8 +21,6 @@ ARIA modeling service template module
 
 from __future__ import absolute_import  # so we can import standard 'types'
 
-from datetime import datetime
-
 from sqlalchemy import (
     Column,
     Text,
@@ -33,15 +31,10 @@ from sqlalchemy import (
 )
 from sqlalchemy.ext.declarative import declared_attr
 
-from ..parser import validation
-from ..parser.consumption import ConsumptionContext
-from ..parser.reading import deepcopy_with_locators
-from ..utils import (collections, formatting, console)
-from ..utils.versions import VersionString
+from ..utils import (collections, formatting)
 from .mixins import TemplateModelMixin
 from . import (
     relationship,
-    utils,
     types as modeling_types
 )
 
@@ -331,130 +324,6 @@ class ServiceTemplateBase(TemplateModelMixin):
             ('interface_types', formatting.as_raw(self.interface_types)),
             ('artifact_types', formatting.as_raw(self.artifact_types))))
 
-    def instantiate(self, container, model_storage, inputs=None):  # pylint: disable=arguments-differ
-        from . import models
-        now = datetime.now()
-        service = models.Service(created_at=now,
-                                 updated_at=now,
-                                 description=deepcopy_with_locators(self.description),
-                                 service_template=self)
-
-        # TODO: we want to remove this use of the context
-        context = ConsumptionContext.get_thread_local()
-        context.modeling.instance = service
-
-        utils.validate_no_undeclared_inputs(declared_inputs=self.inputs,
-                                            supplied_inputs=inputs or {})
-        utils.validate_required_inputs_are_supplied(declared_inputs=self.inputs,
-                                                    supplied_inputs=inputs or {})
-
-        service.inputs = utils.merge_parameter_values(inputs, self.inputs, model_cls=models.Input)
-        # TODO: now that we have inputs, we should scan properties and inputs and evaluate functions
-
-        for plugin_specification in self.plugin_specifications.itervalues():
-            if plugin_specification.enabled:
-                if plugin_specification.resolve(model_storage):
-                    plugin = plugin_specification.plugin
-                    service.plugins[plugin.name] = plugin
-                else:
-                    context = ConsumptionContext.get_thread_local()
-                    context.validation.report('specified plugin not found: {0}'.format(
-                        plugin_specification.name), level=validation.Issue.EXTERNAL)
-
-        utils.instantiate_dict(self, service.meta_data, self.meta_data)
-
-        for node_template in self.node_templates.itervalues():
-            for _ in range(node_template.scaling['default_instances']):
-                node = node_template.instantiate(container)
-                service.nodes[node.name] = node
-
-        utils.instantiate_dict(self, service.groups, self.group_templates)
-        utils.instantiate_dict(self, service.policies, self.policy_templates)
-        utils.instantiate_dict(self, service.workflows, self.workflow_templates)
-
-        if self.substitution_template is not None:
-            service.substitution = self.substitution_template.instantiate(container)
-
-        utils.instantiate_dict(self, service.outputs, self.outputs)
-
-        return service
-
-    def validate(self):
-        utils.validate_dict_values(self.meta_data)
-        utils.validate_dict_values(self.node_templates)
-        utils.validate_dict_values(self.group_templates)
-        utils.validate_dict_values(self.policy_templates)
-        if self.substitution_template is not None:
-            self.substitution_template.validate()
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.outputs)
-        utils.validate_dict_values(self.workflow_templates)
-        if self.node_types is not None:
-            self.node_types.validate()
-        if self.group_types is not None:
-            self.group_types.validate()
-        if self.policy_types is not None:
-            self.policy_types.validate()
-        if self.relationship_types is not None:
-            self.relationship_types.validate()
-        if self.capability_types is not None:
-            self.capability_types.validate()
-        if self.interface_types is not None:
-            self.interface_types.validate()
-        if self.artifact_types is not None:
-            self.artifact_types.validate()
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.meta_data, report_issues)
-        utils.coerce_dict_values(self.node_templates, report_issues)
-        utils.coerce_dict_values(self.group_templates, report_issues)
-        utils.coerce_dict_values(self.policy_templates, report_issues)
-        if self.substitution_template is not None:
-            self.substitution_template.coerce_values(report_issues)
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.outputs, report_issues)
-        utils.coerce_dict_values(self.workflow_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.description is not None:
-            console.puts(context.style.meta(self.description))
-        utils.dump_dict_values(self.meta_data, 'Metadata')
-        for node_template in self.node_templates.itervalues():
-            node_template.dump()
-        for group_template in self.group_templates.itervalues():
-            group_template.dump()
-        for policy_template in self.policy_templates.itervalues():
-            policy_template.dump()
-        if self.substitution_template is not None:
-            self.substitution_template.dump()
-        utils.dump_dict_values(self.inputs, 'Inputs')
-        utils.dump_dict_values(self.outputs, 'Outputs')
-        utils.dump_dict_values(self.workflow_templates, 'Workflow templates')
-
-    def dump_types(self):
-        if self.node_types.children:
-            console.puts('Node types:')
-            self.node_types.dump()
-        if self.group_types.children:
-            console.puts('Group types:')
-            self.group_types.dump()
-        if self.capability_types.children:
-            console.puts('Capability types:')
-            self.capability_types.dump()
-        if self.relationship_types.children:
-            console.puts('Relationship types:')
-            self.relationship_types.dump()
-        if self.policy_types.children:
-            console.puts('Policy types:')
-            self.policy_types.dump()
-        if self.artifact_types.children:
-            console.puts('Artifact types:')
-            self.artifact_types.dump()
-        if self.interface_types.children:
-            console.puts('Interface types:')
-            self.interface_types.dump()
-
 
 class NodeTemplateBase(TemplateModelMixin):
     """
@@ -625,114 +494,6 @@ class NodeTemplateBase(TemplateModelMixin):
             ('capability_templates', formatting.as_raw_list(self.capability_templates)),
             ('requirement_templates', formatting.as_raw_list(self.requirement_templates))))
 
-    def instantiate(self, container):
-        from . import models
-        node = models.Node(name=self._next_name,
-                           type=self.type,
-                           description=deepcopy_with_locators(self.description),
-                           state=models.Node.INITIAL,
-                           node_template=self)
-        utils.instantiate_dict(node, node.properties, self.properties)
-        utils.instantiate_dict(node, node.attributes, self.attributes)
-        utils.instantiate_dict(node, node.interfaces, self.interface_templates)
-        utils.instantiate_dict(node, node.artifacts, self.artifact_templates)
-        utils.instantiate_dict(node, node.capabilities, self.capability_templates)
-
-        # Default attributes
-        if ('tosca_name' in node.attributes) \
-            and (node.attributes['tosca_name'].type_name == 'string'):
-            node.attributes['tosca_name'].value = self.name
-        if 'tosca_id' in node.attributes \
-            and (node.attributes['tosca_id'].type_name == 'string'):
-            node.attributes['tosca_id'].value = node.name
-
-        return node
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.attributes)
-        utils.validate_dict_values(self.interface_templates)
-        utils.validate_dict_values(self.artifact_templates)
-        utils.validate_dict_values(self.capability_templates)
-        utils.validate_list_values(self.requirement_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.attributes, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-        utils.coerce_dict_values(self.artifact_templates, report_issues)
-        utils.coerce_dict_values(self.capability_templates, report_issues)
-        utils.coerce_list_values(self.requirement_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Node template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_dict_values(self.attributes, 'Attributes')
-            utils.dump_interfaces(self.interface_templates)
-            utils.dump_dict_values(self.artifact_templates, 'Artifact templates')
-            utils.dump_dict_values(self.capability_templates, 'Capability templates')
-            utils.dump_list_values(self.requirement_templates, 'Requirement templates')
-
-    @property
-    def scaling(self):
-        scaling = {}
-
-        def extract_property(properties, name):
-            if name in scaling:
-                return
-            prop = properties.get(name)
-            if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None):
-                scaling[name] = prop.value
-
-        def extract_properties(properties):
-            extract_property(properties, 'min_instances')
-            extract_property(properties, 'max_instances')
-            extract_property(properties, 'default_instances')
-
-        def default_property(name, value):
-            if name not in scaling:
-                scaling[name] = value
-
-        # From our scaling capabilities
-        for capability_template in self.capability_templates.itervalues():
-            if capability_template.type.role == 'scaling':
-                extract_properties(capability_template.properties)
-
-        # From service scaling policies
-        for policy_template in self.service_template.policy_templates.itervalues():
-            if policy_template.type.role == 'scaling':
-                if policy_template.is_for_node_template(self.name):
-                    extract_properties(policy_template.properties)
-
-        # Defaults
-        default_property('min_instances', 0)
-        default_property('max_instances', 1)
-        default_property('default_instances', 1)
-
-        # Validate
-        # pylint: disable=too-many-boolean-expressions
-        if ((scaling['min_instances'] < 0) or
-                (scaling['max_instances'] < 0) or
-                (scaling['default_instances'] < 0) or
-                (scaling['max_instances'] < scaling['min_instances']) or
-                (scaling['default_instances'] < scaling['min_instances']) or
-                (scaling['default_instances'] > scaling['max_instances'])):
-            context = ConsumptionContext.get_thread_local()
-            context.validation.report('invalid scaling parameters for node template "{0}": '
-                                      'min={1}, max={2}, default={3}'.format(
-                                          self.name,
-                                          scaling['min_instances'],
-                                          scaling['max_instances'],
-                                          scaling['default_instances']),
-                                      level=validation.Issue.BETWEEN_TYPES)
-
-        return scaling
-
     def is_target_node_template_valid(self, target_node_template):
         """
         Checks if ``target_node_template`` matches all our ``target_node_template_constraints``.
@@ -769,6 +530,40 @@ class NodeTemplateBase(TemplateModelMixin):
 
         return '{name}_{index}'.format(name=self.name, index=self._next_index)
 
+    @property
+    def scaling(self):
+        scaling = {}
+
+        def extract_property(properties, name):
+            if name in scaling:
+                return
+            prop = properties.get(name)
+            if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None):
+                scaling[name] = prop.value
+
+        def extract_properties(properties):
+            extract_property(properties, 'min_instances')
+            extract_property(properties, 'max_instances')
+            extract_property(properties, 'default_instances')
+
+        # From our scaling capabilities
+        for capability_template in self.capability_templates.itervalues():
+            if capability_template.type.role == 'scaling':
+                extract_properties(capability_template.properties)
+
+        # From service scaling policies
+        for policy_template in self.service_template.policy_templates.itervalues():
+            if policy_template.type.role == 'scaling':
+                if policy_template.is_for_node_template(self.name):
+                    extract_properties(policy_template.properties)
+
+        # Defaults
+        scaling.setdefault('min_instances', 0)
+        scaling.setdefault('max_instances', 1)
+        scaling.setdefault('default_instances', 1)
+
+        return scaling
+
 
 class GroupTemplateBase(TemplateModelMixin):
     """
@@ -876,40 +671,6 @@ class GroupTemplateBase(TemplateModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interface_templates', formatting.as_raw_list(self.interface_templates))))
 
-    def instantiate(self, container):
-        from . import models
-        group = models.Group(name=self.name,
-                             type=self.type,
-                             description=deepcopy_with_locators(self.description),
-                             group_template=self)
-        utils.instantiate_dict(self, group.properties, self.properties)
-        utils.instantiate_dict(self, group.interfaces, self.interface_templates)
-        if self.node_templates:
-            for node_template in self.node_templates:
-                group.nodes += node_template.nodes
-        return group
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interface_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Group template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates)
-            if self.node_templates:
-                console.puts('Member node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.node_templates))))
-
     def contains_node_template(self, name):
         for node_template in self.node_templates:
             if node_template.name == name:
@@ -1022,42 +783,6 @@ class PolicyTemplateBase(TemplateModelMixin):
             ('type_name', self.type.name),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, container):
-        from . import models
-        policy = models.Policy(name=self.name,
-                               type=self.type,
-                               description=deepcopy_with_locators(self.description),
-                               policy_template=self)
-        utils.instantiate_dict(self, policy.properties, self.properties)
-        if self.node_templates:
-            for node_template in self.node_templates:
-                policy.nodes += node_template.nodes
-        if self.group_templates:
-            for group_template in self.group_templates:
-                policy.groups += group_template.groups
-        return policy
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Policy template: {0}'.format(context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.properties, 'Properties')
-            if self.node_templates:
-                console.puts('Target node templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.node_templates))))
-            if self.group_templates:
-                console.puts('Target group templates: {0}'.format(', '.join(
-                    (str(context.style.node(v.name)) for v in self.group_templates))))
-
     def is_for_node_template(self, name):
         for node_template in self.node_templates:
             if node_template.name == name:
@@ -1134,26 +859,6 @@ class SubstitutionTemplateBase(TemplateModelMixin):
             ('node_type_name', self.node_type.name),
             ('mappings', formatting.as_raw_dict(self.mappings))))
 
-    def instantiate(self, container):
-        from . import models
-        substitution = models.Substitution(node_type=self.node_type,
-                                           substitution_template=self)
-        utils.instantiate_dict(container, substitution.mappings, self.mappings)
-        return substitution
-
-    def validate(self):
-        utils.validate_dict_values(self.mappings)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.mappings, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts('Substitution template:')
-        with context.style.indent:
-            console.puts('Node type: {0}'.format(context.style.type(self.node_type.name)))
-            utils.dump_dict_values(self.mappings, 'Mappings')
-
 
 class SubstitutionTemplateMappingBase(TemplateModelMixin):
     """
@@ -1233,59 +938,6 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
         return collections.OrderedDict((
             ('name', self.name),))
 
-    def coerce_values(self, report_issues):
-        pass
-
-    def instantiate(self, container):
-        from . import models
-        context = ConsumptionContext.get_thread_local()
-        if self.capability_template is not None:
-            node_template = self.capability_template.node_template
-        else:
-            node_template = self.requirement_template.node_template
-        nodes = node_template.nodes
-        if len(nodes) == 0:
-            context.validation.report(
-                'mapping "{0}" refers to node template "{1}" but there are no '
-                'node instances'.format(self.mapped_name, self.node_template.name),
-                level=validation.Issue.BETWEEN_INSTANCES)
-            return None
-        # The TOSCA spec does not provide a way to choose the node,
-        # so we will just pick the first one
-        node = nodes[0]
-        capability = None
-        if self.capability_template:
-            for a_capability in node.capabilities.itervalues():
-                if a_capability.capability_template.name == self.capability_template.name:
-                    capability = a_capability
-        return models.SubstitutionMapping(name=self.name,
-                                          capability=capability,
-                                          requirement_template=self.requirement_template,
-                                          node=node)
-
-
-    def validate(self):
-        context = ConsumptionContext.get_thread_local()
-        if (self.capability_template is None) and (self.requirement_template is None):
-            context.validation.report('mapping "{0}" refers to neither capability nor a requirement'
-                                      ' in node template: {1}'.format(
-                                          self.name,
-                                          formatting.safe_repr(self.node_template.name)),
-                                      level=validation.Issue.BETWEEN_TYPES)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.capability_template is not None:
-            node_template = self.capability_template.node_template
-        else:
-            node_template = self.requirement_template.node_template
-        console.puts('{0} -> {1}.{2}'.format(
-            context.style.node(self.name),
-            context.style.node(node_template.name),
-            context.style.node(self.capability_template.name
-                               if self.capability_template
-                               else self.requirement_template.name)))
-
 
 class RequirementTemplateBase(TemplateModelMixin):
     """
@@ -1424,56 +1076,6 @@ class RequirementTemplateBase(TemplateModelMixin):
     :type: [:class:`NodeTemplateConstraint`]
     """)
 
-    def find_target(self, source_node_template):
-        context = ConsumptionContext.get_thread_local()
-
-        # We might already have a specific node template, so we'll just verify it
-        if self.target_node_template is not None:
-            if not source_node_template.is_target_node_template_valid(self.target_node_template):
-                context.validation.report('requirement "{0}" of node template "{1}" is for node '
-                                          'template "{2}" but it does not match constraints'.format(
-                                              self.name,
-                                              self.target_node_template.name,
-                                              source_node_template.name),
-                                          level=validation.Issue.BETWEEN_TYPES)
-            if (self.target_capability_type is not None) \
-                or (self.target_capability_name is not None):
-                target_node_capability = self.find_target_capability(source_node_template,
-                                                                     self.target_node_template)
-                if target_node_capability is None:
-                    return None, None
-            else:
-                target_node_capability = None
-
-            return self.target_node_template, target_node_capability
-
-        # Find first node that matches the type
-        elif self.target_node_type is not None:
-            for target_node_template in \
-                    self.node_template.service_template.node_templates.itervalues():
-                if self.target_node_type.get_descendant(target_node_template.type.name) is None:
-                    continue
-
-                if not source_node_template.is_target_node_template_valid(target_node_template):
-                    continue
-
-                target_node_capability = self.find_target_capability(source_node_template,
-                                                                     target_node_template)
-                if target_node_capability is None:
-                    continue
-
-                return target_node_template, target_node_capability
-
-        return None, None
-
-    def find_target_capability(self, source_node_template, target_node_template):
-        for capability_template in target_node_template.capability_templates.itervalues():
-            if capability_template.satisfies_requirement(source_node_template,
-                                                         self,
-                                                         target_node_template):
-                return capability_template
-        return None
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1487,43 +1089,6 @@ class RequirementTemplateBase(TemplateModelMixin):
             ('target_capability_name', self.target_capability_name),
             ('relationship_template', formatting.as_raw(self.relationship_template))))
 
-    def validate(self):
-        if self.relationship_template:
-            self.relationship_template.validate()
-
-    def coerce_values(self, report_issues):
-        if self.relationship_template is not None:
-            self.relationship_template.coerce_values(report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.name:
-            console.puts(context.style.node(self.name))
-        else:
-            console.puts('Requirement:')
-        with context.style.indent:
-            if self.target_node_type is not None:
-                console.puts('Target node type: {0}'.format(
-                    context.style.type(self.target_node_type.name)))
-            elif self.target_node_template is not None:
-                console.puts('Target node template: {0}'.format(
-                    context.style.node(self.target_node_template.name)))
-            if self.target_capability_type is not None:
-                console.puts('Target capability type: {0}'.format(
-                    context.style.type(self.target_capability_type.name)))
-            elif self.target_capability_name is not None:
-                console.puts('Target capability name: {0}'.format(
-                    context.style.node(self.target_capability_name)))
-            if self.target_node_template_constraints:
-                console.puts('Target node template constraints:')
-                with context.style.indent:
-                    for constraint in self.target_node_template_constraints:
-                        console.puts(context.style.literal(constraint))
-            if self.relationship_template:
-                console.puts('Relationship:')
-                with context.style.indent:
-                    self.relationship_template.dump()
-
 
 class RelationshipTemplateBase(TemplateModelMixin):
     """
@@ -1606,37 +1171,6 @@ class RelationshipTemplateBase(TemplateModelMixin):
             ('properties', formatting.as_raw_dict(self.properties)),
             ('interface_templates', formatting.as_raw_list(self.interface_templates))))
 
-    def instantiate(self, container):
-        from . import models
-        relationship_model = models.Relationship(name=self.name,
-                                                 type=self.type,
-                                                 relationship_template=self)
-        utils.instantiate_dict(container, relationship_model.properties, self.properties)
-        utils.instantiate_dict(container, relationship_model.interfaces, self.interface_templates)
-        return relationship_model
-
-    def validate(self):
-        # TODO: either type or name must be set
-        utils.validate_dict_values(self.properties)
-        utils.validate_dict_values(self.interface_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-        utils.coerce_dict_values(self.interface_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        if self.type is not None:
-            console.puts('Relationship type: {0}'.format(context.style.type(self.type.name)))
-        else:
-            console.puts('Relationship template: {0}'.format(
-                context.style.node(self.name)))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            utils.dump_dict_values(self.properties, 'Properties')
-            utils.dump_interfaces(self.interface_templates, 'Interface templates')
-
 
 class CapabilityTemplateBase(TemplateModelMixin):
     """
@@ -1739,29 +1273,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
     :type: :obj:`int`
     """)
 
-    def satisfies_requirement(self,
-                              source_node_template,
-                              requirement,
-                              target_node_template):
-        # Do we match the required capability type?
-        if requirement.target_capability_type and \
-            requirement.target_capability_type.get_descendant(self.type.name) is None:
-            return False
-
-        # Are we in valid_source_node_types?
-        if self.valid_source_node_types:
-            for valid_source_node_type in self.valid_source_node_types:
-                if valid_source_node_type.get_descendant(source_node_template.type.name) is None:
-                    return False
-
-        # Apply requirement constraints
-        if requirement.target_node_template_constraints:
-            for node_template_constraint in requirement.target_node_template_constraints:
-                if not node_template_constraint.matches(source_node_template, target_node_template):
-                    return False
-
-        return True
-
     @property
     def as_raw(self):
         return collections.OrderedDict((
@@ -1773,42 +1284,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
             ('valid_source_node_types', [v.name for v in self.valid_source_node_types]),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, container):
-        from . import models
-        capability = models.Capability(name=self.name,
-                                       type=self.type,
-                                       min_occurrences=self.min_occurrences,
-                                       max_occurrences=self.max_occurrences,
-                                       occurrences=0,
-                                       capability_template=self)
-        utils.instantiate_dict(container, capability.properties, self.properties)
-        return capability
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Type: {0}'.format(context.style.type(self.type.name)))
-            console.puts(
-                'Occurrences: {0:d}{1}'.format(
-                    self.min_occurrences or 0,
-                    ' to {0:d}'.format(self.max_occurrences)
-                    if self.max_occurrences is not None
-                    else ' or more'))
-            if self.valid_source_node_types:
-                console.puts('Valid source node types: {0}'.format(
-                    ', '.join((str(context.style.type(v.name))
-                               for v in self.valid_source_node_types))))
-            utils.dump_dict_values(self.properties, 'Properties')
-
 
 class InterfaceTemplateBase(TemplateModelMixin):
     """
@@ -1938,34 +1413,6 @@ class InterfaceTemplateBase(TemplateModelMixin):
             # TODO fix self.properties reference
             ('operation_templates', formatting.as_raw_list(self.operation_templates))))
 
-    def instantiate(self, container):
-        from . import models
-        interface = models.Interface(name=self.name,
-                                     type=self.type,
-                                     description=deepcopy_with_locators(self.description),
-                                     interface_template=self)
-        utils.instantiate_dict(container, interface.inputs, self.inputs)
-        utils.instantiate_dict(container, interface.operations, self.operation_templates)
-        return interface
-
-    def validate(self):
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.operation_templates)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.operation_templates, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            utils.dump_dict_values(self.operation_templates, 'Operation templates')
-
 
 class OperationTemplateBase(TemplateModelMixin):
     """
@@ -2124,65 +1571,6 @@ class OperationTemplateBase(TemplateModelMixin):
             ('dependencies', self.dependencies),
             ('inputs', formatting.as_raw_dict(self.inputs))))
 
-    def instantiate(self, container):
-        from . import models
-
-        plugin = self.plugin_specification.plugin \
-            if (self.plugin_specification is not None) and self.plugin_specification.enabled \
-            else None
-
-        operation = models.Operation(name=self.name,
-                                     description=deepcopy_with_locators(self.description),
-                                     relationship_edge=self.relationship_edge,
-                                     implementation=self.implementation,
-                                     dependencies=self.dependencies,
-                                     executor=self.executor,
-                                     plugin=plugin,
-                                     function=self.function,
-                                     max_attempts=self.max_attempts,
-                                     retry_interval=self.retry_interval,
-                                     operation_template=self)
-
-        utils.instantiate_dict(container, operation.inputs, self.inputs)
-        utils.instantiate_dict(container, operation.configurations, self.configurations)
-
-        return operation
-
-    def validate(self):
-        utils.validate_dict_values(self.inputs)
-        utils.validate_dict_values(self.configurations)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.inputs, report_issues)
-        utils.coerce_dict_values(self.configurations, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            if self.implementation is not None:
-                console.puts('Implementation: {0}'.format(
-                    context.style.literal(self.implementation)))
-            if self.dependencies:
-                console.puts('Dependencies: {0}'.format(
-                    ', '.join((str(context.style.literal(v)) for v in self.dependencies))))
-            utils.dump_dict_values(self.inputs, 'Inputs')
-            if self.executor is not None:
-                console.puts('Executor: {0}'.format(context.style.literal(self.executor)))
-            if self.max_attempts is not None:
-                console.puts('Max attempts: {0}'.format(context.style.literal(self.max_attempts)))
-            if self.retry_interval is not None:
-                console.puts('Retry interval: {0}'.format(
-                    context.style.literal(self.retry_interval)))
-            if self.plugin_specification is not None:
-                console.puts('Plugin specification: {0}'.format(
-                    context.style.literal(self.plugin_specification.name)))
-            utils.dump_dict_values(self.configurations, 'Configuration')
-            if self.function is not None:
-                console.puts('Function: {0}'.format(context.style.literal(self.function)))
-
 
 class ArtifactTemplateBase(TemplateModelMixin):
     """
@@ -2295,43 +1683,6 @@ class ArtifactTemplateBase(TemplateModelMixin):
             ('repository_credential', formatting.as_agnostic(self.repository_credential)),
             ('properties', formatting.as_raw_dict(self.properties))))
 
-    def instantiate(self, container):
-        from . import models
-        artifact = models.Artifact(name=self.name,
-                                   type=self.type,
-                                   description=deepcopy_with_locators(self.description),
-                                   source_path=self.source_path,
-                                   target_path=self.target_path,
-                                   repository_url=self.repository_url,
-                                   repository_credential=self.repository_credential,
-                                   artifact_template=self)
-        utils.instantiate_dict(container, artifact.properties, self.properties)
-        return artifact
-
-    def validate(self):
-        utils.validate_dict_values(self.properties)
-
-    def coerce_values(self, report_issues):
-        utils.coerce_dict_values(self.properties, report_issues)
-
-    def dump(self):
-        context = ConsumptionContext.get_thread_local()
-        console.puts(context.style.node(self.name))
-        if self.description:
-            console.puts(context.style.meta(self.description))
-        with context.style.indent:
-            console.puts('Artifact type: {0}'.format(context.style.type(self.type.name)))
-            console.puts('Source path: {0}'.format(context.style.literal(self.source_path)))
-            if self.target_path is not None:
-                console.puts('Target path: {0}'.format(context.style.literal(self.target_path)))
-            if self.repository_url is not None:
-                console.puts('Repository URL: {0}'.format(
-                    context.style.literal(self.repository_url)))
-            if self.repository_credential:
-                console.puts('Repository credential: {0}'.format(
-                    context.style.literal(self.repository_credential)))
-            utils.dump_dict_values(self.properties, 'Properties')
-
 
 class PluginSpecificationBase(TemplateModelMixin):
     """
@@ -2399,24 +1750,3 @@ class PluginSpecificationBase(TemplateModelMixin):
             ('name', self.name),
             ('version', self.version),
             ('enabled', self.enabled)))
-
-    def coerce_values(self, report_issues):
-        pass
-
-    def resolve(self, model_storage):
-        # TODO: we are planning a separate "instantiation" module where this will be called or
-        # moved to.
-        plugins = model_storage.plugin.list()
-        matching_plugins = []
-        if plugins:
-            for plugin in plugins:
-                if (plugin.name == self.name) and \
-                    ((self.version is None) or \
-                     (VersionString(plugin.package_version) >= self.version)):
-                    matching_plugins.append(plugin)
-        self.plugin = None
-        if matching_plugins:
-            # Return highest version of plugin
-            key = lambda plugin: VersionString(plugin.package_version).key
-            self.plugin = sorted(matching_plugins, key=key)[-1]
-        return self.plugin is not None