diff options
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/topology/topology.py')
-rw-r--r-- | azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/topology/topology.py | 223 |
1 files changed, 223 insertions, 0 deletions
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 index 0000000..f86c9dd --- /dev/null +++ b/azure/aria/aria-extension-cloudify/src/aria/aria/orchestrator/topology/topology.py @@ -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) |