From f792e3088da8d527d15cadfd5969c9e93a76e7d9 Mon Sep 17 00:00:00 2001 From: lyp <1647564982@qq.com> Date: Sat, 2 Dec 2023 10:37:06 +0800 Subject: [PATCH] Impove(enter): enter leader mds directly without id option Signed-off-by: lyp <1647564982@qq.com> --- cli/command/enter.go | 74 ++++++++++++++++++-- internal/common/common.go | 1 + internal/errno/errno.go | 3 +- internal/playbook/factory.go | 3 + internal/task/task/common/service_status.go | 76 +++++++++++++++++++++ 5 files changed, 151 insertions(+), 6 deletions(-) diff --git a/cli/command/enter.go b/cli/command/enter.go index e7d54c10d..d47f6f1cf 100644 --- a/cli/command/enter.go +++ b/cli/command/enter.go @@ -26,13 +26,19 @@ package command import ( "github.com/opencurve/curveadm/cli/cli" + comm "github.com/opencurve/curveadm/internal/common" "github.com/opencurve/curveadm/internal/configure/topology" "github.com/opencurve/curveadm/internal/errno" + "github.com/opencurve/curveadm/internal/playbook" "github.com/opencurve/curveadm/internal/tools" "github.com/opencurve/curveadm/internal/utils" "github.com/spf13/cobra" ) +var ( + ATTACH_LEADER_OR_RANDOM_CONTAINER = []int{playbook.ATTACH_LEADER_OR_RANDOM_CONTAINER} +) + type enterOptions struct { id string } @@ -43,8 +49,11 @@ func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { cmd := &cobra.Command{ Use: "enter ID", Short: "Enter service container", - Args: utils.ExactArgs(1), + Args: utils.RequiresMaxArgs(1), PreRunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return nil + } options.id = args[0] return curveadm.CheckId(options.id) }, @@ -57,6 +66,55 @@ func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { return cmd } +func genLeaderOrRandomPlaybook(curveadm *cli.CurveAdm, + dcs []*topology.DeployConfig) (*playbook.Playbook, error) { + if len(dcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := ATTACH_LEADER_OR_RANDOM_CONTAINER + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: dcs, + ExecOptions: playbook.ExecOptions{ + SilentSubBar: true, + SilentMainBar: true, + SkipError: true, + }, + }) + } + return pb, nil +} + +func checkOrGetId(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, options enterOptions) (string, error) { + id := options.id + if id != "" { + return id, nil + } + pb, err := genLeaderOrRandomPlaybook(curveadm, dcs) + if err != nil { + return "", err + } + // run playground + err = pb.Run() + if err != nil { + return "", err + } + // get leader or random container id + value := curveadm.MemStorage().Get(comm.LEADER_OR_RANDOM_ID) + id = value.([2]string)[0] + id_random := value.([2]string)[1] + if id == "" && id_random == "" { + return "", errno.ERR_NO_LEADER_OR_RANDOM_CONTAINER_FOUND + } else if id != "" { + return id, nil + } else { + return id_random, nil + } +} + func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { // 1) parse cluster topology dcs, err := curveadm.ParseTopology() @@ -64,9 +122,15 @@ func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { return err } - // 2) filter service + // 2) check id options + id, err := checkOrGetId(curveadm, dcs, options) + if err != nil { + return err + } + + // 3) filter service dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ - Id: options.id, + Id: id, Role: "*", Host: "*", }) @@ -74,7 +138,7 @@ func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { return errno.ERR_NO_SERVICES_MATCHED } - // 3) get container id + // 4) get container id dc := dcs[0] serviceId := curveadm.GetServiceId(dc.GetId()) containerId, err := curveadm.GetContainerId(serviceId) @@ -82,7 +146,7 @@ func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { return err } - // 4) attch remote container + // 5) attach remote container home := dc.GetProjectLayout().ServiceRootDir return tools.AttachRemoteContainer(curveadm, dc.GetHost(), containerId, home) } diff --git a/internal/common/common.go b/internal/common/common.go index 8e67c6485..ff726c663 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -49,6 +49,7 @@ const ( POOLSET = "poolset" POOLSET_DISK_TYPE = "poolset-disktype" KEY_NUMBER_OF_CHUNKSERVER = "NUMBER_OF_CHUNKSERVER" + LEADER_OR_RANDOM_ID = "LEADER_OR_RANDOM_ID" // format KEY_ALL_FORMAT_STATUS = "ALL_FORMAT_STATUS" diff --git a/internal/errno/errno.go b/internal/errno/errno.go index 46b8228c5..53cc5c676 100644 --- a/internal/errno/errno.go +++ b/internal/errno/errno.go @@ -253,7 +253,8 @@ var ( ERR_UNSUPPORT_CLEAN_ITEM = EC(210005, "unsupport clean item") ERR_NO_SERVICES_MATCHED = EC(210006, "no services matched") // TODO: please check pool set disk type - ERR_INVALID_DISK_TYPE = EC(210007, "poolset disk type must be lowercase and can only be one of ssd, hdd and nvme") + ERR_INVALID_DISK_TYPE = EC(210007, "poolset disk type must be lowercase and can only be one of ssd, hdd and nvme") + ERR_NO_LEADER_OR_RANDOM_CONTAINER_FOUND = EC(210008, "no leader or random container found") // 220: commad options (client common) ERR_UNSUPPORT_CLIENT_KIND = EC(220000, "unsupport client kind") diff --git a/internal/playbook/factory.go b/internal/playbook/factory.go index f62a7b3e5..b4a52e4f5 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -83,6 +83,7 @@ const ( GET_CLIENT_STATUS INSTALL_CLIENT UNINSTALL_CLIENT + ATTACH_LEADER_OR_RANDOM_CONTAINER // bs FORMAT_CHUNKFILE_POOL @@ -225,6 +226,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { t, err = comm.NewInitServiceStatusTask(curveadm, config.GetDC(i)) case GET_SERVICE_STATUS: t, err = comm.NewGetServiceStatusTask(curveadm, config.GetDC(i)) + case ATTACH_LEADER_OR_RANDOM_CONTAINER: + t, err = comm.NewAttachLeaderOrRandomContainerTask(curveadm, config.GetDC(i)) case CLEAN_SERVICE: t, err = comm.NewCleanServiceTask(curveadm, config.GetDC(i)) case INIT_SUPPORT: diff --git a/internal/task/task/common/service_status.go b/internal/task/task/common/service_status.go index 660fd68c7..c07398a13 100644 --- a/internal/task/task/common/service_status.go +++ b/internal/task/task/common/service_status.go @@ -80,6 +80,13 @@ type ( memStorage *utils.SafeMap } + step2SetLeaderOrRandom struct { + serviceId string + status *string + isLeader *bool + memStorage *utils.SafeMap + } + ServiceStatus struct { Id string ParentId string @@ -218,6 +225,28 @@ func (s *step2FormatServiceStatus) Execute(ctx *context.Context) error { return nil } +func (s *step2SetLeaderOrRandom) Execute(ctx *context.Context) error { + id := s.serviceId + IsLeader := *s.isLeader + if !strings.HasPrefix(*s.status, "Up") { + return nil + } + s.memStorage.TX(func(kv *utils.SafeMap) error { + m := [2]string{"", ""} + m[1] = id + v := kv.Get(comm.LEADER_OR_RANDOM_ID) + if v != nil && v.([2]string)[0] != "" { + return nil + } + if IsLeader { + m[0] = id + } + kv.Set(comm.LEADER_OR_RANDOM_ID, m) + return nil + }) + return nil +} + func NewInitServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { serviceId := curveadm.GetServiceId(dc.GetId()) containerId, err := curveadm.GetContainerId(serviceId) @@ -306,3 +335,50 @@ func NewGetServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) return t, nil } + +func NewAttachLeaderOrRandomContainerTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { + serviceId := curveadm.GetServiceId(dc.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if curveadm.IsSkip(dc) { + return nil, nil + } else if err != nil { + return nil, err + } + hc, err := curveadm.GetHost(dc.GetHost()) + if err != nil { + return nil, err + } + + // new task + subname := fmt.Sprintf("host=%s role=%s containerId=%s", + dc.GetHost(), dc.GetRole(), tui.TrimContainerId(containerId)) + t := task.NewTask("Enter Leader container", subname, hc.GetSSHConfig()) + + // add step to task + var status string + var isLeader bool + t.AddStep(&step.ListContainers{ + Format: `"{{.Status}}"`, + Filter: fmt.Sprintf("id=%s", containerId), + Out: &status, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Lambda{ + Lambda: TrimContainerStatus(&status), + }) + t.AddStep(&step2GetLeader{ + dc: dc, + containerId: containerId, + status: &status, + isLeader: &isLeader, + execOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step2SetLeaderOrRandom{ + serviceId: serviceId, + status: &status, + isLeader: &isLeader, + memStorage: curveadm.MemStorage(), + }) + + return t, nil +}