diff --git a/tools-v2/README.md b/tools-v2/README.md index f3778138e9..a6cbc5936c 100644 --- a/tools-v2/README.md +++ b/tools-v2/README.md @@ -89,6 +89,7 @@ A tool for CurveFS & CurveBs. - [create](#create-1) - [create file](#create-file) - [create dir](#create-dir) + - [create volume snapshot](#create-volume-snapshot) - [check](#check-1) - [check copyset](#check-copyset-1) - [check chunkserver](#check-chunkserver) @@ -1875,6 +1876,24 @@ Output: +---------+ ``` +##### create volume snapshot + +create snapshot + +Usage: +```bash +curve bs create volume snapshot --user root --filename test --snapshotname snap-test +``` + +Output: +``` ++------+----------+--------------+ +| USER | FILENAME | SNAPSHOTNAME | ++------+----------+--------------- +| root | test | snap-test | ++------+----------+--------------+ +``` + #### check ##### check copyset diff --git a/tools-v2/internal/utils/row.go b/tools-v2/internal/utils/row.go index cbda105325..2e468056bd 100644 --- a/tools-v2/internal/utils/row.go +++ b/tools-v2/internal/utils/row.go @@ -137,6 +137,7 @@ const ( ROW_ISLAZY = "isLazy" ROW_NEXTSTEP = "nextStep" ROW_TIME = "time" + ROW_SNAPSHOTNAME = "snapshotName" ROW_RW_STATUS = "rwStatus" ROW_DISK_STATE = "diskState" diff --git a/tools-v2/internal/utils/snapshot/const.go b/tools-v2/internal/utils/snapshot/const.go index 933ec4291f..c5b202dac5 100644 --- a/tools-v2/internal/utils/snapshot/const.go +++ b/tools-v2/internal/utils/snapshot/const.go @@ -38,6 +38,7 @@ const ( QueryStatus = "Status" QueryType = "Type" QueryFile = "File" + QueryName = "Name" ActionClone = "Clone" ActionRecover = "Recover" diff --git a/tools-v2/pkg/cli/command/curvebs/create/create.go b/tools-v2/pkg/cli/command/curvebs/create/create.go index 947385d113..8c0971b2c7 100644 --- a/tools-v2/pkg/cli/command/curvebs/create/create.go +++ b/tools-v2/pkg/cli/command/curvebs/create/create.go @@ -27,6 +27,7 @@ import ( "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create/cluster" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create/dir" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create/file" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create/volume" "github.com/spf13/cobra" ) @@ -41,6 +42,7 @@ func (createCmd *CreateCmd) AddSubCommands() { cluster.NewClusterTopoCmd(), dir.NewDirectoryCommand(), file.NewFileCommand(), + volume.NewVolumeCommand(), ) } diff --git a/tools-v2/pkg/cli/command/curvebs/create/volume/snapshot/snapshot.go b/tools-v2/pkg/cli/command/curvebs/create/volume/snapshot/snapshot.go new file mode 100644 index 0000000000..01925b4382 --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/create/volume/snapshot/snapshot.go @@ -0,0 +1,130 @@ +/* +* 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-09-23 +* Author: baytan0720 + */ + +package snapshot + +import ( + "encoding/json" + "fmt" + "time" + + cmderror "github.com/opencurve/curve/tools-v2/internal/error" + cobrautil "github.com/opencurve/curve/tools-v2/internal/utils" + snapshotutil "github.com/opencurve/curve/tools-v2/internal/utils/snapshot" + 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/spf13/cobra" +) + +const ( + snapshotExample = `$ curve bs create volume snapshot --user root --filename test --snapshotname snap-test` +) + +type SnapshotCmd struct { + basecmd.FinalCurveCmd + snapshotAddrs []string + timeout time.Duration + + user string + fileName string + snapshotName string +} + +var _ basecmd.FinalCurveCmdFunc = (*SnapshotCmd)(nil) + +func NewCommand() *cobra.Command { + return NewSnapshotCmd().Cmd +} + +func NewSnapshotCmd() *SnapshotCmd { + sCmd := &SnapshotCmd{ + FinalCurveCmd: basecmd.FinalCurveCmd{ + Use: "snapshot", + Short: "create volume snapshot in curvebs cluster", + Example: snapshotExample, + }, + } + basecmd.NewFinalCurveCli(&sCmd.FinalCurveCmd, sCmd) + return sCmd +} + +func (sCmd *SnapshotCmd) AddFlags() { + config.AddBsSnapshotCloneFlagOption(sCmd.Cmd) + config.AddHttpTimeoutFlag(sCmd.Cmd) + config.AddBsUserRequiredFlag(sCmd.Cmd) + config.AddBsFileNameRequiredFlag(sCmd.Cmd) + config.AddBsSnapshotNameRequiredFlag(sCmd.Cmd) +} + +func (sCmd *SnapshotCmd) Init(cmd *cobra.Command, args []string) error { + snapshotAddrs, err := config.GetBsSnapshotAddrSlice(sCmd.Cmd) + if err.TypeCode() != cmderror.CODE_SUCCESS || len(snapshotAddrs) == 0 { + return err.ToError() + } + sCmd.snapshotAddrs = snapshotAddrs + sCmd.timeout = config.GetFlagDuration(sCmd.Cmd, config.HTTPTIMEOUT) + sCmd.user = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_USER) + sCmd.fileName = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_FILENAME) + sCmd.snapshotName = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_SNAPSHOTNAME) + sCmd.SetHeader([]string{cobrautil.ROW_USER, cobrautil.ROW_FILE_NAME, cobrautil.ROW_SNAPSHOTNAME}) + return nil +} + +func (sCmd *SnapshotCmd) RunCommand(cmd *cobra.Command, args []string) error { + params := map[string]any{ + snapshotutil.QueryAction: snapshotutil.ActionCreateSnapshot, + snapshotutil.QueryUser: sCmd.user, + snapshotutil.QueryFile: sCmd.fileName, + snapshotutil.QueryName: sCmd.snapshotName, + } + subUri := snapshotutil.NewQuerySubUri(params) + metric := basecmd.NewMetric(sCmd.snapshotAddrs, subUri, sCmd.timeout) + result, err := basecmd.QueryMetric(metric) + if err.TypeCode() != cmderror.CODE_SUCCESS { + return err.ToError() + } + resp := snapshotutil.Response{} + if err := json.Unmarshal([]byte(result), &resp); err != nil { + return err + } + row := make(map[string]string) + row[cobrautil.ROW_USER] = sCmd.user + row[cobrautil.ROW_FILE_NAME] = sCmd.fileName + row[cobrautil.ROW_SNAPSHOTNAME] = sCmd.snapshotName + + if resp.Code != snapshotutil.ResultSuccess { + return fmt.Errorf("create snapshot fail, requestId: %s, code: %s, error: %s", resp.RequestId, resp.Code, resp.Message) + } + + sCmd.TableNew.Append(cobrautil.Map2List(row, sCmd.Header)) + sCmd.Result = row + sCmd.Error = cmderror.Success() + return nil +} + +func (sCmd *SnapshotCmd) Print(cmd *cobra.Command, args []string) error { + return output.FinalCmdOutput(&sCmd.FinalCurveCmd, sCmd) +} + +func (sCmd *SnapshotCmd) ResultPlainOutput() error { + return output.FinalCmdOutputPlain(&sCmd.FinalCurveCmd) +} diff --git a/tools-v2/pkg/cli/command/curvebs/create/volume/volume.go b/tools-v2/pkg/cli/command/curvebs/create/volume/volume.go new file mode 100644 index 0000000000..a0f2ea41ef --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/create/volume/volume.go @@ -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-09-23 +* Author: baytan0720 + */ + +package volume + +import ( + basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/create/volume/snapshot" + "github.com/spf13/cobra" +) + +type VolumeCommand struct { + basecmd.MidCurveCmd +} + +var _ basecmd.MidCurveCmdFunc = (*VolumeCommand)(nil) // check interface + +func (vCmd *VolumeCommand) AddSubCommands() { + vCmd.Cmd.AddCommand( + snapshot.NewCommand(), + ) +} + +func NewVolumeCommand() *cobra.Command { + vCmd := &VolumeCommand{ + basecmd.MidCurveCmd{ + Use: "volume", + Short: "create resources in the curvebs", + }, + } + return basecmd.NewMidCurveCli(&vCmd.MidCurveCmd, vCmd) +} diff --git a/tools-v2/pkg/cli/command/curvebs/update/volume/flatten/flatten.go b/tools-v2/pkg/cli/command/curvebs/update/volume/flatten/flatten.go index a3bd04ee8f..e50c36a2d1 100644 --- a/tools-v2/pkg/cli/command/curvebs/update/volume/flatten/flatten.go +++ b/tools-v2/pkg/cli/command/curvebs/update/volume/flatten/flatten.go @@ -69,8 +69,8 @@ func NewFlattenCmd() *FlattenCmd { func (fCmd *FlattenCmd) AddFlags() { config.AddBsSnapshotCloneFlagOption(fCmd.Cmd) config.AddHttpTimeoutFlag(fCmd.Cmd) - config.AddBsUserRequireFlag(fCmd.Cmd) - config.AddBsTaskIDRequireFlag(fCmd.Cmd) + config.AddBsUserRequiredFlag(fCmd.Cmd) + config.AddBsTaskIDRequiredFlag(fCmd.Cmd) } func (fCmd *FlattenCmd) Init(cmd *cobra.Command, args []string) error { diff --git a/tools-v2/pkg/config/bs.go b/tools-v2/pkg/config/bs.go index 2eceb2b9ca..97eb3b8a67 100644 --- a/tools-v2/pkg/config/bs.go +++ b/tools-v2/pkg/config/bs.go @@ -147,11 +147,15 @@ const ( CURVEBS_DEFAULT_SNAPSHOT_ID = "*" CURVEBS_FAILED = "failed" VIPER_CURVEBS_FAILED = "curvebs.failed" - CURVEBS_CHUNK_SIZE = "chunksize" - VIPER_CURVEBS_CHUNK_SIZE = "curvebs.chunksize" - CURVEBS_CHECK_HASH = "checkhash" - VIPER_CURVEBS_CHECK_HASH = "curvebs.checkhash" - CURVEBS_DEFAULT_CHECK_HASH = false + CURVEBS_CHUNK_SIZE = "chunksize" + VIPER_CURVEBS_CHUNK_SIZE = "curvebs.chunksize" + CURVEBS_CHECK_HASH = "checkhash" + VIPER_CURVEBS_CHECK_HASH = "curvebs.checkhash" + CURVEBS_DEFAULT_CHECK_HASH = false + CURVEBS_FILENAME = "filename" + VIPER_CURVEBS_FILENAME = "curvebs.filename" + CURVEBS_SNAPSHOTNAME = "snapshotname" + VIPER_CURVEBS_SNAPSHOTNAME = "curvebs.snapshotname" ) var ( @@ -207,8 +211,10 @@ var ( CURVEBS_TASKID: VIPER_CURVEBS_TASKID, CURVEBS_SNAPSHOT_ID: VIPER_CURVEBS_SNAPSHOT_ID, CURVEBS_FAILED: VIPER_CURVEBS_FAILED, - CURVEBS_CHUNK_SIZE: VIPER_CURVEBS_CHUNK_SIZE, - CURVEBS_CHECK_HASH: VIPER_CURVEBS_CHECK_HASH, + CURVEBS_CHUNK_SIZE: VIPER_CURVEBS_CHUNK_SIZE, + CURVEBS_CHECK_HASH: VIPER_CURVEBS_CHECK_HASH, + CURVEBS_FILENAME: VIPER_CURVEBS_FILENAME, + CURVEBS_SNAPSHOTNAME: VIPER_CURVEBS_SNAPSHOTNAME, } BSFLAG2DEFAULT = map[string]interface{}{ @@ -232,7 +238,7 @@ var ( CURVEBS_ALL: CURVEBS_DEFAULT_ALL, CURVEBS_LOGIC_POOL_ID: CURVEBS_DEFAULT_LOGIC_POOL_ID, CURVEBS_COPYSET_ID: CURVEBS_DEFAULT_COPYSET_ID, - CURVEBS_CHECK_HASH: CURVEBS_DEFAULT_CHECK_HASH, + CURVEBS_CHECK_HASH: CURVEBS_DEFAULT_CHECK_HASH, CURVEBS_SNAPSHOT_ID: CURVEBS_DEFAULT_SNAPSHOT_ID, } ) @@ -663,11 +669,11 @@ func AddBsFailedOptionFlag(cmd *cobra.Command) { AddBsBoolOptionFlag(cmd, CURVEBS_FAILED, "failed") } -func AddBsUserRequireFlag(cmd *cobra.Command) { +func AddBsUserRequiredFlag(cmd *cobra.Command) { AddBsStringRequiredFlag(cmd, CURVEBS_USER, "user name") } -func AddBsTaskIDRequireFlag(cmd *cobra.Command) { +func AddBsTaskIDRequiredFlag(cmd *cobra.Command) { AddBsStringRequiredFlag(cmd, CURVEBS_TASKID, "task id") } @@ -679,6 +685,14 @@ func AddBsTaskTypeOptionFlag(cmd *cobra.Command) { AddBsStringOptionFlag(cmd, CURVEBS_TYPE, "only query target type (clone or recover)") } +func AddBsFileNameRequiredFlag(cmd *cobra.Command) { + AddBsStringRequiredFlag(cmd, CURVEBS_FILENAME, "file name") +} + +func AddBsSnapshotNameRequiredFlag(cmd *cobra.Command) { + AddBsStringRequiredFlag(cmd, CURVEBS_SNAPSHOTNAME, "snapshot name") +} + // get stingslice flag func GetBsFlagStringSlice(cmd *cobra.Command, flagName string) []string { var value []string