Files
tryton/trytond/server.py
T

249 lines
9.4 KiB
Python
Raw Normal View History

2008-09-13 19:41:02 +02:00
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
2007-12-10 01:04:13 +01:00
"""
%prog [options]
"""
2008-09-12 19:57:33 +02:00
import logging
2009-02-11 20:37:24 +01:00
import logging.handlers
2012-04-01 23:08:15 +02:00
import sys
import os
import signal
2007-12-10 01:04:13 +01:00
import time
2008-07-30 11:52:20 +02:00
from getpass import getpass
import threading
2007-12-10 01:04:13 +01:00
2013-09-06 22:32:37 +02:00
from trytond.config import CONFIG
from trytond import backend
from trytond.pool import Pool
from trytond.monitor import monitor
from .transaction import Transaction
2013-09-06 22:32:37 +02:00
2007-12-10 01:04:13 +01:00
class TrytonServer(object):
def __init__(self, options):
format = '[%(asctime)s] %(levelname)s:%(name)s:%(message)s'
datefmt = '%a %b %d %H:%M:%S %Y'
logging.basicConfig(level=logging.INFO, format=format,
datefmt=datefmt)
CONFIG.update_etc(options['configfile'])
CONFIG.update_cmdline(options)
2008-09-12 19:57:33 +02:00
if CONFIG['logfile']:
logf = CONFIG['logfile']
# test if the directories exist, else create them
try:
diff = 0
if os.path.isfile(logf):
diff = int(time.time()) - int(os.stat(logf)[-1])
2008-09-12 19:57:33 +02:00
handler = logging.handlers.TimedRotatingFileHandler(
logf, 'D', 1, 30)
handler.rolloverAt -= diff
2008-09-12 19:57:33 +02:00
except Exception, exception:
2013-02-27 22:50:31 +01:00
sys.stderr.write(
"ERROR: couldn't create the logfile directory:"
+ str(exception))
2008-09-12 19:57:33 +02:00
else:
formatter = logging.Formatter(format, datefmt)
2008-09-12 19:57:33 +02:00
# tell the handler to use this format
handler.setFormatter(formatter)
# add the handler to the root logger
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)
elif os.name != 'nt':
reverse = '\x1b[7m'
reset = '\x1b[0m'
# reverse color for error and critical messages
for level in logging.ERROR, logging.CRITICAL:
msg = reverse + logging.getLevelName(level) + reset
logging.addLevelName(level, msg)
2009-02-11 20:57:42 +01:00
self.logger = logging.getLogger("server")
2007-12-10 01:04:13 +01:00
2008-11-18 17:40:30 +01:00
if CONFIG.configfile:
2013-02-27 22:50:31 +01:00
self.logger.info('using %s as configuration file'
% CONFIG.configfile)
else:
self.logger.info('using default configuration')
2008-09-12 19:57:33 +02:00
self.logger.info('initialising distributed objects services')
self.xmlrpcd = []
self.jsonrpcd = []
self.webdavd = []
2007-12-10 01:04:13 +01:00
def run(self):
"Run the server and never return"
update = bool(CONFIG['init'] or CONFIG['update'])
init = {}
signal.signal(signal.SIGINT, lambda *a: self.stop())
signal.signal(signal.SIGTERM, lambda *a: self.stop())
if hasattr(signal, 'SIGQUIT'):
signal.signal(signal.SIGQUIT, lambda *a: self.stop())
if hasattr(signal, 'SIGUSR1'):
signal.signal(signal.SIGUSR1, lambda *a: self.restart())
if CONFIG['pidfile']:
with open(CONFIG['pidfile'], 'w') as fd_pid:
fd_pid.write("%d" % (os.getpid()))
if not CONFIG["db_name"] \
and bool(CONFIG['init'] or CONFIG['update']):
raise Exception('Missing database option!')
if not update:
self.start_servers()
for db_name in CONFIG["db_name"]:
init[db_name] = False
with Transaction().start(db_name, 0) as transaction:
cursor = transaction.cursor
2011-05-16 12:22:43 +02:00
if CONFIG['init']:
if not cursor.test():
self.logger.info("init db")
backend.get('Database').init(cursor)
2011-05-16 12:22:43 +02:00
init[db_name] = True
cursor.commit()
elif not cursor.test():
raise Exception("'%s' is not a Tryton database!" % db_name)
for db_name in CONFIG["db_name"]:
if update:
with Transaction().start(db_name, 0) as transaction:
cursor = transaction.cursor
if not cursor.test():
2012-04-01 23:08:15 +02:00
raise Exception("'%s' is not a Tryton database!"
% db_name)
2013-02-27 22:50:31 +01:00
cursor.execute('SELECT code FROM ir_lang '
'WHERE translatable')
lang = [x[0] for x in cursor.fetchall()]
else:
lang = None
2009-02-11 14:52:22 +01:00
Pool(db_name).init(update=update, lang=lang)
for kind in ('init', 'update'):
CONFIG[kind] = {}
for db_name in CONFIG['db_name']:
if init[db_name]:
# try to read password from environment variable
# TRYTONPASSFILE, empty TRYTONPASSFILE ignored
passpath = os.getenv('TRYTONPASSFILE')
password = ''
if passpath:
try:
with open(passpath) as passfile:
password = passfile.readline()[:-1]
except Exception, err:
2013-02-27 22:50:31 +01:00
sys.stderr.write('Can not read password '
'from "%s": "%s"\n' % (passpath, err))
if not password:
while True:
password = getpass('Admin Password for %s: ' % db_name)
password2 = getpass('Admin Password Confirmation: ')
if password != password2:
2013-02-27 22:50:31 +01:00
sys.stderr.write('Admin Password Confirmation '
'doesn\'t match Admin Password!\n')
continue
if not password:
sys.stderr.write('Admin Password is required!\n')
continue
break
with Transaction().start(db_name, 0) as transaction:
2013-09-25 19:21:50 +02:00
pool = Pool()
User = pool.get('res.user')
admin, = User.search([('login', '=', 'admin')])
User.write([admin], {
'password': password,
})
transaction.cursor.commit()
2008-07-30 11:52:20 +02:00
2009-02-11 14:52:22 +01:00
if update:
2008-09-12 19:57:33 +02:00
self.logger.info('Update/Init succeed!')
2008-12-30 20:42:02 +01:00
logging.shutdown()
2007-12-10 01:04:13 +01:00
sys.exit(0)
2011-06-14 11:28:51 +02:00
threads = {}
while True:
2011-06-14 11:28:51 +02:00
if CONFIG['cron']:
for dbname in Pool.database_list():
thread = threads.get(dbname)
if thread and thread.is_alive():
continue
pool = Pool(dbname)
if not pool.lock.acquire(0):
2011-06-14 11:28:51 +02:00
continue
try:
if 'ir.cron' not in pool.object_name_list():
continue
2012-09-24 22:16:53 +02:00
Cron = pool.get('ir.cron')
finally:
pool.lock.release()
2011-06-14 11:28:51 +02:00
thread = threading.Thread(
2012-09-24 22:16:53 +02:00
target=Cron.run,
2011-06-14 11:28:51 +02:00
args=(dbname,), kwargs={})
thread.start()
threads[dbname] = thread
if CONFIG['auto_reload']:
for _ in range(60):
if monitor():
self.restart()
time.sleep(1)
else:
time.sleep(60)
def start_servers(self):
# Launch Server
if CONFIG['jsonrpc']:
from trytond.protocols.jsonrpc import JSONRPCDaemon
for hostname, port in CONFIG['jsonrpc']:
self.jsonrpcd.append(JSONRPCDaemon(hostname, port,
CONFIG['ssl_jsonrpc']))
self.logger.info("starting JSON-RPC%s protocol on %s:%d" %
(CONFIG['ssl_jsonrpc'] and ' SSL' or '', hostname or '*',
port))
if CONFIG['xmlrpc']:
from trytond.protocols.xmlrpc import XMLRPCDaemon
for hostname, port in CONFIG['xmlrpc']:
self.xmlrpcd.append(XMLRPCDaemon(hostname, port,
CONFIG['ssl_xmlrpc']))
self.logger.info("starting XML-RPC%s protocol on %s:%d" %
(CONFIG['ssl_xmlrpc'] and ' SSL' or '', hostname or '*',
port))
if CONFIG['webdav']:
from trytond.protocols.webdav import WebDAVServerThread
for hostname, port in CONFIG['webdav']:
self.webdavd.append(WebDAVServerThread(hostname, port,
CONFIG['ssl_webdav']))
self.logger.info("starting WebDAV%s protocol on %s:%d" %
(CONFIG['ssl_webdav'] and ' SSL' or '', hostname or '*',
port))
for servers in (self.xmlrpcd, self.jsonrpcd, self.webdavd):
for server in servers:
server.start()
def stop(self, exit=True):
for servers in (self.xmlrpcd, self.jsonrpcd, self.webdavd):
for server in servers:
server.stop()
server.join()
if exit:
if CONFIG['pidfile']:
os.unlink(CONFIG['pidfile'])
logging.getLogger('server').info('stopped')
logging.shutdown()
sys.exit(0)
def restart(self):
self.stop(False)
args = ([sys.executable] + ['-W%s' % o for o in sys.warnoptions]
+ sys.argv)
if sys.platform == "win32":
args = ['"%s"' % arg for arg in args]
os.execv(sys.executable, args)