Skip to content

Commit

Permalink
[feat] tools-v2: add snapshot-clone-status
Browse files Browse the repository at this point in the history
Signed-off-by: Xinlong-Chen <[email protected]>
  • Loading branch information
Xinlong-Chen committed Apr 27, 2023
1 parent 61c07b3 commit 59b61c3
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 81 deletions.
6 changes: 3 additions & 3 deletions tools-v2/docs/zh/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ docker cp ./sbin/curve de7603f17cf9:/
4. 准备配置文件,将之拷贝进 playground 容器内:
```shell
docker cp ./pkg/config/template.yaml de7603f17cf9:/etc/curve/curve.yaml
docker cp ./pkg/config/curve.yaml de7603f17cf9:/etc/curve/curve.yaml
```
5. 进入对应的容器:
Expand Down Expand Up @@ -558,10 +558,10 @@ curveadm status
make
```
3. 准备配置文件,将项目目录下的 `tools-v2/pkg/config/template.yaml` 复制到 `$(HOME)/.curve/curve.yaml`
3. 准备配置文件,将项目目录下的 `tools-v2/pkg/config/curve.yaml` 复制到 `$(HOME)/.curve/curve.yaml`
```shell
cp ./pkg/config/template.yaml ~/.curve/curve.yaml
cp ./pkg/config/curve.yaml ~/.curve/curve.yaml
```
4. 在项目目录(`curve/tools-v2`) 下执行命令/调试:
Expand Down
15 changes: 10 additions & 5 deletions tools-v2/pkg/cli/command/curvebs/status/etcd/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ func NewEtcdCommand() *cobra.Command {
}

func (eCmd *EtcdCommand) AddFlags() {
config.AddBsEtcdAddrFlag(eCmd.Cmd)
config.AddHttpTimeoutFlag(eCmd.Cmd)
config.AddBsEtcdAddrFlag(eCmd.Cmd)
}

func (eCmd *EtcdCommand) Init(cmd *cobra.Command, args []string) error {
eCmd.health = cobrautil.HEALTH_ERROR

header := []string{cobrautil.ROW_ADDR, cobrautil.ROW_VERSION, cobrautil.ROW_STATUS}
eCmd.SetHeader(header)
eCmd.TableNew.SetAutoMergeCellsByColumnIndex(cobrautil.GetIndexSlice(
Expand All @@ -85,6 +86,7 @@ func (eCmd *EtcdCommand) Init(cmd *cobra.Command, args []string) error {
if addrErr.TypeCode() != cmderror.CODE_SUCCESS {
return fmt.Errorf(addrErr.Message)
}

for _, addr := range etcdAddrs {
// set metric
timeout := viper.GetDuration(config.VIPER_GLOBALE_HTTPTIMEOUT)
Expand Down Expand Up @@ -117,6 +119,7 @@ func (eCmd *EtcdCommand) RunCommand(cmd *cobra.Command, args []string) error {
size++
go func(m *basecmd.Metric) {
result, err := basecmd.QueryMetric(m)

var key string
var metricKey string
if m.SubUri == STATUS_SUBURI {
Expand All @@ -126,13 +129,15 @@ func (eCmd *EtcdCommand) RunCommand(cmd *cobra.Command, args []string) error {
key = "version"
metricKey = VARSION_METRIC_KEY
}

var value string
if err.TypeCode() == cmderror.CODE_SUCCESS {
value, err = basecmd.GetKeyValueFromJsonMetric(result, metricKey)
if err.TypeCode() != cmderror.CODE_SUCCESS {
errs = append(errs, err)
}
}

results <- basecmd.MetricResult{
Addr: m.Addrs[0],
Key: key,
Expand Down Expand Up @@ -166,21 +171,21 @@ func (eCmd *EtcdCommand) RunCommand(cmd *cobra.Command, args []string) error {
break
}
}
mergeErr := cmderror.MergeCmdErrorExceptSuccess(errs)
eCmd.Error = mergeErr

if len(errs) > 0 && len(errs) < len(eCmd.rows) {
eCmd.health = cobrautil.HEALTH_WARN
} else if len(errs) == 0 {
eCmd.health = cobrautil.HEALTH_OK
}

mergeErr := cmderror.MergeCmdErrorExceptSuccess(errs)
eCmd.Error = mergeErr
list := cobrautil.ListMap2ListSortByKeys(eCmd.rows, eCmd.Header, []string{
cobrautil.ROW_STATUS, cobrautil.ROW_VERSION,
})
eCmd.TableNew.AppendBulk(list)

eCmd.Result = eCmd.rows

return nil
}

Expand All @@ -206,7 +211,7 @@ func GetEtcdStatus(caller *cobra.Command) (*interface{}, *tablewriter.Table, *cm
fmt.Sprintf("--%s", config.FORMAT), config.FORMAT_NOOUT,
})
config.AlignFlagsValue(caller, etcdCmd.Cmd, []string{
config.RPCRETRYTIMES, config.RPCTIMEOUT, config.CURVEFS_MDSADDR,
config.RPCRETRYTIMES, config.RPCTIMEOUT, config.CURVEFS_ETCDADDR,
})
etcdCmd.Cmd.SilenceErrors = true
etcdCmd.Cmd.Execute()
Expand Down
10 changes: 9 additions & 1 deletion tools-v2/pkg/cli/command/curvebs/status/mds/mds.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ func NewMdsCommand() *cobra.Command {
}

func (mCmd *MdsCommand) AddFlags() {
config.AddBsMdsFlagOption(mCmd.Cmd)
config.AddHttpTimeoutFlag(mCmd.Cmd)
config.AddBsMdsFlagOption(mCmd.Cmd)
config.AddBsMdsDummyFlagOption(mCmd.Cmd)
}

Expand All @@ -84,6 +84,7 @@ func (mCmd *MdsCommand) Init(cmd *cobra.Command, args []string) error {
if addrErr.TypeCode() != cmderror.CODE_SUCCESS {
return fmt.Errorf(addrErr.Message)
}

for _, addr := range dummyAddrs {
// Use the dummy port to access the metric service
timeout := viper.GetDuration(config.VIPER_GLOBALE_HTTPTIMEOUT)
Expand Down Expand Up @@ -118,16 +119,20 @@ func (mCmd *MdsCommand) RunCommand(cmd *cobra.Command, args []string) error {
size++
go func(m *basecmd.Metric) {
result, err := basecmd.QueryMetric(m)

var key string

if m.SubUri == STATUS_SUBURI {
key = "status"
} else {
key = "version"
}

var value string
if err.TypeCode() == cmderror.CODE_SUCCESS {
value, err = basecmd.GetMetricValue(result)
}

results <- basecmd.MetricResult{
Addr: m.Addrs[0],
Key: key,
Expand Down Expand Up @@ -157,18 +162,21 @@ func (mCmd *MdsCommand) RunCommand(cmd *cobra.Command, args []string) error {
break
}
}

if len(errs) > 0 && len(errs) < len(mCmd.rows) {
mCmd.health = cobrautil.HEALTH_WARN
} else if len(errs) == 0 {
mCmd.health = cobrautil.HEALTH_OK
}

mergeErr := cmderror.MergeCmdErrorExceptSuccess(errs)
mCmd.Error = mergeErr
list := cobrautil.ListMap2ListSortByKeys(mCmd.rows, mCmd.Header, []string{
cobrautil.ROW_STATUS, cobrautil.ROW_VERSION,
})
mCmd.TableNew.AppendBulk(list)
mCmd.Result = mCmd.rows

return nil
}

Expand Down
220 changes: 220 additions & 0 deletions tools-v2/pkg/cli/command/curvebs/status/snapshot/snapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* 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-04-25
* Author: Xinlong-Chen
*/

package snapshot

import (
"fmt"

"github.com/olekukonko/tablewriter"
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"
config "github.com/opencurve/curve/tools-v2/pkg/config"
"github.com/opencurve/curve/tools-v2/pkg/output"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/exp/slices"
)

const (
snapshotExample = `$ curve bs status snapshot`
)

type SnapshotCommand struct {
basecmd.FinalCurveCmd
metrics []*basecmd.Metric
rows []map[string]string
health cobrautil.ClUSTER_HEALTH_STATUS
}

const (
STATUS_SUBURI = "/vars/snapshotcloneserver_status"
VERSION_SUBURI = "/vars/curve_version"
)

var (
SnapshotCloneStatusMap = map[string]string{
"active": "leader",
"standby": "follower",
}
)

var _ basecmd.FinalCurveCmdFunc = (*SnapshotCommand)(nil) // check interface

func NewSnapshotCommand() *cobra.Command {
return NewStatusSnapshotCommand().Cmd
}

func (sCmd *SnapshotCommand) AddFlags() {
config.AddHttpTimeoutFlag(sCmd.Cmd)
config.AddBsSnapshotCloneFlagOption(sCmd.Cmd)
config.AddBsSnapshotCloneDummyFlagOption(sCmd.Cmd)
}

func (sCmd *SnapshotCommand) Init(cmd *cobra.Command, args []string) error {
sCmd.health = cobrautil.HEALTH_ERROR

header := []string{cobrautil.ROW_ADDR, cobrautil.ROW_DUMMY_ADDR, cobrautil.ROW_VERSION, cobrautil.ROW_STATUS}
sCmd.SetHeader(header)
sCmd.TableNew.SetAutoMergeCellsByColumnIndex(cobrautil.GetIndexSlice(
sCmd.Header, []string{cobrautil.ROW_STATUS, cobrautil.ROW_VERSION},
))

// set main addr
mainAddrs, addrErr := config.GetBsSnapshotAddrSlice(sCmd.Cmd)
if addrErr.TypeCode() != cmderror.CODE_SUCCESS {
return fmt.Errorf(addrErr.Message)
}

// set dummy addr
dummyAddrs, addrErr := config.GetBsSnapshotDummyAddrSlice(sCmd.Cmd)
if addrErr.TypeCode() != cmderror.CODE_SUCCESS {
return fmt.Errorf(addrErr.Message)
}

for _, addr := range dummyAddrs {
// Use the dummy port to access the metric service
timeout := viper.GetDuration(config.VIPER_GLOBALE_HTTPTIMEOUT)

addrs := []string{addr}
statusMetric := basecmd.NewMetric(addrs, STATUS_SUBURI, timeout)
sCmd.metrics = append(sCmd.metrics, statusMetric)
versionMetric := basecmd.NewMetric(addrs, VERSION_SUBURI, timeout)
sCmd.metrics = append(sCmd.metrics, versionMetric)
}

for i := range mainAddrs {
row := make(map[string]string)
row[cobrautil.ROW_ADDR] = mainAddrs[i]
row[cobrautil.ROW_DUMMY_ADDR] = dummyAddrs[i]
row[cobrautil.ROW_STATUS] = cobrautil.ROW_VALUE_OFFLINE
row[cobrautil.ROW_VERSION] = cobrautil.ROW_VALUE_UNKNOWN
sCmd.rows = append(sCmd.rows, row)
}

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 {
results := make(chan basecmd.MetricResult, config.MaxChannelSize())
size := 0
for _, metric := range sCmd.metrics {
size++
go func(m *basecmd.Metric) {
result, err := basecmd.QueryMetric(m)

var key string
if m.SubUri == STATUS_SUBURI {
key = "status"
} else {
key = "version"
}

var value string
if err.TypeCode() == cmderror.CODE_SUCCESS {
value, err = basecmd.GetMetricValue(result)
}

results <- basecmd.MetricResult{
Addr: m.Addrs[0],
Key: key,
Value: value,
Err: err,
}
}(metric)
}

count := 0
var errs []*cmderror.CmdError
var recordAddrs []string
for res := range results {
for _, row := range sCmd.rows {
if res.Err.TypeCode() == cmderror.CODE_SUCCESS && row[cobrautil.ROW_DUMMY_ADDR] == res.Addr {
if res.Key == "status" {
row[res.Key] = SnapshotCloneStatusMap[res.Value]
} else {
row[res.Key] = res.Value
}
} else if res.Err.TypeCode() != cmderror.CODE_SUCCESS {
index := slices.Index(recordAddrs, res.Addr)
if index == -1 {
errs = append(errs, res.Err)
recordAddrs = append(recordAddrs, res.Addr)
}
}
}
count++
if count >= size {
break
}
}

if len(errs) > 0 && len(errs) < len(sCmd.rows) {
sCmd.health = cobrautil.HEALTH_WARN
} else if len(errs) == 0 {
sCmd.health = cobrautil.HEALTH_OK
}

mergeErr := cmderror.MergeCmdErrorExceptSuccess(errs)
sCmd.Error = mergeErr
list := cobrautil.ListMap2ListSortByKeys(sCmd.rows, sCmd.Header, []string{
cobrautil.ROW_STATUS, cobrautil.ROW_VERSION,
})
sCmd.TableNew.AppendBulk(list)
sCmd.Result = sCmd.rows

return nil
}

func (sCmd *SnapshotCommand) ResultPlainOutput() error {
return output.FinalCmdOutputPlain(&sCmd.FinalCurveCmd)
}

func NewStatusSnapshotCommand() *SnapshotCommand {
snapshotCmd := &SnapshotCommand{
FinalCurveCmd: basecmd.FinalCurveCmd{
Use: "snapshot",
Short: "get the snapshot clone status of curvebs",
Example: snapshotExample,
},
}
basecmd.NewFinalCurveCli(&snapshotCmd.FinalCurveCmd, snapshotCmd)
return snapshotCmd
}

func GetSnapshotStatus(caller *cobra.Command) (*interface{}, *tablewriter.Table, *cmderror.CmdError, cobrautil.ClUSTER_HEALTH_STATUS) {
snapshotCmd := NewStatusSnapshotCommand()
snapshotCmd.Cmd.SetArgs([]string{
fmt.Sprintf("--%s", config.FORMAT), config.FORMAT_NOOUT,
})
config.AlignFlagsValue(caller, snapshotCmd.Cmd, []string{
config.RPCRETRYTIMES, config.RPCTIMEOUT, config.CURVEBS_SNAPSHOTADDR,
})
snapshotCmd.Cmd.SilenceErrors = true
snapshotCmd.Cmd.Execute()
return &snapshotCmd.Result, snapshotCmd.TableNew, snapshotCmd.Error, snapshotCmd.health
}
Loading

0 comments on commit 59b61c3

Please sign in to comment.