Files
tryton/trytond/server.py
T

232 lines
7.6 KiB
Python

#This file is part of Tryton. The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms.
"""
%prog [options]
"""
import sys, os, signal
import netsvc
import time
import psycopg2
import pooler
import sql_db
import config
from config import CONFIG
import web_service
import wkf_service
from module import register_classes
import osv, security, tools, version
import mx.DateTime
from getpass import getpass
import sha
class TrytonServer(object):
def __init__(self):
netsvc.init_logger()
self.logger = netsvc.Logger()
if not hasattr(mx.DateTime, 'strptime'):
mx.DateTime.strptime = lambda x, y: mx.DateTime.mktime(
time.strptime(x, y))
self.logger.notify_channel("init", netsvc.LOG_INFO,
'using %s as configuration file' % CONFIG.configfile)
self.logger.notify_channel("init", netsvc.LOG_INFO,
'initialising distributed objects services')
self.dispatcher = netsvc.Dispatcher()
self.dispatcher.monitor(signal.SIGINT)
web_service.DB()
web_service.Common()
web_service.Object()
web_service.Wizard()
web_service.Report()
wkf_service.WorkflowService()
def run(self):
"Run the server and never return"
db_name = CONFIG["db_name"]
cursor = None
try:
if db_name:
cursor = pooler.get_db_only(db_name).cursor()
except psycopg2.OperationalError:
self.logger.notify_channel("init", netsvc.LOG_INFO,
"could not connect to database '%s'!" % db_name,)
init = False
if cursor and CONFIG['init']:
cursor.execute("SELECT relname " \
"FROM pg_class " \
"WHERE relkind = 'r' AND relname in (" \
"'inherit', "
"'ir_model', "
"'ir_model_field', "
"'ir_ui_view', "
"'ir_ui_menu', "
"'res_user', "
"'res_group', "
"'res_group_user_rel', "
"'wkf', "
"'wkf_activity', "
"'wkf_transition', "
"'wkf_instance', "
"'wkf_workitem', "
"'wkf_witm_trans', "
"'ir_module_category', "
"'ir_module_module', "
"'ir_module_module_dependency, '"
"'ir_translation, '"
"'ir_lang'"
")")
if len(cursor.fetchall()) == 0:
self.logger.notify_channel("init", netsvc.LOG_INFO, "init db")
sql_db.init_db(cursor)
init = True
cursor.commit()
register_classes()
update_module = False
if db_name:
lang = None
if cursor:
cursor.execute('SELECT code FROM ir_lang ' \
'WHERE translatable = True')
lang = [x[0] for x in cursor.fetchall()]
cursor.close()
update_module = bool(CONFIG['init'] or CONFIG['update'])
pooler.get_db_and_pool(db_name, update_module=update_module,
lang=lang)
if init and db_name:
while True:
password = getpass('Admin Password:')
password2 = getpass('Admin Password Confirmation:')
if password != password2:
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
cursor = pooler.get_db_only(db_name).cursor()
cursor.execute('UPDATE res_user ' \
'SET password = %s ' \
'WHERE login = \'admin\'',
(sha.new(password).hexdigest(),))
cursor.commit()
cursor.close()
if update_module:
self.logger.notify_channel('init', netsvc.LOG_INFO,
'Update/Init succeed!')
sys.exit(0)
# Launch Server
secure = CONFIG["secure"]
if CONFIG['xmlrpc']:
interface = CONFIG["interface"]
try:
port = int(CONFIG["xmlport"])
except:
self.logger.notify_channel("init", netsvc.LOG_ERROR,
"invalid port '%s'!" % (CONFIG["xmlport"],))
sys.exit(1)
httpd = netsvc.HttpDaemon(interface, port, secure)
xml_gw = netsvc.XmlRpc.RpcGateway('web-service')
httpd.attach("/xmlrpc", xml_gw )
self.logger.notify_channel("web-service", netsvc.LOG_INFO,
"starting XML-RPC" + \
(CONFIG['secure'] and ' Secure' or '') + \
" services, port " + str(port))
if CONFIG['netrpc']:
interface = CONFIG["interface"]
try:
port = int(CONFIG["netport"])
except:
self.logger.notify_channel("init", netsvc.LOG_ERROR,
"invalid port '%s'!" % (CONFIG["netport"],))
sys.exit(1)
tinysocket = netsvc.TinySocketServerThread(interface, port,
secure)
self.logger.notify_channel("web-service", netsvc.LOG_INFO,
"starting netrpc service, port " + str(port))
if CONFIG['webdav']:
interface = CONFIG['interface']
try:
port = int(CONFIG['webdavport'])
except:
self.logger.notify_channel('init', netsvc.LOG_ERROR,
"invalid port '%s'!" % (CONFIG['webdavport'],))
sys.exit(1)
webdavd = netsvc.WebDAVServerThread(interface, port, secure)
self.logger.notify_channel('web-service', netsvc.LOG_INFO,
'starting webdav service, port ' + str(port))
def handler(signum, frame):
if CONFIG['netrpc']:
tinysocket.stop()
if CONFIG['xmlrpc']:
httpd.stop()
if CONFIG['webdav']:
webdavd.stop()
netsvc.Agent.quit()
if CONFIG['pidfile']:
os.unlink(CONFIG['pidfile'])
sys.exit(0)
if CONFIG['pidfile']:
fd_pid = open(CONFIG['pidfile'], 'w')
pidtext = "%d" % (os.getpid())
fd_pid.write(pidtext)
fd_pid.close()
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
self.logger.notify_channel("init", netsvc.LOG_INFO,
'the server is running, waiting for connections...')
if CONFIG['netrpc']:
tinysocket.start()
if CONFIG['xmlrpc']:
httpd.start()
if CONFIG['webdav']:
webdavd.start()
#DISPATCHER.run()
try:
import psyco
psyco.full()
except ImportError:
pass
count = 0
while True:
time.sleep(1)
count += 1
if count == 60:
#TODO check if we don't need to run pool_jobs in a thread
for dbname in pooler.get_db_list():
pool = pooler.get_pool(dbname)
pool.get('ir.cron').pool_jobs(dbname)
count = 0
if __name__ == "__main__":
SERVER = TrytonServer()
SERVER.run()