summaryrefslogtreecommitdiffstats
path: root/src/Client/SystemCommands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Client/SystemCommands.cpp')
-rw-r--r--src/Client/SystemCommands.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/Client/SystemCommands.cpp b/src/Client/SystemCommands.cpp
new file mode 100644
index 0000000..5409828
--- /dev/null
+++ b/src/Client/SystemCommands.cpp
@@ -0,0 +1,262 @@
+/*
+ * SystemCommands.cpp
+ *
+ * Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "SystemCommands.h"
+#include "CommandParser.h"
+
+#include <Common/Logger.h>
+#include <Common/RequestManager.h>
+
+#include "Requests/DaemonFSInfoRequest.h"
+#include "Requests/DaemonCommandRequest.h"
+#include "Requests/DaemonStatusRequest.h"
+#include <Common/Requests/FSInfoRequest.h>
+#include <Common/Requests/StatusRequest.h>
+
+#include <iostream>
+
+
+namespace Mad {
+namespace Client {
+
+void SystemCommands::printFSInfo(boost::shared_ptr<const Common::XmlPacket> &packet) {
+ const std::string units[] = {
+ "kB", "MB", "GB", "TB", ""
+ };
+
+ for(size_t i = 0; i < (*packet)["filesystems"].getSize(); ++i) {
+ const Common::XmlPacket::Entry &fs = (*packet)["filesystems"][i];
+
+ unsigned usedUnit = 0, totalUnit = 0;
+
+ float used = fs["usedSize"];
+ float total = fs["totalSize"];
+ float available = fs["availableSize"];
+
+ while(used >= 1024 && !units[usedUnit+1].empty()) {
+ ++usedUnit;
+ used /= 1024;
+ available /= 1024;
+ }
+
+ while(total >= 1024 && !units[totalUnit+1].empty()) {
+ ++totalUnit;
+ total /= 1024;
+ }
+
+
+ std::string name = fs["name"];
+ std::string mountedOn = fs["mountedOn"];
+
+ std::string nameString = mountedOn + " (" + name + ")";
+
+ if(nameString.length() < 32) {
+ nameString.resize(32, ' ');
+ }
+ else {
+ nameString += "\n\t";
+ nameString.resize(nameString.length() + 32, ' ');
+ }
+
+ std::printf("\t%s%.*f%s", nameString.c_str(), (used < 10) ? 2 : 1, used, (usedUnit == totalUnit) ? "" : (" " + units[usedUnit]).c_str());
+ std::printf("/%.*f %s (%.1f%%)\n", (total < 10) ? 2 : 1, total, units[totalUnit].c_str(), std::min(100*used/(used+available), 100.0f));
+ }
+
+ std::printf("\n");
+}
+
+void SystemCommands::printHostStatus(boost::shared_ptr<const Common::XmlPacket> &packet) {
+ unsigned long uptime = (*packet)["uptime"];
+
+ if(uptime) {
+ unsigned long uptime = (*packet)["uptime"];
+
+ unsigned long days = uptime/86400;
+ unsigned long hours = (uptime%86400)/3600;
+ unsigned long minutes = (uptime%3600)/60;
+
+ std::printf("\tUptime:\t\t");
+
+ if(days) std::printf("%lu days ", days);
+
+ std::printf("%lu:%02lu", hours, minutes);
+
+ std::printf(" (load average: %.2f %.2f %.2f, %lu processes)", (float)(*packet)["loadAvg1"], (float)(*packet)["loadAvg5"], (float)(*packet)["loadAvg15"], (unsigned long)(*packet)["nProcesses"]);
+
+ std::printf("\n\n");
+ }
+
+ if((unsigned long)(*packet)["totalMem"] && (unsigned long)(*packet)["freeMem"]) {
+ const std::string units[] = {
+ "kB", "MB", "GB", "TB", ""
+ };
+
+ unsigned unit = 0;
+ float totalMem = (*packet)["totalMem"], usedMem = totalMem-(float)(*packet)["freeMem"];
+
+ while(totalMem >= 1024 && !units[unit+1].empty()) {
+ ++unit;
+ totalMem /= 1024;
+ usedMem /= 1024;
+ }
+
+ std::printf("\tMemory usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str());
+ std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem);
+
+ if((unsigned long)(*packet)["totalSwap"] && (unsigned long)(*packet)["freeSwap"]) {
+ unit = 0;
+ totalMem = (*packet)["totalSwap"]; usedMem = totalMem-(float)(*packet)["freeSwap"];
+
+ while(totalMem >= 1024 && !units[unit+1].empty()) {
+ ++unit;
+ totalMem /= 1024;
+ usedMem /= 1024;
+ }
+
+ std::printf("\tSwap usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str());
+ std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem);
+ }
+
+ std::printf("\n");
+ }
+}
+
+
+void SystemCommands::fsinfoCommand(const std::vector<std::string> &args, Common::Connection *connection) {
+ boost::shared_ptr<Common::Request> request;
+
+ if(args.size() == 1)
+ request = boost::shared_ptr<Common::Requests::FSInfoRequest>(new Common::Requests::FSInfoRequest);
+ else if(args.size() == 2)
+ request = boost::shared_ptr<Requests::DaemonFSInfoRequest>(new Requests::DaemonFSInfoRequest(args[1]));
+ else {
+ Common::Logger::logf(Common::Logger::ERROR, "%s: Too many arguments.", args[0].c_str());
+ CommandParser::printUsage("fsinfo");
+ return;
+ }
+
+ Common::RequestManager::get()->sendRequest(connection, request);
+ request->wait();
+
+ std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult();
+
+ if(!result.first || result.second) {
+ Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str());
+ }
+ else {
+ if(args.size() == 1)
+ std::cout << "Server file system usage:" << std::endl;
+ else
+ std::cout << "Host file system usage:" << std::endl;
+
+ printFSInfo(result.first);
+ }
+}
+
+void SystemCommands::rebootCommand(const std::vector<std::string> &args, Common::Connection *connection) {
+ if(args.size() < 2) {
+ Common::Logger::logf(Common::Logger::ERROR, "%s: No host given.", args[0].c_str());
+ CommandParser::printUsage("reboot");
+ return;
+ }
+
+ std::map<std::string, Common::HostInfo> hosts = CommandParser::parseHostList(std::vector<std::string>(args.begin()+1, args.end()), true);
+
+ std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> > requests;
+
+ for(std::map<std::string, Common::HostInfo>::iterator host = hosts.begin(); host != hosts.end(); ++host) {
+ boost::shared_ptr<Requests::DaemonCommandRequest> request(new Requests::DaemonCommandRequest(host->first, true));
+ Common::RequestManager::get()->sendRequest(connection, request);
+
+ requests.push_back(request);
+ }
+
+ for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request)
+ (*request)->wait();
+
+ for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) {
+ std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = (*request)->getResult();
+
+ if(result.second)
+ Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str());
+ }
+}
+
+void SystemCommands::shutdownCommand(const std::vector<std::string> &args, Common::Connection *connection) {
+ if(args.size() < 2) {
+ Common::Logger::logf(Common::Logger::ERROR, "%s: No host given.", args[0].c_str());
+ CommandParser::printUsage("shutdown");
+ return;
+ }
+
+ std::map<std::string, Common::HostInfo> hosts = CommandParser::parseHostList(std::vector<std::string>(args.begin()+1, args.end()), true);
+
+ std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> > requests;
+
+ for(std::map<std::string, Common::HostInfo>::iterator host = hosts.begin(); host != hosts.end(); ++host) {
+ boost::shared_ptr<Requests::DaemonCommandRequest> request(new Requests::DaemonCommandRequest(host->first, false));
+ Common::RequestManager::get()->sendRequest(connection, request);
+
+ requests.push_back(request);
+ }
+
+ for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request)
+ (*request)->wait();
+
+ for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) {
+ std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = (*request)->getResult();
+
+ if(result.second)
+ Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str());
+ }
+}
+
+void SystemCommands::statusCommand(const std::vector<std::string> &args, Common::Connection *connection) {
+ boost::shared_ptr<Common::Request> request;
+
+ if(args.size() == 1)
+ request = boost::shared_ptr<Common::Requests::StatusRequest>(new Common::Requests::StatusRequest);
+ else if(args.size() == 2)
+ request = boost::shared_ptr<Requests::DaemonStatusRequest>(new Requests::DaemonStatusRequest(args[1]));
+ else {
+ Common::Logger::logf(Common::Logger::ERROR, "%s: Too many arguments.", args[0].c_str());
+ CommandParser::printUsage("status");
+ return;
+ }
+
+ Common::RequestManager::get()->sendRequest(connection, request);
+ request->wait();
+
+ std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult();
+
+ if(!result.first || result.second) {
+ Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str());
+ }
+ else {
+ if(args.size() == 1)
+ std::cout << "Server status:" << std::endl;
+ else
+ std::cout << "Host status:" << std::endl;
+
+ printHostStatus(result.first);
+ }
+}
+
+}
+}