diff --git a/CHANGELOG b/CHANGELOG index 7e33dc5ca0..17332ccbf1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow to specify more than one interface * Use unoconv for report format conversion * Allow to use any Opendocument as report template * Drop NetRPC and activate JSON-RPC by default diff --git a/etc/trytond.conf b/etc/trytond.conf index 85dc4cf004..d706c48199 100644 --- a/etc/trytond.conf +++ b/etc/trytond.conf @@ -3,28 +3,22 @@ [options] # This is the hostname used when generating tryton URI -#hostname = - -# Configure the IP address for trytond -# If empty, the server will listen on all available interfaces -#interface = - -# Activate the xml-rpc protocol -#xmlrpc = False -# Configure the port for the xml-rpc protocol to listen -#xmlport = 8069 +#hostname = # Activate the json-rpc protocol -#jsonrpc = True -# Configure the port for the json-rpc protocol to listen -#jsonport = 8000 +jsonrpc = localhost:8000 +#ssl_jsonrpc = False + # Configure the path of json-rpc data #jsondata_path = /var/www/localhost/tryton +# Activate the xml-rpc protocol +#xmlrpc = *:8069 +#ssl_xmlrpc = False + # Activate the webdav protocol -#webdav = False -# Configure the port for the webdav protocol to listen -#webdavport = 8080 +#webdav = *:8080 +#ssl_webdav = False # Configure the database type # allowed values are postgresql, sqlite, mysql @@ -51,10 +45,6 @@ #pidfile = False #logfile = False -# Enable secure connection with SSL -#secure_xmlrpc = False -#secure_jsonrpc = False -#secure_webdav = False #privatekey = server.pem #certificate = server.pem diff --git a/trytond/config.py b/trytond/config.py index 04068f0a0c..dea23a99f6 100644 --- a/trytond/config.py +++ b/trytond/config.py @@ -2,19 +2,36 @@ #this repository contains the full copyright notices and license terms. import ConfigParser, os, sys +def get_hostname(netloc): + if '[' in netloc and ']' in netloc: + return netloc.split(']')[0][1:] + elif ':' in netloc: + return netloc.split(':')[0] + else: + return netloc + +def get_port(netloc, protocol): + netloc = netloc.split(']')[-1] + if ':' in netloc: + return int(netloc.split(':')[1]) + else: + return { + 'jsonrpc': 8000, + 'xmlrpc': 8069, + 'webdav': 8080, + }.get(protocol) class ConfigManager(object): def __init__(self, fname=None): self.options = { 'hostname': None, - 'interface': '', - 'xmlrpc': False, - 'xmlport': 8069, - 'jsonrpc': True, - 'jsonport': 8000, + 'jsonrpc': [('localhost', '8000')], + 'ssl_jsonrpc': False, + 'xmlrpc': [], + 'ssl_xmlrpc': False, 'jsondata_path': '/var/www/localhost/tryton', - 'webdav': False, - 'webdavport': 8080, + 'webdav': [], + 'ssl_webdav': False, 'db_type': 'postgresql', 'db_host': False, 'db_port': False, @@ -29,9 +46,6 @@ class ConfigManager(object): 'debug_mode': False, 'pidfile': None, 'logfile': None, - 'secure_xmlrpc': False, - 'secure_jsonrpc': False, - 'secure_webdav': False, 'privatekey': '/etc/ssl/trytond/server.key', 'certificate': '/etc/ssl/trytond/server.pem', 'smtp_server': 'localhost', @@ -89,8 +103,9 @@ class ConfigManager(object): value = True if value == 'False' or value == 'false': value = False - if name in ('netport', 'xmlport', 'webdavport', 'jsonport'): - value = int(value) + if name in ('netrpc', 'xmlrpc', 'jsonrpc', 'webdav'): + value = [(get_hostname(netloc).replace('*', ''), + get_port(netloc, name)) for netloc in value.split(',')] self.options[name] = value def get(self, key, default=None): diff --git a/trytond/protocols/common.py b/trytond/protocols/common.py index 13092f77dc..1b972b2135 100644 --- a/trytond/protocols/common.py +++ b/trytond/protocols/common.py @@ -25,12 +25,11 @@ class daemon(threading.Thread): threading.Thread.__init__(self, name=name) self.secure = secure self.ipv6 = False - if socket.has_ipv6: - try: - socket.getaddrinfo(interface or None, port, socket.AF_INET6) + for family, _, _, _, _ in socket.getaddrinfo(interface or None, port, + socket.AF_UNSPEC, socket.SOCK_STREAM): + if family == socket.AF_INET6: self.ipv6 = True - except Exception: - pass + break def stop(self): self.server.shutdown() diff --git a/trytond/server.py b/trytond/server.py index 79a9c1dd35..c1ae7cea63 100644 --- a/trytond/server.py +++ b/trytond/server.py @@ -154,44 +154,45 @@ class TrytonServer(object): sys.exit(0) # Launch Server - if CONFIG['xmlrpc']: - from trytond.protocols.xmlrpc import XMLRPCDaemon - xmlrpcd = XMLRPCDaemon(CONFIG['interface'], CONFIG['xmlport'], - CONFIG['secure_xmlrpc']) - self.logger.info("starting XML-RPC%s protocol, port %d" % \ - (CONFIG['secure_xmlrpc'] and ' Secure' or '', - CONFIG['xmlport'])) - + jsonrpcd = [] if CONFIG['jsonrpc']: from trytond.protocols.jsonrpc import JSONRPCDaemon - jsonrpcd = JSONRPCDaemon(CONFIG['interface'], CONFIG['jsonport'], - CONFIG['secure_jsonrpc']) - self.logger.info("starting JSON-RPC%s protocol, port %d" % \ - (CONFIG['secure_jsonrpc'] and ' Secure' or '', - CONFIG['jsonport'])) + for hostname, port in CONFIG['jsonrpc']: + 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)) + xmlrpcd = [] + if CONFIG['xmlrpc']: + from trytond.protocols.xmlrpc import XMLRPCDaemon + for hostname, port in CONFIG['xmlrpc']: + 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)) + + webdavd = [] if CONFIG['webdav']: from trytond.protocols.webdav import WebDAVServerThread - webdavd = WebDAVServerThread(CONFIG['interface'], - CONFIG['webdavport'], CONFIG['secure_webdav']) - self.logger.info("starting WebDAV%s protocol, port %d" % \ - (CONFIG['secure_webdav'] and ' Secure' or '', - CONFIG['webdavport'])) + for hostname, port in CONFIG['webdav']: + 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)) def handler(signum, frame): if hasattr(signal, 'SIGUSR1'): if signum == signal.SIGUSR1: Pool.start() return - if CONFIG['xmlrpc']: - xmlrpcd.stop() - xmlrpcd.join() - if CONFIG['jsonrpc']: - jsonrpcd.stop() - jsonrpcd.join() - if CONFIG['webdav']: - webdavd.stop() - webdavd.join() + for servers in (xmlrpcd, jsonrpcd, webdavd): + for server in servers: + server.stop() + server.join() if CONFIG['pidfile']: os.unlink(CONFIG['pidfile']) logging.getLogger('server').info('stopped') @@ -210,12 +211,9 @@ class TrytonServer(object): signal.signal(signal.SIGUSR1, handler) self.logger.info('waiting for connections...') - if CONFIG['xmlrpc']: - xmlrpcd.start() - if CONFIG['jsonrpc']: - jsonrpcd.start() - if CONFIG['webdav']: - webdavd.start() + for servers in (xmlrpcd, jsonrpcd, webdavd): + for server in servers: + server.start() if CONFIG['psyco']: import psyco diff --git a/trytond/tests/test_mixins.py b/trytond/tests/test_mixins.py index b17a88cb78..735913e52e 100644 --- a/trytond/tests/test_mixins.py +++ b/trytond/tests/test_mixins.py @@ -26,28 +26,28 @@ class UrlTestCase(unittest.TestCase): "Test model URLs" with Transaction().start(DB_NAME, USER, CONTEXT): self.assertEqual(self.urlmodel.get_url(), - 'tryton://%s:%s/%s/model/test.urlobject' % (self.hostname, - CONFIG['jsonport'], urllib.quote(DB_NAME))) + 'tryton://%s/%s/model/test.urlobject' % (self.hostname, + urllib.quote(DB_NAME))) server_name = 'michaelscott.paper.test' CONFIG['hostname'] = server_name self.assertEqual(self.urlmodel.get_url(), - 'tryton://%s:%s/%s/model/test.urlobject' % (server_name, - CONFIG['jsonport'], urllib.quote(DB_NAME))) + 'tryton://%s/%s/model/test.urlobject' % (server_name, + urllib.quote(DB_NAME))) def testWizardURL(self): "Test wizard URLs" with Transaction().start(DB_NAME, USER, CONTEXT): CONFIG['hostname'] = None self.assertEqual(self.urlwizard.get_url(), - 'tryton://%s:%s/%s/wizard/test.test_wizard' % (self.hostname, - CONFIG['jsonport'], urllib.quote(DB_NAME))) + 'tryton://%s/%s/wizard/test.test_wizard' % (self.hostname, + urllib.quote(DB_NAME))) server_name = 'michaelscott.paper.test' CONFIG['hostname'] = server_name self.assertEqual(self.urlwizard.get_url(), - 'tryton://%s:%s/%s/wizard/test.test_wizard' % (server_name, - CONFIG['jsonport'], urllib.quote(DB_NAME))) + 'tryton://%s/%s/wizard/test.test_wizard' % (server_name, + urllib.quote(DB_NAME))) def suite(): diff --git a/trytond/url.py b/trytond/url.py index 6bb9aae8d5..e98c970e66 100644 --- a/trytond/url.py +++ b/trytond/url.py @@ -15,13 +15,12 @@ class URLMixin(object): from trytond.model import Model from trytond.wizard import Wizard from trytond.report import Report - url_part = {} hostname = CONFIG['hostname'] or unicode(socket.getfqdn(), 'utf8') - url_part['hostname'] = '.'.join(encodings.idna.ToASCII(part) for part in + hostname = '.'.join(encodings.idna.ToASCII(part) for part in hostname.split('.')) - url_part['port'] = CONFIG['jsonport'] + url_part = {} if isinstance(self, Model): url_part['type'] = 'model' elif isinstance(self, Wizard): @@ -34,6 +33,5 @@ class URLMixin(object): url_part['name'] = self._name url_part['database'] = Transaction().cursor.database_name - host_part = '%(hostname)s:%(port)s' % url_part local_part = urllib.quote('%(database)s/%(type)s/%(name)s' % url_part) - return 'tryton://%s/%s' % (host_part, local_part) + return 'tryton://%s/%s' % (hostname, local_part)