def member_add(self, member_id=None, params=None):
        """add new member into existing configuration"""
        member_id = member_id or str(uuid4())
        if 'members' in params:
            # is replica set
            rs_params = params.copy()
            # Turn 'rs_id' -> 'id', to be consistent with 'server_id' below.
            rs_params['id'] = rs_params.pop('rs_id', None)
            rs_params.update({'sslParams': self.sslParams})

            rs_params['version'] = params.pop('version', self._version)
            rs_params['members'] = map(self._strip_auth, rs_params['members'])
            rs_id = ReplicaSets().create(rs_params)
            members = ReplicaSets().members(rs_id)
            cfgs = rs_id + r"/" + ','.join([item['host'] for item in members])
            result = self._add(cfgs, member_id)
            if result.get('ok', 0) == 1:
                self._shards[result['shardAdded']] = {'isReplicaSet': True, '_id': rs_id}
                # return self._shards[result['shardAdded']].copy()
                return self.member_info(member_id)

        else:
            # is single server
            params.update({'autostart': True, 'sslParams': self.sslParams})
            params = params.copy()
            params['procParams'] = self._strip_auth(
                params.get('procParams', {}))
            params.setdefault('version', self._version)
            logger.debug("servers create params: {params}".format(**locals()))
            server_id = Servers().create('mongod', **params)
            result = self._add(Servers().hostname(server_id), member_id)
            if result.get('ok', 0) == 1:
                self._shards[result['shardAdded']] = {'isServer': True, '_id': server_id}
                return self.member_info(member_id)
Example #2
0
def member_del(rs_id, member_id):
    logger.debug("member_del({rs_id}), {member_id}".format(**locals()))
    member_id = int(member_id)
    if rs_id not in ReplicaSets():
        return send_result(404)
    result = ReplicaSets().member_del(rs_id, member_id)
    return send_result(204, result)
Example #3
0
def rs_member_primary(rs_id):
    logger.debug("rs_member_primary({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    result = ReplicaSets().primary(rs_id)
    result['links'] = _build_member_links(rs_id, result)
    result['links'].extend(
        _build_member_parent_links(rs_id, 'get-replica-set-primary'))
    return send_result(200, result)
Example #4
0
def member_info(rs_id, member_id):
    logger.debug("member_info({rs_id}, {member_id})".format(**locals()))
    member_id = int(member_id)
    if rs_id not in ReplicaSets():
        return send_result(404)
    result = ReplicaSets().member_info(rs_id, member_id)
    result['links'] = _build_member_links(rs_id, result)
    result['links'].extend(_build_member_parent_links(rs_id))
    return send_result(200, result)
Example #5
0
def _rs_create(params):
    rs_id = ReplicaSets().create(params)
    result = ReplicaSets().info(rs_id)
    result['links'] = all_replica_set_links(rs_id)
    # Add GET link to corresponding Server resource.
    for member in result['members']:
        member['links'] = [
            server_link('get-server-info', server_id=member['server_id']),
            replica_set_link('get-replica-set-member-info', rs_id,
                             member['_id'])
        ]
    return result
Example #6
0
def members(rs_id):
    logger.debug("members({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    member_docs = []
    for member_info in ReplicaSets().members(rs_id):
        member_info['links'] = _build_member_links(rs_id, member_info)
        member_docs.append(member_info)
    result = {
        'members': member_docs,
        'links': _build_member_parent_links(rs_id, 'get-replica-set-members')
    }
    return send_result(200, result)
Example #7
0
def member_add(rs_id):
    logger.debug("member_add({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    data = get_json(request.body)
    member_id = ReplicaSets().member_add(rs_id, data)
    result = ReplicaSets().member_info(rs_id, member_id)
    result['links'] = _build_member_links(rs_id, result)
    result['links'].extend(
        _build_member_parent_links(rs_id, 'add-replica-set-member'))
    result['links'].append(
        replica_set_link('add-replica-set-member', self_rel=True))
    return send_result(200, result)
Example #8
0
def rs_info(rs_id):
    logger.debug("rs_info({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    result = ReplicaSets().info(rs_id)
    result['links'] = all_replica_set_links(rs_id, 'get-replica-set-info')
    for member in result['members']:
        member['links'] = [
            server_link('get-server-info', server_id=member['server_id']),
            replica_set_link('get-replica-set-member-info', rs_id,
                             member['_id'])
        ]
    return send_result(200, result)
Example #9
0
def servers(rs_id):
    logger.debug("hosts({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    server_docs = []
    for server_info in ReplicaSets().servers(rs_id):
        server_info['links'] = _build_member_links(rs_id, server_info)
        server_docs.append(server_info)
    result = {
        'servers': server_docs,
        'links': _build_member_parent_links(rs_id, 'get-replica-set-servers')
    }
    return send_result(200, result)
def member_update(rs_id, member_id):
    logger.debug("member_update({rs_id}, {member_id})".format(**locals()))
    member_id = int(member_id)
    if rs_id not in ReplicaSets():
        return send_result(404)
    data = get_json(request.body)
    ReplicaSets().member_update(rs_id, member_id, data)
    result = ReplicaSets().member_info(rs_id, member_id)
    result['links'] = _build_member_links(rs_id, result)
    result['links'].extend(_build_member_parent_links(rs_id))
    result['links'].append(replica_set_link(
        'update-replica-set-member-config', rs_id, member_id, self_rel=True))
    return send_result(200, result)
Example #11
0
def arbiters(rs_id):
    logger.debug("arbiters({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    arbiter_docs = []
    for arbiter_info in ReplicaSets().arbiters(rs_id):
        arbiter_info['links'] = _build_member_links(rs_id, arbiter_info)
        arbiter_docs.append(arbiter_info)
    result = {
        'arbiters': arbiter_docs,
        'links': _build_member_parent_links(rs_id, 'get-replica-set-arbiters')
    }
    return send_result(200, result)
Example #12
0
def rs_command(rs_id):
    logger.debug("rs_command({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    command = get_json(request.body).get('action')
    if command is None:
        raise RequestError('Expected body with an {"action": ...}.')
    result = {
        'command_result': ReplicaSets().command(rs_id, command),
        'links': all_replica_set_links(rs_id, 'replica-set-command')
    }
    result['links'].append(
        replica_set_link('replica-set-command', self_rel=True))
    return send_result(200, result)
def hidden(rs_id):
    logger.debug("hidden({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    hidden_docs = []
    for hidden_info in ReplicaSets().hidden(rs_id):
        hidden_info['links'] = _build_member_links(rs_id, hidden_info)
        hidden_docs.append(hidden_info)
    result = {
        'hidden': hidden_docs,
        'links': _build_member_parent_links(
            rs_id, 'get-replica-set-hidden-members')
    }
    return send_result(200, result)
def passives(rs_id):
    logger.debug("passives({rs_id})".format(**locals()))
    if rs_id not in ReplicaSets():
        return send_result(404)
    passive_docs = []
    for passive_info in ReplicaSets().passives(rs_id):
        passive_info['links'] = _build_member_links(rs_id, passive_info)
        passive_docs.append(passive_info)
    result = {
        'passives': passive_docs,
        'links': _build_member_parent_links(
            rs_id, 'get-replica-set-passive-members')
    }
    return send_result(200, result)
    def test_reset(self):
        all_hosts = []

        # Start a ShardedCluster with 1 router and 1 config server.
        self.sh = ShardedCluster({})
        # Add 1 Server shard and 1 ReplicaSet shard.
        server_id = self.sh.member_add(params={})['_id']
        all_hosts.append(Servers().hostname(server_id))
        repl_id = self.sh.member_add(params={'members': [{}, {}, {}]})['_id']

        # Shut down the standalone.
        Servers().command(server_id, 'stop')
        # Shut down each member of the replica set.
        server_ids = [m['server_id'] for m in ReplicaSets().members(repl_id)]
        for s_id in server_ids:
            Servers().command(s_id, 'stop')
            all_hosts.append(Servers().hostname(s_id))
        # Shut down config server and router.
        config_id = self.sh.configsvrs[0]['id']
        print("config_id=%r" % config_id)
        all_hosts.append(Servers().hostname(config_id))
        router_id = self.sh.routers[0]['id']
        print("router_id=%r" % router_id)
        all_hosts.append(Servers().hostname(router_id))
        Servers().command(config_id, 'stop')
        Servers().command(router_id, 'stop')

        # Reset the ShardedCluster.
        self.sh.reset()
        # Everything is up.
        for host in all_hosts:
            # No ConnectionFailure/AutoReconnect.
            pymongo.MongoClient(host)
    def router_add(self, params):
        """add new router (mongos) into existing configuration"""
        if self.uses_rs_configdb:
            # Replica set configdb.
            rs_id = self._configsvrs[0]
            config_members = ReplicaSets().members(rs_id)
            configdb = '%s/%s' % (rs_id, ','.join(m['host']
                                                  for m in config_members))
        else:
            configdb = ','.join(Servers().hostname(item)
                                for item in self._configsvrs)
        server_id = params.pop('server_id', None)
        version = params.pop('version', self._version)
        params.update({'configdb': configdb})

        if self.enable_ipv6:
            common.enable_ipv6_single(params)
        # Remove flags that turn auth on.
        params = self._strip_auth(params)

        self._routers.append(Servers().create('mongos',
                                              params,
                                              sslParams=self.sslParams,
                                              autostart=True,
                                              version=version,
                                              server_id=server_id))
        return {
            'id': self._routers[-1],
            'hostname': Servers().hostname(self._routers[-1])
        }
 def reset(self):
     """Ensure all shards, configs, and routers are running and available."""
     # Ensure all shards by calling "reset" on each.
     for shard_id in self._shards:
         if self._shards[shard_id].get('isReplicaSet'):
             singleton = ReplicaSets()
         elif self._shards[shard_id].get('isServer'):
             singleton = Servers()
         singleton.command(self._shards[shard_id]['_id'], 'reset')
     # Ensure all config servers by calling "reset" on each.
     for config_id in self._configsvrs:
         self.configdb_singleton.command(config_id, 'reset')
     # Ensure all routers by calling "reset" on each.
     for router_id in self._routers:
         Servers().command(router_id, 'reset')
     return self.info()
 def reset(self):
     """Ensure all shards, configs, and routers are running and available."""
     # Ensure all shards by calling "reset" on each.
     for shard_id in self._shards:
         if self._shards[shard_id].get('isReplicaSet'):
             singleton = ReplicaSets()
         elif self._shards[shard_id].get('isServer'):
             singleton = Servers()
         singleton.command(self._shards[shard_id]['_id'], 'reset')
     # Ensure all config servers by calling "reset" on each.
     for config_id in self._configsvrs:
         Servers().command(config_id, 'reset')
     # Ensure all routers by calling "reset" on each.
     for router_id in self._routers:
         Servers().command(router_id, 'reset')
     return self.info()
    def member_add(self, member_id=None, params=None):
        """add new member into existing configuration"""
        member_id = member_id or str(uuid4())
        if 'members' in params:
            # is replica set
            rs_params = params.copy()
            rs_params.update({'auth_key': self.auth_key})
            rs_params.update({'sslParams': self.sslParams})
            if self.login and self.password:
                rs_params.update({
                    'login': self.login,
                    'password': self.password
                })
            if self._version:
                rs_params['version'] = self._version
            rs_id = ReplicaSets().create(rs_params)
            members = ReplicaSets().members(rs_id)
            cfgs = rs_id + r"/" + ','.join([item['host'] for item in members])
            result = self._add(cfgs, member_id)
            if result.get('ok', 0) == 1:
                self._shards[result['shardAdded']] = {
                    'isReplicaSet': True,
                    '_id': rs_id
                }
                # return self._shards[result['shardAdded']].copy()
                return self.member_info(member_id)

        else:
            # is single server
            params.update({
                'autostart': True,
                'auth_key': self.auth_key,
                'sslParams': self.sslParams
            })
            params['procParams'] = params.get('procParams', {})
            if self._version:
                params['version'] = self._version
            logger.debug("servers create params: {params}".format(**locals()))
            server_id = Servers().create('mongod', **params)
            result = self._add(Servers().hostname(server_id), member_id)
            if result.get('ok', 0) == 1:
                self._shards[result['shardAdded']] = {
                    'isServer': True,
                    '_id': server_id
                }
                # return self._shards[result['shardAdded']]
                return self.member_info(member_id)
Example #20
0
 def configsvrs(self):
     """return list of config servers"""
     if self.uses_rs_configdb:
         rs_id = self._configsvrs[0]
         mongodb_uri = ReplicaSets().info(rs_id)['mongodb_uri']
         return [{'id': rs_id, 'mongodb_uri': mongodb_uri}]
     return [{'id': h_id, 'hostname': Servers().hostname(h_id)}
             for h_id in self._configsvrs]
 def _remove(self, shard_name):
     """remove member from configuration"""
     result = self.router_command("removeShard", shard_name, is_eval=False)
     if result['ok'] == 1 and result['state'] == 'completed':
         shard = self._shards.pop(shard_name)
         if shard.get('isServer', False):
             Servers().remove(shard['_id'])
         if shard.get('isReplicaSet', False):
             ReplicaSets().remove(shard['_id'])
     return result
 def __init_configrs(self, rs_cfg):
     """Create and start a config replica set."""
     # Use 'rs_id' to set the id for consistency, but need to rename
     # to 'id' to use with ReplicaSets.create()
     rs_cfg['id'] = rs_cfg.pop('rs_id', None)
     for member in rs_cfg.setdefault('members', [{}]):
         member['procParams'] = self._strip_auth(
             member.get('procParams', {}))
         member['procParams']['configsvr'] = True
     rs_cfg['sslParams'] = self.sslParams
     self._configsvrs.append(ReplicaSets().create(rs_cfg))
    def cleanup(self):
        """cleanup configuration: stop and remove all servers"""
        for _id, shard in self._shards.items():
            if shard.get('isServer', False):
                Servers().remove(shard['_id'])
            if shard.get('isReplicaSet', False):
                ReplicaSets().remove(shard['_id'])

        for mongos in self._routers:
            Servers().remove(mongos)

        for config_id in self._configsvrs:
            self.configdb_singleton.remove(config_id)

        self._configsvrs = []
        self._routers = []
        self._shards = {}
def rs_list():
    logger.debug("rs_list()")
    replica_sets = []
    for rs_id in ReplicaSets():
        repl_info = {'id': rs_id}
        repl_info['links'] = all_replica_set_links(rs_id, 'get-replica-sets')
        replica_sets.append(repl_info)
    response = {'links': [
        base_link('service'),
        base_link('get-releases'),
        sharded_cluster_link('get-sharded-clusters'),
        replica_set_link('get-replica-sets', self_rel=True),
        replica_set_link('add-replica-set'),
        server_link('get-servers')
    ]}
    response['replica_sets'] = replica_sets
    return send_result(200, response)
Example #25
0
class ReplicaSetsTestCase(unittest.TestCase):
    def setUp(self):
        PortPool().change_range()
        self.rs = ReplicaSets()

    def tearDown(self):
        self.rs.cleanup()

    def waiting(self, fn, timeout=300, sleep=10):
        t_start = time.time()
        while not fn():
            if time.time() - t_start > timeout:
                return False
            time.sleep(sleep)
        return True

    def test_singleton(self):
        self.assertEqual(id(self.rs), id(ReplicaSets()))

    def test_bool(self):
        self.assertEqual(False, bool(self.rs))
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.assertEqual(True, bool(self.rs))

    def test_operations(self):
        repl_cfg = {'members': [{}, {}]}
        repl = ReplicaSet(repl_cfg)

        self.assertEqual(len(self.rs), 0)
        operator.setitem(self.rs, 1, repl)
        self.assertEqual(len(self.rs), 1)
        self.assertEqual(operator.getitem(self.rs, 1).repl_id, repl.repl_id)
        operator.delitem(self.rs, 1)
        self.assertEqual(len(self.rs), 0)
        self.assertRaises(KeyError, operator.getitem, self.rs, 1)

    def test_operations2(self):
        self.assertTrue(len(self.rs) == 0)
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.rs.create({'id': 'test-rs-2', 'members': [{}, {}]})
        self.assertTrue(len(self.rs) == 2)
        for key in self.rs:
            self.assertTrue(key in ('test-rs-1', 'test-rs-2'))
        for key in ('test-rs-1', 'test-rs-2'):
            self.assertTrue(key in self.rs)

    def test_cleanup(self):
        self.assertTrue(len(self.rs) == 0)
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.rs.create({'id': 'test-rs-2', 'members': [{}, {}]})
        self.assertTrue(len(self.rs) == 2)
        self.rs.cleanup()
        self.assertTrue(len(self.rs) == 0)

    def test_rs_new(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        repl_id = self.rs.create({
            'id':
            'test-rs-1',
            'members': [{
                "procParams": {
                    "port": port1
                }
            }, {
                "procParams": {
                    "port": port2
                }
            }]
        })
        self.assertEqual(repl_id, 'test-rs-1')
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        c = pymongo.MongoClient([server1, server2], replicaSet=repl_id)
        self.assertEqual(c.admin.eval("rs.conf()")['_id'], repl_id)
        c.close()

    def test_rs_new_with_auth(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        repl_id = self.rs.create({
            'id':
            'test-rs-1',
            'auth_key':
            'sercret',
            'login':
            '******',
            'password':
            '******',
            'members': [{
                "procParams": {
                    "port": port1
                }
            }, {
                "procParams": {
                    "port": port2
                }
            }]
        })
        self.assertEqual(repl_id, 'test-rs-1')
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        c = pymongo.MongoClient([server1, server2], replicaSet=repl_id)
        self.assertRaises(pymongo.errors.OperationFailure,
                          c.admin.collection_names)
        self.assertTrue(c.admin.authenticate('admin', 'admin'))
        self.assertTrue(isinstance(c.admin.collection_names(), list))
        c.admin.logout()
        self.assertRaises(pymongo.errors.OperationFailure,
                          c.admin.collection_names)
        c.close()

    def test_info(self):
        repl_id = self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        info = self.rs.info(repl_id)
        self.assertTrue(isinstance(info, dict))
        for item in ("id", "mongodb_uri", "members", "orchestration"):
            self.assertTrue(item in info)

        self.assertEqual(info['id'], repl_id)
        self.assertEqual(len(info['members']), 2)
        mongodb_uri = info['mongodb_uri']
        for member in self.rs.members(repl_id):
            self.assertIn(member['host'], mongodb_uri)
        self.assertTrue(mongodb_uri.find('mongodb://') == 0)
        self.assertEqual(info['orchestration'], 'replica_sets')

    def test_info_with_auth(self):
        repl_id = self.rs.create({
            'id': 'test-rs-1',
            'login': '******',
            'password': '******',
            'members': [{}, {}]
        })
        info = self.rs.info(repl_id)
        self.assertTrue(isinstance(info, dict))
        self.assertEqual(info['id'], repl_id)
        self.assertEqual(len(info['members']), 2)

    def test_primary(self):
        repl_id = self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        primary = self.rs.primary(repl_id)['mongodb_uri']
        c = connected(pymongo.MongoClient(primary))
        self.assertTrue(c.is_primary)
        c.close()

    def test_primary_stepdown(self):
        # This tests Server, but only makes sense in the context of a replica set.
        repl_id = self.rs.create({
            'id':
            'test-rs-stepdown',
            'members': [{}, {}, {
                "rsParams": {
                    "priority": 1.4
                }
            }]
        })
        primary = self.rs.primary(repl_id)
        primary_server = Servers()._storage[primary['server_id']]
        # No Exception.
        primary_server.stepdown()
        self.assertNotEqual(primary['mongodb_uri'],
                            self.rs.primary(repl_id)['mongodb_uri'])

    def test_rs_del(self):
        self.rs.create({'members': [{}, {}]})
        repl_id = self.rs.create({'members': [{}, {}]})
        self.assertEqual(len(self.rs), 2)
        primary = self.rs.primary(repl_id)['mongodb_uri']
        connected(pymongo.MongoClient(primary))  # No error.
        self.rs.remove(repl_id)
        self.assertEqual(len(self.rs), 1)
        with self.assertRaises(pymongo.errors.PyMongoError):
            connected(pymongo.MongoClient(primary))

    def test_members(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        repl_id = self.rs.create({
            'members': [{
                "procParams": {
                    "port": port1
                }
            }, {
                "procParams": {
                    "port": port2
                }
            }]
        })
        members = self.rs.members(repl_id)
        self.assertEqual(len(members), 2)
        self.assertTrue(server1 in [member['host'] for member in members])
        self.assertTrue(server2 in [member['host'] for member in members])

    def test_secondaries(self):
        repl_id = self.rs.create(
            {'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}, {}]})
        secondaries = self.rs.secondaries(repl_id)
        self.assertEqual(len(secondaries), 2)

    def test_arbiters(self):
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}, {
                "rsParams": {
                    "arbiterOnly": True
                }
            }]
        })
        arbiters = self.rs.arbiters(repl_id)
        self.assertEqual(len(arbiters), 1)

    def test_hidden(self):
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}, {
                "rsParams": {
                    "priority": 0,
                    "hidden": True
                }
            }]
        })
        hidden = self.rs.hidden(repl_id)
        self.assertEqual(len(hidden), 1)

    def test_passives(self):
        config = {
            "members": [{}, {
                "rsParams": {
                    "priority": 0
                }
            }, {
                "rsParams": {
                    "arbiterOnly": True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'hidden': True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'slaveDelay': 5
                }
            }]
        }
        repl_id = self.rs.create(config)
        passives = self.rs.passives(repl_id)
        self.assertEqual(len(passives), 1)

    def test_servers(self):
        config = {
            "members": [{}, {
                "rsParams": {
                    "priority": 0
                }
            }, {
                "rsParams": {
                    "arbiterOnly": True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'hidden': True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'slaveDelay': 5
                }
            }]
        }
        repl_id = self.rs.create(config)
        servers = self.rs.servers(repl_id)
        self.assertEqual(len(servers), 1)

    def test_compare_passives_and_servers(self):
        config = {
            "members": [{}, {
                "rsParams": {
                    "priority": 0
                }
            }, {
                "rsParams": {
                    "arbiterOnly": True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'hidden': True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    'slaveDelay': 5
                }
            }]
        }

        repl_id = self.rs.create(config)
        passives = [server['host'] for server in self.rs.passives(repl_id)]
        servers = [server['host'] for server in self.rs.servers(repl_id)]
        for item in passives:
            self.assertTrue(item not in servers)

        for item in servers:
            self.assertTrue(item not in passives)

    def test_member_info(self):
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {
                "rsParams": {
                    "arbiterOnly": True
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    "hidden": True
                }
            }]
        })
        info = self.rs.member_info(repl_id, 0)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 0)
        self.assertTrue(info['statuses']['primary'])

        info = self.rs.member_info(repl_id, 1)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 1)
        self.assertTrue(info['rsInfo']['arbiterOnly'])

        info = self.rs.member_info(repl_id, 2)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 2)
        self.assertTrue(info['rsInfo']['hidden'])

    def test_tagging(self):
        tags_0 = {"status": "primary"}
        tags_1 = {"status": "arbiter"}
        tags_2 = {"status": "hidden"}
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 1.5,
                    "tags": tags_0
                }
            }, {
                "rsParams": {
                    "arbiterOnly": True
                },
                "tags": tags_1
            }, {
                "rsParams": {
                    "priority": 0,
                    "hidden": True,
                    "tags": tags_2
                }
            }]
        })
        self.assertEqual(tags_0, self.rs.primary(repl_id)['rsInfo']['tags'])

        member_arbiter = self.rs.arbiters(repl_id)[0]['_id']
        self.assertFalse(
            'tags' in self.rs.member_info(repl_id, member_arbiter)['rsInfo'])

        member_hidden = self.rs.hidden(repl_id)[0]['_id']
        self.assertTrue(
            'tags' in self.rs.member_info(repl_id, member_hidden)['rsInfo'])

    def test_member_del(self):
        repl_id = self.rs.create(
            {'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}, {}]})
        self.assertEqual(len(self.rs.members(repl_id)), 3)
        secondary = self.rs.secondaries(repl_id)[0]
        connected(pymongo.MongoClient(secondary['host']))  # No error.
        self.assertTrue(self.rs.member_del(repl_id, secondary['_id']))
        self.assertEqual(len(self.rs.members(repl_id)), 2)
        with self.assertRaises(pymongo.errors.PyMongoError):
            connected(pymongo.MongoClient(secondary['host']))

    def test_member_add(self):
        repl_id = self.rs.create(
            {'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}]})
        self.assertEqual(len(self.rs.members(repl_id)), 2)
        member_id = self.rs.member_add(
            repl_id, {"rsParams": {
                "priority": 0,
                "hidden": True
            }})
        self.assertEqual(len(self.rs.members(repl_id)), 3)
        info = self.rs.member_info(repl_id, member_id)
        self.assertTrue(info['rsInfo']['hidden'])

    def test_member_command(self):
        _id = 1
        repl_id = self.rs.create(
            {'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {}]})
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'stop')
        self.assertFalse(
            self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'start')
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'restart')
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])

    def test_member_freeze(self):
        # This tests Server, but only makes sense in the context of a replica set.
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 19
                }
            }, {
                "rsParams": {
                    "priority": 5
                }
            }, {}]
        })
        next_primary_info = self.rs.member_info(repl_id, 2)
        next_primary = next_primary_info['mongodb_uri']
        secondary_info = self.rs.member_info(repl_id, 1)
        secondary_server = Servers()._storage[secondary_info['server_id']]
        primary_info = self.rs.member_info(repl_id, 0)
        primary_server = Servers()._storage[primary_info['server_id']]

        assert_eventually(lambda: primary_server.connection.is_primary)

        def freeze_and_stop():
            self.assertTrue(secondary_server.freeze(10))
            try:
                # Call replSetStepDown before killing the primary's process.
                # This raises OperationFailure if no secondaries are capable
                # of taking over.
                primary_server.connection.admin.command('replSetStepDown', 10)
            except pymongo.errors.AutoReconnect:
                # Have to stop the server as well so it doesn't get reelected.
                primary_server.stop()
                return True
            except pymongo.errors.OperationFailure:
                # No secondaries within 10 seconds of my optime...
                return False

        assert_eventually(freeze_and_stop, "Primary didn't step down.")
        assert_eventually(
            lambda: (self.rs.primary(repl_id)['mongodb_uri'] == next_primary),
            "Secondary did not freeze.",
            max_tries=120)
        assert_eventually(
            lambda: (self.rs.primary(repl_id)['mongodb_uri'] == self.rs.
                     member_info(repl_id, 1)['mongodb_uri']),
            "Higher priority secondary never promoted.")

    def test_member_update(self):
        repl_id = self.rs.create({
            'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    "hidden": True
                }
            }, {}]
        })
        hidden = self.rs.hidden(repl_id)[0]
        self.assertTrue(
            self.rs.member_info(repl_id, hidden['_id'])['rsInfo']['hidden'])
        self.rs.member_update(repl_id, hidden['_id'],
                              {"rsParams": {
                                  "priority": 1,
                                  "hidden": False
                              }})
        self.assertEqual(len(self.rs.hidden(repl_id)), 0)
        self.assertFalse(
            self.rs.member_info(repl_id,
                                hidden['_id'])['rsInfo'].get('hidden', False))

    def test_member_update_with_auth(self):
        repl_id = self.rs.create({
            'login':
            '******',
            'password':
            '******',
            'members': [{
                "rsParams": {
                    "priority": 1.5
                }
            }, {
                "rsParams": {
                    "priority": 0,
                    "hidden": True
                }
            }, {}]
        })
        hidden = self.rs.hidden(repl_id)[0]
        self.assertTrue(
            self.rs.member_info(repl_id, hidden['_id'])['rsInfo']['hidden'])
        self.rs.member_update(repl_id, hidden['_id'],
                              {"rsParams": {
                                  "priority": 1,
                                  "hidden": False
                              }})
        self.assertEqual(len(self.rs.hidden(repl_id)), 0)
        self.assertFalse(
            self.rs.member_info(repl_id,
                                hidden['_id'])['rsInfo'].get('hidden', False))
 def set_settings(self, releases=None, default_release=None):
     """set path to storage"""
     super(ShardedClusters, self).set_settings(releases, default_release)
     ReplicaSets().set_settings(releases, default_release)
Example #27
0
    Route('/replica_sets', method='GET'): rs_list,
    Route('/replica_sets/<rs_id>', method='GET'): rs_info,
    Route('/replica_sets/<rs_id>', method='POST'): rs_command,
    Route('/replica_sets/<rs_id>', method='PUT'): rs_create_by_id,
    Route('/replica_sets/<rs_id>', method='DELETE'): rs_del,
    Route('/replica_sets/<rs_id>/members', method='POST'): member_add,
    Route('/replica_sets/<rs_id>/members', method='GET'): members,
    Route('/replica_sets/<rs_id>/secondaries', method='GET'): secondaries,
    Route('/replica_sets/<rs_id>/arbiters', method='GET'): arbiters,
    Route('/replica_sets/<rs_id>/hidden', method='GET'): hidden,
    Route('/replica_sets/<rs_id>/passives', method='GET'): passives,
    Route('/replica_sets/<rs_id>/servers', method='GET'): servers,
    Route('/replica_sets/<rs_id>/primary', method='GET'): rs_member_primary,
    Route('/replica_sets/<rs_id>/members/<member_id>',
          method='GET'): member_info,
    Route('/replica_sets/<rs_id>/members/<member_id>',
          method='DELETE'): member_del,
    Route('/replica_sets/<rs_id>/members/<member_id>',
          method='PATCH'): member_update
}

setup_versioned_routes(ROUTES, version='v1')
# Assume v1 if no version is specified.
setup_versioned_routes(ROUTES)


if __name__ == '__main__':
    rs = ReplicaSets()
    rs.set_settings()
    run(host='localhost', port=8889, debug=True, reloader=False)
    def __init__(self, params):
        """init configuration acording params"""
        self.id = params.get('id', None) or str(uuid4())
        self.admin_added = False
        self.login = params.get('login', '')
        self.password = params.get('password', '')
        self.auth_key = params.get('auth_key', None)
        self.auth_source = params.get('authSource', 'admin')
        self._version = params.get('version')
        self._configsvrs = []
        self._routers = []
        self._shards = {}
        self.tags = {}

        self.sslParams = params.get('sslParams', {})
        self.kwargs = {}
        self.restart_required = self.login or self.auth_key
        self.x509_extra_user = False

        if self.sslParams:
            self.kwargs.update(DEFAULT_SSL_OPTIONS)

        self.enable_ipv6 = common.ipv6_enabled_sharded(params)
        # Determine what to do with config servers via mongos version.
        mongos_name = os.path.join(Servers().bin_path(self._version), 'mongos')
        mongos = Server(name=mongos_name, procParams={})
        mongos_version = mongos.version
        mongos.cleanup()
        configsvr_configs = params.get('configsvrs', [{}])
        self.uses_rs_configdb = (mongos_version >= (3, 1, 2)
                                 and len(configsvr_configs) == 1)
        self.configdb_singleton = (ReplicaSets()
                                   if self.uses_rs_configdb else Servers())
        if self.uses_rs_configdb:
            self.__init_configrs(configsvr_configs[0])
        elif mongos_version >= (3, 3, 2):
            raise ShardedClusterError(
                'mongos >= 3.3.2 requires the config database to be backed by '
                'a replica set.')
        elif mongos_version >= (3, 1, 2) and len(configsvr_configs) != 3:
            raise ShardedClusterError(
                "mongos >= 3.1.2 needs a config replica set or 3 old-style "
                "config servers.")
        else:
            self.__init_configsvrs(configsvr_configs)

        for r in params.get('routers', [{}]):
            self.router_add(r)
        for cfg in params.get('shards', []):
            shard_params = cfg.get('shardParams', {})
            shard_tags = shard_params.pop('tags', None)
            info = self.member_add(cfg.get('id', None), shard_params)
            if shard_tags:
                self.tags[info['id']] = shard_tags

        # SERVER-37631 changed 3.6 sharded cluster setup so that it's required
        # to run refreshLogicalSessionCacheNow on the config server followed by
        # each mongos. Only then will each 3.6 mongos correctly report
        # logicalSessionTimeoutMinutes in its isMaster responses.
        if mongos_version[:2] == (3, 6):
            router_clients = self.router_connections()
            is_master = router_clients[0].admin.command('isMaster')
            if 'logicalSessionTimeoutMinutes' not in is_master:
                self.config_connection().admin.command(
                    'refreshLogicalSessionCacheNow')
                for client in router_clients:
                    client.admin.command('refreshLogicalSessionCacheNow')

        if self.tags:
            for sh_id in self.tags:
                logger.debug('Add tags %r to %s' % (self.tags[sh_id], sh_id))
                db = self.connection().get_database(
                    'config',
                    write_concern=write_concern.WriteConcern(fsync=True))
                db.shards.update(
                    {'_id': sh_id},
                    {'$addToSet': {
                        'tags': {
                            '$each': self.tags[sh_id]
                        }
                    }})

        shard_configs = [
            s.get('shardParams', {}).get('procParams', {})
            for s in params.get('shards', [])
        ]
        if self.login:
            # Do we need to add an extra x509 user?
            def only_x509(config):
                set_params = config.get('setParameter', {})
                auth_mechs = set_params.get('authenticationMechanisms', '')
                auth_mechs = auth_mechs.split(',')
                if len(auth_mechs) == 1 and auth_mechs[0] == 'MONGODB-X509':
                    return True
                return False

            any_only_x509 = lambda l: any(map(only_x509, l))
            rs_shard_configs = [
                m.get('procParams', {}) for s in params.get('shards', [])
                for m in s.get('shardParams', {}).get('members', [])
            ]
            router_configs = params.get('routers', [])

            self.x509_extra_user = (any_only_x509(configsvr_configs)
                                    or any_only_x509(shard_configs)
                                    or any_only_x509(rs_shard_configs)
                                    or any_only_x509(router_configs))

            self._add_users(
                self.connection().get_database(
                    self.auth_source,
                    write_concern=write_concern.WriteConcern(fsync=True)),
                mongos_version)

            # Secondary user given from request.
            secondary_login = {
                'name': self.login,
                'roles': self._user_roles(self.connection())
            }
            if self.password:
                secondary_login['password'] = self.password

            if mongos_version >= (3, 7, 2):
                secondary_login['mechanisms'] = ['SCRAM-SHA-1']
            # Do the same for the shards.
            for shard_id, config in zip(self._shards, shard_configs):
                shard = self._shards[shard_id]
                instance_id = shard['_id']
                if shard.get('isServer'):
                    client = Servers()._storage[instance_id].connection
                elif shard.get('isReplicaSet'):
                    client = ReplicaSets()._storage[instance_id].connection()
                db = client[self.auth_source]
                if self.x509_extra_user:
                    db.add_user(DEFAULT_SUBJECT,
                                roles=self._user_roles(client))
                if self.login:
                    db.add_user(**secondary_login)

        if self.restart_required:
            # Do we need to add clusterAuthMode back?
            cluster_auth_mode = None
            for cfg in shard_configs:
                cam = cfg.get('clusterAuthMode')
                if cam:
                    cluster_auth_mode = cam
                    break

            def restart_with_auth(server_or_rs):
                server_or_rs.x509_extra_user = self.x509_extra_user
                server_or_rs.auth_source = self.auth_source
                server_or_rs.ssl_params = self.sslParams
                server_or_rs.login = self.login
                server_or_rs.password = self.password
                server_or_rs.auth_key = self.auth_key

                def add_auth(cfg):
                    if self.auth_key:
                        cfg['keyFile'] = self.key_file
                    # Add clusterAuthMode back in.
                    if cluster_auth_mode:
                        cfg['clusterAuthMode'] = cam
                    return cfg

                server_or_rs.restart(config_callback=add_auth)

            for config_id in self._configsvrs:
                restart_with_auth(self.configdb_singleton._storage[config_id])

            for server_id in self._routers:
                server = Servers()._storage[server_id]
                restart_with_auth(server)

            for shard_id in self._shards:
                shard = self._shards[shard_id]
                instance_id = shard['_id']
                klass = ReplicaSets if shard.get('isReplicaSet') else Servers
                instance = klass()._storage[instance_id]
                restart_with_auth(instance)

            self.restart_required = False
Example #29
0
def cleanup_storage(*args):
    """Clean up processes after SIGTERM or SIGINT is received."""
    ShardedClusters().cleanup()
    ReplicaSets().cleanup()
    Servers().cleanup()
    sys.exit(0)
 def setUp(self):
     PortPool().change_range()
     self.rs = ReplicaSets()
     self.rs.set_settings(os.environ.get('MONGOBIN', None))
Example #31
0
 def setUp(self):
     PortPool().change_range()
     self.rs = ReplicaSets()
 def setUp(self):
     PortPool().change_range()
     self.rs = ReplicaSets()
class ReplicaSetsTestCase(unittest.TestCase):
    def setUp(self):
        PortPool().change_range()
        self.rs = ReplicaSets()

    def tearDown(self):
        self.rs.cleanup()

    def waiting(self, fn, timeout=300, sleep=10):
        t_start = time.time()
        while not fn():
            if time.time() - t_start > timeout:
                return False
            time.sleep(sleep)
        return True

    def test_singleton(self):
        self.assertEqual(id(self.rs), id(ReplicaSets()))

    def test_bool(self):
        self.assertEqual(False, bool(self.rs))
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.assertEqual(True, bool(self.rs))

    def test_operations(self):
        repl_cfg = {'members': [{}, {}]}
        repl = ReplicaSet(repl_cfg)

        self.assertEqual(len(self.rs), 0)
        operator.setitem(self.rs, 1, repl)
        self.assertEqual(len(self.rs), 1)
        self.assertEqual(operator.getitem(self.rs, 1).repl_id, repl.repl_id)
        operator.delitem(self.rs, 1)
        self.assertEqual(len(self.rs), 0)
        self.assertRaises(KeyError, operator.getitem, self.rs, 1)

    def test_operations2(self):
        self.assertTrue(len(self.rs) == 0)
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.rs.create({'id': 'test-rs-2', 'members': [{}, {}]})
        self.assertTrue(len(self.rs) == 2)
        for key in self.rs:
            self.assertTrue(key in ('test-rs-1', 'test-rs-2'))
        for key in ('test-rs-1', 'test-rs-2'):
            self.assertTrue(key in self.rs)

    def test_cleanup(self):
        self.assertTrue(len(self.rs) == 0)
        self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        self.rs.create({'id': 'test-rs-2', 'members': [{}, {}]})
        self.assertTrue(len(self.rs) == 2)
        self.rs.cleanup()
        self.assertTrue(len(self.rs) == 0)

    def test_rs_new(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        repl_id = self.rs.create({'id': 'test-rs-1',
                                  'members': [{"procParams": {"port": port1}},
                                              {"procParams": {"port": port2}}
                                              ]})
        self.assertEqual(repl_id, 'test-rs-1')
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        c = pymongo.MongoClient([server1, server2], replicaSet=repl_id)
        self.assertEqual(c.admin.eval("rs.conf()")['_id'], repl_id)
        c.close()

    def test_rs_new_with_auth(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        repl_id = self.rs.create({'id': 'test-rs-1',
                                  'auth_key': 'sercret', 'login': '******', 'password': '******',
                                  'members': [{"procParams": {"port": port1}},
                                              {"procParams": {"port": port2}}
                                              ]})
        self.assertEqual(repl_id, 'test-rs-1')
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        c = pymongo.MongoClient([server1, server2], replicaSet=repl_id)
        self.assertRaises(pymongo.errors.OperationFailure, c.admin.collection_names)
        self.assertTrue(c.admin.authenticate('admin', 'admin'))
        self.assertTrue(isinstance(c.admin.collection_names(), list))
        c.admin.logout()
        self.assertRaises(pymongo.errors.OperationFailure, c.admin.collection_names)
        c.close()

    def test_info(self):
        repl_id = self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        info = self.rs.info(repl_id)
        self.assertTrue(isinstance(info, dict))
        for item in ("id", "mongodb_uri", "members", "orchestration"):
            self.assertTrue(item in info)

        self.assertEqual(info['id'], repl_id)
        self.assertEqual(len(info['members']), 2)
        mongodb_uri = info['mongodb_uri']
        for member in self.rs.members(repl_id):
            self.assertIn(member['host'], mongodb_uri)
        self.assertTrue(mongodb_uri.find('mongodb://') == 0)
        self.assertEqual(info['orchestration'], 'replica_sets')

    def test_info_with_auth(self):
        repl_id = self.rs.create({'id': 'test-rs-1', 'login': '******', 'password': '******', 'members': [{}, {}]})
        info = self.rs.info(repl_id)
        self.assertTrue(isinstance(info, dict))
        self.assertEqual(info['id'], repl_id)
        self.assertEqual(len(info['members']), 2)

    def test_primary(self):
        repl_id = self.rs.create({'id': 'test-rs-1', 'members': [{}, {}]})
        primary = self.rs.primary(repl_id)['mongodb_uri']
        c = connected(pymongo.MongoClient(primary))
        self.assertTrue(c.is_primary)
        c.close()

    def test_primary_stepdown(self):
        # This tests Server,
        # but only makes sense in the context of a replica set.
        repl_id = self.rs.create(
            {'id': 'test-rs-stepdown', 'members': [{}, {}, {}]})
        primary = self.rs.primary(repl_id)
        primary_server = Servers()._storage[primary['server_id']]
        time.sleep(20)

        # No Exception.
        primary_server.stepdown()
        self.assertNotEqual(primary['mongodb_uri'],
                            self.rs.primary(repl_id)['mongodb_uri'])

    def test_rs_del(self):
        self.rs.create({'members': [{}, {}]})
        repl_id = self.rs.create({'members': [{}, {}]})
        self.assertEqual(len(self.rs), 2)
        primary = self.rs.primary(repl_id)['mongodb_uri']
        connected(pymongo.MongoClient(primary))  # No error.
        self.rs.remove(repl_id)
        self.assertEqual(len(self.rs), 1)
        with self.assertRaises(pymongo.errors.PyMongoError):
            connected(pymongo.MongoClient(primary))

    def test_members(self):
        port1, port2 = PortPool().port(check=True), PortPool().port(check=True)
        server1 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port1)
        server2 = "{hostname}:{port}".format(hostname=HOSTNAME, port=port2)
        repl_id = self.rs.create({'members': [{"procParams": {"port": port1}}, {"procParams": {"port": port2}}]})
        members = self.rs.members(repl_id)
        self.assertEqual(len(members), 2)
        self.assertTrue(server1 in [member['host'] for member in members])
        self.assertTrue(server2 in [member['host'] for member in members])

    def test_secondaries(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {}, {}]})
        secondaries = self.rs.secondaries(repl_id)
        self.assertEqual(len(secondaries), 2)

    def test_arbiters(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {}, {"rsParams": {"arbiterOnly": True}}]})
        arbiters = self.rs.arbiters(repl_id)
        self.assertEqual(len(arbiters), 1)

    def test_hidden(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {}, {"rsParams": {"priority": 0, "hidden": True}}]})
        hidden = self.rs.hidden(repl_id)
        self.assertEqual(len(hidden), 1)

    def test_passives(self):
        config = {"members": [{},
                              {"rsParams": {"priority": 0}},
                              {"rsParams": {"arbiterOnly": True}},
                              {"rsParams": {"priority": 0, 'hidden': True}},
                              {"rsParams": {"priority": 0, 'slaveDelay': 5}}]}
        repl_id = self.rs.create(config)
        passives = self.rs.passives(repl_id)
        self.assertEqual(len(passives), 1)

    def test_servers(self):
        config = {"members": [{},
                              {"rsParams": {"priority": 0}},
                              {"rsParams": {"arbiterOnly": True}},
                              {"rsParams": {"priority": 0, 'hidden': True}},
                              {"rsParams": {"priority": 0, 'slaveDelay': 5}}]}
        repl_id = self.rs.create(config)
        servers = self.rs.servers(repl_id)
        self.assertEqual(len(servers), 1)

    def test_compare_passives_and_servers(self):
        config = {"members": [{},
                              {"rsParams": {"priority": 0}},
                              {"rsParams": {"arbiterOnly": True}},
                              {"rsParams": {"priority": 0, 'hidden': True}},
                              {"rsParams": {"priority": 0, 'slaveDelay': 5}}]}

        repl_id = self.rs.create(config)
        passives = [server['host'] for server in self.rs.passives(repl_id)]
        servers = [server['host'] for server in self.rs.servers(repl_id)]
        for item in passives:
            self.assertTrue(item not in servers)

        for item in servers:
            self.assertTrue(item not in passives)

    def test_member_info(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {"rsParams": {"arbiterOnly": True}}, {"rsParams": {"priority": 0, "hidden": True}}]})
        info = self.rs.member_info(repl_id, 0)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 0)
        self.assertTrue(info['statuses']['primary'])

        info = self.rs.member_info(repl_id, 1)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 1)
        self.assertTrue(info['rsInfo']['arbiterOnly'])

        info = self.rs.member_info(repl_id, 2)
        for key in ('procInfo', 'mongodb_uri', 'statuses', 'rsInfo'):
            self.assertTrue(key in info)
        self.assertEqual(info['_id'], 2)
        self.assertTrue(info['rsInfo']['hidden'])

    def test_tagging(self):
        tags_0 = {"status": "primary"}
        tags_1 = {"status": "arbiter"}
        tags_2 = {"status": "hidden"}
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5, "tags": tags_0}}, {"rsParams": {"arbiterOnly": True}, "tags": tags_1}, {"rsParams": {"priority": 0, "hidden": True, "tags": tags_2}}]})
        self.assertEqual(tags_0, self.rs.primary(repl_id)['rsInfo']['tags'])

        member_arbiter = self.rs.arbiters(repl_id)[0]['_id']
        self.assertFalse('tags' in self.rs.member_info(repl_id, member_arbiter)['rsInfo'])

        member_hidden = self.rs.hidden(repl_id)[0]['_id']
        self.assertTrue('tags' in self.rs.member_info(repl_id, member_hidden)['rsInfo'])

    def test_member_del(self):
        repl_id = self.rs.create(
            {'members': [{"rsParams": {"priority": 1.5}}, {}, {}]})
        self.assertEqual(len(self.rs.members(repl_id)), 3)
        assert_eventually(lambda: len(self.rs.secondaries(repl_id)) > 0)
        secondary = self.rs.secondaries(repl_id)[0]
        connected(pymongo.MongoClient(secondary['host']))  # No error.
        self.assertTrue(self.rs.member_del(repl_id, secondary['_id']))
        self.assertEqual(len(self.rs.members(repl_id)), 2)
        with self.assertRaises(pymongo.errors.PyMongoError):
            connected(pymongo.MongoClient(secondary['host']))

    def test_member_add(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {}]})
        self.assertEqual(len(self.rs.members(repl_id)), 2)
        member_id = self.rs.member_add(repl_id, {"rsParams": {"priority": 0, "hidden": True}})
        self.assertEqual(len(self.rs.members(repl_id)), 3)
        info = self.rs.member_info(repl_id, member_id)
        self.assertTrue(info['rsInfo']['hidden'])

    def test_member_command(self):
        _id = 1
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {}]})
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'stop')
        self.assertFalse(self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'start')
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])
        self.rs.member_command(repl_id, _id, 'restart')
        self.assertTrue(self.rs.member_info(repl_id, _id)['procInfo']['alive'])

    def test_member_freeze(self):
        # This tests Server, but only makes sense in the context of a replica set.
        repl_id = self.rs.create(
            {'members': [{"rsParams": {"priority": 19}},
                         {"rsParams": {"priority": 5}}, {}]})
        next_primary_info = self.rs.member_info(repl_id, 2)
        next_primary = next_primary_info['mongodb_uri']
        secondary_info = self.rs.member_info(repl_id, 1)
        secondary_server = Servers()._storage[secondary_info['server_id']]
        primary_info = self.rs.member_info(repl_id, 0)
        primary_server = Servers()._storage[primary_info['server_id']]

        assert_eventually(lambda: primary_server.connection.is_primary)

        def freeze_and_stop():
            self.assertTrue(secondary_server.freeze(100))
            try:
                # Call replSetStepDown before killing the primary's process.
                # This raises OperationFailure if no secondaries are capable
                # of taking over.
                primary_server.connection.admin.command('replSetStepDown', 10)
            except pymongo.errors.AutoReconnect:
                # Have to stop the server as well so it doesn't get reelected.
                primary_server.stop()
                return True
            except pymongo.errors.OperationFailure:
                # No secondaries within 10 seconds of my optime...
                return False

        assert_eventually(freeze_and_stop, "Primary didn't step down.")
        assert_eventually(lambda: (
            self.rs.primary(repl_id)['mongodb_uri'] == next_primary),
            "Secondary did not freeze.",
            max_tries=120
        )
        assert_eventually(lambda: (
            self.rs.primary(repl_id)['mongodb_uri'] ==
            self.rs.member_info(repl_id, 1)['mongodb_uri']),
            "Higher priority secondary never promoted.",
            max_tries=120
        )

    def test_member_update(self):
        repl_id = self.rs.create({'members': [{"rsParams": {"priority": 1.5}}, {"rsParams": {"priority": 0, "hidden": True}}, {}]})
        hidden = self.rs.hidden(repl_id)[0]
        self.assertTrue(self.rs.member_info(repl_id, hidden['_id'])['rsInfo']['hidden'])
        self.rs.member_update(repl_id, hidden['_id'], {"rsParams": {"priority": 1, "hidden": False}})
        self.assertEqual(len(self.rs.hidden(repl_id)), 0)
        self.assertFalse(self.rs.member_info(repl_id, hidden['_id'])['rsInfo'].get('hidden', False))

    def test_member_update_with_auth(self):
        repl_id = self.rs.create({'login': '******', 'password': '******',
                                 'members': [{"rsParams": {"priority": 1.5}},
                                             {"rsParams": {"priority": 0, "hidden": True}},
                                             {}]})
        hidden = self.rs.hidden(repl_id)[0]
        self.assertTrue(self.rs.member_info(repl_id, hidden['_id'])['rsInfo']['hidden'])
        self.rs.member_update(repl_id, hidden['_id'], {"rsParams": {"priority": 1, "hidden": False}})
        self.assertEqual(len(self.rs.hidden(repl_id)), 0)
        self.assertFalse(self.rs.member_info(repl_id, hidden['_id'])['rsInfo'].get('hidden', False))
Example #34
0
 def test_singleton(self):
     self.assertEqual(id(self.rs), id(ReplicaSets()))
Example #35
0
def set_releases(releases=None, default_release=None):
    Servers().set_settings(releases, default_release)
    ReplicaSets().set_settings(releases, default_release)
    ShardedClusters().set_settings(releases, default_release)