Source code for bigchaindb.backend.localmongodb.connection

# Copyright © 2020 Interplanetary Database Association e.V.,
# BigchainDB and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0

import logging
from ssl import CERT_REQUIRED

import pymongo

from bigchaindb.backend.connection import Connection
from bigchaindb.backend.exceptions import (DuplicateKeyError,
                                           OperationError,
                                           ConnectionError)
from bigchaindb.backend.utils import get_bigchaindb_config_value
from bigchaindb.common.exceptions import ConfigurationError
from bigchaindb.utils import Lazy

logger = logging.getLogger(__name__)


[docs]class LocalMongoDBConnection(Connection): def __init__(self, replicaset=None, ssl=None, login=None, password=None, ca_cert=None, certfile=None, keyfile=None, keyfile_passphrase=None, crlfile=None, **kwargs): """Create a new Connection instance. Args: replicaset (str, optional): the name of the replica set to connect to. **kwargs: arbitrary keyword arguments provided by the configuration's ``database`` settings """ super().__init__(**kwargs) self.replicaset = replicaset or get_bigchaindb_config_value('replicaset') self.ssl = ssl if ssl is not None else get_bigchaindb_config_value('ssl', False) self.login = login or get_bigchaindb_config_value('login') self.password = password or get_bigchaindb_config_value('password') self.ca_cert = ca_cert or get_bigchaindb_config_value('ca_cert') self.certfile = certfile or get_bigchaindb_config_value('certfile') self.keyfile = keyfile or get_bigchaindb_config_value('keyfile') self.keyfile_passphrase = keyfile_passphrase or get_bigchaindb_config_value('keyfile_passphrase') self.crlfile = crlfile or get_bigchaindb_config_value('crlfile') @property def db(self): return self.conn[self.dbname] def query(self): return Lazy()
[docs] def collection(self, name): """Return a lazy object that can be used to compose a query. Args: name (str): the name of the collection to query. """ return self.query()[self.dbname][name]
[docs] def run(self, query): try: try: return query.run(self.conn) except pymongo.errors.AutoReconnect: logger.warning('Lost connection to the database, ' 'retrying query.') return query.run(self.conn) except pymongo.errors.AutoReconnect as exc: raise ConnectionError from exc except pymongo.errors.DuplicateKeyError as exc: raise DuplicateKeyError from exc except pymongo.errors.OperationFailure as exc: print(f'DETAILS: {exc.details}') raise OperationError 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
MONGO_OPTS = { 'socketTimeoutMS': 20000, }