#include "servers.hpp" #include "server_env.hpp" #include "service_runner.hpp" #include "tableprint.hpp" #include "interactive/interactive.hpp" #include "utils/envmanager.hpp" #include "utils/directories.hpp" #include "services.hpp" #include #include #include #include #include namespace fs = boost::filesystem; namespace dropshell { std::vector get_configured_servers() { std::vector servers; std::string servers_dir = get_local_config_servers_path(); if (servers_dir.empty()) { return servers; } if (!fs::exists(servers_dir)) { std::cerr << "Error: Servers directory not found:" << servers_dir << std::endl; return servers; } for (const auto& entry : fs::directory_iterator(servers_dir)) { if (fs::is_directory(entry)) { std::string server_name = entry.path().filename().string(); server_env env(server_name); if (!env.is_valid()) { std::cerr << "Error: Invalid server environment file: " << server_name << std::endl; continue; } servers.push_back({ server_name, env.get_SSH_HOST(), env.get_SSH_USER(), env.get_SSH_PORT() }); } } return servers; } void list_servers() { auto servers = get_configured_servers(); tableprint tp("All DropShell Servers"); tp.add_row({"Name", "Address", "Health", "Ports"}); for (const auto& server : servers) { std::vector ports_used; std::string serviceticks = ""; std::vector services = get_server_services_info(server.name); for (const auto& service : services) { service_runner ss; if (ss.init(server.name, service.service_name)) serviceticks += ss.healthmark() + " "; else std::cout<<"Error: Failed to initialise service runner for server: ["< ports = ss.get_ports(); ports_used.insert(ports_used.end(), ports.begin(), ports.end()); } // convert ports_used to string std::string ports_used_str = ""; bool first = true; for (const auto& port : ports_used) { if (!first) { ports_used_str += ", "; } ports_used_str += std::to_string(port); first = false; } tp.add_row({server.name, server.ssh_host, serviceticks, ports_used_str}); } tp.print(); } void show_server_details(const std::string& server_name) { server_env env(server_name); if (!env.is_valid()) { std::cerr << "Error: Invalid server environment file: " << server_name << std::endl; return; } //--------------------- // Check if server is reachable via SSH std::string ssh_address = env.get_SSH_HOST(); std::string ssh_user = env.get_SSH_USER(); std::string ssh_port = env.get_SSH_PORT(); if (!ssh_address.empty()) { std::cout << std::endl << "Server Status:" << std::endl; std::cout << std::string(40, '-') << std::endl; // Try to connect to the server std::string cmd = "ssh -o ConnectTimeout=5 " + ssh_user + "@" + ssh_address + " -p " + ssh_port + " 'echo connected' 2>/dev/null"; int result = system(cmd.c_str()); if (result == 0) { std::cout << "Status: Online" << std::endl; // // Get uptime if possible // cmd = "ssh " + ssh_address + " 'uptime' 2>/dev/null"; // int rval = system(cmd.c_str()); // if (rval != 0) { // std::cout << "Error: Failed to get uptime" << std::endl; // } } else { std::cout << "Status: Offline" << std::endl; } } std::cout << std::endl; //--------------------- { std::cout << std::endl; tableprint tp("Server Configuration: " + server_name, true); tp.add_row({"Key", "Value"}); for (const auto& [key, value] : env.get_variables()) { tp.add_row({key, value}); } tp.print(); } //--------------------- // list services, and run healthcheck on each { tableprint tp("Services: " + server_name, false); tp.add_row({"Status", "Service", "Ports"}); std::vector services = get_server_services_info(server_name); for (const auto& service : services) { std::string healthy = "?"; std::vector ports; service_runner ss; if (ss.init(server_name, service.service_name)) { healthy = ss.healthmark(); ports = ss.get_ports(); } bool first = true; std::string ports_str = ""; for (const auto& port : ports) { if (!first) { ports_str += ", "; } ports_str += std::to_string(port); first = false; } tp.add_row({healthy, service.service_name, ports_str}); } // end of for (const auto& service : services) tp.print(); } // end of list services } // end of show_server_details void interactive_mode() { interactive::fullscreen_window iw("DropShell Servers"); iw.set_input_text_display("Loading all servers' status..."); auto servers = get_configured_servers(); std::vector server_names; for (const auto& server : servers) { server_names.push_back(server.name); } list_servers(); while (true) { std::string server_name = iw.set_input_multiple_choice("Select a server", server_names); if (server_name.empty()) { iw.close(); return; } while (!server_name.empty()) { iw.clear_display(); show_server_details(server_name); server_name = iw.set_input_multiple_choice("Select a server", server_names, server_name); } iw.clear_display(); list_servers(); } } } // namespace dropshell