From 8119d8920074dfc05a8bc9e256019a7b79c83d97 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 11 Jan 2013 16:31:13 +0100 Subject: [PATCH 01/11] [ADD] oe web: run an OpenERP web process. bzr revid: vmt@openerp.com-20130111153113-ue2ybx33e2gh99sx --- openerp/service/wsgi_server.py | 17 +++++------ openerpcommand/__init__.py | 3 +- openerpcommand/web.py | 56 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 openerpcommand/web.py diff --git a/openerp/service/wsgi_server.py b/openerp/service/wsgi_server.py index 67436a1c0bf..c9294365d71 100644 --- a/openerp/service/wsgi_server.py +++ b/openerp/service/wsgi_server.py @@ -410,22 +410,15 @@ def application(environ, start_response): # The WSGI server, started by start_server(), stopped by stop_server(). httpd = None -def serve(): +def serve(interface, port, threaded): """ Serve HTTP requests via werkzeug development server. - If werkzeug can not be imported, we fall back to wsgiref's simple_server. - Calling this function is blocking, you might want to call it in its own thread. """ global httpd - - # TODO Change the xmlrpc_* options to http_* - interface = config['xmlrpc_interface'] or '0.0.0.0' - port = config['xmlrpc_port'] - httpd = werkzeug.serving.make_server(interface, port, application, threaded=True) - _logger.info('HTTP service (werkzeug) running on %s:%s', interface, port) + httpd = werkzeug.serving.make_server(interface, port, application, threaded=threaded) httpd.serve_forever() def start_service(): @@ -433,7 +426,11 @@ def start_service(): The WSGI server can be shutdown with stop_server() below. """ - threading.Thread(target=serve).start() + # TODO Change the xmlrpc_* options to http_* + interface = config['xmlrpc_interface'] or '0.0.0.0' + port = config['xmlrpc_port'] + _logger.info('HTTP service (werkzeug) running on %s:%s', interface, port) + threading.Thread(target=serve, args=(interface, port, True)).start() def stop_service(): """ Initiate the shutdown of the WSGI server. diff --git a/openerpcommand/__init__.py b/openerpcommand/__init__.py index 53d456c7639..5a243ded229 100644 --- a/openerpcommand/__init__.py +++ b/openerpcommand/__init__.py @@ -17,9 +17,10 @@ from . import run_tests from . import scaffold from . import uninstall from . import update +from . import web command_list_server = (conf, drop, initialize, model, module, read, run_tests, - scaffold, uninstall, update, ) + scaffold, uninstall, update, web, ) command_list_client = (Call, Open, Show, ConsumeNothing, ConsumeMemory, LeakMemory, ConsumeCPU, Bench, BenchRead, diff --git a/openerpcommand/web.py b/openerpcommand/web.py new file mode 100644 index 00000000000..632aa482646 --- /dev/null +++ b/openerpcommand/web.py @@ -0,0 +1,56 @@ +""" +Run a normal OpenERP HTTP process. +""" + +import logging +import os +import threading + +import openerp.cli.server +import openerp.service.wsgi_server +import openerp.tools.config + +import common + +_logger = logging.getLogger(__name__) + +def run(args): + os.environ["TZ"] = "UTC" + + if args.addons: + args.addons = args.addons.split(':') + else: + args.addons = [] + + config = openerp.tools.config + config['addons_path'] = ','.join(args.addons) + + openerp.cli.server.check_root_user() + openerp.netsvc.init_logger() + #openerp.cli.server.report_configuration() + openerp.cli.server.configure_babel_localedata_path() + openerp.cli.server.setup_signal_handlers() + + target = openerp.service.wsgi_server.serve + if not args.gevent: + arg = (args.interface, int(args.port), args.threaded) + threading.Thread(target=target, args=arg).start() + openerp.cli.server.quit_on_signals() + else: + print "The --gevent option is not yet implemented." + +def add_parser(subparsers): + parser = subparsers.add_parser('web', + description='Run a normal OpenERP HTTP process. By default a ' + 'singly-threaded Werkzeug server is used.') + common.add_addons_argument(parser) + parser.add_argument('--interface', default='0.0.0.0', + help='HTTP interface to listen on (default is %(default)s)') + parser.add_argument('--port', metavar='INT', default=8069, + help='HTTP port to listen on (default is %(default)s)') + parser.add_argument('--threaded', action='store_true', + help='Use a multithreaded Werkzeug server (incompatible with --gevent)') + parser.add_argument('--gevent', action='store_true', + help="Use gevent's WSGI server (incompatible with --threaded)") + + parser.set_defaults(run=run) From 40c02c12b663acf587dc75c2173d7f31a380794b Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 11 Jan 2013 17:12:16 +0100 Subject: [PATCH 02/11] [IMP] oe web: option to use gevent WSGI server. bzr revid: vmt@openerp.com-20130111161216-visss6da671f0qup --- openerpcommand/web.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openerpcommand/web.py b/openerpcommand/web.py index 632aa482646..a1eb7abd2e5 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -37,7 +37,17 @@ def run(args): threading.Thread(target=target, args=arg).start() openerp.cli.server.quit_on_signals() else: - print "The --gevent option is not yet implemented." + config.options["gevent"] = True + import gevent.monkey + import gevent.wsgi + import gevent_psycopg2 + gevent.monkey.patch_all() + gevent_psycopg2.monkey_patch() + + app = openerp.service.wsgi_server.application + server = gevent.wsgi.WSGIServer((args.interface, int(args.port)), app) + server.serve_forever() + # TODO quit_on_signals def add_parser(subparsers): parser = subparsers.add_parser('web', From b146cd6fec80185f157c32f5b5dd68629c1636bd Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Tue, 15 Jan 2013 15:01:10 +0100 Subject: [PATCH 03/11] [ADD] oe: added cron sub-command to run a single process dedicated to cron jobs. bzr revid: vmt@openerp.com-20130115140110-fwu7yb2v0sj3oqqv --- openerp/addons/base/ir/ir_cron.py | 4 +++ openerpcommand/__init__.py | 3 +- openerpcommand/cron.py | 55 +++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 openerpcommand/cron.py diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index 4bf99cf9934..60aa685b6fc 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -135,6 +135,10 @@ class ir_cron(osv.osv): _logger.debug('%.3fs (%s, %s)' % (end_time - start_time, model_name, method_name)) except Exception, e: self._handle_callback_exception(cr, uid, model_name, method_name, args, job_id, e) + else: + msg = "Method `%s.%s` do not exist." % (model._name, method_name) \ + if model else "Model `%s` do not exist." % model._name + _logger.warning(msg) def _process_job(self, job_cr, job, cron_cr): """ Run a given job taking care of the repetition. diff --git a/openerpcommand/__init__.py b/openerpcommand/__init__.py index 5a243ded229..6d41c2842dc 100644 --- a/openerpcommand/__init__.py +++ b/openerpcommand/__init__.py @@ -8,6 +8,7 @@ from .bench_sale_mrp import BenchSaleMrp from . import common from . import conf # Not really server-side (in the `for` below). +from . import cron from . import drop from . import initialize from . import model @@ -19,7 +20,7 @@ from . import uninstall from . import update from . import web -command_list_server = (conf, drop, initialize, model, module, read, run_tests, +command_list_server = (conf, cron, drop, initialize, model, module, read, run_tests, scaffold, uninstall, update, web, ) command_list_client = (Call, Open, Show, ConsumeNothing, ConsumeMemory, diff --git a/openerpcommand/cron.py b/openerpcommand/cron.py new file mode 100644 index 00000000000..dc74e92ff09 --- /dev/null +++ b/openerpcommand/cron.py @@ -0,0 +1,55 @@ +""" +Run an OpenERP cron process. +""" + +import os + +import common + +def set_addons(args): + import openerp.tools.config + config = openerp.tools.config + + assert hasattr(args, 'addons') + if args.addons: + args.addons = args.addons.split(':') + else: + args.addons = [] + + config['addons_path'] = ','.join(args.addons) + +def run(args): + import openerp.cli.server + import openerp.tools.config + import openerp.service.cron + config = openerp.tools.config + + os.environ["TZ"] = "UTC" + set_addons(args) + args.database = args.database or [] + + config['log_handler'] = [':WARNING', 'openerp.addons.base.ir.ir_cron:DEBUG'] + + openerp.cli.server.check_root_user() + openerp.netsvc.init_logger() + #openerp.cli.server.report_configuration() + openerp.cli.server.configure_babel_localedata_path() + openerp.cli.server.setup_signal_handlers() + import openerp.addons.base + if args.database: + for db in args.database: + openerp.cli.server.preload_registry(db) + openerp.service.cron.start_service() + openerp.cli.server.quit_on_signals() + else: + print "No database given." + + +def add_parser(subparsers): + parser = subparsers.add_parser('cron', + description='Run an OpenERP cron process.') + common.add_addons_argument(parser) + parser.add_argument('--database', action='append', + help='Database for which cron jobs are processed (can be given repeated)') + + parser.set_defaults(run=run) From f6e2a1314cc9150bb841d093e01ff9fa7c726420 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 16 Jan 2013 14:25:41 +0100 Subject: [PATCH 04/11] [IMP] oe cron: use setproctitle, set openerp.multi_process. bzr revid: vmt@openerp.com-20130116132541-r655evhfrptxxyxl --- openerpcommand/common.py | 4 ++++ openerpcommand/cron.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/openerpcommand/common.py b/openerpcommand/common.py index 89898ff4c3c..bc3101c4be5 100644 --- a/openerpcommand/common.py +++ b/openerpcommand/common.py @@ -3,6 +3,10 @@ Define a few common arguments for server-side command-line tools. """ import argparse import os +try: + from setproctitle import setproctitle +except ImportError: + setproctitle = lambda x: None import sys def add_addons_argument(parser): diff --git a/openerpcommand/cron.py b/openerpcommand/cron.py index dc74e92ff09..635aca97fa4 100644 --- a/openerpcommand/cron.py +++ b/openerpcommand/cron.py @@ -19,6 +19,7 @@ def set_addons(args): config['addons_path'] = ','.join(args.addons) def run(args): + import openerp import openerp.cli.server import openerp.tools.config import openerp.service.cron @@ -30,6 +31,9 @@ def run(args): config['log_handler'] = [':WARNING', 'openerp.addons.base.ir.ir_cron:DEBUG'] + openerp.multi_process = True + common.setproctitle('openerp-cron [%s]' % ', '.join(args.database)) + openerp.cli.server.check_root_user() openerp.netsvc.init_logger() #openerp.cli.server.report_configuration() From 24878795fe64d87583f61b5a303d0414915cdb68 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 18 Jan 2013 13:16:19 +0100 Subject: [PATCH 05/11] [IMP] oe web/cron: slight refactor. bzr revid: vmt@openerp.com-20130118121619-be5n01rieac11oru --- openerpcommand/common.py | 15 +++++++++++++++ openerpcommand/cron.py | 16 ++-------------- openerpcommand/web.py | 24 ++++++++++++------------ 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/openerpcommand/common.py b/openerpcommand/common.py index bc3101c4be5..45c2742d68f 100644 --- a/openerpcommand/common.py +++ b/openerpcommand/common.py @@ -16,6 +16,21 @@ def add_addons_argument(parser): parser.add_argument('--addons', metavar='ADDONS', **required_or_default('ADDONS', 'colon-separated list of paths to addons')) +def set_addons(args): + """ + Turn args.addons into a list instead of a column-separated strings. + Set openerp.toools.config accordingly. + """ + import openerp.tools.config + config = openerp.tools.config + + assert hasattr(args, 'addons') + if args.addons: + args.addons = args.addons.split(':') + else: + args.addons = [] + + config['addons_path'] = ','.join(args.addons) def get_addons_from_paths(paths, exclude): """ diff --git a/openerpcommand/cron.py b/openerpcommand/cron.py index 635aca97fa4..441cc48d457 100644 --- a/openerpcommand/cron.py +++ b/openerpcommand/cron.py @@ -6,18 +6,6 @@ import os import common -def set_addons(args): - import openerp.tools.config - config = openerp.tools.config - - assert hasattr(args, 'addons') - if args.addons: - args.addons = args.addons.split(':') - else: - args.addons = [] - - config['addons_path'] = ','.join(args.addons) - def run(args): import openerp import openerp.cli.server @@ -26,7 +14,7 @@ def run(args): config = openerp.tools.config os.environ["TZ"] = "UTC" - set_addons(args) + common.set_addons(args) args.database = args.database or [] config['log_handler'] = [':WARNING', 'openerp.addons.base.ir.ir_cron:DEBUG'] @@ -54,6 +42,6 @@ def add_parser(subparsers): description='Run an OpenERP cron process.') common.add_addons_argument(parser) parser.add_argument('--database', action='append', - help='Database for which cron jobs are processed (can be given repeated)') + help='Database for which cron jobs are processed (can be repeated)') parser.set_defaults(run=run) diff --git a/openerpcommand/web.py b/openerpcommand/web.py index a1eb7abd2e5..fa29d08b85d 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -6,24 +6,21 @@ import logging import os import threading -import openerp.cli.server -import openerp.service.wsgi_server -import openerp.tools.config - import common _logger = logging.getLogger(__name__) def run(args): - os.environ["TZ"] = "UTC" - - if args.addons: - args.addons = args.addons.split(':') - else: - args.addons = [] - + import openerp.cli.server + import openerp.service.wsgi_server + import openerp.tools.config config = openerp.tools.config - config['addons_path'] = ','.join(args.addons) + + os.environ["TZ"] = "UTC" + common.set_addons(args) + + openerp.multi_process = True + common.setproctitle('openerp-web') openerp.cli.server.check_root_user() openerp.netsvc.init_logger() @@ -33,6 +30,9 @@ def run(args): target = openerp.service.wsgi_server.serve if not args.gevent: + # TODO openerp.multi_process with a multi-threaded process probably + # doesn't work very well (e.g. waiting for all threads to complete + # before killing the process is not implemented). arg = (args.interface, int(args.port), args.threaded) threading.Thread(target=target, args=arg).start() openerp.cli.server.quit_on_signals() From 8b8f9249b5c81acc37db90011dd8d724f45fc0d0 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 18 Jan 2013 15:00:53 +0100 Subject: [PATCH 06/11] [FIX] oe web: always set gevent in tools.config. bzr revid: vmt@openerp.com-20130118140053-d38r8zjhjatykhcz --- openerpcommand/web.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerpcommand/web.py b/openerpcommand/web.py index fa29d08b85d..b254b4ac0c6 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -30,6 +30,7 @@ def run(args): target = openerp.service.wsgi_server.serve if not args.gevent: + config["gevent"] = False # TODO openerp.multi_process with a multi-threaded process probably # doesn't work very well (e.g. waiting for all threads to complete # before killing the process is not implemented). @@ -37,7 +38,7 @@ def run(args): threading.Thread(target=target, args=arg).start() openerp.cli.server.quit_on_signals() else: - config.options["gevent"] = True + config["gevent"] = True import gevent.monkey import gevent.wsgi import gevent_psycopg2 From 83b49ff62546ba167071379b3a1c5e5abd9b4a82 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 18 Jan 2013 15:47:50 +0100 Subject: [PATCH 07/11] [DOC] added prose for oe web and oe cron. bzr revid: vmt@openerp.com-20130118144750-lddby5a526092vdi --- doc/commands.rst | 40 ++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 1 + doc/openerp-command.rst | 22 ++++++++++++++-------- 3 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 doc/commands.rst diff --git a/doc/commands.rst b/doc/commands.rst new file mode 100644 index 00000000000..7a758b1ab2a --- /dev/null +++ b/doc/commands.rst @@ -0,0 +1,40 @@ +.. _commands: + +Available commands +================== + +This page explain some of the available ``oe`` commands. For an overview about +``oe``, see :doc:`openerp-command`. + +Keep in mind that ``oe --help`` and ``oe --help`` already give a lot +of information about the commands and their options and flags. + +``web`` +------- + +The ``web`` command is used to create a single OpenERP server process to handle +regular HTTP requests and XML-RPC requests. It is possible to execute such +process multiple times, possibly on different machines. + +It is possible to chose the ``--threaded`` or ``--gevent`` flags. It is +recommanded to use ``--threaded`` only when running a single process. +``--gevent`` is experimental; it is planned to use it for the embedded chat +feature. + +Example invocation:: + + > oe web --addons ../../addons/trunk:../../web/trunk/addons --threaded + +``cron`` +-------- + +The ``cron`` command is used to create a single OpenERP process to execute +so-called cron jobs, also called scheduled tasks in the OpenERP interface. As +for the ``web`` command, multiple cron processes can be run side by side. + +It is necessary to specify on the command-line which database need to be +watched by the cron process with the ``--database`` option. + +Example invocation:: + + > oe cron --addons ../../addons/trunk:../../web/trunk/addons --database production diff --git a/doc/index.rst b/doc/index.rst index 64fc04b552e..37870af49a8 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -25,6 +25,7 @@ OpenERP Command :maxdepth: 1 openerp-command.rst + commands.rst adding-command.rst OpenERP Server API diff --git a/doc/openerp-command.rst b/doc/openerp-command.rst index 2bfd845f8e3..6ca7b02b645 100644 --- a/doc/openerp-command.rst +++ b/doc/openerp-command.rst @@ -1,21 +1,22 @@ .. _openerp-command: -OpenERP Command -=============== +The ``oe`` script +================= The ``oe`` script provides a set of command-line tools around the OpenERP -framework. +framework. It is meant to replace the older ``openerp-server`` script (which +is still available). -Using OpenERP Command ---------------------- +Using ``oe`` +------------ In contrast to the previous ``openerp-server`` script, ``oe`` defines a few -sub-commands, each with its own set of flags and options. You can get some +commands, each with its own set of flags and options. You can get some information for any of them with :: - > oe --help + > oe --help For instance:: @@ -43,6 +44,11 @@ for instance here is a, say, ``test-trunk-view-validation.sh`` file:: # itself does not need it. oe run-tests -d ignored -m openerp.test_view_validation +Available commands +------------------- + +See the :doc:`commands` page. + Adding new commands ------------------- @@ -57,4 +63,4 @@ A preliminary ``oe-bash-completion`` file is provided. After sourcing it, > . oe-bash-completion -completion (using the TAB character) in Bash should be working. +completion (using the TAB character) in Bash should work. From 669885ce68ed960091ab1d3b75a10f236d1761c9 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 18 Jan 2013 16:32:35 +0100 Subject: [PATCH 08/11] [IMP] oe web: use openerp/__init__ instead of tools.config to store the gevent flag (similarly to the multi_procsess flag). bzr revid: vmt@openerp.com-20130118153235-hj6ttxargln4he4c --- openerp/__init__.py | 2 ++ openerpcommand/web.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/openerp/__init__.py b/openerp/__init__.py index c9db7076e71..307170b9033 100644 --- a/openerp/__init__.py +++ b/openerp/__init__.py @@ -51,6 +51,8 @@ wsgi.register_wsgi_handler = wsgi.wsgi_server.register_wsgi_handler # its own copy of the data structure and we don't need to care about # locks between threads. multi_process = False +# Is the server running with gevent. +evented = False # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerpcommand/web.py b/openerpcommand/web.py index b254b4ac0c6..7c39d8ecdc6 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -11,6 +11,7 @@ import common _logger = logging.getLogger(__name__) def run(args): + import openerp import openerp.cli.server import openerp.service.wsgi_server import openerp.tools.config @@ -30,7 +31,7 @@ def run(args): target = openerp.service.wsgi_server.serve if not args.gevent: - config["gevent"] = False + openerp.evented = False # TODO openerp.multi_process with a multi-threaded process probably # doesn't work very well (e.g. waiting for all threads to complete # before killing the process is not implemented). @@ -38,7 +39,7 @@ def run(args): threading.Thread(target=target, args=arg).start() openerp.cli.server.quit_on_signals() else: - config["gevent"] = True + openerp.evented = True import gevent.monkey import gevent.wsgi import gevent_psycopg2 From 8a279675254b4a157a41512b5418cda149d40079 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 21 Jan 2013 16:35:40 +0100 Subject: [PATCH 09/11] [IMP] oe web: handle SIGINT and somewhat SIGTERM for the gevent case. bzr revid: vmt@openerp.com-20130121153540-wnlnz7u8ypwg165i --- openerp/cli/server.py | 8 ++++---- openerpcommand/cron.py | 2 +- openerpcommand/web.py | 44 +++++++++++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index 7fb252f905f..2408703d6b8 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -181,9 +181,9 @@ def dumpstacks(sig, frame): code.append(" %s" % (line.strip())) _logger.info("\n".join(code)) -def setup_signal_handlers(): - """ Register the signal handler defined above. """ - SIGNALS = map(lambda x: getattr(signal, "SIG%s" % x), "INT TERM".split()) +def setup_signal_handlers(signal_handler): + """ Register the given signal handler. """ + SIGNALS = (signal.SIGINT, signal.SIGTERM) if os.name == 'posix': map(lambda sig: signal.signal(sig, signal_handler), SIGNALS) signal.signal(signal.SIGQUIT, dumpstacks) @@ -238,7 +238,7 @@ def main(args): configure_babel_localedata_path() - setup_signal_handlers() + setup_signal_handlers(signal_handler) if config["test_file"]: run_test_file(config['db_name'], config['test_file']) diff --git a/openerpcommand/cron.py b/openerpcommand/cron.py index 441cc48d457..16b983dbc50 100644 --- a/openerpcommand/cron.py +++ b/openerpcommand/cron.py @@ -26,7 +26,7 @@ def run(args): openerp.netsvc.init_logger() #openerp.cli.server.report_configuration() openerp.cli.server.configure_babel_localedata_path() - openerp.cli.server.setup_signal_handlers() + openerp.cli.server.setup_signal_handlers(openerp.cli.server.signal_handler) import openerp.addons.base if args.database: for db in args.database: diff --git a/openerpcommand/web.py b/openerpcommand/web.py index 7c39d8ecdc6..728318d1d9f 100644 --- a/openerpcommand/web.py +++ b/openerpcommand/web.py @@ -4,13 +4,36 @@ Run a normal OpenERP HTTP process. import logging import os -import threading +import signal import common _logger = logging.getLogger(__name__) +def mk_signal_handler(server): + def signal_handler(sig, frame): + """ + Specialized signal handler for the evented process. + """ + print "\n\n\nStopping gevent HTTP server...\n\n\n" + server.stop() + return signal_handler + +def setup_signal_handlers(signal_handler): + SIGNALS = (signal.SIGINT, signal.SIGTERM) + map(lambda sig: signal.signal(sig, signal_handler), SIGNALS) + def run(args): + # Note that gevent monkey patching must be done before importing the + # `threading` module, see http://stackoverflow.com/questions/8774958/. + if args.gevent: + import gevent + import gevent.monkey + import gevent.wsgi + import gevent_psycopg2 + gevent.monkey.patch_all() + gevent_psycopg2.monkey_patch() + import threading import openerp import openerp.cli.server import openerp.service.wsgi_server @@ -27,11 +50,11 @@ def run(args): openerp.netsvc.init_logger() #openerp.cli.server.report_configuration() openerp.cli.server.configure_babel_localedata_path() - openerp.cli.server.setup_signal_handlers() target = openerp.service.wsgi_server.serve if not args.gevent: openerp.evented = False + openerp.cli.server.setup_signal_handlers(openerp.cli.server.signal_handler) # TODO openerp.multi_process with a multi-threaded process probably # doesn't work very well (e.g. waiting for all threads to complete # before killing the process is not implemented). @@ -40,16 +63,19 @@ def run(args): openerp.cli.server.quit_on_signals() else: openerp.evented = True - import gevent.monkey - import gevent.wsgi - import gevent_psycopg2 - gevent.monkey.patch_all() - gevent_psycopg2.monkey_patch() app = openerp.service.wsgi_server.application server = gevent.wsgi.WSGIServer((args.interface, int(args.port)), app) - server.serve_forever() - # TODO quit_on_signals + setup_signal_handlers(mk_signal_handler(server)) + try: + server.serve_forever() + except KeyboardInterrupt: + try: + server.stop() + gevent.shutdown() + except KeyboardInterrupt: + sys.stderr.write("Forced shutdown.\n") + gevent.shutdown() def add_parser(subparsers): parser = subparsers.add_parser('web', From 9d56c47916678ef163fc4ffde095988862ec02f0 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 21 Jan 2013 16:41:07 +0100 Subject: [PATCH 10/11] [IMP] oe read: use the environment if --addons is not provided. bzr revid: vmt@openerp.com-20130121154107-uwa6pfowzks106xp --- openerpcommand/read.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openerpcommand/read.py b/openerpcommand/read.py index 83d6a5340f8..b013f14fecd 100644 --- a/openerpcommand/read.py +++ b/openerpcommand/read.py @@ -5,6 +5,8 @@ import os import sys import textwrap +import common + # TODO provide a --rpc flag to use XML-RPC (with a specific username) instead # of server-side library. def run(args): @@ -13,6 +15,11 @@ def run(args): import openerp config = openerp.tools.config config['log_handler'] = [':CRITICAL'] + if args.addons: + args.addons = args.addons.split(':') + else: + args.addons = [] + config['addons_path'] = ','.join(args.addons) openerp.netsvc.init_logger() registry = openerp.modules.registry.RegistryManager.get( args.database, update_module=False) @@ -44,8 +51,9 @@ def run(args): def add_parser(subparsers): parser = subparsers.add_parser('read', description='Display a record.') - parser.add_argument('-d', '--database', metavar='DATABASE', required=True, - help='the database to connect to') + parser.add_argument('-d', '--database', metavar='DATABASE', + **common.required_or_default('DATABASE', 'the database to connect to')) + common.add_addons_argument(parser) parser.add_argument('-m', '--model', metavar='MODEL', required=True, help='the model for which a record should be read') parser.add_argument('-i', '--id', metavar='RECORDID', required=True, From 59e0ef08c4baec5bf8e04b37576b54a84119872a Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 21 Jan 2013 17:27:01 +0100 Subject: [PATCH 11/11] [IMP] oe read: use common.set_addons(). bzr revid: vmt@openerp.com-20130121162701-1230alp0cc2l2u5e --- openerpcommand/read.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openerpcommand/read.py b/openerpcommand/read.py index b013f14fecd..d8455e16fff 100644 --- a/openerpcommand/read.py +++ b/openerpcommand/read.py @@ -15,11 +15,7 @@ def run(args): import openerp config = openerp.tools.config config['log_handler'] = [':CRITICAL'] - if args.addons: - args.addons = args.addons.split(':') - else: - args.addons = [] - config['addons_path'] = ','.join(args.addons) + common.set_addons(args) openerp.netsvc.init_logger() registry = openerp.modules.registry.RegistryManager.get( args.database, update_module=False)