From ea9cb1d389ca8a33dc1da3cd3775f88c2bcd37f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Streitenberger?= Date: Fri, 28 Aug 2026 20:37:49 -0300 Subject: [PATCH] fix(cmd): add stop subcommand to check preflight, trim volume, and get replica MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the existing install preflight stop / export replica stop pattern. If one of these commands is interrupted before its PostRun cleanup runs, the DaemonSet (and RBAC, for check preflight) it created is left behind in the cluster. stop lets the user clean those up manually. checksum is intentionally left out: its Cleanup() is a no-op since it only patches the Volume CR directly and creates no cluster resources that could be orphaned. Issue longhorn/longhorn#9311 Signed-off-by: Nicolás Streitenberger --- cmd/remote/subcmd/check.go | 44 ++++++++++++++++++++++++++++++++++++++ cmd/remote/subcmd/get.go | 44 ++++++++++++++++++++++++++++++++++++++ cmd/remote/subcmd/trim.go | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/cmd/remote/subcmd/check.go b/cmd/remote/subcmd/check.go index 51235251a..537e1e8fb 100644 --- a/cmd/remote/subcmd/check.go +++ b/cmd/remote/subcmd/check.go @@ -97,6 +97,8 @@ INFO[2024-07-16T17:17:42+08:00] Completed preflight checker`, }, } + cmd.AddCommand(newCmdCheckPreflightStop(globalOpts)) + utils.SetGlobalOptionsRemote(cmd, globalOpts) cmd.Flags().BoolVar(&preflightChecker.EnableSpdk, consts.CmdOptEnableSpdk, false, "Enable checking of SPDK required packages, modules, and setup.") @@ -105,3 +107,45 @@ INFO[2024-07-16T17:17:42+08:00] Completed preflight checker`, return cmd } + +func newCmdCheckPreflightStop(globalOpts *types.GlobalCmdOptions) *cobra.Command { + var preflightChecker = preflight.Checker{} + + cmd := &cobra.Command{ + Use: consts.SubCmdStop, + Short: "Stop Longhorn preflight checker", + Long: `This command terminates the preflight checker.`, + Example: `$ longhornctl check preflight stop +INFO[2024-07-16T17:21:32+08:00] Stopping preflight checker +INFO[2024-07-16T17:21:32+08:00] Successfully stopped preflight checker`, + + PreRun: func(cmd *cobra.Command, args []string) { + preflightChecker.KubeConfigPath = globalOpts.KubeConfigPath + preflightChecker.Namespace = globalOpts.Namespace + + if err := preflightChecker.Init(); err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to initialize preflight checker")) + } + }, + + Run: func(cmd *cobra.Command, args []string) { + logrus.Info("Stopping preflight checker") + + err := preflightChecker.Cleanup() + if err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to stop preflight checker")) + } + + logrus.Info("Successfully stopped preflight checker") + }, + } + + utils.SetGlobalOptionsRemote(cmd, globalOpts) + + // Hidden, not removed, so `stop` can be appended to the parent command as-is. + utils.SetFlagHidden(cmd, consts.CmdOptEnableSpdk) + utils.SetFlagHidden(cmd, consts.CmdOptHugePageSize) + utils.SetFlagHidden(cmd, consts.CmdOptUserspaceDriver) + + return cmd +} diff --git a/cmd/remote/subcmd/get.go b/cmd/remote/subcmd/get.go index f4725d300..5c6588b00 100644 --- a/cmd/remote/subcmd/get.go +++ b/cmd/remote/subcmd/get.go @@ -101,6 +101,8 @@ INFO[2024-07-16T17:23:51+08:00] Completed replica getter`, }, } + cmd.AddCommand(newCmdGetReplicaStop(globalOpts)) + utils.SetGlobalOptionsRemote(cmd, globalOpts) cmd.Flags().StringVar(&replicaGetter.ReplicaName, consts.CmdOptName, "", "Specify the name of the replica to retrieve information.") @@ -109,3 +111,45 @@ INFO[2024-07-16T17:23:51+08:00] Completed replica getter`, return cmd } + +func newCmdGetReplicaStop(globalOpts *types.GlobalCmdOptions) *cobra.Command { + var replicaGetter = replica.Getter{} + + cmd := &cobra.Command{ + Use: consts.SubCmdStop, + Short: "Stop the replica getter", + Long: `This command terminates the ongoing replica information retrieval and stops the replica getter.`, + Example: `$ longhornctl get replica stop +INFO[2024-07-16T17:29:14+08:00] Stopping replica getter +INFO[2024-07-16T17:29:14+08:00] Successfully stopped replica getter`, + + PreRun: func(cmd *cobra.Command, args []string) { + replicaGetter.KubeConfigPath = globalOpts.KubeConfigPath + replicaGetter.Namespace = globalOpts.Namespace + + if err := replicaGetter.Init(); err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to initialize replica getter")) + } + }, + + Run: func(cmd *cobra.Command, args []string) { + logrus.Info("Stopping replica getter") + + err := replicaGetter.Cleanup() + if err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to stop replica getter")) + } + + logrus.Info("Successfully stopped replica getter") + }, + } + + utils.SetGlobalOptionsRemote(cmd, globalOpts) + + // Hidden, not removed, so `stop` can be appended to the parent command as-is. + utils.SetFlagHidden(cmd, consts.CmdOptName) + utils.SetFlagHidden(cmd, consts.CmdOptLonghornVolumeName) + utils.SetFlagHidden(cmd, consts.CmdOptLonghornDataDirectory) + + return cmd +} diff --git a/cmd/remote/subcmd/trim.go b/cmd/remote/subcmd/trim.go index 6d52f7e52..ee694e24c 100644 --- a/cmd/remote/subcmd/trim.go +++ b/cmd/remote/subcmd/trim.go @@ -86,9 +86,51 @@ INFO[2024-07-16T17:32:01+08:00] Completed volume trimmer vo }, } + cmd.AddCommand(newCmdTrimVolumeStop(globalOpts)) + utils.SetGlobalOptionsRemote(cmd, globalOpts) cmd.Flags().StringVar(&volumeTrimmer.VolumeName, consts.CmdOptName, "", "Name of the Longhorn volum to be trimmed.") return cmd } + +func newCmdTrimVolumeStop(globalOpts *types.GlobalCmdOptions) *cobra.Command { + var volumeTrimmer = volume.Trimmer{} + + cmd := &cobra.Command{ + Use: consts.SubCmdStop, + Short: "Stop the volume trimmer", + Long: `This command terminates the ongoing volume trim process and stops the volume trimmer.`, + Example: `$ longhornctl trim volume --name="pvc-48a6457d-585e-423b-b530-bbc68a5f948a" stop +INFO[2024-07-16T17:29:14+08:00] Stopping volume trimmer +INFO[2024-07-16T17:29:14+08:00] Successfully stopped volume trimmer`, + + PreRun: func(cmd *cobra.Command, args []string) { + volumeTrimmer.KubeConfigPath = globalOpts.KubeConfigPath + volumeTrimmer.Namespace = globalOpts.Namespace + + if err := volumeTrimmer.Init(); err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to initialize volume trimmer")) + } + }, + + Run: func(cmd *cobra.Command, args []string) { + logrus.Info("Stopping volume trimmer") + + err := volumeTrimmer.Cleanup() + if err != nil { + utils.CheckErr(errors.Wrap(err, "Failed to stop volume trimmer")) + } + + logrus.Info("Successfully stopped volume trimmer") + }, + } + + utils.SetGlobalOptionsRemote(cmd, globalOpts) + + // Hidden, not removed, so `stop` can be appended to the parent command as-is. + utils.SetFlagHidden(cmd, consts.CmdOptName) + + return cmd +}