Handle interfaces directly defined on a TOSCA Compute node.
Change-Id: I0b6f3c5bfb557bdbe16d22f89c4a9c7da4d6030e
This commit is contained in:
parent
3b7fe1d7e4
commit
1267ad19c0
@ -141,14 +141,22 @@ class HotResource(object):
|
|||||||
# hosting_server is None if requirements is None
|
# hosting_server is None if requirements is None
|
||||||
hosting_on_server = (hosting_server.name if
|
hosting_on_server = (hosting_server.name if
|
||||||
hosting_server else None)
|
hosting_server else None)
|
||||||
if operation.name == reserve_current:
|
base_type = HotResource.get_base_type(
|
||||||
|
self.nodetemplate.type_definition).type
|
||||||
|
# handle interfaces directly defined on a compute
|
||||||
|
if hosting_on_server is None \
|
||||||
|
and base_type == 'tosca.nodes.Compute':
|
||||||
|
hosting_on_server = self.name
|
||||||
|
|
||||||
|
if operation.name == reserve_current and \
|
||||||
|
base_type != 'tosca.nodes.Compute':
|
||||||
deploy_resource = self
|
deploy_resource = self
|
||||||
self.name = deploy_name
|
self.name = deploy_name
|
||||||
self.type = 'OS::Heat::SoftwareDeployment'
|
self.type = 'OS::Heat::SoftwareDeployment'
|
||||||
self.properties = {'config': {'get_resource': config_name},
|
self.properties = {'config': {'get_resource': config_name},
|
||||||
'server': {'get_resource':
|
'server': {'get_resource':
|
||||||
hosting_on_server}}
|
hosting_on_server}}
|
||||||
deploy_lookup[operation.name] = self
|
deploy_lookup[operation] = self
|
||||||
else:
|
else:
|
||||||
sd_config = {'config': {'get_resource': config_name},
|
sd_config = {'config': {'get_resource': config_name},
|
||||||
'server': {'get_resource':
|
'server': {'get_resource':
|
||||||
@ -159,7 +167,7 @@ class HotResource(object):
|
|||||||
'OS::Heat::SoftwareDeployment',
|
'OS::Heat::SoftwareDeployment',
|
||||||
sd_config)
|
sd_config)
|
||||||
hot_resources.append(deploy_resource)
|
hot_resources.append(deploy_resource)
|
||||||
deploy_lookup[operation.name] = deploy_resource
|
deploy_lookup[operation] = deploy_resource
|
||||||
lifecycle_inputs = self._get_lifecycle_inputs(operation)
|
lifecycle_inputs = self._get_lifecycle_inputs(operation)
|
||||||
if lifecycle_inputs:
|
if lifecycle_inputs:
|
||||||
deploy_resource.properties['input_values'] = \
|
deploy_resource.properties['input_values'] = \
|
||||||
@ -169,24 +177,34 @@ class HotResource(object):
|
|||||||
# in operations_deploy_sequence
|
# in operations_deploy_sequence
|
||||||
# TODO(anyone): find some better way to encode this implicit sequence
|
# TODO(anyone): find some better way to encode this implicit sequence
|
||||||
group = {}
|
group = {}
|
||||||
|
op_index_max = -1
|
||||||
for op, hot in deploy_lookup.items():
|
for op, hot in deploy_lookup.items():
|
||||||
# position to determine potential preceding nodes
|
# position to determine potential preceding nodes
|
||||||
op_index = operations_deploy_sequence.index(op)
|
op_index = operations_deploy_sequence.index(op.name)
|
||||||
for preceding_op in \
|
if op_index > op_index_max:
|
||||||
|
op_index_max = op_index
|
||||||
|
for preceding_op_name in \
|
||||||
reversed(operations_deploy_sequence[:op_index]):
|
reversed(operations_deploy_sequence[:op_index]):
|
||||||
preceding_hot = deploy_lookup.get(preceding_op)
|
preceding_hot = deploy_lookup.get(
|
||||||
|
operations.get(preceding_op_name))
|
||||||
if preceding_hot:
|
if preceding_hot:
|
||||||
hot.depends_on.append(preceding_hot)
|
hot.depends_on.append(preceding_hot)
|
||||||
hot.depends_on_nodes.append(preceding_hot)
|
hot.depends_on_nodes.append(preceding_hot)
|
||||||
group[preceding_hot] = hot
|
group[preceding_hot] = hot
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if op_index_max >= 0:
|
||||||
|
last_deploy = deploy_lookup.get(operations.get(
|
||||||
|
operations_deploy_sequence[op_index_max]))
|
||||||
|
else:
|
||||||
|
last_deploy = None
|
||||||
|
|
||||||
# save this dependency chain in the set of HOT resources
|
# save this dependency chain in the set of HOT resources
|
||||||
self.group_dependencies.update(group)
|
self.group_dependencies.update(group)
|
||||||
for hot in hot_resources:
|
for hot in hot_resources:
|
||||||
hot.group_dependencies.update(group)
|
hot.group_dependencies.update(group)
|
||||||
|
|
||||||
return hot_resources
|
return hot_resources, deploy_lookup, last_deploy
|
||||||
|
|
||||||
def handle_connectsto(self, tosca_source, tosca_target, hot_source,
|
def handle_connectsto(self, tosca_source, tosca_target, hot_source,
|
||||||
hot_target, config_location, operation):
|
hot_target, config_location, operation):
|
||||||
|
@ -50,4 +50,4 @@ class ToscaBlockStorageAttachment(HotResource):
|
|||||||
self.properties.pop('device')
|
self.properties.pop('device')
|
||||||
|
|
||||||
def handle_life_cycle(self):
|
def handle_life_cycle(self):
|
||||||
pass
|
return None, None, None
|
||||||
|
@ -84,6 +84,14 @@ class ToscaCompute(HotResource):
|
|||||||
('architecture', 'distribution', 'type', 'version')
|
('architecture', 'distribution', 'type', 'version')
|
||||||
toscatype = 'tosca.nodes.Compute'
|
toscatype = 'tosca.nodes.Compute'
|
||||||
|
|
||||||
|
ALLOWED_NOVA_SERVER_PROPS = \
|
||||||
|
('admin_pass', 'availability_zone', 'block_device_mapping',
|
||||||
|
'block_device_mapping_v2', 'config_drive', 'diskConfig', 'flavor',
|
||||||
|
'flavor_update_policy', 'image', 'image_update_policy', 'key_name',
|
||||||
|
'metadata', 'name', 'networks', 'personality', 'reservation_id',
|
||||||
|
'scheduler_hints', 'security_groups', 'software_config_transport',
|
||||||
|
'user_data', 'user_data_format', 'user_data_update_policy')
|
||||||
|
|
||||||
def __init__(self, nodetemplate):
|
def __init__(self, nodetemplate):
|
||||||
super(ToscaCompute, self).__init__(nodetemplate,
|
super(ToscaCompute, self).__init__(nodetemplate,
|
||||||
type='OS::Nova::Server')
|
type='OS::Nova::Server')
|
||||||
@ -98,6 +106,7 @@ class ToscaCompute(HotResource):
|
|||||||
self.properties['user_data_format'] = 'SOFTWARE_CONFIG'
|
self.properties['user_data_format'] = 'SOFTWARE_CONFIG'
|
||||||
tosca_props = self.get_tosca_props()
|
tosca_props = self.get_tosca_props()
|
||||||
for key, value in tosca_props.items():
|
for key, value in tosca_props.items():
|
||||||
|
if key in self.ALLOWED_NOVA_SERVER_PROPS:
|
||||||
self.properties[key] = value
|
self.properties[key] = value
|
||||||
|
|
||||||
# To be reorganized later based on new development in Glance and Graffiti
|
# To be reorganized later based on new development in Glance and Graffiti
|
||||||
|
@ -146,6 +146,9 @@ class TranslateNodeTemplates(object):
|
|||||||
log.debug(_('Mapping between TOSCA nodetemplate and HOT resource.'))
|
log.debug(_('Mapping between TOSCA nodetemplate and HOT resource.'))
|
||||||
self.hot_lookup = {}
|
self.hot_lookup = {}
|
||||||
self.policies = self.tosca.topology_template.policies
|
self.policies = self.tosca.topology_template.policies
|
||||||
|
# stores the last deploy of generated behavior for a resource
|
||||||
|
# useful to satisfy underlying dependencies between interfaces
|
||||||
|
self.last_deploy_map = {}
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
return self._translate_nodetemplates()
|
return self._translate_nodetemplates()
|
||||||
@ -219,9 +222,14 @@ class TranslateNodeTemplates(object):
|
|||||||
# into multiple HOT resources and may change their name
|
# into multiple HOT resources and may change their name
|
||||||
lifecycle_resources = []
|
lifecycle_resources = []
|
||||||
for resource in self.hot_resources:
|
for resource in self.hot_resources:
|
||||||
expanded = resource.handle_life_cycle()
|
expanded_resources, deploy_lookup, last_deploy = resource.\
|
||||||
if expanded:
|
handle_life_cycle()
|
||||||
lifecycle_resources += expanded
|
if expanded_resources:
|
||||||
|
lifecycle_resources += expanded_resources
|
||||||
|
if deploy_lookup:
|
||||||
|
self.hot_lookup.update(deploy_lookup)
|
||||||
|
if last_deploy:
|
||||||
|
self.last_deploy_map[resource] = last_deploy
|
||||||
self.hot_resources += lifecycle_resources
|
self.hot_resources += lifecycle_resources
|
||||||
|
|
||||||
# Handle configuration from ConnectsTo relationship in the TOSCA node:
|
# Handle configuration from ConnectsTo relationship in the TOSCA node:
|
||||||
@ -253,7 +261,9 @@ class TranslateNodeTemplates(object):
|
|||||||
# if the source of dependency is a server and the
|
# if the source of dependency is a server and the
|
||||||
# relationship type is 'tosca.relationships.HostedOn',
|
# relationship type is 'tosca.relationships.HostedOn',
|
||||||
# add dependency as properties.server
|
# add dependency as properties.server
|
||||||
if node_depend.type == 'tosca.nodes.Compute' and \
|
base_type = HotResource.get_base_type(
|
||||||
|
node_depend.type_definition)
|
||||||
|
if base_type.type == 'tosca.nodes.Compute' and \
|
||||||
node.related[node_depend].type == \
|
node.related[node_depend].type == \
|
||||||
node.type_definition.HOSTEDON:
|
node.type_definition.HOSTEDON:
|
||||||
self.hot_lookup[node].properties['server'] = \
|
self.hot_lookup[node].properties['server'] = \
|
||||||
@ -266,6 +276,13 @@ class TranslateNodeTemplates(object):
|
|||||||
self.hot_lookup[node].depends_on_nodes.append(
|
self.hot_lookup[node].depends_on_nodes.append(
|
||||||
self.hot_lookup[node_depend].top_of_chain())
|
self.hot_lookup[node_depend].top_of_chain())
|
||||||
|
|
||||||
|
last_deploy = self.last_deploy_map.get(
|
||||||
|
self.hot_lookup[node_depend])
|
||||||
|
if last_deploy and \
|
||||||
|
last_deploy not in self.hot_lookup[node].depends_on:
|
||||||
|
self.hot_lookup[node].depends_on.append(last_deploy)
|
||||||
|
self.hot_lookup[node].depends_on_nodes.append(last_deploy)
|
||||||
|
|
||||||
# handle hosting relationship
|
# handle hosting relationship
|
||||||
for resource in self.hot_resources:
|
for resource in self.hot_resources:
|
||||||
resource.handle_hosting()
|
resource.handle_hosting()
|
||||||
@ -297,6 +314,17 @@ class TranslateNodeTemplates(object):
|
|||||||
for name, value in six.iteritems(inputs):
|
for name, value in six.iteritems(inputs):
|
||||||
inputs[name] = self._translate_input(value, resource)
|
inputs[name] = self._translate_input(value, resource)
|
||||||
|
|
||||||
|
# remove resources without type defined
|
||||||
|
# for example a SoftwareComponent without interfaces
|
||||||
|
# would fall in this case
|
||||||
|
to_remove = []
|
||||||
|
for resource in self.hot_resources:
|
||||||
|
if resource.type is None:
|
||||||
|
to_remove.append(resource)
|
||||||
|
|
||||||
|
for resource in to_remove:
|
||||||
|
self.hot_resources.remove(resource)
|
||||||
|
|
||||||
return self.hot_resources
|
return self.hot_resources
|
||||||
|
|
||||||
def _translate_input(self, input_value, resource):
|
def _translate_input(self, input_value, resource):
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
heat_template_version: 2013-05-23
|
||||||
|
|
||||||
|
description: >
|
||||||
|
TOSCA template to test Compute node with interface
|
||||||
|
|
||||||
|
parameters: {}
|
||||||
|
resources:
|
||||||
|
softwarecomponent_depending_on_customcompute_install_create_deploy:
|
||||||
|
type: OS::Heat::SoftwareDeployment
|
||||||
|
properties:
|
||||||
|
config:
|
||||||
|
get_resource: softwarecomponent_depending_on_customcompute_install_create_config
|
||||||
|
server:
|
||||||
|
get_resource: server
|
||||||
|
depends_on:
|
||||||
|
- server_create_deploy
|
||||||
|
server:
|
||||||
|
type: OS::Nova::Server
|
||||||
|
properties:
|
||||||
|
flavor: m1.small
|
||||||
|
image: ubuntu-12.04-software-config-os-init
|
||||||
|
user_data_format: SOFTWARE_CONFIG
|
||||||
|
softwarecomponent_depending_on_customcompute_install_create_config:
|
||||||
|
type: OS::Heat::SoftwareConfig
|
||||||
|
properties:
|
||||||
|
config:
|
||||||
|
get_file: post_install.sh
|
||||||
|
group: script
|
||||||
|
server_create_config:
|
||||||
|
type: OS::Heat::SoftwareConfig
|
||||||
|
properties:
|
||||||
|
config:
|
||||||
|
get_file: install.sh
|
||||||
|
group: script
|
||||||
|
server_create_deploy:
|
||||||
|
type: OS::Heat::SoftwareDeployment
|
||||||
|
properties:
|
||||||
|
config:
|
||||||
|
get_resource: server_create_config
|
||||||
|
input_values:
|
||||||
|
install_path: /opt
|
||||||
|
server:
|
||||||
|
get_resource: server
|
||||||
|
outputs: {}
|
48
translator/tests/data/test_tosca_interface_on_compute.yaml
Normal file
48
translator/tests/data/test_tosca_interface_on_compute.yaml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
tosca_definitions_version: tosca_simple_yaml_1_0
|
||||||
|
|
||||||
|
description: TOSCA template to test Compute node with interface
|
||||||
|
|
||||||
|
node_types:
|
||||||
|
tosca.nodes.CustomCompute:
|
||||||
|
derived_from: tosca.nodes.Compute
|
||||||
|
properties:
|
||||||
|
install_path:
|
||||||
|
type: string
|
||||||
|
default: /opt
|
||||||
|
interfaces:
|
||||||
|
Standard:
|
||||||
|
create:
|
||||||
|
implementation: install.sh
|
||||||
|
inputs:
|
||||||
|
install_path: { get_property: [ SELF, install_path ] }
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
node_templates:
|
||||||
|
|
||||||
|
softwarecomponent_without_behavior:
|
||||||
|
type: tosca.nodes.SoftwareComponent
|
||||||
|
requirements:
|
||||||
|
- host: server
|
||||||
|
|
||||||
|
softwarecomponent_depending_on_customcompute_install:
|
||||||
|
type: tosca.nodes.SoftwareComponent
|
||||||
|
interfaces:
|
||||||
|
Standard:
|
||||||
|
create:
|
||||||
|
implementation: post_install.sh
|
||||||
|
requirements:
|
||||||
|
- host: server
|
||||||
|
|
||||||
|
server:
|
||||||
|
type: tosca.nodes.CustomCompute
|
||||||
|
capabilities:
|
||||||
|
host:
|
||||||
|
properties:
|
||||||
|
num_cpus: 1
|
||||||
|
mem_size: 1 GB
|
||||||
|
os:
|
||||||
|
properties:
|
||||||
|
type: Linux
|
||||||
|
distribution: Ubuntu
|
||||||
|
version: 12.04
|
||||||
|
architecture: x86_64
|
@ -471,3 +471,9 @@ class ToscaHotTranslationTest(TestCase):
|
|||||||
hot_file = '../tests/data/hot_output/hot_script_types.yaml'
|
hot_file = '../tests/data/hot_output/hot_script_types.yaml'
|
||||||
params = {}
|
params = {}
|
||||||
self._test_successful_translation(tosca_file, hot_file, params)
|
self._test_successful_translation(tosca_file, hot_file, params)
|
||||||
|
|
||||||
|
def test_hot_interface_on_compute(self):
|
||||||
|
tosca_file = '../tests/data/test_tosca_interface_on_compute.yaml'
|
||||||
|
hot_file = '../tests/data/hot_output/hot_interface_on_compute.yaml'
|
||||||
|
params = {}
|
||||||
|
self._test_successful_translation(tosca_file, hot_file, params)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user