diff options
author | Steven Hardy <shardy@redhat.com> | 2014-01-03 16:56:58 +0000 |
---|---|---|
committer | Steven Hardy <shardy@redhat.com> | 2014-01-07 13:53:16 +0000 |
commit | 4ca7941a6526fafc9a68e19fe327da2057b3a1be (patch) | |
tree | 8f7fc8b9674934b7d0d8520972dc5bcde73c40db | |
parent | 2beab0228ab5476b2a13992f7f3acbeb09e01719 (diff) | |
download | heat-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.sample | 9 | ||||
-rw-r--r-- | heat/engine/resources/loadbalancer.py | 39 | ||||
-rw-r--r-- | heat/tests/test_loadbalancer.py | 15 |
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) |