Commit 58774fb6 authored by Julien Muchembled's avatar Julien Muchembled

master: new option to automatically start a new cluster

parent 5a76664a
...@@ -100,3 +100,8 @@ class ConfigurationManager(object): ...@@ -100,3 +100,8 @@ class ConfigurationManager(object):
def getUpstreamMasters(self): def getUpstreamMasters(self):
return util.parseMasterList(self.__get('upstream_masters')) return util.parseMasterList(self.__get('upstream_masters'))
def getAutostart(self):
n = self.__get('autostart', True)
if n:
return int(n)
...@@ -56,6 +56,7 @@ class Application(object): ...@@ -56,6 +56,7 @@ class Application(object):
self.name = config.getCluster() self.name = config.getCluster()
self.server = config.getBind() self.server = config.getBind()
self.autostart = config.getAutostart()
self.storage_readiness = set() self.storage_readiness = set()
master_addresses, connector_name = config.getMasters() master_addresses, connector_name = config.getMasters()
......
...@@ -66,10 +66,12 @@ class RecoveryManager(MasterHandler): ...@@ -66,10 +66,12 @@ class RecoveryManager(MasterHandler):
node_list = [node for node in node_list if node.isPending()] node_list = [node for node in node_list if node.isPending()]
elif not all(node.isPending() for node in node_list): elif not all(node.isPending() for node in node_list):
continue continue
elif app._startup_allowed: elif app._startup_allowed or app.autostart:
# No partition table and admin allowed startup, we are # No partition table and admin allowed startup, we are
# creating a new cluster out of all pending nodes. # creating a new cluster out of all pending nodes.
node_list = app.nm.getStorageList(only_identified=True) node_list = app.nm.getStorageList(only_identified=True)
if not app._startup_allowed and len(node_list) < app.autostart:
continue
else: else:
continue continue
if node_list and not any(node.getConnection().isPending() if node_list and not any(node.getConnection().isPending()
......
...@@ -33,6 +33,10 @@ parser.add_option('-p', '--partitions', help = 'partitions number') ...@@ -33,6 +33,10 @@ parser.add_option('-p', '--partitions', help = 'partitions number')
parser.add_option('-l', '--logfile', help = 'specify a logging file') parser.add_option('-l', '--logfile', help = 'specify a logging file')
parser.add_option('-D', '--dynamic-master-list', help='path of the file ' parser.add_option('-D', '--dynamic-master-list', help='path of the file '
'containing dynamic master node list') 'containing dynamic master node list')
parser.add_option('-A', '--autostart',
help='minimum number of pending storage nodes to automatically start'
' new cluster (to avoid unwanted recreation of the cluster,'
' this should be the total number of storage nodes)')
parser.add_option('-C', '--upstream-cluster', parser.add_option('-C', '--upstream-cluster',
help='the name of cluster to backup') help='the name of cluster to backup')
parser.add_option('-M', '--upstream-masters', parser.add_option('-M', '--upstream-masters',
...@@ -55,6 +59,7 @@ def main(args=None): ...@@ -55,6 +59,7 @@ def main(args=None):
masters = options.masters, masters = options.masters,
replicas = options.replicas, replicas = options.replicas,
partitions = options.partitions, partitions = options.partitions,
autostart = options.autostart,
upstream_cluster = options.upstream_cluster, upstream_cluster = options.upstream_cluster,
upstream_masters = options.upstream_masters, upstream_masters = options.upstream_masters,
) )
......
...@@ -561,7 +561,7 @@ class NEOCluster(object): ...@@ -561,7 +561,7 @@ class NEOCluster(object):
adapter=os.getenv('NEO_TESTS_ADAPTER', 'SQLite'), adapter=os.getenv('NEO_TESTS_ADAPTER', 'SQLite'),
storage_count=None, db_list=None, clear_databases=True, storage_count=None, db_list=None, clear_databases=True,
db_user=DB_USER, db_password='', compress=True, db_user=DB_USER, db_password='', compress=True,
importer=None): importer=None, autostart=None):
self.name = 'neo_%s' % self._allocate('name', self.name = 'neo_%s' % self._allocate('name',
lambda: random.randint(0, 100)) lambda: random.randint(0, 100))
master_list = [MasterApplication.newAddress() master_list = [MasterApplication.newAddress()
...@@ -574,7 +574,8 @@ class NEOCluster(object): ...@@ -574,7 +574,8 @@ class NEOCluster(object):
self.upstream = weakref.proxy(upstream) self.upstream = weakref.proxy(upstream)
kw.update(getUpstreamCluster=upstream.name, kw.update(getUpstreamCluster=upstream.name,
getUpstreamMasters=parseMasterList(upstream.master_nodes)) getUpstreamMasters=parseMasterList(upstream.master_nodes))
self.master_list = [MasterApplication(address=x, **kw) self.master_list = [MasterApplication(getAutostart=autostart,
address=x, **kw)
for x in master_list] for x in master_list]
if db_list is None: if db_list is None:
if storage_count is None: if storage_count is None:
...@@ -647,20 +648,20 @@ class NEOCluster(object): ...@@ -647,20 +648,20 @@ class NEOCluster(object):
node.start() node.start()
self.tic() self.tic()
if fast_startup: if fast_startup:
self._startCluster() self.startCluster()
if storage_list is None: if storage_list is None:
storage_list = self.storage_list storage_list = self.storage_list
for node in storage_list: for node in storage_list:
node.start() node.start()
self.tic() self.tic()
if not fast_startup: if not fast_startup:
self._startCluster() self.startCluster()
self.tic() self.tic()
state = self.neoctl.getClusterState() state = self.neoctl.getClusterState()
assert state in (ClusterStates.RUNNING, ClusterStates.BACKINGUP), state assert state in (ClusterStates.RUNNING, ClusterStates.BACKINGUP), state
self.enableStorageList(storage_list) self.enableStorageList(storage_list)
def _startCluster(self): def startCluster(self):
try: try:
self.neoctl.startCluster() self.neoctl.startCluster()
except RuntimeError: except RuntimeError:
......
...@@ -840,5 +840,17 @@ class Test(NEOThreadedTest): ...@@ -840,5 +840,17 @@ class Test(NEOThreadedTest):
finally: finally:
cluster.stop() cluster.stop()
def testAutostart(self):
def startCluster():
getClusterState = cluster.neoctl.getClusterState
self.assertEqual(ClusterStates.RECOVERING, getClusterState())
cluster.storage_list[2].start()
cluster = NEOCluster(storage_count=3, autostart=3)
try:
cluster.startCluster = startCluster
cluster.start(cluster.storage_list[:2])
finally:
cluster.stop()
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
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