Launchpad automatic translations update.
[odoo/odoo.git] / openerp / service / __init__.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #    Copyright (C) 2010-2012 OpenERP SA (<http://www.openerp.com>)
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU Affero General Public License as
10 #    published by the Free Software Foundation, either version 3 of the
11 #    License, or (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU Affero General Public License for more details.
17 #
18 #    You should have received a copy of the GNU Affero General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 import logging
24 import os
25 import signal
26 import subprocess
27 import sys
28 import threading
29 import time
30
31 import cron
32 import wsgi_server
33
34 import openerp.modules
35 import openerp.netsvc
36 import openerp.osv
37 from openerp.release import nt_service_name
38 import openerp.tools
39
40 import common
41 import db
42 import model
43 import report
44
45 #.apidoc title: RPC Services
46
47 """ Classes of this module implement the network protocols that the
48     OpenERP server uses to communicate with remote clients.
49
50     Some classes are mostly utilities, whose API need not be visible to
51     the average user/developer. Study them only if you are about to
52     implement an extension to the network protocols, or need to debug some
53     low-level behavior of the wire.
54 """
55
56 _logger = logging.getLogger(__name__)
57
58 def load_server_wide_modules():
59     for m in openerp.conf.server_wide_modules:
60         try:
61             openerp.modules.module.load_openerp_module(m)
62         except Exception:
63             msg = ''
64             if m == 'web':
65                 msg = """
66 The `web` module is provided by the addons found in the `openerp-web` project.
67 Maybe you forgot to add those addons in your addons_path configuration."""
68             _logger.exception('Failed to load server-wide module `%s`.%s', m, msg)
69
70 start_internal_done = False
71 main_thread_id = threading.currentThread().ident
72
73 def start_internal():
74     global start_internal_done
75     if start_internal_done:
76         return
77     openerp.netsvc.init_logger()
78
79     load_server_wide_modules()
80     start_internal_done = True
81
82 def start_services():
83     """ Start all services including http, and cron """
84     start_internal()
85     # Start the WSGI server.
86     wsgi_server.start_service()
87     # Start the main cron thread.
88     cron.start_service()
89
90 def stop_services():
91     """ Stop all services. """
92     # stop services
93     cron.stop_service()
94     wsgi_server.stop_service()
95
96     _logger.info("Initiating shutdown")
97     _logger.info("Hit CTRL-C again or send a second signal to force the shutdown.")
98
99     # Manually join() all threads before calling sys.exit() to allow a second signal
100     # to trigger _force_quit() in case some non-daemon threads won't exit cleanly.
101     # threading.Thread.join() should not mask signals (at least in python 2.5).
102     me = threading.currentThread()
103     _logger.debug('current thread: %r', me)
104     for thread in threading.enumerate():
105         _logger.debug('process %r (%r)', thread, thread.isDaemon())
106         if thread != me and not thread.isDaemon() and thread.ident != main_thread_id:
107             while thread.isAlive():
108                 _logger.debug('join and sleep')
109                 # Need a busyloop here as thread.join() masks signals
110                 # and would prevent the forced shutdown.
111                 thread.join(0.05)
112                 time.sleep(0.05)
113
114     _logger.debug('--')
115     openerp.modules.registry.RegistryManager.delete_all()
116     logging.shutdown()
117
118 def start_services_workers():
119     import openerp.service.workers
120     openerp.multi_process = True
121     openerp.service.workers.Multicorn(openerp.service.wsgi_server.application).run()
122
123 def _reexec():
124     """reexecute openerp-server process with (nearly) the same arguments"""
125     if openerp.tools.osutil.is_running_as_nt_service():
126         subprocess.call('net stop {0} && net start {0}'.format(nt_service_name), shell=True)
127     exe = os.path.basename(sys.executable)
128     strip_args = ['-d', '-u']
129     a = sys.argv[:]
130     args = [x for i, x in enumerate(a) if x not in strip_args and a[max(i - 1, 0)] not in strip_args]
131     if not args or args[0] != exe:
132         args.insert(0, exe)
133     os.execv(sys.executable, args)
134
135 def restart_server():
136     if openerp.multi_process:
137         raise NotImplementedError("Multicorn is not supported (but gunicorn was)")
138         pid = openerp.wsgi.core.arbiter_pid
139         os.kill(pid, signal.SIGHUP)
140     else:
141         if os.name == 'nt':
142             def reborn():
143                 stop_services()
144                 _reexec()
145
146             # run in a thread to let the current thread return response to the caller.
147             threading.Thread(target=reborn).start()
148         else:
149             openerp.phoenix = True
150             os.kill(os.getpid(), signal.SIGINT)
151
152 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: