はじめに
本年度から業務内容がWindowsアプリ開発からAWS関連の業務に代わり、
最初のタスクが「Azure Blob Storageから AWS S3に移行されたデータが正しく移行されているかの検証」でした。
aws s3にはアップロード時に、アップロード前と後のオブジェクトの整合性を検証する手段があるのですが、今回は既に全データ移行済みだったため、BlobとS3のメタデータを取得して格納されているMD5ハッシュ値で検証を実施しました。
ちなみに言語はpythonを使っています。
結論
- オブジェクトのメタデータ取得(S3編)
- オブジェクトのメタデータ取得(Blob編)
- 終わり
オブジェクトのメタデータ取得(S3編)
pythonかつaws s3のメタデータを取得する方法は探せば多くの情報が見つかると思います。
下記のコードもその一例になります。
from azure.storage.blob import BlobServiceClient
# AWS CLIの aws configure コマンドで .aws/credentialsファイルに書き込むこと
aws_access_key_id = ''
aws_secret_access_key = ''
bucket_name = ''
key_name = ''
s3_cli = boto3.client('s3',aws_access_key_id, aws_secret_access_key)
# オブジェクトのメタデータを取得
s3_resp = s3_cli.head_object(bucket_name, key_name)
# レスポンスからMD5ハッシュが格納されているEtagを取得
s3obj_etag = s3_resp['ETag'].strip('"')
return s3obj_etag
key_id
やbucket_name
は自分の環境にあわせて値を代入してください。
boto3.client()
でs3へアクセスするオブジェクトをまず取得します。
その後、head_object()
でオブジェクトのメタデータを取得します。
# オブジェクトのメタデータを取得
s3_resp = s3_cli.head_object(bucket_name, key_name)
s3_respはjson
が返ってきます。返り値の中身は下記のようなデータが入っています。
"s_respの中身の例"
{'ResponseMetadata': {'RequestId': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e',
'HostId': '',
'HTTPStatusCode': 200,
'HTTPHeaders': {'date': 'Sun, 13 Dec 2020 22:43:10 GMT',
'x-amz-request-id': '9dad3fc3-0e30-1dbc-a754-06bdfcde1d5e',
'last-modified': 'Sun, 13 Dec 2020 22:40:57 GMT',
'etag': '"669fdad9e309b552f1e9cf7b489c1f73-2"',
'content-type': 'binary/octet-stream',
'x-amz-server-side-encryption': 'AES256',
'x-amz-version-id': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e',
'accept-ranges': 'bytes',
'content-length': '10485760',
'server': 'CloudianS3'},
'RetryAttempts': 0},
'AcceptRanges': 'bytes',
'LastModified': datetime.datetime(2020, 12, 13, 22, 40, 57, tzinfo=tzutc()),
'ContentLength': 10485760,
'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"',
'VersionId': 'fe14c26b-bba0-6edf-a754-06bdfcde1d5e',
'ContentType': 'binary/octet-stream',
'ServerSideEncryption': 'AES256',
'Metadata': {}}
head_object
の返り値にETag
というキーがあります。この値がMD5ハッシュ値になります。
'ETag': '"669fdad9e309b552f1e9cf7b489c1f73-2"'
数字型として使う場合は、下記のようにstrip()で "" を削除して使いましょう。
# レスポンスからMD5ハッシュが格納されているEtagを取得
# ""を除去
s3obj_etag = s3_resp['ETag'].strip('"')
以上でaws s3のMD5ハッシュ取得については終了です。
オブジェクトのメタデータ取得(Blob編)
s3と違ってazure blobのメタデータ取得については、探すのに時間がかかりました。
なので、ここからは皆さんのお役になる情報だと思います。
from azure.storage.blob import BlobServiceClient
# BLOB接続文字列
connectionString = ''
container_name = ''
blob_name = ''
blob_service_client = BlobServiceClient.from_connection_string(connectionString)
blob_client = blob_service_client.get_blob_client(container_name, blob_name)
# BLOBのすべてのユーザー定義メタデータ、標準HTTPプロパティ、およびシステムプロパティを受け取る
prop = blob_client.get_blob_properties()
bytearray = prop['content_settings']['content_md5']
return bytearray.hex()
以下、解説になります。
from_connection_string()
、get_blob_client()
を使ってBlobClient
を取得します。
blob_service_client = BlobServiceClient.from_connection_string(connectionString)
blob_client = blob_service_client.get_blob_client(container_name, blob_name)
BlobClient
クラスにはget_blob_properties()
というAPIがあり、このAPIがBLOBのメタデータ(BlobProperties
)を返してくれます。
ここで注意点なのですが、BlobProperties
にはetagというキーがありますが、今回欲しいハッシュ値は、content_settings
キーの値ContentSettings
にcontent_md5
というキーがありこちらになります。
prop = blob_client.get_blob_properties()
bytearray = prop['content_settings']['content_md5']
return bytearray.hex()
content_md5はbytearray
型なので、hex()
で変換することでs3で取得した値と同じものになるかと思います。
終わり
以上になります。
先にs3のハッシュを取得できていたため、BlobProperties
にはetagを見つけて返り値を確認した時は、なぜs3の返り値と値が異なるのかと頭を抱えていました。
Microsoftのドキュメントをきちんと確認することはやはり大事ですね。
皆さんはデータ移行時は必ずアップロード時に整合性を確認して、失敗した場合はリトライなどの処理をしましょう。データ数が多いので、移行後の整合性確認はお金の無駄でしかありません。