OSDN Git Service

MOD cambios en comentarios, configuraciones y menores
[ipzuni/ip_zuni.git] / server / openerp-server.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 ##############################################################################
4 #
5 #    OpenERP, Open Source Management Solution
6 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
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 """
24 OpenERP - Server
25 OpenERP is an ERP+CRM program for small and medium businesses.
26
27 The whole source code is distributed under the terms of the
28 GNU Public Licence.
29
30 (c) 2003-TODAY, Fabien Pinckaers - OpenERP SA
31 """
32
33 import imp
34 import logging
35 import os
36 import signal
37 import sys
38 import threading
39 import traceback
40 import time
41
42 import pydevd
43
44 import openerp
45 __author__ = openerp.release.author
46 __version__ = openerp.release.version
47
48 # Also use the `openerp` logger for the main script.
49 _logger = logging.getLogger('openerp')
50
51 def check_root_user():
52     """ Exit if the process's user is 'root' (on POSIX system)."""
53     if os.name == 'posix':
54         import pwd
55         if pwd.getpwuid(os.getuid())[0] == 'root' :
56             sys.stderr.write("Running as user 'root' is a security risk, aborting.\n")
57             sys.exit(1)
58
59 def check_postgres_user():
60     """ Exit if the configured database user is 'postgres'.
61
62     This function assumes the configuration has been initialized.
63     """
64     config = openerp.tools.config
65     if config['db_user'] == 'postgres':
66         sys.stderr.write("Using the database user 'postgres' is a security risk, aborting.")
67         sys.exit(1)
68
69 def report_configuration():
70     """ Log the server version and some configuration values.
71
72     This function assumes the configuration has been initialized.
73     """
74     config = openerp.tools.config
75     _logger.info("OpenERP version %s", __version__)
76     for name, value in [('addons paths', config['addons_path']),
77                         ('database hostname', config['db_host'] or 'localhost'),
78                         ('database port', config['db_port'] or '5432'),
79                         ('database user', config['db_user'])]:
80         _logger.info("%s: %s", name, value)
81
82 def setup_pid_file():
83     """ Create a file with the process id written in it.
84
85     This function assumes the configuration has been initialized.
86     """
87     config = openerp.tools.config
88     if config['pidfile']:
89         fd = open(config['pidfile'], 'w')
90         pidtext = "%d" % (os.getpid())
91         fd.write(pidtext)
92         fd.close()
93
94 def preload_registry(dbname):
95     """ Preload a registry, and start the cron."""
96     try:
97         db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
98
99         # jobs will start to be processed later, when openerp.cron.start_master_thread() is called by openerp.service.start_services()
100         registry.schedule_cron_jobs()
101     except Exception:
102         _logger.exception('Failed to initialize database `%s`.', dbname)
103
104 def run_test_file(dbname, test_file):
105     """ Preload a registry, possibly run a test file, and start the cron."""
106     try:
107         db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
108         cr = db.cursor()
109         _logger.info('loading test file %s', test_file)
110         openerp.tools.convert_yaml_import(cr, 'base', file(test_file), {}, 'test', True)
111         cr.rollback()
112         cr.close()
113     except Exception:
114         _logger.exception('Failed to initialize database `%s` and run test file `%s`.', dbname, test_file)
115
116
117 def export_translation():
118     config = openerp.tools.config
119     dbname = config['db_name']
120
121     if config["language"]:
122         msg = "language %s" % (config["language"],)
123     else:
124         msg = "new language"
125     _logger.info('writing translation file for %s to %s', msg,
126         config["translate_out"])
127
128     fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower()
129     buf = file(config["translate_out"], "w")
130     cr = openerp.pooler.get_db(dbname).cursor()
131     openerp.tools.trans_export(config["language"],
132         config["translate_modules"] or ["all"], buf, fileformat, cr)
133     cr.close()
134     buf.close()
135
136     _logger.info('translation file written successfully')
137
138 def import_translation():
139     config = openerp.tools.config
140     context = {'overwrite': config["overwrite_existing_translations"]}
141     dbname = config['db_name']
142
143     cr = openerp.pooler.get_db(dbname).cursor()
144     openerp.tools.trans_load( cr, config["translate_in"], config["language"],
145         context=context)
146     cr.commit()
147     cr.close()
148
149 # Variable keeping track of the number of calls to the signal handler defined
150 # below. This variable is monitored by ``quit_on_signals()``.
151 quit_signals_received = 0
152
153 def signal_handler(sig, frame):
154     """ Signal handler: exit ungracefully on the second handled signal.
155
156     :param sig: the signal number
157     :param frame: the interrupted stack frame or None
158     """
159     global quit_signals_received
160     quit_signals_received += 1
161     if quit_signals_received > 1:
162         # logging.shutdown was already called at this point.
163         sys.stderr.write("Forced shutdown.\n")
164         os._exit(0)
165
166 def dumpstacks(sig, frame):
167     """ Signal handler: dump a stack trace for each existing thread."""
168     # code from http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application#answer-2569696
169     # modified for python 2.5 compatibility
170     thread_map = dict(threading._active, **threading._limbo)
171     id2name = dict([(threadId, thread.getName()) for threadId, thread in thread_map.items()])
172     code = []
173     for threadId, stack in sys._current_frames().items():
174         code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,'n/a'), threadId))
175         for filename, lineno, name, line in traceback.extract_stack(stack):
176             code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
177             if line:
178                 code.append("  %s" % (line.strip()))
179     _logger.info("\n".join(code))
180
181 def setup_signal_handlers():
182     """ Register the signal handler defined above. """
183     SIGNALS = map(lambda x: getattr(signal, "SIG%s" % x), "INT TERM".split())
184     if os.name == 'posix':
185         map(lambda sig: signal.signal(sig, signal_handler), SIGNALS)
186         signal.signal(signal.SIGQUIT, dumpstacks)
187     elif os.name == 'nt':
188         import win32api
189         win32api.SetConsoleCtrlHandler(lambda sig: signal_handler(sig, None), 1)
190
191 def quit_on_signals():
192     """ Wait for one or two signals then shutdown the server.
193
194     The first SIGINT or SIGTERM signal will initiate a graceful shutdown while
195     a second one if any will force an immediate exit.
196
197     """
198     # Wait for a first signal to be handled. (time.sleep will be interrupted
199     # by the signal handler.) The try/except is for the win32 case.
200     try:
201         while quit_signals_received == 0:
202             time.sleep(60)
203     except KeyboardInterrupt, e:
204         pass
205
206     if config['pidfile']:
207         os.unlink(config['pidfile'])
208
209     openerp.service.stop_services()
210     sys.exit(0)
211
212 def configure_babel_localedata_path():
213     # Workaround: py2exe and babel.
214     if hasattr(sys, 'frozen'):
215         import babel
216         babel.localedata._dirname = os.path.join(os.path.dirname(sys.executable), 'localedata')
217
218 if __name__ == "__main__":
219
220     os.environ["TZ"] = "UTC"
221
222     check_root_user()
223     openerp.tools.config.parse_config(sys.argv[1:])
224
225     check_postgres_user()
226     openerp.netsvc.init_logger()
227     report_configuration()
228
229     config = openerp.tools.config
230
231     configure_babel_localedata_path()
232
233     setup_signal_handlers()
234
235     if config["test_file"]:
236         run_test_file(config['db_name'], config['test_file'])
237         sys.exit(0)
238
239     if config["translate_out"]:
240         export_translation()
241         sys.exit(0)
242
243     if config["translate_in"]:
244         import_translation()
245         sys.exit(0)
246
247     if not config["stop_after_init"]:
248         # Some module register themselves when they are loaded so we need the
249         # services to be running before loading any registry.
250         openerp.service.start_services()
251
252     for m in openerp.conf.server_wide_modules:
253
254         try:
255             openerp.modules.module.load_openerp_module(m)
256         except Exception:
257             msg = ''
258             if m == 'web':
259                 msg = """
260 The `web` module is provided by the addons found in the `openerp-web` project.
261 Maybe you forgot to add those addons in your addons_path configuration."""
262             _logger.exception('Failed to load server-wide module `%s`.%s', m, msg)
263
264     if config['db_name']:
265         for dbname in config['db_name'].split(','):
266             preload_registry(dbname)
267
268     if config["stop_after_init"]:
269         sys.exit(0)
270
271     setup_pid_file()
272     _logger.info('OpenERP server is running, waiting for connections...')
273     quit_on_signals()
274
275 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: