Back to index

nordugrid-arc-nox  1.1.0~rc6
janitor.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <string>
00006 
00007 #include <glibmm.h>
00008 
00009 #include <arc/Thread.h>
00010 #include <arc/Run.h>
00011 #include <arc/Logger.h>
00012 #include <arc/XMLNode.h>
00013 
00014 #include "../conf/conf.h"
00015 #include "../conf/conf_sections.h"
00016 #include "../conf/environment.h"
00017 #include "../jobs/users.h"
00018 #include "../files/info_files.h"
00019 
00020 /*
00021 * janitor [ deploy | help | list | info | register |
00022 *             remove | setstate | search | sweep ]
00023 *   deploy <job-id>:             deploys all REs needed by job <job-id>
00024 *   help:                        displays this message
00025 *   list:                        lists details about all registered jobs
00026 *   info <job-id>:               lists information about this job's REs
00027 *   register <job-id> [ REs ]:   registers a new job
00028 *   remove <job-id>:             unregister job <job-id>
00029 *   setstate <newstate> [ REs ]: sets the state of REs
00030 *   search [ REs ]:              searches for informations about REs
00031 *   sweep [--force]:             clean up runtime environments
00032 */
00033 
00034 #include "janitor.h"
00035 
00036 
00037 static Arc::Logger logger(Arc::Logger::rootLogger, "Janitor Control");
00038 
00039 Janitor::Janitor(const std::string& id,const std::string& cdir):
00040          id_(id),cdir_(cdir),running_(false),result_(FAILED),enabled_(false) {
00041   if(!readConfig()) return;
00042   if(!enabled()) return;
00043   if(id_.empty()) return;
00044   if(cdir_.empty()) return;
00045   // create path to janitor utility
00046   path_ = Glib::build_filename(nordugrid_libexec_loc(),"janitor");
00047   if(path_.empty()) {
00048     logger.msg(Arc::ERROR, "Failed to create path to janitor at %s",nordugrid_libexec_loc());
00049     return;
00050   };
00051   // check if utility exists
00052   if(!Glib::file_test(path_,Glib::FILE_TEST_IS_EXECUTABLE)) {
00053     logger.msg(Arc::ERROR, "Janitor executable not found at %s",path_);
00054     path_.resize(0);
00055     return;
00056   };
00057 }
00058 
00059 Janitor::~Janitor(void) {
00060   cancel();;
00061 }
00062 
00063 bool Janitor::readConfig() {
00064   // open conf file
00065   std::ifstream cfile;
00066   if(nordugrid_config_loc().empty()) read_env_vars(true);
00067   if(!config_open(cfile)) {
00068     logger.msg(Arc::ERROR,"Can't open configuration file");
00069     return false;
00070   }
00071   switch(config_detect(cfile)) {
00072     case config_file_XML: {
00073       Arc::XMLNode cfg;
00074       if(!cfg.ReadFromStream(cfile)) {
00075         config_close(cfile);
00076         logger.msg(Arc::ERROR,"Can't interpret configuration file as XML");
00077         return false;
00078       }
00079       std::string enabled = cfg["janitor"]["enabled"];
00080       enabled_ = (enabled == "1");
00081     }; break;
00082     case config_file_INI: {
00083       ConfigSections* cf = new ConfigSections(cfile);
00084       cf->AddSection("janitor");
00085       for(;;) {
00086         std::string rest;
00087         std::string command;
00088         cf->ReadNext(command,rest);
00089         if(command.empty()) break;
00090         if(command == "enabled") enabled_ = (config_next_arg(rest) == "1");
00091       }
00092       delete cf;
00093     }; break;
00094     default: {
00095       logger.msg(Arc::ERROR,"Can't recognize type of configuration file");
00096       return false;
00097     }; break;
00098   };
00099   config_close(cfile);
00100   return true;
00101 }
00102 
00103 void Janitor::cancel(void) {
00104   if(!running_) return;
00105   if(completed_.wait(0)) return;
00106   cancel_.signal();
00107   completed_.wait();
00108 }
00109 
00110 void Janitor::deploy_thread(void* arg) {
00111   Janitor& it = *((Janitor*)arg);
00112   it.result_=FAILED;
00113     // Fetch list of REs
00114   JobUser user;
00115   user.SetControlDir(it.cdir_);
00116   std::list<std::string> rtes;
00117   if(!job_rte_read_file(it.id_,user,rtes)) { it.completed_.signal(); return; };
00118   if(rtes.size() == 0) {
00119     it.result_=DEPLOYED;
00120     it.completed_.signal();
00121     return;
00122   };
00123   std::string cmd;
00124   // Make command line
00125   cmd = it.path_ + " register " + it.id_;
00126   while(rtes.size() > 0) {
00127     cmd += " " + *rtes.begin();
00128     rtes.pop_front();
00129   };
00130   // Run command
00131   {
00132     Arc::Run run(cmd);
00133     if(!run) {
00134       logger.msg(Arc::DEBUG, "Can't run %s", cmd);
00135       it.completed_.signal();
00136       return;
00137     };
00138     run.KeepStdout(true);
00139     run.KeepStderr(true);
00140     if(!run.Start()) {
00141       logger.msg(Arc::DEBUG, "Can't start %s", cmd);
00142       it.completed_.signal();
00143       return;
00144     };
00145     // Wait for result or cancel request
00146     for(;;) {
00147       if(run.Wait(1)) break;
00148       if(it.cancel_.wait(0)) { it.completed_.signal(); return; };
00149     };
00150     if(run.Result() == 0) {
00151       logger.msg(Arc::DEBUG, "janitor register returned 0 - no RTE needs to be deployed");
00152       it.result_=DEPLOYED; it.completed_.signal();
00153       return;
00154     };
00155     if(run.Result() == 3) {
00156       logger.msg(Arc::DEBUG, "janitor register returned 3 - no Janitor enabled in configuration");
00157       it.result_=NOTENABLED; it.completed_.signal();
00158       return;
00159     };
00160     if(run.Result() != 1) {
00161       logger.msg(Arc::ERROR, "janitor register failed with exit code %i",run.Result());
00162       it.completed_.signal();
00163       return;
00164     };
00165     logger.msg(Arc::DEBUG, "janitor register returned 1 - need to run janitor deploy");
00166   };
00167   // Make command line
00168   cmd = it.path_ + " deploy " + it.id_;
00169   // Run command
00170   {
00171     Arc::Run run(cmd);
00172     if(!run) {
00173       logger.msg(Arc::DEBUG, "Can't run %s", cmd);
00174       it.completed_.signal();
00175       return;
00176     };
00177     run.KeepStdout(true);
00178     run.KeepStderr(true);
00179     if(!run.Start()) {
00180       logger.msg(Arc::DEBUG, "Can't start %s", cmd);
00181       it.completed_.signal();
00182       return;
00183     };
00184     // Wait for result or cancel request
00185     for(;;) {
00186       if(run.Wait(1)) break;
00187       if(it.cancel_.wait(0)) { it.completed_.signal(); return; };
00188     };
00189     if(run.Result() == 3) {
00190       logger.msg(Arc::VERBOSE, "janitor deploy returned 3 - no Janitor enabled in configuration");
00191       it.result_=NOTENABLED; it.completed_.signal();
00192       return;
00193     };
00194     if(run.Result() != 0) {
00195       logger.msg(Arc::DEBUG, "janitor deploy failed with exit code %i",run.Result());
00196       it.completed_.signal();
00197       return;
00198     };
00199   };
00200   it.result_=DEPLOYED;
00201   it.completed_.signal();
00202   return;
00203 }
00204 
00205 void Janitor::remove_thread(void* arg) {
00206   Janitor& it = *((Janitor*)arg);
00207   it.result_=FAILED;
00208   std::string cmd;
00209   // Make command line
00210   cmd = it.path_ + " remove " + it.id_;
00211   // Run command
00212   {
00213     Arc::Run run(cmd);
00214     if(!run) {
00215       logger.msg(Arc::DEBUG, "Can't run %s", cmd);
00216       it.completed_.signal();
00217       return;
00218     };
00219     run.KeepStdout(true);
00220     run.KeepStderr(true);
00221     if(!run.Start()) {
00222       logger.msg(Arc::DEBUG, "Can't start %s", cmd);
00223       it.completed_.signal();
00224       return;
00225     };
00226     // Wait for result or cancel request
00227     for(;;) {
00228       if(run.Wait(1)) break;
00229       if(it.cancel_.wait(0)) { it.completed_.signal(); return; };
00230     };
00231     if(run.Result() == 3) {
00232       logger.msg(Arc::VERBOSE, "janitor remove returned 3 - no Janitor enabled in configuration");
00233       it.result_=NOTENABLED; it.completed_.signal();
00234       return;
00235     };
00236     if(run.Result() != 0) {
00237       logger.msg(Arc::DEBUG, "janitor remove failed with exit code %i",run.Result());
00238       it.completed_.signal();
00239       return;
00240     };
00241   }
00242   it.result_=REMOVED;
00243   it.completed_.signal();
00244   return;
00245 }
00246 
00247 bool Janitor::deploy(void) {
00248   if(operator!()) return false;
00249   if(running_) return false;
00250   running_=true;
00251   running_=Arc::CreateThreadFunction(&Janitor::deploy_thread,this);
00252   return running_;
00253 }
00254 
00255 bool Janitor::remove(void) {
00256   if(operator!()) return false;
00257   if(running_) return false;
00258   running_=true;
00259   running_=Arc::CreateThreadFunction(&Janitor::remove_thread,this);
00260   return running_;
00261 }
00262 
00263 bool Janitor::wait(int timeout) {
00264   if(!running_) return true;
00265   if(!completed_.wait(timeout*1000)) return false;
00266   running_=false;
00267   return true;
00268 }
00269 
00270 Janitor::Result Janitor::result(void) {
00271   return result_;
00272 }
00273 
00274 
00275 
00276