Add handler for ConnectsTo relationship

The ConnectsTo relationship in a node can have an interface that
contains the Configure relationship.  This interface would have
a lifecycle operation associated with it, something like a
configuration script requiring some input parameters.
In the Heat template, each of these lifecycle operation would
be implemented as a software config node.
This patch adds the handler in the main translation loop to
process the ConnectsTo relationship.

Partially Implements: blueprint translate-tosca-monitoring-usecase
Change-Id: I5ca4b935cc8189ac46dca0d24a9aa8b40133928c
This commit is contained in:
Ton Ngo 2015-06-03 23:11:26 -07:00
parent d5384a681e
commit 908e1fa120
3 changed files with 136 additions and 0 deletions

View File

@ -164,6 +164,35 @@ class HotResource(object):
return hot_resources
def handle_connectsto(self, tosca_source, tosca_target, hot_source,
hot_target, config_location, operation):
# The ConnectsTo relationship causes a configuration operation in
# the target.
# This hot resource is the software config portion in the HOT template
# This method adds the matching software deployment with the proper
# target server and dependency
if config_location == 'target':
hosting_server = hot_target._get_hosting_server()
hot_depends = hot_target
elif config_location == 'source':
hosting_server = self._get_hosting_server()
hot_depends = hot_source
deploy_name = tosca_source.name + '_' + tosca_target.name + \
'_connect_deploy'
sd_config = {'config': {'get_resource': self.name},
'server': {'get_resource': hosting_server.name}}
deploy_resource = \
HotResource(self.nodetemplate,
deploy_name,
'OS::Heat::SoftwareDeployment',
sd_config,
depends_on=[hot_depends])
connect_inputs = self._get_connect_inputs(config_location, operation)
if connect_inputs:
deploy_resource.properties['input_values'] = connect_inputs
return deploy_resource
def handle_expansion(self):
pass
@ -222,6 +251,17 @@ class HotResource(object):
deploy_inputs[name] = value
return deploy_inputs
def _get_connect_inputs(self, config_location, operation):
if config_location == 'target':
inputs = operation.get('pre_configure_target').get('inputs')
elif config_location == 'source':
inputs = operation.get('pre_configure_source').get('inputs')
deploy_inputs = {}
if inputs:
for name, value in six.iteritems(inputs):
deploy_inputs[name] = value
return deploy_inputs
def _get_hosting_server(self, node_template=None):
# find the server that hosts this software by checking the
# requirements and following the hosting chain

View File

@ -13,6 +13,7 @@
import six
from translator.hot.syntax.hot_resource import HotResource
from translator.hot.tosca.tosca_block_storage import ToscaBlockStorage
from translator.hot.tosca.tosca_block_storage_attachment import (
ToscaBlockStorageAttachment
@ -153,6 +154,24 @@ class TranslateNodeTemplates(object):
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):
target = details.get('node')
relation = details.get('relationship')
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:
@ -264,3 +283,63 @@ class TranslateNodeTemplates(object):
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:
raise Exception(_("Template error: "
"no configuration found for ConnectsTo "
"in {1}").format(self.nodetemplate.name))
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

View File

@ -117,4 +117,21 @@ resources:
depends_on:
- logstash_create_deploy
app_collectd_logstash_connect_config:
type: OS::Heat::SoftwareConfig
properties:
config:
get_file: logstash/configure_collectd.py
group: script
app_collectd_logstash_connect_deploy:
type: OS::Heat::SoftwareDeployment
properties:
config:
get_resource: app_collectd_logstash_connect_config
server:
get_resource: logstash_server
depends_on:
- logstash_create_deploy
outputs: {}