示例#1
0
class TestMonitorRemovesRecoveringMember(unittest.TestCase):
    # Members in STARTUP2 or RECOVERING states are shown in the primary's
    # isMaster response, but aren't secondaries and shouldn't be read from.
    # Verify that if a secondary goes into RECOVERING mode, the Monitor removes
    # it from the set of readers.

    def setUp(self):
        members = [{}, {'priority': 0}, {'priority': 0}]
        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

    def test_monitor_removes_recovering_member(self):
        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        secondaries = ha_tools.get_secondaries()

        for mode in SECONDARY, SECONDARY_PREFERRED:
            partitioned_secondaries = [_partition_node(s) for s in secondaries]
            utils.assertReadFromAll(self, self.c, partitioned_secondaries, mode)

        secondary, recovering_secondary = secondaries
        ha_tools.set_maintenance(recovering_secondary, True)
        sleep(2 * MONITOR_INTERVAL)

        for mode in SECONDARY, SECONDARY_PREFERRED:
            # Don't read from recovering member
            utils.assertReadFrom(self, self.c, _partition_node(secondary), mode)

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#2
0
class TestPassiveAndHidden(unittest.TestCase):

    def setUp(self):
        members = [{},
                   {'priority': 0},
                   {'arbiterOnly': True},
                   {'priority': 0, 'hidden': True},
                   {'priority': 0, 'slaveDelay': 5}
        ]
        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

    def test_passive_and_hidden(self):
        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        passives = ha_tools.get_passives()
        passives = [_partition_node(member) for member in passives]
        self.assertEqual(self.c.secondaries, set(passives))

        for mode in SECONDARY, SECONDARY_PREFERRED:
            utils.assertReadFromAll(self, self.c, passives, mode)

        ha_tools.kill_members(ha_tools.get_passives(), 2)
        sleep(2 * MONITOR_INTERVAL)
        utils.assertReadFrom(self, self.c, self.c.primary, SECONDARY_PREFERRED)

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#3
0
class TestMonitorRemovesRecoveringMember(unittest.TestCase):
    # Members in STARTUP2 or RECOVERING states are shown in the primary's
    # isMaster response, but aren't secondaries and shouldn't be read from.
    # Verify that if a secondary goes into RECOVERING mode, the Monitor removes
    # it from the set of readers.

    def setUp(self):
        members = [{}, {'priority': 0}, {'priority': 0}]
        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

    def test_monitor_removes_recovering_member(self):
        self.c = MongoReplicaSetClient(self.seed,
                                       replicaSet=self.name,
                                       use_greenlets=use_greenlets)

        secondaries = ha_tools.get_secondaries()

        for mode in SECONDARY, SECONDARY_PREFERRED:
            partitioned_secondaries = [_partition_node(s) for s in secondaries]
            utils.assertReadFromAll(self, self.c, partitioned_secondaries,
                                    mode)

        secondary, recovering_secondary = secondaries
        ha_tools.set_maintenance(recovering_secondary, True)
        sleep(2 * MONITOR_INTERVAL)

        for mode in SECONDARY, SECONDARY_PREFERRED:
            # Don't read from recovering member
            utils.assertReadFrom(self, self.c, _partition_node(secondary),
                                 mode)

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#4
0
class TestPassiveAndHidden(unittest.TestCase):
    def setUp(self):
        members = [{}, {
            'priority': 0
        }, {
            'arbiterOnly': True
        }, {
            'priority': 0,
            'hidden': True
        }, {
            'priority': 0,
            'slaveDelay': 5
        }]
        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

    def test_passive_and_hidden(self):
        self.c = MongoReplicaSetClient(self.seed,
                                       replicaSet=self.name,
                                       use_greenlets=use_greenlets)

        passives = ha_tools.get_passives()
        passives = [_partition_node(member) for member in passives]
        self.assertEqual(self.c.secondaries, set(passives))

        for mode in SECONDARY, SECONDARY_PREFERRED:
            utils.assertReadFromAll(self, self.c, passives, mode)

        ha_tools.kill_members(ha_tools.get_passives(), 2)
        sleep(2 * MONITOR_INTERVAL)
        utils.assertReadFrom(self, self.c, self.c.primary, SECONDARY_PREFERRED)

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#5
0
    def test_sasl_plain(self):

        client = MongoClient(SASL_HOST, SASL_PORT)
        self.assertTrue(
            client.ldap.authenticate(SASL_USER, SASL_PASS, SASL_DB, 'PLAIN'))
        client.ldap.test.find_one()

        uri = ('mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;'
               'authSource=%s' % (quote_plus(SASL_USER), quote_plus(SASL_PASS),
                                  SASL_HOST, SASL_PORT, SASL_DB))
        client = MongoClient(uri)
        client.ldap.test.find_one()

        set_name = client.admin.command('ismaster').get('setName')
        if set_name:
            client = MongoReplicaSetClient(SASL_HOST,
                                           port=SASL_PORT,
                                           replicaSet=set_name)
            self.assertTrue(
                client.ldap.authenticate(SASL_USER, SASL_PASS, SASL_DB,
                                         'PLAIN'))
            client.ldap.test.find_one()

            uri = ('mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;'
                   'authSource=%s;replicaSet=%s' %
                   (quote_plus(SASL_USER), quote_plus(SASL_PASS), SASL_HOST,
                    SASL_PORT, SASL_DB, str(set_name)))
            client = MongoReplicaSetClient(uri)
            client.ldap.test.find_one()
 def init(self):
     logger.info('[Mongodb-Notification-Broker] Initialization of '
                 'mongodb_notification_broker module')
     self._set_mongodb_url()
     logger.debug('[Mongodb-Notification-Broker] Mongodb connect url: %s' 
                  % self.mongodb_url)
     
     # In case notification broker process down occasionally, the self.conn 
     # object must be dropped cleanly in Broker daemon.
     self.do_stop()
     try:
         if not self.high_availability:
             self.conn = MongoClient(self.mongodb_url)
         else:
             self.conn = MongoReplicaSetClient(self.mongodb_url)
     except ConnectionFailure:
         logger.warn('[Mongodb-Notification-Broker] Can not make connection '
                     ' with MongoDB')
         raise
         
     except (InvalidURI, ConfigurationError):
         logger.warn('[Mongodb-Notification-Broker] Mongodb connect url '
                     'error')
         logger.warn('[Mongodb-Notification-Broker] Mongodb connect url: %s' 
                     % self.mongodb_url)
         raise 
     self._get_collections()
示例#7
0
 def setUp(self):
     members = [{}, {}, {'arbiterOnly': True}]
     res = ha_tools.start_replica_set(members)
     self.c = MongoReplicaSetClient(res[0],
                                    replicaSet=res[1],
                                    use_greenlets=use_greenlets,
                                    auto_start_request=True)
示例#8
0
    def test_scram_sha1(self):
        client = MongoClient(host, port)
        self.assertTrue(
            client.pymongo_test.authenticate('user',
                                             'pass',
                                             mechanism='SCRAM-SHA-1'))
        client.pymongo_test.command('dbstats')

        client = MongoClient('mongodb://*****:*****@%s:%d/pymongo_test'
                             '?authMechanism=SCRAM-SHA-1' % (host, port))
        client.pymongo_test.command('dbstats')

        if self.set_name:
            client = MongoReplicaSetClient(
                'mongodb://*****:*****@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1'
                   '&replicaSet=%s' % (host, port, self.set_name))
            client = MongoReplicaSetClient(uri)
            client.pymongo_test.command('dbstats')
            client.read_preference = ReadPreference.SECONDARY
            client.pymongo_test.command('dbstats')
示例#9
0
    def test_init_disconnected_with_auth(self):
        c = self._get_client()

        auth_context.client.admin.add_user("admin", "pass")
        c.admin.authenticate("admin", "pass")
        try:
            c.pymongo_test.add_user("user",
                                    "pass",
                                    roles=['readWrite', 'userAdmin'])

            # Auth with lazy connection.
            host = one(self.hosts)
            uri = "mongodb://*****:*****@%s:%d/pymongo_test?replicaSet=%s" % (
                host[0], host[1], self.name)

            authenticated_client = MongoReplicaSetClient(uri, _connect=False)
            authenticated_client.pymongo_test.test.find_one()

            # Wrong password.
            bad_uri = (
                "mongodb://*****:*****@%s:%d/pymongo_test?replicaSet=%s" %
                (host[0], host[1], self.name))

            bad_client = MongoReplicaSetClient(bad_uri, _connect=False)
            self.assertRaises(OperationFailure,
                              bad_client.pymongo_test.test.find_one)

        finally:
            # Clean up.
            remove_all_users(c.pymongo_test)
            c.admin.remove_user('admin')
示例#10
0
    def test_gssapi_simple(self):

        client = MongoClient(GSSAPI_HOST, GSSAPI_PORT)
        self.assertTrue(client.test.authenticate(PRINCIPAL,
                                                 mechanism='GSSAPI'))
        # Just test that we can run a simple command.
        self.assertTrue(client.database_names())

        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'GSSAPI' % (quote_plus(PRINCIPAL), GSSAPI_HOST, GSSAPI_PORT))
        client = MongoClient(uri)
        self.assertTrue(client.database_names())

        set_name = client.admin.command('ismaster').get('setName')
        if set_name:
            client = MongoReplicaSetClient(GSSAPI_HOST,
                                           port=GSSAPI_PORT,
                                           replicaSet=set_name)
            self.assertTrue(
                client.test.authenticate(PRINCIPAL, mechanism='GSSAPI'))
            self.assertTrue(client.database_names())
            uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet'
                   '=%s' % (quote_plus(PRINCIPAL), GSSAPI_HOST, GSSAPI_PORT,
                            str(set_name)))
            client = MongoReplicaSetClient(uri)
            self.assertTrue(client.database_names())
示例#11
0
class Connection():
	def __init__(self):
		self.connection = None

	def connect(self,hosts="localhost", replicaSet="", readPreference=ReadPreference.SECONDARY_PREFERRED):
		# if the replicaset is empty, we use a normal connection, if not, we use a MongoReplicaSetClient
		# in wich case we set the read preference
		# by default, SECONDARY_PREFERRED since we don't big have consistancy issues. Fail safe when the primary/secondary goes down.
		if replicaSet == "":
			print("Using mongodb host " + hosts + " for read/writes.")
			self.connection = MongoConnection(hosts)
		else:
			print("Using mongodb hosts " + hosts + " with replica set " + replicaSet + " and read pref " + str(readPreference))
			self.connection = MongoReplicaSetClient(hosts, replicaSet=replicaSet, read_preference=readPreference)
			print("Replica set:")
			print("PRIMARY: " + str(self.connection.primary))
			print("SECONDARIES: " + str(self.connection.secondaries))
			print("ARBITERS: " + str(self.connection.arbiters))

	def close(self):
		self.connection.close()
		self.connection = None

	# \return the requested db setting the readPreference if set.
	def getDatabase(self, dbname, readPreference=None):
		db = self.connection[dbname]
		if readPreference != None:
			db.read_preference = readPreference
		return db
示例#12
0
def getDB(name):
    if name=='mongo':
        conn=MongoReplicaSetClient('dbserver-1:27017,dbserver-2:27017,dbserver-3:27017', replicaSet='ats_rs')
        conn.read_preference = ReadPreference.SECONDARY_PREFERRED
        return conn.brauth
    elif name=='redis':
        return redis.Redis(connection_pool = redis.ConnectionPool(host='192.168.7.210', port=6379, db=6))
    else:
        return None  
示例#13
0
    def __init__(
        self, standalones, members, mongoses, ismaster_hosts=None,
        *args, **kwargs
    ):
        MockClientBase.__init__(
            self, standalones, members, mongoses, ismaster_hosts)

        kwargs['_pool_class'] = my_partial(MockPool, self)
        MongoReplicaSetClient.__init__(self, *args, **kwargs)
示例#14
0
    def __init__(self, settings, **kw):
        if MongoClient is None:
            raise NotConfigured('%s is missing pymongo or gridfs module.' %
                                self.__class__.__name__)
        if (2, 4, 0) > mongo_version:
            version = '.'.join('%s' % v for v in mongo_version)
            raise NotConfigured(
                '%s requires pymongo version >= 2.4 but got %s' %
                (self.__class__.__name__, version))
        super(MongodbCacheStorage, self).__init__(settings)
        self.sharded = settings.getbool('HTTPCACHE_SHARDED', False)
        kwargs = get_database(settings)
        kwargs.update(kw)
        db = kwargs.pop('db')
        user = kwargs.pop('user', None)
        password = kwargs.pop('password', None)
        if 'replicaSet' in kwargs:
            client = MongoReplicaSetClient(**kwargs)
        else:
            client = MongoClient(**kwargs)

        # do not override a database passed in a 'mongodb://' URI string
        try:
            self.db = client.get_default_database()
        except ConfigurationError:
            self.db = client[db]
        except TypeError:
            # get_default_database() only since pymongo 2.6, but
            # pymongo>2.5.2 only works with mongodb > ~2.4.3
            # fall back to parsing uri string in this edge-case :(
            if 'mongodb://' in kwargs.get('host'):
                try:
                    from urlparse import urlparse
                    loc = urlparse(uri).path.strip('/')
                    if not loc:
                        self.db = client[db]
                except (ImportError, Exception):
                    client.connection.close()
                    raise NotConfigured('%s could not reliably detect if \
                    there was a database passed in URI string. Please install \
                    urlparse to fix this, or use host:port arguments instead.'
                                        % self.__class__.__name__)
            else:
                self.db = client[db]

        if user is not None and password is not None:
            self.db.authenticate(user, password)
        logger.debug(
            "Backend %(storage)s connected to %(host)s:%(port)s, using database '%(db)s'"
            % {
                'storage': self.__class__.__name__,
                'host': client.host,
                'port': client.port,
                'db': db
            })
        self.fs = {}
示例#15
0
class TestReplicaSetRequest(unittest.TestCase):
    def setUp(self):
        members = [{}, {}, {'arbiterOnly': True}]
        res = ha_tools.start_replica_set(members)
        self.c = MongoReplicaSetClient(res[0],
                                       replicaSet=res[1],
                                       use_greenlets=use_greenlets,
                                       auto_start_request=True)

    def test_request_during_failover(self):
        primary = _partition_node(ha_tools.get_primary())
        secondary = _partition_node(ha_tools.get_random_secondary())

        self.assertTrue(self.c.auto_start_request)
        self.assertTrue(self.c.in_request())

        primary_pool = self.c._MongoReplicaSetClient__members[primary].pool
        secondary_pool = self.c._MongoReplicaSetClient__members[secondary].pool

        # Trigger start_request on primary pool
        utils.assertReadFrom(self, self.c, primary, PRIMARY)
        self.assertTrue(primary_pool.in_request())

        # Fail over
        ha_tools.kill_primary()
        patience_seconds = 60
        for _ in range(patience_seconds):
            sleep(1)
            try:
                if ha_tools.ha_tools_debug:
                    print 'Waiting for failover'
                if ha_tools.get_primary():
                    # We have a new primary
                    break
            except ConnectionFailure:
                pass
        else:
            self.fail("Problem with test: No new primary after %s seconds" %
                      patience_seconds)

        try:
            # Trigger start_request on secondary_pool, which is becoming new
            # primary
            self.c.test.test.find_one()
        except AutoReconnect:
            # We've noticed the failover now
            pass

        # The old secondary is now primary
        utils.assertReadFrom(self, self.c, secondary, PRIMARY)
        self.assertTrue(self.c.in_request())
        self.assertTrue(secondary_pool.in_request())

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#16
0
class TestReplicaSetRequest(unittest.TestCase):
    def setUp(self):
        members = [{}, {}, {'arbiterOnly': True}]
        res = ha_tools.start_replica_set(members)
        self.c = MongoReplicaSetClient(res[0], replicaSet=res[1],
                                       use_greenlets=use_greenlets,
                                       auto_start_request=True)

    def test_request_during_failover(self):
        primary = _partition_node(ha_tools.get_primary())
        secondary = _partition_node(ha_tools.get_random_secondary())

        self.assertTrue(self.c.auto_start_request)
        self.assertTrue(self.c.in_request())

        primary_pool = self.c._MongoReplicaSetClient__members[primary].pool
        secondary_pool = self.c._MongoReplicaSetClient__members[secondary].pool

        # Trigger start_request on primary pool
        utils.assertReadFrom(self, self.c, primary, PRIMARY)
        self.assertTrue(primary_pool.in_request())

        # Fail over
        ha_tools.kill_primary()
        patience_seconds = 60
        for _ in range(patience_seconds):
            sleep(1)
            try:
                if ha_tools.ha_tools_debug:
                    print 'Waiting for failover'
                if ha_tools.get_primary():
                    # We have a new primary
                    break
            except ConnectionFailure:
                pass
        else:
            self.fail("Problem with test: No new primary after %s seconds"
                % patience_seconds)

        try:
            # Trigger start_request on secondary_pool, which is becoming new
            # primary
            self.c.test.test.find_one()
        except AutoReconnect:
            # We've noticed the failover now
            pass

        # The old secondary is now primary
        utils.assertReadFrom(self, self.c, secondary, PRIMARY)
        self.assertTrue(self.c.in_request())
        self.assertTrue(secondary_pool.in_request())

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#17
0
def getDB(name):
    if name == 'mongo':
        conn = MongoReplicaSetClient(
            'dbserver-1:27017,dbserver-2:27017,dbserver-3:27017',
            replicaSet='ats_rs')
        conn.read_preference = ReadPreference.SECONDARY_PREFERRED
        return conn.brauth
    elif name == 'redis':
        return redis.Redis(connection_pool=redis.ConnectionPool(
            host='192.168.7.210', port=6379, db=6))
    else:
        return None
示例#18
0
    def _mongo(self, instances, force=False):
        if not hasattr(AwsMongoBackup, 'mongo') or force:
            mongo_rs_str = ','.join([x.public_dns_name for x in instances])
            self.logger.debug("connecting to mongo URI %s" % mongo_rs_str)
            self.mongo = MongoReplicaSetClient(mongo_rs_str,
                                               replicaSet=self.replicaset)

            if self.mongo.alive():
                return self.mongo
            else:
                self.mongo = None
                return None
    def __init__(self,
                 standalones,
                 members,
                 mongoses,
                 ismaster_hosts=None,
                 *args,
                 **kwargs):
        MockClientBase.__init__(self, standalones, members, mongoses,
                                ismaster_hosts)

        kwargs['_pool_class'] = my_partial(MockPool, self)
        MongoReplicaSetClient.__init__(self, *args, **kwargs)
示例#20
0
	def connect(self,hosts="localhost", replicaSet="", readPreference=ReadPreference.SECONDARY_PREFERRED):
		# if the replicaset is empty, we use a normal connection, if not, we use a MongoReplicaSetClient
		# in wich case we set the read preference
		# by default, SECONDARY_PREFERRED since we don't big have consistancy issues. Fail safe when the primary/secondary goes down.
		if replicaSet == "":
			print("Using mongodb host " + hosts + " for read/writes.")
			self.connection = MongoConnection(hosts)
		else:
			print("Using mongodb hosts " + hosts + " with replica set " + replicaSet + " and read pref " + str(readPreference))
			self.connection = MongoReplicaSetClient(hosts, replicaSet=replicaSet, read_preference=readPreference)
			print("Replica set:")
			print("PRIMARY: " + str(self.connection.primary))
			print("SECONDARIES: " + str(self.connection.secondaries))
			print("ARBITERS: " + str(self.connection.arbiters))
示例#21
0
    def __init__(self, settings, **kw):
        if MongoClient is None:
            raise NotConfigured('%s is missing pymongo or gridfs module.' %
                                self.__class__.__name__)
        if (2,4,0) > mongo_version:
            version = '.'.join('%s'% v for v in mongo_version)
            raise NotConfigured('%s requires pymongo version >= 2.4 but got %s' %
                    (self.__class__.__name__, version))
        self.expire = settings.getint('HTTPCACHE_EXPIRATION_SECS')
        self.sharded = settings.getbool('HTTPCACHE_SHARDED', False)
        kwargs = get_database(settings)
        kwargs.update(kw)
        db = kwargs.pop('db')
        user = kwargs.pop('user', None)
        password = kwargs.pop('password', None)
        if 'replicaSet' in kwargs:
            client = MongoReplicaSetClient(**kwargs)
        else:
            client = MongoClient(**kwargs)

        # do not override a database passed in a 'mongodb://' URI string
        try:
            self.db = client.get_default_database()
        except ConfigurationError:
            self.db = client[db]
        except TypeError:
            # get_default_database() only since pymongo 2.6, but
            # pymongo>2.5.2 only works with mongodb > ~2.4.3
            # fall back to parsing uri string in this edge-case :(
            if 'mongodb://' in kwargs.get('host'):
                try:
                    from urlparse import urlparse
                    loc = urlparse(uri).path.strip('/')
                    if not loc:
                        self.db = client[db]
                except (ImportError, Exception):
                    client.connection.close()
                    raise NotConfigured('%s could not reliably detect if \
                    there was a database passed in URI string. Please install \
                    urlparse to fix this, or use host:port arguments instead.' %
                    self.__class__.__name__)
            else:
                self.db = client[db]

        if user is not None and password is not None:
            self.db.authenticate(user, password)
        log.msg('%s connected to %s:%s, using database \'%s\'' %
                (self.__class__.__name__, client.host, client.port, db),
                level=log.DEBUG)
        self.fs = {}
示例#22
0
    def test_passive_and_hidden(self):
        self.c = MongoReplicaSetClient(self.seed,
                                       replicaSet=self.name,
                                       use_greenlets=use_greenlets)

        passives = ha_tools.get_passives()
        passives = [_partition_node(member) for member in passives]
        self.assertEqual(self.c.secondaries, set(passives))

        for mode in SECONDARY, SECONDARY_PREFERRED:
            utils.assertReadFromAll(self, self.c, passives, mode)

        ha_tools.kill_members(ha_tools.get_passives(), 2)
        sleep(2 * MONITOR_INTERVAL)
        utils.assertReadFrom(self, self.c, self.c.primary, SECONDARY_PREFERRED)
示例#23
0
 def _establish_connection(cls, *args, **kwargs):
     for i in range(MAX_ATTEMPTS - 1):
         try:
             if 'replicaSet' in kwargs:
                 return MongoReplicaSetClient(*args, **kwargs)
             else:
                 return MongoClient(*args, **kwargs)
         except ConnectionFailure as e:
             logging.error(
                 'Fail to connect to %s, %s [%s]', args, kwargs, e)
             sleep(CONNECT_SLEEP_TIME)
     if 'replicaSet' in kwargs:
         return MongoReplicaSetClient(*args, **kwargs)
     else:
         return MongoClient(*args, **kwargs)
示例#24
0
    def test_stepdown_triggers_refresh(self):
        c_find_one = MongoReplicaSetClient(self.seed,
                                           replicaSet=self.name,
                                           use_greenlets=use_greenlets)

        # We've started the primary and one secondary
        primary = ha_tools.get_primary()
        secondary = ha_tools.get_secondaries()[0]
        self.assertEqual(one(c_find_one.secondaries),
                         _partition_node(secondary))

        ha_tools.stepdown_primary()

        # Make sure the stepdown completes
        sleep(1)

        # Trigger a refresh
        self.assertRaises(AutoReconnect, c_find_one.test.test.find_one)

        # Wait for the immediate refresh to complete - we're not waiting for
        # the periodic refresh, which has been disabled
        sleep(1)

        # We've detected the stepdown
        self.assertTrue(not c_find_one.primary
                        or primary != _partition_node(c_find_one.primary))
def getClient(conf, dbname):
    '''
        conf : json  conf objet
        conf=load_conf(configfile)
        db = getClient(conf)['ceph']
        collection =db['cluster']
        cursor=collection.find_one()
        Return  a connexion to  database specified  in  conf file
        take care with authentication
    '''
    mongodb_host = conf.get("mongodb_host", "127.0.0.1")
    mongodb_port = conf.get("mongodb_port", "27017")
    mongodb_URL = "mongodb://" + mongodb_host + ":" + str(mongodb_port)
    #mongodb replication
    is_mongo_replicat = conf.get("is_mongo_replicat", 0)
    mongodb_set = "'" + conf.get("mongodb_set", "") + "'"
    mongodb_replicaSet = conf.get("mongodb_replicaSet", None)
    mongodb_read_preference = conf.get("mongodb_read_preference", None)

    if is_mongo_replicat == 1:
        client = MongoReplicaSetClient(
            eval(mongodb_set),
            replicaSet=mongodb_replicaSet,
            read_preference=eval(mongodb_read_preference))
    else:
        #if not replicated
        client = MongoClient(mongodb_URL)
    # mongo db  authentication
    is_mongo_authenticate = conf.get("is_mongo_authenticate", 0)
    mongodb_user = conf.get("mongodb_user", "ceph")
    mongodb_passwd = conf.get("mongodb_passwd", "empty")
    if is_mongo_authenticate == 1:
        client[dbname].authenticate(mongodb_user, mongodb_passwd)

    return client[dbname]
示例#26
0
    def test_read_with_failover(self):
        c = MongoReplicaSetClient(self.seed,
                                  replicaSet=self.name,
                                  use_greenlets=use_greenlets)
        self.assertTrue(bool(len(c.secondaries)))

        def iter_cursor(cursor):
            for _ in cursor:
                pass
            return True

        db = c.pymongo_test
        w = len(c.secondaries) + 1
        db.test.remove({}, w=w)
        # Force replication
        db.test.insert([{'foo': i} for i in xrange(10)], w=w)
        self.assertEqual(10, db.test.count())

        db.read_preference = SECONDARY_PREFERRED
        cursor = db.test.find().batch_size(5)
        cursor.next()
        self.assertEqual(5, cursor._Cursor__retrieved)
        self.assertTrue(cursor._Cursor__connection_id in c.secondaries)
        ha_tools.kill_primary()
        # Primary failure shouldn't interrupt the cursor
        self.assertTrue(iter_cursor(cursor))
        self.assertEqual(10, cursor._Cursor__retrieved)
示例#27
0
def mongoDBHelper(dbName, readOnly=False):
    global connection
    if len(app_config.MONGODB_CONFIG) == 0:
        connection = None
        return
    try:
        connection
    except NameError:
        if app_config.MONGODB_CONFIG['RS'] != "":
            connection = MongoReplicaSetClient(
                app_config.MONGODB_CONFIG['URL'],
                replicaSet=app_config.MONGODB_CONFIG['RS'])
        else:
            connection = MongoClient(app_config.MONGODB_CONFIG['URL'])

    db = connection[dbName]
    if 'AUTH' in app_config.MONGODB_CONFIG:
        if 'true' == app_config.MONGODB_CONFIG['AUTH']:
            db.authenticate(app_config.MONGODB_CONFIG['USER'],
                            app_config.MONGODB_CONFIG['PASSWORD'])
        else:
            pass
    # if readOnly:
    #     db.read_preference = ReadPreference.SECONDARY_PREFERRED
    # else:
    #     db.read_preference = ReadPreference.PRIMARY_PREFERRED
    return db
示例#28
0
    def test_recovering_member_triggers_refresh(self):
        # To test that find_one() and count() trigger immediate refreshes,
        # we'll create a separate client for each
        self.c_find_one, self.c_count = [
            MongoReplicaSetClient(self.seed,
                                  replicaSet=self.name,
                                  use_greenlets=use_greenlets,
                                  read_preference=SECONDARY) for _ in xrange(2)
        ]

        # We've started the primary and one secondary
        primary = ha_tools.get_primary()
        secondary = ha_tools.get_secondaries()[0]

        # Pre-condition: just make sure they all connected OK
        for c in self.c_find_one, self.c_count:
            self.assertEqual(one(c.secondaries), _partition_node(secondary))

        ha_tools.set_maintenance(secondary, True)

        # Trigger a refresh in various ways
        self.assertRaises(AutoReconnect, self.c_find_one.test.test.find_one)
        self.assertRaises(AutoReconnect, self.c_count.test.test.count)

        # Wait for the immediate refresh to complete - we're not waiting for
        # the periodic refresh, which has been disabled
        sleep(1)

        for c in self.c_find_one, self.c_count:
            self.assertFalse(c.secondaries)
            self.assertEqual(_partition_node(primary), c.primary)
示例#29
0
    def get_mongo(self):
        """Return the mongo connection from the environment."""
        if self.mongo_db:
            return self.mongo_db

        if len(self.uri_params['nodelist']) > 1 and MongoReplicaSetClient:
            nodes = ','.join(
                ['%s:%d' % n for n in self.uri_params['nodelist']])
            client = MongoReplicaSetClient(nodes, **self.uri_params['options'])
        else:
            client = MongoClient(self.uri_params['nodelist'][0][0],
                                 self.uri_params['nodelist'][0][1],
                                 **self.uri_params['options'])

        db = client[self.uri_params['database']]
        if self.uri_params['username']:
            if not db.authenticate(self.uri_params['username'],
                                   self.uri_params['password']):
                raise PluginError('Cannot authenticate to MongoDB for '
                                  'user: %s' % self.uri_params['username'])

        if self.post_create:
            db = self.post_create(db)

        self.mongo_db = db

        return self.mongo_db
示例#30
0
    def test_rs_client_attrs(self):
        pymongo_rs_client_only = set(['pool_class']).union(pymongo_client_only)

        sync_cx_rs = MongoReplicaSetClient(env.rs_uri)
        self.assertEqual(
            attrs(sync_cx_rs) - pymongo_rs_client_only,
            attrs(self.rsc) - motor_client_only)
def getClient(conf):
    '''
        Return  a connexion to  database specified  in  conf file
        take care with autentication
    '''
    mongodb_host = conf.get("mongodb_host", "127.0.0.1")
    mongodb_port = conf.get("mongodb_port", "27017")
    mongodb_URL = "mongodb://"+str(mongodb_host)+":"+str(mongodb_port)
    #mongodb replication
    is_mongo_replicat = conf.get("is_mongo_replicat", 0)
    mongodb_set = "'"+conf.get("mongodb_set","")+"'"
    mongodb_replicaSet =conf.get("mongodb_replicaSet",None)
    mongodb_read_preference = conf.get("mongodb_read_preference",None)
    cluster = conf.get("cluster", "ceph")
    if is_mongo_replicat ==  1:
        client = MongoReplicaSetClient(eval(mongodb_set), replicaSet=mongodb_replicaSet, read_preference=eval(mongodb_read_preference))
    else:
        #if not replicated
        client = MongoClient(mongodb_URL)
    # mongo db  authentication
    is_mongo_authenticate = conf.get("is_mongo_authenticate", 0)
    mongodb_user = conf.get("mongodb_user", "ceph")
    mongodb_passwd = conf.get("mongodb_passwd", "empty")
    if is_mongo_authenticate == 1:
        client[cluster].authenticate(mongodb_user,mongodb_passwd)
    return client
示例#32
0
def startapp(app):
    # do not display server and version information
    # https://stackoverflow.com/a/55209796/2249798
    # https://stackoverflow.com/a/54947461/2249798
    cherrypy.__version__ = ""
    cherrypy.config.update({"response.headers.server": ""})
    cherrypy._cperror._HTTPErrorTemplate = \
        cherrypy._cperror._HTTPErrorTemplate.replace(
            "Powered by <a href=\"http://www.cherrypy.org\">"
            + "CherryPy %(version)s</a>\n",
            "%(version)s"
        )

    if config["mongodb"].getboolean('replicaset'):
        print("Connecting to MongoDB ReplicaSet: %s" %
              config["mongodb"]["url"])
        dbe = MongoReplicaSetClient(config["mongodb"]["url"],
                                    w="majority",
                                    maxPoolSize=16,
                                    socketTimeoutMS=60000,
                                    connectTimeoutMS=30000,
                                    waitQueueTimeoutMS=60000,
                                    waitQueueMultiple=64)
        atexit.register(dbe.close)
    else:
        print("Connecting to MongoDB: %s" % config["mongodb"]["url"])
        dbe = MongoClient(config["mongodb"]["url"],
                          maxPoolSize=16,
                          socketTimeoutMS=60000,
                          connectTimeoutMS=30000,
                          waitQueueTimeoutMS=60000,
                          waitQueueMultiple=64)
    dbm = dbe[config["mongodb"]["dbname"]]
    return cherrypy.Application(app(dbm), script_name=None, config=None)
示例#33
0
    def test_cert_ssl_validation_hostname_fail(self):
        # Expects the server to be running with the server.pem, ca.pem
        # and crl.pem provided in mongodb and the server tests eg:
        #
        #   --sslPEMKeyFile=jstests/libs/server.pem
        #   --sslCAFile=jstests/libs/ca.pem
        #   --sslCRLFile=jstests/libs/crl.pem
        if not CERT_SSL:
            raise SkipTest("No mongod available over SSL with certs")

        client = MongoClient(host, port, ssl=True, ssl_certfile=CLIENT_PEM)
        response = client.admin.command('ismaster')

        try:
            MongoClient(pair,
                        ssl=True,
                        ssl_certfile=CLIENT_PEM,
                        ssl_cert_reqs=ssl.CERT_REQUIRED,
                        ssl_ca_certs=CA_PEM)
            self.fail("Invalid hostname should have failed")
        except CertificateError:
            pass

        if 'setName' in response:
            try:
                MongoReplicaSetClient(pair,
                                      replicaSet=response['setName'],
                                      w=len(response['hosts']),
                                      ssl=True,
                                      ssl_certfile=CLIENT_PEM,
                                      ssl_cert_reqs=ssl.CERT_REQUIRED,
                                      ssl_ca_certs=CA_PEM)
                self.fail("Invalid hostname should have failed")
            except CertificateError:
                pass
示例#34
0
    def test_cert_ssl_implicitly_set(self):
        # Expects the server to be running with the server.pem, ca.pem
        # and crl.pem provided in mongodb and the server tests eg:
        #
        #   --sslPEMKeyFile=jstests/libs/server.pem
        #   --sslCAFile=jstests/libs/ca.pem
        #   --sslCRLFile=jstests/libs/crl.pem
        #
        # Also requires an /etc/hosts entry where "server" is resolvable
        if not CERT_SSL:
            raise SkipTest("No mongod available over SSL with certs")

        client = MongoClient(host, port, ssl_certfile=CLIENT_PEM)
        response = client.admin.command('ismaster')
        if 'setName' in response:
            client = MongoReplicaSetClient(pair,
                                           replicaSet=response['setName'],
                                           w=len(response['hosts']),
                                           ssl_certfile=CLIENT_PEM)

        db = client.pymongo_ssl_test
        db.test.drop()
        self.assertTrue(db.test.insert({'ssl': True}))
        self.assertTrue(db.test.find_one()['ssl'])
        client.drop_database('pymongo_ssl_test')
示例#35
0
    def test_gssapi_threaded(self):

        # Use auto_start_request=True to make sure each thread
        # uses a different socket.
        client = MongoClient(GSSAPI_HOST, auto_start_request=True)
        self.assertTrue(client.test.authenticate(PRINCIPAL,
                                                 mechanism='GSSAPI'))

        threads = []
        for _ in xrange(4):
            threads.append(AutoAuthenticateThread(client.foo))
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()
            self.assertTrue(thread.success)

        set_name = client.admin.command('ismaster').get('setName')
        if set_name:
            preference = ReadPreference.SECONDARY
            client = MongoReplicaSetClient(GSSAPI_HOST,
                                           replicaSet=set_name,
                                           read_preference=preference)
            self.assertTrue(
                client.test.authenticate(PRINCIPAL, mechanism='GSSAPI'))
            self.assertTrue(client.foo.command('dbstats'))

            threads = []
            for _ in xrange(4):
                threads.append(AutoAuthenticateThread(client.foo))
            for thread in threads:
                thread.start()
            for thread in threads:
                thread.join()
                self.assertTrue(thread.success)
示例#36
0
def QueryFunc(addr, insertnum):
    print "query process"
    contentsrc = "objids_0113.txt"
    f = open(contentsrc, "r")
    print "h0"
    mm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    print "hi"
    fsize = os.path.getsize(contentsrc)
    numtopicids = fsize / 24
    addrnew = addr + ":29002"
    print "h1"
    client = MongoReplicaSetClient(addrnew, replicaSet="rs0")
    db = client.topicdb
    collection = db.topiccol
    count = 0
    totinsertnum = insertnum * 3
    print "h2"
    while count < totinsertnum:
        topicidstart = random.randint(0, numtopicids - 1) * 24
        topicidsend = topicidstart + 24
        rand_topicid = mm[topicidstart:topicidsend]
        try:
            #collection.find_one({"_id":ObjectId(rand_topicid)}, read_preference=ReadPreference.SECONDARY_PREFERRED)
            collection.find_one(
                {"_id": ObjectId(rand_topicid)},
                read_preference=ReadPreference.SECONDARY_PREFERRED)
            #print "q id:", rand_topicid
            #collection.find_one({"_id":ObjectId(rand_topicid)})
        except pymongo.errors.AutoReconnect:
            print "auto reconnect"
            time.sleep(2)
            continue
        count += 1
    mm.close()
示例#37
0
def InsertFunc(addr, insertnum):
    contentsrc = "cs.txt"
    f = open(contentsrc, "r")
    mm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)
    fsize = os.path.getsize(contentsrc)
    addrnew = addr + ":29002"
    client = MongoReplicaSetClient(addrnew, replicaSet="rs0")
    db = client.topicdb
    collection = db.topiccol
    count = 0
    while count < insertnum:
        post = GenerateTopicPost(mm, fsize)
        try:
            collection.insert(post)
        except InvalidStringData:
            continue
        except pymongo.errors.AutoReconnect:
            print "insert auto reconnect", time.ctime(time.time())
            time.sleep(5)
            print "sleep over", time.ctime(time.time())
            continue
            print "continue:", count
        except Exception, e:
            print e
        count += 1
示例#38
0
    def test_writes_with_failover(self):
        c = MongoReplicaSetClient(self.seed,
                                  replicaSet=self.name,
                                  use_greenlets=use_greenlets)
        primary = c.primary
        db = c.pymongo_test
        w = len(c.secondaries) + 1
        db.test.remove({}, w=w)
        db.test.insert({'foo': 'bar'}, w=w)
        self.assertEqual('bar', db.test.find_one()['foo'])

        def try_write():
            for _ in xrange(30):
                try:
                    db.test.insert({'bar': 'baz'})
                    return True
                except AutoReconnect:
                    sleep(1)
            return False

        killed = ha_tools.kill_primary(9)
        self.assertTrue(bool(len(killed)))
        self.assertTrue(try_write())
        self.assertTrue(primary != c.primary)
        self.assertEqual('baz', db.test.find_one({'bar': 'baz'})['bar'])
示例#39
0
    def test_secondary_failure(self):
        c = MongoReplicaSetClient(self.seed,
                                  replicaSet=self.name,
                                  use_greenlets=use_greenlets)
        self.assertTrue(bool(len(c.secondaries)))
        primary = c.primary
        secondaries = c.secondaries

        def readers_changed():
            for _ in xrange(20):
                if c.secondaries != secondaries:
                    return True

                sleep(1)
            return False

        killed = ha_tools.kill_secondary()
        sleep(2 * MONITOR_INTERVAL)
        self.assertTrue(bool(len(killed)))
        self.assertEqual(primary, c.primary)
        self.assertTrue(readers_changed())
        secondaries = c.secondaries

        ha_tools.restart_members([killed])
        self.assertEqual(primary, c.primary)
        self.assertTrue(readers_changed())
示例#40
0
class TestReplicaSetAuth(unittest.TestCase):
    def setUp(self):
        members = [
            {},
            {'priority': 0},
            {'priority': 0},
        ]

        res = ha_tools.start_replica_set(members, auth=True)
        self.c = MongoReplicaSetClient(res[0], replicaSet=res[1],
                                       use_greenlets=use_greenlets)

        # Add an admin user to enable auth
        self.c.admin.add_user('admin', 'adminpass')
        self.c.admin.authenticate('admin', 'adminpass')

        self.db = self.c.pymongo_ha_auth
        self.db.add_user('user', 'userpass')
        self.c.admin.logout()

    def test_auth_during_failover(self):
        self.assertTrue(self.db.authenticate('user', 'userpass'))
        self.assertTrue(self.db.foo.insert({'foo': 'bar'},
                                           safe=True, w=3, wtimeout=1000))
        self.db.logout()
        self.assertRaises(OperationFailure, self.db.foo.find_one)

        primary = '%s:%d' % self.c.primary
        ha_tools.kill_members([primary], 2)

        # Let monitor notice primary's gone
        sleep(2 * MONITOR_INTERVAL)

        # Make sure we can still authenticate
        self.assertTrue(self.db.authenticate('user', 'userpass'))
        # And still query.
        self.db.read_preference = PRIMARY_PREFERRED
        self.assertEqual('bar', self.db.foo.find_one()['foo'])

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
示例#41
0
    def test_alive(self):
        primary = ha_tools.get_primary()
        secondary = ha_tools.get_random_secondary()
        primary_cx = MongoClient(primary, use_greenlets=use_greenlets)
        secondary_cx = MongoClient(secondary, use_greenlets=use_greenlets)
        rsc = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        try:
            self.assertTrue(primary_cx.alive())
            self.assertTrue(secondary_cx.alive())
            self.assertTrue(rsc.alive())
    
            ha_tools.kill_primary()
            time.sleep(0.5)

            self.assertFalse(primary_cx.alive())
            self.assertTrue(secondary_cx.alive())
            self.assertFalse(rsc.alive())
            
            ha_tools.kill_members([secondary], 2)
            time.sleep(0.5)

            self.assertFalse(primary_cx.alive())
            self.assertFalse(secondary_cx.alive())
            self.assertFalse(rsc.alive())
        finally:
            rsc.close()
示例#42
0
    def _mongo(self, instances, force=False):
        if not hasattr(AwsMongoBackup, 'mongo') or force:
            mongo_rs_str = ','.join([x.public_dns_name for x in instances])
            self.logger.debug("connecting to mongo URI %s" % mongo_rs_str)
            self.mongo = MongoReplicaSetClient(
                mongo_rs_str,
                replicaSet=self.replicaset
            )

            if self.mongo.alive():
                return self.mongo
            else:
                self.mongo = None
                return None
示例#43
0
	def __getitem__(self, alias):
		if alias in self._connections:
			return self._connections[alias]
		
		try:
			conn = self.databases[alias]
		except KeyError:
			raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)
		
		if type(conn['location']) == type([]):
			conn['location'] = ','.join(conn['location'])
			
		if 'replicaSet' in conn:
			conn = MongoReplicaSetClient(conn['location'], replicaSet=conn['replicaSet'], safe=True, w=2, j=True)
			conn.read_preferences = ReadPreference.PRIMARY_PREFERRED
			conn.write_concerns = {'w': 2, 'j':True} # para sure
		else:
#			conn = MongoClient(conn['location'], safe=True, w=2, j=True)
			conn = MongoClient(conn['location'], safe=True)

		self._connections[alias] = ConnectionWrapper(conn, self.databases[alias]['name'], config=self.databases)
			
		return self._connections[alias]
示例#44
0
    def setUp(self):
        members = [
            # primary
            {'tags': {'dc': 'ny', 'name': 'primary'}},

            # secondary
            {'tags': {'dc': 'la', 'name': 'secondary'}, 'priority': 0},

            # other_secondary
            {'tags': {'dc': 'ny', 'name': 'other_secondary'}, 'priority': 0},
        ]

        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

        primary = ha_tools.get_primary()
        self.primary = _partition_node(primary)
        self.primary_tags = ha_tools.get_tags(primary)
        # Make sure priority worked
        self.assertEqual('primary', self.primary_tags['name'])

        self.primary_dc = {'dc': self.primary_tags['dc']}

        secondaries = ha_tools.get_secondaries()

        (secondary, ) = [
            s for s in secondaries
            if ha_tools.get_tags(s)['name'] == 'secondary']

        self.secondary = _partition_node(secondary)
        self.secondary_tags = ha_tools.get_tags(secondary)
        self.secondary_dc = {'dc': self.secondary_tags['dc']}

        (other_secondary, ) = [
            s for s in secondaries
            if ha_tools.get_tags(s)['name'] == 'other_secondary']

        self.other_secondary = _partition_node(other_secondary)
        self.other_secondary_tags = ha_tools.get_tags(other_secondary)
        self.other_secondary_dc = {'dc': self.other_secondary_tags['dc']}

        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)
        self.db = self.c.pymongo_test
        self.w = len(self.c.secondaries) + 1
        self.db.test.remove({}, w=self.w)
        self.db.test.insert(
            [{'foo': i} for i in xrange(10)], w=self.w)

        self.clear_ping_times()
示例#45
0
    def test_passive_and_hidden(self):
        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        passives = ha_tools.get_passives()
        passives = [_partition_node(member) for member in passives]
        self.assertEqual(self.c.secondaries, set(passives))

        for mode in SECONDARY, SECONDARY_PREFERRED:
            utils.assertReadFromAll(self, self.c, passives, mode)

        ha_tools.kill_members(ha_tools.get_passives(), 2)
        sleep(2 * MONITOR_INTERVAL)
        utils.assertReadFrom(self, self.c, self.c.primary, SECONDARY_PREFERRED)
示例#46
0
def init_mongodb_client(conf_item):
    section = conf_item
    servers = section.get('servers')

    def build_node_desc(node_conf):
        return '%s:%s' % (node_conf['host'], node_conf['port'])

    if section.get('replica', False):
        from pymongo import MongoReplicaSetClient
        from pymongo import ReadPreference

        client = MongoReplicaSetClient(','.join(map(build_node_desc, servers)), replicaSet=section.get('replName'))
        pref = section.get('readPref', 'PRIMARY')
        client.read_preference = getattr(ReadPreference, pref)
    else:
        from pymongo import MongoClient

        s = servers[0]
        client = MongoClient(s['host'], s['port'])

    setattr(client, 'auth_list', set([]))

    return client
示例#47
0
    def test_monitor_removes_recovering_member(self):
        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        secondaries = ha_tools.get_secondaries()

        for mode in SECONDARY, SECONDARY_PREFERRED:
            partitioned_secondaries = [_partition_node(s) for s in secondaries]
            utils.assertReadFromAll(self, self.c, partitioned_secondaries, mode)

        secondary, recovering_secondary = secondaries
        ha_tools.set_maintenance(recovering_secondary, True)
        sleep(2 * MONITOR_INTERVAL)

        for mode in SECONDARY, SECONDARY_PREFERRED:
            # Don't read from recovering member
            utils.assertReadFrom(self, self.c, _partition_node(secondary), mode)
示例#48
0
    def setUp(self):
        members = [
            {},
            {'priority': 0},
            {'priority': 0},
        ]

        res = ha_tools.start_replica_set(members, auth=True)
        self.c = MongoReplicaSetClient(res[0], replicaSet=res[1],
                                       use_greenlets=use_greenlets)

        # Add an admin user to enable auth
        self.c.admin.add_user('admin', 'adminpass')
        self.c.admin.authenticate('admin', 'adminpass')

        self.db = self.c.pymongo_ha_auth
        self.db.add_user('user', 'userpass')
        self.c.admin.logout()
示例#49
0
class AwsMongoBackup(object):

    def __init__(self,
                 replicaset=None,
                 filters=None,
                 instance_ids=None,
                 ssh_opts=None,
                 dryrun=False,
                 region=None,
                 logger=None):
        self.creation_time = datetime.utcnow().strftime("%m-%d-%Y %H:%M:%S")

        if logger is not None:
            self.logger = logger

        if region is None:
            region = 'us-east-1'

        if AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY:
            self.ec2 = ec2_connect_to_region(
                region,
                aws_access_key_id=AWS_ACCESS_KEY_ID,
                aws_secret_access_key=AWS_SECRET_ACCESS_KEY
            )
        else:
            self.ec2 = ec2_connect_to_region(
                region
            )

        if replicaset is None:
            raise RuntimeError('replicaset must be provided.')

        self.replicaset = replicaset

        if filters:
            self.instances = self._instances_via_filters(filters=filters)
        elif instance_ids:
            self.instances = self._instances_via_ids(instance_ids=instance_ids)
        else:
            raise RuntimeError('Either an API filter or a list of instance'
                               'IDs must be provided.')
        self.logger.debug("found instances %s" % self.instances)

        self.mongo = self._mongo(instances=self.instances)
        self.logger.debug("connected to mongo %s" % self.mongo)

        self.ssh_opts = ssh_opts
        self.logger.debug("set ssh opts to %s" % self.ssh_opts)

        self.dryrun = dryrun

    def _instances_via_filters(self, filters=None):
        if filters is None:
            raise ValueError('filters must be a dict of valid EC2 API filters')

        reservations = self.ec2.get_all_instances(
            filters=filters
        )

        instances = []

        for reservation in reservations:
            instances.extend(reservation.instances)

        return instances

    def _instances_via_ids(self, instance_ids=None):
        if instance_ids is None or type(instance_ids) is not 'list':
            raise ValueError('instances must be provided in a list')

        raise NotImplementedError("I'll come back to this later.")

    def _mongo(self, instances, force=False):
        if not hasattr(AwsMongoBackup, 'mongo') or force:
            mongo_rs_str = ','.join([x.public_dns_name for x in instances])
            self.logger.debug("connecting to mongo URI %s" % mongo_rs_str)
            self.mongo = MongoReplicaSetClient(
                mongo_rs_str,
                replicaSet=self.replicaset
            )

            if self.mongo.alive():
                return self.mongo
            else:
                self.mongo = None
                return None

    def _ssh(self, hostname, ssh_opts):
        self.ssh = SSHClient()
        self.ssh.set_missing_host_key_policy(AutoAddPolicy())
        self.ssh.connect(hostname=hostname, **ssh_opts)

        self.logger.debug("connected via ssh to %s" % hostname)

        return self.ssh

    def test_replicaset(self):
        test_result = True
        err_str = ''

        optime_dates = []
        rs_states = {}
        hidden_members = []

        rs_status = self.mongo.admin.command('replSetGetStatus')
        rs_member_hosts = [z[0] for z in self.mongo.hosts]

        for rs_member in rs_status['members']:
            if rs_member['name'].split(':')[0] not in rs_member_hosts:
                hidden_members.append((
                    rs_member['name'].split(':')[0],
                    int(rs_member['name'].split(':')[1])
                ))
            try:
                rs_states[rs_member['state']] += 1
            except KeyError:
                rs_states[rs_member['state']] = 1

            if rs_member['state'] not in [1, 2, 7]:
                # primary, secondary, arbiter
                err_str = "RS member {rs_member} has a state of {state}, "\
                    "please check RS integrity and try again."\
                    .format(
                        rs_member=rs_member['name'],
                        state=rs_member['stateStr']
                    )
                test_result = False
                return (test_result, err_str)
            self.logger.debug("member %s passed state" % rs_member['name'])

            if rs_member.get('health', 1) != 1:
                err_str = "RS member {rs_member} is marked as unhealthy, "\
                    "please check RS integrity and try again."\
                    .format(rs_member=rs_member['name'])
                test_result = False
                return (test_result, err_str)
            self.logger.debug("member %s passed health" % rs_member['name'])

            if rs_member.get('pingMs', 0) > 10:
                err_str = "ping time for RS member {rs_member} is larger than"\
                    "10ms.  Please check network connectivity and try again."\
                    .format(rs_member=rs_member['name'])
                test_result = False
                return (test_result, err_str)
            self.logger.debug("member %s passed pingMs" % rs_member['name'])

            optime_dates.append(rs_member['optimeDate'])

        self.hidden_members = hidden_members

        if (max(optime_dates) - min(optime_dates)).total_seconds() > 5:
            err_str = "optimeDates is over 5 seconds, there is too much "\
                "replication lag to continue."
            test_result = False
            return (test_result, err_str)
        self.logger.debug("passed replication lag test")

        if len(self.mongo.secondaries) + len(hidden_members) < 2:
            err_str = "There needs to be at least two secondaries or a hidden"\
                " member available to do backups.  Please check RS integrity "\
                "and try again."
            test_result = False
            return (test_result, err_str)

        self.logger.debug("mongo secondaries test passed")

        if rs_states[1] != 1:
            err_str = "There needs to be one and exactly one mongo primary to"\
                " do backups.  Please check RS integrity and try again."
            test_result = False
            return (test_result, err_str)
        self.logger.debug("passed primary mongo test")

        return (test_result, err_str)

    def choose_member(self):
        if self.hidden_members:
            return self.hidden_members.pop()
        else:
            return self.mongo.secondaries.pop()

    def backup(self):
        # Test that the replica set is in a good state to perform backups
        test_result, err_str = self.test_replicaset()
        if test_result is False:
            raise RuntimeError(err_str)

        # Choose a member from which to back up
        backup_member = self.choose_member()

        self._ssh(backup_member[0], self.ssh_opts)

        # Get the instance ID
        stdin, stdout, stderr = self.ssh.exec_command(
            '/usr/bin/curl http://169.254.169.254/latest/meta-data/instance-id'
        )

        instance_id = stdout.readline().rstrip()
        self.logger.debug("Working on instance %s" % instance_id)

        reservation = self.ec2.get_all_instances(instance_ids=[instance_id, ])
        instance = reservation[0].instances[0]

        self.logger.debug("got boto ec2 instance %s" % instance)

        # Connect to the backup target directly
        backup_member_mongo = MongoClient(
            host=backup_member[0],
            port=backup_member[1]
        )
        self.logger.debug("connected to mongo target %s" % backup_member_mongo)

        freeze_rs = True
        if backup_member_mongo.admin.command('isMaster').get('hidden', False):
            # This member is hidden so we can safely take backups without
            # doing any other maintenance work
            freeze_rs = False

        # Find what volume database data is on
        cfg = backup_member_mongo.admin.command('getCmdLineOpts')

        cfg_data_volume = cfg['parsed']['dbpath']

        self.logger.debug("found parsed dbpath of %s" % cfg_data_volume)

        stdin, stdout, stderr = self.ssh.exec_command(
            '/usr/bin/sudo /bin/df {cfg_data_volume} | '
            '/bin/grep -v "Filesystem"'
            .format(cfg_data_volume=cfg_data_volume)
        )

        mount_info = stdout.readline().rstrip()
        mount_info = mount_info.split(' ')[0]

        self.logger.debug("working on mount %s" % mount_info)

        # Find the matching EBS volume for this mount point
        volumes = self.ec2.get_all_volumes(
            filters={'attachment.instance-id': instance_id}
        )

        data_volume = None
        for volume in volumes:
            # There's a strange thing that happens, /dev/sdh1 can magically
            # become /dev/xdh1 at boot time on instances.  Check for both.
            volume_mount_point = volume.attach_data.device
            if volume_mount_point == mount_info or \
                    volume_mount_point.replace('sd', 'xvd') == mount_info:
                data_volume = volume

        if data_volume is None:
            raise RuntimeError("Couldn't find EBS data volume!")

        self.logger.debug("found data volume %s" % data_volume)

        # Remove the member from the replicaset (mark as hidden)
        if freeze_rs:
            # Can probably use replSetMaintenance here but not available
            # in my testing version
            if self.dryrun:
                self.logger.debug("Would have frozen replicaset")
            else:
                self.logger.debug('Freezing replicaset')
                backup_member_mongo.admin.command({'replSetFreeze': 86400})

        else:
            self.logger.debug(
                "skipping replicaset freeze, %s is a hidden member"
                % backup_member[0]
            )

        # Fsynclock mongo
        if self.dryrun:
            self.logger.debug(
                "Would have fsynclocked {backup_member}"
                .format(backup_member=backup_member)
            )
        else:
            self.logger.debug(
                "fsync/locking {backup_member}"
                .format(backup_member=backup_member)
            )
            backup_member_mongo.fsync(lock=True)

        if self.dryrun:
            self.logger.debug(
                "Would have created snapshot of volume {volume}"
                .format(volume=data_volume)
            )
            self.current_snapshot = None
        else:
            self.logger.debug("creating snapshot of %s" % data_volume)
            snapshot = data_volume.create_snapshot(
                description="mongobackup {date} {replicaset}".format(
                    date=self.creation_time,
                    replicaset=self.replicaset)
            )

            self.current_snapshot = snapshot.id

            tags = {
                'replicaset': self.replicaset,
                'sourcehost': backup_member[0],
                'creation_time': self.creation_time
            }
            self.logger.debug(
                "adding tags %s to snapshot %s" % (tags, snapshot)
            )

            self.ec2.create_tags(
                resource_ids=[snapshot.id, ],
                tags=tags
            )

        # Unlock mongo
        if self.dryrun:
            self.logger.debug("Would have unlocked mongo")
        else:
            if freeze_rs:
                self.logger.debug('unfreezing replicaset')
                backup_member_mongo.admin.command({'replSetFreeze': 0})

            self.logger.debug(
                "unlocking {backup_member}"
                .format(backup_member=backup_member)
            )
            backup_member_mongo.unlock()
示例#50
0
 def setUp(self):
     members = [{}, {}, {'arbiterOnly': True}]
     res = ha_tools.start_replica_set(members)
     self.c = MongoReplicaSetClient(res[0], replicaSet=res[1],
                                    use_greenlets=use_greenlets,
                                    auto_start_request=True)
示例#51
0
    def __new__(mcs, name, bases, attrs):
        new_class = super(ModelBase,
                          mcs).__new__(mcs, name, bases, attrs)
        parents = [b for b in bases if isinstance(b, ModelBase)]
        if not parents:
            # If this isn't a subclass of Model, don't do anything special.
            return new_class

        # Processing Model metadata.
        try:
            meta = getattr(new_class, 'Meta')
        except AttributeError:
            meta = None
        else:
            # Won't need the original metadata container anymore.
            delattr(new_class, 'Meta')

        options = _Options(meta)
        options.collection = options.collection or to_underscore(name)

        if options.interface:
            new_class._meta = None
            new_class.database = None
            new_class.collection = DummyCollection
            return new_class

        if not (options.host and options.port and options.database):
            raise Exception(
                'Model %r improperly configured: %s %s %s' % (
                    name, options.host, options.port, options.database))

        # Checking connection / client pool for an existing connection / client.
        pool_key = options.host,options.port
        if options.replica_set_name:
            logging.debug("Using replica_set_name=%s as database pool key." % options.replica_set_name)
            pool_key = options.replica_set_name

        if pool_key in mcs._connections:
            client = mcs._connections[pool_key]
            logging.debug("Got database client from pool for pool_key=%s" % (pool_key,))
        else:
            logging.debug("Creating new database client for pool_key=%s" % (pool_key,))
            if options.replica_set_name:
                logging.debug("Setting up a replica set client...")
                client = MongoReplicaSetClient(options.replica_set_uri, replicaSet=options.replica_set_name)
                client.read_preference = ReadPreference.SECONDARY_PREFERRED
            else:
                logging.debug("Setting up a normal client...")
                client = MongoClient(options.host, options.port)

            mcs._connections[pool_key] = client

        new_class._meta = options
        new_class.connection = client
        new_class.database = client[options.database]
        if options.username and options.password:
            new_class.database.authenticate(options.username, options.password)
        new_class.collection = options.collection_class(
            new_class.database, options.collection, document_class=new_class)

        if options.auto_index:
            new_class.auto_index()   # Generating required indices.

        return new_class
示例#52
0
 def __init__(self, *args, **kwargs):
     # Specifying that it should run both the inits
     MongoKitConnection.__init__(self, *args, **kwargs)
     PymongoReplicaSetConnection.__init__(self, *args, **kwargs)
示例#53
0
文件: db.py 项目: liuct/bugquery-lt
 def getMongoDB(self):
     conn=MongoReplicaSetClient(Config['ReplicaSetServer'], replicaSet=Config['ReplicaSetName'])
     conn.read_preference = ReadPreference.SECONDARY_PREFERRED
     return conn.bugreporter
示例#54
0
class TestReadPreference(unittest.TestCase):
    def setUp(self):
        members = [
            # primary
            {'tags': {'dc': 'ny', 'name': 'primary'}},

            # secondary
            {'tags': {'dc': 'la', 'name': 'secondary'}, 'priority': 0},

            # other_secondary
            {'tags': {'dc': 'ny', 'name': 'other_secondary'}, 'priority': 0},
        ]

        res = ha_tools.start_replica_set(members)
        self.seed, self.name = res

        primary = ha_tools.get_primary()
        self.primary = _partition_node(primary)
        self.primary_tags = ha_tools.get_tags(primary)
        # Make sure priority worked
        self.assertEqual('primary', self.primary_tags['name'])

        self.primary_dc = {'dc': self.primary_tags['dc']}

        secondaries = ha_tools.get_secondaries()

        (secondary, ) = [
            s for s in secondaries
            if ha_tools.get_tags(s)['name'] == 'secondary']

        self.secondary = _partition_node(secondary)
        self.secondary_tags = ha_tools.get_tags(secondary)
        self.secondary_dc = {'dc': self.secondary_tags['dc']}

        (other_secondary, ) = [
            s for s in secondaries
            if ha_tools.get_tags(s)['name'] == 'other_secondary']

        self.other_secondary = _partition_node(other_secondary)
        self.other_secondary_tags = ha_tools.get_tags(other_secondary)
        self.other_secondary_dc = {'dc': self.other_secondary_tags['dc']}

        self.c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)
        self.db = self.c.pymongo_test
        self.w = len(self.c.secondaries) + 1
        self.db.test.remove({}, w=self.w)
        self.db.test.insert(
            [{'foo': i} for i in xrange(10)], w=self.w)

        self.clear_ping_times()

    def set_ping_time(self, host, ping_time_seconds):
        Member._host_to_ping_time[host] = ping_time_seconds

    def clear_ping_times(self):
        Member._host_to_ping_time.clear()

    def test_read_preference(self):
        # We pass through four states:
        #
        #       1. A primary and two secondaries
        #       2. Primary down
        #       3. Primary up, one secondary down
        #       4. Primary up, all secondaries down
        #
        # For each state, we verify the behavior of PRIMARY,
        # PRIMARY_PREFERRED, SECONDARY, SECONDARY_PREFERRED, and NEAREST
        c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets)

        def assertReadFrom(member, *args, **kwargs):
            utils.assertReadFrom(self, c, member, *args, **kwargs)

        def assertReadFromAll(members, *args, **kwargs):
            utils.assertReadFromAll(self, c, members, *args, **kwargs)

        def unpartition_node(node):
            host, port = node
            return '%s:%s' % (host, port)

        # To make the code terser, copy hosts into local scope
        primary = self.primary
        secondary = self.secondary
        other_secondary = self.other_secondary

        bad_tag = {'bad': 'tag'}

        # 1. THREE MEMBERS UP -------------------------------------------------
        #       PRIMARY
        assertReadFrom(primary, PRIMARY)

        #       PRIMARY_PREFERRED
        # Trivial: mode and tags both match
        assertReadFrom(primary, PRIMARY_PREFERRED, self.primary_dc)

        # Secondary matches but not primary, choose primary
        assertReadFrom(primary, PRIMARY_PREFERRED, self.secondary_dc)

        # Chooses primary, ignoring tag sets
        assertReadFrom(primary, PRIMARY_PREFERRED, self.primary_dc)

        # Chooses primary, ignoring tag sets
        assertReadFrom(primary, PRIMARY_PREFERRED, bad_tag)
        assertReadFrom(primary, PRIMARY_PREFERRED, [bad_tag, {}])

        #       SECONDARY
        assertReadFromAll([secondary, other_secondary], SECONDARY)

        #       SECONDARY_PREFERRED
        assertReadFromAll([secondary, other_secondary], SECONDARY_PREFERRED)

        # Multiple tags
        assertReadFrom(secondary, SECONDARY_PREFERRED, self.secondary_tags)

        # Fall back to primary if it's the only one matching the tags
        assertReadFrom(primary, SECONDARY_PREFERRED, {'name': 'primary'})

        # No matching secondaries
        assertReadFrom(primary, SECONDARY_PREFERRED, bad_tag)

        # Fall back from non-matching tag set to matching set
        assertReadFromAll([secondary, other_secondary],
            SECONDARY_PREFERRED, [bad_tag, {}])

        assertReadFrom(other_secondary,
            SECONDARY_PREFERRED, [bad_tag, {'dc': 'ny'}])

        #       NEAREST
        self.clear_ping_times()

        assertReadFromAll([primary, secondary, other_secondary], NEAREST)

        assertReadFromAll([primary, other_secondary],
            NEAREST, [bad_tag, {'dc': 'ny'}])

        self.set_ping_time(primary, 0)
        self.set_ping_time(secondary, .03) # 30 ms
        self.set_ping_time(other_secondary, 10)

        # Nearest member, no tags
        assertReadFrom(primary, NEAREST)

        # Tags override nearness
        assertReadFrom(primary, NEAREST, {'name': 'primary'})
        assertReadFrom(secondary, NEAREST, self.secondary_dc)

        # Make secondary fast
        self.set_ping_time(primary, .03) # 30 ms
        self.set_ping_time(secondary, 0)

        assertReadFrom(secondary, NEAREST)

        # Other secondary fast
        self.set_ping_time(secondary, 10)
        self.set_ping_time(other_secondary, 0)

        assertReadFrom(other_secondary, NEAREST)

        # High secondaryAcceptableLatencyMS, should read from all members
        assertReadFromAll(
            [primary, secondary, other_secondary],
            NEAREST, secondary_acceptable_latency_ms=1000*1000)

        self.clear_ping_times()

        assertReadFromAll([primary, other_secondary], NEAREST, [{'dc': 'ny'}])

        # 2. PRIMARY DOWN -----------------------------------------------------
        killed = ha_tools.kill_primary()

        # Let monitor notice primary's gone
        sleep(2 * MONITOR_INTERVAL)

        #       PRIMARY
        assertReadFrom(None, PRIMARY)

        #       PRIMARY_PREFERRED
        # No primary, choose matching secondary
        assertReadFromAll([secondary, other_secondary], PRIMARY_PREFERRED)
        assertReadFrom(secondary, PRIMARY_PREFERRED, {'name': 'secondary'})

        # No primary or matching secondary
        assertReadFrom(None, PRIMARY_PREFERRED, bad_tag)

        #       SECONDARY
        assertReadFromAll([secondary, other_secondary], SECONDARY)

        # Only primary matches
        assertReadFrom(None, SECONDARY, {'name': 'primary'})

        # No matching secondaries
        assertReadFrom(None, SECONDARY, bad_tag)

        #       SECONDARY_PREFERRED
        assertReadFromAll([secondary, other_secondary], SECONDARY_PREFERRED)

        # Mode and tags both match
        assertReadFrom(secondary, SECONDARY_PREFERRED, {'name': 'secondary'})

        #       NEAREST
        self.clear_ping_times()

        assertReadFromAll([secondary, other_secondary], NEAREST)

        # 3. PRIMARY UP, ONE SECONDARY DOWN -----------------------------------
        ha_tools.restart_members([killed])

        for _ in range(30):
            if ha_tools.get_primary():
                break
            sleep(1)
        else:
            self.fail("Primary didn't come back up")

        ha_tools.kill_members([unpartition_node(secondary)], 2)
        self.assertTrue(MongoClient(
            unpartition_node(primary), use_greenlets=use_greenlets,
            read_preference=PRIMARY_PREFERRED
        ).admin.command('ismaster')['ismaster'])

        sleep(2 * MONITOR_INTERVAL)

        #       PRIMARY
        assertReadFrom(primary, PRIMARY)

        #       PRIMARY_PREFERRED
        assertReadFrom(primary, PRIMARY_PREFERRED)

        #       SECONDARY
        assertReadFrom(other_secondary, SECONDARY)
        assertReadFrom(other_secondary, SECONDARY, self.other_secondary_dc)

        # Only the down secondary matches
        assertReadFrom(None, SECONDARY, {'name': 'secondary'})

        #       SECONDARY_PREFERRED
        assertReadFrom(other_secondary, SECONDARY_PREFERRED)
        assertReadFrom(
            other_secondary, SECONDARY_PREFERRED, self.other_secondary_dc)

        # The secondary matching the tag is down, use primary
        assertReadFrom(primary, SECONDARY_PREFERRED, {'name': 'secondary'})

        #       NEAREST
        assertReadFromAll([primary, other_secondary], NEAREST)
        assertReadFrom(other_secondary, NEAREST, {'name': 'other_secondary'})
        assertReadFrom(primary, NEAREST, {'name': 'primary'})

        # 4. PRIMARY UP, ALL SECONDARIES DOWN ---------------------------------
        ha_tools.kill_members([unpartition_node(other_secondary)], 2)
        self.assertTrue(MongoClient(
            unpartition_node(primary), use_greenlets=use_greenlets,
            read_preference=PRIMARY_PREFERRED
        ).admin.command('ismaster')['ismaster'])

        #       PRIMARY
        assertReadFrom(primary, PRIMARY)

        #       PRIMARY_PREFERRED
        assertReadFrom(primary, PRIMARY_PREFERRED)
        assertReadFrom(primary, PRIMARY_PREFERRED, self.secondary_dc)

        #       SECONDARY
        assertReadFrom(None, SECONDARY)
        assertReadFrom(None, SECONDARY, self.other_secondary_dc)
        assertReadFrom(None, SECONDARY, {'dc': 'ny'})

        #       SECONDARY_PREFERRED
        assertReadFrom(primary, SECONDARY_PREFERRED)
        assertReadFrom(primary, SECONDARY_PREFERRED, self.secondary_dc)
        assertReadFrom(primary, SECONDARY_PREFERRED, {'name': 'secondary'})
        assertReadFrom(primary, SECONDARY_PREFERRED, {'dc': 'ny'})

        #       NEAREST
        assertReadFrom(primary, NEAREST)
        assertReadFrom(None, NEAREST, self.secondary_dc)
        assertReadFrom(None, NEAREST, {'name': 'secondary'})

        # Even if primary's slow, still read from it
        self.set_ping_time(primary, 100)
        assertReadFrom(primary, NEAREST)
        assertReadFrom(None, NEAREST, self.secondary_dc)

        self.clear_ping_times()

    def test_pinning(self):
        # To make the code terser, copy modes into local scope
        PRIMARY = ReadPreference.PRIMARY
        PRIMARY_PREFERRED = ReadPreference.PRIMARY_PREFERRED
        SECONDARY = ReadPreference.SECONDARY
        SECONDARY_PREFERRED = ReadPreference.SECONDARY_PREFERRED
        NEAREST = ReadPreference.NEAREST

        c = MongoReplicaSetClient(
            self.seed, replicaSet=self.name, use_greenlets=use_greenlets,
            auto_start_request=True)

        # Verify that changing the mode unpins the member. We'll try it for
        # every relevant change of mode.
        for mode0, mode1 in itertools.permutations(
            (PRIMARY, SECONDARY, SECONDARY_PREFERRED, NEAREST), 2
        ):
            # Try reading and then changing modes and reading again, see if we
            # read from a different host
            for _ in range(1000):
                # pin to this host
                host = utils.read_from_which_host(c, mode0)
                # unpin?
                new_host = utils.read_from_which_host(c, mode1)
                if host != new_host:
                    # Reading with a different mode unpinned, hooray!
                    break
            else:
                self.fail(
                    "Changing from mode %s to mode %s never unpinned" % (
                        modes[mode0], modes[mode1]))

        # Now verify changing the tag_sets unpins the member.
        tags0 = [{'a': 'a'}, {}]
        tags1 = [{'a': 'x'}, {}]
        for _ in range(1000):
            host = utils.read_from_which_host(c, NEAREST, tags0)
            new_host = utils.read_from_which_host(c, NEAREST, tags1)
            if host != new_host:
                break
        else:
            self.fail(
                "Changing from tags %s to tags %s never unpinned" % (
                    tags0, tags1))

        # Finally, verify changing the secondary_acceptable_latency_ms unpins
        # the member.
        for _ in range(1000):
            host = utils.read_from_which_host(c, SECONDARY, None, 15)
            new_host = utils.read_from_which_host(c, SECONDARY, None, 20)
            if host != new_host:
                break
        else:
            self.fail(
                "Changing secondary_acceptable_latency_ms from 15 to 20"
                " never unpinned")

    def tearDown(self):
        self.c.close()
        ha_tools.kill_all_members()
        self.clear_ping_times()
示例#55
0
members = ""
database = "xxx"
admin_user = "******"
admin_passwd = "xxxxxxxx"
replicaset  = "rs0"
mongod_port = 27017
mongos_port = 27018
servers =  [ "docker-1:27017","docker-2:27017","docker-3:27017" ]

uri_mongod = "mongodb://"+admin_user+":"+admin_passwd+"@"+"localhost"+":"+str(mongod_port) + "/admin"
uri_mongos = "localhost" +":"+str(mongos_port)

#Connection to mongos and mongod
try:
    mongos = MongoClient(uri_mongos,read_preference=ReadPreference.PRIMARY_PREFERRED)
    mongod = MongoReplicaSetClient(uri_mongod ,replicaSet=replicaset ,read_preference=ReadPreference.PRIMARY_PREFERRED)


except pymongo.errors.ConnectionFailure ,e:
    sys.stderr.write("Connection %s failed: " % e)
    sys.exit(1)

try:
        #Enable the sharding for a database
        mongos.admin.command( "enableSharding" ,database)
        #add nodes to the shard
        mongos.admin.command('addShard' , servers[0] , servers[1] , servers[2])
        #initiate Sharding
        config = {_id: replicaset, members: [
        {_id: 0, host: servers[0]},
        {_id: 1, host: servers[1]},
class MongodbBroker(BaseModule):
    
    def __init__(self, mod_conf):
        BaseModule.__init__(self, mod_conf)
        self._parse_conf(mod_conf)
        
        self.queue = Queue.Queue(self.queue_size)
        self.conn = None
        # service notification log broks. 
        # ref: service.raise_notification_log_entry
        self.service_notification = ('contact',
                                     'host',
                                     'service_description',
                                     'state',
                                     'command',
                                     'output'
                                     )
        # host notification log broks.
        # ref: host.raise_notification_log_entry
        self.host_notification = ('contact',
                                  'host',
                                  'state',
                                  'command',
                                  'output')
        
        self.timestamp_regex = re.compile('.*\[(?P<timestamp>\d+)\].*')
        
    def _parse_conf(self, mod_conf):
        self.high_availability = to_bool(getattr(mod_conf,
                                                 'high_availability', 'false'))
        if not self.high_availability:
            self.stand_alone = getattr(mod_conf, 'stand_alone', '')
            if not self.stand_alone:
                logger.error('[Mongodb-Notification-Broker] Mongodb is '
                             'configured with high availability be false but '
                             'stand_alone is not configured')
                raise Exception('[Mongodb-Notification-Broker] Configuration '
                                'Error')
        else:
            replica_set_str = getattr(mod_conf, 'replica_set', '')
            self._set_replica_set(replica_set_str)
        self.database = getattr(mod_conf,
                                'database', 'shinken_broker_notification')
        self.username = getattr(mod_conf,
                                'username', 'shinken_broker_notification')
        self.password = getattr(mod_conf,
                                'password', 'shinken_broker_notification')
        self.url_options = getattr(mod_conf, 'url_options', '')
        
        try:
            self.retry_per_log = int(getattr(mod_conf, 'retry_per_log'))
        except:
            self.retry_per_log = 5
        try:
            self.queue_size = int(getattr(mod_conf, 'queue_size'))
        except:
            self.queue_size = 10000
        
    def _set_replica_set(self, replica_set_str):
        raw_members = replica_set_str.split(',')
        members = []
        for member in raw_members:
            members.append(member.strip())
        self.replica_set = members        
        
    def _set_mongodb_url(self):
        scheme = 'mongodb://'
        db_and_options = '/%s?%s' % (self.database, self.url_options) 
        credential = ':'.join((self.username, '%s@' % self.password))
        if not self.high_availability:
            address = self.stand_alone
            mongodb_url = ''.join((scheme, credential, address, db_and_options))
        else:
            address = ','.join(self.replica_set)
            mongodb_url = ''.join((scheme, credential, address, db_and_options))
        self.mongodb_url = mongodb_url
        
    # Called by Broker to do init work
    def init(self):
        logger.info('[Mongodb-Notification-Broker] Initialization of '
                    'mongodb_notification_broker module')
        self._set_mongodb_url()
        logger.debug('[Mongodb-Notification-Broker] Mongodb connect url: %s' 
                     % self.mongodb_url)
        
        # In case notification broker process down occasionally, the self.conn 
        # object must be dropped cleanly in Broker daemon.
        self.do_stop()
        try:
            if not self.high_availability:
                self.conn = MongoClient(self.mongodb_url)
            else:
                self.conn = MongoReplicaSetClient(self.mongodb_url)
        except ConnectionFailure:
            logger.warn('[Mongodb-Notification-Broker] Can not make connection '
                        ' with MongoDB')
            raise
            
        except (InvalidURI, ConfigurationError):
            logger.warn('[Mongodb-Notification-Broker] Mongodb connect url '
                        'error')
            logger.warn('[Mongodb-Notification-Broker] Mongodb connect url: %s' 
                        % self.mongodb_url)
            raise 
        self._get_collections()
        
    def _get_collections(self):
        db = self.conn[self.database]
        self.hosts = db['hosts']
        self.services = db['services']
        self.notifications = db['notifications']
    
    # Override the same function in basemodule.py for clean up 
    def do_stop(self):
        if self.conn:
            self.conn.close()
            self.conn = None
    
    # If we are confronted with AutoReconnect Exception, then we should always 
    # retry until the operation succeeds. However, if other exception is thrown,
    # we should ignore the operation and go to next operation.
    def _process_db_operation(self, operation, *param):
        reconnect_start = time.time()
        result = None        
        while True:
            try:
                result = operation(*param)
            except AutoReconnect:
                logger.warn('[Mongodb-Notification-Broker] Update error. ' 
                            'Reconnected last %d seconds' % (time.time() - reconnect_start))
                # avoid to invoke too many write operations
                time.sleep(self.retry_per_log)
            except Exception:
                logger.warn('[Mongodb-Notification-Broker] Update error. '
                            'operation %s, param %s' % (operation, param))
                logger.warn('[Mongodb-Notification-Broker] %s' % traceback.format_exc())
                break
            else:
                logger.debug('[Mongodb-Notification-Broker] Update success. '
                             'Operation %s, param %s' % (operation, param))
                break
        return result    
    
    # main function to update mongodb database
    def _save(self, ref, ref_identity, notification):
        self._process_db_operation(self.notifications.insert, notification)
        if ref == 'service':
            _id = ','.join((ref_identity.get('host'),
                            ref_identity.get('service_description')))
            cursor = self._process_db_operation(self.services.find,
                                                {'_id': _id})
        elif ref == 'host':
            _id = ref_identity.get('host')
            cursor = self._process_db_operation(self.hosts.find, {'_id': _id})
        
        # if service or host find error, 'cursor' will be None.
        # then we can not make sure that whether specific host or service 
        # exists. In order to not make data be corrupted, we should stop here.
        if cursor:
            if not cursor.count():
                # if notification insert error, then '_id' will not be in it and we
                # then should ignore the notification.
                ref_identity.setdefault('notification_ids',
                                        [notification.get('_id')] if '_id' in notification else [])
                ref_identity.setdefault('_id', _id)
                
                if ref == 'service':
                    self._process_db_operation(self.services.insert, ref_identity)
                elif ref == 'host':
                    self._process_db_operation(self.hosts.insert, ref_identity)
            else:
                document = cursor[0]
                notification_ids = document.get('notification_ids')
                # if notification insert error, then '_id' will not be in it and we 
                # then should ignore the notification
                if '_id' in notification:
                    notification_ids.append(notification.get('_id'))
                    if ref == 'service':
                        self._process_db_operation(self.services.update,
                                                   {'_id': _id},
                                                   {'$set': {'notification_ids': notification_ids}})
                    elif ref == 'host':
                        self._process_db_operation(self.hosts.update,
                                                   {'_id': _id},
                                                   {'$set': {'notification_ids': notification_ids}})    
        else:
            logger.warn('[Mongodb-Notification-Broker] Update notification '
                        'success, link with host or service error.')
        logger.debug('[Mongodb-Notification-Broker] Update notification ends.')    
        
    
    # restore 'log' type notification to self.queue
    def _do_loop_turn(self):
        while not self.interrupted:
            broks = self.to_q.get()
            for brok in broks:
                brok.prepare()
                self._manage_brok(brok)
    
    def _update_db(self):
        while True:
            # if self.queue is empty, get operation will be blocked.
            brok = self.queue.get()
            logger.debug('[Mongodb-Notification-Broker] '
                         'Update notification begins.')
            
            msg = brok.data['log']
            parts = msg.split(':', 1)
            if 'SERVICE' in parts[0]:
                service_identiry, notification = self._process_notification_brok('service',
                                                                                 self.service_notification,
                                                                                 parts[0], parts[1])
                self._save('service', service_identiry, notification)
            elif 'HOST' in parts[0]:
                host_identity, notification = self._process_notification_brok('host',
                                                                              self.host_notification,
                                                                              parts[0], parts[1])
                self._save('host', host_identity, notification)

    def _process_notification_brok(self, ref, keys, header, notification_info):
        elts = notification_info.split(';', len(keys))
        
        timestamp = ''
        match = self.timestamp_regex.match(header)
        if match:
            timestamp = match.group('timestamp')
        
        info_map = dict(zip(keys, elts))
        if ref == 'service':
            ref_identity = {'host': info_map.get('host'),
                            'service_description': info_map.get('service_description')
                            }
        elif ref == 'host':
            ref_identity = {'host': info_map.get('host')}
            
        notification = {'contact': info_map.get('contact'),
                        'command': info_map.get('command'),
                        'output': info_map.get('output'),
                        'timestamp': timestamp
                        }
        return ref_identity, notification
    
    def _manage_brok(self, brok):
        if brok.type == 'log' and 'NOTIFICATION' in brok.data['log']:
            try:
                self.queue.put_nowait(brok)
            except Queue.Full:
                logger.warn('[Mongodb-Notification-Broker] Queue full. '
                            'Ignore broks.')
        
    # invoked by basemodule._main        
    def main(self):
        logger.info('[Mongodb-Notification-Broker] Start main function.')
        worker = Thread(target=self._update_db)
        worker.setDaemon(True)
        worker.start()
        self._do_loop_turn()