/* * SystemCommands.cpp * * Copyright (C) 2009 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "SystemCommands.h" #include "Application.h" #include "CommandParser.h" #include #include "Requests/DaemonFSInfoRequest.h" #include "Requests/DaemonCommandRequest.h" #include "Requests/DaemonStatusRequest.h" #include #include #include #include namespace Mad { namespace Client { void SystemCommands::printFSInfo(boost::shared_ptr &packet) { const Core::String units[] = { "kB", "MB", "GB", "TB", "" }; const Common::XmlData::List *list = packet->getList("filesystems"); if(list) { for(Common::XmlData::List::const_iterator fs = list->begin(); fs != list->end(); ++fs) { unsigned usedUnit = 0, totalUnit = 0; float used = fs->get("usedSize"); float total = fs->get("totalSize"); float available = fs->get("availableSize"); while(used >= 1024 && !units[usedUnit+1].isEmpty()) { ++usedUnit; used /= 1024; available /= 1024; } while(total >= 1024 && !units[totalUnit+1].isEmpty()) { ++totalUnit; total /= 1024; } Core::String name = fs->get("name"); Core::String mountedOn = fs->get("mountedOn"); Core::String nameString = mountedOn + " (" + name + ")"; if(nameString.length() < 32) { while(nameString.length() < 32) nameString.append(' '); } else { nameString += "\n\t"; for(int i = 0; i < 32; ++i) nameString.append(' '); } float percent = 100*used/(used+available); if(percent > 100) percent = 100; std::printf("\t%s%.*f%s", nameString.toLocale().c_str(), (used < 10) ? 2 : 1, used, (usedUnit == totalUnit) ? "" : Core::String(" " + units[usedUnit]).toLocale().c_str()); std::printf("/%.*f %s (%.1f%%)\n", (total < 10) ? 2 : 1, total, units[totalUnit].toLocale().c_str(), percent); } } std::printf("\n"); } void SystemCommands::printHostStatus(boost::shared_ptr &packet) { unsigned long uptime = packet->get("uptime"); if(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)", packet->get("loadAvg1"), packet->get("loadAvg5"), packet->get("loadAvg15"), packet->get("nProcesses")); std::printf("\n\n"); } float totalMem = packet->get("totalMem"); float freeMem = packet->get("freeMem"); if(totalMem && freeMem) { const Core::String units[] = { "kB", "MB", "GB", "TB", "" }; unsigned unit = 0; float usedMem = totalMem-freeMem; while(totalMem >= 1024 && !units[unit+1].isEmpty()) { ++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].toLocale().c_str()); std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); totalMem = packet->get("totalSwap"); freeMem = packet->get("freeSwap"); if(totalMem && freeMem) { unit = 0; usedMem = totalMem-freeMem; while(totalMem >= 1024 && !units[unit+1].isEmpty()) { ++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].toLocale().c_str()); std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); } std::printf("\n"); } } void SystemCommands::fsinfoCommand(CommandParser *commandParser, const std::vector &args) { boost::shared_ptr request; if(args.size() == 1) request = boost::shared_ptr(new Common::Requests::FSInfoRequest(commandParser->application)); else if(args.size() == 2) request = boost::shared_ptr(new Requests::DaemonFSInfoRequest(commandParser->application, args[1])); else { std::cerr << args[0] << ": Too many arguments." << std::endl; commandParser->printUsage("fsinfo"); return; } commandParser->application->getRequestManager()->sendRequest(commandParser->connection, request); request->wait(); std::pair, Core::Exception> result = request->getResult(); if(!result.first || result.second) { std::cerr << "An error occurred during your request: " << result.second.what() << "." << std::endl; } 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(CommandParser *commandParser, const std::vector &args) { if(args.size() < 2) { std::cerr << args[0] << ": No host given." << std::endl; commandParser->printUsage("reboot"); return; } std::map hosts = commandParser->parseHostList(std::vector(args.begin()+1, args.end()), true); std::vector > requests; for(std::map::iterator host = hosts.begin(); host != hosts.end(); ++host) { boost::shared_ptr request(new Requests::DaemonCommandRequest(commandParser->application, host->first, true)); commandParser->application->getRequestManager()->sendRequest(commandParser->connection, request); requests.push_back(request); } for(std::vector >::iterator request = requests.begin(); request != requests.end(); ++request) (*request)->wait(); for(std::vector >::iterator request = requests.begin(); request != requests.end(); ++request) { std::pair, Core::Exception> result = (*request)->getResult(); if(result.second) std::cerr << "An error occurred during your request: " << result.second.what() << "." << std::endl; } } void SystemCommands::shutdownCommand(CommandParser *commandParser, const std::vector &args) { if(args.size() < 2) { std::cerr << args[0] << ": No host given." << std::endl; commandParser->printUsage("shutdown"); return; } std::map hosts = commandParser->parseHostList(std::vector(args.begin()+1, args.end()), true); std::vector > requests; for(std::map::iterator host = hosts.begin(); host != hosts.end(); ++host) { boost::shared_ptr request(new Requests::DaemonCommandRequest(commandParser->application, host->first, false)); commandParser->application->getRequestManager()->sendRequest(commandParser->connection, request); requests.push_back(request); } for(std::vector >::iterator request = requests.begin(); request != requests.end(); ++request) (*request)->wait(); for(std::vector >::iterator request = requests.begin(); request != requests.end(); ++request) { std::pair, Core::Exception> result = (*request)->getResult(); if(result.second) std::cerr << "An error occurred during your request: " << result.second.what() << "." << std::endl; } } void SystemCommands::statusCommand(CommandParser *commandParser, const std::vector &args) { boost::shared_ptr request; if(args.size() == 1) request = boost::shared_ptr(new Common::Requests::StatusRequest(commandParser->application)); else if(args.size() == 2) request = boost::shared_ptr(new Requests::DaemonStatusRequest(commandParser->application, args[1])); else { std::cerr << args[0] << ": Too many arguments." << std::endl; commandParser->printUsage("status"); return; } commandParser->application->getRequestManager()->sendRequest(commandParser->connection, request); request->wait(); std::pair, Core::Exception> result = request->getResult(); if(!result.first || result.second) { std::cerr << "An error occurred during your request: " << result.second.what() << "." << std::endl; } else { if(args.size() == 1) std::cout << "Server status:" << std::endl; else std::cout << "Host status:" << std::endl; printHostStatus(result.first); } } } }