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_on_server = (hosting_server.name if
|
||||
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
|
||||
self.name = deploy_name
|
||||
self.type = 'OS::Heat::SoftwareDeployment'
|
||||
self.properties = {'config': {'get_resource': config_name},
|
||||
'server': {'get_resource':
|
||||
hosting_on_server}}
|
||||
deploy_lookup[operation.name] = self
|
||||
deploy_lookup[operation] = self
|
||||
else:
|
||||
sd_config = {'config': {'get_resource': config_name},
|
||||
'server': {'get_resource':
|
||||
@ -159,7 +167,7 @@ class HotResource(object):
|
||||
'OS::Heat::SoftwareDeployment',
|
||||
sd_config)
|
||||
hot_resources.append(deploy_resource)
|
||||
deploy_lookup[operation.name] = deploy_resource
|
||||
deploy_lookup[operation] = deploy_resource
|
||||
lifecycle_inputs = self._get_lifecycle_inputs(operation)
|
||||
if lifecycle_inputs:
|
||||
deploy_resource.properties['input_values'] = \
|
||||
@ -169,24 +177,34 @@ class HotResource(object):
|
||||
# in operations_deploy_sequence
|
||||
# TODO(anyone): find some better way to encode this implicit sequence
|
||||
group = {}
|
||||
op_index_max = -1
|
||||
for op, hot in deploy_lookup.items():
|
||||
# position to determine potential preceding nodes
|
||||
op_index = operations_deploy_sequence.index(op)
|
||||
for preceding_op in \
|
||||
op_index = operations_deploy_sequence.index(op.name)
|
||||
if op_index > op_index_max:
|
||||
op_index_max = op_index
|
||||
for preceding_op_name in \
|
||||
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:
|
||||
hot.depends_on.append(preceding_hot)
|
||||
hot.depends_on_nodes.append(preceding_hot)
|
||||
group[preceding_hot] = hot
|
||||
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
|
||||
self.group_dependencies.update(group)
|
||||
for hot in hot_resources:
|
||||
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,
|
||||
hot_target, config_location, operation):
|
||||
|
@ -50,4 +50,4 @@ class ToscaBlockStorageAttachment(HotResource):
|
||||
self.properties.pop('device')
|
||||
|
||||
def handle_life_cycle(self):
|
||||
pass
|
||||
return None, None, None
|
||||
|
@ -84,6 +84,14 @@ class ToscaCompute(HotResource):
|
||||
('architecture', 'distribution', 'type', 'version')
|
||||
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):
|
||||
super(ToscaCompute, self).__init__(nodetemplate,
|
||||
type='OS::Nova::Server')
|
||||
@ -98,6 +106,7 @@ class ToscaCompute(HotResource):
|
||||
self.properties['user_data_format'] = 'SOFTWARE_CONFIG'
|
||||
tosca_props = self.get_tosca_props()
|
||||
for key, value in tosca_props.items():
|
||||
if key in self.ALLOWED_NOVA_SERVER_PROPS:
|
||||
self.properties[key] = value
|
||||
|
||||
# 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.'))
|
||||
self.hot_lookup = {}
|
||||
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):
|
||||
return self._translate_nodetemplates()
|
||||
@ -219,9 +222,14 @@ class TranslateNodeTemplates(object):
|
||||
# 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
|
||||
expanded_resources, deploy_lookup, last_deploy = resource.\
|
||||
handle_life_cycle()
|
||||
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
|
||||
|
||||
# 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
|
||||
# relationship type is 'tosca.relationships.HostedOn',
|
||||
# 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.type_definition.HOSTEDON:
|
||||
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_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
|
||||
for resource in self.hot_resources:
|
||||
resource.handle_hosting()
|
||||
@ -297,6 +314,17 @@ class TranslateNodeTemplates(object):
|
||||
for name, value in six.iteritems(inputs):
|
||||
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
|
||||
|
||||
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'
|
||||
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…
Reference in New Issue
Block a user