def _connect(self): """Try to connect to the database. Raises: :exc:`~ConnectionError`: If the connection to the database fails. """ try: # we should only return a connection if the replica set is # initialized. initialize_replica_set will check if the # replica set is initialized else it will initialize it. initialize_replica_set(self.host, self.port, self.connection_timeout, self.dbname, self.ssl, self.login, self.password) # FYI: this might raise a `ServerSelectionTimeoutError`, # that is a subclass of `ConnectionFailure`. client = pymongo.MongoClient(self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout, ssl=self.ssl) if self.login is not None and self.password is not None: client[self.dbname].authenticate(self.login, self.password) return client # `initialize_replica_set` might raise `ConnectionFailure` or `OperationFailure`. except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc: if "Authentication fail" in str(exc): raise AuthenticationError() from exc raise ConnectionError() from exc
def _connect(self): """Try to connect to the database. Raises: :exc:`~ConnectionError`: If the connection to the database fails. """ try: # we should only return a connection if the replica set is # initialized. initialize_replica_set will check if the # replica set is initialized else it will initialize it. initialize_replica_set(self.host, self.port, self.connection_timeout) # FYI: this might raise a `ServerSelectionTimeoutError`, # that is a subclass of `ConnectionFailure`. return pymongo.MongoClient( self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout) # `initialize_replica_set` might raise `ConnectionFailure` or `OperationFailure`. except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc: raise ConnectionError() from exc
def _connect(self): """Try to connect to the database. Raises: :exc:`~ConnectionError`: If the connection to the database fails. :exc:`~AuthenticationError`: If there is a OperationFailure due to Authentication failure after connecting to the database. :exc:`~ConfigurationError`: If there is a ConfigurationError while connecting to the database. """ try: # FYI: the connection process might raise a # `ServerSelectionTimeoutError`, that is a subclass of # `ConnectionFailure`. # The presence of ca_cert, certfile, keyfile, crlfile implies the # use of certificates for TLS connectivity. if self.ca_cert is None or self.certfile is None or \ self.keyfile is None or self.crlfile is None: client = pymongo.MongoClient( self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout, ssl=self.ssl, **MONGO_OPTS) if self.login is not None and self.password is not None: client[self.dbname].authenticate(self.login, self.password) else: logger.info('Connecting to MongoDB over TLS/SSL...') client = pymongo.MongoClient( self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout, ssl=self.ssl, ssl_ca_certs=self.ca_cert, ssl_certfile=self.certfile, ssl_keyfile=self.keyfile, ssl_pem_passphrase=self.keyfile_passphrase, ssl_crlfile=self.crlfile, ssl_cert_reqs=CERT_REQUIRED, **MONGO_OPTS) if self.login is not None: client[self.dbname].authenticate(self.login, mechanism='MONGODB-X509') return client except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc: logger.info('Exception in _connect(): {}'.format(exc)) raise ConnectionError(str(exc)) from exc except pymongo.errors.ConfigurationError as exc: raise ConfigurationError from exc
def test_connection_failure(): from bigchaindb.backend.exceptions import ConnectionError from bigchaindb.backend.mongodb.changefeed import run_changefeed conn = mock.MagicMock() conn.run.side_effect = [ConnectionError(), RuntimeError()] changefeed = run_changefeed(conn, 'backlog', -1) with pytest.raises(RuntimeError): for record in changefeed: assert False, 'Shouldn\'t get here'
def connect(self): """Try to connect to the database. Raises: :exc:`~ConnectionError`: If the connection to the database fails. """ attempt = 0 for i in self.max_tries_counter: attempt += 1 try: self._conn = self._connect() except ConnectionError as exc: logger.warning('Attempt %s/%s. Connection to %s:%s failed after %sms.', attempt, self.max_tries if self.max_tries != 0 else '∞', self.host, self.port, self.connection_timeout) if attempt == self.max_tries: logger.critical('Cannot connect to the Database. Giving up.') raise ConnectionError() from exc else: break
def initialize_replica_set(host, port, connection_timeout, dbname, ssl, login, password, ca_cert, certfile, keyfile, keyfile_passphrase, crlfile): """Initialize a replica set. If already initialized skip.""" # Setup a MongoDB connection # The reason we do this instead of `backend.connect` is that # `backend.connect` will connect you to a replica set but this fails if # you try to connect to a replica set that is not yet initialized try: # The presence of ca_cert, certfile, keyfile, crlfile implies the # use of certificates for TLS connectivity. if ca_cert is None or certfile is None or keyfile is None or \ crlfile is None: conn = pymongo.MongoClient( host, port, serverselectiontimeoutms=connection_timeout, ssl=ssl) if login is not None and password is not None: conn[dbname].authenticate(login, password) else: logger.info('Connecting to MongoDB over TLS/SSL...') conn = pymongo.MongoClient( host, port, serverselectiontimeoutms=connection_timeout, ssl=ssl, ssl_ca_certs=ca_cert, ssl_certfile=certfile, ssl_keyfile=keyfile, ssl_pem_passphrase=keyfile_passphrase, ssl_crlfile=crlfile, ssl_cert_reqs=CERT_REQUIRED) if login is not None: logger.info('Authenticating to the database...') conn[dbname].authenticate(login, mechanism='MONGODB-X509') except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc: logger.info('Exception in _connect(): {}'.format(exc)) raise ConnectionError(str(exc)) from exc except pymongo.errors.ConfigurationError as exc: raise ConfigurationError from exc _check_replica_set(conn) host = '{}:{}'.format(bigchaindb.config['database']['host'], bigchaindb.config['database']['port']) config = { '_id': bigchaindb.config['database']['replicaset'], 'members': [{ '_id': 0, 'host': host }] } try: conn.admin.command('replSetInitiate', config) except pymongo.errors.OperationFailure as exc_info: if exc_info.details['codeName'] == 'AlreadyInitialized': return raise else: _wait_for_replica_set_initialization(conn) logger.info('Initialized replica set') finally: if conn is not None: logger.info('Closing initial connection to MongoDB') conn.close()
def _connect(self): """Try to connect to the database. Raises: :exc:`~ConnectionError`: If the connection to the database fails. :exc:`~AuthenticationError`: If there is a OperationFailure due to Authentication failure after connecting to the database. :exc:`~ConfigurationError`: If there is a ConfigurationError while connecting to the database. """ try: if self.replicaset: # we should only return a connection if the replica set is # initialized. initialize_replica_set will check if the # replica set is initialized else it will initialize it. initialize_replica_set(self.host, self.port, self.connection_timeout, self.dbname, self.ssl, self.login, self.password, self.ca_cert, self.certfile, self.keyfile, self.keyfile_passphrase, self.crlfile) # FYI: the connection process might raise a # `ServerSelectionTimeoutError`, that is a subclass of # `ConnectionFailure`. # The presence of ca_cert, certfile, keyfile, crlfile implies the # use of certificates for TLS connectivity. if self.ca_cert is None or self.certfile is None or \ self.keyfile is None or self.crlfile is None: client = pymongo.MongoClient( self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout, ssl=self.ssl, **MONGO_OPTS) if self.login is not None and self.password is not None: client[self.dbname].authenticate(self.login, self.password) else: logger.info('Connecting to MongoDB over TLS/SSL...') client = pymongo.MongoClient( self.host, self.port, replicaset=self.replicaset, serverselectiontimeoutms=self.connection_timeout, ssl=self.ssl, ssl_ca_certs=self.ca_cert, ssl_certfile=self.certfile, ssl_keyfile=self.keyfile, ssl_pem_passphrase=self.keyfile_passphrase, ssl_crlfile=self.crlfile, ssl_cert_reqs=CERT_REQUIRED, **MONGO_OPTS) if self.login is not None: client[self.dbname].authenticate(self.login, mechanism='MONGODB-X509') # Riddle&Code # 2018-05-18 # adding parameter "atlas" to the "database" section of the configuration file if self.atlas: client = pymongo.MongoClient(self.atlas) return client # `initialize_replica_set` might raise `ConnectionFailure`, # `OperationFailure` or `ConfigurationError`. except (pymongo.errors.ConnectionFailure, pymongo.errors.OperationFailure) as exc: logger.info('Exception in _connect(): {}'.format(exc)) raise ConnectionError(str(exc)) from exc except pymongo.errors.ConfigurationError as exc: raise ConfigurationError from exc