From 5683ed5163367cd4bc49fbf7069566f77f762eb4 Mon Sep 17 00:00:00 2001 From: Rodolphe Marques Date: Tue, 24 Jan 2017 15:59:02 +0100 Subject: [PATCH] Added mongodb admin commands to add and remove members from the replicaset --- bigchaindb/backend/admin.py | 10 +++++ bigchaindb/backend/mongodb/admin.py | 59 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 bigchaindb/backend/mongodb/admin.py diff --git a/bigchaindb/backend/admin.py b/bigchaindb/backend/admin.py index 057b5995..1a57c8a4 100644 --- a/bigchaindb/backend/admin.py +++ b/bigchaindb/backend/admin.py @@ -20,3 +20,13 @@ def set_shards(connection, *, shards): @singledispatch def set_replicas(connection, *, replicas): raise NotImplementedError + + +@singledispatch +def add_replicas(connection, *, replicas): + raise NotImplementedError + + +@singledispatch +def remove_replicas(connection, *, replicas): + raise NotImplementedError diff --git a/bigchaindb/backend/mongodb/admin.py b/bigchaindb/backend/mongodb/admin.py new file mode 100644 index 00000000..b41021e9 --- /dev/null +++ b/bigchaindb/backend/mongodb/admin.py @@ -0,0 +1,59 @@ +"""Database configuration functions.""" +import logging + +from bigchaindb.backend import admin +from bigchaindb.backend.utils import module_dispatch_registrar +from bigchaindb.backend.mongodb.connection import MongoDBConnection + +logger = logging.getLogger(__name__) + +register_admin = module_dispatch_registrar(admin) + + +@register_admin(MongoDBConnection) +def add_replicas(connection, replicas): + """Add a set of replicas to the replicaset + + Args: + replicas list of strings: of the form "hostname:port". + """ + # get current configuration + conf = connection.conn.admin.command('replSetGetConfig') + + # MongoDB does not automatically add and id for the members so we need + # to chose one that does not exists yet. The safest way is to use + # incrementing ids, so we first check what is the highest id already in + # the set and continue from there. + cur_id = max([member['_id'] for member in conf['config']['members']]) + + # add the nodes to the members list of the replica set + for replica in replicas: + cur_id += 1 + conf['config']['members'].append({'_id': cur_id, 'host': replica}) + + # increase the configuration version number + conf['config']['version'] += 1 + + # apply new configuration + return connection.conn.admin.command('replSetReconfig', conf['config']) + + +@register_admin(MongoDBConnection) +def remove_replicas(connection, replicas): + """Remove a set of replicas from the replicaset + + """ + # get the current configuration + conf = connection.conn.admin.command('replSetGetConfig') + + # remove the nodes from the members list in the replica set + conf['config']['members'] = list( + filter(lambda member: member['host'] not in replicas, + conf['config']['members']) + ) + + # increase the configuration version number + conf['config']['version'] += 1 + + # apply new configuration + return connection.conn.admin.command('replSetReconfig', conf['config'])