
Create TOSCA BlockStorage node type and its mapping in Heat. Introduce relationship template which will also provide a base for implementing relationship templates section in the TOSCA template. Introduce tests for generator/translator code. implements blueprint tosca-blockstorage-type Closes-Bug: #1351129 Closes-Bug: #1354632 Change-Id: I7df198ea45875031557e2607d932f14f272bf2e1
147 lines
6.4 KiB
Python
147 lines
6.4 KiB
Python
#
|
|
# 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.
|
|
|
|
from translator.hot.tosca.tosca_block_storage import ToscaBlockStorage
|
|
from translator.hot.tosca.tosca_block_storage_attachment import (
|
|
ToscaBlockStorageAttachment
|
|
)
|
|
from translator.hot.tosca.tosca_compute import ToscaCompute
|
|
from translator.hot.tosca.tosca_database import ToscaDatabase
|
|
from translator.hot.tosca.tosca_dbms import ToscaDbms
|
|
from translator.hot.tosca.tosca_webserver import ToscaWebserver
|
|
from translator.hot.tosca.tosca_wordpress import ToscaWordpress
|
|
from translator.toscalib.relationship_template import RelationshipTemplate
|
|
|
|
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')
|
|
|
|
# dict to look up HOT translation class,
|
|
# TODO(replace with function to scan the classes in translator.hot.tosca)
|
|
TOSCA_TO_HOT_TYPE = {'tosca.nodes.Compute': ToscaCompute,
|
|
'tosca.nodes.WebServer': ToscaWebserver,
|
|
'tosca.nodes.DBMS': ToscaDbms,
|
|
'tosca.nodes.Database': ToscaDatabase,
|
|
'tosca.nodes.WebApplication.WordPress': ToscaWordpress,
|
|
'tosca.nodes.BlockStorage': ToscaBlockStorage}
|
|
|
|
TOSCA_TO_HOT_REQUIRES = {'container': 'server', 'host': 'server',
|
|
'dependency': 'depends_on', "connects": 'depends_on'}
|
|
|
|
TOSCA_TO_HOT_PROPERTIES = {'properties': 'input'}
|
|
|
|
|
|
class TranslateNodeTemplates():
|
|
'''Translate TOSCA NodeTemplates to Heat Resources.'''
|
|
|
|
def __init__(self, nodetemplates, hot_template):
|
|
self.nodetemplates = nodetemplates
|
|
self.hot_template = hot_template
|
|
|
|
def translate(self):
|
|
return self._translate_nodetemplates()
|
|
|
|
def _translate_nodetemplates(self):
|
|
hot_resources = []
|
|
hot_lookup = {}
|
|
|
|
attachment_suffix = 0
|
|
# Copy the TOSCA graph: nodetemplate
|
|
for node in self.nodetemplates:
|
|
hot_node = TOSCA_TO_HOT_TYPE[node.type](node)
|
|
hot_resources.append(hot_node)
|
|
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
|
|
reuirements = node.requirements
|
|
# Find the name of associated BlockStorage node
|
|
for requires in reuirements:
|
|
for value in requires.values():
|
|
for n in self.nodetemplates:
|
|
if n.name == value:
|
|
volume_name = value
|
|
break
|
|
attachment_suffix = attachment_suffix + 1
|
|
attachment_node = self._get_attachment_node(node,
|
|
attachment_suffix,
|
|
volume_name)
|
|
if attachment_node:
|
|
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 hot_resources:
|
|
expanded = resource.handle_life_cycle()
|
|
if expanded:
|
|
lifecycle_resources += expanded
|
|
hot_resources += lifecycle_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, add dependency
|
|
# as properties.get_resource
|
|
if node_depend.type == 'tosca.nodes.Compute':
|
|
hot_lookup[node].properties['server'] = \
|
|
{'get_resource': hot_lookup[node_depend].name}
|
|
# for all others, add dependency as depends_on
|
|
else:
|
|
hot_lookup[node].depends_on.append(hot_lookup[node_depend].
|
|
top_of_chain())
|
|
|
|
# handle hosting relationship
|
|
for resource in hot_resources:
|
|
resource.handle_hosting()
|
|
|
|
# Handle properties
|
|
for resource in hot_resources:
|
|
resource.handle_properties()
|
|
|
|
return hot_resources
|
|
|
|
def _get_attachment_node(self, node, suffix, volume_name):
|
|
attach = False
|
|
ntpl = self.nodetemplates
|
|
for key, value in node.relationship.items():
|
|
if key.type == 'tosca.relationships.AttachTo':
|
|
if value.type == 'tosca.nodes.BlockStorage':
|
|
attach = True
|
|
if attach:
|
|
for req in node.requirements:
|
|
for rkey, rval in req.items():
|
|
if rkey == 'type':
|
|
rval = rval + "_" + str(suffix)
|
|
att = RelationshipTemplate(req, rval, None)
|
|
hot_node = ToscaBlockStorageAttachment(att, ntpl,
|
|
node.name,
|
|
volume_name
|
|
)
|
|
return hot_node
|