Example #1
0
def db(request):
    """
    Require a Mongo test database.

    Provides a Mongo test database named after the requesting test function. Mongo databases are
    created/destroyed based on the URI provided with the --mongo-uri option and tear-down
    behavior is modified by the --keep-db option.
    """
    from girderformindlogger.models import _dbClients, getDbConnection, pymongo
    from girderformindlogger.models import model_base
    from girderformindlogger.external import mongodb_proxy

    mockDb = request.config.getoption('--mock-db')
    dbUri = request.config.getoption('--mongo-uri')
    dbName = 'girder_test_%s' % hashlib.md5(_uid(
        request.node).encode('utf8')).hexdigest()
    keepDb = request.config.getoption('--keep-db')
    executable_methods = mongodb_proxy.EXECUTABLE_MONGO_METHODS
    realMongoClient = pymongo.MongoClient

    if mockDb:
        mongodb_proxy.EXECUTABLE_MONGO_METHODS = set()
        pymongo.MongoClient = mongomock.MongoClient

    connection = getDbConnection(uri='%s/%s' % (dbUri, dbName), quiet=False)

    # Force getDbConnection from models to return our connection
    _dbClients[(None, None)] = connection

    connection.drop_database(dbName)

    # Since models store a local reference to the current database, we need to force them all to
    # reconnect
    for model in model_base._modelSingletons:
        model.reconnect()

    yield connection

    if not keepDb:
        connection.drop_database(dbName)

    connection.close()

    if mockDb:
        mongodb_proxy.EXECUTABLE_MONGO_METHODS = executable_methods
        pymongo.MongoClient = realMongoClient
Example #2
0
def getStatus(mode='basic', user=None):
    """
    Get a dictionary of status information regarding the Girder server.

    :param mode: 'basic' returns values available to any anonymous user.
        'quick' returns only values that are cheap to acquire.
        'slow' provides all of that information and adds additional
    :param user: a user record.  Must have admin access to get anything other
                 than basic mode.
    :returns: a status dictionary.
    """
    isAdmin = (user is not None and user['admin'])

    status = {}
    status['bootTime'] = psutil.boot_time()
    status['currentTime'] = time.time()
    process = psutil.Process(os.getpid())
    status['processStartTime'] = process.create_time()

    if mode in ('quick', 'slow') and isAdmin:
        status['virtualMemory'] = _objectToDict(psutil.virtual_memory())
        status['swap'] = _objectToDict(psutil.swap_memory())
        status['cpuCount'] = psutil.cpu_count()

        status['processMemory'] = _objectToDict(process.memory_info())
        status['processName'] = process.name()
        status['cmdline'] = process.cmdline()
        status['exe'] = process.exe()
        status['cwd'] = process.cwd()
        status['userName'] = process.username()
        status['processCpuTimes'] = _objectToDict(process.cpu_times())
        db = getDbConnection().get_database()
        status['mongoBuildInfo'] = db.command('buildInfo')
        status['cherrypyThreadsMaxUsed'] = len(
            cherrypy.tools.status.seenThreads)
        status['cherrypyThreadsInUse'] = len([
            True for threadId in cherrypy.tools.status.seenThreads
            if 'end' not in cherrypy.tools.status.seenThreads[threadId]
        ])
        status['cherrypyThreadPoolSize'] = cherrypy.server.thread_pool

    if mode == 'slow' and isAdmin:
        _computeSlowStatus(process, status, db)
    return status
 def __init__(self, assetstore):
     """
     :param assetstore: The assetstore to act on.
     """
     super(GridFsAssetstoreAdapter, self).__init__(assetstore)
     recent = False
     try:
         # Guard in case the connectionArgs is unhashable
         key = (self.assetstore.get('mongohost'),
                self.assetstore.get('replicaset'))
         if key in _recentConnections:
             recent = (time.time() - _recentConnections[key]['created']
                       < RECENT_CONNECTION_CACHE_TIME)
     except TypeError:
         key = None
     try:
         # MongoClient automatically reuses connections from a pool, but we
         # want to avoid redoing ensureChunkIndices each time we get such a
         # connection.
         client = getDbConnection(self.assetstore.get('mongohost'),
                                  self.assetstore.get('replicaset'),
                                  quiet=recent)
         self.chunkColl = MongoProxy(client[self.assetstore['db']].chunk)
         if not recent:
             _ensureChunkIndices(self.chunkColl)
             if key is not None:
                 if len(_recentConnections) >= RECENT_CONNECTION_CACHE_MAX_SIZE:
                     _recentConnections.clear()
                 _recentConnections[key] = {
                     'created': time.time()
                 }
     except pymongo.errors.ConnectionFailure:
         logger.error('Failed to connect to GridFS assetstore %s',
                      self.assetstore['db'])
         self.chunkColl = 'Failed to connect'
         self.unavailable = True
     except pymongo.errors.ConfigurationError:
         logger.exception('Failed to configure GridFS assetstore %s',
                          self.assetstore['db'])
         self.chunkColl = 'Failed to configure'
         self.unavailable = True
    def validateInfo(doc):
        """
        Validate the assetstore -- make sure we can connect to it and that the
        necessary indexes are set up.
        """
        if not doc.get('db', ''):
            raise ValidationException('Database name must not be empty.', 'db')
        if '.' in doc['db'] or ' ' in doc['db']:
            raise ValidationException('Database name cannot contain spaces'
                                      ' or periods.', 'db')

        try:
            chunkColl = getDbConnection(
                doc.get('mongohost'), doc.get('replicaset'), autoRetry=False,
                serverSelectionTimeoutMS=10000)[doc['db']].chunk
            _ensureChunkIndices(chunkColl)
        except pymongo.errors.ServerSelectionTimeoutError as e:
            raise ValidationException(
                'Could not connect to the database: %s' % str(e))

        return doc
Example #5
0
def _computeSlowStatus(process, status, db):
    status['diskPartitions'] = [
        _objectToDict(part) for part in psutil.disk_partitions()
    ]
    try:
        # This fails in certain environments, so guard it
        status['diskIO'] = _objectToDict(psutil.disk_io_counters())
    except Exception:
        pass
    # Report on the disk usage where the script is located
    if hasattr(girderformindlogger, '__file__'):
        status['girderPath'] = os.path.abspath(girderformindlogger.__file__)
        status['girderDiskUsage'] = _objectToDict(
            psutil.disk_usage(status['girderPath']))
    # Report where our logs are and how much space is available for them
    status['logs'] = []
    for handler in logger.handlers:
        try:
            logInfo = {'path': handler.baseFilename}
            logInfo['diskUsage'] = _objectToDict(
                psutil.disk_usage(logInfo['path']))
            status['logs'].append(logInfo)
        except Exception:
            # If we can't read information about the log, don't throw an
            # exception
            pass
    status['mongoDbStats'] = db.command('dbStats')
    status['mongoDbPath'] = getDbConnection().admin.command(
        'getCmdLineOpts')['parsed']['storage']['dbPath']
    status['mongoDbDiskUsage'] = _objectToDict(
        psutil.disk_usage(status['mongoDbPath']))

    status['processDirectChildrenCount'] = len(process.children())
    status['processAllChildrenCount'] = len(process.children(True))
    status['openFiles'] = [
        _objectToDict(file) for file in process.open_files()
    ]
    # I'd rather see textual names for the family and type of connections,
    # so make a lookup table for them
    connFamily = {
        getattr(socket, key): key
        for key in dir(socket) if key.startswith('AF_')
    }
    connType = {
        getattr(socket, key): key
        for key in dir(socket) if key.startswith('SOCK_')
    }
    connections = []
    for conn in process.connections():
        connDict = _objectToDict(conn)
        connDict.pop('raddr', None)
        connDict.pop('laddr', None)
        connDict['family'] = connFamily.get(connDict['family'],
                                            connDict['family'])
        connDict['type'] = connType.get(connDict['type'], connDict['type'])
        connections.append(connDict)
    status['connections'] = connections
    if hasattr(process, 'io_counters'):
        status['ioCounters'] = _objectToDict(process.io_counters())

    status['cherrypyThreads'] = {}
    for threadId in cherrypy.tools.status.seenThreads:
        info = cherrypy.tools.status.seenThreads[threadId].copy()
        if 'end' in info:
            info['duration'] = info['end'] - info['start']
            info['idle'] = time.time() - info['end']
        status['cherrypyThreads'][threadId] = info