Make the all application target work in starterd
Instead of restart_all, support restart all. While we are here, start
all, stop all, status all are pretty easy, so let's do those too.
This also cleans up autostart behavior so autostart=false doesn't get
automatically started when start all is issued.
Change-Id: Ia6a980d24f88577da97ead9bb93b25fad4c4b6ee
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/aos/starter/starter_cmd.cc b/aos/starter/starter_cmd.cc
index 5f67c4b..28119a8 100644
--- a/aos/starter/starter_cmd.cc
+++ b/aos/starter/starter_cmd.cc
@@ -23,6 +23,32 @@
{"stop", aos::starter::Command::STOP},
{"restart", aos::starter::Command::RESTART}};
+const aos::Node *MaybeMyNode(const aos::Configuration *configuration) {
+ if (!configuration->has_nodes()) {
+ return nullptr;
+ }
+
+ return aos::configuration::GetMyNode(configuration);
+}
+
+bool ValidApplication(const aos::Configuration *config,
+ std::string_view application_name) {
+ const aos::Node *node = MaybeMyNode(config);
+ const aos::Application *application =
+ aos::configuration::GetApplication(config, node, application_name);
+ if (application == nullptr) {
+ if (node) {
+ std::cout << "Unknown application '" << application_name << "' on node '"
+ << node->name()->string_view() << "'" << std::endl;
+ } else {
+ std::cout << "Unknown application '" << application_name << "'"
+ << std::endl;
+ }
+ return false;
+ }
+ return true;
+}
+
void PrintKey() {
absl::PrintF("%-30s %-8s %-6s %-9s\n", "Name", "State", "PID", "Uptime");
}
@@ -43,8 +69,8 @@
}
}
-bool GetStarterStatus(int argc, char **argv, const aos::Configuration *config) {
- if (argc == 1) {
+// Prints the status for all applications.
+void GetAllStarterStatus(const aos::Configuration *config) {
// Print status for all processes.
const auto optional_status = aos::starter::GetStarterStatus(config);
if (optional_status) {
@@ -58,10 +84,25 @@
} else {
LOG(WARNING) << "No status found";
}
+}
+
+// Handles the "status" command. Returns true if the help message should be
+// printed.
+bool GetStarterStatus(int argc, char **argv, const aos::Configuration *config) {
+ if (argc == 1) {
+ GetAllStarterStatus(config);
} else if (argc == 2) {
// Print status for the specified process.
const auto application_name =
aos::starter::FindApplication(argv[1], config);
+ if (application_name == "all") {
+ GetAllStarterStatus(config);
+ return false;
+ }
+
+ if (!ValidApplication(config, application_name)) {
+ return false;
+ }
auto status = aos::starter::GetStatus(application_name, config);
PrintKey();
PrintApplicationStatus(&status.message(), aos::monotonic_clock::now());
@@ -72,12 +113,63 @@
return false;
}
+// Sends the provided command to all applications. Prints the success text on
+// success, and failure text on failure.
+void InteractWithAll(const aos::Configuration *config,
+ const aos::starter::Command command,
+ std::string_view success_text,
+ std::string_view failure_text) {
+ const auto optional_status = aos::starter::GetStarterStatus(config);
+ if (optional_status) {
+ auto status = *optional_status;
+ const aos::Node *my_node = MaybeMyNode(config);
+ std::vector<std::pair<aos::starter::Command, std::string_view>> commands;
+
+ for (const aos::Application *application : *config->applications()) {
+ // Ignore any applications which aren't supposed to be started on this
+ // node.
+ if (!aos::configuration::ApplicationShouldStart(config, my_node,
+ application)) {
+ continue;
+ }
+
+ const std::string_view application_name =
+ application->name()->string_view();
+ if (!application->autostart()) {
+ const aos::starter::ApplicationStatus *application_status =
+ aos::starter::FindApplicationStatus(status.message(),
+ application_name);
+ if (application_status->state() == aos::starter::State::STOPPED) {
+ std::cout << "Skipping " << application_name
+ << " because it is STOPPED\n";
+ continue;
+ }
+ }
+
+ commands.emplace_back(command, application_name);
+ }
+
+ // Restart each running process
+ if (aos::starter::SendCommandBlocking(commands, config,
+ chrono::seconds(5))) {
+ std::cout << success_text << "all \n";
+ } else {
+ std::cout << failure_text << "all \n";
+ }
+ } else {
+ LOG(WARNING) << "Starter not running";
+ }
+}
+
+// Handles the "start", "stop", and "restart" commands. Returns true if the
+// help message should be printed.
bool InteractWithProgram(int argc, char **argv,
const aos::Configuration *config) {
const char *command_string = argv[0];
if (argc != 2) {
- LOG(ERROR) << "The \"" << command_string
- << "\" command requires an application name as an argument.";
+ LOG(ERROR)
+ << "The \"" << command_string
+ << "\" command requires an application name or 'all' as an argument.";
return true;
}
@@ -85,56 +177,38 @@
CHECK(command_search != kCommandConversions.end())
<< "Internal error: \"" << command_string
<< "\" is not in kCommandConversions.";
-
const aos::starter::Command command = command_search->second;
- const auto application_name = aos::starter::FindApplication(argv[1], config);
+
+ std::string_view success_text;
+ const std::string failure_text =
+ std::string("Failed to ") + std::string(command_string) + " ";
+ switch (command) {
+ case aos::starter::Command::START:
+ success_text = "Successfully started ";
+ break;
+ case aos::starter::Command::STOP:
+ success_text = "Successfully stopped ";
+ break;
+ case aos::starter::Command::RESTART:
+ success_text = "Successfully restarted ";
+ break;
+ }
+
+ const std::string_view application_name =
+ aos::starter::FindApplication(argv[1], config);
+ if (application_name == "all") {
+ InteractWithAll(config, command, success_text, failure_text);
+ return false;
+ }
+ if (!ValidApplication(config, application_name)) {
+ return false;
+ }
+
if (aos::starter::SendCommandBlocking(command, application_name, config,
chrono::seconds(5))) {
- switch (command) {
- case aos::starter::Command::START:
- std::cout << "Successfully started " << application_name << '\n';
- break;
- case aos::starter::Command::STOP:
- std::cout << "Successfully stopped " << application_name << '\n';
- break;
- case aos::starter::Command::RESTART:
- std::cout << "Successfully restarted " << application_name << '\n';
- break;
- }
+ std::cout << success_text << application_name << '\n';
} else {
- std::cout << "Failed to " << command_string << ' ' << application_name
- << '\n';
- }
- return false;
-}
-
-bool RestartAll(int argc, char **, const aos::Configuration *config) {
- if (argc == 1) {
- const auto optional_status = aos::starter::GetStarterStatus(config);
- if (optional_status) {
- auto status = *optional_status;
- for (const aos::starter::ApplicationStatus *app_status :
- *status.message().statuses()) {
- const auto application_name = aos::starter::FindApplication(
- app_status->name()->string_view(), config);
-
- // Restart each running process
-
- if (aos::starter::SendCommandBlocking(aos::starter::Command::RESTART,
- application_name, config,
- chrono::seconds(5))) {
- std::cout << "Successfully restarted " << application_name << '\n';
- } else {
- std::cout << "Failed to restart " << application_name << '\n';
- return true;
- }
- }
- } else {
- LOG(WARNING) << "No processes found";
- }
- } else {
- LOG(ERROR) << "The \"restart_all\" command requires only zero arguments.";
- return true;
+ std::cout << failure_text << application_name << '\n';
}
return false;
}
@@ -151,8 +225,7 @@
kCommands{{"status", GetStarterStatus},
{"start", InteractWithProgram},
{"stop", InteractWithProgram},
- {"restart", InteractWithProgram},
- {"restart_all", RestartAll}};
+ {"restart", InteractWithProgram}};
} // namespace