def test_mongos(self): self.server.stop() self.server.cleanup() self.server = Server(self.mongod, {'configsvr': True}, auth_key='secret') self.server.start(30) mongos = os.path.join(os.environ.get('MONGOBIN', ''), 'mongos') self.server2 = Server(mongos, {'configdb': self.server.hostname}, auth_key='secret', login='******', password='******') self.server2.start() for server in (self.server, self.server2): c = pymongo.MongoClient(server.host, server.port) self.assertRaises(pymongo.errors.OperationFailure, c.admin.collection_names) self.assertTrue(c.admin.authenticate('admin', 'admin')) self.assertTrue(isinstance(c.admin.collection_names(), list)) self.assertTrue(c.admin.logout() is None) self.assertRaises(pymongo.errors.OperationFailure, c.admin.collection_names) self.server2.stop() self.server2.cleanup()
def test_mongos(self): self.server.cleanup() self.server = Server(self.mongod, {'configsvr': True}) self.server.start(30) mongos = os.path.join(os.environ.get('MONGOBIN', ''), 'mongos') self.server2 = Server(mongos, {'configdb': self.server.hostname}) self.assertTrue(self.server2.start()) self.assertTrue(self.server2.info()['statuses'].get('mongos', False)) self.server2.stop() self.server2.cleanup()
def test_ssl_auth(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") proc_params = { 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } ssl_params = { 'sslPEMKeyFile': certificate('server.pem'), 'sslCAFile': certificate('ca.pem'), 'sslMode': 'requireSSL', 'sslAllowInvalidCertificates': True } # Should not raise an Exception. self.server = Server('mongod', proc_params, ssl_params, login=TEST_SUBJECT, auth_source='$external') self.server.start() # Should create an extra user. Doesn't raise. client = pymongo.MongoClient(self.server.hostname, ssl_certfile=DEFAULT_CLIENT_CERT) client['$external'].authenticate(DEFAULT_SUBJECT, mechanism='MONGODB-X509') # Should also create the user we requested. Doesn't raise. client = pymongo.MongoClient(self.server.hostname, ssl_certfile=certificate('client.pem')) client['$external'].authenticate(TEST_SUBJECT, mechanism='MONGODB-X509')
def test_start_with_repair(self): self.server.cleanup() self.server = Server(self.mongod, {"journal": False}) self.server.start(30) os.kill(self.server.pid, 9) self.assertTrue(self.server._is_locked) self.assertTrue(self.server.start(20))
def test_info(self): self.server.start(30) info = self.server.info() for item in ("mongodb_uri", "statuses", "serverInfo", "procInfo", "orchestration"): self.assertTrue(item in info) self.assertTrue(info['mongodb_uri'].find(self.server.hostname)) self.assertTrue(info['mongodb_uri'].find('mongodb://') == 0) fd_log, log_path = tempfile.mkstemp() os.close(fd_log) db_path = tempfile.mkdtemp() params = {'logpath': log_path, 'dbpath': db_path} server2 = Server(self.mongod, params) server2.start() info2 = server2.info() for param, value in params.items(): self.assertTrue( info2['procInfo']['params'].get(param, value) == value) server2.stop() info = server2.info() self.assertEqual(len(info['serverInfo']), 0) self.assertEqual(len(info['statuses']), 0) self.assertEqual(info['orchestration'], 'servers') server2.cleanup()
def test_mongodb_auth_uri(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") proc_params = { 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } ssl_params = { 'sslPEMKeyFile': certificate('server.pem'), 'sslCAFile': certificate('ca.pem'), 'sslMode': 'requireSSL', 'sslAllowInvalidCertificates': True } self.server = Server(self.mongod_name, proc_params, ssl_params, login=TEST_SUBJECT, auth_source='$external') self.server.start() self.assertIn('mongodb_auth_uri', self.server.info()) auth_uri = self.server.info()['mongodb_auth_uri'] self.assertIn(self.server.hostname, auth_uri) self.assertIn(TEST_SUBJECT, auth_uri) self.assertIn('authSource=$external', auth_uri) self.assertIn('authMechanism=MONGODB-X509', auth_uri)
def setUp(self): PortPool().change_range() self.mongod = os.path.join(os.environ.get('MONGOBIN', ''), 'mongod') self.server = Server(self.mongod, {}, auth_key='secret', login='******', password='******') self.server.start()
def test_start(self): self.assertNotIn('pid', self.server.info()['procInfo']) self.assertTrue(self.server.start(30)) self.assertTrue(self.server.info()['procInfo']['pid'] > 0) fake_server = Server('fake_proc_', {}) self.assertRaises(OSError, fake_server.start, 5) fake_server.cleanup()
def test_init_path(self): self.server.cleanup() mongod = os.path.join(os.environ.get('MONGOBIN', ''), 'mongod') log_dir = os.path.join(tempfile.gettempdir(), os.path.split(tempfile.mktemp())[-1]) log_path = tempfile.mktemp(dir=log_dir) db_path = os.path.join(tempfile.gettempdir(), os.path.split(tempfile.mktemp())[-1]) self.assertFalse(os.path.exists(log_dir)) self.assertFalse(os.path.exists(db_path)) self.server = Server(mongod, {'logpath': log_path, 'dbpath': db_path}) self.assertTrue(os.path.exists(log_dir)) self.assertTrue(os.path.exists(db_path))
def test_set_parameter(self): self.server.cleanup() cfg = {"setParameter": {"textSearchEnabled": True, "enableTestCommands": 1}} self.server = Server(self.mongod, cfg) self.server.start() c = pymongo.MongoClient(self.server.hostname) c.foo.bar.insert({"data": "text stuff"}) # No Exception. c.foo.bar.ensure_index([("data", pymongo.TEXT)]) # No Exception. c.admin.command("sleep", secs=1)
def test_ssl(self): ssl_params = { 'sslPEMKeyFile': certificate('server.pem'), 'sslCAFile': certificate('ca.pem'), 'sslMode': 'requireSSL', 'sslAllowInvalidCertificates': True } # Should not raise an Exception. self.server = Server('mongod', {}, ssl_params) self.server.start() # Server should require SSL. self.assertRaises(pymongo.errors.ConnectionFailure, pymongo.MongoClient, self.server.hostname) # Doesn't raise with certificate provided. pymongo.MongoClient(self.server.hostname, ssl_certfile=certificate('client.pem'))
def test_operations(self): server_id = self.servers.create('mongod', {}, autostart=False) self.assertTrue(len(self.servers) == 1) self.assertTrue(server_id in self.servers) server_id2 = 'server-id2' server2 = Server(os.path.join(os.environ.get('MONGOBIN', ''), 'mongod'), {}) server2.start(30) server2_pid = server2.info()['procInfo']['pid'] self.servers[server_id2] = server2 self.assertTrue(self.servers[server_id2]['procInfo']['pid'] == server2_pid) self.assertTrue(server_id2 in self.servers) for h_id in self.servers: self.assertTrue(h_id in (server_id, server_id2)) operator.delitem(self.servers, server_id2) self.assertFalse(server_id2 in self.servers) server2.stop() server2.cleanup()
def test_scram_with_ssl(self): ssl_params = { 'sslPEMKeyFile': certificate('server.pem'), 'sslCAFile': certificate('ca.pem'), 'sslMode': 'requireSSL', 'sslAllowInvalidCertificates': True } # Should not raise an Exception. self.server = Server( 'mongod', {}, ssl_params, login='******', password='******') self.server.start() # Should create the user we requested. No raise on authenticate. client = pymongo.MongoClient( self.server.hostname, ssl_certfile=certificate('client.pem')) client.admin.authenticate('luke', 'ekul') # This should be the only user. self.assertEqual(len(client.admin.command('usersInfo')['users']), 1) self.assertFalse(client['$external'].command('usersInfo')['users'])
def test_set_parameter(self): if SERVER_VERSION < (2, 4): raise SkipTest( "Need at least MongoDB >= 2.4 to test setParameter.") self.server.cleanup() cfg = { "setParameter": { "textSearchEnabled": True, "enableTestCommands": 1 } } self.server = Server(self.mongod, cfg) self.server.start() c = pymongo.MongoClient(self.server.hostname) c.foo.bar.insert({"data": "text stuff"}) # No Exception. c.foo.bar.ensure_index([("data", pymongo.TEXT)]) # No Exception. c.admin.command("sleep", secs=1)
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
def setUp(self): PortPool().change_range() self.mongod = os.path.join(os.environ.get('MONGOBIN', ''), 'mongod') self.server = Server(self.mongod, {})