3030#include " cuttlefish/flag_parser/gflags_compat.h"
3131#include " cuttlefish/host/commands/cvd/cli/command_request.h"
3232#include " cuttlefish/host/commands/cvd/cli/commands/command_handler.h"
33+ #include " cuttlefish/host/commands/cvd/cli/help_format.h"
3334#include " cuttlefish/host/commands/cvd/cli/selector/selector.h"
3435#include " cuttlefish/host/commands/cvd/cli/types.h"
3536#include " cuttlefish/host/commands/cvd/cli/utils.h"
4142namespace cuttlefish {
4243namespace {
4344
44- constexpr char kSummaryHelpText [] = " Stop all instances in a group" ;
45-
46- constexpr char kDetailedHelpText [] =
47- R"""(
48- Stops all instances in an instance group
49-
50- Usage:
51- cvd stop [--wait_for_launcher=SECONDS] [--clear_instance_dirs]
52-
53- Stops a running cuttlefish instance group.
54-
55- --wait_for_launcher=SECONDS The number of seconds to wait for the launcher to
56- respond to the stop request. If SECONDS is 0 it will wait
57- indefinitely. Defaults to 5 seconds.
58-
59- --clear_instance_dirs If provided the instance directories will be deleted
60- after stopping.
61- )""" ;
45+ constexpr char kSummaryHelpText [] = " Stop Cuttlefish instances" ;
6246
6347struct StopFlags {
6448 size_t wait_for_launcher_secs = 5 ;
6549 bool clear_instance_dirs = false ;
6650};
67- Result<StopFlags> ParseCommandFlags (cvd_common::Args& args) {
68- StopFlags flag_values;
69- std::vector<Flag> flags = {
70- GflagsCompatFlag (" wait_for_launcher" , flag_values.wait_for_launcher_secs ),
71- GflagsCompatFlag (" clear_instance_dirs" , flag_values.clear_instance_dirs ),
72- };
73- CF_EXPECT (ConsumeFlags (flags, args, {.fail_on_unexpected_argument = true }));
74- return flag_values;
75- }
76-
7751} // namespace
7852
7953CvdStopCommandHandler::CvdStopCommandHandler (InstanceManager& instance_manager)
@@ -89,10 +63,11 @@ Result<void> CvdStopCommandHandler::Handle(const CommandRequest& request) {
8963 auto group = CF_EXPECT (selector::SelectGroup (instance_manager_, request));
9064 CF_EXPECT (group.HasActiveInstances (), " Selected group is not running" );
9165
92- StopFlags flags = CF_EXPECT (ParseCommandFlags (cmd_args));
66+ CF_EXPECT (ConsumeFlags (CF_EXPECT (Flags (request)), cmd_args,
67+ {.fail_on_unexpected_argument = true }));
9368 std::optional<std::chrono::seconds> launcher_timeout;
94- if (flags .wait_for_launcher_secs > 0 ) {
95- launcher_timeout.emplace (flags .wait_for_launcher_secs );
69+ if (flags_ .wait_for_launcher_secs > 0 ) {
70+ launcher_timeout.emplace (flags_ .wait_for_launcher_secs );
9671 }
9772
9873 std::vector<unsigned > instance_nums;
@@ -109,8 +84,8 @@ Result<void> CvdStopCommandHandler::Handle(const CommandRequest& request) {
10984
11085 Result<void > stop_outcome = instance_manager_.StopInstanceGroup (
11186 group, launcher_timeout,
112- flags .clear_instance_dirs ? InstanceDirActionOnStop::Clear
113- : InstanceDirActionOnStop::Keep,
87+ flags_ .clear_instance_dirs ? InstanceDirActionOnStop::Clear
88+ : InstanceDirActionOnStop::Keep,
11489 instance_nums);
11590
11691 GatherVmStopMetrics (group);
@@ -127,9 +102,43 @@ std::string CvdStopCommandHandler::SummaryHelp() const {
127102 return kSummaryHelpText ;
128103}
129104
130- Result<std::string> CvdStopCommandHandler::DetailedHelp (
131- const CommandRequest& request) {
132- return kDetailedHelpText ;
105+ std::vector<HelpParagraph> CvdStopCommandHandler::Description () const {
106+ std::vector<HelpParagraph> description;
107+ description.emplace_back (
108+ HelpParagraph::Raw (" Usage:\n cvd [selectors] stop [args]" ));
109+ description.emplace_back (
110+ " Stop a subset of instances from a group. A single instance, several or "
111+ " all instances in a group can be stopped at once. To stop instances from "
112+ " different groups the command must be invoked multiple times." );
113+ description.emplace_back (
114+ " Instances must be in 'Running' or 'Starting' states, otherwise the "
115+ " command will fail. Instances will be left in 'Stopped' state if the "
116+ " command succeeds and can later be started with the `cvd start` "
117+ " command." );
118+ description.emplace_back (
119+ " Instances are stopped by asking the virtual machine manager to stop, "
120+ " which typically means immediately stopping all VCPU threads. This may "
121+ " lead to data loss and/or corruption as it's roughly equivalent to "
122+ " removing the battery from a physical Android device. Logs, virtual "
123+ " disks and other files are preserved after a stop completes unless "
124+ " --clear_instance_dirs is given." );
125+ return description;
126+ }
127+
128+ Result<std::vector<Flag>> CvdStopCommandHandler::Flags (const CommandRequest&) {
129+ return std::vector<Flag>{
130+ GflagsCompatFlag (" wait_for_launcher_seconds" ,
131+ flags_.wait_for_launcher_secs )
132+ .Alias (" wait_for_launcher" )
133+ .Help (" Number of seconds to wait for the running instance(s) "
134+ " to report that it stopped successfully before "
135+ " forcefully stopping it." ),
136+ GflagsCompatFlag (" clear_instance_dirs" , flags_.clear_instance_dirs )
137+ .Help (" Deletes log files, temporary files, virtual disks "
138+ " overlays and other instance specific state. It does "
139+ " not delete the original disk images, but reverts any "
140+ " changes the instance may have written to disk." ),
141+ };
133142}
134143
135144std::unique_ptr<CvdCommandHandler> NewCvdStopCommandHandler (
0 commit comments