Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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'
Beispiel #5
0
    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
Beispiel #6
0
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()
Beispiel #7
0
    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