summaryrefslogtreecommitdiffstats
path: root/tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py
diff options
context:
space:
mode:
Diffstat (limited to 'tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py')
-rw-r--r--tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py408
1 files changed, 0 insertions, 408 deletions
diff --git a/tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py b/tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py
deleted file mode 100644
index 152603d..0000000
--- a/tosca2heat/heat-translator-0.3.0/translator/hot/translate_node_templates.py
+++ /dev/null
@@ -1,408 +0,0 @@
-#
-# Licensed 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.
-
-import importlib
-import logging
-import os
-import six
-
-from toscaparser.functions import GetAttribute
-from toscaparser.functions import GetInput
-from toscaparser.functions import GetProperty
-from toscaparser.relationship_template import RelationshipTemplate
-from translator.common.exception import ToscaClassAttributeError
-from translator.common.exception import ToscaClassImportError
-from translator.common.exception import ToscaModImportError
-from translator.conf.config import ConfigProvider as translatorConfig
-from translator.hot.syntax.hot_resource import HotResource
-from translator.hot.tosca.tosca_block_storage_attachment import (
- ToscaBlockStorageAttachment
- )
-
-###########################
-# Module utility Functions
-# for dynamic class loading
-###########################
-
-
-def _generate_type_map():
- '''Generate TOSCA translation types map.
-
- Load user defined classes from location path specified in conf file.
- Base classes are located within the tosca directory.
-
- '''
-
- # Base types directory
- BASE_PATH = 'translator/hot/tosca'
-
- # Custom types directory defined in conf file
- custom_path = translatorConfig.get_value('DEFAULT',
- 'custom_types_location')
-
- # First need to load the parent module, for example 'contrib.hot',
- # for all of the dynamically loaded classes.
- classes = []
- _load_classes((BASE_PATH, custom_path), classes)
- try:
- types_map = {clazz.toscatype: clazz for clazz in classes}
- except AttributeError as e:
- raise ToscaClassAttributeError(message=e.message)
-
- return types_map
-
-
-def _load_classes(locations, classes):
- '''Dynamically load all the classes from the given locations.'''
-
- for cls_path in locations:
- # Use the absolute path of the class path
- abs_path = os.path.dirname(os.path.abspath(__file__))
- abs_path = abs_path.replace('translator/hot', cls_path)
-
- # Grab all the tosca type module files in the given path
- mod_files = [f for f in os.listdir(abs_path) if f.endswith('.py')
- and not f.startswith('__init__')
- and f.startswith('tosca_')]
-
- # For each module, pick out the target translation class
- for f in mod_files:
- # NOTE: For some reason the existing code does not use the map to
- # instantiate ToscaBlockStorageAttachment. Don't add it to the map
- # here until the dependent code is fixed to use the map.
- if f == 'tosca_block_storage_attachment.py':
- continue
-
- mod_name = cls_path + '/' + f.strip('.py')
- mod_name = mod_name.replace('/', '.')
- try:
- mod = importlib.import_module(mod_name)
- target_name = getattr(mod, 'TARGET_CLASS_NAME')
- clazz = getattr(mod, target_name)
- classes.append(clazz)
- except ImportError:
- raise ToscaModImportError(mod_name=mod_name)
- except AttributeError:
- if target_name:
- raise ToscaClassImportError(name=target_name,
- mod_name=mod_name)
- else:
- # TARGET_CLASS_NAME is not defined in module.
- # Re-raise the exception
- raise
-
-##################
-# Module constants
-##################
-
-SECTIONS = (TYPE, PROPERTIES, REQUIREMENTS, INTERFACES, LIFECYCLE, INPUT) = \
- ('type', 'properties', 'requirements',
- 'interfaces', 'lifecycle', 'input')
-
-# TODO(anyone): the following requirement names should not be hard-coded
-# in the translator. Since they are basically arbitrary names, we have to get
-# them from TOSCA type definitions.
-# To be fixed with the blueprint:
-# https://blueprints.launchpad.net/heat-translator/+spec/tosca-custom-types
-REQUIRES = (CONTAINER, DEPENDENCY, DATABASE_ENDPOINT, CONNECTION, HOST) = \
- ('container', 'dependency', 'database_endpoint',
- 'connection', 'host')
-
-INTERFACES_STATE = (CREATE, START, CONFIGURE, START, DELETE) = \
- ('create', 'stop', 'configure', 'start', 'delete')
-
-
-TOSCA_TO_HOT_REQUIRES = {'container': 'server', 'host': 'server',
- 'dependency': 'depends_on', "connects": 'depends_on'}
-
-TOSCA_TO_HOT_PROPERTIES = {'properties': 'input'}
-log = logging.getLogger('heat-translator')
-
-TOSCA_TO_HOT_TYPE = _generate_type_map()
-
-
-class TranslateNodeTemplates(object):
- '''Translate TOSCA NodeTemplates to Heat Resources.'''
-
- def __init__(self, tosca, hot_template):
- self.tosca = tosca
- self.nodetemplates = self.tosca.nodetemplates
- self.hot_template = hot_template
- # list of all HOT resources generated
- self.hot_resources = []
- # mapping between TOSCA nodetemplate and HOT resource
- self.hot_lookup = {}
-
- def translate(self):
- return self._translate_nodetemplates()
-
- def _recursive_handle_properties(self, resource):
- '''Recursively handle the properties of the depends_on_nodes nodes.'''
- # Use of hashtable (dict) here should be faster?
- if resource in self.processed_resources:
- return
- self.processed_resources.append(resource)
- for depend_on in resource.depends_on_nodes:
- self._recursive_handle_properties(depend_on)
-
- resource.handle_properties()
-
- def _translate_nodetemplates(self):
-
- suffix = 0
- # Copy the TOSCA graph: nodetemplate
- for node in self.nodetemplates:
- hot_node = TOSCA_TO_HOT_TYPE[node.type](node)
- self.hot_resources.append(hot_node)
- self.hot_lookup[node] = hot_node
-
- # BlockStorage Attachment is a special case,
- # which doesn't match to Heat Resources 1 to 1.
- if node.type == "tosca.nodes.Compute":
- volume_name = None
- requirements = node.requirements
- if requirements:
- # Find the name of associated BlockStorage node
- for requires in requirements:
- for value in requires.values():
- if isinstance(value, dict):
- for node_name in value.values():
- for n in self.nodetemplates:
- if n.name == node_name:
- volume_name = node_name
- break
- else: # unreachable code !
- for n in self.nodetemplates:
- if n.name == node_name:
- volume_name = node_name
- break
-
- suffix = suffix + 1
- attachment_node = self._get_attachment_node(node,
- suffix,
- volume_name)
- if attachment_node:
- self.hot_resources.append(attachment_node)
-
- # Handle life cycle operations: this may expand each node
- # into multiple HOT resources and may change their name
- lifecycle_resources = []
- for resource in self.hot_resources:
- expanded = resource.handle_life_cycle()
- if expanded:
- lifecycle_resources += expanded
- self.hot_resources += lifecycle_resources
-
- # Handle configuration from ConnectsTo relationship in the TOSCA node:
- # this will generate multiple HOT resources, set of 2 for each
- # configuration
- connectsto_resources = []
- for node in self.nodetemplates:
- for requirement in node.requirements:
- for endpoint, details in six.iteritems(requirement):
- relation = None
- if isinstance(details, dict):
- target = details.get('node')
- relation = details.get('relationship')
- else:
- target = details
- if (target and relation and
- not isinstance(relation, six.string_types)):
- interfaces = relation.get('interfaces')
- connectsto_resources += \
- self._create_connect_configs(node,
- target,
- interfaces)
- self.hot_resources += connectsto_resources
-
- # Copy the initial dependencies based on the relationship in
- # the TOSCA template
- for node in self.nodetemplates:
- for node_depend in node.related_nodes:
- # if the source of dependency is a server and the
- # relationship type is 'tosca.relationships.HostedOn',
- # add dependency as properties.server
- if node_depend.type == 'tosca.nodes.Compute' and \
- node.related[node_depend].type == \
- node.type_definition.HOSTEDON:
- self.hot_lookup[node].properties['server'] = \
- {'get_resource': self.hot_lookup[node_depend].name}
- # for all others, add dependency as depends_on
- else:
- self.hot_lookup[node].depends_on.append(
- self.hot_lookup[node_depend].top_of_chain())
-
- self.hot_lookup[node].depends_on_nodes.append(
- self.hot_lookup[node_depend].top_of_chain())
-
- # handle hosting relationship
- for resource in self.hot_resources:
- resource.handle_hosting()
-
- # handle built-in properties of HOT resources
- # if a resource depends on other resources,
- # their properties need to be handled first.
- # Use recursion to handle the properties of the
- # dependent nodes in correct order
- self.processed_resources = []
- for resource in self.hot_resources:
- self._recursive_handle_properties(resource)
-
- # handle resources that need to expand to more than one HOT resource
- expansion_resources = []
- for resource in self.hot_resources:
- expanded = resource.handle_expansion()
- if expanded:
- expansion_resources += expanded
- self.hot_resources += expansion_resources
-
- # Resolve function calls: GetProperty, GetAttribute, GetInput
- # at this point, all the HOT resources should have been created
- # in the graph.
- for resource in self.hot_resources:
- # traverse the reference chain to get the actual value
- inputs = resource.properties.get('input_values')
- if inputs:
- for name, value in six.iteritems(inputs):
- if isinstance(value, GetAttribute):
- # for the attribute
- # get the proper target type to perform the translation
- args = value.result()
- target = args[0]
- hot_target = self.find_hot_resource(target)
-
- inputs[name] = hot_target.get_hot_attribute(args[1],
- args)
- else:
- if isinstance(value, GetProperty) or \
- isinstance(value, GetInput):
- inputs[name] = value.result()
-
- return self.hot_resources
-
- def _get_attachment_node(self, node, suffix, volume_name):
- attach = False
- ntpl = self.nodetemplates
- for key, value in node.relationships.items():
- if key.is_derived_from('tosca.relationships.AttachesTo'):
- if value.is_derived_from('tosca.nodes.BlockStorage'):
- attach = True
- if attach:
- relationship_tpl = None
- for req in node.requirements:
- for key, val in req.items():
- attach = val
- relship = val.get('relationship')
- for rkey, rval in val.items():
- if relship and isinstance(relship, dict):
- for rkey, rval in relship.items():
- if rkey == 'type':
- relationship_tpl = val
- attach = rval
- elif rkey == 'template':
- rel_tpl_list = \
- (self.tosca.topology_template.
- _tpl_relationship_templates())
- relationship_tpl = rel_tpl_list[rval]
- attach = rval
- else:
- continue
- elif isinstance(relship, str):
- attach = relship
- relationship_tpl = val
- relationship_templates = \
- self.tosca._tpl_relationship_templates()
- if 'relationship' in relationship_tpl and \
- attach not in \
- self.tosca._tpl_relationship_types() and \
- attach in relationship_templates:
- relationship_tpl['relationship'] = \
- relationship_templates[attach]
- break
- if relationship_tpl:
- rval_new = attach + "_" + str(suffix)
- att = RelationshipTemplate(
- relationship_tpl, rval_new,
- self.tosca._tpl_relationship_types())
- hot_node = ToscaBlockStorageAttachment(att, ntpl,
- node.name,
- volume_name
- )
- return hot_node
-
- def find_hot_resource(self, name):
- for resource in self.hot_resources:
- if resource.name == name:
- return resource
-
- def _find_tosca_node(self, tosca_name):
- for node in self.nodetemplates:
- if node.name == tosca_name:
- return node
-
- def _find_hot_resource_for_tosca(self, tosca_name):
- for node in self.nodetemplates:
- if node.name == tosca_name:
- return self.hot_lookup[node]
-
- def _create_connect_configs(self, source_node, target_name,
- connect_interfaces):
- connectsto_resources = []
- if connect_interfaces:
- for iname, interface in six.iteritems(connect_interfaces):
- connectsto_resources += \
- self._create_connect_config(source_node, target_name,
- interface)
- return connectsto_resources
-
- def _create_connect_config(self, source_node, target_name,
- connect_interface):
- connectsto_resources = []
- target_node = self._find_tosca_node(target_name)
- # the configuration can occur on the source or the target
- connect_config = connect_interface.get('pre_configure_target')
- if connect_config is not None:
- config_location = 'target'
- else:
- connect_config = connect_interface.get('pre_configure_source')
- if connect_config is not None:
- config_location = 'source'
- else:
- msg = _("Template error: "
- "no configuration found for ConnectsTo "
- "in {1}").format(self.nodetemplate.name)
- log.warning(msg)
- raise Exception(msg)
- config_name = source_node.name + '_' + target_name + '_connect_config'
- implement = connect_config.get('implementation')
- if config_location == 'target':
- hot_config = HotResource(target_node,
- config_name,
- 'OS::Heat::SoftwareConfig',
- {'config': {'get_file': implement}})
- elif config_location == 'source':
- hot_config = HotResource(source_node,
- config_name,
- 'OS::Heat::SoftwareConfig',
- {'config': {'get_file': implement}})
- connectsto_resources.append(hot_config)
- hot_target = self._find_hot_resource_for_tosca(target_name)
- hot_source = self._find_hot_resource_for_tosca(source_node.name)
- connectsto_resources.append(hot_config.
- handle_connectsto(source_node,
- target_node,
- hot_source,
- hot_target,
- config_location,
- connect_interface))
- return connectsto_resources