Fix host server assignment for resources with multi-node dependency
An additional check was introduced for determining the host node to verify the type of relationship, and assign a node as host only if a 'tosca.relationships.HostedOn' relationship exists between the two nodes. A test case is also added. Change-Id: Iec5d0f70b092dd2a09c514e0f28e638abdb25997 Closes-Bug: #1455263
This commit is contained in:
parent
e2143adbf8
commit
d98ecc8691
@ -157,9 +157,12 @@ class TranslateNodeTemplates(object):
|
||||
# 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':
|
||||
# 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 \
|
||||
node.related[node_depend].type == \
|
||||
node.type_definition.HOSTEDON:
|
||||
self.hot_lookup[node].properties['server'] = \
|
||||
{'get_resource': self.hot_lookup[node_depend].name}
|
||||
# for all others, add dependency as depends_on
|
||||
|
@ -10,8 +10,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from translator.common.utils import CompareUtils
|
||||
from translator.hot.tosca_translator import TOSCATranslator
|
||||
from translator.tests.base import TestCase
|
||||
from translator.toscalib.tosca_template import ToscaTemplate
|
||||
@ -48,7 +50,7 @@ class ToscaNetworkTest(TestCase):
|
||||
}}
|
||||
|
||||
expected_resource_3 = {'type': 'OS::Neutron::Port',
|
||||
'depends_on': ['my_network'],
|
||||
'depends_on': ['my_server', 'my_network'],
|
||||
'properties':
|
||||
{'network': {'get_resource': 'my_network'}
|
||||
}}
|
||||
@ -67,7 +69,11 @@ class ToscaNetworkTest(TestCase):
|
||||
self.assertEqual(resources.get('my_network'), expected_resource_1)
|
||||
self.assertEqual(resources.get('my_network_subnet'),
|
||||
expected_resource_2)
|
||||
self.assertEqual(resources.get('my_port'), expected_resource_3)
|
||||
|
||||
diff = CompareUtils.diff_dicts(resources.get('my_port'),
|
||||
expected_resource_3)
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4, separators=(', ', ': ')))
|
||||
|
||||
self.assertIn('properties', resources.get('my_server'))
|
||||
self.assertIn('networks', resources.get('my_server').get('properties'))
|
||||
@ -107,14 +113,20 @@ class ToscaNetworkTest(TestCase):
|
||||
}}
|
||||
|
||||
expected_resource_3 = {'type': 'OS::Neutron::Port',
|
||||
'depends_on': ['my_network'],
|
||||
'depends_on': ['my_server', 'my_network'],
|
||||
'properties':
|
||||
{'network': {'get_resource': 'my_network'}
|
||||
}}
|
||||
|
||||
expected_resource_4 = [{'port': {'get_resource': 'my_port'}}]
|
||||
expected_resource_4 = {'type': 'OS::Neutron::Port',
|
||||
'depends_on': ['my_server2', 'my_network'],
|
||||
'properties':
|
||||
{'network': {'get_resource': 'my_network'}
|
||||
}}
|
||||
|
||||
expected_resource_5 = [{'port': {'get_resource': 'my_port2'}}]
|
||||
expected_resource_5 = [{'port': {'get_resource': 'my_port'}}]
|
||||
|
||||
expected_resource_6 = [{'port': {'get_resource': 'my_port2'}}]
|
||||
|
||||
output_dict = translator.toscalib.utils.yamlparser.simple_parse(output)
|
||||
|
||||
@ -130,21 +142,29 @@ class ToscaNetworkTest(TestCase):
|
||||
self.assertEqual(resources.get('my_network'), expected_resource_1)
|
||||
self.assertEqual(resources.get('my_network_subnet'),
|
||||
expected_resource_2)
|
||||
self.assertEqual(resources.get('my_port'), expected_resource_3)
|
||||
self.assertEqual(resources.get('my_port2'), expected_resource_3)
|
||||
|
||||
diff = CompareUtils.diff_dicts(resources.get('my_port'),
|
||||
expected_resource_3)
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4, separators=(', ', ': ')))
|
||||
|
||||
diff = CompareUtils.diff_dicts(resources.get('my_port2'),
|
||||
expected_resource_4)
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4, separators=(', ', ': ')))
|
||||
|
||||
self.assertIn('properties', resources.get('my_server'))
|
||||
self.assertIn('networks', resources.get('my_server').get('properties'))
|
||||
translated_resource = resources.get('my_server').\
|
||||
get('properties').get('networks')
|
||||
self.assertEqual(translated_resource, expected_resource_4)
|
||||
self.assertEqual(translated_resource, expected_resource_5)
|
||||
|
||||
self.assertIn('properties', resources.get('my_server2'))
|
||||
self.assertIn('networks', resources.get('my_server2').
|
||||
get('properties'))
|
||||
translated_resource = resources.get('my_server2').\
|
||||
get('properties').get('networks')
|
||||
self.assertEqual(translated_resource, expected_resource_5)
|
||||
self.assertEqual(translated_resource, expected_resource_6)
|
||||
|
||||
def test_translate_server_existing_network(self):
|
||||
'''TOSCA template with 1 server attached to existing network.'''
|
||||
@ -210,7 +230,7 @@ class ToscaNetworkTest(TestCase):
|
||||
}
|
||||
|
||||
expected_resource_port = {'type': 'OS::Neutron::Port',
|
||||
'depends_on': [net_name],
|
||||
'depends_on': ['my_server', net_name],
|
||||
'properties':
|
||||
{'network': {'get_resource': net_name}}}
|
||||
|
||||
@ -221,7 +241,12 @@ class ToscaNetworkTest(TestCase):
|
||||
self.assertEqual(resources.get(net_name), expected_resource_net)
|
||||
self.assertEqual(resources.get(subnet_name),
|
||||
expected_resource_subnet)
|
||||
self.assertEqual(resources.get(port_name), expected_resource_port)
|
||||
|
||||
diff = CompareUtils.diff_dicts(resources.get(port_name),
|
||||
expected_resource_port)
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4,
|
||||
separators=(', ', ': ')))
|
||||
|
||||
self.assertIn('properties', resources.get('my_server'))
|
||||
self.assertIn('networks', resources.get('my_server').get('properties'))
|
||||
|
@ -44,3 +44,14 @@ class ToscaHotTranslationTest(TestCase):
|
||||
{})
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4, separators=(', ', ': ')))
|
||||
|
||||
def test_hot_translate_host_assignment(self):
|
||||
tosca_file = \
|
||||
'../toscalib/tests/data/test_host_assignment.yaml'
|
||||
hot_file = '../toscalib/tests/data/hot_output/' \
|
||||
'hot_host_assignment.yaml'
|
||||
diff = TranslationUtils.compare_tosca_translation_with_hot(tosca_file,
|
||||
hot_file,
|
||||
{})
|
||||
self.assertEqual({}, diff, '<difference> : ' +
|
||||
json.dumps(diff, indent=4, separators=(', ', ': ')))
|
||||
|
@ -0,0 +1,120 @@
|
||||
heat_template_version: 2013-05-23
|
||||
|
||||
description: >
|
||||
A template to test host assignment for translated hot resources.
|
||||
It makes sure if a resource depends on multiple hosts only the
|
||||
one with the "HostedOn" relationship is picked as the host. In
|
||||
this template, the translated resource 'app_collectd_create_deploy'
|
||||
would depend on 'logstash_server' and 'app_server'. But it would
|
||||
have "HostedOn" relationship with 'app_server', and that server
|
||||
would be its host.
|
||||
|
||||
parameters: {}
|
||||
resources:
|
||||
app_server:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: m1.medium
|
||||
image: ubuntu-software-config-os-init
|
||||
key_name: userkey
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
|
||||
logstash_server:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: m1.medium
|
||||
image: ubuntu-software-config-os-init
|
||||
key_name: userkey
|
||||
user_data_format: SOFTWARE_CONFIG
|
||||
|
||||
app_collectd_create_config:
|
||||
type: OS::Heat::SoftwareConfig
|
||||
properties:
|
||||
config:
|
||||
get_file: collectd/create.sh
|
||||
group: script
|
||||
|
||||
app_collectd_create_deploy:
|
||||
type: OS::Heat::SoftwareDeployment
|
||||
properties:
|
||||
config:
|
||||
get_resource: app_collectd_create_config
|
||||
server:
|
||||
get_resource: app_server
|
||||
depends_on:
|
||||
- logstash_start_deploy
|
||||
|
||||
app_collectd_configure_config:
|
||||
type: OS::Heat::SoftwareConfig
|
||||
properties:
|
||||
config:
|
||||
get_file: collectd/config.py
|
||||
group: script
|
||||
|
||||
app_collectd_configure_deploy:
|
||||
type: OS::Heat::SoftwareDeployment
|
||||
properties:
|
||||
config:
|
||||
get_resource: app_collectd_configure_config
|
||||
input_values:
|
||||
logstash_ip:
|
||||
get_attr:
|
||||
- logstash_server
|
||||
- networks
|
||||
- private
|
||||
- 0
|
||||
server:
|
||||
get_resource: app_server
|
||||
depends_on:
|
||||
- app_collectd_create_deploy
|
||||
|
||||
app_collectd_start_config:
|
||||
type: OS::Heat::SoftwareConfig
|
||||
properties:
|
||||
config:
|
||||
get_file: collectd/start.sh
|
||||
group: script
|
||||
|
||||
app_collectd_start_deploy:
|
||||
type: OS::Heat::SoftwareDeployment
|
||||
properties:
|
||||
config:
|
||||
get_resource: app_collectd_start_config
|
||||
server:
|
||||
get_resource: app_server
|
||||
depends_on:
|
||||
- app_collectd_configure_deploy
|
||||
|
||||
logstash_create_config:
|
||||
type: OS::Heat::SoftwareConfig
|
||||
properties:
|
||||
config:
|
||||
get_file: logstash/create.sh
|
||||
group: script
|
||||
|
||||
logstash_create_deploy:
|
||||
type: OS::Heat::SoftwareDeployment
|
||||
properties:
|
||||
config:
|
||||
get_resource: logstash_create_config
|
||||
server:
|
||||
get_resource: logstash_server
|
||||
|
||||
logstash_start_config:
|
||||
type: OS::Heat::SoftwareConfig
|
||||
properties:
|
||||
config:
|
||||
get_file: logstash/start.sh
|
||||
group: script
|
||||
|
||||
logstash_start_deploy:
|
||||
type: OS::Heat::SoftwareDeployment
|
||||
properties:
|
||||
config:
|
||||
get_resource: logstash_start_config
|
||||
server:
|
||||
get_resource: logstash_server
|
||||
depends_on:
|
||||
- logstash_create_deploy
|
||||
|
||||
outputs: {}
|
80
translator/toscalib/tests/data/test_host_assignment.yaml
Normal file
80
translator/toscalib/tests/data/test_host_assignment.yaml
Normal file
@ -0,0 +1,80 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_0_0
|
||||
|
||||
description: >
|
||||
A template to test host assignment for translated hot resources.
|
||||
It makes sure if a resource depends on multiple hosts only the
|
||||
one with the "HostedOn" relationship is picked as the host. In
|
||||
this template, the translated resource 'app_collectd_create_deploy'
|
||||
would depend on 'logstash_server' and 'app_server'. But it would
|
||||
have "HostedOn" relationship with 'app_server', and that server
|
||||
would be its host.
|
||||
|
||||
imports:
|
||||
- custom_types/logstash.yaml
|
||||
- custom_types/collectd.yaml
|
||||
- custom_types/rsyslog.yaml
|
||||
- custom_types/elasticsearch.yaml
|
||||
|
||||
dsl_definitions:
|
||||
host_capabilities: &host_capabilities
|
||||
# compute properties (flavor)
|
||||
disk_size: 10 GB
|
||||
num_cpus: 1
|
||||
mem_size: 4096 MB
|
||||
os_capabilities: &os_capabilities
|
||||
architecture: x86_64
|
||||
type: Linux
|
||||
distribution: Ubuntu
|
||||
version: 14.04
|
||||
|
||||
topology_template:
|
||||
node_templates:
|
||||
app_collectd:
|
||||
type: tosca.nodes.SoftwareComponent.Collectd
|
||||
requirements:
|
||||
- host:
|
||||
node: app_server
|
||||
- log_endpoint:
|
||||
node: logstash
|
||||
capability: log_endpoint
|
||||
relationship:
|
||||
type: tosca.relationships.ConnectsTo
|
||||
interfaces:
|
||||
Configure:
|
||||
pre_configure_target:
|
||||
implementation: logstash/configure_collectd.py
|
||||
interfaces:
|
||||
tosca.interfaces.node.lifecycle.Standard:
|
||||
create: collectd/create.sh
|
||||
configure:
|
||||
implementation: collectd/config.py
|
||||
inputs:
|
||||
logstash_ip: { get_attribute: [logstash_server, private_address] }
|
||||
start: collectd/start.sh
|
||||
|
||||
logstash:
|
||||
type: tosca.nodes.SoftwareComponent.Logstash
|
||||
requirements:
|
||||
- host:
|
||||
node: logstash_server
|
||||
interfaces:
|
||||
tosca.interfaces.node.lifecycle.Standard:
|
||||
create: logstash/create.sh
|
||||
start: logstash/start.sh
|
||||
|
||||
app_server:
|
||||
type: tosca.nodes.Compute
|
||||
capabilities:
|
||||
os:
|
||||
properties: *os_capabilities
|
||||
host:
|
||||
properties: *host_capabilities
|
||||
|
||||
logstash_server:
|
||||
type: tosca.nodes.Compute
|
||||
capabilities:
|
||||
os:
|
||||
properties: *os_capabilities
|
||||
host:
|
||||
properties: *host_capabilities
|
||||
|
Loading…
x
Reference in New Issue
Block a user