summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Hardy <shardy@redhat.com>2014-01-03 16:56:58 +0000
committerSteven Hardy <shardy@redhat.com>2014-01-07 13:53:16 +0000
commit4ca7941a6526fafc9a68e19fe327da2057b3a1be (patch)
tree8f7fc8b9674934b7d0d8520972dc5bcde73c40db
parent2beab0228ab5476b2a13992f7f3acbeb09e01719 (diff)
downloadheat-4ca7941a6526fafc9a68e19fe327da2057b3a1be.tar.gz
Make LoadBalancer nested stack template configurable
Reviving work originally posted by Angus Salkeld under https://review.openstack.org/#/c/21405/ This is to enable the various distros to easily override the hard-coded default nested template (which currently only supports Fedora 17) with a template approporate to their distro, and enables deployers to specify their own template (although the latter use-case will probably be catered for via a provider template implementation long-term). Conflicts: heat/engine/resources/loadbalancer.py Partial-Bug: #1234375 Co-Authored-By: Angus Salkeld <angus@salkeld.id.au> (cherry picked from commit 746a0ed4ad2273d0e67b896efbb6d7a69f9f4c77) Change-Id: I0a4eccb23b2eebbf31b7aabf0fe85ab31f0ca971
-rw-r--r--etc/heat/heat.conf.sample9
-rw-r--r--heat/engine/resources/loadbalancer.py39
-rw-r--r--heat/tests/test_loadbalancer.py15
3 files changed, 54 insertions, 9 deletions
diff --git a/etc/heat/heat.conf.sample b/etc/heat/heat.conf.sample
index 1444f9ba2..ad6fb7cab 100644
--- a/etc/heat/heat.conf.sample
+++ b/etc/heat/heat.conf.sample
@@ -121,6 +121,15 @@
#
+# Options defined in heat.engine.resources.loadbalancer
+#
+
+# Custom template for the built-in loadbalancer nested stack
+# (string value)
+#loadbalancer_template=<None>
+
+
+#
# Options defined in heat.openstack.common.db.sqlalchemy.session
#
diff --git a/heat/engine/resources/loadbalancer.py b/heat/engine/resources/loadbalancer.py
index 700158e06..7350d6cac 100644
--- a/heat/engine/resources/loadbalancer.py
+++ b/heat/engine/resources/loadbalancer.py
@@ -12,7 +12,11 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+import os
+from oslo.config import cfg
+
+from heat.common import exception
from heat.common import template_format
from heat.engine import stack_resource
from heat.engine.resources import nova_utils
@@ -21,7 +25,7 @@ from heat.openstack.common import log as logging
logger = logging.getLogger(__name__)
-lb_template = r'''
+lb_template_default = r'''
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Built in HAProxy server",
@@ -189,11 +193,15 @@ lb_template = r'''
'''
-#
-# TODO(asalkeld) the above inline template _could_ be placed in an external
-# file at the moment this is because we will probably need to implement a
-# LoadBalancer based on keepalived as well (for for ssl support).
-#
+# Allow user to provide alternative nested stack template to the above
+loadbalancer_opts = [
+ cfg.StrOpt('loadbalancer_template',
+ default=None,
+ help='Custom template for the built-in '
+ 'loadbalancer nested stack')]
+cfg.CONF.register_opts(loadbalancer_opts)
+
+
class LoadBalancer(stack_resource.StackResource):
listeners_schema = {
@@ -361,8 +369,18 @@ class LoadBalancer(stack_resource.StackResource):
return '%s%s%s%s\n' % (gl, frontend, backend, '\n'.join(servers))
+ def get_parsed_template(self):
+ if cfg.CONF.loadbalancer_template:
+ with open(cfg.CONF.loadbalancer_template) as templ_fd:
+ logger.info(_('Using custom loadbalancer template %s')
+ % cfg.CONF.loadbalancer_template)
+ contents = templ_fd.read()
+ else:
+ contents = lb_template_default
+ return template_format.parse(contents)
+
def handle_create(self):
- templ = template_format.parse(lb_template)
+ templ = self.get_parsed_template()
if self.properties['Instances']:
md = templ['Resources']['LB_instance']['Metadata']
@@ -388,7 +406,7 @@ class LoadBalancer(stack_resource.StackResource):
rely on the cfn-hup to reconfigure HAProxy
'''
if 'Instances' in prop_diff:
- templ = template_format.parse(lb_template)
+ templ = self.get_parsed_template()
cfg = self._haproxy_config(templ, prop_diff['Instances'])
md = self.nested()['LB_instance'].metadata
@@ -408,6 +426,11 @@ class LoadBalancer(stack_resource.StackResource):
if res:
return res
+ if cfg.CONF.loadbalancer_template and \
+ not os.access(cfg.CONF.loadbalancer_template, os.R_OK):
+ msg = _('Custom LoadBalancer template can not be found')
+ raise exception.StackValidationFailed(message=msg)
+
health_chk = self.properties['HealthCheck']
if health_chk:
if float(health_chk['Interval']) < float(health_chk['Timeout']):
diff --git a/heat/tests/test_loadbalancer.py b/heat/tests/test_loadbalancer.py
index 843edb27f..aa07bb87f 100644
--- a/heat/tests/test_loadbalancer.py
+++ b/heat/tests/test_loadbalancer.py
@@ -179,8 +179,9 @@ class LoadBalancerTest(HeatTestCase):
self.assertEqual('LoadBalancer', rsrc.FnGetRefId())
- templ = template_format.parse(lb.lb_template)
+ templ = template_format.parse(lb.lb_template_default)
ha_cfg = rsrc._haproxy_config(templ, rsrc.properties['Instances'])
+
self.assertRegexpMatches(ha_cfg, 'bind \*:80')
self.assertRegexpMatches(ha_cfg, 'server server1 1\.2\.3\.4:80 '
'check inter 30s fall 5 rise 3')
@@ -228,3 +229,15 @@ class LoadBalancerTest(HeatTestCase):
msg = '%s: %r not found in %r' % (msg,
expected_regexp.pattern, text)
raise self.failureException(msg)
+
+ def test_loadbalancer_validate_badtemplate(self):
+ cfg.CONF.set_override('loadbalancer_template', '/a/noexist/x.y')
+
+ t = template_format.parse(lb_template)
+ s = utils.parse_stack(t)
+ s.store()
+
+ rsrc = lb.LoadBalancer('LoadBalancer',
+ t['Resources']['LoadBalancer'],
+ s)
+ self.assertRaises(exception.StackValidationFailed, rsrc.validate)