From c5293e03368b869d87f6c16e92e2425c2733abc8 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 6 Nov 2023 13:47:40 +0000 Subject: [PATCH 1/6] [feat]curveadm: add install tool command Signed-off-by: 0fatal <2816813070@qq.com> --- cli/command/cmd.go | 3 +- cli/command/install/cmd.go | 21 ++++ cli/command/install/tool.go | 85 ++++++++++++++ internal/errno/errno.go | 1 + internal/playbook/configs.go | 7 ++ internal/playbook/factory.go | 7 +- internal/task/step/shell.go | 36 ++++++ internal/task/task/install/install_tool.go | 129 +++++++++++++++++++++ 8 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 cli/command/install/cmd.go create mode 100644 cli/command/install/tool.go create mode 100644 internal/task/task/install/install_tool.go diff --git a/cli/command/cmd.go b/cli/command/cmd.go index a1f6c19f5..ae9c60c8c 100644 --- a/cli/command/cmd.go +++ b/cli/command/cmd.go @@ -26,7 +26,6 @@ package command import ( "fmt" - "github.com/opencurve/curveadm/cli/cli" "github.com/opencurve/curveadm/cli/command/client" "github.com/opencurve/curveadm/cli/command/cluster" @@ -34,6 +33,7 @@ import ( "github.com/opencurve/curveadm/cli/command/disks" "github.com/opencurve/curveadm/cli/command/hosts" "github.com/opencurve/curveadm/cli/command/http" + "github.com/opencurve/curveadm/cli/command/install" "github.com/opencurve/curveadm/cli/command/monitor" "github.com/opencurve/curveadm/cli/command/pfs" "github.com/opencurve/curveadm/cli/command/playground" @@ -72,6 +72,7 @@ func addSubCommands(cmd *cobra.Command, curveadm *cli.CurveAdm) { monitor.NewMonitorCommand(curveadm), // curveadm monitor ... http.NewHttpCommand(curveadm), // curveadm http website.NewWebsiteCommand(curveadm), // curveadm website ... + install.NewInstallCommand(curveadm), // curveadm install NewAuditCommand(curveadm), // curveadm audit NewCleanCommand(curveadm), // curveadm clean diff --git a/cli/command/install/cmd.go b/cli/command/install/cmd.go new file mode 100644 index 000000000..342e4f16b --- /dev/null +++ b/cli/command/install/cmd.go @@ -0,0 +1,21 @@ +package install + +import ( + "github.com/opencurve/curveadm/cli/cli" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +func NewInstallCommand(curveadm *cli.CurveAdm) *cobra.Command { + cmd := &cobra.Command{ + Use: "install", + Short: "Manage install", + Args: cliutil.NoArgs, + RunE: cliutil.ShowHelp(curveadm.Err()), + } + + cmd.AddCommand( + NewInstallToolCommand(curveadm), + ) + return cmd +} diff --git a/cli/command/install/tool.go b/cli/command/install/tool.go new file mode 100644 index 000000000..d36df72d1 --- /dev/null +++ b/cli/command/install/tool.go @@ -0,0 +1,85 @@ +package install + +import ( + "github.com/fatih/color" + "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/playbook" + cliutil "github.com/opencurve/curveadm/internal/utils" + "github.com/spf13/cobra" +) + +var ( + INSTALL_TOOL_PLAYBOOK_STEPS = []int{ + playbook.INSTALL_TOOL, + } +) + +type installOptions struct { + host string +} + +func NewInstallToolCommand(curveadm *cli.CurveAdm) *cobra.Command { + var options installOptions + + cmd := &cobra.Command{ + Use: "tool [OPTIONS]", + Short: "Install tool v2 on the specified host", + Args: cliutil.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return runInstallTool(curveadm, options) + }, + DisableFlagsInUseLine: true, + } + + flags := cmd.Flags() + flags.StringVar(&options.host, "host", "localhost", "Specify target host") + + return cmd +} + +func genInstallToolPlaybook(curveadm *cli.CurveAdm, + dcs []*topology.DeployConfig, + options installOptions, +) (*playbook.Playbook, error) { + dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ + Id: "*", + Role: "*", + Host: options.host, + }) + + steps := INSTALL_TOOL_PLAYBOOK_STEPS + pb := playbook.NewPlaybook(curveadm) + for _, step := range steps { + pb.AddStep(&playbook.PlaybookStep{ + Type: step, + Configs: dcs, + Options: map[string]interface{}{ + comm.KEY_CLIENT_HOST: options.host, + }, + }) + } + return pb, nil +} + +func runInstallTool(curveadm *cli.CurveAdm, options installOptions) error { + dcs, err := curveadm.ParseTopology() + if err != nil { + return err + } + + pb, err := genInstallToolPlaybook(curveadm, dcs, options) + if err != nil { + return err + } + + err = pb.Run() + if err != nil { + return err + } + + curveadm.WriteOutln(color.GreenString("Install %s to %s success."), + "curve tool v2", options.host) + return nil +} diff --git a/internal/errno/errno.go b/internal/errno/errno.go index fd40bbc00..2d32b455f 100644 --- a/internal/errno/errno.go +++ b/internal/errno/errno.go @@ -553,6 +553,7 @@ var ( ERR_INSTALL_OR_REMOVE_DEBIAN_PACKAGE_FAILED = EC(620024, "install or remove debian package failed (dpkg)") ERR_INSTALL_OR_REMOVE_RPM_PACKAGE_FAILED = EC(620025, "install or remove rpm package failed (rpm)") ERR_SECURE_COPY_FILE_TO_REMOTE_FAILED = EC(620026, "secure copy file to remote failed (scp)") + ERR_CHMOD_FILE_FAILED = EC(620027, "chmod file failed (chmod)") ERR_RUN_SCRIPT_FAILED = EC(620998, "run script failed (bash script.sh)") ERR_RUN_A_BASH_COMMAND_FAILED = EC(620999, "run a bash command failed (bash -c)") diff --git a/internal/playbook/configs.go b/internal/playbook/configs.go index 80c88b85b..f04ab72db 100644 --- a/internal/playbook/configs.go +++ b/internal/playbook/configs.go @@ -84,6 +84,13 @@ func (c *SmartConfig) GetDC(index int) *topology.DeployConfig { return c.dcs[index] } +func (c *SmartConfig) GetDCS() []*topology.DeployConfig { + if c.ctype != TYPE_CONFIG_DEPLOY { + return nil + } + return c.dcs +} + func (c *SmartConfig) GetCC(index int) *configure.ClientConfig { if index < 0 || index >= c.len || c.ctype != TYPE_CONFIG_CLIENT { return nil diff --git a/internal/playbook/factory.go b/internal/playbook/factory.go index c38254b5e..f8c412da7 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -31,6 +31,7 @@ import ( "github.com/opencurve/curveadm/internal/task/task/checker" comm "github.com/opencurve/curveadm/internal/task/task/common" "github.com/opencurve/curveadm/internal/task/task/fs" + "github.com/opencurve/curveadm/internal/task/task/install" "github.com/opencurve/curveadm/internal/task/task/monitor" pg "github.com/opencurve/curveadm/internal/task/task/playground" "github.com/opencurve/curveadm/internal/task/task/website" @@ -84,6 +85,7 @@ const ( GET_CLIENT_STATUS INSTALL_CLIENT UNINSTALL_CLIENT + INSTALL_TOOL // bs FORMAT_CHUNKFILE_POOL @@ -169,7 +171,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { switch step.Type { case CHECK_SSH_CONNECT, GET_HOST_DATE, - PULL_IMAGE: + PULL_IMAGE, + INSTALL_TOOL: host := config.GetDC(i).GetHost() if once[host] { continue @@ -260,6 +263,8 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { t, err = comm.NewInstallClientTask(curveadm, config.GetCC(i)) case UNINSTALL_CLIENT: t, err = comm.NewUninstallClientTask(curveadm, nil) + case INSTALL_TOOL: + t, err = install.NewInstallToolTask(curveadm, config.GetDCS()) // bs case FORMAT_CHUNKFILE_POOL: t, err = bs.NewFormatChunkfilePoolTask(curveadm, config.GetFC(i)) diff --git a/internal/task/step/shell.go b/internal/task/step/shell.go index e002e1cac..34ae3a6f1 100644 --- a/internal/task/step/shell.go +++ b/internal/task/step/shell.go @@ -79,6 +79,22 @@ type ( module.ExecOptions } + MoveFile struct { + Source string + Dest string + NoClobber bool // do not overwrite an existing file + Out *string + module.ExecOptions + } + + Chmod struct { + Mode string + File string + Recursive bool + Out *string + module.ExecOptions + } + Stat struct { Files []string Format string @@ -324,6 +340,26 @@ func (s *CopyFile) Execute(ctx *context.Context) error { return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_FILES_AND_DIRECTORIES_FAILED) } +func (s *MoveFile) Execute(ctx *context.Context) error { + cmd := ctx.Module().Shell().Rename(s.Source, s.Dest) + if s.NoClobber { + cmd.AddOption("--no-clobber") + } + + out, err := cmd.Execute(s.ExecOptions) + return PostHandle(nil, s.Out, out, err, errno.ERR_RENAME_FILE_OR_DIRECTORY_FAILED) +} + +func (s *Chmod) Execute(ctx *context.Context) error { + cmd := ctx.Module().Shell().Chmod(s.Mode, s.File) + if s.Recursive { + cmd.AddOption("--recursive") + } + + out, err := cmd.Execute(s.ExecOptions) + return PostHandle(nil, s.Out, out, err, errno.ERR_CHMOD_FILE_FAILED) +} + func (s *Stat) Execute(ctx *context.Context) error { cmd := ctx.Module().Shell().Stat(s.Files...) if len(s.Format) > 0 { diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go new file mode 100644 index 000000000..68cb2fe4c --- /dev/null +++ b/internal/task/task/install/install_tool.go @@ -0,0 +1,129 @@ +package install + +import ( + "fmt" + "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/task/step" + "github.com/opencurve/curveadm/internal/task/task" + "strings" +) + +const ( + FORMAT_TOOLSV2_CONF_BS = ` +global: + httpTimeout: 500ms + rpcTimeout: 500ms + rpcRetryTimes: 1 + maxChannelSize: 4 + showError: false +curvebs: + mdsAddr: %s + mdsDummyAddr: %s + etcdAddr: %s + snapshotAddr: %s + snapshotDummyAddr: %s + root: + user: root + password: root_password +` + FORMAT_TOOLSV2_CONF_FS = ` +global: + httpTimeout: 500ms + rpcTimeout: 500ms + rpcRetryTimes: 1 + maxChannelSize: 4 + showError: false +curvefs: + mdsAddr: %s + mdsDummyAddr: %s + etcdAddr: %s + s3: + ak: ak + sk: sk + endpoint: http://localhost:9000 + bucketname: bucketname + blocksize: 4 mib + chunksize: 64 mib +` +) + +func genToolV2Conf(dcs []*topology.DeployConfig) string { + var etcdAddr []string + var mdsAddr []string + var mdsDummyAddr []string + var snapshotCloneDummyAddr []string + var snapshotCloneProxyAddr []string + + for _, dc := range dcs { + ip := dc.GetListenIp() + switch dc.GetRole() { + case topology.ROLE_ETCD: + etcdAddr = append(etcdAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenClientPort())) + case topology.ROLE_MDS: + mdsAddr = append(mdsAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenPort())) + mdsDummyAddr = append(mdsDummyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenDummyPort())) + case topology.ROLE_SNAPSHOTCLONE: + snapshotCloneDummyAddr = append(snapshotCloneDummyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenDummyPort())) + snapshotCloneProxyAddr = append(snapshotCloneProxyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenProxyPort())) + } + } + + var toolConf string + mdsAddrStr := strings.Join(mdsAddr, ",") + mdsDummyAddrStr := strings.Join(mdsDummyAddr, ",") + etcdAddrStr := strings.Join(etcdAddr, ",") + snapshotCloneDummyAddrStr := strings.Join(snapshotCloneDummyAddr, ",") + snapshotCloneProxyAddrStr := strings.Join(snapshotCloneProxyAddr, ",") + + if dcs[0].GetKind() == topology.KIND_CURVEBS { + toolConf = fmt.Sprintf(strings.TrimSpace(FORMAT_TOOLSV2_CONF_BS), mdsAddrStr, mdsDummyAddrStr, etcdAddrStr, snapshotCloneProxyAddrStr, snapshotCloneDummyAddrStr) + } else if dcs[0].GetKind() == topology.KIND_CURVEFS { + toolConf = fmt.Sprintf(strings.TrimSpace(FORMAT_TOOLSV2_CONF_FS), mdsAddrStr, mdsDummyAddrStr, etcdAddrStr) + } + + return toolConf +} + +func NewInstallToolTask(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig) (*task.Task, error) { + host := curveadm.MemStorage().Get(comm.KEY_CLIENT_HOST).(string) + hc, err := curveadm.GetHost(host) + if err != nil { + return nil, err + } + + subname := fmt.Sprintf("host=%s", host) + t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) + + confContent := genToolV2Conf(dcs) + + t.AddStep(&step.CreateDirectory{ + Paths: []string{"~/.curve"}, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Curl{ + Url: "https://curve-tool.nos-eastchina1.126.net/release/curve-latest", + Insecure: true, + Silent: true, + Output: "/tmp/curve-latest", + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.Chmod{ + Mode: "+x", + File: "/tmp/curve-latest", + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.MoveFile{ + Source: "/tmp/curve-latest", + Dest: "/usr/bin/curve", + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.InstallFile{ + Content: &confContent, + HostDestPath: "~/.curve/curve.yaml", + ExecOptions: curveadm.ExecOptions(), + }) + + return t, nil +} From da8a8089b337e56f00670d1689e25d9b7c2aa66f Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Wed, 8 Nov 2023 09:34:37 +0000 Subject: [PATCH 2/6] Copy the binary and conf of toolv2 from container to host Signed-off-by: 0fatal <2816813070@qq.com> --- internal/playbook/configs.go | 7 -- internal/playbook/factory.go | 2 +- internal/task/step/file.go | 16 +++ internal/task/task/install/install_tool.go | 116 ++++----------------- 4 files changed, 40 insertions(+), 101 deletions(-) diff --git a/internal/playbook/configs.go b/internal/playbook/configs.go index f04ab72db..80c88b85b 100644 --- a/internal/playbook/configs.go +++ b/internal/playbook/configs.go @@ -84,13 +84,6 @@ func (c *SmartConfig) GetDC(index int) *topology.DeployConfig { return c.dcs[index] } -func (c *SmartConfig) GetDCS() []*topology.DeployConfig { - if c.ctype != TYPE_CONFIG_DEPLOY { - return nil - } - return c.dcs -} - func (c *SmartConfig) GetCC(index int) *configure.ClientConfig { if index < 0 || index >= c.len || c.ctype != TYPE_CONFIG_CLIENT { return nil diff --git a/internal/playbook/factory.go b/internal/playbook/factory.go index f8c412da7..8b6ff7b35 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -264,7 +264,7 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { case UNINSTALL_CLIENT: t, err = comm.NewUninstallClientTask(curveadm, nil) case INSTALL_TOOL: - t, err = install.NewInstallToolTask(curveadm, config.GetDCS()) + t, err = install.NewInstallToolTask(curveadm, config.GetDC(i)) // bs case FORMAT_CHUNKFILE_POOL: t, err = bs.NewFormatChunkfilePoolTask(curveadm, config.GetFC(i)) diff --git a/internal/task/step/file.go b/internal/task/step/file.go index cfd4fc575..18714e525 100644 --- a/internal/task/step/file.go +++ b/internal/task/step/file.go @@ -53,6 +53,13 @@ type ( module.ExecOptions } + ExtractFile struct { + HostDestPath string + ContainerId string + ContainerSrcPath string + module.ExecOptions + } + InstallFile struct { Content *string HostDestPath string @@ -152,6 +159,15 @@ func (s *ReadFile) Execute(ctx *context.Context) error { return nil } +func (s *ExtractFile) Execute(ctx *context.Context) error { + dockerCli := ctx.Module().DockerCli().CopyFromContainer(s.ContainerId, s.ContainerSrcPath, s.HostDestPath) + _, err := dockerCli.Execute(s.ExecOptions) + if err != nil { + return errno.ERR_COPY_FROM_CONTAINER_FAILED.FD("(%s cp CONTAINER:SRC_PATH DEST_PATH)", s.ExecWithEngine).E(err) + } + return nil +} + func (s *InstallFile) Execute(ctx *context.Context) error { localPath := utils.RandFilename(TEMP_DIR) defer os.Remove(localPath) diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go index 68cb2fe4c..0087887a0 100644 --- a/internal/task/task/install/install_tool.go +++ b/internal/task/task/install/install_tool.go @@ -7,116 +7,46 @@ import ( "github.com/opencurve/curveadm/internal/configure/topology" "github.com/opencurve/curveadm/internal/task/step" "github.com/opencurve/curveadm/internal/task/task" - "strings" ) -const ( - FORMAT_TOOLSV2_CONF_BS = ` -global: - httpTimeout: 500ms - rpcTimeout: 500ms - rpcRetryTimes: 1 - maxChannelSize: 4 - showError: false -curvebs: - mdsAddr: %s - mdsDummyAddr: %s - etcdAddr: %s - snapshotAddr: %s - snapshotDummyAddr: %s - root: - user: root - password: root_password -` - FORMAT_TOOLSV2_CONF_FS = ` -global: - httpTimeout: 500ms - rpcTimeout: 500ms - rpcRetryTimes: 1 - maxChannelSize: 4 - showError: false -curvefs: - mdsAddr: %s - mdsDummyAddr: %s - etcdAddr: %s - s3: - ak: ak - sk: sk - endpoint: http://localhost:9000 - bucketname: bucketname - blocksize: 4 mib - chunksize: 64 mib -` -) - -func genToolV2Conf(dcs []*topology.DeployConfig) string { - var etcdAddr []string - var mdsAddr []string - var mdsDummyAddr []string - var snapshotCloneDummyAddr []string - var snapshotCloneProxyAddr []string - - for _, dc := range dcs { - ip := dc.GetListenIp() - switch dc.GetRole() { - case topology.ROLE_ETCD: - etcdAddr = append(etcdAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenClientPort())) - case topology.ROLE_MDS: - mdsAddr = append(mdsAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenPort())) - mdsDummyAddr = append(mdsDummyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenDummyPort())) - case topology.ROLE_SNAPSHOTCLONE: - snapshotCloneDummyAddr = append(snapshotCloneDummyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenDummyPort())) - snapshotCloneProxyAddr = append(snapshotCloneProxyAddr, fmt.Sprintf("%s:%d", ip, dc.GetListenProxyPort())) - } - } - - var toolConf string - mdsAddrStr := strings.Join(mdsAddr, ",") - mdsDummyAddrStr := strings.Join(mdsDummyAddr, ",") - etcdAddrStr := strings.Join(etcdAddr, ",") - snapshotCloneDummyAddrStr := strings.Join(snapshotCloneDummyAddr, ",") - snapshotCloneProxyAddrStr := strings.Join(snapshotCloneProxyAddr, ",") - - if dcs[0].GetKind() == topology.KIND_CURVEBS { - toolConf = fmt.Sprintf(strings.TrimSpace(FORMAT_TOOLSV2_CONF_BS), mdsAddrStr, mdsDummyAddrStr, etcdAddrStr, snapshotCloneProxyAddrStr, snapshotCloneDummyAddrStr) - } else if dcs[0].GetKind() == topology.KIND_CURVEFS { - toolConf = fmt.Sprintf(strings.TrimSpace(FORMAT_TOOLSV2_CONF_FS), mdsAddrStr, mdsDummyAddrStr, etcdAddrStr) - } - - return toolConf -} - -func NewInstallToolTask(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig) (*task.Task, error) { +func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { + layout := dc.GetProjectLayout() host := curveadm.MemStorage().Get(comm.KEY_CLIENT_HOST).(string) hc, err := curveadm.GetHost(host) if err != nil { return nil, err } + serviceId := curveadm.GetServiceId(dc.GetId()) + containerId, err := curveadm.GetContainerId(serviceId) + if err != nil { + return nil, err + } + subname := fmt.Sprintf("host=%s", host) t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) - confContent := genToolV2Conf(dcs) + var confContent string - t.AddStep(&step.CreateDirectory{ - Paths: []string{"~/.curve"}, - ExecOptions: curveadm.ExecOptions(), - }) - t.AddStep(&step.Curl{ - Url: "https://curve-tool.nos-eastchina1.126.net/release/curve-latest", - Insecure: true, - Silent: true, - Output: "/tmp/curve-latest", - ExecOptions: curveadm.ExecOptions(), + t.AddStep(&step.ExtractFile{ + ContainerSrcPath: layout.ToolsV2BinaryPath, + ContainerId: containerId, + HostDestPath: "/usr/bin/curve", + ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.Chmod{ Mode: "+x", - File: "/tmp/curve-latest", + File: "/usr/bin/curve", ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step.MoveFile{ - Source: "/tmp/curve-latest", - Dest: "/usr/bin/curve", + t.AddStep(&step.ReadFile{ + ContainerSrcPath: layout.ToolsV2ConfSystemPath, + ContainerId: containerId, + Content: &confContent, + ExecOptions: curveadm.ExecOptions(), + }) + t.AddStep(&step.CreateDirectory{ + Paths: []string{"~/.curve"}, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.InstallFile{ From d4a243a274523d3baf4798a1b248d737b250f10c Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 6 Nov 2023 13:47:40 +0000 Subject: [PATCH 3/6] Remove unused code and reuse functions Signed-off-by: 0fatal <2816813070@qq.com> --- cli/command/install/tool.go | 9 ++---- internal/errno/errno.go | 1 - internal/playbook/factory.go | 3 +- internal/task/step/file.go | 16 ---------- internal/task/step/shell.go | 36 ---------------------- internal/task/task/install/install_tool.go | 24 ++++----------- 6 files changed, 9 insertions(+), 80 deletions(-) diff --git a/cli/command/install/tool.go b/cli/command/install/tool.go index d36df72d1..5366602db 100644 --- a/cli/command/install/tool.go +++ b/cli/command/install/tool.go @@ -43,18 +43,13 @@ func genInstallToolPlaybook(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, options installOptions, ) (*playbook.Playbook, error) { - dcs = curveadm.FilterDeployConfig(dcs, topology.FilterOption{ - Id: "*", - Role: "*", - Host: options.host, - }) - + configs := curveadm.FilterDeployConfigByRole(dcs, topology.ROLE_MDS)[:1] steps := INSTALL_TOOL_PLAYBOOK_STEPS pb := playbook.NewPlaybook(curveadm) for _, step := range steps { pb.AddStep(&playbook.PlaybookStep{ Type: step, - Configs: dcs, + Configs: configs, Options: map[string]interface{}{ comm.KEY_CLIENT_HOST: options.host, }, diff --git a/internal/errno/errno.go b/internal/errno/errno.go index 2d32b455f..fd40bbc00 100644 --- a/internal/errno/errno.go +++ b/internal/errno/errno.go @@ -553,7 +553,6 @@ var ( ERR_INSTALL_OR_REMOVE_DEBIAN_PACKAGE_FAILED = EC(620024, "install or remove debian package failed (dpkg)") ERR_INSTALL_OR_REMOVE_RPM_PACKAGE_FAILED = EC(620025, "install or remove rpm package failed (rpm)") ERR_SECURE_COPY_FILE_TO_REMOTE_FAILED = EC(620026, "secure copy file to remote failed (scp)") - ERR_CHMOD_FILE_FAILED = EC(620027, "chmod file failed (chmod)") ERR_RUN_SCRIPT_FAILED = EC(620998, "run script failed (bash script.sh)") ERR_RUN_A_BASH_COMMAND_FAILED = EC(620999, "run a bash command failed (bash -c)") diff --git a/internal/playbook/factory.go b/internal/playbook/factory.go index 8b6ff7b35..69842500c 100644 --- a/internal/playbook/factory.go +++ b/internal/playbook/factory.go @@ -171,8 +171,7 @@ func (p *Playbook) createTasks(step *PlaybookStep) (*tasks.Tasks, error) { switch step.Type { case CHECK_SSH_CONNECT, GET_HOST_DATE, - PULL_IMAGE, - INSTALL_TOOL: + PULL_IMAGE: host := config.GetDC(i).GetHost() if once[host] { continue diff --git a/internal/task/step/file.go b/internal/task/step/file.go index 18714e525..cfd4fc575 100644 --- a/internal/task/step/file.go +++ b/internal/task/step/file.go @@ -53,13 +53,6 @@ type ( module.ExecOptions } - ExtractFile struct { - HostDestPath string - ContainerId string - ContainerSrcPath string - module.ExecOptions - } - InstallFile struct { Content *string HostDestPath string @@ -159,15 +152,6 @@ func (s *ReadFile) Execute(ctx *context.Context) error { return nil } -func (s *ExtractFile) Execute(ctx *context.Context) error { - dockerCli := ctx.Module().DockerCli().CopyFromContainer(s.ContainerId, s.ContainerSrcPath, s.HostDestPath) - _, err := dockerCli.Execute(s.ExecOptions) - if err != nil { - return errno.ERR_COPY_FROM_CONTAINER_FAILED.FD("(%s cp CONTAINER:SRC_PATH DEST_PATH)", s.ExecWithEngine).E(err) - } - return nil -} - func (s *InstallFile) Execute(ctx *context.Context) error { localPath := utils.RandFilename(TEMP_DIR) defer os.Remove(localPath) diff --git a/internal/task/step/shell.go b/internal/task/step/shell.go index 34ae3a6f1..e002e1cac 100644 --- a/internal/task/step/shell.go +++ b/internal/task/step/shell.go @@ -79,22 +79,6 @@ type ( module.ExecOptions } - MoveFile struct { - Source string - Dest string - NoClobber bool // do not overwrite an existing file - Out *string - module.ExecOptions - } - - Chmod struct { - Mode string - File string - Recursive bool - Out *string - module.ExecOptions - } - Stat struct { Files []string Format string @@ -340,26 +324,6 @@ func (s *CopyFile) Execute(ctx *context.Context) error { return PostHandle(nil, s.Out, out, err, errno.ERR_COPY_FILES_AND_DIRECTORIES_FAILED) } -func (s *MoveFile) Execute(ctx *context.Context) error { - cmd := ctx.Module().Shell().Rename(s.Source, s.Dest) - if s.NoClobber { - cmd.AddOption("--no-clobber") - } - - out, err := cmd.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_RENAME_FILE_OR_DIRECTORY_FAILED) -} - -func (s *Chmod) Execute(ctx *context.Context) error { - cmd := ctx.Module().Shell().Chmod(s.Mode, s.File) - if s.Recursive { - cmd.AddOption("--recursive") - } - - out, err := cmd.Execute(s.ExecOptions) - return PostHandle(nil, s.Out, out, err, errno.ERR_CHMOD_FILE_FAILED) -} - func (s *Stat) Execute(ctx *context.Context) error { cmd := ctx.Module().Shell().Stat(s.Files...) if len(s.Format) > 0 { diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go index 0087887a0..5ddfd5434 100644 --- a/internal/task/task/install/install_tool.go +++ b/internal/task/task/install/install_tool.go @@ -26,34 +26,22 @@ func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas subname := fmt.Sprintf("host=%s", host) t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) - var confContent string - - t.AddStep(&step.ExtractFile{ + t.AddStep(&step.CopyFromContainer{ ContainerSrcPath: layout.ToolsV2BinaryPath, ContainerId: containerId, - HostDestPath: "/usr/bin/curve", + HostDestPath: "/usr/local/bin/curve", ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step.Chmod{ - Mode: "+x", - File: "/usr/bin/curve", + t.AddStep(&step.CreateDirectory{ + Paths: []string{"~/.curve"}, ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step.ReadFile{ + t.AddStep(&step.CopyFromContainer{ ContainerSrcPath: layout.ToolsV2ConfSystemPath, ContainerId: containerId, - Content: &confContent, + HostDestPath: "~/.curve/curve.yaml", ExecOptions: curveadm.ExecOptions(), }) - t.AddStep(&step.CreateDirectory{ - Paths: []string{"~/.curve"}, - ExecOptions: curveadm.ExecOptions(), - }) - t.AddStep(&step.InstallFile{ - Content: &confContent, - HostDestPath: "~/.curve/curve.yaml", - ExecOptions: curveadm.ExecOptions(), - }) return t, nil } From 6e0210674eb8643d28f9d6301a30cb44f0ab755c Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 8 Dec 2023 13:10:48 +0000 Subject: [PATCH 4/6] Support specify install path of toolv2 Signed-off-by: 0fatal <2816813070@qq.com> --- cli/command/install/tool.go | 11 +++++++-- internal/common/common.go | 4 ++++ internal/task/task/install/install_tool.go | 28 ++++++++++++++++++++-- internal/tui/common/prompt.go | 9 +++++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/cli/command/install/tool.go b/cli/command/install/tool.go index 5366602db..8c2f94415 100644 --- a/cli/command/install/tool.go +++ b/cli/command/install/tool.go @@ -5,6 +5,7 @@ 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" cliutil "github.com/opencurve/curveadm/internal/utils" "github.com/spf13/cobra" @@ -18,6 +19,7 @@ var ( type installOptions struct { host string + path string } func NewInstallToolCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -35,6 +37,7 @@ func NewInstallToolCommand(curveadm *cli.CurveAdm) *cobra.Command { flags := cmd.Flags() flags.StringVar(&options.host, "host", "localhost", "Specify target host") + flags.StringVar(&options.path, "path", "/usr/local/bin/curve", "Specify target install path of tool v2") return cmd } @@ -43,7 +46,10 @@ func genInstallToolPlaybook(curveadm *cli.CurveAdm, dcs []*topology.DeployConfig, options installOptions, ) (*playbook.Playbook, error) { - configs := curveadm.FilterDeployConfigByRole(dcs, topology.ROLE_MDS)[:1] + configs := curveadm.FilterDeployConfig(dcs, topology.FilterOption{Id: "*", Role: topology.ROLE_MDS, Host: options.host})[:1] + if len(configs) == 0 { + return nil, errno.ERR_NO_SERVICES_MATCHED + } steps := INSTALL_TOOL_PLAYBOOK_STEPS pb := playbook.NewPlaybook(curveadm) for _, step := range steps { @@ -51,7 +57,8 @@ func genInstallToolPlaybook(curveadm *cli.CurveAdm, Type: step, Configs: configs, Options: map[string]interface{}{ - comm.KEY_CLIENT_HOST: options.host, + comm.KEY_INSTALL_HOST: options.host, + comm.KEY_INSTALL_PATH: options.path, }, }) } diff --git a/internal/common/common.go b/internal/common/common.go index df2b68c5b..2b718f20c 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -134,6 +134,10 @@ const ( // website KEY_WEBSITE_STATUS = "WEBSITE_STATUS" + + // install + KEY_INSTALL_HOST = "INSTALL_HOST" + KEY_INSTALL_PATH = "INSTALL_PATH" ) // others diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go index 5ddfd5434..20be81242 100644 --- a/internal/task/task/install/install_tool.go +++ b/internal/task/task/install/install_tool.go @@ -5,13 +5,33 @@ 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/task/step" "github.com/opencurve/curveadm/internal/task/task" + tui "github.com/opencurve/curveadm/internal/tui/common" + "github.com/opencurve/curveadm/pkg/module" ) +func checkPathExist(path string, sshConfig *module.SSHConfig, curveadm *cli.CurveAdm) error { + sshClient, err := module.NewSSHClient(*sshConfig) + if err != nil { + return errno.ERR_SSH_CONNECT_FAILED.E(err) + } + + module := module.NewModule(sshClient) + cmd := module.Shell().Stat(path) + if _, err := cmd.Execute(curveadm.ExecOptions()); err == nil { + if pass := tui.ConfirmYes(tui.PromptPathExist(path)); !pass { + return errno.ERR_CANCEL_OPERATION + } + } + return nil +} + func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { layout := dc.GetProjectLayout() - host := curveadm.MemStorage().Get(comm.KEY_CLIENT_HOST).(string) + host := curveadm.MemStorage().Get(comm.KEY_INSTALL_HOST).(string) + path := curveadm.MemStorage().Get(comm.KEY_INSTALL_PATH).(string) hc, err := curveadm.GetHost(host) if err != nil { return nil, err @@ -23,13 +43,17 @@ func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas return nil, err } + if err = checkPathExist(path, hc.GetSSHConfig(), curveadm); err != nil { + return nil, err + } + subname := fmt.Sprintf("host=%s", host) t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) t.AddStep(&step.CopyFromContainer{ ContainerSrcPath: layout.ToolsV2BinaryPath, ContainerId: containerId, - HostDestPath: "/usr/local/bin/curve", + HostDestPath: path, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.CreateDirectory{ diff --git a/internal/tui/common/prompt.go b/internal/tui/common/prompt.go index 52e8b1588..794c15e02 100644 --- a/internal/tui/common/prompt.go +++ b/internal/tui/common/prompt.go @@ -71,6 +71,9 @@ to watch the formatting progress. ` PROMPT_CANCEL_OPERATION = `[x] {{.operation}} canceled` + PROMPT_PATH_EXIST = `{{.path}} already exists. +` + DEFAULT_CONFIRM_PROMPT = "Do you want to continue?" ) @@ -236,3 +239,9 @@ func PromptAutoUpgrade(version string) string { prompt.data["version"] = version return prompt.Build() } + +func PromptPathExist(path string) string { + prompt := NewPrompt(color.YellowString(PROMPT_PATH_EXIST) + DEFAULT_CONFIRM_PROMPT) + prompt.data["path"] = path + return prompt.Build() +} From e756a9cdd2e3e22c8c642d854d003f27bc9d527b Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 18 Dec 2023 07:36:46 +0000 Subject: [PATCH 5/6] Support specify conf path of toolv2 Signed-off-by: 0fatal <2816813070@qq.com> --- cli/command/install/tool.go | 10 ++++++---- internal/common/common.go | 4 ++-- internal/task/task/install/install_tool.go | 14 +++++++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cli/command/install/tool.go b/cli/command/install/tool.go index 8c2f94415..a93520842 100644 --- a/cli/command/install/tool.go +++ b/cli/command/install/tool.go @@ -18,8 +18,9 @@ var ( ) type installOptions struct { - host string - path string + host string + path string + confPath string } func NewInstallToolCommand(curveadm *cli.CurveAdm) *cobra.Command { @@ -38,6 +39,7 @@ func NewInstallToolCommand(curveadm *cli.CurveAdm) *cobra.Command { flags := cmd.Flags() flags.StringVar(&options.host, "host", "localhost", "Specify target host") flags.StringVar(&options.path, "path", "/usr/local/bin/curve", "Specify target install path of tool v2") + flags.StringVar(&options.confPath, "confPath", "~/.curve/curve.yaml", "Specify target config path of tool v2") return cmd } @@ -57,8 +59,8 @@ func genInstallToolPlaybook(curveadm *cli.CurveAdm, Type: step, Configs: configs, Options: map[string]interface{}{ - comm.KEY_INSTALL_HOST: options.host, - comm.KEY_INSTALL_PATH: options.path, + comm.KEY_INSTALL_PATH: options.path, + comm.KEY_INSTALL_CONF_PATH: options.confPath, }, }) } diff --git a/internal/common/common.go b/internal/common/common.go index 2b718f20c..81cc34858 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -136,8 +136,8 @@ const ( KEY_WEBSITE_STATUS = "WEBSITE_STATUS" // install - KEY_INSTALL_HOST = "INSTALL_HOST" - KEY_INSTALL_PATH = "INSTALL_PATH" + KEY_INSTALL_PATH = "INSTALL_PATH" + KEY_INSTALL_CONF_PATH = "INSTALL_CONF_PATH" ) // others diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go index 20be81242..8dfcf4816 100644 --- a/internal/task/task/install/install_tool.go +++ b/internal/task/task/install/install_tool.go @@ -10,6 +10,7 @@ import ( "github.com/opencurve/curveadm/internal/task/task" tui "github.com/opencurve/curveadm/internal/tui/common" "github.com/opencurve/curveadm/pkg/module" + "path/filepath" ) func checkPathExist(path string, sshConfig *module.SSHConfig, curveadm *cli.CurveAdm) error { @@ -30,9 +31,9 @@ func checkPathExist(path string, sshConfig *module.SSHConfig, curveadm *cli.Curv func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*task.Task, error) { layout := dc.GetProjectLayout() - host := curveadm.MemStorage().Get(comm.KEY_INSTALL_HOST).(string) path := curveadm.MemStorage().Get(comm.KEY_INSTALL_PATH).(string) - hc, err := curveadm.GetHost(host) + confPath := curveadm.MemStorage().Get(comm.KEY_INSTALL_CONF_PATH).(string) + hc, err := curveadm.GetHost(dc.GetHost()) if err != nil { return nil, err } @@ -46,8 +47,11 @@ func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas if err = checkPathExist(path, hc.GetSSHConfig(), curveadm); err != nil { return nil, err } + if err = checkPathExist(confPath, hc.GetSSHConfig(), curveadm); err != nil { + return nil, err + } - subname := fmt.Sprintf("host=%s", host) + subname := fmt.Sprintf("host=%s", dc.GetHost()) t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) t.AddStep(&step.CopyFromContainer{ @@ -57,13 +61,13 @@ func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.CreateDirectory{ - Paths: []string{"~/.curve"}, + Paths: []string{filepath.Dir(confPath)}, ExecOptions: curveadm.ExecOptions(), }) t.AddStep(&step.CopyFromContainer{ ContainerSrcPath: layout.ToolsV2ConfSystemPath, ContainerId: containerId, - HostDestPath: "~/.curve/curve.yaml", + HostDestPath: confPath, ExecOptions: curveadm.ExecOptions(), }) From f1f540afeafab05c54fa75f9877cbf21f2f024e0 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 18 Dec 2023 10:03:14 +0000 Subject: [PATCH 6/6] Create directory of the install path of toolv2 if not exists Signed-off-by: 0fatal <2816813070@qq.com> --- internal/task/task/install/install_tool.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/task/task/install/install_tool.go b/internal/task/task/install/install_tool.go index 8dfcf4816..6352c1786 100644 --- a/internal/task/task/install/install_tool.go +++ b/internal/task/task/install/install_tool.go @@ -54,6 +54,10 @@ func NewInstallToolTask(curveadm *cli.CurveAdm, dc *topology.DeployConfig) (*tas subname := fmt.Sprintf("host=%s", dc.GetHost()) t := task.NewTask("Install tool v2", subname, hc.GetSSHConfig()) + t.AddStep(&step.CreateDirectory{ + Paths: []string{filepath.Dir(path)}, + ExecOptions: curveadm.ExecOptions(), + }) t.AddStep(&step.CopyFromContainer{ ContainerSrcPath: layout.ToolsV2BinaryPath, ContainerId: containerId,