From 7fadce0230010f8be219471337a89b438a04d18f 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 | 82 +++++++++++++++++++-- internal/common/common.go | 1 + internal/errno/errno.go | 3 +- internal/playbook/factory.go | 3 + internal/task/task/common/service_status.go | 71 ++++++++++++++++++ 5 files changed, 152 insertions(+), 8 deletions(-) diff --git a/cli/command/enter.go b/cli/command/enter.go index e7d54c10d..d104a2658 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 ( + AttachMdsLeaderContainer = []int{playbook.ATTACH_MDS_LEADER_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,16 +66,75 @@ func NewEnterCommand(curveadm *cli.CurveAdm) *cobra.Command { return cmd } +func genMdsLeaderPlaybook(curveadm *cli.CurveAdm, + dcs []*topology.DeployConfig, + options statusOptions) (*playbook.Playbook, error) { + dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ + Id: options.id, + Role: options.role, + Host: options.host, + }) + if len(dcs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } + + steps := []int{playbook.ATTACH_MDS_LEADER_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 getMdsLeaderId(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, id string) (string, error) { + statusForMdsLeaderOptions := statusOptions{id: "*", role: ROLE_MDS, host: "*"} + pb, err := genMdsLeaderPlaybook(curveadm, dcs, statusForMdsLeaderOptions) + if err != nil { + return "", err + } + // run playground + err = pb.Run() + if err != nil { + return "", err + } + // get Mds leader id + value := curveadm.MemStorage().Get(comm.MDS_LEADER_ID) + id = value.(string) + if id == "" { + return "", errno.ERR_NO_LEADER_CONTAINER_FOUND + } + return id, nil +} + func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { // 1) parse cluster topology dcs, err := curveadm.ParseTopology() if err != nil { return err } + var containerId string + var dc *topology.DeployConfig + id := options.id - // 2) filter service + // 2) If no id options, get Mds leader id + if id == "" { + id, err = getMdsLeaderId(curveadm, dcs, id) + if err != nil { + return err + } + } + + // 3) filter service dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ - Id: options.id, + Id: id, Role: "*", Host: "*", }) @@ -74,15 +142,15 @@ func runEnter(curveadm *cli.CurveAdm, options enterOptions) error { return errno.ERR_NO_SERVICES_MATCHED } - // 3) get container id - dc := dcs[0] + // 4) get container id + dc = dcs[0] serviceId := curveadm.GetServiceId(dc.GetId()) - containerId, err := curveadm.GetContainerId(serviceId) + containerId, err = curveadm.GetContainerId(serviceId) if err != nil { 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..3b8d363c9 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" + MDS_LEADER_ID = "MDS_LEADER_ID" // format KEY_ALL_FORMAT_STATUS = "ALL_FORMAT_STATUS" diff --git a/internal/errno/errno.go b/internal/errno/errno.go index 46b8228c5..543daf414 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_CONTAINER_FOUND = EC(210008, "no leader 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..be92ab6a7 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -83,6 +83,7 @@ const ( GET_CLIENT_STATUS INSTALL_CLIENT UNINSTALL_CLIENT + ATTACH_MDS_LEADER_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_MDS_LEADER_CONTAINER: + t, err = comm.NewAttachMdsLeaderContainerTask(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..c24e2b7a3 100644 --- a/internal/task/task/common/service_status.go +++ b/internal/task/task/common/service_status.go @@ -80,6 +80,12 @@ type ( memStorage *utils.SafeMap } + step2SetMdsLeader struct { + serviceId string + isLeader *bool + memStorage *utils.SafeMap + } + ServiceStatus struct { Id string ParentId string @@ -218,6 +224,24 @@ func (s *step2FormatServiceStatus) Execute(ctx *context.Context) error { return nil } +func (s *step2SetMdsLeader) Execute(ctx *context.Context) error { + id := s.serviceId + IsLeader := *s.isLeader + s.memStorage.TX(func(kv *utils.SafeMap) error { + m := "" + v := kv.Get(comm.MDS_LEADER_ID) + if v != nil && v.(string) != "" { + return nil + } + if IsLeader { + m = id + } + kv.Set(comm.MDS_LEADER_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 +330,50 @@ func NewGetServiceStatusTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) return t, nil } + +func NewAttachMdsLeaderContainerTask(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{ + ShowAll: true, + 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(&step2SetMdsLeader{ + serviceId: serviceId, + isLeader: &isLeader, + memStorage: curveadm.MemStorage(), + }) + + return t, nil +}