• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 
17 #include <inttypes.h>
18 #include <limits.h>
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <signal.h>
28 
29 #include <algorithm>
30 #include <cstdlib>
31 #include <fstream>
32 #include <iomanip>
33 #include <memory>
34 #include <sstream>
35 #include <string>
36 #include <vector>
37 
38 #include <gflags/gflags.h>
39 #include <android-base/logging.h>
40 
41 #include "common/libs/fs/shared_buf.h"
42 #include "common/libs/fs/shared_fd.h"
43 #include "common/libs/fs/shared_select.h"
44 #include "common/libs/utils/environment.h"
45 #include "host/commands/run_cvd/runner_defs.h"
46 #include "host/libs/config/cuttlefish_config.h"
47 #include "host/libs/vm_manager/vm_manager.h"
48 
49 DEFINE_int32(instance_num, cuttlefish::GetInstance(),
50              "Which instance to powerwash");
51 
52 DEFINE_int32(wait_for_launcher, 30,
53              "How many seconds to wait for the launcher to respond to the status "
54              "command. A value of zero means wait indefinetly");
55 
56 DEFINE_int32(boot_timeout, 1000, "How many seconds to wait for the device to "
57                                  "reboot.");
58 
59 namespace cuttlefish {
60 namespace {
61 
PowerwashCvdMain(int argc,char ** argv)62 int PowerwashCvdMain(int argc, char** argv) {
63   ::android::base::InitLogging(argv, android::base::StderrLogger);
64   google::ParseCommandLineFlags(&argc, &argv, true);
65 
66   auto config = CuttlefishConfig::Get();
67   if (!config) {
68     LOG(ERROR) << "Failed to obtain config object";
69     return 1;
70   }
71 
72   auto instance = config->ForInstance(FLAGS_instance_num);
73   auto monitor_path = instance.launcher_monitor_socket_path();
74   if (monitor_path.empty()) {
75     LOG(ERROR) << "No path to launcher monitor found";
76     return 2;
77   }
78   auto monitor_socket = SharedFD::SocketLocalClient(
79       monitor_path.c_str(), false, SOCK_STREAM, FLAGS_wait_for_launcher);
80   if (!monitor_socket->IsOpen()) {
81     LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
82                << ": " << monitor_socket->StrError();
83     return 3;
84   }
85   auto request = LauncherAction::kPowerwash;
86   auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
87   if (bytes_sent < 0) {
88     LOG(ERROR) << "Error sending launcher monitor the status command: "
89                << monitor_socket->StrError();
90     return 4;
91   }
92   // Perform a select with a timeout to guard against launcher hanging
93   SharedFDSet read_set;
94   read_set.Set(monitor_socket);
95   struct timeval timeout = {FLAGS_wait_for_launcher, 0};
96   int selected = Select(&read_set, nullptr, nullptr,
97                         FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout);
98   if (selected < 0){
99     LOG(ERROR) << "Failed communication with the launcher monitor: "
100                << strerror(errno);
101     return 5;
102   }
103   if (selected == 0) {
104     LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
105     return 6;
106   }
107   LauncherResponse response;
108   auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
109   if (bytes_recv < 0) {
110     LOG(ERROR) << "Error receiving response from launcher monitor: "
111                << monitor_socket->StrError();
112     return 7;
113   }
114   LOG(INFO) << "Requesting powerwash";
115   if (response != LauncherResponse::kSuccess) {
116     LOG(ERROR) << "Received '" << static_cast<char>(response)
117                << "' response from launcher monitor for powerwash request";
118     return 8;
119   }
120   LOG(INFO) << "Waiting for device to boot up again";
121 
122   read_set.Set(monitor_socket);
123   timeout = {FLAGS_boot_timeout, 0};
124   selected = Select(&read_set, nullptr, nullptr,
125                     FLAGS_boot_timeout <= 0 ? nullptr : &timeout);
126   if (selected < 0){
127     LOG(ERROR) << "Failed communication with the launcher monitor: "
128                << strerror(errno);
129     return 5;
130   }
131   if (selected == 0) {
132     LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
133     return 6;
134   }
135 
136   RunnerExitCodes exit_code;
137   bytes_recv = ReadExactBinary(monitor_socket, &exit_code);
138   if (bytes_recv < 0) {
139     LOG(ERROR) << "Error in stream response: " << monitor_socket->StrError();
140     return 9;
141   } else if (bytes_recv == 0) {
142     LOG(ERROR) << "Launcher socket closed unexpectedly";
143     return 10;
144   } else if (bytes_recv != sizeof(exit_code)) {
145     LOG(ERROR) << "Launcher response was too short";
146     return 11;
147   } else if (exit_code == RunnerExitCodes::kVirtualDeviceBootFailed) {
148     LOG(ERROR) << "Boot failed";
149     return 12;
150   } else if (exit_code != RunnerExitCodes::kSuccess) {
151     LOG(ERROR) << "Unknown response: " << (int) exit_code;
152     return 13;
153   }
154   LOG(INFO) << "Powerwash successful";
155   return 0;
156 }
157 
158 } // namespace
159 } // namespace cuttlefish
160 
main(int argc,char ** argv)161 int main(int argc, char** argv) {
162   return cuttlefish::PowerwashCvdMain(argc, argv);
163 }
164