Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat]tools-v2: add bs recover volume #2936

Merged
merged 1 commit into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions tools-v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ A tool for CurveFS & CurveBs.
- [snapshot copyset](#snapshot-copyset)
- [stop](#stop)
- [stop snapshot](#stop-snapshot)
- [recover](#recover)
- [recover volume](#recover-volume)
- [Comparison of old and new commands](#comparison-of-old-and-new-commands)
- [curve fs](#curve-fs)
- [curve bs](#curve-bs)
Expand Down Expand Up @@ -2037,6 +2039,27 @@ Output:
+--------------------------------------+--------------+---------+
```

#### recover

##### recover volume

recover volume from recycleBin

Usage:
```shell
curve bs recover volume --path /test/path --user root
```

Output:
```
+-----------+---------+
| FILENAME | RESULT |
+-----------+---------+
| test/path | success |
+-----------+---------+
```


## Comparison of old and new commands

### curve fs
Expand Down
4 changes: 3 additions & 1 deletion tools-v2/internal/error/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,9 @@ var (
ErrInvalidMetaServerAddr = func() *CmdError {
return NewInternalCmdError(80, "invalid metaserver external addr: %s")
}

ErrBsRecoverFile = func() *CmdError {
return NewInternalCmdError(81, "recover file fail, err: %s")
}
// http error
ErrHttpUnreadableResult = func() *CmdError {
return NewHttpResultCmdError(1, "http response is unreadable, the uri is: %s, the error is: %s")
Expand Down
50 changes: 50 additions & 0 deletions tools-v2/pkg/cli/command/curvebs/recover/recover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 NetEase Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* Project: CurveCli
* Created Date: 2023-11-15
* Author: CrystalAnalyst
*/
package recover

import (
basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command"
volume "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/recover/volume"
"github.com/spf13/cobra"
)

type RecoverCommand struct {
basecmd.MidCurveCmd
}

var _ basecmd.MidCurveCmdFunc = (*RecoverCommand)(nil)

func (rCmd *RecoverCommand) AddSubCommands() {
rCmd.Cmd.AddCommand(
volume.NewVolumeCommand(),
)
}

func NewRecoverCommand() *cobra.Command {
rCmd := &RecoverCommand{
basecmd.MidCurveCmd{
Use: "recover",
Short: "recover resources in curvebs cluster",
},
}
return basecmd.NewMidCurveCli(&rCmd.MidCurveCmd, rCmd)
}
174 changes: 174 additions & 0 deletions tools-v2/pkg/cli/command/curvebs/recover/volume/volume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package volume

import (
"context"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"google.golang.org/grpc"

cmderror "github.com/opencurve/curve/tools-v2/internal/error"
cobrautil "github.com/opencurve/curve/tools-v2/internal/utils"
basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command"
"github.com/opencurve/curve/tools-v2/pkg/config"
"github.com/opencurve/curve/tools-v2/pkg/output"
"github.com/opencurve/curve/tools-v2/proto/proto/nameserver2"
)

const (
RecoverExample = ` $ curve bs recover volume --path /test/path --user username `
)

func NewVolumeCommand() *cobra.Command {
return NewRecoverFileCommand().Cmd
}

func NewRecoverFileCommand() *RecoverFileCommand {
RecoverFileCommand := &RecoverFileCommand{
FinalCurveCmd: basecmd.FinalCurveCmd{
Use: "volume",
Short: "recover volume in curvebs",
Example: RecoverExample,
},
}
basecmd.NewFinalCurveCli(&RecoverFileCommand.FinalCurveCmd, RecoverFileCommand)
return RecoverFileCommand
}

type RecoverCertainFileRPC struct {
Info *basecmd.Rpc
Request *nameserver2.RecoverFileRequest
mdsClient nameserver2.CurveFSServiceClient
}

var _ basecmd.RpcFunc = (*RecoverCertainFileRPC)(nil)

func (gRpc *RecoverCertainFileRPC) NewRpcClient(cc grpc.ClientConnInterface) {
gRpc.mdsClient = nameserver2.NewCurveFSServiceClient(cc)
}

func (gRpc *RecoverCertainFileRPC) Stub_Func(ctx context.Context) (interface{}, error) {
return gRpc.mdsClient.RecoverFile(ctx, gRpc.Request)
}

type RecoverFileCommand struct {
basecmd.FinalCurveCmd
Rpc *RecoverCertainFileRPC
Response *nameserver2.RecoverFileResponse
}

var _ basecmd.FinalCurveCmdFunc = (*RecoverFileCommand)(nil)

func (rCmd *RecoverFileCommand) Init(cmd *cobra.Command, args []string) error {
mdsAddrs, err := config.GetBsMdsAddrSlice(rCmd.Cmd)
if err.TypeCode() != cmderror.CODE_SUCCESS {
return err.ToError()
}

//get the default timeout and retrytimes
timeout := config.GetFlagDuration(rCmd.Cmd, config.RPCTIMEOUT)
retrytimes := config.GetFlagInt32(rCmd.Cmd, config.RPCRETRYTIMES)

//get the params needed from commandline
path := config.GetBsFlagString(rCmd.Cmd, config.CURVEBS_PATH)
username := config.GetBsFlagString(rCmd.Cmd, config.CURVEBS_USER)
password := config.GetBsFlagString(rCmd.Cmd, config.CURVEBS_PASSWORD)
fileId := config.GetBsFlagUint64(rCmd.Cmd, config.CURVEBS_FILE_ID)
date, errDat := cobrautil.GetTimeofDayUs()
if errDat.TypeCode() != cmderror.CODE_SUCCESS {
return errDat.ToError()
}

//add basic info
recoverRequest := nameserver2.RecoverFileRequest{
FileName: &path,
Owner: &username,
FileId: &fileId,
Date: &date,
}

//add signature
if username == viper.GetString(config.VIPER_CURVEBS_USER) && len(password) != 0 {
strSig := cobrautil.GetString2Signature(date, username)
sig := cobrautil.CalcString2Signature(strSig, password)
recoverRequest.Signature = &sig
}
rCmd.Rpc = &RecoverCertainFileRPC{
Info: basecmd.NewRpc(mdsAddrs, timeout, retrytimes, "recoverFile"),
Request: &recoverRequest,
}

//set headers
header := []string{
cobrautil.ROW_FILE_NAME,
cobrautil.ROW_RESULT,
}
rCmd.SetHeader(header)
out := make(map[string]string)
out[cobrautil.ROW_FILE_NAME] = *recoverRequest.FileName
list := cobrautil.Map2List(out, []string{cobrautil.ROW_FILE_NAME})
rCmd.TableNew.Append(list)
return nil
}

func (rCmd *RecoverFileCommand) AddFlags() {
config.AddRpcTimeoutFlag(rCmd.Cmd)
config.AddRpcRetryTimesFlag(rCmd.Cmd)
config.AddBsMdsFlagOption(rCmd.Cmd)

//file path and user name is required.
config.AddBsPathRequiredFlag(rCmd.Cmd)
config.AddBsUserRequireFlag(rCmd.Cmd)

//password and fileID is optional.
config.AddBsPasswordOptionFlag(rCmd.Cmd)
config.AddBsFileIdOptionFlag(rCmd.Cmd)
}

func (rCmd *RecoverFileCommand) RunCommand(cmd *cobra.Command, args []string) error {
result, err := basecmd.GetRpcResponse(rCmd.Rpc.Info, rCmd.Rpc)
if err.TypeCode() != cmderror.CODE_SUCCESS {
rCmd.Error = err
rCmd.Result = result
return err.ToError()
}
rCmd.Response = result.(*nameserver2.RecoverFileResponse)
if rCmd.Response.GetStatusCode() != nameserver2.StatusCode_kOK {
rCmd.Error = cmderror.ErrBsRecoverFile()
rCmd.Result = result
return rCmd.Error.ToError()
}
out := make(map[string]string)
out[cobrautil.ROW_RESULT] = cobrautil.ROW_VALUE_SUCCESS
list := cobrautil.Map2List(out, []string{cobrautil.ROW_RESULT})
rCmd.TableNew.Append(list)
rCmd.Result, rCmd.Error = result, cmderror.Success()
return nil
}

func (rCmd *RecoverFileCommand) Print(cmd *cobra.Command, args []string) error {
return output.FinalCmdOutput(&rCmd.FinalCurveCmd, rCmd)
}

func (rCmd *RecoverFileCommand) ResultPlainOutput() error {
return output.FinalCmdOutputPlain(&rCmd.FinalCurveCmd)
}

func RecoverFile(caller *cobra.Command) (*nameserver2.RecoverFileResponse, *cmderror.CmdError) {
rCmd := NewRecoverFileCommand()
config.AlignFlagsValue(caller, rCmd.Cmd, []string{
config.RPCRETRYTIMES, config.RPCTIMEOUT, config.CURVEBS_MDSADDR,
config.CURVEBS_PATH, config.CURVEBS_USER,
config.CURVEBS_PASSWORD, config.CURVEBS_FILE_ID,
})
rCmd.Cmd.SilenceErrors = true
rCmd.Cmd.SilenceUsage = true
rCmd.Cmd.SetArgs([]string{"--format", config.FORMAT_NOOUT})
err := rCmd.Cmd.Execute()
if err != nil {
retErr := cmderror.ErrBsRecoverFile()
retErr.Format(err.Error())
return rCmd.Response, retErr
}
return rCmd.Response, cmderror.Success()
}
14 changes: 14 additions & 0 deletions tools-v2/pkg/config/bs.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ const (
VIPER_CURVEBS_FILENAME = "curvebs.filename"
CURVEBS_SNAPSHOTNAME = "snapshotname"
VIPER_CURVEBS_SNAPSHOTNAME = "curvebs.snapshotname"
CURVEBS_FILE_ID = "fileId"
VIPER_CURVEBS_FILE_ID = "curvebs.fileId"
)

var (
Expand Down Expand Up @@ -557,6 +559,10 @@ func AddBsPathRequiredFlag(cmd *cobra.Command) {
AddBsStringRequiredFlag(cmd, CURVEBS_PATH, "file path")
}

func AddBsUserRequireFlag(cmd *cobra.Command) {
AddBsStringRequiredFlag(cmd, CURVEBS_USER, "user name")
}

func AddBsLogicalPoolIdRequiredFlag(cmd *cobra.Command) {
AddBsUint32RequiredFlag(cmd, CURVEBS_LOGIC_POOL_ID, "logical pool id")
}
Expand Down Expand Up @@ -693,6 +699,10 @@ func AddBsSnapshotNameRequiredFlag(cmd *cobra.Command) {
AddBsStringRequiredFlag(cmd, CURVEBS_SNAPSHOTNAME, "snapshot name")
}

func AddBsFileIdOptionFlag(cmd *cobra.Command) {
AddBsUint64OptionFlag(cmd, CURVEBS_FILE_ID, "recover fileId")
}

// get stingslice flag
func GetBsFlagStringSlice(cmd *cobra.Command, flagName string) []string {
var value []string
Expand Down Expand Up @@ -876,3 +886,7 @@ func GetBsChunkServerId(cmd *cobra.Command) []uint32 {
}
return chunkserveridSlice
}

func GetBsFileId(cmd *cobra.Command) uint64 {
return GetBsFlagUint64(cmd, CURVEBS_FILE_ID)
}