Update to ARC 4.1.0
[gp-arc-client-c.git] / ext / arc_kill.cpp
index c0a098f..31cc33f 100644 (file)
 #include <algorithm>
 #include "arc_libs.h"
 
+#include "utils.h"
+
 int  arc_kill(int argc, char **argv) {
 
-  Arc::OptionParser options(istring("[job ...]"),
-                            istring("The arckill command is used to kill "
-                                    "running jobs."),
-                            istring("Argument to -c has the format "
-                                    "Flavour:URL e.g.\n"
-                                    "ARC0:ldap://grid.tsl.uu.se:2135/"
-                                    "nordugrid-cluster-name=grid.tsl.uu.se,"
-                                    "Mds-Vo-name=local,o=grid"));
-
-  bool all = false;
-  options.AddOption('a', "all",
-                    istring("all jobs"),
-                    all);
-
-  std::string joblist;
-  options.AddOption('j', "joblist",
-                    istring("file containing a list of jobs"),
-                    istring("filename"),
-                    joblist);
-
-  std::list<std::string> clusters;
-  options.AddOption('c', "cluster",
-                    istring("explicitly select or reject a specific resource"),
-                    istring("[-]name"),
-                    clusters);
-
-  std::list<std::string> status;
-  options.AddOption('s', "status",
-                    istring("only select jobs whose status is statusstr"),
-                    istring("statusstr"),
-                    status);
-
-  bool keep = false;
-  options.AddOption('k', "keep",
-                    istring("keep the files on the server (do not clean)"),
-                    keep);
-
-  int timeout = -1;
-  options.AddOption('t', "timeout", istring("timeout in seconds (default 20)"),
-                    istring("seconds"), timeout);
-
-  std::string conffile;
-  options.AddOption('z', "conffile",
-                    istring("configuration file (default ~/.arc/client.conf)"),
-                    istring("filename"), conffile);
-
-  std::list<std::string> jobs = options.Parse(argc, argv);
-
-
-  Arc::UserConfig usercfg(conffile, joblist);
+  Arc::ArcLocation::Init(argv[0]);
+
+  ClientOptions opt(ClientOptions::CO_KILL,
+                    istring("[job ...]"),
+                    istring("The arckill command is used to kill "
+                            "running jobs."));
+
+  std::list<std::string> jobidentifiers = opt.Parse(argc, argv);
+
+  if (opt.showversion) {
+    std::cout << Arc::IString("%s version %s", "arckill", "4.1.0")
+              << std::endl;
+    return 0;
+  }
+
+  // If debug is specified as argument, it should be set before loading the configuration.
+  if (!opt.debug.empty())
+    Arc::Logger::getRootLogger().setThreshold(Arc::istring_to_level(opt.debug));
+
+  logger.msg(Arc::VERBOSE, "Running command: %s", opt.GetCommandWithArguments());
+
+  if (opt.show_plugins) {
+    std::list<std::string> types;
+    types.push_back("HED:JobControllerPlugin");
+    showplugins("arckill", types, logger);
+    return 0;
+  }
+
+  Arc::UserConfig usercfg(opt.conffile, opt.joblist);
   if (!usercfg) {
     logger.msg(Arc::ERROR, "Failed configuration initialization");
     return 1;
   }
 
-  if (timeout > 0)
-    usercfg.Timeout(timeout);
+  if (!checkproxy(usercfg)) {
+    return 1;
+  }
+
+  if (opt.debug.empty() && !usercfg.Verbosity().empty())
+    Arc::Logger::getRootLogger().setThreshold(Arc::istring_to_level(usercfg.Verbosity()));
 
-  if ((!joblist.empty() || !status.empty()) && jobs.empty() && clusters.empty()){
-    all = true;
-    logger.msg(Arc::DEBUG, "Implicit all turned on");
+  for (std::list<std::string>::const_iterator it = opt.jobidinfiles.begin(); it != opt.jobidinfiles.end(); it++) {
+    if (!Arc::Job::ReadJobIDsFromFile(*it, jobidentifiers)) {
+      logger.msg(Arc::WARNING, "Cannot read specified jobid file: %s", *it);
+    }
   }
 
-  if (jobs.empty() && clusters.empty() && !all) {
+  if (opt.timeout > 0)
+    usercfg.Timeout(opt.timeout);
+
+  if ((!opt.joblist.empty() || !opt.status.empty()) && jobidentifiers.empty() && opt.clusters.empty())
+    opt.all = true;
+
+  if (jobidentifiers.empty() && opt.clusters.empty() && !opt.all) {
     logger.msg(Arc::ERROR, "No jobs given");
     return 1;
   }
 
-  if (!jobs.empty() || all){
-    usercfg.ClearSelectedServices();
-    logger.msg(Arc::DEBUG, "ClearSelectedServcies was invoked.");
+  std::list<std::string> selectedURLs;
+  if (!opt.clusters.empty()) {
+    selectedURLs = getSelectedURLsFromUserConfigAndCommandLine(usercfg, opt.clusters);
+  }
+  std::list<std::string> rejectManagementURLs = getRejectManagementURLsFromUserConfigAndCommandLine(usercfg, opt.rejectmanagement);
+
+  std::list<Arc::Job> jobs;
+  Arc::JobInformationStorage *jobstore = createJobInformationStorage(usercfg);
+  if (jobstore != NULL && !jobstore->IsStorageExisting()) {
+    logger.msg(Arc::ERROR, "Job list file (%s) doesn't exist", usercfg.JobListFile());
+    delete jobstore;
+    return 1;
+  }
+  if (jobstore == NULL ||
+      ( opt.all && !jobstore->ReadAll(jobs, rejectManagementURLs)) ||
+      (!opt.all && !jobstore->Read(jobs, jobidentifiers, selectedURLs, rejectManagementURLs))) {
+    logger.msg(Arc::ERROR, "Unable to read job information from file (%s)", usercfg.JobListFile());
+    delete jobstore;
+    return 1;
   }
 
-  if (!clusters.empty()) {
-    usercfg.ClearSelectedServices();
-    usercfg.AddServices(clusters, Arc::COMPUTING);
+  if (!opt.all) {
+    for (std::list<std::string>::const_iterator itJIDAndName = jobidentifiers.begin();
+         itJIDAndName != jobidentifiers.end(); ++itJIDAndName) {
+      std::cout << Arc::IString("Warning: Job not found in job list: %s", *itJIDAndName) << std::endl;
+    }
   }
 
-  // If the user specified a joblist on the command line joblist equals
-  // usercfg.JobListFile(). If not use the default, ie. usercfg.JobListFile().
   Arc::JobSupervisor jobmaster(usercfg, jobs);
-  if (!jobmaster.JobsFound()) {
-    logger.msg(Arc::ERROR, "No jobs");
-    return 0;
+  jobmaster.Update();
+  jobmaster.SelectValid();
+  if (!opt.status.empty()) {
+    jobmaster.SelectByStatus(opt.status);
   }
-  std::list<Arc::JobController*> jobcont = jobmaster.GetJobControllers();
 
-  if (jobcont.empty()) {
-    logger.msg(Arc::ERROR, "No job controller plugins loaded");
+  if (jobmaster.GetSelectedJobs().empty()) {
+    std::cout << Arc::IString("No jobs") << std::endl;
+    delete jobstore;
     return 1;
   }
 
-  int retval = 0;
-  for (std::list<Arc::JobController*>::iterator it = jobcont.begin();
-       it != jobcont.end(); it++)
-    if (!(*it)->Kill(status, keep))
+  int retval = (int)!jobmaster.Cancel();
+
+  unsigned int selected_num = jobmaster.GetSelectedJobs().size();
+  unsigned int canceled_num = jobmaster.GetIDsProcessed().size();
+  unsigned int cleaned_num = 0;
+
+  if (!opt.keep) {
+    std::list<std::string> canceled = jobmaster.GetIDsProcessed();
+    // No need to clean selection because retrieved is subset of selected
+    jobmaster.SelectByID(canceled);
+    if(!jobmaster.Clean()) {
+      std::cout << Arc::IString("Warning: Some jobs were not removed from server") << std::endl;
+      std::cout << Arc::IString("         Use arclean to remove retrieved jobs from job list", usercfg.JobListFile()) << std::endl;
       retval = 1;
+    }
+    cleaned_num = jobmaster.GetIDsProcessed().size();
+
+    if (!jobstore->Remove(jobmaster.GetIDsProcessed())) {
+      std::cout << Arc::IString("Warning: Failed removing jobs from file (%s)", usercfg.JobListFile()) << std::endl;
+      std::cout << Arc::IString("         Run 'arcclean -s Undefined' to remove killed jobs from job list", usercfg.JobListFile()) << std::endl;
+      retval = 1;
+    }
+    std::cout << Arc::IString("Jobs processed: %d, successfully killed: %d, successfully cleaned: %d", selected_num, canceled_num, cleaned_num) << std::endl;
+  } else {
+    std::cout << Arc::IString("Jobs processed: %d, successfully killed: %d", selected_num, canceled_num) << std::endl;
+  }
+  delete jobstore;
 
   return retval;
-}
\ No newline at end of file
+
+}