Commit 007ab1e5 authored by Grégory Wisniewski's avatar Grégory Wisniewski

Add a configuration manager that load options from :

* Default values
* Command line
* Configuration file
Restore the sample configuration file, updated with new options.
Tests updated.


git-svn-id: https://svn.erp5.org/repos/neo/trunk@1364 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent d63d3e88
# Note: Unless otherwise noted, all parameters in this configuration file
# must be identical for all nodes in a given cluster.
# Default parameters.
[DEFAULT]
# The cluster name
# This must be set.
# It must be a name unique to a given cluster, to prevent foreign
# misconfigured nodes from interfering.
cluster:
# The list of master nodes
# Master nodes not not in this list will be rejected by the cluster.
# This list should be identical for all nodes in a given cluster for
# maximum availability.
masters: 127.0.0.1:10000
# Partition table configuration
# Data in the cluster is distributed among nodes using a partition table, which
# has the following parameters.
# Replicas: How many copies of a partition should exist at a time.
# 0 means no redundancy
# 1 means there is a spare copy of all partitions
replicas: 1
# Partitions: How data spreads among storage nodes. This number must be at
# least equal to the number of storage nodes the cluster contains.
# IMPORTANT: This must not be changed once the cluster contains data.
partitions: 20
# Individual nodes parameters
# Some parameters makes no sense to be defined in [DEFAULT] section.
# They are:
# bind: The ip:port the node will listen on.
# database: Storage nodes only. The MySQL database credentials to use
# (username:password@database).
# Those database must be created manualy.
# Admin node
[admin]
bind: 127.0.0.1:9999
# Master nodes
[master]
bind: 127.0.0.1:10000
# Storage nodes
[storage]
database: neo:neo@neo1
bind: 127.0.0.1:20000
...@@ -51,32 +51,26 @@ class Dispatcher: ...@@ -51,32 +51,26 @@ class Dispatcher:
class Application(object): class Application(object):
"""The storage node application.""" """The storage node application."""
def __init__(self, cluster, bind, masters, uuid=None): def __init__(self, config):
# always use default connector for now # always use default connector for now
self.connector_handler = getConnectorHandler() self.connector_handler = getConnectorHandler()
# set the cluster name self.name = config.getCluster()
if cluster is None: self.server = config.getBind()
raise RuntimeError, 'cluster name must be non-empty' self.master_node_list = config.getMasters()
self.name = cluster
# set the bind address
ip_address, port = bind.split(':')
self.server = (ip_address, int(port))
logging.debug('IP address is %s, port is %d', *(self.server))
# load master node list logging.debug('IP address is %s, port is %d', *(self.server))
self.master_node_list = parseMasterList(masters)
logging.debug('master nodes are %s', self.master_node_list) logging.debug('master nodes are %s', self.master_node_list)
# Internal attributes. # Internal attributes.
self.em = EventManager() self.em = EventManager()
self.nm = NodeManager() self.nm = NodeManager()
# The partition table is initialized after getting the number of # The partition table is initialized after getting the number of
# partitions. # partitions.
self.pt = None self.pt = None
self.uuid = uuid self.uuid = config.getUUID()
self.primary_master_node = None self.primary_master_node = None
self.ptid = None self.ptid = None
self.request_handler = MasterRequestEventHandler(self) self.request_handler = MasterRequestEventHandler(self)
......
#
# Copyright (C) 2006-2009 Nexedi SA
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from ConfigParser import SafeConfigParser
from neo.util import bin, parseMasterList
class ConfigurationManager(object):
"""
Configuration manager that load options from a configuration file and
command line arguments
"""
def __init__(self, defaults, config_file, section, argument_list):
self.defaults = defaults
self.argument_list = argument_list
self.parser = None
if config_file is not None:
self.parser = SafeConfigParser(defaults)
self.parser.read(config_file)
self.section = section
def __get(self, key, optional=False):
value = self.argument_list.get(key)
if value is None:
if self.parser is None:
value = self.defaults.get(key)
else:
value = self.parser.get(self.section, key)
if value is None and not optional:
raise RuntimeError("Option '%s' is undefined'" % (key, ))
return value
def getMasters(self):
""" Get the master node list except itself """
masters = self.__get('masters')
if not masters:
return []
# load master node list except itself
return parseMasterList(masters, except_node=self.getBind())
def getBind(self):
""" Get the address to bind to """
bind = self.__get('bind')
if ':' in bind:
(ip, port) = bind.split(':')
else:
ip = bind
# took port from default bind address
port = self.defaults['bind'].split(':')[1]
return (ip, int(port))
def getDatabase(self):
""" Get the database credentials (username, password, database) """
# expected pattern : [user[:password]@]database
username = None
password = None
database = self.__get('database')
if '@' in database:
(username, database) = database.split('@')
if ':' in username:
(username, password) = username.split(':')
return (username, password, database)
def getCluster(self):
cluster = self.__get('cluster')
assert cluster != '', "Cluster name must be non-empty"
return cluster
def getName(self):
return self.__get('name')
def getReplicas(self):
return int(self.__get('replicas'))
def getPartitions(self):
return int(self.__get('partitions'))
def getReset(self):
# only from command line
return self.argument_list.get('reset', False)
def getUUID(self):
# only from command line
return bin(self.argument_list.get('uuid', None))
...@@ -40,23 +40,16 @@ REQUIRED_NODE_NUMBER = 1 ...@@ -40,23 +40,16 @@ REQUIRED_NODE_NUMBER = 1
class Application(object): class Application(object):
"""The master node application.""" """The master node application."""
def __init__(self, cluster, bind, masters, replicas, partitions, uuid): def __init__(self, config):
# always use default connector for now # always use default connector for now
self.connector_handler = getConnectorHandler() self.connector_handler = getConnectorHandler()
# set the cluster name self.name = config.getCluster()
if cluster is None: self.server = config.getBind()
raise RuntimeError, 'cluster name must be non-empty' self.master_node_list = config.getMasters()
self.name = cluster
# set the bind address
ip_address, port = bind.split(':')
self.server = (ip_address, int(port))
logging.debug('IP address is %s, port is %d', *(self.server)) logging.debug('IP address is %s, port is %d', *(self.server))
# load master node list
self.master_node_list = parseMasterList(masters, self.server)
logging.debug('master nodes are %s', self.master_node_list) logging.debug('master nodes are %s', self.master_node_list)
# Internal attributes. # Internal attributes.
...@@ -64,6 +57,7 @@ class Application(object): ...@@ -64,6 +57,7 @@ class Application(object):
self.nm = NodeManager() self.nm = NodeManager()
# Partition table # Partition table
replicas, partitions = config.getReplicas(), config.getPartitions()
if replicas < 0: if replicas < 0:
raise RuntimeError, 'replicas must be a positive integer' raise RuntimeError, 'replicas must be a positive integer'
if partitions <= 0: if partitions <= 0:
...@@ -78,7 +72,8 @@ class Application(object): ...@@ -78,7 +72,8 @@ class Application(object):
self.cluster_state = None self.cluster_state = None
# Generate an UUID for self # Generate an UUID for self
if uuid is None: uuid = config.getUUID()
if uuid is None or uuid == '':
uuid = self.getNewUUID(NodeTypes.MASTER) uuid = self.getNewUUID(NodeTypes.MASTER)
self.uuid = uuid self.uuid = uuid
......
...@@ -36,38 +36,28 @@ from neo.bootstrap import BootstrapManager ...@@ -36,38 +36,28 @@ from neo.bootstrap import BootstrapManager
class Application(object): class Application(object):
"""The storage node application.""" """The storage node application."""
def __init__(self, cluster, bind, masters, database, uuid, reset): def __init__(self, config):
# always use default connector for now # always use default connector for now
self.connector_handler = getConnectorHandler() self.connector_handler = getConnectorHandler()
# set the cluster name # set the cluster name
if cluster is None: self.name = config.getCluster()
raise RuntimeError, 'cluster name must be non-empty'
self.name = cluster
# set the bind address # set the bind address
ip_address, port = bind.split(':') self.server = config.getBind()
self.server = (ip_address, int(port))
logging.debug('IP address is %s, port is %d', *(self.server)) logging.debug('IP address is %s, port is %d', *(self.server))
# load master node list # load master node list
self.master_node_list = parseMasterList(masters) self.master_node_list = config.getMasters()
logging.debug('master nodes are %s', self.master_node_list) logging.debug('master nodes are %s', self.master_node_list)
# load database connection credentials, from user:password@database # load database connection credentials, from user:password@database
if database is None: (username, password, database) = config.getDatabase()
raise RuntimeError, 'database connection required'
(ident, dbname) = database.split('@')
if ':' in ident:
(username, password) = ident.split(':')
else:
(username, password) = (ident, None)
# Internal attributes. # Internal attributes.
self.em = EventManager() self.em = EventManager()
self.nm = NodeManager() self.nm = NodeManager()
self.dm = MySQLDatabaseManager(database=dbname, user=username, self.dm = MySQLDatabaseManager(database=database, user=username,
password=password) password=password)
# The partition table is initialized after getting the number of # The partition table is initialized after getting the number of
...@@ -92,16 +82,17 @@ class Application(object): ...@@ -92,16 +82,17 @@ class Application(object):
self.has_node_information = False self.has_node_information = False
self.has_partition_table = False self.has_partition_table = False
self.dm.setup(reset) self.dm.setup(reset=config.getReset())
self.loadConfiguration() self.loadConfiguration()
# force node uuid from command line argument, for testing purpose only # force node uuid from command line argument, for testing purpose only
if uuid is not None: if config.getUUID() is not None:
self.uuid = uuid self.uuid = config.getUUID()
def loadConfiguration(self): def loadConfiguration(self):
"""Load persistent configuration data from the database. """Load persistent configuration data from the database.
If data is not present, generate it.""" If data is not present, generate it."""
dm = self.dm dm = self.dm
self.uuid = dm.getUUID() self.uuid = dm.getUUID()
......
...@@ -61,33 +61,31 @@ class NeoTestBase(unittest.TestCase): ...@@ -61,33 +61,31 @@ class NeoTestBase(unittest.TestCase):
def getMasterConfiguration(self, cluster='main', master_number=2, def getMasterConfiguration(self, cluster='main', master_number=2,
replicas=2, partitions=1009, uuid=None): replicas=2, partitions=1009, uuid=None):
assert master_number >= 1 and master_number <= 10 assert master_number >= 1 and master_number <= 10
masters = ['127.0.0.1:1001%d' % i for i in xrange(master_number)] masters = [('127.0.0.1', 10010 + i) for i in xrange(master_number)]
return { return Mock({
'cluster': cluster, 'getCluster': cluster,
'bind': masters[0], 'getBind': masters[0],
'masters': '/'.join(masters), 'getMasters': masters,
'replicas': replicas, 'getReplicas': replicas,
'partitions': partitions, 'getPartitions': partitions,
'uuid': uuid, 'getUUID': uuid,
} })
def getStorageConfiguration(self, cluster='main', master_number=2, def getStorageConfiguration(self, cluster='main', master_number=2,
index=0, prefix=DB_PREFIX, uuid=None): index=0, prefix=DB_PREFIX, uuid=None):
assert master_number >= 1 and master_number <= 10 assert master_number >= 1 and master_number <= 10
assert index >= 0 and index <= 9 assert index >= 0 and index <= 9
masters = ['127.0.0.1:1001%d' % i for i in xrange(master_number)] masters = [('127.0.0.1', 10010 + i) for i in xrange(master_number)]
if DB_PASSWD is None: database = (DB_USER, DB_PASSWD, '%s%d' % (prefix, index))
database = '%s:@%s%d' % (DB_USER, prefix, index) return Mock({
else: 'getCluster': cluster,
database = '%s:%s@%s%d' % (DB_USER, DB_PASSWD, prefix, index) 'getName': 'storage',
return { 'getBind': ('127.0.0.1', 10020 + index),
'cluster': cluster, 'getMasters': masters,
'bind': '127.0.0.1:1002%d' % (index, ), 'getDatabase': database,
'masters': '/'.join(masters), 'getUUID': uuid,
'database': database, 'getReset': False,
'uuid': uuid, })
'reset': False,
}
# XXX: according to changes with namespaced UUIDs, it would be better to # XXX: according to changes with namespaced UUIDs, it would be better to
# implement get<NodeType>UUID() methods # implement get<NodeType>UUID() methods
......
...@@ -30,7 +30,7 @@ class MasterClientHandlerTests(NeoTestBase): ...@@ -30,7 +30,7 @@ class MasterClientHandlerTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration(master_number=1, replicas=1) config = self.getMasterConfiguration(master_number=1, replicas=1)
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
self.app.pt.setID(pack('!Q', 1)) self.app.pt.setID(pack('!Q', 1))
self.app.em = Mock({"getConnectionList" : []}) self.app.em = Mock({"getConnectionList" : []})
......
...@@ -40,7 +40,7 @@ class MasterClientElectionTests(NeoTestBase): ...@@ -40,7 +40,7 @@ class MasterClientElectionTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration() config = self.getMasterConfiguration()
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
self.app.em = Mock({"getConnectionList" : []}) self.app.em = Mock({"getConnectionList" : []})
self.app.finishing_transaction_dict = {} self.app.finishing_transaction_dict = {}
......
...@@ -26,7 +26,7 @@ class MasterAppTests(NeoTestBase): ...@@ -26,7 +26,7 @@ class MasterAppTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration() config = self.getMasterConfiguration()
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
def tearDown(self): def tearDown(self):
......
...@@ -28,7 +28,7 @@ class MasterRecoveryTests(NeoTestBase): ...@@ -28,7 +28,7 @@ class MasterRecoveryTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration() config = self.getMasterConfiguration()
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
self.app.finishing_transaction_dict = {} self.app.finishing_transaction_dict = {}
for address in self.app.master_node_list: for address in self.app.master_node_list:
......
...@@ -32,7 +32,7 @@ class MasterStorageHandlerTests(NeoTestBase): ...@@ -32,7 +32,7 @@ class MasterStorageHandlerTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration(master_number=1, replicas=1) config = self.getMasterConfiguration(master_number=1, replicas=1)
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
self.app.pt.setID(pack('!Q', 1)) self.app.pt.setID(pack('!Q', 1))
self.app.em = Mock({"getConnectionList" : []}) self.app.em = Mock({"getConnectionList" : []})
......
...@@ -31,7 +31,7 @@ class MasterVerificationTests(NeoTestBase): ...@@ -31,7 +31,7 @@ class MasterVerificationTests(NeoTestBase):
def setUp(self): def setUp(self):
# create an application object # create an application object
config = self.getMasterConfiguration() config = self.getMasterConfiguration()
self.app = Application(**config) self.app = Application(config)
self.app.pt.clear() self.app.pt.clear()
self.app.finishing_transaction_dict = {} self.app.finishing_transaction_dict = {}
for address in self.app.master_node_list: for address in self.app.master_node_list:
......
...@@ -46,7 +46,7 @@ class StorageClientHandlerTests(NeoTestBase): ...@@ -46,7 +46,7 @@ class StorageClientHandlerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.app.transaction_dict = {} self.app.transaction_dict = {}
self.app.store_lock_dict = {} self.app.store_lock_dict = {}
self.app.load_lock_dict = {} self.app.load_lock_dict = {}
......
...@@ -30,7 +30,7 @@ class StorageInitializationHandlerTests(NeoTestBase): ...@@ -30,7 +30,7 @@ class StorageInitializationHandlerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.verification = InitializationHandler(self.app) self.verification = InitializationHandler(self.app)
# define some variable to simulate client and storage node # define some variable to simulate client and storage node
self.master_port = 10010 self.master_port = 10010
......
...@@ -45,7 +45,7 @@ class StorageMasterHandlerTests(NeoTestBase): ...@@ -45,7 +45,7 @@ class StorageMasterHandlerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.app.transaction_dict = {} self.app.transaction_dict = {}
self.app.store_lock_dict = {} self.app.store_lock_dict = {}
self.app.load_lock_dict = {} self.app.load_lock_dict = {}
......
...@@ -30,7 +30,7 @@ class StorageAppTests(NeoTestBase): ...@@ -30,7 +30,7 @@ class StorageAppTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.app.event_queue = deque() self.app.event_queue = deque()
def tearDown(self): def tearDown(self):
......
...@@ -43,7 +43,7 @@ class StorageStorageHandlerTests(NeoTestBase): ...@@ -43,7 +43,7 @@ class StorageStorageHandlerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.app.transaction_dict = {} self.app.transaction_dict = {}
self.app.store_lock_dict = {} self.app.store_lock_dict = {}
self.app.load_lock_dict = {} self.app.load_lock_dict = {}
......
...@@ -32,7 +32,7 @@ class StorageVerificationHandlerTests(NeoTestBase): ...@@ -32,7 +32,7 @@ class StorageVerificationHandlerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration(master_number=1) config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config) self.app = Application(config)
self.verification = VerificationHandler(self.app) self.verification = VerificationHandler(self.app)
# define some variable to simulate client and storage node # define some variable to simulate client and storage node
self.master_port = 10010 self.master_port = 10010
......
...@@ -28,7 +28,7 @@ class BootstrapManagerTests(NeoTestBase): ...@@ -28,7 +28,7 @@ class BootstrapManagerTests(NeoTestBase):
self.prepareDatabase(number=1) self.prepareDatabase(number=1)
# create an application object # create an application object
config = self.getStorageConfiguration() config = self.getStorageConfiguration()
self.app = Application(**config) self.app = Application(config)
for address in self.app.master_node_list: for address in self.app.master_node_list:
self.app.nm.createMaster(address=address) self.app.nm.createMaster(address=address)
self.bootstrap = BootstrapManager(self.app, 'main', NodeTypes.STORAGE) self.bootstrap = BootstrapManager(self.app, 'main', NodeTypes.STORAGE)
......
...@@ -89,7 +89,7 @@ def parseMasterList(masters, except_node=None): ...@@ -89,7 +89,7 @@ def parseMasterList(masters, except_node=None):
address = (ip_address, int(port)) address = (ip_address, int(port))
if (address != except_node): if (address != except_node):
master_node_list.append(address) master_node_list.append(address)
return master_node_list return tuple(master_node_list)
class Enum(dict): class Enum(dict):
......
...@@ -20,13 +20,15 @@ ...@@ -20,13 +20,15 @@
from optparse import OptionParser from optparse import OptionParser
from neo import setupLog from neo import setupLog
from neo.util import bin from neo.config import ConfigurationManager
parser = OptionParser() parser = OptionParser()
parser.add_option('-u', '--uuid', help='specify an UUID to use for this ' \ parser.add_option('-u', '--uuid', help='specify an UUID to use for this ' \
'process') 'process')
parser.add_option('-v', '--verbose', action = 'store_true', parser.add_option('-v', '--verbose', action = 'store_true',
help = 'print verbose messages') help = 'print verbose messages')
parser.add_option('-f', '--file', help = 'specify a configuration file')
parser.add_option('-s', '--section', help = 'specify a configuration section')
parser.add_option('-l', '--logfile', help = 'specify a logging file') parser.add_option('-l', '--logfile', help = 'specify a logging file')
parser.add_option('-c', '--cluster', help = 'the cluster name') parser.add_option('-c', '--cluster', help = 'the cluster name')
parser.add_option('-m', '--masters', help = 'master node list') parser.add_option('-m', '--masters', help = 'master node list')
...@@ -35,18 +37,28 @@ parser.add_option('-n', '--name', help = 'the node name (impove logging)') ...@@ -35,18 +37,28 @@ parser.add_option('-n', '--name', help = 'the node name (impove logging)')
# build configuration dict from command line options # build configuration dict from command line options
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
config = { arguments = dict(
'uuid': options.uuid, uuid = options.uuid,
'cluster': options.cluster, cluster = options.cluster,
'masters': options.masters or '127.0.0.1:10000', masters = options.masters,
'bind': options.bind or '127.0.0.1:9999', bind = options.bind,
} )
config['uuid'] = bin(config['uuid']) defaults = dict(
name = 'admin',
bind = '127.0.0.1:9999',
masters = '127.0.0.1:10000',
)
config = ConfigurationManager(
defaults,
options.file,
options.section or 'admin',
arguments,
)
# setup custom logging # setup custom logging
setupLog(options.name or 'admin', options.logfile or None, options.verbose) setupLog(config.getName(), options.logfile or None, options.verbose)
# and then, load and run the application # and then, load and run the application
from neo.admin.app import Application from neo.admin.app import Application
app = Application(**config) app = Application(config)
app.run() app.run()
...@@ -20,11 +20,13 @@ ...@@ -20,11 +20,13 @@
from optparse import OptionParser from optparse import OptionParser
from neo import setupLog from neo import setupLog
from neo.util import bin from neo.config import ConfigurationManager
parser = OptionParser() parser = OptionParser()
parser.add_option('-v', '--verbose', action = 'store_true', parser.add_option('-v', '--verbose', action = 'store_true',
help = 'print verbose messages') help = 'print verbose messages')
parser.add_option('-f', '--file', help = 'specify a configuration file')
parser.add_option('-s', '--section', help = 'specify a configuration section')
parser.add_option('-u', '--uuid', help='the node UUID (testing purpose)') parser.add_option('-u', '--uuid', help='the node UUID (testing purpose)')
parser.add_option('-n', '--name', help = 'the node name (impove logging)') parser.add_option('-n', '--name', help = 'the node name (impove logging)')
parser.add_option('-b', '--bind', help = 'the local address to bind to') parser.add_option('-b', '--bind', help = 'the local address to bind to')
...@@ -36,22 +38,32 @@ parser.add_option('-l', '--logfile', help = 'specify a logging file') ...@@ -36,22 +38,32 @@ parser.add_option('-l', '--logfile', help = 'specify a logging file')
# build configuration dict from command line options # build configuration dict from command line options
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
config = { arguments = dict(
'uuid': options.uuid, uuid = options.uuid or None,
'bind': options.bind or '127.0.0.1:10000', bind = options.bind,
'cluster': options.cluster, cluster = options.cluster,
'masters': options.masters or '', masters = options.masters,
'replicas': options.replicas or 0, replicas = options.replicas,
'partitions': options.partitions or 100, partitions = options.partitions,
} )
config['uuid'] = bin(config['uuid']) defaults = dict(
config['replicas'] = int(config['replicas']) name = 'master',
config['partitions'] = int(config['partitions']) bind = '127.0.0.1:10000',
masters = '',
replicas = 0,
partitions = 100,
)
config = ConfigurationManager(
defaults,
options.file,
options.section or 'master',
arguments,
)
# setup custom logging # setup custom logging
setupLog(options.name or 'master', options.logfile or None, options.verbose) setupLog(config.getName(), options.logfile or None, options.verbose)
# and then, load and run the application # and then, load and run the application
from neo.master.app import Application from neo.master.app import Application
app = Application(**config) app = Application(config)
app.run() app.run()
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
from optparse import OptionParser from optparse import OptionParser
from neo import setupLog from neo import setupLog
from neo.util import bin from neo.config import ConfigurationManager
parser = OptionParser() parser = OptionParser()
...@@ -29,10 +29,11 @@ parser.add_option('-v', '--verbose', action = 'store_true', ...@@ -29,10 +29,11 @@ parser.add_option('-v', '--verbose', action = 'store_true',
parser.add_option('-u', '--uuid', help='specify an UUID to use for this ' \ parser.add_option('-u', '--uuid', help='specify an UUID to use for this ' \
'process. Previously assigned UUID takes precedence (ie ' \ 'process. Previously assigned UUID takes precedence (ie ' \
'you should always use -R with this switch)') 'you should always use -R with this switch)')
parser.add_option('-f', '--file', help = 'specify a configuration file')
parser.add_option('-s', '--section', help = 'specify a configuration section')
parser.add_option('-l', '--logfile', help = 'specify a logging file') parser.add_option('-l', '--logfile', help = 'specify a logging file')
parser.add_option('-R', '--reset', action = 'store_true', parser.add_option('-R', '--reset', action = 'store_true',
help = 'remove an existing database if any') help = 'remove an existing database if any')
parser.add_option('-n', '--name', help = 'the node name (impove logging)') parser.add_option('-n', '--name', help = 'the node name (impove logging)')
parser.add_option('-b', '--bind', help = 'the local address to bind to') parser.add_option('-b', '--bind', help = 'the local address to bind to')
parser.add_option('-c', '--cluster', help = 'the cluster name') parser.add_option('-c', '--cluster', help = 'the cluster name')
...@@ -40,20 +41,30 @@ parser.add_option('-m', '--masters', help = 'master node list') ...@@ -40,20 +41,30 @@ parser.add_option('-m', '--masters', help = 'master node list')
parser.add_option('-d', '--database', help = 'database connections string') parser.add_option('-d', '--database', help = 'database connections string')
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
config = { arguments = dict(
'uuid': options.uuid, uuid = options.uuid,
'bind': options.bind or '127.0.0.1:20000', bind = options.bind,
'cluster': options.cluster, cluster = options.cluster,
'masters': options.masters or '127.0.0.1:10000', masters = options.masters,
'database': options.database, database = options.database,
'reset': options.reset, reset = options.reset,
} )
config['uuid'] = bin(config['uuid']) defaults = dict(
name = 'storage',
bind = '127.0.0.1:20000',
masters = '127.0.0.1:10000',
)
config = ConfigurationManager(
defaults,
options.file,
options.section or 'storage',
arguments,
)
# setup custom logging # setup custom logging
setupLog(options.name or 'storage', options.logfile or None, options.verbose) setupLog(config.getName(), options.logfile or None, options.verbose)
# and then, load and run the application # and then, load and run the application
from neo.storage.app import Application from neo.storage.app import Application
app = Application(**config) app = Application(config)
app.run() app.run()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment