diff --git a/tools-v2/README.md b/tools-v2/README.md index 3325ff61ca..b7a7dea7b4 100644 --- a/tools-v2/README.md +++ b/tools-v2/README.md @@ -65,6 +65,7 @@ A tool for CurveFS & CurveBs. - [query segment](#query-segment) - [query scan-status](#query-scan-status) - [query volume clone-recover](#query-volume-clone-recover) + - [query snapshot](#query-snapshot) - [status](#status-1) - [status etcd](#status-etcd-1) - [status mds](#status-mds-1) @@ -1489,6 +1490,26 @@ Output: +------+--------------------------------------+--------------------------------------+----------+-------+----------+--------+----------+--------+----------+---------------------+ ``` +##### query snapshot + +query snapshot in curvebs + +Usage: + +```shell +curve bs query snapshot --path /test/test111 --snapshotstatus done # other status: "in-progess" "deleting" "errorDeleteing" "canceling" "error" +``` + +Output: + +```shell ++--------------------------------------+--------------+------+--------+----------------+-------------+----------+---------------------+---------------+ +| SNAPSHOTID | SNAPSHOTNAME | USER | STATUS | SNAPSHOTSEQNUM | FILELENGTH | PROGRESS | CREATETIME | FILE | ++--------------------------------------+--------------+------+--------+----------------+-------------+----------+---------------------+---------------+ +| 01a18978-cc3b-4762-a14d-38547511b526 | testsnap1 | root | 0 | 1 | 10737418240 | 100 | 2023-12-04 18:53:55 | /test/test111 | ++--------------------------------------+--------------+------+--------+----------------+-------------+----------+---------------------+---------------+ +``` + #### status ##### status etcd diff --git a/tools-v2/pkg/cli/command/curvebs/list/snapshot/snapshot.go b/tools-v2/pkg/cli/command/curvebs/list/snapshot/snapshot.go index da297d8c20..cb48937c06 100644 --- a/tools-v2/pkg/cli/command/curvebs/list/snapshot/snapshot.go +++ b/tools-v2/pkg/cli/command/curvebs/list/snapshot/snapshot.go @@ -2,11 +2,11 @@ package snapshot import ( "encoding/json" - "fmt" - snapshotutil "github.com/opencurve/curve/tools-v2/internal/utils/snapshot" "strconv" "time" + snapshotutil "github.com/opencurve/curve/tools-v2/internal/utils/snapshot" + 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" @@ -105,18 +105,22 @@ func (sCmd *SnapShotCommand) RunCommand(cmd *cobra.Command, args []string) error return sCmd.Error.ToError() } rows := make([]map[string]string, 0) - for _, item := range snapshotsInfo { - row := make(map[string]string) - row[cobrautil.ROW_SNAPSHOT_ID] = item.UUID - row[cobrautil.ROW_SNAPSHOT_NAME] = item.Name - row[cobrautil.ROW_USER] = item.User - row[cobrautil.ROW_FILE] = item.File - row[cobrautil.ROW_STATUS] = fmt.Sprintf("%d", item.Status) - row[cobrautil.ROW_SNAPSHOT_SEQNUM] = fmt.Sprintf("%d", item.SeqNum) - row[cobrautil.ROW_FILE_LENGTH] = fmt.Sprintf("%d", item.FileLength) - row[cobrautil.ROW_PROGRESS] = fmt.Sprintf("%d", item.Progress) - row[cobrautil.ROW_CREATE_TIME] = time.Unix(int64(item.Time/1000000), 0).Format("2006-01-02 15:04:05") - rows = append(rows, row) + if len(snapshotsInfo) == 0 { + rows = append(rows, EmptyOutput()) + } else { + for _, item := range snapshotsInfo { + row := make(map[string]string) + row[cobrautil.ROW_SNAPSHOT_ID] = item.UUID + row[cobrautil.ROW_SNAPSHOT_NAME] = item.Name + row[cobrautil.ROW_USER] = item.User + row[cobrautil.ROW_FILE] = item.File + row[cobrautil.ROW_STATUS] = strconv.Itoa(item.Status) + row[cobrautil.ROW_SNAPSHOT_SEQNUM] = strconv.Itoa(item.SeqNum) + row[cobrautil.ROW_FILE_LENGTH] = strconv.Itoa(item.FileLength) + row[cobrautil.ROW_PROGRESS] = strconv.FormatFloat(item.Progress, 'f', 2, 64) + row[cobrautil.ROW_CREATE_TIME] = time.Unix(int64(item.Time/1000000), 0).Format("2006-01-02 15:04:05") + rows = append(rows, row) + } } list := cobrautil.ListMap2ListSortByKeys(rows, sCmd.Header, []string{cobrautil.ROW_FILE, cobrautil.ROW_SNAPSHOT_NAME, cobrautil.ROW_SNAPSHOT_ID}) sCmd.TableNew.AppendBulk(list) @@ -161,3 +165,23 @@ func ListSnapShot(addrs []string, timeout time.Duration, params map[string]any) params[snapshotutil.QueryOffset] = strconv.Itoa(offsetValue + limitValue) } } + +func EmptyOutput() map[string]string { + emptyResult := "-" + keys := []string{ + cobrautil.ROW_SNAPSHOT_ID, + cobrautil.ROW_SNAPSHOT_NAME, + cobrautil.ROW_USER, + cobrautil.ROW_FILE, + cobrautil.ROW_STATUS, + cobrautil.ROW_SNAPSHOT_SEQNUM, + cobrautil.ROW_FILE_LENGTH, + cobrautil.ROW_PROGRESS, + cobrautil.ROW_CREATE_TIME, + } + row := make(map[string]string) + for _, key := range keys { + row[key] = emptyResult + } + return row +} diff --git a/tools-v2/pkg/cli/command/curvebs/query/query.go b/tools-v2/pkg/cli/command/curvebs/query/query.go index 04270c5900..721a1b8b85 100644 --- a/tools-v2/pkg/cli/command/curvebs/query/query.go +++ b/tools-v2/pkg/cli/command/curvebs/query/query.go @@ -28,6 +28,7 @@ import ( "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query/file" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query/scanstatus" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query/seginfo" + "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query/snapshot" "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/query/volume" "github.com/spf13/cobra" ) @@ -45,6 +46,7 @@ func (queryCmd *QueryCommand) AddSubCommands() { chunk.NewChunkCommand(), scanstatus.NewScanStatusCommand(), volume.NewVolumeCommand(), + snapshot.NewSnapshotCommand(), ) } diff --git a/tools-v2/pkg/cli/command/curvebs/query/snapshot/snapshot.go b/tools-v2/pkg/cli/command/curvebs/query/snapshot/snapshot.go new file mode 100644 index 0000000000..57a17d8f03 --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/query/snapshot/snapshot.go @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2022 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-12-04 + * Author: ZackSoul + */ +package snapshot + +import ( + "strconv" + "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" + listSnapshot "github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/list/snapshot" + "github.com/opencurve/curve/tools-v2/pkg/config" + "github.com/opencurve/curve/tools-v2/pkg/output" + "github.com/spf13/cobra" +) + +const ( + snapshotExample = `$ curve bs query snapshot --path /test/test111 --snapshotstatus done # other status: "in-progess" "deleting" "errorDeleteing" "canceling" "error"` +) + +type SnapShotCommand struct { + basecmd.FinalCurveCmd + snapshotAddrs []string + timeout time.Duration + + user string + file string + uuid string + status string +} + +var _ basecmd.FinalCurveCmdFunc = (*SnapShotCommand)(nil) + +func NewQuerySnapshotCommand() *SnapShotCommand { + sCmd := &SnapShotCommand{ + FinalCurveCmd: basecmd.FinalCurveCmd{ + Use: "snapshot", + Short: "query snapshot in curve bs", + Example: snapshotExample, + }, + } + + basecmd.NewFinalCurveCli(&sCmd.FinalCurveCmd, sCmd) + return sCmd +} + +func NewSnapshotCommand() *cobra.Command { + return NewQuerySnapshotCommand().Cmd +} + +func (sCmd *SnapShotCommand) AddFlags() { + config.AddBsSnapshotCloneFlagOption(sCmd.Cmd) + config.AddHttpTimeoutFlag(sCmd.Cmd) + config.AddBsUserOptionFlag(sCmd.Cmd) + config.AddBsSnapshotIDOptionFlag(sCmd.Cmd) + config.AddBsPathOptionFlag(sCmd.Cmd) + config.AddSnapshotStatusOptionalFlag(sCmd.Cmd) +} + +func (sCmd *SnapShotCommand) Init(cmd *cobra.Command, args []string) error { + snapshotAddrs, err := config.GetBsSnapshotAddrSlice(sCmd.Cmd) + if err.TypeCode() != cmderror.CODE_SUCCESS { + sCmd.Error = err + return err.ToError() + } + sCmd.snapshotAddrs = snapshotAddrs + sCmd.timeout = config.GetFlagDuration(sCmd.Cmd, config.HTTPTIMEOUT) + sCmd.user = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_USER) + sCmd.file = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_PATH) + sCmd.uuid = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_SNAPSHOT_ID) + sCmd.status = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_SNAPSHOT_STATUS) + header := []string{ + cobrautil.ROW_SNAPSHOT_ID, + cobrautil.ROW_SNAPSHOT_NAME, + cobrautil.ROW_USER, + cobrautil.ROW_STATUS, + cobrautil.ROW_SNAPSHOT_SEQNUM, + cobrautil.ROW_FILE_LENGTH, + cobrautil.ROW_PROGRESS, + cobrautil.ROW_CREATE_TIME, + cobrautil.ROW_FILE, + } + sCmd.SetHeader(header) + sCmd.TableNew.SetAutoMergeCellsByColumnIndex(cobrautil.GetIndexSlice( + sCmd.Header, []string{cobrautil.ROW_FILE}, + )) + return nil +} + +func (sCmd *SnapShotCommand) Print(cmd *cobra.Command, args []string) error { + return output.FinalCmdOutput(&sCmd.FinalCurveCmd, sCmd) +} + +func (sCmd *SnapShotCommand) RunCommand(cmd *cobra.Command, args []string) error { + params := map[string]any{ + snapshotutil.QueryAction: snapshotutil.ActionGetFileSnapshotList, + snapshotutil.QueryVersion: snapshotutil.Version, + snapshotutil.QueryUser: sCmd.user, + snapshotutil.QueryFile: sCmd.file, + snapshotutil.QueryLimit: snapshotutil.Limit, + snapshotutil.QueryOffset: snapshotutil.Offset, + } + if sCmd.uuid != snapshotutil.DefaultSnapID { + params[snapshotutil.QueryUUID] = sCmd.uuid + } + for i, status := range snapshotutil.SnapshotStatus { + if status == sCmd.status { + params[snapshotutil.QueryStatus] = i + } + } + snapshotsInfo, err := listSnapshot.ListSnapShot(sCmd.snapshotAddrs, sCmd.timeout, params) + if err != nil { + sCmd.Error = err + return sCmd.Error.ToError() + } + rows := make([]map[string]string, 0) + if len(snapshotsInfo) == 0 { + rows = append(rows, listSnapshot.EmptyOutput()) + } + for _, item := range snapshotsInfo { + row := make(map[string]string) + row[cobrautil.ROW_SNAPSHOT_ID] = item.UUID + row[cobrautil.ROW_SNAPSHOT_NAME] = item.Name + row[cobrautil.ROW_USER] = item.User + row[cobrautil.ROW_FILE] = item.File + row[cobrautil.ROW_STATUS] = strconv.Itoa(item.Status) + row[cobrautil.ROW_SNAPSHOT_SEQNUM] = strconv.Itoa(item.SeqNum) + row[cobrautil.ROW_FILE_LENGTH] = strconv.Itoa(item.FileLength) + row[cobrautil.ROW_PROGRESS] = strconv.FormatFloat(item.Progress, 'f', 2, 64) + row[cobrautil.ROW_CREATE_TIME] = time.Unix(int64(item.Time/1000000), 0).Format("2006-01-02 15:04:05") + rows = append(rows, row) + } + list := cobrautil.ListMap2ListSortByKeys(rows, sCmd.Header, []string{cobrautil.ROW_SNAPSHOT_NAME, cobrautil.ROW_SNAPSHOT_ID}) + sCmd.TableNew.AppendBulk(list) + sCmd.Result = rows + sCmd.Error = cmderror.Success() + return nil +} + +func (sCmd *SnapShotCommand) ResultPlainOutput() error { + return output.FinalCmdOutputPlain(&sCmd.FinalCurveCmd) +} diff --git a/tools-v2/pkg/config/bs.go b/tools-v2/pkg/config/bs.go index 24980c88dc..bac62403e0 100644 --- a/tools-v2/pkg/config/bs.go +++ b/tools-v2/pkg/config/bs.go @@ -150,6 +150,9 @@ const ( CURVEBS_DEFAULT_SNAPSHOT_FAILED = false CURVEBS_FAILED = "failed" VIPER_CURVEBS_FAILED = "curvebs.failed" + CURVEBS_SNAPSHOT_STATUS = "snapshotstatus" + VIPER_CURVEBS_SNAPSHOT_STATUS = "curvebs.snapshotstatus" + CURVEBS_DEFAULT_SNAPSHOT_STATUS = "done" CURVEBS_CHUNK_SIZE = "chunksize" VIPER_CURVEBS_CHUNK_SIZE = "curvebs.chunksize" CURVEBS_CHECK_HASH = "checkhash" @@ -221,6 +224,7 @@ var ( CURVEBS_FILENAME: VIPER_CURVEBS_FILENAME, CURVEBS_SNAPSHOTNAME: VIPER_CURVEBS_SNAPSHOTNAME, CURVEBS_SNAPSHOT_FAILED: VIPER_CURVEBS_SNAPSHOT_FAILED, + CURVEBS_SNAPSHOT_STATUS: VIPER_CURVEBS_SNAPSHOT_STATUS, } BSFLAG2DEFAULT = map[string]interface{}{ @@ -247,6 +251,7 @@ var ( CURVEBS_CHECK_HASH: CURVEBS_DEFAULT_CHECK_HASH, CURVEBS_SNAPSHOT_ID: CURVEBS_DEFAULT_SNAPSHOT_ID, CURVEBS_SNAPSHOT_FAILED: CURVEBS_DEFAULT_SNAPSHOT_FAILED, + CURVEBS_SNAPSHOT_STATUS: CURVEBS_DEFAULT_SNAPSHOT_STATUS, } ) @@ -696,6 +701,10 @@ func AddBsSnapshotFailedOptionFlag(cmd *cobra.Command) { AddBsBoolOptionFlag(cmd, CURVEBS_SNAPSHOT_FAILED, "snapshot failed(error)") } +func AddSnapshotStatusOptionalFlag(cmd *cobra.Command) { + AddBsStringOptionFlag(cmd, CURVEBS_SNAPSHOT_STATUS, "snapshot status") +} + func AddBsTaskTypeOptionFlag(cmd *cobra.Command) { AddBsStringOptionFlag(cmd, CURVEBS_TYPE, "only query target type (clone or recover)") }