From d6d62c0c77c952b3a89dc1fdf871b82123b656cc Mon Sep 17 00:00:00 2001 From: ZackSoul <2269713951@qq.com> Date: Mon, 4 Dec 2023 19:46:21 +0800 Subject: [PATCH] feat(tool):add curve bs query snapshot Signed-off-by: ZackSoul <2269713951@qq.com> --- tools-v2/README.md | 22 +++ tools-v2/internal/utils/snapshot/const.go | 3 + .../command/curvebs/list/snapshot/snapshot.go | 52 ++++-- .../pkg/cli/command/curvebs/query/query.go | 2 + .../curvebs/query/snapshot/snapshot.go | 164 ++++++++++++++++++ tools-v2/pkg/config/bs.go | 65 ++++--- 6 files changed, 266 insertions(+), 42 deletions(-) create mode 100644 tools-v2/pkg/cli/command/curvebs/query/snapshot/snapshot.go diff --git a/tools-v2/README.md b/tools-v2/README.md index f3778138e9..265348087c 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) @@ -1483,6 +1484,27 @@ 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/internal/utils/snapshot/const.go b/tools-v2/internal/utils/snapshot/const.go index 933ec4291f..f370b05027 100644 --- a/tools-v2/internal/utils/snapshot/const.go +++ b/tools-v2/internal/utils/snapshot/const.go @@ -54,4 +54,7 @@ const ( ResultSuccess = "0" Limit = "100" Offset = "0" + + ErrSnaphshot = "5" + DefaultSnapID = "*" ) 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..a73cc26c8d --- /dev/null +++ b/tools-v2/pkg/cli/command/curvebs/query/snapshot/snapshot.go @@ -0,0 +1,164 @@ +/* + * 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-progress" "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 2eceb2b9ca..5f517ff638 100644 --- a/tools-v2/pkg/config/bs.go +++ b/tools-v2/pkg/config/bs.go @@ -147,11 +147,14 @@ 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_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" + VIPER_CURVEBS_CHECK_HASH = "curvebs.checkhash" + CURVEBS_DEFAULT_CHECK_HASH = false ) var ( @@ -207,33 +210,35 @@ 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_SNAPSHOT_STATUS: VIPER_CURVEBS_SNAPSHOT_STATUS, + CURVEBS_CHUNK_SIZE: VIPER_CURVEBS_CHUNK_SIZE, + CURVEBS_CHECK_HASH: VIPER_CURVEBS_CHECK_HASH, } BSFLAG2DEFAULT = map[string]interface{}{ // bs - CURVEBS_USER: CURVEBS_DEFAULT_USER, - CURVEBS_PASSWORD: CURVEBS_DEFAULT_PASSWORD, - CURVEBS_SIZE: CURVEBS_DEFAULT_SIZE, - CURVEBS_STRIPE_UNIT: CURVEBS_DEFAULT_STRIPE_UNIT, - CURVEBS_STRIPE_COUNT: CURVEBS_DEFAULT_STRIPE_COUNT, - CURVEBS_BURST: CURVEBS_DEFAULT_BURST, - CURVEBS_BURST_LENGTH: CURVEBS_DEFAULT_BURST_LENGTH, - CURVEBS_PATH: CURVEBS_DEFAULT_PATH, - CURVEBS_FORCE: CURVEBS_DEFAULT_FORCE, - CURVEBS_MARGIN: CURVEBS_DEFAULT_MARGIN, - CURVEBS_OP: CURVEBS_DEFAULT_OP, - CURVEBS_CHECK_TIME: CURVEBS_DEFAULT_CHECK_TIME, - CURVEBS_SCAN: CURVEBS_DEFAULT_SCAN, - CURVEBS_CHUNKSERVER_ID: CURVEBS_DEFAULT_CHUNKSERVER_ID, - CURVEBS_DRYRUN: CURVEBS_DEFAULT_DRYRUN, - CURVEBS_FIlTER: CURVEBS_DEFAULT_FILTER, - 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_SNAPSHOT_ID: CURVEBS_DEFAULT_SNAPSHOT_ID, + CURVEBS_USER: CURVEBS_DEFAULT_USER, + CURVEBS_PASSWORD: CURVEBS_DEFAULT_PASSWORD, + CURVEBS_SIZE: CURVEBS_DEFAULT_SIZE, + CURVEBS_STRIPE_UNIT: CURVEBS_DEFAULT_STRIPE_UNIT, + CURVEBS_STRIPE_COUNT: CURVEBS_DEFAULT_STRIPE_COUNT, + CURVEBS_BURST: CURVEBS_DEFAULT_BURST, + CURVEBS_BURST_LENGTH: CURVEBS_DEFAULT_BURST_LENGTH, + CURVEBS_PATH: CURVEBS_DEFAULT_PATH, + CURVEBS_FORCE: CURVEBS_DEFAULT_FORCE, + CURVEBS_MARGIN: CURVEBS_DEFAULT_MARGIN, + CURVEBS_OP: CURVEBS_DEFAULT_OP, + CURVEBS_CHECK_TIME: CURVEBS_DEFAULT_CHECK_TIME, + CURVEBS_SCAN: CURVEBS_DEFAULT_SCAN, + CURVEBS_CHUNKSERVER_ID: CURVEBS_DEFAULT_CHUNKSERVER_ID, + CURVEBS_DRYRUN: CURVEBS_DEFAULT_DRYRUN, + CURVEBS_FIlTER: CURVEBS_DEFAULT_FILTER, + 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_SNAPSHOT_ID: CURVEBS_DEFAULT_SNAPSHOT_ID, + CURVEBS_SNAPSHOT_STATUS: CURVEBS_DEFAULT_SNAPSHOT_STATUS, } ) @@ -675,6 +680,10 @@ func AddBsSnapshotIDOptionFlag(cmd *cobra.Command) { AddBsStringOptionFlag(cmd, CURVEBS_SNAPSHOT_ID, "snapshot seqId") } +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)") }