1 //
2 // Copyright (C) 2021 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "host/libs/vm_manager/crosvm_builder.h"
17
18 #include <android-base/logging.h>
19
20 #include <string>
21
22 #include "common/libs/utils/network.h"
23 #include "common/libs/utils/subprocess.h"
24 #include "host/libs/config/cuttlefish_config.h"
25 #include "host/libs/config/known_paths.h"
26
27 namespace cuttlefish {
28
CrosvmBuilder()29 CrosvmBuilder::CrosvmBuilder() : command_("crosvm") {}
30
ApplyProcessRestarter(const std::string & crosvm_binary,int exit_code)31 void CrosvmBuilder::ApplyProcessRestarter(const std::string& crosvm_binary,
32 int exit_code) {
33 command_.SetExecutableAndName(ProcessRestarterBinary());
34 command_.AddParameter("-when_exited_with_code=", exit_code);
35 command_.AddParameter("--");
36 command_.AddParameter(crosvm_binary);
37 // Flag allows exit codes other than 0 or 1, must be before command argument
38 command_.AddParameter("--extended-status");
39 }
40
AddControlSocket(const std::string & control_socket,const std::string & executable_path)41 void CrosvmBuilder::AddControlSocket(const std::string& control_socket,
42 const std::string& executable_path) {
43 command_.SetStopper([executable_path, control_socket](Subprocess* proc) {
44 Command stop_cmd(executable_path);
45 stop_cmd.AddParameter("stop");
46 stop_cmd.AddParameter(control_socket);
47 if (stop_cmd.Start().Wait() == 0) {
48 return StopperResult::kStopSuccess;
49 }
50 LOG(WARNING) << "Failed to stop VMM nicely, attempting to KILL";
51 return KillSubprocess(proc) == StopperResult::kStopSuccess
52 ? StopperResult::kStopCrash
53 : StopperResult::kStopFailure;
54 });
55 command_.AddParameter("--socket=", control_socket);
56 }
57
AddHvcSink()58 void CrosvmBuilder::AddHvcSink() {
59 command_.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num_,
60 ",type=sink");
61 }
AddHvcReadOnly(const std::string & output,bool console)62 void CrosvmBuilder::AddHvcReadOnly(const std::string& output, bool console) {
63 command_.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num_,
64 ",type=file,path=", output,
65 console ? ",console=true" : "");
66 }
AddHvcReadWrite(const std::string & output,const std::string & input)67 void CrosvmBuilder::AddHvcReadWrite(const std::string& output,
68 const std::string& input) {
69 command_.AddParameter("--serial=hardware=virtio-console,num=", ++hvc_num_,
70 ",type=file,path=", output, ",input=", input);
71 }
72
AddReadOnlyDisk(const std::string & path)73 void CrosvmBuilder::AddReadOnlyDisk(const std::string& path) {
74 command_.AddParameter("--disk=", path);
75 }
76
AddReadWriteDisk(const std::string & path)77 void CrosvmBuilder::AddReadWriteDisk(const std::string& path) {
78 command_.AddParameter("--rwdisk=", path);
79 }
80
AddSerialSink()81 void CrosvmBuilder::AddSerialSink() {
82 command_.AddParameter("--serial=hardware=serial,num=", ++serial_num_,
83 ",type=sink");
84 }
AddSerialConsoleReadOnly(const std::string & output)85 void CrosvmBuilder::AddSerialConsoleReadOnly(const std::string& output) {
86 command_.AddParameter("--serial=hardware=serial,num=", ++serial_num_,
87 ",type=file,path=", output, ",earlycon=true");
88 }
AddSerialConsoleReadWrite(const std::string & output,const std::string & input,bool earlycon)89 void CrosvmBuilder::AddSerialConsoleReadWrite(const std::string& output,
90 const std::string& input,
91 bool earlycon) {
92 command_.AddParameter("--serial=hardware=serial,num=", ++serial_num_,
93 ",type=file,path=", output, ",input=", input,
94 earlycon ? ",earlycon=true" : "");
95 }
AddSerial(const std::string & output,const std::string & input)96 void CrosvmBuilder::AddSerial(const std::string& output,
97 const std::string& input) {
98 command_.AddParameter("--serial=hardware=serial,num=", ++serial_num_,
99 ",type=file,path=", output, ",input=", input);
100 }
101
AddTap(const std::string & tap_name)102 SharedFD CrosvmBuilder::AddTap(const std::string& tap_name) {
103 auto tap_fd = OpenTapInterface(tap_name);
104 if (tap_fd->IsOpen()) {
105 command_.AddParameter("--net=tap-fd=", tap_fd);
106 } else {
107 LOG(ERROR) << "Unable to connect to \"" << tap_name
108 << "\": " << tap_fd->StrError();
109 }
110 return tap_fd;
111 }
112
AddTap(const std::string & tap_name,const std::string & mac)113 SharedFD CrosvmBuilder::AddTap(const std::string& tap_name, const std::string& mac) {
114 auto tap_fd = OpenTapInterface(tap_name);
115 if (tap_fd->IsOpen()) {
116 command_.AddParameter("--net=tap-fd=", tap_fd, ",mac=\"", mac, "\"");
117 } else {
118 LOG(ERROR) << "Unable to connect to \"" << tap_name
119 << "\": " << tap_fd->StrError();
120 }
121 return tap_fd;
122 }
123
HvcNum()124 int CrosvmBuilder::HvcNum() { return hvc_num_; }
125
Cmd()126 Command& CrosvmBuilder::Cmd() { return command_; }
127
128 } // namespace cuttlefish
129