diff options
author | Lon Hohberger <lhh@redhat.com> | 2014-02-18 13:44:56 -0500 |
---|---|---|
committer | Lon Hohberger <lhh@redhat.com> | 2014-02-19 09:43:44 -0500 |
commit | cceda95a35f18f5f7b52daaf0662a4cd3768b3ac (patch) | |
tree | f2e209caa6406394a61868e5005d480bac97c9ea | |
parent | 7c2c54f04d378acc79e143f906c2545ae9ec2514 (diff) | |
download | heat-cceda95a35f18f5f7b52daaf0662a4cd3768b3ac.tar.gz |
Add systemd notification support to heat
This mirrors work done in other OpenStack projects
to add systemd notification support to signal that
a given process is ready to accept requests.
The heat-api, heat-api-cfn, heat-engine, and
heat-api-cloudwatch processes are all covered by
a new, single, 'onready' configuration file option.
Additionally, the sample configuration file has been
updated to match.
Implements: blueprint systemd-integration
Change-Id: I90d2b915e2568a65ed9ed78923c9982e19f9c948
Signed-off-by: Lon Hohberger <lhh@redhat.com>
-rwxr-xr-x | bin/heat-api | 2 | ||||
-rwxr-xr-x | bin/heat-api-cfn | 2 | ||||
-rwxr-xr-x | bin/heat-api-cloudwatch | 2 | ||||
-rwxr-xr-x | bin/heat-engine | 3 | ||||
-rw-r--r-- | etc/heat/heat.conf.sample | 8 | ||||
-rw-r--r-- | heat/common/config.py | 9 | ||||
-rw-r--r-- | heat/common/notify.py | 38 | ||||
-rw-r--r-- | heat/common/systemd.py | 44 |
8 files changed, 107 insertions, 1 deletions
diff --git a/bin/heat-api b/bin/heat-api index d9f7495e2..44e0cf486 100755 --- a/bin/heat-api +++ b/bin/heat-api @@ -40,6 +40,7 @@ from oslo.config import cfg from heat.common import config from heat.common import wsgi +from heat.common import notify from heat.openstack.common import log as logging @@ -62,6 +63,7 @@ if __name__ == '__main__': LOG.info('Starting Heat ReST API on %s:%s' % (host, port)) server = wsgi.Server() server.start(app, cfg.CONF.heat_api, default_port=port) + notify.startup_notify(cfg.CONF.onready) server.wait() except RuntimeError as e: sys.exit("ERROR: %s" % e) diff --git a/bin/heat-api-cfn b/bin/heat-api-cfn index 54bdf637f..07315f903 100755 --- a/bin/heat-api-cfn +++ b/bin/heat-api-cfn @@ -42,6 +42,7 @@ from oslo.config import cfg from heat.common import config from heat.common import wsgi +from heat.common import notify from heat.openstack.common import log as logging @@ -64,6 +65,7 @@ if __name__ == '__main__': LOG.info('Starting Heat API on %s:%s' % (host, port)) server = wsgi.Server() server.start(app, cfg.CONF.heat_api_cfn, default_port=port) + notify.startup_notify(cfg.CONF.onready) server.wait() except RuntimeError as e: sys.exit("ERROR: %s" % e) diff --git a/bin/heat-api-cloudwatch b/bin/heat-api-cloudwatch index 79feb70a9..2f3230b79 100755 --- a/bin/heat-api-cloudwatch +++ b/bin/heat-api-cloudwatch @@ -42,6 +42,7 @@ from oslo.config import cfg from heat.common import config from heat.common import wsgi +from heat.common import notify from heat.openstack.common import log as logging @@ -64,6 +65,7 @@ if __name__ == '__main__': LOG.info('Starting Heat CloudWatch API on %s:%s' % (host, port)) server = wsgi.Server() server.start(app, cfg.CONF.heat_api_cloudwatch, default_port=port) + notify.startup_notify(cfg.CONF.onready) server.wait() except RuntimeError as e: sys.exit("ERROR: %s" % e) diff --git a/bin/heat-engine b/bin/heat-engine index 185d48ee1..426d79ada 100755 --- a/bin/heat-engine +++ b/bin/heat-engine @@ -41,6 +41,8 @@ gettextutils.install('heat', lazy=True) from oslo.config import cfg +from heat.common import notify + from heat.openstack.common import log as logging from heat.openstack.common import service @@ -64,4 +66,5 @@ if __name__ == '__main__': srv = engine.EngineService(cfg.CONF.host, rpc_api.ENGINE_TOPIC) launcher = service.launch(srv) + notify.startup_notify(cfg.CONF.onready) launcher.wait() diff --git a/etc/heat/heat.conf.sample b/etc/heat/heat.conf.sample index 896925ba8..7f1663c24 100644 --- a/etc/heat/heat.conf.sample +++ b/etc/heat/heat.conf.sample @@ -58,6 +58,14 @@ # stack locking. (integer value) #engine_life_check_timeout=2 +# onready allows you to send a notification when the heat +# processes are ready to serve. This is either a module with +# the notify() method or a shell command. To enable +# notifications with systemd, one may use the 'systemd-notify +# --ready' shell command or the 'heat.common.systemd' +# notification module. (string value) +#onready=<None> + # Name of the engine node. This can be an opaque identifier. # It is not necessarily a hostname, FQDN, or IP address. # (string value) diff --git a/heat/common/config.py b/heat/common/config.py index 1cfb50fdd..31d348e50 100644 --- a/heat/common/config.py +++ b/heat/common/config.py @@ -118,7 +118,14 @@ engine_opts = [ cfg.IntOpt('engine_life_check_timeout', default=2, help=_('RPC timeout for the engine liveness check that is used' - ' for stack locking.'))] + ' for stack locking.')), + cfg.StrOpt('onready', + help=_('onready allows you to send a notification when the' + ' heat processes are ready to serve. This is either a' + ' module with the notify() method or a shell command. ' + ' To enable notifications with systemd, one may use' + ' the \'systemd-notify --ready\' shell command or' + ' the \'heat.common.systemd\' notification module.'))] rpc_opts = [ cfg.StrOpt('host', diff --git a/heat/common/notify.py b/heat/common/notify.py new file mode 100644 index 000000000..d168482c4 --- /dev/null +++ b/heat/common/notify.py @@ -0,0 +1,38 @@ +# Copyright 2014 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Startup notification using a shell script or systemd NOTIFY_SOCKET +style notification +""" + +from heat.openstack.common import log as logging +from heat.openstack.common import importutils +from heat.openstack.common import processutils + +logger = logging.getLogger(__name__) + + +def startup_notify(notify_param): + if not notify_param or notify_param == "": + return + try: + notifier = importutils.import_module(notify_param) + except ImportError: + try: + processutils.execute(notify_param, shell=True) + except Exception as e: + logger.error(_('Failed to execute onready command: %s') % str(e)) + else: + notifier.notify() diff --git a/heat/common/systemd.py b/heat/common/systemd.py new file mode 100644 index 000000000..f094dd777 --- /dev/null +++ b/heat/common/systemd.py @@ -0,0 +1,44 @@ +# Copyright 2012 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Helper module for systemd start-up completion notification. +Used for "onready" configuration parameter in heat.conf +""" + +import os +import socket + +from heat.openstack.common import log as logging + +logger = logging.getLogger(__name__) + + +def _sd_notify(msg): + sysd = os.getenv('NOTIFY_SOCKET') + if sysd: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + if sysd.startswith('@'): + # abstract namespace socket + sysd = '\0%s' % sysd[1:] + sock.connect(sysd) + sock.sendall(msg) + sock.close() + else: + logger.warning(_('Unable to notify systemd of startup completion:' + ' NOTIFY_SOCKET not set')) + + +def notify(): + _sd_notify('READY=1') |