From 6cdee8590528a95e9e3c7f2fc156cc9ebb8b39b2 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 17 Aug 2011 16:25:53 -0700 Subject: Make all services use the same launching strategy --- bin/nova-api | 44 +++++++++++++++++--------------------------- nova/service.py | 47 ++++++++++++++++++++++++++++------------------- nova/utils.py | 41 +++-------------------------------------- nova/wsgi.py | 3 --- 4 files changed, 48 insertions(+), 87 deletions(-) diff --git a/bin/nova-api b/bin/nova-api index fe8e83366..d2086dc92 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -19,12 +19,15 @@ """Starter script for Nova API. -Starts both the EC2 and OpenStack APIs in separate processes. +Starts both the EC2 and OpenStack APIs in separate greenthreads. """ +import eventlet +eventlet.monkey_patch() + +import gettext import os -import signal import sys @@ -33,32 +36,19 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) -import nova.service -import nova.utils +gettext.install('nova', unicode=1) from nova import flags - - -FLAGS = flags.FLAGS - - -def main(): - """Launch EC2 and OSAPI services.""" - nova.utils.Bootstrapper.bootstrap_binary(sys.argv) - - launcher = nova.service.Launcher() - - for api in FLAGS.enabled_apis: - service = nova.service.WSGIService(api) - launcher.launch_service(service) - - signal.signal(signal.SIGTERM, lambda *_: launcher.stop()) - - try: - launcher.wait() - except KeyboardInterrupt: - launcher.stop() - +from nova import log as logging +from nova import service +from nova import utils if __name__ == '__main__': - sys.exit(main()) + utils.default_flagfile() + flags.FLAGS(sys.argv) + logging.setup() + services = [] + for api in flags.FLAGS.enabled_apis: + services.append(service.WSGIService(api)) + service.serve(*services) + service.wait() diff --git a/nova/service.py b/nova/service.py index 6e9eddc5a..e0735d26f 100644 --- a/nova/service.py +++ b/nova/service.py @@ -20,13 +20,12 @@ """Generic Node baseclass for all workers that run on hosts.""" import inspect -import multiprocessing import os +import signal +import eventlet import greenlet -from eventlet import greenthread - from nova import context from nova import db from nova import exception @@ -77,10 +76,7 @@ class Launcher(object): """ service.start() - try: - service.wait() - except KeyboardInterrupt: - service.stop() + service.wait() def launch_service(self, service): """Load and start the given service. @@ -89,10 +85,8 @@ class Launcher(object): :returns: None """ - process = multiprocessing.Process(target=self.run_service, - args=(service,)) - process.start() - self._services.append(process) + gt = eventlet.spawn(self.run_service, service) + self._services.append(gt) def stop(self): """Stop all services which are currently running. @@ -101,8 +95,7 @@ class Launcher(object): """ for service in self._services: - if service.is_alive(): - service.terminate() + service.kill() def wait(self): """Waits until all services have been stopped, and then returns. @@ -111,7 +104,10 @@ class Launcher(object): """ for service in self._services: - service.join() + try: + service.wait() + except greenlet.GreenletExit: + pass class Service(object): @@ -121,6 +117,7 @@ class Service(object): periodic_interval=None, *args, **kwargs): self.host = host self.binary = binary + self.name = binary self.topic = topic self.manager_class_name = manager manager_class = utils.import_class(self.manager_class_name) @@ -173,7 +170,7 @@ class Service(object): finally: consumer_set.close() - self.consumer_set_thread = greenthread.spawn(_wait) + self.consumer_set_thread = eventlet.spawn(_wait) if self.report_interval: pulse = utils.LoopingCall(self.report_state) @@ -339,7 +336,17 @@ class WSGIService(object): self.server.wait() +# NOTE(vish): the global launcher is to maintain the existing +# functionality of calling service.serve + +# service.wait +_launcher = None + + def serve(*services): + global _launcher + if not _launcher: + _launcher = Launcher() + signal.signal(signal.SIGTERM, lambda *args: _launcher.stop()) try: if not services: services = [Service.create()] @@ -354,7 +361,7 @@ def serve(*services): flags.DEFINE_flag(flags.HelpXMLFlag()) FLAGS.ParseNewFlags() - name = '_'.join(x.binary for x in services) + name = '_'.join(x.name for x in services) logging.debug(_('Serving %s'), name) logging.debug(_('Full set of FLAGS:')) for flag in FLAGS: @@ -362,9 +369,11 @@ def serve(*services): logging.debug('%(flag)s : %(flag_get)s' % locals()) for x in services: - x.start() + _launcher.launch_service(x) def wait(): - while True: - greenthread.sleep(5) + try: + _launcher.wait() + except KeyboardInterrupt: + _launcher.stop() diff --git a/nova/utils.py b/nova/utils.py index 7276b6bd5..54126f644 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -260,8 +260,9 @@ def default_flagfile(filename='nova.conf', args=None): filename = "./nova.conf" if not os.path.exists(filename): filename = '/etc/nova/nova.conf' - flagfile = '--flagfile=%s' % filename - args.insert(1, flagfile) + if os.path.exists(filename): + flagfile = '--flagfile=%s' % filename + args.insert(1, flagfile) def debug(arg): @@ -837,39 +838,3 @@ def bool_from_str(val): return True if int(val) else False except ValueError: return val.lower() == 'true' - - -class Bootstrapper(object): - """Provides environment bootstrapping capabilities for entry points.""" - - @staticmethod - def bootstrap_binary(argv): - """Initialize the Nova environment using command line arguments.""" - Bootstrapper.setup_flags(argv) - Bootstrapper.setup_logging() - Bootstrapper.log_flags() - - @staticmethod - def setup_logging(): - """Initialize logging and log a message indicating the Nova version.""" - logging.setup() - logging.audit(_("Nova Version (%s)") % - version.version_string_with_vcs()) - - @staticmethod - def setup_flags(input_flags): - """Initialize flags, load flag file, and print help if needed.""" - default_flagfile(args=input_flags) - FLAGS(input_flags or []) - flags.DEFINE_flag(flags.HelpFlag()) - flags.DEFINE_flag(flags.HelpshortFlag()) - flags.DEFINE_flag(flags.HelpXMLFlag()) - FLAGS.ParseNewFlags() - - @staticmethod - def log_flags(): - """Log the list of all active flags being used.""" - logging.audit(_("Currently active flags:")) - for key in FLAGS: - value = FLAGS.get(key, None) - logging.audit(_("%(key)s : %(value)s" % locals())) diff --git a/nova/wsgi.py b/nova/wsgi.py index c8ddb97d7..f2846aa73 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -39,9 +39,6 @@ from nova import log as logging from nova import utils -eventlet.patcher.monkey_patch(socket=True, time=True) - - FLAGS = flags.FLAGS LOG = logging.getLogger('nova.wsgi') -- cgit