Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impove(enter): enter leader mds directly without id option #374

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions cli/command/enter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ 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/task/task/common"
"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
}
Expand All @@ -43,8 +50,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)
},
Expand All @@ -57,32 +67,83 @@ 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)
if value == nil {
return "", errno.ERR_NO_LEADER_OR_RANDOM_CONTAINER_FOUND
}
id = value.(common.Leader0rRandom).Id
return id, nil
}

func runEnter(curveadm *cli.CurveAdm, options enterOptions) error {
// 1) parse cluster topology
dcs, err := curveadm.ParseTopology()
if err != nil {
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: "*",
})
if len(dcs) == 0 {
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)
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)
}
1 change: 1 addition & 0 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 4 additions & 2 deletions internal/errno/errno.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,10 @@ 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_UNSUPPORT_DEPLOY_TYPE = EC(210008, "unknown deploy type")
ERR_INVALID_DISK_TYPE = EC(210007, "poolset disk type must be lowercase and can only be one of ssd, hdd and nvme")
ERR_UNSUPPORT_DEPLOY_TYPE = EC(210008, "unknown deploy type")
ERR_NO_LEADER_OR_RANDOM_CONTAINER_FOUND = EC(210009, "no leader or random container found")

// 220: commad options (client common)
ERR_UNSUPPORT_CLIENT_KIND = EC(220000, "unsupport client kind")
// 221: command options (client/bs)
Expand Down
3 changes: 3 additions & 0 deletions internal/playbook/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const (
GET_CLIENT_STATUS
INSTALL_CLIENT
UNINSTALL_CLIENT
ATTACH_LEADER_OR_RANDOM_CONTAINER

// bs
FORMAT_CHUNKFILE_POOL
Expand Down Expand Up @@ -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:
Expand Down
80 changes: 80 additions & 0 deletions internal/task/task/common/service_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -94,6 +101,11 @@ type (
DataDir string
Config *topology.DeployConfig
}

Leader0rRandom struct {
IsLeader bool
Id string
}
)

func setServiceStatus(memStorage *utils.SafeMap, id string, status ServiceStatus) {
Expand Down Expand Up @@ -218,6 +230,27 @@ 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 := Leader0rRandom{false, id}
v := kv.Get(comm.LEADER_OR_RANDOM_ID)
if v != nil && v.(Leader0rRandom).IsLeader {
return nil
}
if IsLeader {
m = Leader0rRandom{true, 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)
Expand Down Expand Up @@ -306,3 +339,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}}"`,
LYPWYT marked this conversation as resolved.
Show resolved Hide resolved
Filter: fmt.Sprintf("id=%s", containerId),
Out: &status,
ExecOptions: curveadm.ExecOptions(),
})
t.AddStep(&step.Lambda{
LYPWYT marked this conversation as resolved.
Show resolved Hide resolved
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
}