Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ cf_cc_library(
deps = [
"//cuttlefish/flag_parser",
"//cuttlefish/host/commands/cvd/cli:command_request",
"//cuttlefish/host/commands/cvd/cli:help_format",
"//cuttlefish/host/commands/cvd/cli:types",
"//cuttlefish/host/commands/cvd/cli:utils",
"//cuttlefish/host/commands/cvd/cli/commands:command_handler",
Expand Down
81 changes: 45 additions & 36 deletions base/cvd/cuttlefish/host/commands/cvd/cli/commands/stop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "cuttlefish/flag_parser/gflags_compat.h"
#include "cuttlefish/host/commands/cvd/cli/command_request.h"
#include "cuttlefish/host/commands/cvd/cli/commands/command_handler.h"
#include "cuttlefish/host/commands/cvd/cli/help_format.h"
#include "cuttlefish/host/commands/cvd/cli/selector/selector.h"
#include "cuttlefish/host/commands/cvd/cli/types.h"
#include "cuttlefish/host/commands/cvd/cli/utils.h"
Expand All @@ -41,39 +42,12 @@
namespace cuttlefish {
namespace {

constexpr char kSummaryHelpText[] = "Stop all instances in a group";

constexpr char kDetailedHelpText[] =
R"""(
Stops all instances in an instance group

Usage:
cvd stop [--wait_for_launcher=SECONDS] [--clear_instance_dirs]

Stops a running cuttlefish instance group.

--wait_for_launcher=SECONDS The number of seconds to wait for the launcher to
respond to the stop request. If SECONDS is 0 it will wait
indefinitely. Defaults to 5 seconds.

--clear_instance_dirs If provided the instance directories will be deleted
after stopping.
)""";
constexpr char kSummaryHelpText[] = "Stop Cuttlefish instances";

struct StopFlags {
size_t wait_for_launcher_secs = 5;
bool clear_instance_dirs = false;
};
Result<StopFlags> ParseCommandFlags(cvd_common::Args& args) {
StopFlags flag_values;
std::vector<Flag> flags = {
GflagsCompatFlag("wait_for_launcher", flag_values.wait_for_launcher_secs),
GflagsCompatFlag("clear_instance_dirs", flag_values.clear_instance_dirs),
};
CF_EXPECT(ConsumeFlags(flags, args, {.fail_on_unexpected_argument = true}));
return flag_values;
}

} // namespace

CvdStopCommandHandler::CvdStopCommandHandler(InstanceManager& instance_manager)
Expand All @@ -89,10 +63,11 @@ Result<void> CvdStopCommandHandler::Handle(const CommandRequest& request) {
auto group = CF_EXPECT(selector::SelectGroup(instance_manager_, request));
CF_EXPECT(group.HasActiveInstances(), "Selected group is not running");

StopFlags flags = CF_EXPECT(ParseCommandFlags(cmd_args));
CF_EXPECT(ConsumeFlags(CF_EXPECT(Flags(request)), cmd_args,
{.fail_on_unexpected_argument = true}));
std::optional<std::chrono::seconds> launcher_timeout;
if (flags.wait_for_launcher_secs > 0) {
launcher_timeout.emplace(flags.wait_for_launcher_secs);
if (flags_.wait_for_launcher_secs > 0) {
launcher_timeout.emplace(flags_.wait_for_launcher_secs);
}

std::vector<unsigned> instance_nums;
Expand All @@ -109,8 +84,8 @@ Result<void> CvdStopCommandHandler::Handle(const CommandRequest& request) {

Result<void> stop_outcome = instance_manager_.StopInstanceGroup(
group, launcher_timeout,
flags.clear_instance_dirs ? InstanceDirActionOnStop::Clear
: InstanceDirActionOnStop::Keep,
flags_.clear_instance_dirs ? InstanceDirActionOnStop::Clear
: InstanceDirActionOnStop::Keep,
instance_nums);

GatherVmStopMetrics(group);
Expand All @@ -127,9 +102,43 @@ std::string CvdStopCommandHandler::SummaryHelp() const {
return kSummaryHelpText;
}

Result<std::string> CvdStopCommandHandler::DetailedHelp(
const CommandRequest& request) {
return kDetailedHelpText;
std::vector<HelpParagraph> CvdStopCommandHandler::Description() const {
std::vector<HelpParagraph> description;
description.emplace_back(
HelpParagraph::Raw("Usage:\n cvd [selectors] stop [args]"));
description.emplace_back(
"Stop a subset of instances from a group. A single instance, severall or "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: several

"all instances in a group can be stopped at once. To stop instances from "
"different groups the command must be invoked multiple times.");
description.emplace_back(
"Instances must be in 'Running' or 'Starting' states, otherwise the "
"command will fail. Instances will be left in 'Stopped' state if the "
"command succeeds and can later be started with the `cvd start` "
"command.");
description.emplace_back(
"The stop operation attemps to graciously stop the instances by sending "
"an ACPI shutdown. If the shutdown doesn't complete within the "
Comment on lines +119 to +120

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no "ACPI shutdown", was this hallucinated? The distinction is whether processes are SIGKILLed or not. The "nice" shutdown still uses crosvm stop, which immediately stops all KVM threads.

"configured timeout the virtual machines and accompanying processes are "
"forcefully terminated. Logs, virtual disks and other files are "
"preserved after a stop completes unless --clear_instance_dirs is "
"given.");
return description;
}

Result<std::vector<Flag>> CvdStopCommandHandler::Flags(const CommandRequest&) {
return std::vector<Flag>{
GflagsCompatFlag("wait_for_launcher_seconds",
flags_.wait_for_launcher_secs)
.Alias("wait_for_launcher")
.Help("Number of seconds to wait for the running instance(s) "
"to report that it stopped successfully before "
"forcefully stopping it."),
GflagsCompatFlag("clear_instance_dirs", flags_.clear_instance_dirs)
.Help("Deletes log files, temporary files, virtual disks "
"overlays and other instance specific state. It does "
"not delete the original disk images, but reverts any "
"changes the instance may have written to disk."),
};
}

std::unique_ptr<CvdCommandHandler> NewCvdStopCommandHandler(
Expand Down
11 changes: 10 additions & 1 deletion base/cvd/cuttlefish/host/commands/cvd/cli/commands/stop.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@

#include <memory>
#include <string>
#include <vector>

#include "cuttlefish/flag_parser/flag.h"
#include "cuttlefish/host/commands/cvd/cli/command_request.h"
#include "cuttlefish/host/commands/cvd/cli/commands/command_handler.h"
#include "cuttlefish/host/commands/cvd/cli/help_format.h"
#include "cuttlefish/host/commands/cvd/cli/types.h"
#include "cuttlefish/host/commands/cvd/instances/instance_manager.h"
#include "cuttlefish/result/result.h"
Expand All @@ -33,12 +36,18 @@ class CvdStopCommandHandler : public CvdCommandHandler {

Result<void> Handle(const CommandRequest& request) override;
cvd_common::Args CmdList() const override;
Result<std::vector<Flag>> Flags(const CommandRequest& request) override;

std::string SummaryHelp() const override;
std::vector<HelpParagraph> Description() const override;
bool RequiresDeviceExists() const override { return true; }
Result<std::string> DetailedHelp(const CommandRequest& request) override;

private:
struct {
size_t wait_for_launcher_secs = 5;
bool clear_instance_dirs = false;
} flags_;

InstanceManager& instance_manager_;
};

Expand Down
Loading