vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / orchestrator / topology / topology.py
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from ...parser.validation import issue
17 from ...modeling import models
18 from ...utils import console
19 from . import (
20     template_handler,
21     instance_handler,
22     common
23 )
24
25
26 class Topology(issue.ReporterMixin):
27
28     _init_map = {
29         models.ServiceTemplate: models.Service,
30         models.ArtifactTemplate: models.Artifact,
31         models.CapabilityTemplate: models.Capability,
32         models.GroupTemplate: models.Group,
33         models.InterfaceTemplate: models.Interface,
34         models.NodeTemplate: models.Node,
35         models.PolicyTemplate: models.Policy,
36         models.SubstitutionTemplate: models.Substitution,
37         models.RelationshipTemplate: models.Relationship,
38         models.OperationTemplate: models.Operation,
39         models.SubstitutionTemplateMapping: models.SubstitutionMapping,
40
41         # Common
42         models.Metadata: models.Metadata,
43         models.Attribute: models.Attribute,
44         models.Property: models.Property,
45         models.Input: models.Input,
46         models.Output: models.Output,
47         models.Configuration: models.Configuration,
48         models.Argument: models.Argument,
49         models.Type: models.Type
50     }
51
52     def __init__(self, *args, **kwargs):
53         super(Topology, self).__init__(*args, **kwargs)
54         self._model_cls_to_handler = dict(self._init_handlers(instance_handler),
55                                           **self._init_handlers(template_handler))
56
57     @staticmethod
58     def _init_handlers(module_):
59         """
60         Register handlers from a handler module to the models.
61
62         :param module_: the module to look for handlers
63         :returns: dict where the key is the models class, and the value is the handler class
64          associated with it from the provided module
65         """
66         handlers = {}
67         for attribute_name in dir(module_):
68             if attribute_name.startswith('_'):
69                 continue
70             attribute = getattr(module_, attribute_name)
71             if isinstance(attribute, type) and issubclass(attribute, common.HandlerBase):
72                 handlers[getattr(models, attribute_name)] = attribute
73         return handlers
74
75     def instantiate(self, model, **kwargs):
76         """
77         Instantiate the provided model.
78
79         :param model:
80         :param kwargs:
81         :returns:
82         """
83         if isinstance(model, dict):
84             return dict((name, self.instantiate(value, **kwargs))
85                         for name, value in model.iteritems())
86         elif isinstance(model, list):
87             return list(self.instantiate(value, **kwargs) for value in model)
88         elif model is not None:
89             _handler = self._model_cls_to_handler[model.__class__]
90             model_instance_cls = self._init_map[model.__class__]
91             return _handler(self, model).instantiate(model_instance_cls, **kwargs)
92
93     def validate(self, model, **kwargs):
94         if isinstance(model, dict):
95             return self.validate(model.values(), **kwargs)
96         elif isinstance(model, list):
97             return all(self.validate(value, **kwargs) for value in model)
98         elif model is not None:
99             _handler = self._model_cls_to_handler[model.__class__]
100             return _handler(self, model).validate(**kwargs)
101
102     def dump(self, model, out_stream=None, title=None, **kwargs):
103         out_stream = out_stream or console.TopologyStylizer()
104
105         # if model is empty, no need to print out the section name
106         if model and title:
107             out_stream.write('{0}:'.format(title))
108
109         if isinstance(model, dict):
110             if str(out_stream):
111                 with out_stream.indent():
112                     return self.dump(model.values(), out_stream=out_stream, **kwargs)
113             else:
114                 return self.dump(model.values(), out_stream=out_stream, **kwargs)
115
116         elif isinstance(model, list):
117             for value in model:
118                 self.dump(value, out_stream=out_stream, **kwargs)
119
120         elif model is not None:
121             _handler = self._model_cls_to_handler[model.__class__]
122             _handler(self, model).dump(out_stream=out_stream, **kwargs)
123
124         return out_stream
125
126     def dump_graph(self, service):
127         out_stream = console.TopologyStylizer()
128         for node in service.nodes.itervalues():
129             if not node.inbound_relationships:
130                 self._dump_graph_node(out_stream, node)
131         return out_stream
132
133     def _dump_graph_node(self, out_stream, node, capability=None):
134         out_stream.write(out_stream.node_style(node.name))
135         if capability is not None:
136             out_stream.write('{0} ({1})'.format(out_stream.property_style(capability.name),
137                                                 out_stream.type_style(capability.type.name)))
138         if node.outbound_relationships:
139             with out_stream.indent():
140                 for relationship_model in node.outbound_relationships:
141                     styled_relationship_name = out_stream.property_style(relationship_model.name)
142                     if relationship_model.type is not None:
143                         out_stream.write('-> {0} ({1})'.format(
144                             styled_relationship_name,
145                             out_stream.type_style(relationship_model.type.name)))
146                     else:
147                         out_stream.write('-> {0}'.format(styled_relationship_name))
148                     with out_stream.indent(3):
149                         self._dump_graph_node(out_stream,
150                                               relationship_model.target_node,
151                                               relationship_model.target_capability)
152
153     def coerce(self, model, **kwargs):
154         if isinstance(model, dict):
155             return self.coerce(model.values(), **kwargs)
156         elif isinstance(model, list):
157             return all(self.coerce(value, **kwargs) for value in model)
158         elif model is not None:
159             _handler = self._model_cls_to_handler[model.__class__]
160             return _handler(self, model).coerce(**kwargs)
161
162     def dump_types(self, service_template, out_stream=None):
163         out_stream = out_stream or console.TopologyStylizer()
164         self.dump(service_template.node_types, out_stream, 'Node types')
165         self.dump(service_template.group_types, out_stream, 'Group types')
166         self.dump(service_template.capability_types, out_stream, 'Capability types')
167         self.dump(service_template.relationship_types, out_stream, 'Relationship types')
168         self.dump(service_template.policy_types, out_stream, 'Policy types')
169         self.dump(service_template.artifact_types, out_stream, 'Artifact types')
170         self.dump(service_template.interface_types, out_stream, 'Interface types')
171
172         return out_stream
173
174     def satisfy_requirements(self, model, **kwargs):
175         if isinstance(model, dict):
176             return self.satisfy_requirements(model.values(), **kwargs)
177         elif isinstance(model, list):
178             return all(self.satisfy_requirements(value, **kwargs) for value in model)
179         elif model is not None:
180             _handler = self._model_cls_to_handler[model.__class__]
181             return _handler(self, model).satisfy_requirements(**kwargs)
182
183     def validate_capabilities(self, model, **kwargs):
184         if isinstance(model, dict):
185             return self.validate_capabilities(model.values(), **kwargs)
186         elif isinstance(model, list):
187             return all(self.validate_capabilities(value, **kwargs) for value in model)
188         elif model is not None:
189             _handler = self._model_cls_to_handler[model.__class__]
190             return _handler(self, model).validate_capabilities(**kwargs)
191
192     def _find_host(self, node):
193         if node.type.role == 'host':
194             return node
195
196         def target_has_role(rel, role):
197             return (rel.target_capability is not None and
198                     rel.target_capability.type.role == role)
199
200         for outbound_relationship in node.outbound_relationships:
201             if target_has_role(outbound_relationship, 'host'):
202                 host = self._find_host(outbound_relationship.target_node)
203                 if host is not None:
204                     return host
205         for inbound_relationship in node.inbound_relationships:
206             if target_has_role(inbound_relationship, 'feature'):
207                 host = self._find_host(inbound_relationship.source_node)
208                 if host is not None:
209                     return host
210         return None
211
212     def assign_hosts(self, service):
213         for node in service.nodes.values():
214             node.host = self._find_host(node)
215
216     def configure_operations(self, model, **kwargs):
217         if isinstance(model, dict):
218             return self.configure_operations(model.values(), **kwargs)
219         elif isinstance(model, list):
220             return all(self.configure_operations(value, **kwargs) for value in model)
221         elif model is not None:
222             _handler = self._model_cls_to_handler[model.__class__]
223             return _handler(self, model).configure_operations(**kwargs)