Skip to content

Commit

Permalink
oracleobjectstorage: Support "backend restore" command - fixes rclone…
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilahuja authored and ncw committed Jan 9, 2024
1 parent 0563cc6 commit 1045f54
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
102 changes: 102 additions & 0 deletions backend/oracleobjectstorage/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"sync"
"time"

"github.com/oracle/oci-go-sdk/v65/common"
"github.com/oracle/oci-go-sdk/v65/objectstorage"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/operations"
)

// ------------------------------------------------------------
Expand All @@ -23,6 +26,7 @@ const (
operationRename = "rename"
operationListMultiPart = "list-multipart-uploads"
operationCleanup = "cleanup"
operationRestore = "restore"
)

var commandHelp = []fs.CommandHelp{{
Expand Down Expand Up @@ -77,6 +81,42 @@ Durations are parsed as per the rest of rclone, 2h, 7d, 7w etc.
Opts: map[string]string{
"max-age": "Max age of upload to delete",
},
}, {
Name: operationRestore,
Short: "Restore objects from Archive to Standard storage",
Long: `This command can be used to restore one or more objects from Archive to Standard storage.
Usage Examples:
rclone backend restore oos:bucket/path/to/directory -o hours=HOURS
rclone backend restore oos:bucket -o hours=HOURS
This flag also obeys the filters. Test first with --interactive/-i or --dry-run flags
rclone --interactive backend restore --include "*.txt" oos:bucket/path -o hours=72
All the objects shown will be marked for restore, then
rclone backend restore --include "*.txt" oos:bucket/path -o hours=72
It returns a list of status dictionaries with Object Name and Status
keys. The Status will be "RESTORED"" if it was successful or an error message
if not.
[
{
"Object": "test.txt"
"Status": "RESTORED",
},
{
"Object": "test/file4.txt"
"Status": "RESTORED",
}
]
`,
Opts: map[string]string{
"hours": "The number of hours for which this object will be restored. Default is 24 hrs.",
},
},
}

Expand Down Expand Up @@ -113,6 +153,8 @@ func (f *Fs) Command(ctx context.Context, commandName string, args []string,
}
}
return nil, f.cleanUp(ctx, maxAge)
case operationRestore:
return f.restore(ctx, opt)
default:
return nil, fs.ErrorCommandNotFound
}
Expand Down Expand Up @@ -290,3 +332,63 @@ func (f *Fs) listMultipartUploadParts(ctx context.Context, bucketName, bucketPat
}
return uploadedParts, nil
}

func (f *Fs) restore(ctx context.Context, opt map[string]string) (interface{}, error) {
req := objectstorage.RestoreObjectsRequest{
NamespaceName: common.String(f.opt.Namespace),
RestoreObjectsDetails: objectstorage.RestoreObjectsDetails{},
}
if hours := opt["hours"]; hours != "" {
ihours, err := strconv.Atoi(hours)
if err != nil {
return nil, fmt.Errorf("bad value for hours: %w", err)
}
req.RestoreObjectsDetails.Hours = &ihours
}
type status struct {
Object string
Status string
}
var (
outMu sync.Mutex
out = []status{}
err error
)
err = operations.ListFn(ctx, f, func(obj fs.Object) {
// Remember this is run --checkers times concurrently
o, ok := obj.(*Object)
st := status{Object: obj.Remote(), Status: "RESTORED"}
defer func() {
outMu.Lock()
out = append(out, st)
outMu.Unlock()
}()
if !ok {
st.Status = "Not an OCI Object Storage object"
return
}
if o.storageTier == nil || (*o.storageTier != "archive") {
st.Status = "Object not in Archive storage tier"
return
}
if operations.SkipDestructive(ctx, obj, "restore") {
return
}
bucket, bucketPath := o.split()
reqCopy := req
reqCopy.BucketName = &bucket
reqCopy.ObjectName = &bucketPath
var response objectstorage.RestoreObjectsResponse
err = f.pacer.Call(func() (bool, error) {
response, err = f.srv.RestoreObjects(ctx, reqCopy)
return shouldRetry(ctx, response.HTTPResponse(), err)
})
if err != nil {
st.Status = err.Error()
}
})
if err != nil {
return out, err
}
return out, nil
}
41 changes: 41 additions & 0 deletions docs/content/oracleobjectstorage.md
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,47 @@ Options:

- "max-age": Max age of upload to delete

### restore

Restore objects from Archive to Standard storage

rclone backend restore remote: [options] [<arguments>+]

This command can be used to restore one or more objects from Archive to Standard storage.

Usage Examples:

rclone backend restore oos:bucket/path/to/directory -o hours=HOURS
rclone backend restore oos:bucket -o hours=HOURS

This flag also obeys the filters. Test first with --interactive/-i or --dry-run flags

rclone --interactive backend restore --include "*.txt" oos:bucket/path -o hours=72

All the objects shown will be marked for restore, then

rclone backend restore --include "*.txt" oos:bucket/path -o hours=72

It returns a list of status dictionaries with Object Name and Status
keys. The Status will be "RESTORED"" if it was successful or an error message
if not.

[
{
"Object": "test.txt"
"Status": "RESTORED",
},
{
"Object": "test/file4.txt"
"Status": "RESTORED",
}
]


Options:

- "hours": The number of hours for which this object will be restored. Default is 24 hrs.

{{< rem autogenerated options stop >}}

## Tutorials
Expand Down

0 comments on commit 1045f54

Please sign in to comment.