Skip to content

Commit

Permalink
support ColdArchive
Browse files Browse the repository at this point in the history
  • Loading branch information
taowei.wtw authored and kkuai committed Apr 21, 2020
1 parent 2a3b380 commit 8d1309e
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 36 deletions.
11 changes: 2 additions & 9 deletions lib/bucket_inventory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func (s *OssutilCommandSuite) TestInventoryPutSuccess(c *C) {
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Frequency: "Daily",
IncludedObjectVersions: "All",
Expand Down Expand Up @@ -109,9 +108,7 @@ func (s *OssutilCommandSuite) TestInventoryGetErrorResultFileOpenError(c *C) {
AccountId: accountID,
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Prefix: "prefix1"},
Frequency: "Daily",
IncludedObjectVersions: "All",
OptionalFields: oss.OptionalFields{
Expand Down Expand Up @@ -315,7 +312,6 @@ func (s *OssutilCommandSuite) TestInventoryGetConfirm(c *C) {
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Frequency: "Daily",
IncludedObjectVersions: "All",
Expand Down Expand Up @@ -393,7 +389,6 @@ func (s *OssutilCommandSuite) TestInventoryDelete(c *C) {
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Frequency: "Daily",
IncludedObjectVersions: "All",
Expand Down Expand Up @@ -478,7 +473,6 @@ func (s *OssutilCommandSuite) TestInventoryListSuccess(c *C) {
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Frequency: "Daily",
IncludedObjectVersions: "All",
Expand Down Expand Up @@ -557,7 +551,6 @@ func (s *OssutilCommandSuite) TestInventoryListMarkerSuccess(c *C) {
RoleArn: stsARN,
Bucket: "acs:oss:::" + bucketName,
Prefix: "prefix1",
KeyId: "keyId",
},
Frequency: "Daily",
IncludedObjectVersions: "All",
Expand Down Expand Up @@ -629,7 +622,7 @@ func (s *OssutilCommandSuite) TestInventoryListMarkerSuccess(c *C) {
c.Assert(err, IsNil)

// list error,result file open error
inventoryArgs = []string{CloudURLToString(bucketName, ""), string(os.PathSeparator) + "root1" + string(os.PathListSeparator) + "test-file"}
inventoryArgs = []string{CloudURLToString(bucketName, ""), string(os.PathSeparator) + "root1" + string(os.PathSeparator) + "test-file"}
_, err = cm.RunCommand("inventory", inventoryArgs, options)
c.Assert(err, NotNil)

Expand Down
3 changes: 2 additions & 1 deletion lib/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const (
const (
Package string = "ossutil"
ChannelBuf int = 1000
Version string = "v1.6.11"
Version string = "v1.6.12"
DefaultEndpoint string = "oss.aliyuncs.com"
ChineseLanguage = "CH"
EnglishLanguage = "EN"
Expand Down Expand Up @@ -170,6 +170,7 @@ const (
StorageStandard = string(oss.StorageStandard)
StorageIA = string(oss.StorageIA)
StorageArchive = string(oss.StorageArchive)
StorageColdArchive = string(oss.StorageColdArchive)
DefaultStorageClass = StorageStandard
DefaultMethod = string(oss.HTTPGet)
DefaultTimeout = 60
Expand Down
14 changes: 7 additions & 7 deletions lib/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2133,7 +2133,7 @@ func (cc *CopyCommand) ossPutObjectRetry(bucket *oss.Bucket, objectName string,
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d:put object:%s.\n", i-1, objectName)
}
Expand All @@ -2157,7 +2157,7 @@ func (cc *CopyCommand) ossUploadFileRetry(bucket *oss.Bucket, objectName string,
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d:upload file:%s\n", i-1, filePath)
}
Expand Down Expand Up @@ -2238,7 +2238,7 @@ func (cc *CopyCommand) ossResumeUploadRetry(bucket *oss.Bucket, objectName strin
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d,multipart upload file:%s.\n", i-1, filePath)
}
Expand Down Expand Up @@ -2525,7 +2525,7 @@ func (cc *CopyCommand) ossDownloadFileRetry(bucket *oss.Bucket, objectName, file
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d:get object to file:%s.\n", i-1, fileName)
}
Expand Down Expand Up @@ -2555,7 +2555,7 @@ func (cc *CopyCommand) ossResumeDownloadRetry(bucket *oss.Bucket, objectName str
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d:mulitpart download file:%s.\n", i-1, objectName)
}
Expand Down Expand Up @@ -2963,7 +2963,7 @@ func (cc *CopyCommand) ossCopyObjectRetry(bucket *oss.Bucket, objectName, destBu
options = append(options, oss.TaggingDirective(oss.TaggingReplace))
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d,copy object:%s.\n", i-1, objectName)
}
Expand All @@ -2990,7 +2990,7 @@ func (cc *CopyCommand) ossResumeCopyRetry(bucketName, objectName, destBucketName
retryTimes, _ := GetInt(OptionRetryTimes, cc.command.options)
for i := 1; ; i++ {
if i > 1 {
time.Sleep(time.Duration(1) * time.Second)
time.Sleep(time.Duration(3) * time.Second)
if int64(i) >= retryTimes {
fmt.Printf("\nretry count:%d, resume copy object:%s.\n", i-1, objectName)
}
Expand Down
8 changes: 6 additions & 2 deletions lib/mb.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var storageClassList = []string{
StorageStandard,
StorageIA,
StorageArchive,
StorageColdArchive,
}

func formatStorageClassString(sep string) string {
Expand Down Expand Up @@ -46,7 +47,7 @@ ACL:
StorageClass:
bucket的StorageClass有三种
bucket的StorageClass有四种
` + formatStorageClassString("\n ") + `
关于StorageClass的更多信息请参考:https://help.aliyun.com/document_detail/31959.html?spm=5176.doc31957.6.839.E1ifnh
Expand Down Expand Up @@ -104,7 +105,7 @@ ACL:
StorageClass:
There are three kinds of StorageClass:
There are four kinds of StorageClass:
` + formatStorageClassString("\n ") + `
More information about StorageClass see: https://help.aliyun.com/document_detail/31959.html?spm=5176.doc31957.6.839.E1ifnh
Expand Down Expand Up @@ -270,5 +271,8 @@ func (mc *MakeBucketCommand) getStorageClass() oss.StorageClassType {
if strings.EqualFold(storageClass, StorageArchive) {
return oss.StorageArchive
}
if strings.EqualFold(storageClass, StorageColdArchive) {
return oss.StorageColdArchive
}
return oss.StorageStandard
}
6 changes: 3 additions & 3 deletions lib/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ var OptionMap = map[string]Option{
OptionAllType: Option{"-a", "--all-type", "", OptionTypeFlagTrue, "", "", "指定操作的对象为bucket中的object和未完成的Multipart事件。", "Indicate that the subject of the command contains both objects and uncompleted Multipart Uploads."},
OptionRecursion: Option{"-r", "--recursive", "", OptionTypeFlagTrue, "", "", "递归进行操作。对于支持该选项的命令,当指定该选项时,命令会对bucket下所有符合条件的objects进行操作,否则只对url中指定的单个object进行操作。", "operate recursively, for those commands which support the option, when use them, if the option is specified, the command will operate on all match objects under the bucket, else we will search the specified object and operate on the single object."},
OptionBucket: Option{"-b", "--bucket", "", OptionTypeFlagTrue, "", "", "对bucket进行操作,该选项用于确认操作作用于bucket", "the option used to make sure the operation will operate on bucket"},
OptionStorageClass: Option{"", "--storage-class", DefaultStorageClass, OptionTypeAlternative, fmt.Sprintf("%s/%s/%s", StorageStandard, StorageIA, StorageArchive), "",
fmt.Sprintf("设置对象的存储方式,默认值:%s,取值范围:%s/%s/%s。", DefaultStorageClass, StorageStandard, StorageIA, StorageArchive),
fmt.Sprintf("set the storage class of bucket(default: %s), value range is: %s/%s/%s.", DefaultStorageClass, StorageStandard, StorageIA, StorageArchive)},
OptionStorageClass: Option{"", "--storage-class", DefaultStorageClass, OptionTypeAlternative, fmt.Sprintf("%s/%s/%s/%s", StorageStandard, StorageIA, StorageArchive, StorageColdArchive), "",
fmt.Sprintf("设置对象的存储方式,默认值:%s,取值范围:%s/%s/%s/%s。", DefaultStorageClass, StorageStandard, StorageIA, StorageArchive, StorageColdArchive),
fmt.Sprintf("set the storage class of bucket(default: %s), value range is: %s/%s/%s/%s.", DefaultStorageClass, StorageStandard, StorageIA, StorageArchive, StorageColdArchive)},
OptionForce: Option{"-f", "--force", "", OptionTypeFlagTrue, "", "", "强制操作,不进行询问提示。", "operate silently without asking user to confirm the operation."},
OptionUpdate: Option{"-u", "--update", "", OptionTypeFlagTrue, "", "", "更新操作", "update"},
OptionDelete: Option{"", "--delete", "", OptionTypeFlagTrue, "", "", "删除操作", "delete"},
Expand Down
90 changes: 76 additions & 14 deletions lib/restore.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package lib

import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
"strings"

oss "github.com/aliyun/aliyun-oss-go-sdk/oss"
Expand All @@ -16,17 +19,16 @@ var specChineseRestore = SpecText{

synopsisText: "恢复冷冻状态的Objects为可读状态",

paramText: "cloud_url [options]",
paramText: "cloud_url [local_xml_file] [options]",

syntaxText: `
ossutil restore cloud_url [--encoding-type url] [-r] [-f] [--output-dir=odir] [--version-id versionId] [--payer requester] [-c file]
ossutil restore cloud_url [local_xml_file] [--encoding-type url] [-r] [-f] [--output-dir=odir] [--version-id versionId] [--payer requester] [-c file]
`,

detailHelpText: `
该命令恢复处于冷冻状态的object进入可读状态,即操作对象object必须为` + StorageArchive + `存储类型
的object。
该命令恢复处于冷冻状态的object进入可读状态,即操作对象object的存储类型为StorageArchive、StorageColdArchive
一个Archive类型的object初始时处于冷冻状态
一个Archive、StorageColdArchive类型的object初始时处于冷冻状态
针对处于冷冻状态的object调用restore命令,返回成功。object处于解冻中,服务端执行解
冻,在此期间再次调用restore命令,同样成功,且不会延长object可读状态持续时间。
Expand All @@ -43,18 +45,26 @@ var specChineseRestore = SpecText{
该命令有两种用法:
1) ossutil restore oss://bucket/object [--encoding-type url]
1) ossutil restore oss://bucket/object [--encoding-type url] [local_xml_file]
该用法恢复单个冷冻状态object为可读状态,当指定object不存在时,ossutil会提示错
误,此时请确保指定的url精确匹配需要设置acl的object,并且不要指定--recursive选项(
否则ossutil会进行前缀匹配,恢复多个冷冻状态的objects为可读状态)。无论--force选项
是否指定,都不会进行询问提示。
2) ossutil restore oss://bucket[/prefix] -r [--encoding-type url] [-f] [--output-dir=odir]
2) ossutil restore oss://bucket[/prefix] -r [--encoding-type url] [-f] [--output-dir=odir] [local_xml_file]
该用法可批量恢复多个冷冻状态的objects为可读状态,此时必须输入--recursive选项,
ossutil会查找所有前缀匹配url的objects,恢复它们为可读状态。当一个object操作出现错
误时,会将出错object的错误信息记录到report文件,并继续操作其他object,成功操作的
object信息将不会被记录到report文件中(更多信息见cp命令的帮助)。如果--force选项被
指定,则不会进行询问提示。
上面的local_xml_file是本地xml格式文件, 支持设置更多的restore参数, 举例如下
<RestoreRequest>
<Days>2</Days>
<JobParameters>
<Tier>Bulk</Tier>
</JobParameters>
</RestoreRequest>
`,

sampleText: `
Expand All @@ -63,22 +73,23 @@ var specChineseRestore = SpecText{
3) ossutil restore oss://bucket-restore/object-prefix -r -f
4) ossutil restore oss://bucket-restore/%e4%b8%ad%e6%96%87 --encoding-type url
5) ossutil restore oss://bucket-restore/object-store --payer requester
6) ossutil restore oss://bucket-restore/object-prefix -r -f local_xml_file
`,
}

var specEnglishRestore = SpecText{

synopsisText: "Restore Frozen State Object to Read Ready Status",

paramText: "cloud_url [options]",
paramText: "cloud_url [local_xml_file] [options]",

syntaxText: `
ossutil restore cloud_url [--encoding-type url] [-r] [-f] [--output-dir=odir] [--version-id versionId] [--payer requester] [-c file]
ossutil restore cloud_url [local_xml_file] [--encoding-type url] [-r] [-f] [--output-dir=odir] [--version-id versionId] [--payer requester] [-c file]
`,

detailHelpText: `
The command restore frozen state object to read ready status, the object must be in the storage
class of ` + StorageArchive + `.
class of StorageArchive、StorageColdArchive
An object of Archive storage class will be in frozen state at first.
Expand All @@ -99,19 +110,27 @@ Usage:
There are two usages:
1) ossutil restore oss://bucket/object [--encoding-type url]
1) ossutil restore oss://bucket/object [--encoding-type url] [local_xml_file]
If --recursive option is not specified, ossutil restore the specified frozen state object
to readable status. In the usage, please make sure url exactly specified the object you want to
restore, if object not exist, error occurs. No matter --force option is specified or not, ossutil
will not show prompt question.
2) ossutil restore oss://bucket[/prefix] -r [--encoding-type url] [-f] [--output-dir=odir]
2) ossutil restore oss://bucket[/prefix] -r [--encoding-type url] [-f] [--output-dir=odir] [local_xml_file]
The usage restore the objects with the specified prefix and in frozen state to readable status.
--recursive option is required for the usage, and ossutil will search for prefix-matching objects
and restore those objects. When an error occurs when restore an object, ossutil will record the
error message to report file, and ossutil will continue to attempt to set acl on the remaining
objects(more information see help of cp command). If --force option is specified, ossutil will
not show prompt question.
The local_xml_file is a local XML format file, which supports setting more restore configurations. For example:
<RestoreRequest>
<Days>2</Days>
<JobParameters>
<Tier>Bulk</Tier>
</JobParameters>
</RestoreRequest>
`,

sampleText: `
Expand All @@ -120,6 +139,7 @@ Usage:
3) ossutil restore oss://bucket-restore/object-prefix -r -f
4) ossutil restore oss://bucket-restore/%e4%b8%ad%e6%96%87 --encoding-type url
5) ossutil restore oss://bucket-restore/object-store --payer requester
6) ossutil restore oss://bucket-restore/object-prefix -r -f local_xml_file
`,
}

Expand All @@ -129,14 +149,16 @@ type RestoreCommand struct {
command Command
reOption batchOptionType
commonOptions []oss.Option
restoreConfig oss.RestoreConfiguration
hasConfig bool
}

var restoreCommand = RestoreCommand{
command: Command{
name: "restore",
nameAlias: []string{},
minArgc: 1,
maxArgc: 1,
maxArgc: 2,
specChinese: specChineseRestore,
specEnglish: specEnglishRestore,
group: GroupTypeNormalCommand,
Expand Down Expand Up @@ -201,6 +223,40 @@ func (rc *RestoreCommand) RunCommand() error {
return err
}

if len(rc.command.args) == 2 {
xmlFile := rc.command.args[1]
fileInfo, err := os.Stat(xmlFile)
if err != nil {
return err
}

if fileInfo.IsDir() {
return fmt.Errorf("%s is dir,not the expected file", xmlFile)
}

if fileInfo.Size() == 0 {
return fmt.Errorf("%s is empty file", xmlFile)
}

// parsing the xml file
file, err := os.Open(xmlFile)
if err != nil {
return err
}
defer file.Close()
text, err := ioutil.ReadAll(file)
if err != nil {
return err
}

err = xml.Unmarshal(text, &(rc.restoreConfig))
if err != nil {
fmt.Printf("xml.Unmarshal error,%s is not valid xml file\n", xmlFile)
return err
}
rc.hasConfig = true
}

bucket, err := rc.command.ossBucket(cloudURL.bucket)
if err != nil {
return err
Expand Down Expand Up @@ -234,7 +290,13 @@ func (rc *RestoreCommand) ossRestoreObject(bucket *oss.Bucket, object string, ve
}
options = append(options, rc.commonOptions...)

err := bucket.RestoreObject(object, options...)
var err error
if rc.hasConfig {
err = bucket.RestoreObjectDetail(object, rc.restoreConfig, options...)
} else {
err = bucket.RestoreObject(object, options...)
}

if err == nil {
return err
}
Expand Down
Loading

0 comments on commit 8d1309e

Please sign in to comment.