@@ -159,12 +159,14 @@ int StopInstance(const CuttlefishConfig& config,
159159struct FlagVaules {
160160 std::int32_t wait_for_launcher;
161161 bool clear_instance_dirs;
162+ std::vector<unsigned > instance_nums;
162163 bool helpxml;
163164};
164165
165166FlagVaules GetFlagValues (int argc, char ** argv) {
166167 std::int32_t wait_for_launcher = 5 ;
167168 bool clear_instance_dirs = false ;
169+ std::vector<unsigned > instance_nums;
168170 std::vector<Flag> flags;
169171 flags.emplace_back (
170172 GflagsCompatFlag (" wait_for_launcher" , wait_for_launcher)
@@ -174,6 +176,9 @@ FlagVaules GetFlagValues(int argc, char** argv) {
174176 GflagsCompatFlag (" clear_instance_dirs" , clear_instance_dirs)
175177 .Help (" If provided, deletes the instance dir after attempting to "
176178 " stop each instance." ));
179+ flags.emplace_back (
180+ GflagsCompatFlag (" instance_nums" , instance_nums)
181+ .Help (" Comma-separated list of instance numbers to stop." ));
177182 flags.emplace_back (HelpFlag (flags));
178183 bool helpxml = false ;
179184 flags.emplace_back (HelpXmlFlag (flags, std::cout, helpxml));
@@ -182,22 +187,48 @@ FlagVaules GetFlagValues(int argc, char** argv) {
182187 auto parse_res = ConsumeFlags (flags, args);
183188 CHECK (parse_res.ok () || helpxml) << " Could not process command line flags." ;
184189
185- return {wait_for_launcher, clear_instance_dirs, helpxml};
190+ return {wait_for_launcher, clear_instance_dirs, instance_nums, helpxml};
186191}
187192
188193int StopCvdMain (const std::int32_t wait_for_launcher,
189- const bool clear_instance_dirs) {
194+ const bool clear_instance_dirs,
195+ const std::vector<unsigned >& instance_nums) {
190196 auto config = CuttlefishConfig::Get ();
191197 if (!config) {
192198 LOG (ERROR ) << " Failed to obtain config object" ;
193199 return FallBackStop (FallbackDirs ());
194200 }
195201
202+ std::set<unsigned > instance_ids (instance_nums.begin (), instance_nums.end ());
203+
196204 int exit_code = 0 ;
197205 auto instances = config->Instances ();
206+
207+ if (!instance_ids.empty () && !instances.empty ()) {
208+ unsigned first_instance_id;
209+ if (absl::SimpleAtoi (instances[0 ].id (), &first_instance_id)) {
210+ if (instance_ids.count (first_instance_id) > 0 &&
211+ instance_ids.size () < instances.size ()) {
212+ LOG (ERROR ) << " Stopping the first instance (ID: " << first_instance_id
213+ << " ) is not allowed while other instances are remaining. "
214+ << " Stop the entire group instead." ;
215+ return 1 ;
216+ }
217+ }
218+ }
219+
198220 std::vector<std::future<int >> exit_state_futures;
199221 exit_state_futures.reserve (instances.size ());
200222 for (const auto & instance : instances) {
223+ unsigned id;
224+ if (!absl::SimpleAtoi (instance.id (), &id)) {
225+ LOG (ERROR ) << " Failed to parse instance ID \" " << instance.id () << " \" as unsigned" ;
226+ exit_code |= 1 ;
227+ continue ;
228+ }
229+ if (!instance_ids.empty () && instance_ids.count (id) == 0 ) {
230+ continue ;
231+ }
201232 std::future<int > exit_code_from_thread = std::async (
202233 std::launch::async,
203234 [&instance, &config, &wait_for_launcher,
@@ -223,7 +254,7 @@ int StopCvdMain(const std::int32_t wait_for_launcher,
223254} // namespace cuttlefish
224255
225256int main (int argc, char ** argv) {
226- const auto [wait_for_launcher, clear_instance_dirs, helpxml] =
257+ const auto [wait_for_launcher, clear_instance_dirs, instance_nums, helpxml] =
227258 cuttlefish::GetFlagValues (argc, argv);
228259 cuttlefish::LogToStderr ();
229260
@@ -244,5 +275,5 @@ int main(int argc, char** argv) {
244275 cuttlefish::MetricsReceiver::LogMetricsVMStop ();
245276 }
246277
247- return cuttlefish::StopCvdMain (wait_for_launcher, clear_instance_dirs);
278+ return cuttlefish::StopCvdMain (wait_for_launcher, clear_instance_dirs, instance_nums );
248279}
0 commit comments