vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / orchestrator / topology / topology.py
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/topology/topology.py b/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/topology/topology.py
new file mode 100644 (file)
index 0000000..f86c9dd
--- /dev/null
@@ -0,0 +1,223 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ...parser.validation import issue
+from ...modeling import models
+from ...utils import console
+from . import (
+    template_handler,
+    instance_handler,
+    common
+)
+
+
+class Topology(issue.ReporterMixin):
+
+    _init_map = {
+        models.ServiceTemplate: models.Service,
+        models.ArtifactTemplate: models.Artifact,
+        models.CapabilityTemplate: models.Capability,
+        models.GroupTemplate: models.Group,
+        models.InterfaceTemplate: models.Interface,
+        models.NodeTemplate: models.Node,
+        models.PolicyTemplate: models.Policy,
+        models.SubstitutionTemplate: models.Substitution,
+        models.RelationshipTemplate: models.Relationship,
+        models.OperationTemplate: models.Operation,
+        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
+
+        # Common
+        models.Metadata: models.Metadata,
+        models.Attribute: models.Attribute,
+        models.Property: models.Property,
+        models.Input: models.Input,
+        models.Output: models.Output,
+        models.Configuration: models.Configuration,
+        models.Argument: models.Argument,
+        models.Type: models.Type
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(Topology, self).__init__(*args, **kwargs)
+        self._model_cls_to_handler = dict(self._init_handlers(instance_handler),
+                                          **self._init_handlers(template_handler))
+
+    @staticmethod
+    def _init_handlers(module_):
+        """
+        Register handlers from a handler module to the models.
+
+        :param module_: the module to look for handlers
+        :returns: dict where the key is the models class, and the value is the handler class
+         associated with it from the provided module
+        """
+        handlers = {}
+        for attribute_name in dir(module_):
+            if attribute_name.startswith('_'):
+                continue
+            attribute = getattr(module_, attribute_name)
+            if isinstance(attribute, type) and issubclass(attribute, common.HandlerBase):
+                handlers[getattr(models, attribute_name)] = attribute
+        return handlers
+
+    def instantiate(self, model, **kwargs):
+        """
+        Instantiate the provided model.
+
+        :param model:
+        :param kwargs:
+        :returns:
+        """
+        if isinstance(model, dict):
+            return dict((name, self.instantiate(value, **kwargs))
+                        for name, value in model.iteritems())
+        elif isinstance(model, list):
+            return list(self.instantiate(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            model_instance_cls = self._init_map[model.__class__]
+            return _handler(self, model).instantiate(model_instance_cls, **kwargs)
+
+    def validate(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.validate(model.values(), **kwargs)
+        elif isinstance(model, list):
+            return all(self.validate(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            return _handler(self, model).validate(**kwargs)
+
+    def dump(self, model, out_stream=None, title=None, **kwargs):
+        out_stream = out_stream or console.TopologyStylizer()
+
+        # if model is empty, no need to print out the section name
+        if model and title:
+            out_stream.write('{0}:'.format(title))
+
+        if isinstance(model, dict):
+            if str(out_stream):
+                with out_stream.indent():
+                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
+            else:
+                return self.dump(model.values(), out_stream=out_stream, **kwargs)
+
+        elif isinstance(model, list):
+            for value in model:
+                self.dump(value, out_stream=out_stream, **kwargs)
+
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            _handler(self, model).dump(out_stream=out_stream, **kwargs)
+
+        return out_stream
+
+    def dump_graph(self, service):
+        out_stream = console.TopologyStylizer()
+        for node in service.nodes.itervalues():
+            if not node.inbound_relationships:
+                self._dump_graph_node(out_stream, node)
+        return out_stream
+
+    def _dump_graph_node(self, out_stream, node, capability=None):
+        out_stream.write(out_stream.node_style(node.name))
+        if capability is not None:
+            out_stream.write('{0} ({1})'.format(out_stream.property_style(capability.name),
+                                                out_stream.type_style(capability.type.name)))
+        if node.outbound_relationships:
+            with out_stream.indent():
+                for relationship_model in node.outbound_relationships:
+                    styled_relationship_name = out_stream.property_style(relationship_model.name)
+                    if relationship_model.type is not None:
+                        out_stream.write('-> {0} ({1})'.format(
+                            styled_relationship_name,
+                            out_stream.type_style(relationship_model.type.name)))
+                    else:
+                        out_stream.write('-> {0}'.format(styled_relationship_name))
+                    with out_stream.indent(3):
+                        self._dump_graph_node(out_stream,
+                                              relationship_model.target_node,
+                                              relationship_model.target_capability)
+
+    def coerce(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.coerce(model.values(), **kwargs)
+        elif isinstance(model, list):
+            return all(self.coerce(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            return _handler(self, model).coerce(**kwargs)
+
+    def dump_types(self, service_template, out_stream=None):
+        out_stream = out_stream or console.TopologyStylizer()
+        self.dump(service_template.node_types, out_stream, 'Node types')
+        self.dump(service_template.group_types, out_stream, 'Group types')
+        self.dump(service_template.capability_types, out_stream, 'Capability types')
+        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
+        self.dump(service_template.policy_types, out_stream, 'Policy types')
+        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
+        self.dump(service_template.interface_types, out_stream, 'Interface types')
+
+        return out_stream
+
+    def satisfy_requirements(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.satisfy_requirements(model.values(), **kwargs)
+        elif isinstance(model, list):
+            return all(self.satisfy_requirements(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            return _handler(self, model).satisfy_requirements(**kwargs)
+
+    def validate_capabilities(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.validate_capabilities(model.values(), **kwargs)
+        elif isinstance(model, list):
+            return all(self.validate_capabilities(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            return _handler(self, model).validate_capabilities(**kwargs)
+
+    def _find_host(self, node):
+        if node.type.role == 'host':
+            return node
+
+        def target_has_role(rel, role):
+            return (rel.target_capability is not None and
+                    rel.target_capability.type.role == role)
+
+        for outbound_relationship in node.outbound_relationships:
+            if target_has_role(outbound_relationship, 'host'):
+                host = self._find_host(outbound_relationship.target_node)
+                if host is not None:
+                    return host
+        for inbound_relationship in node.inbound_relationships:
+            if target_has_role(inbound_relationship, 'feature'):
+                host = self._find_host(inbound_relationship.source_node)
+                if host is not None:
+                    return host
+        return None
+
+    def assign_hosts(self, service):
+        for node in service.nodes.values():
+            node.host = self._find_host(node)
+
+    def configure_operations(self, model, **kwargs):
+        if isinstance(model, dict):
+            return self.configure_operations(model.values(), **kwargs)
+        elif isinstance(model, list):
+            return all(self.configure_operations(value, **kwargs) for value in model)
+        elif model is not None:
+            _handler = self._model_cls_to_handler[model.__class__]
+            return _handler(self, model).configure_operations(**kwargs)