Merge "Add wait condition for heat templates"

This commit is contained in:
Jenkins 2015-09-23 00:05:04 +00:00 committed by Gerrit Code Review
commit e42969b18a
3 changed files with 104 additions and 8 deletions

View File

@ -227,6 +227,11 @@ NTP_ENABLED = Config(
'instances'
)
HEAT_WAIT_CONDITION_TIMEOUT = Config(
"Heat Wait Condition timeout", "general", "cluster", priority=1,
config_type="int", default_value=3600, is_optional=True,
description="The number of seconds to wait for the instance to boot")
def list_of_common_configs():
return [NTP_ENABLED, NTP_URL]
return [NTP_ENABLED, NTP_URL, HEAT_WAIT_CONDITION_TIMEOUT]

View File

@ -19,6 +19,7 @@ from oslo_log import log as logging
import six
import yaml
from sahara.plugins import provisioning as plugin_provisioning
from sahara.utils import general as g
from sahara.utils.openstack import base as b
from sahara.utils.openstack import heat as h
@ -29,6 +30,7 @@ CONF = cfg.CONF
LOG = logging.getLogger(__name__)
SSH_PORT = 22
INSTANCE_RESOURCE_NAME = "inst"
def _get_inst_name(ng):
@ -89,6 +91,14 @@ def _get_volume_name(ng):
}
def _get_wc_handle_name(inst_name):
return '%s-wc-handle' % inst_name
def _get_wc_waiter_name(inst_name):
return '%s-wc-waiter' % inst_name
class ClusterStack(object):
def __init__(self, cluster):
self.cluster = cluster
@ -204,8 +214,8 @@ class ClusterStack(object):
"resources": self._serialize_instance(ng),
"outputs": {
"instance": {"value": {
"physical_id": {"get_resource": "inst"},
"name": {"get_attr": ["inst", "name"]}
"physical_id": {"get_resource": INSTANCE_RESOURCE_NAME},
"name": {"get_attr": [INSTANCE_RESOURCE_NAME, "name"]}
}}}
})
@ -266,6 +276,15 @@ class ClusterStack(object):
return rules
@staticmethod
def _get_wait_condition_timeout(ng):
configs = ng.cluster.cluster_configs
timeout_cfg = plugin_provisioning.HEAT_WAIT_CONDITION_TIMEOUT
cfg_target = timeout_cfg.applicable_target
cfg_name = timeout_cfg.name
return int(configs.get(cfg_target,
{}).get(cfg_name, timeout_cfg.default_value))
def _serialize_instance(self, ng):
resources = {}
properties = {}
@ -297,7 +316,22 @@ class ClusterStack(object):
properties["key_name"] = self.cluster.user_keypair_id
gen_userdata_func = self.node_groups_extra[ng.id]['gen_userdata_func']
userdata = gen_userdata_func(ng, inst_name)
key_script = gen_userdata_func(ng, inst_name)
wait_condition_script = (
"wc_notify --data-binary '{\"status\": \"SUCCESS\"}'")
userdata = {
"str_replace": {
"template": "\n".join([key_script, wait_condition_script]),
"params": {
"wc_notify": {
"get_attr": [
_get_wc_handle_name(ng.name),
"curl_cli"
]
}
}
}
}
if ng.availability_zone:
properties["availability_zone"] = ng.availability_zone
@ -313,7 +347,7 @@ class ClusterStack(object):
})
resources.update({
"inst": {
INSTANCE_RESOURCE_NAME: {
"type": "OS::Nova::Server",
"properties": properties
}
@ -322,6 +356,20 @@ class ClusterStack(object):
if ng.volumes_per_node > 0 and ng.volumes_size > 0:
resources.update(self._serialize_volume(ng))
resources.update(self._serialize_volume(ng))
resources.update({
_get_wc_handle_name(ng.name): {
"type": "OS::Heat::WaitConditionHandle"
},
_get_wc_waiter_name(ng.name): {
"type": "OS::Heat::WaitCondition",
"depends_on": INSTANCE_RESOURCE_NAME,
"properties": {
"timeout": self._get_wait_condition_timeout(ng),
"handle": {"get_resource": _get_wc_handle_name(ng.name)}
}
}
})
return resources
def _serialize_port(self, port_name, fixed_net_id, security_groups):
@ -363,7 +411,7 @@ class ClusterStack(object):
"type": "OS::Nova::FloatingIPAssociation",
"properties": {
"floating_ip": {"get_resource": "floating_ip"},
"server_id": {"get_resource": "inst"}
"server_id": {"get_resource": INSTANCE_RESOURCE_NAME}
}
}
}
@ -382,7 +430,8 @@ class ClusterStack(object):
"properties": {
"volume_index": "%index%",
"instance_index": {"get_param": "instance_index"},
"instance": {"get_resource": "inst"}}
"instance": {"get_resource":
INSTANCE_RESOURCE_NAME}}
}
}
}

View File

@ -21,7 +21,7 @@ from sahara.tests.unit import base
from sahara.tests.unit import testutils as tu
class TestClusterTemplate(base.SaharaWithDbTestCase):
class BaseTestClusterTemplate(base.SaharaWithDbTestCase):
"""Checks valid structure of Resources section in generated Heat templates.
1. It checks templates generation with different OpenStack
@ -52,6 +52,8 @@ class TestClusterTemplate(base.SaharaWithDbTestCase):
default_image_id='1', image_id=None,
anti_affinity=anti_affinity)
class TestClusterTemplate(BaseTestClusterTemplate):
def _make_heat_template(self, cluster, ng1, ng2):
heat_template = h.ClusterStack(cluster)
heat_template.add_node_group_extra(ng1['id'], 1,
@ -167,6 +169,46 @@ class TestClusterTemplate(base.SaharaWithDbTestCase):
self.assertEqual(expected, actual)
class TestClusterTemplateWaitCondition(BaseTestClusterTemplate):
def _make_heat_template(self, cluster, ng1, ng2):
heat_template = h.ClusterStack(cluster)
heat_template.add_node_group_extra(ng1.id, 1,
get_ud_generator('line1\nline2'))
heat_template.add_node_group_extra(ng2.id, 1,
get_ud_generator('line2\nline3'))
return heat_template
def setUp(self):
super(TestClusterTemplateWaitCondition, self).setUp()
_ng1, _ng2 = self._make_node_groups("floating")
_cluster = self._make_cluster("private_net", _ng1, _ng2)
_ng1["cluster"] = _ng2["cluster"] = _cluster
self.ng1 = mock.Mock()
self.ng1.configure_mock(**_ng1)
self.ng2 = mock.Mock()
self.ng2.configure_mock(**_ng2)
self.cluster = mock.Mock()
self.cluster.configure_mock(**_cluster)
self.template = self._make_heat_template(self.cluster,
self.ng1, self.ng2)
def test_use_wait_condition(self):
instance = self.template._serialize_instance(self.ng1)
expected_wc_handle = {
"type": "OS::Heat::WaitConditionHandle"
}
expected_wc_waiter = {
"type": "OS::Heat::WaitCondition",
"depends_on": "inst",
"properties": {
"timeout": 3600,
"handle": {"get_resource": "master-wc-handle"}
}
}
self.assertEqual(expected_wc_handle, instance["master-wc-handle"])
self.assertEqual(expected_wc_waiter, instance["master-wc-waiter"])
def get_ud_generator(s):
def generator(*args, **kwargs):
return s