// ---------------------------------------------------------------------- // File: com_geosched.cc // Author: Geoffray Adde - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 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 "console/ConsoleMain.hh" #include "common/ParseUtils.hh" #include "common/RWMutex.hh" #include "common/StringTokenizer.hh" #include #include /*----------------------------------------------------------------------------*/ /* Namespace Interface */ int com_geosched(char* arg1) { eos::common::StringTokenizer subtokenizer(arg1); subtokenizer.GetLine(); XrdOucString cmd = subtokenizer.GetToken(); std::set supportedParam = {"skipSaturatedAccess", "skipSaturatedDrnAccess", "skipSaturatedBlcAccess", "plctDlScorePenalty", "plctUlScorePenalty", "accessDlScorePenalty", "accessUlScorePenalty", "fillRatioLimit", "fillRatioCompTol", "saturationThres", "timeFrameDurationMs", "penaltyUpdateRate", "proxyCloseToFs" }; XrdOucString in = ""; if (wants_help(arg1)) { goto com_geosched_usage; } if ((cmd != "show") && (cmd != "set") && (cmd != "updater") && (cmd != "forcerefresh") && (cmd != "disabled") && (cmd != "access")) { goto com_geosched_usage; } in = "mgm.cmd=geosched"; if (cmd == "show") { XrdOucString subcmd = subtokenizer.GetToken(); if (subcmd == "-c") { in += "&mgm.usecolors=1"; subcmd = subtokenizer.GetToken(); } else if (subcmd == "-m") { in += "&mgm.monitoring=1"; subcmd = subtokenizer.GetToken(); } if ((subcmd != "tree") && (subcmd != "snapshot") && (subcmd != "state") && (subcmd != "param")) { goto com_geosched_usage; } if (subcmd == "state") { in += "&mgm.subcmd=showstate"; subcmd = subtokenizer.GetToken(); if (subcmd == "-m") { in += "&mgm.monitoring=1"; } } if (subcmd == "param") { in += "&mgm.subcmd=showparam"; } if (subcmd == "tree") { in += "&mgm.subcmd=showtree"; in += "&mgm.schedgroup="; XrdOucString group = subtokenizer.GetToken(); if (group.length()) { in += group; } } if (subcmd == "snapshot") { in += "&mgm.subcmd=showsnapshot"; in += "&mgm.schedgroup="; XrdOucString group = subtokenizer.GetToken(); if (group.length()) { in += group; } in += "&mgm.optype="; XrdOucString optype = subtokenizer.GetToken(); if (optype.length()) { in += optype; } } } if (cmd == "set") { XrdOucString parameter = subtokenizer.GetToken(); if (!parameter.length()) { fprintf(stderr, "Error: parameter name is not provided\n"); goto com_geosched_usage; } if (supportedParam.find(parameter.c_str()) == supportedParam.end()) { fprintf(stderr, "Error: parameter %s not supported\n", parameter.c_str()); return 0; } XrdOucString index = subtokenizer.GetToken(); XrdOucString value = subtokenizer.GetToken(); if (!index.length()) { fprintf(stderr, "Error: value is not provided\n"); goto com_geosched_usage; } if (!value.length()) { value = index; index = "-1"; } double didx = 0.0; if (!sscanf(value.c_str(), "%lf", &didx)) { fprintf(stderr, "Error: parameter %s should have a numeric value, %s was provided\n", parameter.c_str(), value.c_str()); return 0; } if (!XrdOucString(index.c_str()).isdigit()) { fprintf(stderr, "Error: index for parameter %s should have a numeric value, %s was provided\n", parameter.c_str(), index.c_str()); return 0; } in += "&mgm.subcmd=set"; in += "&mgm.param="; in += parameter.c_str(); in += "&mgm.paramidx="; in += index.c_str(); in += "&mgm.value="; in += value.c_str(); } if (cmd == "updater") { XrdOucString subcmd = subtokenizer.GetToken(); if (subcmd == "pause") { in += "&mgm.subcmd=updtpause"; } if (subcmd == "resume") { in += "&mgm.subcmd=updtresume"; } } if (cmd == "forcerefresh") { in += "&mgm.subcmd=forcerefresh"; } if (cmd == "disabled") { XrdOucString subcmd = subtokenizer.GetToken(); XrdOucString geotag, group, optype; if ((subcmd != "add") && (subcmd != "rm") && (subcmd != "show")) { goto com_geosched_usage; } geotag = subtokenizer.GetToken(); optype = subtokenizer.GetToken(); group = subtokenizer.GetToken(); if (!group.length() || !optype.length() || !geotag.length()) { goto com_geosched_usage; } std::string sgroup(group.c_str()), soptype(optype.c_str()), sgeotag(geotag.c_str()); const char fbdChars[] = "&/,;%$#@!*"; auto fbdMatch = sgroup.find_first_of(fbdChars); if (fbdMatch != std::string::npos && !(sgroup == "*")) { fprintf(stdout, "illegal character %c detected in group name %s\n", sgroup[fbdMatch], sgroup.c_str()); return 0; } fbdMatch = soptype.find_first_of(fbdChars); if (fbdMatch != std::string::npos && !(soptype == "*")) { fprintf(stdout, "illegal character %c detected in optype %s\n", soptype[fbdMatch], soptype.c_str()); return 0; } if (!(sgeotag == "*" && subcmd != "add")) { std::string tmp_geotag = eos::common::SanitizeGeoTag(sgeotag); if (tmp_geotag != sgeotag) { fprintf(stderr, "%s\n", tmp_geotag.c_str()); return 0; } } in += ("&mgm.subcmd=disabled" + subcmd); // mgm.subcmd is disabledadd or disabledrm or disabledshow if (geotag.length()) { in += ("&mgm.geotag=" + geotag); } in += ("&mgm.schedgroup=" + group); in += ("&mgm.optype=" + optype); } if (cmd == "access") { XrdOucString subcmd = subtokenizer.GetToken(); XrdOucString geotag, geotag_list, optype; if ((subcmd != "setdirect") && (subcmd != "showdirect") && (subcmd != "cleardirect") && (subcmd != "setproxygroup") && (subcmd != "showproxygroup") && (subcmd != "clearproxygroup")) { goto com_geosched_usage; } const char* token = 0; if ((token = subtokenizer.GetToken())) { geotag = token; } if ((token = subtokenizer.GetToken())) { geotag_list = token; } // mgm.subcmd is accesssetdirect or accesssetproxygroup or // accessshowdirect or accessshowproxygroup or // accesscleardirect or accessclearproxygroup in += ("&mgm.subcmd=access" + subcmd); if (subcmd == "showdirect" || subcmd == "showproxygroup") { if (geotag.length()) { if (geotag != "-m" || geotag_list.length()) { goto com_geosched_usage; } else { in += "&mgm.monitoring=1"; } } } else { if (subcmd == "setdirect" || subcmd == "setproxygroup") { if (!geotag.length() || !geotag_list.length()) { goto com_geosched_usage; } // Check each geotag from the list if (subcmd == "setdirect") { std::string tmp_list(geotag_list.c_str()); auto geotags = eos::common::StringTokenizer::split>(tmp_list, ','); tmp_list.clear(); for (const auto& tag : geotags) { std::string tmp_tag = eos::common::SanitizeGeoTag(tag); if (tmp_tag != tag) { fprintf(stderr, "%s\n", tmp_tag.c_str()); return 0; } } } in += ("&mgm.geotaglist=" + geotag_list); } else { // cleardirect or clearproxygroup if (!geotag.length() || geotag_list.length()) { goto com_geosched_usage; } } std::string tmp_geotag = eos::common::SanitizeGeoTag(geotag.c_str()); if (tmp_geotag != geotag.c_str()) { fprintf(stderr, "%s\n", tmp_geotag.c_str()); return 0; } in += ("&mgm.geotag=" + geotag); } } if (subtokenizer.GetToken()) { goto com_geosched_usage; } global_retc = output_result(client_command(in, true)); return (0); com_geosched_usage: fprintf(stdout, "'[eos] geosched ..' Interact with the file geoscheduling engine in EOS.\n"); fprintf(stdout, "Usage: geosched show|set|updater|forcerefresh|disabled|access ...\n"); fprintf(stdout, "Options:\n"); fprintf(stdout, " geosched show [-c|-m] tree [] : show scheduling trees\n"); fprintf(stdout, " : if is specified only the tree for this group is shown. If it's not all, the trees are shown.\n"); fprintf(stdout, " : '-c' enables color display\n"); fprintf(stdout, " : '-m' list in monitoring format\n"); fprintf(stdout, " geosched show [-c|-m] snapshot [{,*} []] : show snapshots of scheduling trees\n"); fprintf(stdout, " : if is specified only the snapshot(s) for this group is/are shown. If it's not all, the snapshots for all the groups are shown.\n"); fprintf(stdout, " : if is specified only the snapshot for this operation is shown. If it's not, the snapshots for all the optypes are shown.\n"); fprintf(stdout, " : can be one of the folowing plct,accsro,accsrw,accsdrain,plctdrain\n"); fprintf(stdout, " : '-c' enables color display\n"); fprintf(stdout, " : '-m' list in monitoring format\n"); fprintf(stdout, " geosched show param : show internal parameters\n"); fprintf(stdout, " geosched show state [-m] : show internal state\n"); fprintf(stdout, " : '-m' list in monitoring format\n"); fprintf(stdout, " geosched set [param index] : set the value of an internal state parameter (all names can be listed with geosched show param) \n"); fprintf(stdout, " geosched updater {pause|resume} : pause / resume the tree updater\n"); fprintf(stdout, " geosched forcerefresh : force a refresh of the trees/snapshots\n"); fprintf(stdout, " geosched disabled add {,*} {,*} : disable a branch of a subtree for the specified group and operation\n"); fprintf(stdout, " : multiple branches can be disabled (by successive calls) as long as they have no intersection\n"); fprintf(stdout, " geosched disabled rm {,*} {,*} {,*} : re-enable a disabled branch for the specified group and operation\n"); fprintf(stdout, " : when called with *, the whole tree(s) are re-enabled, canceling all previous disabling\n"); fprintf(stdout, " geosched disabled show {,*} {,*} {,*} : show list of disabled branches for for the specified groups and operation\n"); fprintf(stdout, " geosched access setdirect : set a mapping between an accesser geotag and a set of target geotags \n"); fprintf(stdout, " : these mappings specify which geotag can be accessed from which geotag without going through a firewall entrypoint\n"); fprintf(stdout, " : geotag_list is of the form token1::token2,token3::token4::token5,... \n"); fprintf(stdout, " geosched access showdirect [-m] : show mappings between accesser geotags and target geotags\n"); fprintf(stdout, " : '-m' list in monitoring format\n"); fprintf(stdout, " geosched access cleardirect {|all} : clear a mapping between an accesser geotag and a set of target geotags\n"); fprintf(stdout, " geosched access setproxygroup : set the proxygroup acting as a firewall entrypoint for the given subtree \n"); fprintf(stdout, " : if a client accesses a file from a geotag which does not have direct access to the subtree the replica is,\n"); fprintf(stdout, " : it will be scheduled to access through a node from the given proxygroup \n"); fprintf(stdout, " geosched access showproxygroup [-m] : show mappings between accesser geotags and target geotags\n"); fprintf(stdout, " : '-m' list in monitoring format\n"); fprintf(stdout, " geosched access clearproxygroup {|all} : clear a mapping between an accesser geotag and a set of target geotags\n"); fprintf(stdout, "\nNote:\n"); fprintf(stdout, " Make sure that geotags contain only alphanumeric segments which are no longer than 8 characters, in ::::...:: format.\n"); return (0); }