Восстановление данных из Amazon Glacier

Есть ли способ командной строки для восстановления данных из Glacier? Пока что я попробовал:

s3cmd restore --recursive s3://mybucketname/folder/

aws s3 ls s3://<bucket_name> | awk '{print $4}' | xargs -L 1 aws s3api restore-object --restore-request Days=<days> --bucket <bucket_name> --key

Но никакой помощи там нет. PS: я знаю, что мы можем сделать это через консоль.

3 ответа

Вы можете использовать нижний уровень aws s3api команда:

aws s3api restore-object --request-payer requester \
                         --key path/to/key.blob \
                         --bucket my-bucket \
                         --cli-input-json "$(cat request.json)"

А затем установите свои параметры внутри request.json, например:

{
    "RestoreRequest": {
     "Days": 1,
     "GlacierJobParameters": {
         "Tier": "Standard"
     }
    }
}

После того, как запрос на восстановление будет инициирован, вам нужно будет позвонить head-object чтобы определить его статус восстановления:

aws s3api head-object --key path/to/key.blob \
                      --bucket my-bucket \
                      --request-payer requester
{
    "AcceptRanges": "bytes",
    "Restore": "ongoing-request=\"true\"",
    "LastModified": "Thu, 30 May 2019 22:43:48 GMT",
    "ContentLength": 1573320976,
    "ETag": "\"5e9bae0592655103e72d0c026e643184-94\"",
    "ContentType": "application/x-gzip",
    "Metadata": {
        "digest-md5": "7ace7afadfaec591a7dcff2b942df701",
        "import-digests": "md5"
    },
    "StorageClass": "GLACIER",
    "RequestCharged": "requester"
}

когда Restore содержит, ongoing-request="false", восстановление будет завершено. Временная копия в S3 будет храниться в течение времени, указанного в команде восстановления. ВStorageClass всегда GLACIER(или DEEP_ARCHIVE) для любого восстановленного файла, даже после его восстановления. Это не интуитивно.

Если вы хотите восстановить эту копию на постоянной основе в S3, т.е. и изменить класс хранения с GLACIER на STANDARD, вам нужно будет поместить / скопировать (потенциально поверх себя) восстановленную копию в новый файл. Это раздражает.

Связанные с:

Обратите внимание --request-payer requesterне является обязательным. Я использую это в своей настройке, но если вы владелец ведра, он вам не нужен.

К сожалению, это невозможно. Вы можете получить доступ к объектам, которые были заархивированы в Amazon Glacier, только с помощью Amazon S3.

См. http://docs.aws.amazon.com/AmazonS3/latest/user-guide/restore-archived-objects.html

Вот пример использования Java для восстановления объекта. По этой ссылке вы можете сделать что-то похожее на выбранном вами языке.

Восстановление заархивированного объекта с помощью AWS SDK для Java

Вы можете использовать код Python ниже, чтобы восстановить данные ледника до s3.

import boto3, botocore
import subprocess, os, shutil, tempfile, argparse, sys, time, codecs
from pprint import pprint

sys.stdout = codecs.getwriter('utf8')(sys.stdout)

parser = argparse.ArgumentParser()
parser.add_argument('--max-rate-mb', action='store', type=int, default=10000, help='The maximum rate in MB/h to restore files at.  Files larger than this will not be restored.')
parser.add_argument('--restore-days', action='store', type=int, default=30, help='How many days restored objects will remain in S3.')
parser.add_argument('--restore-path', action='store', help='The bucket/prefix to restore from')
parser.add_argument('--pretend', action='store_true', help='Do not execute restores')
parser.add_argument('--estimate', action='store_true', help='When pretending, do not check for already-restored files')
args = parser.parse_args()

if not args.restore_path:
    print 'No restore path specified.'
    sys.exit(1)

BUCKET = None
PREFIX = None
if '/' in args.restore_path:
    BUCKET, PREFIX = args.restore_path.split('/',1)
else:
    BUCKET = args.restore_path
    PREFIX = ''

RATE_LIMIT_BYTES = args.max_rate_mb * 1024 * 1024

s3 = boto3.Session(aws_access_key_id='<ACCESS_KEY>', aws_secret_access_key='<SECRET_KEY>').resource('s3')
bucket = s3.Bucket(BUCKET)

totalsize = 0
objects = []

objcount = 0
for objpage in bucket.objects.filter(Prefix=PREFIX).page_size(100).pages():
    for obj in objpage:
        objcount += 1
        print obj
        objects.append(obj)
    print u'Found {} objects.'.format(objcount)
print

objects.sort(key=lambda x: x.size, reverse=True)

objects = filter(lambda x: x.storage_class == 'GLACIER', objects)

if objects:
    obj = objects[0]
    print u'The largest object found is of {} size: {:14,d}  {:1s}  {}'.format(('a restorable' if obj.size <= RATE_LIMIT_BYTES else 'an UNRESTORABLE'), obj.size, obj.storage_class[0], obj.key)
    print

while objects:
    current_set = []
    current_set_total = 0
    unreported_unrestoreable_objects = []
    i = 0
    while i < len(objects):
        obj = objects[i]

        if obj.size > RATE_LIMIT_BYTES:
            unreported_unrestoreable_objects.append(obj)
        elif unreported_unrestoreable_objects:
            # No longer accumulating these.  Print the ones we found.
            print u'Some objects could not be restored due to exceeding the hourly rate limit:'
            for obj in unreported_unrestoreable_objects:
                print u'- {:14,d}  {:1s}  {}'.format(obj.size, obj.storage_class[0], obj.key)
            print

        if current_set_total + obj.size <= RATE_LIMIT_BYTES:
            if not args.pretend or not args.estimate:
                if obj.Object().restore is not None:
                    objects.pop(i)
                    continue
            current_set.append(obj)
            current_set_total += obj.size
            objects.pop(i)
            continue
        i += 1

    for obj in current_set:
        print u'{:14,d}  {:1s}  {}'.format(obj.size, obj.storage_class[0], obj.key)
        #pprint(obj.Object().restore)
        if not args.pretend:
            obj.restore_object(RestoreRequest={'Days': args.restore_days})
        #sys.exit(0)

    print u'{:s} Requested restore of {:d} objects consisting of {:,d} bytes.  {:d} objects remaining.  {:,d} bytes of hourly restore rate wasted'.format(time.strftime('%Y-%m-%d %H:%M:%S'), len(current_set), current_set_total, len(objects), RATE_LIMIT_BYTES - current_set_total)
    print
    if not objects:
        break
    if not args.pretend:
        time.sleep(3690)

Команда для запуска скрипта:

python restore_glacier_data_to_s3.py --restore-path s3-bucket-name/folder-name/
Другие вопросы по тегам