//------------------------------------------------------------------------------ // @file: IoCmd.cc // @author: Fabio Luchetti - CERN //------------------------------------------------------------------------------ /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2018 CERN/Switzerland * * * * 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 .* ************************************************************************/ #include "IoCmd.hh" #include "mgm/proc/ProcInterface.hh" #include "mgm/XrdMgmOfs.hh" #include "mgm/Iostat.hh" EOSMGMNAMESPACE_BEGIN //------------------------------------------------------------------------------ // Method implementing the specific behavior of the command executed //------------------------------------------------------------------------------ eos::console::ReplyProto IoCmd::ProcessRequest() noexcept { eos::console::ReplyProto reply; eos::console::IoProto io = mReqProto.io(); switch (mReqProto.io().subcmd_case()) { case eos::console::IoProto::kStat: StatSubcmd(io.stat(), reply); break; case eos::console::IoProto::kEnable: EnableSubcmd(io.enable(), reply); break; case eos::console::IoProto::kReport: ReportSubcmd(io.report(), reply); break; case eos::console::IoProto::kNs: NsSubcmd(io.ns(), reply); break; default: reply.set_retc(EINVAL); reply.set_std_err("error: not supported"); } return reply; } //------------------------------------------------------------------------------ // Execute stat subcommand //------------------------------------------------------------------------------ void IoCmd::StatSubcmd(const eos::console::IoProto_StatProto& stat, eos::console::ReplyProto& reply) { XrdOucString out = ""; bool monitoring = stat.monitoring() || WantsJsonOutput(); // If nothing is selected, we show the summary information if (!(stat.apps() || stat.domain() || stat.top() || stat.details())) { gOFS->IoStats->PrintOut(out, true, stat.details(), monitoring, stat.numerical(), stat.top(), stat.domain(), stat.apps(), stat.sample_stat(), stat.time_ago(), stat.time_interval()); } else { gOFS->IoStats->PrintOut(out, stat.summary(), stat.details(), monitoring, stat.numerical(), stat.top(), stat.domain(), stat.apps(), stat.sample_stat(), stat.time_ago(), stat.time_interval()); } if (WantsJsonOutput()) { out = ResponseToJsonString(out.c_str()).c_str(); } reply.set_std_out(out.c_str()); reply.set_retc(0); } //------------------------------------------------------------------------------ // Execute enable subcommand //------------------------------------------------------------------------------ void IoCmd::EnableSubcmd(const eos::console::IoProto_EnableProto& enable, eos::console::ReplyProto& reply) { std::ostringstream out, err; int ret_c = 0; if (enable.switchx()) { // enable if ((!enable.reports()) && (!enable.namespacex())) { if (enable.upd_address().length()) { if (gOFS->IoStats->AddUdpTarget(enable.upd_address().c_str())) { out << "success: enabled IO udp target " << enable.upd_address(); } else { err << "error: IO udp target was not configured " << enable.upd_address(); ret_c = EINVAL; } } else { if (enable.popularity()) { // Always enable collection otherwise we don't get anything for // popularity reporting gOFS->IoStats->StartCollection(); if (gOFS->IoStats->StartPopularity()) { out << "success: enabled IO popularity collection"; } else { err << "error: IO popularity collection already enabled"; ret_c = EINVAL; } } else { if (gOFS->IoStats->StartCollection()) { out << "success: enabled IO report collection"; } else { err << "error: IO report collection already enabled"; ret_c = EINVAL; } } } } else { // disable if (enable.reports()) { if (gOFS->IoStats->StartReport()) { out << "success: enabled IO report store"; } else { err << "error: IO report store already enabled"; ret_c = EINVAL; } } if (enable.namespacex()) { if (gOFS->IoStats->StartReportNamespace()) { out << "success: enabled IO report namespace"; } else { err << "error: IO report namespace already enabled"; ret_c = EINVAL; } } } } else { if ((!enable.reports()) && (!enable.namespacex())) { if (enable.upd_address().length()) { if (gOFS->IoStats->RemoveUdpTarget(enable.upd_address().c_str())) { out << "success: disabled IO udp target " << enable.upd_address(); } else { err << "error: IO udp target was not configured " << enable.upd_address(); ret_c = EINVAL; } } else { if (enable.popularity()) { if (gOFS->IoStats->StopPopularity()) { out << "success: disabled IO popularity collection"; } else { err << "error: IO popularity collection already disabled"; ret_c = EINVAL; } } else { if (gOFS->IoStats->StopCollection()) { out << "success: disabled IO report collection"; } else { err << "error: IO report collection already disabled"; ret_c = EINVAL; } } } } else { if (enable.reports()) { if (gOFS->IoStats->StopReport()) { out << "success: disabled IO report store"; } else { err << "error: IO report store already disabled"; ret_c = EINVAL; } } if (enable.namespacex()) { if (gOFS->IoStats->StopReportNamespace()) { out << "success: disabled IO report namespace"; } else { err << "error: IO report namespace already disabled"; ret_c = EINVAL; } } } } reply.set_std_out(out.str()); reply.set_std_err(err.str()); reply.set_retc(ret_c); } //------------------------------------------------------------------------------ // Execute report subcommand //------------------------------------------------------------------------------ void IoCmd::ReportSubcmd(const eos::console::IoProto_ReportProto& report, eos::console::ReplyProto& reply) { XrdOucString out {""}; XrdOucString err {""}; if (mVid.uid != 0) { reply.set_std_err("error: you have to take role 'root' to execute this command"); reply.set_retc(EPERM); return; } if (gOFS->IoStats) { gOFS->IoStats->PrintNsReport(report.path().c_str(), out); } reply.set_std_out(out.c_str()); reply.set_std_err(err.c_str()); reply.set_retc(0); } //------------------------------------------------------------------------------ // Execute ns subcommand //------------------------------------------------------------------------------ void IoCmd::NsSubcmd(const eos::console::IoProto_NsProto& ns, eos::console::ReplyProto& reply) { std::string option; if (ns.monitoring() || WantsJsonOutput()) { option += "-m"; } if (ns.rank_by_byte()) { option += "-b"; } if (ns.rank_by_access()) { option += "-n"; } if (ns.last_week()) { option += "-w"; } if (ns.hotfiles()) { option += "-f"; } switch (ns.count()) { case eos::console::IoProto_NsProto::ONEHUNDRED: option += "-100"; break; case eos::console::IoProto_NsProto::ONETHOUSAND: option += "-1000"; break; case eos::console::IoProto_NsProto::TENTHOUSAND: option += "-10000"; break; case eos::console::IoProto_NsProto::ALL: option += "-a"; break; default : // NONE break; } XrdOucString out = ""; gOFS->IoStats->PrintNsPopularity(out, option.c_str()); if (WantsJsonOutput()) { out = ResponseToJsonString(out.c_str()).c_str(); } reply.set_std_out(out.c_str()); reply.set_retc(0); } EOSMGMNAMESPACE_END