mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 18:15:51 +00:00
249 lines
6.4 KiB
Go
249 lines
6.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/cubefs/cubefs/proto"
|
|
"github.com/cubefs/cubefs/sdk/master"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
const (
|
|
cmdDiskUse = "disk [COMMAND]"
|
|
cmdDiskShort = "Manage cluster disks"
|
|
)
|
|
|
|
func newDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: cmdDiskUse,
|
|
Short: cmdDiskShort,
|
|
Args: cobra.MinimumNArgs(0),
|
|
Aliases: []string{"disk"},
|
|
}
|
|
cmd.AddCommand(
|
|
newListDisksCmd(client),
|
|
newDiskDetailCmd(client),
|
|
newListBadDiskCmd(client),
|
|
newDecommissionDiskCmd(client),
|
|
newRecommissionDiskCmd(client),
|
|
newQueryDecommissionDiskCmd(client),
|
|
newCancelDecommissionDiskCmd(client),
|
|
)
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdDiskDetailShort = "show disk detail"
|
|
)
|
|
|
|
func newDiskDetailCmd(client *master.MasterClient) *cobra.Command {
|
|
var optDpDetail bool
|
|
cmd := &cobra.Command{
|
|
Use: CliOpInfo + " [DATANODE_IP:PORT] [DISK_PATH]",
|
|
Short: cmdDiskDetailShort,
|
|
Args: cobra.ExactArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var (
|
|
detail *proto.DiskInfo
|
|
err error
|
|
)
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
if detail, err = client.AdminAPI().DiskDetail(args[0], args[1]); err != nil {
|
|
return
|
|
}
|
|
stdout("Summary:\n%s\n", formatDiskDetailSummary(detail))
|
|
|
|
// print data partition detail
|
|
if optDpDetail {
|
|
var view *proto.DiskDataPartitionsView
|
|
if view, err = client.ClientAPI().GetDiskDataPartitions(args[0], args[1]); err != nil {
|
|
err = fmt.Errorf("Get disk data detail information failed:\n%v\n", err)
|
|
return
|
|
}
|
|
stdout("Data partitions:\n")
|
|
stdout("%v\n", diskDataPartitionTableHeader)
|
|
sort.SliceStable(view.DataPartitions, func(i, j int) bool {
|
|
return view.DataPartitions[i].PartitionID < view.DataPartitions[j].PartitionID
|
|
})
|
|
for _, dp := range view.DataPartitions {
|
|
stdout("%v\n", formatDiskDataPartitionTableRow(dp))
|
|
}
|
|
}
|
|
},
|
|
}
|
|
cmd.Flags().BoolVarP(&optDpDetail, "data-partition", "d", false, "Display data partitions on the disk")
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdListDisksShort = "list disks"
|
|
)
|
|
|
|
func newListDisksCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: CliOpList + " [DATANODE_IP:PORT]",
|
|
Short: cmdListDisksShort,
|
|
Args: cobra.MinimumNArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var (
|
|
infos *proto.DiskInfos
|
|
err error
|
|
)
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
addr := ""
|
|
if len(args) > 0 {
|
|
addr = args[0]
|
|
}
|
|
if infos, err = client.AdminAPI().QueryDisks(addr); err != nil {
|
|
return
|
|
}
|
|
sort.SliceStable(infos.Disks, func(i, j int) bool {
|
|
return infos.Disks[i].Address < infos.Disks[j].Address
|
|
})
|
|
stdout("%v\n", formatDiskList(infos.Disks))
|
|
},
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdCheckBadDisksShort = "Check and list unhealthy disks"
|
|
)
|
|
|
|
func newListBadDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: CliOpCheck,
|
|
Short: cmdCheckBadDisksShort,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var (
|
|
infos *proto.BadDiskInfos
|
|
err error
|
|
)
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
if infos, err = client.AdminAPI().QueryBadDisks(); err != nil {
|
|
return
|
|
}
|
|
stdout("(partitionID=0 means detected by datanode disk checking, not associated with any partition)\n\n[Unavaliable disks]:\n")
|
|
stdout("%v\n", formatBadDiskTableHeader())
|
|
|
|
sort.SliceStable(infos.BadDisks, func(i, j int) bool {
|
|
return infos.BadDisks[i].Address < infos.BadDisks[j].Address
|
|
})
|
|
for _, disk := range infos.BadDisks {
|
|
stdout("%v\n", formatBadDiskInfoRow(disk))
|
|
}
|
|
},
|
|
}
|
|
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdDecommissionDisksShort = "Decommission disk on datanode"
|
|
)
|
|
|
|
func newDecommissionDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
var (
|
|
weight int
|
|
raftForceDel bool
|
|
)
|
|
cmd := &cobra.Command{
|
|
Use: CliOpDecommission + " [DATA NODE ADDR] [DISK]",
|
|
Short: cmdDecommissionDisksShort,
|
|
Args: cobra.MinimumNArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var err error
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
if err = client.AdminAPI().DecommissionDisk(args[0], args[1], weight, raftForceDel); err != nil {
|
|
return
|
|
}
|
|
stdout("Mark disk %v:%v to be decommissioned\n", args[0], args[1])
|
|
},
|
|
}
|
|
cmd.Flags().IntVar(&weight, CliFLagDecommissionWeight, lowPriorityDecommissionWeight, "decommission weight")
|
|
cmd.Flags().BoolVarP(&raftForceDel, CliFlagDecommissionRaftForce, "r", false, "true for raftForceDel")
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdRecommissionDisksShort = "Recommission disk on datanode"
|
|
)
|
|
|
|
func newRecommissionDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: CliOpRecommission + " [DATA NODE ADDR] [DISK]",
|
|
Short: cmdRecommissionDisksShort,
|
|
Args: cobra.MinimumNArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var err error
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
if err = client.AdminAPI().RecommissionDisk(args[0], args[1]); err != nil {
|
|
return
|
|
}
|
|
stdout("Mark disk %v:%v to be recommissioned\n", args[0], args[1])
|
|
},
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdQueryDecommissionDiskProgressShort = "Query decommmission progress on datanode"
|
|
)
|
|
|
|
func newQueryDecommissionDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: CliOpQueryProgress + " [DATA NODE ADDR] [DISK]",
|
|
Short: cmdQueryDecommissionDiskProgressShort,
|
|
Args: cobra.MinimumNArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var err error
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
progress, err := client.AdminAPI().QueryDecommissionDiskProgress(args[0], args[1])
|
|
if err != nil {
|
|
return
|
|
}
|
|
stdout("%v", formatDecommissionProgress(progress))
|
|
},
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
const (
|
|
cmdCancelDecommissionDiskShort = "cancel disk decommission"
|
|
)
|
|
|
|
func newCancelDecommissionDiskCmd(client *master.MasterClient) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: CliOpCancelDecommission + " [DATA NODE ADDR] [DISK]",
|
|
Short: cmdCancelDecommissionDiskShort,
|
|
Args: cobra.MinimumNArgs(2),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
var err error
|
|
defer func() {
|
|
errout(err)
|
|
}()
|
|
|
|
err = client.AdminAPI().AbortDiskDecommission(args[0], args[1])
|
|
if err != nil {
|
|
err = fmt.Errorf("%v, please exec curl -v http://masterAddr:17010/disk/queryDecommissionProgress?addr=dataAddr:17310&disk=dataPath to check if the disk has been canceled", err)
|
|
return
|
|
}
|
|
stdout("%v\n", "cancel decommission successfully")
|
|
},
|
|
}
|
|
return cmd
|
|
}
|