Adds support for SoftwareDeploymentGroup in HT

Change-Id: I7f23bc663ac315d8cab931465ea3a0ca18794d69
Closes-Bug: #1646929
This commit is contained in:
Bharath Thiruveedula 2016-12-05 23:02:45 +05:30
parent 947752a644
commit e793a3efba
4 changed files with 196 additions and 19 deletions

View File

@ -139,13 +139,25 @@ class HotResource(object):
hosting_server = None
if self.nodetemplate.requirements is not None:
hosting_server = self._get_hosting_server()
servers = {}
server_key = 'server'
sw_deploy_res = 'OS::Heat::SoftwareDeployment'
if hosting_server is not None:
if len(hosting_server) == 1:
servers['get_resource'] = hosting_server[0]
else:
for server in hosting_server:
servers[server] = {'get_resource': server}
sw_deploy_res += 'Group'
server_key = 'servers'
# hosting_server is None if requirements is None
hosting_on_server = hosting_server.name if hosting_server else None
hosting_on_server = hosting_server if hosting_server else None
base_type = HotResource.get_base_type_str(
self.nodetemplate.type_definition)
# if we are on a compute node the host is self
if hosting_on_server is None and base_type == 'tosca.nodes.Compute':
hosting_on_server = self.name
servers = {'get_resource': self.name}
cwd = os.getcwd()
for operation in operations.values():
@ -168,19 +180,17 @@ class HotResource(object):
base_type != 'tosca.nodes.Compute':
deploy_resource = self
self.name = deploy_name
self.type = 'OS::Heat::SoftwareDeployment'
self.type = sw_deploy_res
self.properties = {'config': {'get_resource': config_name},
'server': {'get_resource':
hosting_on_server}}
server_key: servers}
deploy_lookup[operation] = self
else:
sd_config = {'config': {'get_resource': config_name},
'server': {'get_resource':
hosting_on_server}}
server_key: servers}
deploy_resource = \
HotResource(self.nodetemplate,
deploy_name,
'OS::Heat::SoftwareDeployment',
sw_deploy_res,
sd_config, csar_dir=self.csar_dir)
hot_resources.append(deploy_resource)
deploy_lookup[operation] = deploy_resource
@ -225,7 +235,7 @@ class HotResource(object):
hot.group_dependencies.update(group)
roles_deploy_resource = self._handle_ansiblegalaxy_roles(
hot_resources, node_name, hosting_on_server)
hot_resources, node_name, servers)
# add a dependency to this ansible roles deploy to
# the first "classic" deploy generated for this node
@ -241,6 +251,11 @@ class HotResource(object):
hosting_on_server):
artifacts = self.get_all_artifacts(self.nodetemplate)
install_roles_script = ''
server_key = 'server'
sw_deploy_res = 'OS::Heat::SoftwareDeployment'
if len(hosting_on_server.keys()) > 1:
server_key += 's'
sw_deploy_res += 'Group'
for artifact_name, artifact in artifacts.items():
artifact_type = artifact.get('type', '').lower()
if artifact_type == 'tosca.artifacts.ansiblegalaxy.role':
@ -263,11 +278,10 @@ class HotResource(object):
{'config': install_roles_script},
csar_dir=self.csar_dir))
sd_config = {'config': {'get_resource': config_name},
'server': {'get_resource':
hosting_on_server}}
server_key: hosting_on_server}
deploy_resource = \
HotResource(self.nodetemplate, deploy_name,
'OS::Heat::SoftwareDeployment',
sw_deploy_res,
sd_config, csar_dir=self.csar_dir)
hot_resources.append(deploy_resource)
@ -280,20 +294,31 @@ class HotResource(object):
# 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
servers = {}
server_key = 'server'
sw_deploy_res = 'OS::Heat::SoftwareDeployment'
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
if hosting_server is not None:
if len(hosting_server) == 1:
servers['get_resource'] = hosting_server[0]
else:
for server in hosting_server:
servers[server] = {'get_resource': server}
sw_deploy_res += 'Group'
server_key = 'servers'
deploy_name = tosca_source.name + '_' + tosca_target.name + \
'_connect_deploy'
sd_config = {'config': {'get_resource': self.name},
'server': {'get_resource': hosting_server.name}}
server_key: servers}
deploy_resource = \
HotResource(self.nodetemplate,
deploy_name,
'OS::Heat::SoftwareDeployment',
sw_deploy_res,
sd_config,
depends_on=[hot_depends], csar_dir=self.csar_dir)
connect_inputs = self._get_connect_inputs(config_location, operation)
@ -309,17 +334,29 @@ class HotResource(object):
# handle hosting server for the OS:HEAT::SoftwareDeployment
# from the TOSCA nodetemplate, traverse the relationship chain
# down to the server
if self.type == 'OS::Heat::SoftwareDeployment':
sw_deploy_group = 'OS::Heat::SoftwareDeploymentGroup'
sw_deploy = 'OS::Heat::SoftwareDeployment'
if self.properties.get('servers') and \
self.properties.get('server'):
del self.properties['server']
if self.type == sw_deploy_group or self.type == sw_deploy:
# skip if already have hosting
# If type is NodeTemplate, look up corresponding HotResrouce
host_server = self.properties.get('server')
if host_server is None or not host_server['get_resource']:
host_server = self.properties.get('servers') \
or self.properties.get('server')
if host_server is None:
raise Exception(_("Internal Error: expecting host "
"in software deployment"))
elif isinstance(host_server['get_resource'], NodeTemplate):
elif isinstance(host_server.get('get_resource'), NodeTemplate):
self.properties['server']['get_resource'] = \
host_server['get_resource'].name
elif isinstance(host_server, dict) and \
not host_server.get('get_resource'):
self.properties['servers'] = \
host_server
def top_of_chain(self):
dependent = self.group_dependencies.get(self)
if dependent is None:
@ -374,6 +411,8 @@ class HotResource(object):
def _get_hosting_server(self, node_template=None):
# find the server that hosts this software by checking the
# requirements and following the hosting chain
hosting_servers = []
host_exists = False
this_node_template = self.nodetemplate \
if node_template is None else node_template
for requirement in this_node_template.requirements:
@ -387,9 +426,12 @@ class HotResource(object):
if node_name and node_name == check_node.name:
if self._is_container_type(requirement_name,
check_node):
return check_node
elif check_node.related_nodes:
hosting_servers.append(check_node.name)
host_exists = True
elif check_node.related_nodes and not host_exists:
return self._get_hosting_server(check_node)
if hosting_servers:
return hosting_servers
return None
def _is_container_type(self, requirement_name, node):

View File

@ -0,0 +1,71 @@
heat_template_version: 2013-05-23
description: >
TOSCA simple profile with a software component.
parameters:
cpus:
type: number
description: Number of CPUs for the server.
default: 1
constraints:
- allowed_values:
- 1
- 2
- 4
- 8
resources:
server1:
type: OS::Nova::Server
properties:
flavor: m1.small
image: ubuntu-software-config-os-init
user_data_format: SOFTWARE_CONFIG
server2:
type: OS::Nova::Server
properties:
flavor: m1.small
image: ubuntu-software-config-os-init
user_data_format: SOFTWARE_CONFIG
my_software_create_deploy:
type: OS::Heat::SoftwareDeploymentGroup
properties:
config:
get_resource: my_software_create_config
servers:
server1:
get_resource: server1
server2:
get_resource: server2
my_software_create_config:
type: OS::Heat::SoftwareConfig
properties:
config:
get_file: software_install.sh
group: script
my_software_start_deploy:
type: OS::Heat::SoftwareDeploymentGroup
properties:
config:
get_resource: my_software_start_config
servers:
server1:
get_resource: server1
server2:
get_resource: server2
depends_on:
- my_software_create_deploy
my_software_start_config:
type: OS::Heat::SoftwareConfig
properties:
config:
get_file: software_start.sh
group: script
outputs: {}

View File

@ -0,0 +1,55 @@
tosca_definitions_version: tosca_simple_yaml_1_0
description: >
TOSCA simple profile with a software component.
topology_template:
inputs:
cpus:
type: integer
description: Number of CPUs for the server.
constraints:
- valid_values: [ 1, 2, 4, 8 ]
default: 1
node_templates:
my_software:
type: tosca.nodes.SoftwareComponent
properties:
component_version: 1.0
requirements:
- host: server1
- host: server2
interfaces:
Standard:
create: software_install.sh
start: software_start.sh
server1:
type: tosca.nodes.Compute
capabilities:
host:
properties:
disk_size: 10 GB
num_cpus: { get_input: cpus }
mem_size: 1024 MB
os:
properties:
architecture: x86_64
type: Linux
distribution: Ubuntu
version: 14.04
server2:
type: tosca.nodes.Compute
capabilities:
host:
properties:
disk_size: 10 GB
num_cpus: { get_input: cpus }
mem_size: 1024 MB
os:
properties:
architecture: x86_64
type: Linux
distribution: Ubuntu
version: 14.04

View File

@ -235,6 +235,15 @@ class ToscaHotTranslationTest(TestCase):
'download_url': 'http://www.software.com/download'}
self._test_successful_translation(tosca_file, hot_file, params)
def test_hot_translate_software_component_multiple_hosts(self):
tosca_file = '../tests/data/tosca_software_component'\
'_multiple_hosts.yaml'
hot_file = '../tests/data/hot_output/hot_software_component'\
'_multiple_hosts.yaml'
params = {'cpus': '1',
'download_url': 'http://www.software.com/download'}
self._test_successful_translation(tosca_file, hot_file, params)
def test_hot_translate_web_application(self):
tosca_file = '../tests/data/tosca_web_application.yaml'
hot_file = '../tests/data/hot_output/hot_web_application.yaml'