1+ # -*- coding=utf-8
2+ #
3+ # ref to @shezhangjun
4+ # https://github.com/shezhangjun/TencentCOS/blob/master/Python_SDK/COS_Disaster_Recovery/DisasterRecovery.py
5+ #
6+ from qcloud_cos import CosConfig
7+ from qcloud_cos import CosS3Client
8+ import sys
9+ import os
10+ import logging
11+
12+ # logging.basicConfig(level=logging.INFO, stream=sys.stdout)
13+
14+
15+ def _recover_main (src_region , src_secret_id , src_secret_key , src_bucket , prefix ,
16+ dst_region , dst_secret_id , dst_secret_key , dst_bucket ):
17+ src_client = CosS3Client (CosConfig (Region = src_region , SecretId = src_secret_id , SecretKey = src_secret_key ))
18+ dst_client = CosS3Client (CosConfig (Region = dst_region , SecretId = dst_secret_id , SecretKey = dst_secret_key ))
19+ while True :
20+ key_marker = ''
21+ versionId_marker = ''
22+ response = src_client .list_objects_versions (
23+ Bucket = src_bucket ,
24+ Prefix = prefix ,
25+ KeyMarker = key_marker ,
26+ VersionIdMarker = versionId_marker ,
27+ )
28+ delete_marker_keys = list ()
29+ recovered_keys = list ()
30+ # 从 DeleteMarker 取出被删除的对象
31+ if 'DeleteMarker' in response :
32+ for version in response ['DeleteMarker' ]:
33+ if version ['IsLatest' ] == 'true' :
34+ delete_marker_keys .append (version ['Key' ])
35+
36+ if len (delete_marker_keys ) == 0 :
37+ print ('no delete markers found, no data to recover' )
38+ return
39+
40+ # 从 Version 取最新的版本号
41+ if 'Version' in response :
42+ for version in response ['Version' ]:
43+ key = version ['Key' ]
44+ versionId = version ['VersionId' ]
45+ if key in delete_marker_keys and not key in recovered_keys :
46+ print ('recover from key:{key}, versionId:{versionId}' .format (key = key , versionId = versionId ))
47+ try :
48+ dst_client .copy (
49+ Bucket = dst_bucket ,
50+ Key = key ,
51+ CopySource = {
52+ 'Bucket' : src_bucket ,
53+ 'Key' : key ,
54+ 'Region' : src_region ,
55+ 'VersionId' : versionId ,
56+ }
57+ )
58+ recovered_keys .append (key )
59+ print ("success recover object: {src_bucket}/{key}({versionId}) => {dst_bucket}/{key}" .format (
60+ src_bucket = src_bucket , key = key , versionId = versionId , dst_bucket = dst_bucket ))
61+ except Exception as e :
62+ print (e )
63+ pass
64+
65+ if response ['IsTruncated' ] == 'false' :
66+ break
67+
68+ key_marker = response ['NextKeyMarker' ]
69+ versionId_marker = response ['NextVersionIdMarker' ]
70+
71+
72+ if __name__ == '__main__' :
73+ # 使用场景:
74+ # 根据源桶src_bucket的删除标记从历史版本里把文件恢复到dst_bucket
75+ # src_bucket和dst_bucket可以一致, 即原地恢复
76+
77+ # 源桶信息
78+ src_region = 'ap-guangzhou' # 源地域
79+ src_secret_id = '' # 源桶SecretID
80+ src_secret_key = '' # 源桶SecretKey
81+ src_bucket = 'bucket-1200000000' # 源桶名
82+
83+ # 目标桶信息
84+ dst_region = 'ap-guangzhou' # 目标桶地域
85+ dst_secret_id = '' # 目标桶SecretID
86+ dst_secret_key = '' # 目标桶SecretKey
87+ dst_bucket = 'bucket-1250000000' # 目标桶名
88+
89+ prefix = '' # 设置要恢复的对象前缀
90+
91+ _recover_main (src_region , src_secret_id , src_secret_key , src_bucket , prefix ,
92+ dst_region , dst_secret_id , dst_secret_key , dst_bucket )
0 commit comments