Skip to content

Commit b2ddc4e

Browse files
Update cvd start to handle single instances
1 parent c560e42 commit b2ddc4e

3 files changed

Lines changed: 104 additions & 0 deletions

File tree

base/cvd/cuttlefish/host/commands/cvd/cli/commands/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ cf_cc_library(
390390
hdrs = ["start.h"],
391391
clang_format_enabled = False,
392392
deps = [
393+
"//cuttlefish/common/libs/fs",
393394
"//cuttlefish/common/libs/utils:contains",
394395
"//cuttlefish/common/libs/utils:files",
395396
"//cuttlefish/common/libs/utils:json",

base/cvd/cuttlefish/host/commands/cvd/cli/commands/start.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "cuttlefish/host/commands/cvd/cli/commands/start.h"
1818

19+
#include <fcntl.h>
1920
#include <signal.h> // IWYU pragma: keep
2021
#include <stddef.h>
2122
#include <stdlib.h>
@@ -40,6 +41,7 @@
4041
#include "absl/strings/str_join.h"
4142
#include "absl/strings/str_split.h"
4243

44+
#include "cuttlefish/common/libs/fs/shared_fd.h"
4345
#include "cuttlefish/common/libs/utils/contains.h"
4446
#include "cuttlefish/common/libs/utils/files.h"
4547
#include "cuttlefish/flag_parser/flag.h"
@@ -327,6 +329,21 @@ static Result<void> ConsumeDaemonModeFlag(cvd_common::Args& args) {
327329
return {};
328330
}
329331

332+
static bool HasUnsafeFlagsForBypass(const std::vector<std::string>& args) {
333+
std::vector<std::string> args_copy = args;
334+
bool daemon = true;
335+
std::string report_anonymous = "";
336+
std::vector<Flag> safe_flags = {
337+
GflagsCompatFlag("daemon", daemon),
338+
GflagsCompatFlag("report_anonymous_usage_stats", report_anonymous),
339+
};
340+
auto res = ConsumeFlags(safe_flags, args_copy);
341+
if (!res.ok()) {
342+
return true;
343+
}
344+
return !args_copy.empty();
345+
}
346+
330347
Result<void> CvdStartCommandHandler::Handle(const CommandRequest& request) {
331348
std::vector<std::string> subcmd_args = request.SubcommandArguments();
332349
CF_EXPECT(!GetConfigPath(subcmd_args).has_value(),
@@ -337,6 +354,22 @@ Result<void> CvdStartCommandHandler::Handle(const CommandRequest& request) {
337354
return CF_ERR(NoGroupMessage(request));
338355
}
339356

357+
if (request.Selectors().instance_names &&
358+
request.Selectors().instance_names->size() == 1) {
359+
auto [instance, group] =
360+
CF_EXPECT(selector::SelectInstance(instance_manager_, request));
361+
362+
if (instance.State() == cvd::INSTANCE_STATE_STOPPED &&
363+
group.StartTime() != TimeStamp{} &&
364+
!HasUnsafeFlagsForBypass(subcmd_args)) {
365+
CF_EXPECT(LaunchSingleInstance(instance, group, request));
366+
return {};
367+
} else {
368+
VLOG(1) << "Instance is not in stopped state. Proceeding with "
369+
"normal group start.";
370+
}
371+
}
372+
340373
CF_EXPECT(ConsumeDaemonModeFlag(subcmd_args));
341374
subcmd_args.push_back("--daemon=true");
342375

@@ -472,6 +505,72 @@ Result<void> CvdStartCommandHandler::LaunchDeviceInterruptible(
472505
return {};
473506
}
474507

508+
Result<void> CvdStartCommandHandler::LaunchSingleInstance(
509+
LocalInstance& instance, LocalInstanceGroup& group,
510+
const CommandRequest& request) {
511+
auto bin_path = group.HostArtifactsPath() + "/bin/run_cvd";
512+
cvd_common::Envs run_cvd_envs = request.Env();
513+
run_cvd_envs[kCuttlefishInstanceEnvVarName] = std::to_string(instance.Id());
514+
run_cvd_envs["HOME"] = group.HomeDir();
515+
run_cvd_envs[kAndroidHostOut] = group.HostArtifactsPath();
516+
run_cvd_envs[kAndroidProductOut] = group.ProductOutPath();
517+
run_cvd_envs[kAndroidSoongHostOut] = group.HostArtifactsPath();
518+
run_cvd_envs[kCvdMarkEnv] = "true";
519+
520+
ConstructCommandParam construct_cmd_param{.bin_path = bin_path,
521+
.home = group.HomeDir(),
522+
.args = cvd_common::Args{},
523+
.envs = run_cvd_envs,
524+
.working_dir = CurrentDirectory(),
525+
.command_name = "run_cvd"};
526+
527+
Command command = CF_EXPECT(ConstructCommand(construct_cmd_param));
528+
command.RedirectStdIO(Subprocess::StdIOChannel::kStdOut,
529+
Subprocess::StdIOChannel::kStdErr);
530+
SharedFD dev_null = SharedFD::Open("/dev/null", O_RDONLY);
531+
if (dev_null->IsOpen()) {
532+
command.RedirectStdIO(Subprocess::StdIOChannel::kStdIn, dev_null);
533+
} else {
534+
LOG(ERROR) << "Failed to open /dev/null: " << dev_null->StrError();
535+
}
536+
537+
auto symlink_config_res = SymlinkPreviousConfig(group.HomeDir());
538+
if (!symlink_config_res.ok()) {
539+
LOG(ERROR) << "Failed to symlink the config file at system wide home: "
540+
<< symlink_config_res.error();
541+
}
542+
543+
auto set_instance_state = [&group, &instance](cvd::InstanceState state) {
544+
for (auto& inst : group.Instances()) {
545+
if (inst.Id() == instance.Id()) {
546+
inst.SetState(state);
547+
break;
548+
}
549+
}
550+
};
551+
552+
set_instance_state(cvd::INSTANCE_STATE_STARTING);
553+
group.SetStartTime(CvdServerClock::now());
554+
CF_EXPECT(instance_manager_.UpdateInstanceGroup(group));
555+
556+
Result<void> start_res =
557+
LaunchDevice(std::move(command), group, run_cvd_envs, request);
558+
559+
if (!start_res.ok()) {
560+
set_instance_state(cvd::INSTANCE_STATE_BOOT_FAILED);
561+
CF_EXPECT(instance_manager_.UpdateInstanceGroup(group));
562+
return start_res;
563+
}
564+
565+
set_instance_state(cvd::INSTANCE_STATE_RUNNING);
566+
CF_EXPECT(instance_manager_.UpdateInstanceGroup(group));
567+
568+
auto group_json = CF_EXPECT(group.FetchStatus());
569+
std::cout << group_json.toStyledString();
570+
571+
return {};
572+
}
573+
475574
std::vector<HelpParagraph> CvdStartCommandHandler::Description() const {
476575
std::vector<HelpParagraph> description;
477576
description.emplace_back(

base/cvd/cuttlefish/host/commands/cvd/cli/commands/start.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ class CvdStartCommandHandler : public CvdCommandHandler {
4343
bool RequiresDeviceExists() const override { return true; }
4444

4545
private:
46+
Result<void> LaunchSingleInstance(LocalInstance& instance,
47+
LocalInstanceGroup& group,
48+
const CommandRequest& request);
49+
4650
Result<void> LaunchDevice(Command command, LocalInstanceGroup& group,
4751
const cvd_common::Envs& envs,
4852
const CommandRequest& request);

0 commit comments

Comments
 (0)