Пример #1
0
def migrate(env, dry_run=False):
    """
    User-friendly frontend to run database migrations.
    """
    registry = env['registry']
    settings = registry.settings
    readonly_backends = ('storage', 'permission')
    readonly_mode = asbool(settings.get('readonly', False))

    for backend in ('cache', 'storage', 'permission'):
        if hasattr(registry, backend):
            if readonly_mode and backend in readonly_backends:
                message = ('Cannot migrate the %s backend while '
                           'in readonly mode.' % backend)
                logger.error(message)
            else:
                getattr(registry, backend).initialize_schema(dry_run=dry_run)
Пример #2
0
def delete_collection(env, bucket_id, collection_id):
    registry = env['registry']
    settings = registry.settings
    readonly_mode = asbool(settings.get('readonly', False))

    if readonly_mode:
        message = ('Cannot delete the collection while in readonly mode.')
        logger.error(message)
        return 31

    bucket = '/buckets/{}'.format(bucket_id)
    collection = '/buckets/{}/collections/{}'.format(bucket_id, collection_id)

    try:
        registry.storage.get(collection_id='bucket',
                             parent_id='',
                             object_id=bucket_id)
    except storage_exceptions.RecordNotFoundError:
        logger.error("Bucket '{}' does not exist.".format(bucket))
        return 32

    try:
        registry.storage.get(collection_id='collection',
                             parent_id=bucket,
                             object_id=collection_id)
    except storage_exceptions.RecordNotFoundError:
        logger.error("Collection '{}' does not exist.".format(collection))
        return 33

    deleted = registry.storage.delete_all(collection_id='record',
                                          parent_id=collection,
                                          with_deleted=False)
    if len(deleted) == 0:
        logger.info("No records found for '{}'.".format(collection))
    else:
        logger.info('{} record(s) were deleted.'.format(len(deleted)))

    registry.storage.delete(collection_id='collection',
                            parent_id=bucket,
                            object_id=collection_id,
                            with_deleted=False)
    logger.info("'{}' collection object was deleted.".format(collection))

    record = ('/buckets/{bucket_id}'
              '/collections/{collection_id}'
              '/records/{record_id}')

    registry.permission.delete_object_permissions(
        collection, *[
            record.format(bucket_id=bucket_id,
                          collection_id=collection_id,
                          record_id=r['id']) for r in deleted
        ])
    logger.info('Related permissions were deleted.')

    current_transaction.commit()

    return 0
Пример #3
0
def delete_collection(env, bucket_id, collection_id):
    registry = env['registry']
    settings = registry.settings
    readonly_mode = asbool(settings.get('readonly', False))

    if readonly_mode:
        message = ('Cannot delete the collection while in readonly mode.')
        logger.error(message)
        return 31

    bucket = '/buckets/%s' % bucket_id
    collection = '/buckets/%s/collections/%s' % (bucket_id, collection_id)

    try:
        registry.storage.get(collection_id='bucket',
                             parent_id='',
                             object_id=bucket_id)
    except storage_exceptions.RecordNotFoundError:
        logger.error("Bucket %r does not exist." % bucket)
        return 32

    try:
        registry.storage.get(collection_id='collection',
                             parent_id=bucket,
                             object_id=collection_id)
    except storage_exceptions.RecordNotFoundError:
        logger.error("Collection %r does not exist." % collection)
        return 33

    deleted = registry.storage.delete_all(collection_id='record',
                                          parent_id=collection,
                                          with_deleted=False)
    if len(deleted) == 0:
        logger.info('No records found for %r.' % collection)
    else:
        logger.info('%d record(s) were deleted.' % len(deleted))

    registry.storage.delete(collection_id='collection',
                            parent_id=bucket,
                            object_id=collection_id,
                            with_deleted=False)
    logger.info("%r collection object was deleted." % collection)

    record = ('/buckets/{bucket_id}'
              '/collections/{collection_id}'
              '/records/{record_id}')

    registry.permission.delete_object_permissions(
        collection,
        *[record.format(bucket_id=bucket_id,
                        collection_id=collection_id,
                        record_id=r['id']) for r in deleted])
    logger.info('Related permissions were deleted.')

    current_transaction.commit()

    return 0
Пример #4
0
def get_heartbeat(request):
    """Return information about server health."""
    status = {}

    def heartbeat_check(name, func):
        status[name] = False
        status[name] = func(request)
        # Since the heartbeat checks run concurrently, their transactions
        # overlap and might end in shared lock errors. By aborting here
        # we clean-up the state on each heartbeat call instead of once at the
        # end of the request. See bug Kinto/kinto#804
        transaction.abort()

    # Start executing heartbeats concurrently.
    heartbeats = request.registry.heartbeats
    pool = ThreadPoolExecutor(max_workers=max(1, len(heartbeats.keys())))
    futures = []
    for name, func in heartbeats.items():
        future = pool.submit(heartbeat_check, name, func)
        future.__heartbeat_name = name  # For logging purposes.
        futures.append(future)

    # Wait for the results, with timeout.
    seconds = float(request.registry.settings['heartbeat_timeout_seconds'])
    done, not_done = wait(futures, timeout=seconds)

    # A heartbeat is supposed to return True or False, and never raise.
    # Just in case, go though results to spot any potential exception.
    for future in done:
        exc = future.exception()
        if exc is not None:
            logger.error("'{}' heartbeat failed.".format(
                future.__heartbeat_name))
            logger.error(exc)

    # Log timed-out heartbeats.
    for future in not_done:
        name = future.__heartbeat_name
        error_msg = "'{}' heartbeat has exceeded timeout of {} seconds."
        logger.error(error_msg.format(name, seconds))

    # If any has failed, return a 503 error response.
    has_error = not all([v or v is None for v in status.values()])
    if has_error:
        request.response.status = 503

    return status
Пример #5
0
def get_heartbeat(request):
    """Return information about server health."""
    status = {}

    def heartbeat_check(name, func):
        status[name] = False
        status[name] = func(request)

    # Start executing heartbeats concurrently.
    heartbeats = request.registry.heartbeats
    pool = ThreadPoolExecutor(max_workers=max(1, len(heartbeats.keys())))
    futures = []
    for name, func in heartbeats.items():
        future = pool.submit(heartbeat_check, name, func)
        future.__heartbeat_name = name  # For logging purposes.
        futures.append(future)

    # Wait for the results, with timeout.
    seconds = float(request.registry.settings['heartbeat_timeout_seconds'])
    done, not_done = wait(futures, timeout=seconds)

    # A heartbeat is supposed to return True or False, and never raise.
    # Just in case, go though results to spot any potential exception.
    for future in done:
        exc = future.exception()
        if exc is not None:
            logger.error("%r heartbeat failed." % future.__heartbeat_name)
            logger.error(exc)

    # Log timed-out heartbeats.
    for future in not_done:
        name = future.__heartbeat_name
        error_msg = "%r heartbeat has exceeded timeout of %s seconds."
        logger.error(error_msg % (name, seconds))

    # If any has failed, return a 503 error response.
    has_error = not all([v or v is None for v in status.values()])
    if has_error:
        request.response.status = 503

    return status
Пример #6
0
def get_heartbeat(request):
    """Return information about server health."""
    status = {}

    def heartbeat_check(name, func):
        status[name] = False
        status[name] = func(request)

    # Start executing heartbeats concurrently.
    heartbeats = request.registry.heartbeats
    pool = ThreadPoolExecutor(max_workers=max(1, len(heartbeats.keys())))
    futures = []
    for name, func in heartbeats.items():
        future = pool.submit(heartbeat_check, name, func)
        future.__heartbeat_name = name  # For logging purposes.
        futures.append(future)

    # Wait for the results, with timeout.
    seconds = float(request.registry.settings['heartbeat_timeout_seconds'])
    done, not_done = wait(futures, timeout=seconds)

    # A heartbeat is supposed to return True or False, and never raise.
    # Just in case, go though results to spot any potential exception.
    for future in done:
        exc = future.exception()
        if exc is not None:
            logger.error("%r heartbeat failed." % future.__heartbeat_name)
            logger.error(exc)

    # Log timed-out heartbeats.
    for future in not_done:
        name = future.__heartbeat_name
        error_msg = "%r heartbeat has exceeded timeout of %s seconds."
        logger.error(error_msg % (name, seconds))

    # If any has failed, return a 503 error response.
    has_error = not all([v or v is None for v in status.values()])
    if has_error:
        request.response.status = 503

    return status