[MERGE] merged oe-related changes:
- added a cron command - added a web command - added rst documentation - changed the read command to use the environment when --addons is not given bzr revid: vmt@openerp.com-20130121163525-im9rt2pvljz3bs7t
This commit is contained in:
commit
6fe1c4faec
|
@ -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 <command> --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
|
|
@ -25,6 +25,7 @@ OpenERP Command
|
|||
:maxdepth: 1
|
||||
|
||||
openerp-command.rst
|
||||
commands.rst
|
||||
adding-command.rst
|
||||
|
||||
OpenERP Server API
|
||||
|
|
|
@ -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 <sub-command> --help
|
||||
> oe <command> --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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
@ -17,9 +18,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, )
|
||||
command_list_server = (conf, cron, drop, initialize, model, module, read, run_tests,
|
||||
scaffold, uninstall, update, web, )
|
||||
|
||||
command_list_client = (Call, Open, Show, ConsumeNothing, ConsumeMemory,
|
||||
LeakMemory, ConsumeCPU, Bench, BenchRead,
|
||||
|
|
|
@ -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):
|
||||
|
@ -12,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):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
Run an OpenERP cron process.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import common
|
||||
|
||||
def run(args):
|
||||
import openerp
|
||||
import openerp.cli.server
|
||||
import openerp.tools.config
|
||||
import openerp.service.cron
|
||||
config = openerp.tools.config
|
||||
|
||||
os.environ["TZ"] = "UTC"
|
||||
common.set_addons(args)
|
||||
args.database = args.database or []
|
||||
|
||||
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()
|
||||
openerp.cli.server.configure_babel_localedata_path()
|
||||
openerp.cli.server.setup_signal_handlers(openerp.cli.server.signal_handler)
|
||||
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 repeated)')
|
||||
|
||||
parser.set_defaults(run=run)
|
|
@ -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,7 @@ def run(args):
|
|||
import openerp
|
||||
config = openerp.tools.config
|
||||
config['log_handler'] = [':CRITICAL']
|
||||
common.set_addons(args)
|
||||
openerp.netsvc.init_logger()
|
||||
registry = openerp.modules.registry.RegistryManager.get(
|
||||
args.database, update_module=False)
|
||||
|
@ -44,8 +47,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,
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
"""
|
||||
Run a normal OpenERP HTTP process.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
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
|
||||
import openerp.tools.config
|
||||
config = openerp.tools.config
|
||||
|
||||
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()
|
||||
#openerp.cli.server.report_configuration()
|
||||
openerp.cli.server.configure_babel_localedata_path()
|
||||
|
||||
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).
|
||||
arg = (args.interface, int(args.port), args.threaded)
|
||||
threading.Thread(target=target, args=arg).start()
|
||||
openerp.cli.server.quit_on_signals()
|
||||
else:
|
||||
openerp.evented = True
|
||||
|
||||
app = openerp.service.wsgi_server.application
|
||||
server = gevent.wsgi.WSGIServer((args.interface, int(args.port)), app)
|
||||
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',
|
||||
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)
|
Loading…
Reference in New Issue