Skip to content

Commit e5fa7e4

Browse files
committed
[feat] tools-v2: add bs status volume snapshot command
Signed-off-by: saicaca <zephyird@gmail.com>
1 parent d19e7e9 commit e5fa7e4

File tree

8 files changed

+308
-9
lines changed

8 files changed

+308
-9
lines changed

tools-v2/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,38 @@ Output:
15611561
+------------+-----------+--------+--------+--------+---------+
15621562
```
15631563

1564+
##### status volume
1565+
1566+
###### status volume snapshot
1567+
1568+
get the snapshot status
1569+
1570+
Usage:
1571+
1572+
```bash
1573+
curve bs status volume snapshot --filename test --snapshotaddr 127.0.0.1:5550,127.0.0.1:5551,127.0.0.1:5552
1574+
```
1575+
1576+
Output:
1577+
1578+
```bash
1579+
+---------------+-------+
1580+
| STATUS | COUNT |
1581+
+---------------+-------+
1582+
| done | 10 |
1583+
+---------------+-------+
1584+
| in-progress | 4 |
1585+
+---------------+-------+
1586+
| deleting | 2 |
1587+
+---------------+-------+
1588+
| errorDeleting | 0 |
1589+
+---------------+-------+
1590+
| canceling | 0 |
1591+
+---------------+-------+
1592+
| error | 0 |
1593+
+---------------+-------+
1594+
```
1595+
15641596
#### delete
15651597

15661598
##### delete peer

tools-v2/internal/error/error.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,9 @@ var (
493493
ErrBsGetChunkHash = func() *CmdError {
494494
return NewInternalCmdError(77, "get chunk hash fail, err: %s")
495495
}
496+
ErrBsGetSnapshotStatus = func() *CmdError {
497+
return NewInternalCmdError(76, "get snapshot status fail, err: %s")
498+
}
496499

497500
// http error
498501
ErrHttpUnreadableResult = func() *CmdError {

tools-v2/internal/utils/row.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
ROW_COPYSET = "copyset"
3838
ROW_COPYSET_ID = "copysetId"
3939
ROW_COPYSET_KEY = "copysetKey"
40+
ROW_COUNT = "count"
4041
ROW_CREATE_TIME = "createTime"
4142
ROW_CREATED = "created"
4243
ROW_CTIME = "ctime"

tools-v2/internal/utils/snapshot.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
QueryOffset = "Offset"
4343
QueryStatus = "Status"
4444
QueryType = "Type"
45+
QueryFile = "File"
4546

4647
ActionClone = "Clone"
4748
ActionRecover = "Recover"
@@ -64,7 +65,7 @@ func NewSnapshotQuerySubUri(params map[string]any) string {
6465
values.Add(QueryVersion, Version)
6566
for key, value := range params {
6667
if value != "" {
67-
values.Add(key, fmt.Sprintf("%s", value))
68+
values.Add(key, fmt.Sprintf("%v", value))
6869
}
6970
}
7071

tools-v2/pkg/cli/command/curvebs/status/status.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/etcd"
3232
"github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/mds"
3333
"github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/snapshot"
34+
"github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/volume"
3435
"github.com/spf13/cobra"
3536
)
3637

@@ -49,6 +50,7 @@ func (statusCmd *StatusCommand) AddSubCommands() {
4950
chunkserver.NewChunkServerCommand(),
5051
copyset.NewCopysetCommand(),
5152
cluster.NewClusterCommand(),
53+
volume.NewVolumeCommand(),
5254
)
5355
}
5456

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* Copyright (c) 2023 NetEase Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*
18+
* Project: CurveCli
19+
* Created Date: 2023-09-13
20+
* Author: saicaca
21+
*/
22+
23+
package snapshot
24+
25+
import (
26+
"encoding/json"
27+
"fmt"
28+
cmderror "github.com/opencurve/curve/tools-v2/internal/error"
29+
cobrautil "github.com/opencurve/curve/tools-v2/internal/utils"
30+
basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command"
31+
"github.com/opencurve/curve/tools-v2/pkg/config"
32+
"github.com/opencurve/curve/tools-v2/pkg/output"
33+
"github.com/spf13/cobra"
34+
"strconv"
35+
"time"
36+
)
37+
38+
type QueryResponse struct {
39+
Code string `json:"Code"`
40+
Message string `json:"Message"`
41+
RequestId string `json:"RequestId"`
42+
TotalCount int `json:"TotalCount"`
43+
Snapshots []*SnapshotInfoData `json:"Snapshots,omitempty"`
44+
}
45+
46+
type SnapshotInfoData struct {
47+
UUID string `json:"UUID"`
48+
User string `json:"User"`
49+
FileName string `json:"FileName"`
50+
SnapshotName string `json:"SnapshotName"`
51+
SeqNum uint64 `json:"SeqNum"`
52+
ChunkSize uint32 `json:"ChunkSize"`
53+
SegmentSize uint64 `json:"SegmentSize"`
54+
FileLength uint64 `json:"FileLength"`
55+
Time uint64 `json:"Time"`
56+
Status int32 `json:"Status"`
57+
StripeUnit *uint64 `json:"StripeUnit,omitempty"`
58+
StripeCount *uint64 `json:"StripeCount,omitempty"`
59+
Poolset *string `json:"Poolset,omitempty"`
60+
}
61+
62+
const (
63+
SNAPSHOT_QUERY_LIMIT = 100
64+
SNAPSHOT_QUERY_INITIAL_OFFSET = 0
65+
SNAPSHOT_QUERY_CODE_SUCCESS = "0"
66+
LENGTH_EMPTY = 0
67+
)
68+
69+
const (
70+
STATUS_DONE = iota
71+
STATUS_IN_PROGRESS
72+
STATUS_DELETING
73+
STATUS_ERROR_DELETING
74+
STATUS_CANCELING
75+
STATUS_ERROR
76+
)
77+
78+
var statusList = []int{
79+
STATUS_DONE,
80+
STATUS_IN_PROGRESS,
81+
STATUS_DELETING,
82+
STATUS_ERROR_DELETING,
83+
STATUS_CANCELING,
84+
STATUS_ERROR,
85+
}
86+
87+
var statusName = map[int]string{
88+
STATUS_DONE: "done",
89+
STATUS_IN_PROGRESS: "in-progress",
90+
STATUS_DELETING: "deleting",
91+
STATUS_ERROR_DELETING: "errorDeleting",
92+
STATUS_CANCELING: "canceling",
93+
STATUS_ERROR: "error",
94+
}
95+
96+
type SnapshotCommand struct {
97+
basecmd.FinalCurveCmd
98+
99+
snapshotAddrs []string
100+
timeout time.Duration
101+
user string
102+
filename string
103+
104+
errCode int
105+
health cobrautil.ClUSTER_HEALTH_STATUS
106+
}
107+
108+
var _ basecmd.FinalCurveCmdFunc = (*SnapshotCommand)(nil) // check interface
109+
110+
func NewSnapshotCommand() *cobra.Command {
111+
return NewVolumeSnapshotCommand().Cmd
112+
}
113+
114+
func NewVolumeSnapshotCommand() *SnapshotCommand {
115+
vsCmd := &SnapshotCommand{
116+
FinalCurveCmd: basecmd.FinalCurveCmd{
117+
Use: "snapshot",
118+
Short: "show the snapshot status",
119+
},
120+
}
121+
basecmd.NewFinalCurveCli(&vsCmd.FinalCurveCmd, vsCmd)
122+
return vsCmd
123+
}
124+
125+
func (sCmd *SnapshotCommand) Init(cmd *cobra.Command, args []string) error {
126+
snapshotAddrs, err := config.GetBsSnapshotAddrSlice(sCmd.Cmd)
127+
if err.TypeCode() != cmderror.CODE_SUCCESS || len(snapshotAddrs) == 0 {
128+
return err.ToError()
129+
}
130+
sCmd.snapshotAddrs = snapshotAddrs
131+
sCmd.filename = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_FILENAME)
132+
sCmd.user = config.GetBsFlagString(sCmd.Cmd, config.CURVEBS_USER)
133+
sCmd.timeout = config.GetFlagDuration(sCmd.Cmd, config.HTTPTIMEOUT)
134+
135+
header := []string{cobrautil.ROW_STATUS, cobrautil.ROW_COUNT}
136+
sCmd.SetHeader(header)
137+
138+
return nil
139+
}
140+
141+
func (sCmd *SnapshotCommand) RunCommand(cmd *cobra.Command, args []string) error {
142+
params := map[string]any{
143+
cobrautil.QueryAction: cobrautil.ActionGetFileSnapshotList,
144+
cobrautil.QueryUser: sCmd.user,
145+
cobrautil.QueryFile: sCmd.filename,
146+
cobrautil.QueryLimit: SNAPSHOT_QUERY_LIMIT,
147+
cobrautil.QueryOffset: SNAPSHOT_QUERY_INITIAL_OFFSET,
148+
}
149+
count := make(map[int]int)
150+
for {
151+
subUri := cobrautil.NewSnapshotQuerySubUri(params)
152+
153+
metric := basecmd.NewMetric(sCmd.snapshotAddrs, subUri, sCmd.timeout)
154+
result, err := basecmd.QueryMetric(metric)
155+
if err.TypeCode() != cmderror.CODE_SUCCESS {
156+
return err.ToError()
157+
}
158+
159+
var resp QueryResponse
160+
if err := json.Unmarshal([]byte(result), &resp); err != nil {
161+
return err
162+
}
163+
if resp.Code != SNAPSHOT_QUERY_CODE_SUCCESS {
164+
return fmt.Errorf("get clone list fail, error code: %s", resp.Code)
165+
}
166+
if len(resp.Snapshots) == LENGTH_EMPTY {
167+
break
168+
}
169+
for _, s := range resp.Snapshots {
170+
count[int(s.Status)] += 1
171+
}
172+
173+
params[cobrautil.QueryOffset] = params[cobrautil.QueryOffset].(int) + params[cobrautil.QueryLimit].(int)
174+
}
175+
176+
rows := make([]map[string]string, 0)
177+
for _, s := range statusList {
178+
rows = append(rows, map[string]string{
179+
cobrautil.ROW_STATUS: statusName[s],
180+
cobrautil.ROW_COUNT: strconv.Itoa(count[s]),
181+
})
182+
}
183+
list := cobrautil.ListMap2ListSortByKeys(rows, sCmd.Header, []string{})
184+
sCmd.TableNew.AppendBulk(list)
185+
sCmd.Result = rows
186+
sCmd.Error = cmderror.ErrSuccess()
187+
188+
return nil
189+
}
190+
191+
func (sCmd *SnapshotCommand) Print(cmd *cobra.Command, args []string) error {
192+
return output.FinalCmdOutput(&sCmd.FinalCurveCmd, sCmd)
193+
}
194+
195+
func (sCmd *SnapshotCommand) ResultPlainOutput() error {
196+
return output.FinalCmdOutputPlain(&sCmd.FinalCurveCmd)
197+
}
198+
199+
func (sCmd *SnapshotCommand) AddFlags() {
200+
config.AddBsUserOptionFlag(sCmd.Cmd)
201+
config.AddBsSnapshotFilenameFlag(sCmd.Cmd)
202+
config.AddBsSnapshotCloneFlagOption(sCmd.Cmd)
203+
config.AddHttpTimeoutFlag(sCmd.Cmd)
204+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2023 NetEase Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*
18+
* Project: CurveCli
19+
* Created Date: 2023-09-13
20+
* Author: saicaca
21+
*/
22+
23+
package volume
24+
25+
import (
26+
basecmd "github.com/opencurve/curve/tools-v2/pkg/cli/command"
27+
"github.com/opencurve/curve/tools-v2/pkg/cli/command/curvebs/status/volume/snapshot"
28+
"github.com/spf13/cobra"
29+
)
30+
31+
type VolumeCommand struct {
32+
basecmd.MidCurveCmd
33+
}
34+
35+
var _ basecmd.MidCurveCmdFunc = (*VolumeCommand)(nil) // check interface
36+
37+
func (volumeCmd *VolumeCommand) AddSubCommands() {
38+
volumeCmd.Cmd.AddCommand(
39+
snapshot.NewSnapshotCommand(),
40+
)
41+
}
42+
43+
func NewVolumeCommand() *cobra.Command {
44+
volumeCmd := &VolumeCommand{
45+
basecmd.MidCurveCmd{
46+
Use: "volume",
47+
Short: "get the status of curvebs volume",
48+
},
49+
}
50+
return basecmd.NewMidCurveCli(&volumeCmd.MidCurveCmd, volumeCmd)
51+
}

tools-v2/pkg/config/bs.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,12 @@ const (
144144
VIPER_CURVEBS_TASKID = "curvebs.taskid"
145145
CURVEBS_FAILED = "failed"
146146
VIPER_CURVEBS_FAILED = "curvebs.failed"
147-
CURVEBS_CHUNK_SIZE = "chunksize"
148-
VIPER_CURVEBS_CHUNK_SIZE = "curvebs.chunksize"
149-
CURVEBS_CHECK_HASH = "checkhash"
150-
VIPER_CURVEBS_CHECK_HASH = "curvebs.checkhash"
151-
CURVEBS_DEFAULT_CHECK_HASH = false
147+
CURVEBS_CHUNK_SIZE = "chunksize"
148+
VIPER_CURVEBS_CHUNK_SIZE = "curvebs.chunksize"
149+
CURVEBS_CHECK_HASH = "checkhash"
150+
VIPER_CURVEBS_CHECK_HASH = "curvebs.checkhash"
151+
CURVEBS_DEFAULT_CHECK_HASH = false
152+
CURVEBS_FILENAME = "filename"
152153
)
153154

154155
var (
@@ -203,8 +204,8 @@ var (
203204
CURVEBS_DEST: VIPER_CURVEBS_DEST,
204205
CURVEBS_TASKID: VIPER_CURVEBS_TASKID,
205206
CURVEBS_FAILED: VIPER_CURVEBS_FAILED,
206-
CURVEBS_CHUNK_SIZE: VIPER_CURVEBS_CHUNK_SIZE,
207-
CURVEBS_CHECK_HASH: VIPER_CURVEBS_CHECK_HASH,
207+
CURVEBS_CHUNK_SIZE: VIPER_CURVEBS_CHUNK_SIZE,
208+
CURVEBS_CHECK_HASH: VIPER_CURVEBS_CHECK_HASH,
208209
}
209210

210211
BSFLAG2DEFAULT = map[string]interface{}{
@@ -228,7 +229,7 @@ var (
228229
CURVEBS_ALL: CURVEBS_DEFAULT_ALL,
229230
CURVEBS_LOGIC_POOL_ID: CURVEBS_DEFAULT_LOGIC_POOL_ID,
230231
CURVEBS_COPYSET_ID: CURVEBS_DEFAULT_COPYSET_ID,
231-
CURVEBS_CHECK_HASH: CURVEBS_DEFAULT_CHECK_HASH,
232+
CURVEBS_CHECK_HASH: CURVEBS_DEFAULT_CHECK_HASH,
232233
}
233234
)
234235

@@ -658,6 +659,10 @@ func AddBsFailedOptionFlag(cmd *cobra.Command) {
658659
AddBsBoolOptionFlag(cmd, CURVEBS_FAILED, "failed")
659660
}
660661

662+
func AddBsSnapshotFilenameFlag(cmd *cobra.Command) {
663+
AddBsStringOptionFlag(cmd, CURVEBS_FILENAME, "snapshot filename")
664+
}
665+
661666
func AddBsUserRequireFlag(cmd *cobra.Command) {
662667
AddBsStringRequiredFlag(cmd, CURVEBS_USER, "user name")
663668
}

0 commit comments

Comments
 (0)