heat-all: all-in-one heat launcher

This patch implements a new heat-all command that can be used
to launch a single process version of the configured heat services.
The end user can control which services are launched by setting
'enabled_services' in the heat config file:

[heat_all]
  enabled_services = api,engine

One use case for this launcher would be to launch a single process heat
using rpc_backend = fake, connection=sqlite://heat.db, to have access
to a minimal all in one Heat API/Engine for TripleO undercloud
deployments via Heat templates.

Change-Id: Ic35bdc455fe1397ac575522af0c8fca96dd95676
This commit is contained in:
Dan Prince 2016-07-26 13:55:20 -04:00
parent 0a2e21b40f
commit 1486289a75
6 changed files with 174 additions and 54 deletions

91
heat/cmd/all.py Normal file
View File

@ -0,0 +1,91 @@
#!/usr/bin/env python
#
# 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.
"""Heat All Server.
An OpenStack Heat server that can run all services.
"""
import eventlet
eventlet.monkey_patch(os=False)
import six
import sys
from heat.cmd import api
from heat.cmd import api_cfn
from heat.cmd import api_cloudwatch
from heat.cmd import engine
from heat.common import config
from heat.common import messaging
from heat import version
from oslo_config import cfg
import oslo_i18n as i18n
from oslo_log import log as logging
from oslo_service import systemd
i18n.enable_lazy()
LOG = logging.getLogger('heat.all')
API_LAUNCH_OPTS = {'setup_logging': False}
LAUNCH_SERVICES = {
'engine': [engine.launch_engine, {'setup_logging': False}],
'api': [api.launch_api, API_LAUNCH_OPTS],
'api_cfn': [api_cfn.launch_cfn_api, API_LAUNCH_OPTS],
'api_cloudwatch': [api_cloudwatch.launch_cloudwatch_api, API_LAUNCH_OPTS],
}
services_opt = cfg.ListOpt(
'enabled_services',
default=['engine', 'api', 'api_cfn'],
help='Specifies the heat services that are enabled when running heat-all. '
'Valid options are all or any combination of '
'api, engine, api_cfn, or api_cloudwatch.'
)
cfg.CONF.register_opt(services_opt, group='heat_all')
def _start_service_threads(services):
threads = []
for option in services:
launch_func = LAUNCH_SERVICES[option][0]
kwargs = LAUNCH_SERVICES[option][1]
threads.append(eventlet.spawn(launch_func, **kwargs))
return threads
def launch_all(setup_logging=True):
if setup_logging:
logging.register_options(cfg.CONF)
cfg.CONF(project='heat', prog='heat-all',
version=version.version_info.version_string())
if setup_logging:
logging.setup(cfg.CONF, 'heat-all')
config.set_config_defaults()
messaging.setup()
return _start_service_threads(set(cfg.CONF.heat_all.enabled_services))
def main():
try:
threads = launch_all()
services = [thread.wait() for thread in threads]
systemd.notify_once()
[service.wait() for service in services]
except RuntimeError as e:
msg = six.text_type(e)
sys.exit("ERROR: %s" % msg)

View File

@ -41,25 +41,32 @@ i18n.enable_lazy()
LOG = logging.getLogger('heat.api') LOG = logging.getLogger('heat.api')
def launch_api(setup_logging=True):
if setup_logging:
logging.register_options(cfg.CONF)
cfg.CONF(project='heat', prog='heat-api',
version=version.version_info.version_string())
if setup_logging:
logging.setup(cfg.CONF, 'heat-api')
config.set_config_defaults()
messaging.setup()
app = config.load_paste_app()
port = cfg.CONF.heat_api.bind_port
host = cfg.CONF.heat_api.bind_host
LOG.info(_LI('Starting Heat REST API on %(host)s:%(port)s'),
{'host': host, 'port': port})
profiler.setup('heat-api', host)
gmr.TextGuruMeditation.setup_autorun(version)
server = wsgi.Server('heat-api', cfg.CONF.heat_api)
server.start(app, default_port=port)
return server
def main(): def main():
try: try:
logging.register_options(cfg.CONF) server = launch_api()
cfg.CONF(project='heat', prog='heat-api',
version=version.version_info.version_string())
logging.setup(cfg.CONF, 'heat-api')
config.set_config_defaults()
messaging.setup()
app = config.load_paste_app()
port = cfg.CONF.heat_api.bind_port
host = cfg.CONF.heat_api.bind_host
LOG.info(_LI('Starting Heat REST API on %(host)s:%(port)s'),
{'host': host, 'port': port})
profiler.setup('heat-api', host)
gmr.TextGuruMeditation.setup_autorun(version)
server = wsgi.Server('heat-api', cfg.CONF.heat_api)
server.start(app, default_port=port)
systemd.notify_once() systemd.notify_once()
server.wait() server.wait()
except RuntimeError as e: except RuntimeError as e:

View File

@ -43,27 +43,34 @@ i18n.enable_lazy()
LOG = logging.getLogger('heat.api.cfn') LOG = logging.getLogger('heat.api.cfn')
def main(): def launch_cfn_api(setup_logging=True):
try: if setup_logging:
logging.register_options(cfg.CONF) logging.register_options(cfg.CONF)
cfg.CONF(project='heat', cfg.CONF(project='heat',
prog='heat-api-cfn', prog='heat-api-cfn',
version=version.version_info.version_string()) version=version.version_info.version_string())
if setup_logging:
logging.setup(cfg.CONF, 'heat-api-cfn') logging.setup(cfg.CONF, 'heat-api-cfn')
logging.set_defaults() logging.set_defaults()
config.set_config_defaults() config.set_config_defaults()
messaging.setup() messaging.setup()
app = config.load_paste_app() app = config.load_paste_app()
port = cfg.CONF.heat_api_cfn.bind_port port = cfg.CONF.heat_api_cfn.bind_port
host = cfg.CONF.heat_api_cfn.bind_host host = cfg.CONF.heat_api_cfn.bind_host
LOG.info(_LI('Starting Heat API on %(host)s:%(port)s'), LOG.info(_LI('Starting Heat API on %(host)s:%(port)s'),
{'host': host, 'port': port}) {'host': host, 'port': port})
profiler.setup('heat-api-cfn', host) profiler.setup('heat-api-cfn', host)
gmr.TextGuruMeditation.setup_autorun(version) gmr.TextGuruMeditation.setup_autorun(version)
server = wsgi.Server('heat-api-cfn', cfg.CONF.heat_api_cfn) server = wsgi.Server('heat-api-cfn', cfg.CONF.heat_api_cfn)
server.start(app, default_port=port) server.start(app, default_port=port)
return server
def main():
try:
server = launch_cfn_api()
systemd.notify_once() systemd.notify_once()
server.wait() server.wait()
except RuntimeError as e: except RuntimeError as e:

View File

@ -43,28 +43,35 @@ i18n.enable_lazy()
LOG = logging.getLogger('heat.api.cloudwatch') LOG = logging.getLogger('heat.api.cloudwatch')
def main(): def launch_cloudwatch_api(setup_logging=True):
try: if setup_logging:
logging.register_options(cfg.CONF) logging.register_options(cfg.CONF)
cfg.CONF(project='heat', cfg.CONF(project='heat',
prog='heat-api-cloudwatch', prog='heat-api-cloudwatch',
version=version.version_info.version_string()) version=version.version_info.version_string())
if setup_logging:
logging.setup(cfg.CONF, 'heat-api-cloudwatch') logging.setup(cfg.CONF, 'heat-api-cloudwatch')
logging.set_defaults() logging.set_defaults()
config.set_config_defaults() config.set_config_defaults()
messaging.setup() messaging.setup()
app = config.load_paste_app() app = config.load_paste_app()
port = cfg.CONF.heat_api_cloudwatch.bind_port port = cfg.CONF.heat_api_cloudwatch.bind_port
host = cfg.CONF.heat_api_cloudwatch.bind_host host = cfg.CONF.heat_api_cloudwatch.bind_host
LOG.info(_LI('Starting Heat CloudWatch API on %(host)s:%(port)s'), LOG.info(_LI('Starting Heat CloudWatch API on %(host)s:%(port)s'),
{'host': host, 'port': port}) {'host': host, 'port': port})
profiler.setup('heat-api-cloudwatch', host) profiler.setup('heat-api-cloudwatch', host)
gmr.TextGuruMeditation.setup_autorun(version) gmr.TextGuruMeditation.setup_autorun(version)
server = wsgi.Server('heat-api-cloudwatch', server = wsgi.Server('heat-api-cloudwatch',
cfg.CONF.heat_api_cloudwatch) cfg.CONF.heat_api_cloudwatch)
server.start(app, default_port=port) server.start(app, default_port=port)
return server
def main():
try:
server = launch_cloudwatch_api()
systemd.notify_once() systemd.notify_once()
server.wait() server.wait()
except RuntimeError as e: except RuntimeError as e:

View File

@ -44,12 +44,14 @@ i18n.enable_lazy()
LOG = logging.getLogger('heat.engine') LOG = logging.getLogger('heat.engine')
def main(): def launch_engine(setup_logging=True):
logging.register_options(cfg.CONF) if setup_logging:
logging.register_options(cfg.CONF)
cfg.CONF(project='heat', prog='heat-engine', cfg.CONF(project='heat', prog='heat-engine',
version=version.version_info.version_string()) version=version.version_info.version_string())
logging.setup(cfg.CONF, 'heat-engine') if setup_logging:
logging.set_defaults() logging.setup(cfg.CONF, 'heat-engine')
logging.set_defaults()
messaging.setup() messaging.setup()
config.startup_sanity_check() config.startup_sanity_check()
@ -76,4 +78,9 @@ def main():
# We create the periodic tasks here, which mean they are created # We create the periodic tasks here, which mean they are created
# only in the parent process when num_engine_workers>1 is specified # only in the parent process when num_engine_workers>1 is specified
srv.create_periodic_tasks() srv.create_periodic_tasks()
return launcher
def main():
launcher = launch_engine()
launcher.wait() launcher.wait()

View File

@ -30,6 +30,7 @@ scripts =
[entry_points] [entry_points]
console_scripts = console_scripts =
heat-all = heat.cmd.all:main
heat-api = heat.cmd.api:main heat-api = heat.cmd.api:main
heat-api-cfn = heat.cmd.api_cfn:main heat-api-cfn = heat.cmd.api_cfn:main
heat-api-cloudwatch = heat.cmd.api_cloudwatch:main heat-api-cloudwatch = heat.cmd.api_cloudwatch:main