Back to index

nordugrid-arc-nox  1.1.0~rc6
conf_file.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 #include <pwd.h>
00007 
00008 #include <arc/StringConv.h>
00009 #include <arc/Utils.h>
00010 #include <arc/XMLNode.h>
00011 #include "../jobs/users.h"
00012 #include "../jobs/states.h"
00013 #include "../jobs/plugins.h"
00014 #include "conf.h"
00015 #include "conf_sections.h"
00016 #include "environment.h"
00017 #include "gridmap.h"
00018 #include "../run/run_plugin.h"
00019 #include "conf_cache.h"
00020 #include "conf_file.h"
00021 
00022 static Arc::Logger& logger = Arc::Logger::getRootLogger();
00023 
00024 JobLog job_log;
00025 ContinuationPlugins plugins;
00026 RunPlugin cred_plugin;
00027 
00028 static void check_lrms_backends(const std::string& default_lrms) {
00029   std::string tool_path;
00030   tool_path=nordugrid_libexec_loc()+"/cancel-"+default_lrms+"-job";
00031   if(!Glib::file_test(tool_path,Glib::FILE_TEST_IS_REGULAR)) {
00032     logger.msg(Arc::WARNING,"Missing cancel-%s-job - job cancelation may not work",default_lrms);
00033   };
00034   tool_path=nordugrid_libexec_loc()+"/submit-"+default_lrms+"-job";
00035   if(!Glib::file_test(tool_path,Glib::FILE_TEST_IS_REGULAR)) {
00036     logger.msg(Arc::WARNING,"Missing submit-%s-job - job submission to LRMS may not work",default_lrms);
00037   };
00038   tool_path=nordugrid_libexec_loc()+"/scan-"+default_lrms+"-job";
00039   if(!Glib::file_test(tool_path,Glib::FILE_TEST_IS_REGULAR)) {
00040     logger.msg(Arc::WARNING,"Missing scan-%s-job - may miss when job finished executing",default_lrms);
00041   };
00042 }
00043 
00044 bool configure_serviced_users(JobUsers &users,uid_t my_uid,const std::string &my_username,JobUser &my_user,Daemon* daemon) {
00045   std::ifstream cfile;
00046   std::vector<std::string> session_roots;
00047   std::string session_root("");
00048   std::string default_lrms("");
00049   std::string default_queue("");
00050   std::string last_control_dir("");
00051   time_t default_ttl = DEFAULT_KEEP_FINISHED;
00052   time_t default_ttr = DEFAULT_KEEP_DELETED;
00053   int default_reruns = DEFAULT_JOB_RERUNS;
00054   int default_diskspace = DEFAULT_DISKSPACE;
00055   bool superuser = (my_uid == 0);
00056   bool strict_session = false;
00057   std::string central_control_dir("");
00058   std::string infosys_user("");
00059   std::string jobreport_key("");
00060   std::string jobreport_cert("");
00061   std::string jobreport_cadir("");
00062 
00063   /* read configuration and add users and other things */
00064   if(!config_open(cfile)) {
00065     logger.msg(Arc::ERROR,"Can't read configuration file"); return false;
00066   };
00067   /* detect type of file */
00068   switch(config_detect(cfile)) {
00069     case config_file_XML: {
00070       Arc::XMLNode cfg;
00071       if(!cfg.ReadFromStream(cfile)) {
00072         config_close(cfile);
00073         logger.msg(Arc::ERROR,"Can't interpret configuration file as XML");
00074         return false;
00075       }; 
00076       config_close(cfile);
00077       return configure_serviced_users(cfg,users,my_uid,my_username,my_user);
00078     }; break;
00079     case config_file_INI: {
00080       // Fall through. TODO: make INI processing a separate function.
00081     }; break;
00082     default: {
00083       logger.msg(Arc::ERROR,"Can't recognize type of configuration file"); return false;
00084     }; break;
00085   };
00086   ConfigSections* cf = new ConfigSections(cfile);
00087   cf->AddSection("common");
00088   cf->AddSection("grid-manager");
00089   cf->AddSection("infosys");
00090   /* process configuration information here */
00091   for(;;) {
00092     std::string rest;
00093     std::string command;
00094     cf->ReadNext(command,rest);
00095     if(cf->SectionNum() == 2) { // infosys - looking for user name only
00096       if(command == "user") infosys_user=rest;
00097       continue;
00098     };
00099     if(cf->SectionNum() == 0) { // infosys user may be in common too
00100       if(command == "user") infosys_user=rest;
00101     };
00102     if(daemon) {
00103       int r = daemon->config(command,rest);
00104       if(r == 0) continue;
00105       if(r == -1) goto exit;
00106     } else {
00107       int r = Daemon::skip_config(command);
00108       if(r == 0) continue;
00109     };
00110     if(command.length() == 0) {
00111       if(central_control_dir.length() != 0) {
00112         command="control"; rest=central_control_dir+" .";
00113         central_control_dir="";
00114       } else {
00115         break;
00116       };
00117     };
00118     if(command == "runtimedir") { 
00119       runtime_config_dir(rest);
00120     } else if(command == "joblog") { /* where to write job inforamtion */ 
00121       std::string fname = config_next_arg(rest);  /* empty is allowed too */
00122       job_log.SetOutput(fname.c_str());
00123     }
00124     else if(command == "jobreport") { /* service to report information to */ 
00125       for(;;) {
00126         std::string url = config_next_arg(rest); 
00127         if(url.length() == 0) break;
00128         unsigned int i;
00129         if(Arc::stringto(url,i)) {
00130           job_log.SetExpiration(i);
00131           continue;
00132         };
00133         job_log.SetReporter(url.c_str());
00134       };
00135     }
00136     else if(command == "jobreport_credentials") {
00137       jobreport_key = config_next_arg(rest); 
00138       jobreport_cert = config_next_arg(rest); 
00139       jobreport_cadir = config_next_arg(rest); 
00140     }
00141     else if(command == "jobreport_options") { /* e.g. for SGAS, interpreted by usage reporter */ 
00142       std::string accounting_options = config_next_arg(rest); 
00143       job_log.set_options(accounting_options);
00144     }
00145     else if(command == "maxjobs") { /* maximum number of the jobs to support */ 
00146       std::string max_jobs_s = config_next_arg(rest);
00147       long int i;
00148       int max_jobs, max_jobs_running = -1;
00149       if(max_jobs_s.length() != 0) {
00150         if(!Arc::stringto(max_jobs_s,i)) {
00151           logger.msg(Arc::ERROR,"wrong number in maxjobs: %s",max_jobs_s);
00152           goto exit;
00153         };
00154         if(i<0) i=-1; max_jobs=i;
00155       };
00156       max_jobs_s = config_next_arg(rest);
00157       if(max_jobs_s.length() != 0) {
00158         if(!Arc::stringto(max_jobs_s,i)) {
00159           logger.msg(Arc::ERROR,"wrong number in maxjobs: %s",max_jobs_s);
00160           goto exit;
00161         };
00162         if(i<0) i=-1; max_jobs_running=i;
00163       };
00164       JobsList::SetMaxJobs(
00165               max_jobs,max_jobs_running);
00166     }
00167     else if(command == "maxload") { /* maximum number of the jobs processed on frontend */
00168       std::string max_jobs_s = config_next_arg(rest);
00169       long int i;
00170       int max_jobs_processing, max_jobs_processing_emergency, max_downloads = -1;
00171       if(max_jobs_s.length() != 0) {
00172         if(!Arc::stringto(max_jobs_s,i)) {
00173           logger.msg(Arc::ERROR,"wrong number in maxload: %s",max_jobs_s);
00174           goto exit;
00175         };
00176         if(i<0) i=-1; max_jobs_processing=i;
00177       };
00178       max_jobs_s = config_next_arg(rest);
00179       if(max_jobs_s.length() != 0) {
00180         if(!Arc::stringto(max_jobs_s,i)) {
00181           logger.msg(Arc::ERROR,"wrong number in maxload: %s",max_jobs_s);
00182           goto exit;
00183         };
00184         if(i<0) i=-1; max_jobs_processing_emergency=i;
00185       };
00186       max_jobs_s = config_next_arg(rest);
00187       if(max_jobs_s.length() != 0) {
00188         if(!Arc::stringto(max_jobs_s,i)) {
00189           logger.msg(Arc::ERROR,"wrong number in maxload: %s",max_jobs_s);
00190           goto exit;
00191         };
00192         if(i<0) i=-1; max_downloads=i;
00193       };
00194       JobsList::SetMaxJobsLoad(
00195               max_jobs_processing,max_jobs_processing_emergency,max_downloads);
00196     }
00197     else if(command == "maxloadshare") {
00198        std::string max_share_s = config_next_arg(rest);
00199         unsigned int max_share = 0;
00200         if(max_share_s.length() != 0) {
00201           if(!Arc::stringto(max_share_s,max_share) || max_share<=0) {
00202             logger.msg(Arc::ERROR,"wrong number in maxloadshare: %s", max_share_s); goto exit;
00203           };
00204         };
00205         std::string transfer_share = config_next_arg(rest);
00206        if (transfer_share.empty()){
00207             logger.msg(Arc::ERROR,"the type of share is not set in maxloadshare"); goto exit;
00208        }
00209         JobsList::SetTransferShare(max_share, transfer_share);
00210     }
00211     else if(command == "share_limit") {
00212       std::string share_name = config_next_arg(rest);
00213       std::string share_limit_s = config_next_arg(rest);
00214       std::string temp = config_next_arg(rest);
00215       while(temp.length() != 0) {
00216         share_name.append(" ");
00217         share_name.append(share_limit_s);
00218         share_limit_s = temp;
00219         temp = config_next_arg(rest);
00220       }
00221       if (share_name.empty()) {
00222         logger.msg(Arc::ERROR,"the name of share is not set in share_limit"); goto exit;
00223       }
00224       unsigned int share_limit = 0;
00225       if(share_limit_s.length() != 0) {
00226         if(!Arc::stringto(share_limit_s,share_limit) || share_limit<=0){
00227           logger.msg(Arc::ERROR,"wrong number in share_limit: %s",share_limit); goto exit;
00228         }
00229       }
00230       if(!JobsList::AddLimitedShare(share_name,share_limit)) {
00231         logger.msg(Arc::ERROR,"share_limit should be located after maxloadshare"); goto exit;
00232       }
00233     }
00234     else if(command == "speedcontrol") {  
00235       std::string speed_s = config_next_arg(rest);
00236       int min_speed=0;
00237       int min_speed_time=300;
00238       int min_average_speed=0;
00239       int max_inactivity_time=300;
00240       if(speed_s.length() != 0) {
00241         if(!Arc::stringto(speed_s,min_speed)) {
00242           logger.msg(Arc::ERROR,"wrong number in speedcontrol: %s",speed_s);
00243           goto exit;
00244         };
00245       };
00246       speed_s = config_next_arg(rest);
00247       if(speed_s.length() != 0) {
00248         if(!Arc::stringto(speed_s,min_speed_time)) {
00249           logger.msg(Arc::ERROR,"wrong number in speedcontrol: ",speed_s);
00250           goto exit;
00251         };
00252       };
00253       speed_s = config_next_arg(rest);
00254       if(speed_s.length() != 0) {
00255         if(!Arc::stringto(speed_s,min_average_speed)) {
00256           logger.msg(Arc::ERROR,"wrong number in speedcontrol: %s",speed_s);
00257           goto exit;
00258         };
00259       };
00260       speed_s = config_next_arg(rest);
00261       if(speed_s.length() != 0) {
00262         if(!Arc::stringto(speed_s,max_inactivity_time)) {
00263           logger.msg(Arc::ERROR,"wrong number in speedcontrol: %s",speed_s);
00264           goto exit;
00265         };
00266       };
00267       JobsList::SetSpeedControl(
00268               min_speed,min_speed_time,min_average_speed,max_inactivity_time);
00269     }
00270     else if(command == "wakeupperiod") { 
00271       std::string wakeup_s = config_next_arg(rest);
00272       unsigned int wakeup_period;
00273       if(wakeup_s.length() != 0) {
00274         if(!Arc::stringto(wakeup_s,wakeup_period)) {
00275           logger.msg(Arc::ERROR,"wrong number in wakeupperiod: %s",wakeup_s);
00276           goto exit;
00277         };
00278         JobsList::SetWakeupPeriod(wakeup_period);
00279       };
00280     }
00281     else if(command == "securetransfer") {
00282       std::string s = config_next_arg(rest);
00283       bool use_secure_transfer;
00284       if(strcasecmp("yes",s.c_str()) == 0) {
00285         use_secure_transfer=true;
00286       } 
00287       else if(strcasecmp("no",s.c_str()) == 0) {
00288         use_secure_transfer=false;
00289       }
00290       else {
00291         logger.msg(Arc::ERROR,"wrong option in securetransfer"); goto exit;
00292       };
00293       JobsList::SetSecureTransfer(use_secure_transfer);
00294     }
00295     else if(command == "passivetransfer") {
00296       std::string s = config_next_arg(rest);
00297       bool use_passive_transfer;
00298       if(strcasecmp("yes",s.c_str()) == 0) {
00299         use_passive_transfer=true;
00300       }
00301       else if(strcasecmp("no",s.c_str()) == 0) {
00302         use_passive_transfer=false;
00303       }
00304       else {
00305         logger.msg(Arc::ERROR,"wrong option in passivetransfer"); goto exit;
00306       };
00307       JobsList::SetPassiveTransfer(use_passive_transfer);
00308     }
00309     else if(command == "maxtransfertries") {
00310       std::string maxtries_s = config_next_arg(rest);
00311       int max_retries = DEFAULT_MAX_RETRIES;
00312       if(maxtries_s.length() != 0) {
00313         if(!Arc::stringto(maxtries_s,max_retries)) {
00314           logger.msg(Arc::ERROR,"wrong number in maxtransfertries"); goto exit;
00315         };
00316         JobsList::SetMaxRetries(max_retries);
00317       };
00318     }
00319     else if(command == "norootpower") {
00320       std::string s = config_next_arg(rest);
00321       if(strcasecmp("yes",s.c_str()) == 0) {
00322         strict_session=true;
00323       }
00324       else if(strcasecmp("no",s.c_str()) == 0) {
00325         strict_session=false;
00326       }
00327       else {
00328         logger.msg(Arc::ERROR,"wrong option in norootpower"); goto exit;
00329       };
00330     }
00331     else if(command == "localtransfer") {
00332       std::string s = config_next_arg(rest);
00333       bool use_local_transfer;
00334       if(strcasecmp("yes",s.c_str()) == 0) {
00335         use_local_transfer=true;
00336       }
00337       else if(strcasecmp("no",s.c_str()) == 0) {
00338         use_local_transfer=false;
00339       }
00340       else {
00341         logger.msg(Arc::ERROR,"wrong option in localtransfer"); goto exit;
00342       };
00343       JobsList::SetLocalTransfer(use_local_transfer);
00344     }
00345     else if(command == "mail") { /* internal address from which to send mail */ 
00346       support_mail_address(config_next_arg(rest));
00347       if(support_mail_address().empty()) {
00348         logger.msg(Arc::ERROR,"mail is empty"); goto exit;
00349       };
00350     }
00351     else if(command == "defaultttl") { /* time to keep job after finished */ 
00352       char *ep;
00353       std::string default_ttl_s = config_next_arg(rest);
00354       if(default_ttl_s.length() == 0) {
00355         logger.msg(Arc::ERROR,"defaultttl is empty"); goto exit;
00356       };
00357       default_ttl=strtoul(default_ttl_s.c_str(),&ep,10);
00358       if(*ep != 0) {
00359         logger.msg(Arc::ERROR,"wrong number in defaultttl command"); goto exit;
00360       };
00361       default_ttl_s = config_next_arg(rest);
00362       if(default_ttl_s.length() != 0) {
00363         if(rest.length() != 0) {
00364           logger.msg(Arc::ERROR,"junk in defaultttl command"); goto exit;
00365         };
00366         default_ttr=strtoul(default_ttl_s.c_str(),&ep,10);
00367         if(*ep != 0) {
00368           logger.msg(Arc::ERROR,"wrong number in defaultttl command"); goto exit;
00369         };
00370       } else {
00371         default_ttr=DEFAULT_KEEP_DELETED;
00372       };
00373     }
00374     else if(command == "maxrerun") { /* number of retries allowed */ 
00375       std::string default_reruns_s = config_next_arg(rest);
00376       if(default_reruns_s.length() == 0) {
00377         logger.msg(Arc::ERROR,"maxrerun is empty"); goto exit;
00378       };
00379       if(rest.length() != 0) {
00380         logger.msg(Arc::ERROR,"junk in maxrerun command"); goto exit;
00381       };
00382       char *ep;
00383       default_reruns=strtoul(default_reruns_s.c_str(),&ep,10);
00384       if(*ep != 0) {
00385         logger.msg(Arc::ERROR,"wrong number in maxrerun command"); goto exit;
00386       };      
00387     }
00388     else if(command == "diskspace") { /* maximal amount of disk space */ 
00389       std::string default_diskspace_s = config_next_arg(rest);
00390       if(default_diskspace_s.length() == 0) {
00391         logger.msg(Arc::ERROR,"diskspace is empty"); goto exit;
00392       };
00393       if(rest.length() != 0) {
00394         logger.msg(Arc::ERROR,"junk in diskspace command"); goto exit;
00395       };
00396       char *ep;
00397       default_diskspace=strtoull(default_diskspace_s.c_str(),&ep,10);
00398       if(*ep != 0) {
00399         logger.msg(Arc::ERROR,"wrong number in diskspace command"); goto exit;
00400       };      
00401     }
00402     else if(command == "lrms") {
00403       /* set default lrms type and queue 
00404          (optionally). Applied to all following
00405          'control' commands. MUST BE thing */
00406       default_lrms = config_next_arg(rest);
00407       default_queue = config_next_arg(rest);
00408       if(default_lrms.empty()) {
00409         logger.msg(Arc::ERROR,"defaultlrms is empty"); goto exit;
00410       };
00411       if(!rest.empty()) {
00412         logger.msg(Arc::ERROR,"junk in defaultlrms command"); goto exit;
00413       };
00414       check_lrms_backends(default_lrms);
00415     }
00416     else if(command == "authplugin") { /* set plugin to be called on 
00417                                           state changes */
00418       std::string state_name = config_next_arg(rest);
00419       if(state_name.length() == 0) {
00420         logger.msg(Arc::ERROR,"state name for plugin is missing"); goto exit;
00421       };
00422       std::string options_s = config_next_arg(rest);
00423       if(options_s.length() == 0) {
00424         logger.msg(Arc::ERROR,"Options for plugin are missing"); goto exit;
00425       };
00426       if(!plugins.add(state_name.c_str(),options_s.c_str(),rest.c_str())) {
00427         logger.msg(Arc::ERROR,"Failed to register plugin for state %s",state_name);      
00428         goto exit;
00429       };
00430     }
00431     else if(command == "localcred") {
00432       std::string timeout_s = config_next_arg(rest);
00433       if(timeout_s.length() == 0) {
00434         logger.msg(Arc::ERROR,"timeout for plugin is missing"); goto exit;
00435       };
00436       char *ep;
00437       int to = strtoul(timeout_s.c_str(),&ep,10);
00438       if((*ep != 0) || (to<0)) {
00439         logger.msg(Arc::ERROR,"wrong number for timeout in plugin command");
00440         goto exit;
00441       };
00442       cred_plugin = rest;
00443       cred_plugin.timeout(to);
00444     }
00445     else if(command == "sessiondir") {
00446       /* set session root directory - applied
00447          to all following 'control' commands */
00448       std::string session_root = config_next_arg(rest);
00449       if(session_root.length() == 0) {
00450         logger.msg(Arc::ERROR,"session root dir is missing"); goto exit;
00451       };
00452       if(rest.length() != 0 && rest != "drain") {
00453         logger.msg(Arc::ERROR,"junk in session root command"); goto exit;
00454       };
00455       session_roots.push_back(session_root);
00456     } else if(command == "controldir") {
00457       central_control_dir=rest;
00458     } else if(command == "control") {
00459       std::string control_dir = config_next_arg(rest);
00460       if(control_dir.length() == 0) {
00461         logger.msg(Arc::ERROR,"missing directory in control command"); goto exit;
00462       };
00463       if(control_dir == "*") control_dir="";
00464       if(command == "controldir") rest=".";
00465       for(;;) {
00466         std::string username = config_next_arg(rest);
00467         if(username.length() == 0) break;
00468         if(username == "*") {  /* add all gridmap users */
00469           if(!gridmap_user_list(rest)) {
00470             logger.msg(Arc::ERROR,"Can't read users in gridmap file %s",globus_gridmap()); goto exit;
00471           };
00472           continue;
00473         };
00474         if(username == ".") {  /* accept all users in this control directory */
00475            /* !!!!!!! substitutions involving user names won't work !!!!!!!  */
00476            if(superuser) { username=""; }
00477            else { username=my_username; };
00478         };
00479         /* add new user to list */
00480         if(superuser || (my_username == username)) {
00481           if(users.HasUser(username)) { /* first is best */
00482             continue;
00483           };
00484           JobUsers::iterator user=users.AddUser(username,&cred_plugin,
00485                                        control_dir,&session_roots);
00486           if(user == users.end()) { /* bad bad user */
00487             logger.msg(Arc::WARNING,"Warning: creation of user \"%s\" failed",username);
00488           }
00489           else {
00490             std::string control_dir_ = control_dir;
00491             for(std::vector<std::string>::iterator i = session_roots.begin(); i != session_roots.end(); i++) {
00492               user->substitute(*i);
00493             }
00494             user->SetLRMS(default_lrms,default_queue);
00495             user->SetKeepFinished(default_ttl);
00496             user->SetKeepDeleted(default_ttr);
00497             user->SetReruns(default_reruns);
00498             user->SetDiskSpace(default_diskspace);
00499             user->substitute(control_dir_);
00500             user->SetControlDir(control_dir_);
00501             user->SetSessionRoot(session_roots);
00502             user->SetStrictSession(strict_session);
00503             // get cache parameters for this user
00504             try {
00505               CacheConfig * cache_config = new CacheConfig(user->UnixName());
00506               user->SetCacheParams(cache_config);
00507             }
00508             catch (CacheConfigException e) {
00509               logger.msg(Arc::ERROR, "Error with cache configuration: %s", e.what());
00510               goto exit;
00511             }
00512             /* add helper to poll for finished jobs */
00513             std::string cmd_ = nordugrid_libexec_loc();
00514             make_escaped_string(control_dir_);
00515             cmd_+="/scan-"+default_lrms+"-job";
00516             make_escaped_string(cmd_);
00517             cmd_+=" --config ";
00518             cmd_+=nordugrid_config_loc();
00519             cmd_+=" ";
00520             cmd_+=user->ControlDir();
00521             user->add_helper(cmd_);
00522             /* creating empty list of jobs */
00523             JobsList *jobs = new JobsList(*user,plugins); 
00524             (*user)=jobs; /* back-associate jobs with user :) */
00525           };
00526         };
00527       };
00528       last_control_dir = control_dir;
00529       session_roots.clear();
00530     }
00531     else if(command == "helper") {
00532       std::string helper_user = config_next_arg(rest);
00533       if(helper_user.length() == 0) {
00534         logger.msg(Arc::ERROR,"user for helper program is missing"); goto exit;
00535       };
00536       if(rest.length() == 0) {
00537         logger.msg(Arc::ERROR,"helper program is missing"); goto exit;
00538       };
00539       if(helper_user == "*") {  /* go through all configured users */
00540         for(JobUsers::iterator user=users.begin();user!=users.end();++user) {
00541           if(!(user->has_helpers())) {
00542             std::string rest_=rest;
00543             user->substitute(rest_);
00544             user->add_helper(rest_);
00545           };    
00546         };
00547       }
00548       else if(helper_user == ".") { /* special helper */
00549         std::string control_dir_ = last_control_dir;
00550         my_user.SetLRMS(default_lrms,default_queue);
00551         my_user.SetKeepFinished(default_ttl);
00552         my_user.SetKeepDeleted(default_ttr);
00553         my_user.substitute(control_dir_);
00554         my_user.SetSessionRoot(session_roots);
00555         my_user.SetControlDir(control_dir_);
00556         std::string my_helper=rest;
00557         users.substitute(my_helper);
00558         my_user.substitute(my_helper);
00559         my_user.add_helper(my_helper);
00560       }
00561       else {
00562         /* look for that user */
00563         JobUsers::iterator user=users.find(helper_user);
00564         if(user == users.end()) {
00565           logger.msg(Arc::ERROR,"%s user for helper program is not configured",helper_user);
00566           goto exit;
00567         };
00568         user->substitute(rest);
00569         user->add_helper(rest);
00570       };
00571     };
00572   };
00573   delete cf;
00574   config_close(cfile);
00575   if(infosys_user.length()) {
00576     struct passwd pw_;
00577     struct passwd *pw;
00578     char buf[BUFSIZ];
00579     getpwnam_r(infosys_user.c_str(),&pw_,buf,BUFSIZ,&pw);
00580     if(pw != NULL) {
00581       if(pw->pw_uid != 0) {
00582         for(JobUsers::iterator user=users.begin();user!=users.end();++user) {
00583           if(pw->pw_uid != user->get_uid()) {
00584             if(pw->pw_gid != user->get_gid()) {
00585               user->SetShareLevel(JobUser::jobinfo_share_group);
00586             } else {
00587               user->SetShareLevel(JobUser::jobinfo_share_all);
00588             };
00589           };
00590         };
00591       };
00592     };
00593   };
00594   if(daemon) {
00595     if(jobreport_key.empty()) jobreport_key = daemon->keypath();
00596     if(jobreport_cert.empty()) jobreport_cert = daemon->certpath();
00597     if(jobreport_cadir.empty()) jobreport_cadir = daemon->cadirpath();
00598   }
00599   job_log.set_credentials(jobreport_key,jobreport_cert,jobreport_cadir);
00600   return true;
00601 exit:
00602   delete cf;
00603   config_close(cfile);
00604   return false;
00605 }
00606 
00607 bool configure_serviced_users(Arc::XMLNode cfg,JobUsers &users,uid_t my_uid,const std::string &my_username,JobUser &my_user) {
00608   Arc::XMLNode tmp_node;
00609   bool superuser = (my_uid == 0);
00610   std::string default_lrms;
00611   std::string default_queue;
00612   std::string last_control_dir;
00613   std::vector<std::string> session_roots;
00614   /*
00615    Currently we have everything running inside same arched.
00616    So we do not need any special treatment for infosys.
00617     std::string infosys_user("");
00618   */
00619   /*
00620   jobLogPath
00621 
00622   jobReport
00623     destination
00624     expiration
00625     type
00626     parameters
00627     keyPath
00628     certificatePath
00629     CACertificatesDir
00630   */
00631   tmp_node = cfg["jobLogPath"];
00632   if(tmp_node) {
00633     std::string fname = tmp_node;
00634     job_log.SetOutput(fname.c_str());
00635   };
00636   tmp_node = cfg["jobReport"];
00637   if(tmp_node) {
00638     std::string url = tmp_node["destination"];
00639     if(!url.empty()) {
00640       // destination is required
00641       job_log.SetReporter(url.c_str());
00642       unsigned int i;
00643       if(Arc::stringto(tmp_node["expiration"],i)) job_log.SetExpiration(i);
00644       std::string parameters = tmp_node["parameters"];
00645       if(!parameters.empty()) job_log.set_options(parameters);
00646       std::string jobreport_key = tmp_node["keyPath"];
00647       std::string jobreport_cert = tmp_node["certificatePath"];
00648       std::string jobreport_cadir = tmp_node["CACertificatesDir"];
00649       job_log.set_credentials(jobreport_key,jobreport_cert,jobreport_cadir);
00650     };
00651   };
00652 
00653   /*
00654   loadLimits
00655     maxJobsTracked
00656     maxJobsRun
00657     maxJobsTransfered
00658     maxJobsTransferedAdditional
00659     maxFilesTransfered
00660     maxLoadShare
00661     loadShareType
00662     wakeupPeriod
00663   */
00664   tmp_node = cfg["loadLimits"];
00665   if(tmp_node) {
00666     int max_jobs = -1;
00667     int max_jobs_running = -1;
00668     int max_jobs_processing = -1;
00669     int max_jobs_processing_emergency = -1;
00670     int max_downloads = -1;
00671     int max_share;
00672     unsigned int wakeup_period = JobsList::WakeupPeriod();
00673     elementtoint(tmp_node,"maxJobsTracked",max_jobs,&logger);
00674     elementtoint(tmp_node,"maxJobsRun",max_jobs_running,&logger);
00675     JobsList::SetMaxJobs(max_jobs,max_jobs_running);
00676     elementtoint(tmp_node,"maxJobsTransfered",max_jobs_processing,&logger);
00677     elementtoint(tmp_node,"maxJobsTransferedAdditional",max_jobs_processing_emergency,&logger);
00678     elementtoint(tmp_node,"maxFilesTransfered",max_downloads,&logger);
00679     JobsList::SetMaxJobsLoad(max_jobs_processing,
00680                              max_jobs_processing_emergency,
00681                              max_downloads);
00682     std::string transfer_share = tmp_node["loadShareType"];
00683     if(elementtoint(tmp_node,"maxLoadShare",max_share,&logger) && (max_share > 0) && ! transfer_share.empty()){
00684        JobsList::SetTransferShare(max_share, transfer_share);
00685     }
00686     if(elementtoint(tmp_node,"wakeupPeriod",wakeup_period,&logger)) {
00687       JobsList::SetWakeupPeriod(wakeup_period);
00688     };
00689     Arc::XMLNode share_limit_node;
00690     share_limit_node = tmp_node["shareLimit"];
00691     for(;share_limit_node;++share_limit_node) {
00692       int share_limit = -1;
00693       std::string limited_share = share_limit_node["name"];
00694       if(elementtoint(share_limit_node,"limit",share_limit,&logger) && (share_limit > 0) && ! limited_share.empty()) {
00695         JobsList::AddLimitedShare(limited_share,share_limit);
00696       }
00697     }
00698   }
00699 
00700   /*
00701   dataTransfer
00702     secureTransfer
00703     passiveTransfer
00704     localTransfer
00705     timeouts
00706       minSpeed
00707       minSpeedTime
00708       minAverageSpeed
00709       maxInactivityTime
00710     maxRetries
00711     mapURL (link)
00712       from
00713       to
00714     Globus
00715       gridmapfile
00716       cadir
00717       certpath
00718       keypath
00719       TCPPortRange
00720       UDPPortRange
00721     httpProxy
00722   */
00723   tmp_node = cfg["dataTransfer"];
00724   if(tmp_node) {
00725     int min_speed=0;
00726     int min_speed_time=300;
00727     int min_average_speed=0;
00728     int max_inactivity_time=300;
00729     int max_retries = DEFAULT_MAX_RETRIES;
00730     bool use_secure_transfer = false;
00731     bool use_passive_transfer = true;
00732     bool use_local_transfer = false;
00733     Arc::XMLNode to_node = tmp_node["timeouts"];
00734     if(to_node) {
00735       elementtoint(tmp_node,"minSpeed",min_speed,&logger);
00736       elementtoint(tmp_node,"minSpeedTime",min_speed_time,&logger);
00737       elementtoint(tmp_node,"minAverageSpeed",min_average_speed,&logger);
00738       elementtoint(tmp_node,"maxInactivityTime",max_inactivity_time,&logger);
00739       JobsList::SetSpeedControl(min_speed,min_speed_time,
00740                                 min_average_speed,max_inactivity_time);
00741     };
00742     elementtobool(tmp_node,"passiveTransfer",use_passive_transfer,&logger);
00743     JobsList::SetPassiveTransfer(use_passive_transfer);
00744     elementtobool(tmp_node,"secureTransfer",use_secure_transfer,&logger);
00745     JobsList::SetSecureTransfer(use_secure_transfer);
00746     elementtobool(tmp_node,"localTransfer",use_local_transfer,&logger);
00747     JobsList::SetLocalTransfer(use_local_transfer);
00748     if(elementtoint(tmp_node,"maxRetries",max_retries,&logger) && (max_retries > 0)) {
00749         JobsList::SetMaxRetries(max_retries);
00750     }
00751 
00752 
00753   };
00754   /*
00755   serviceMail
00756   */
00757   tmp_node = cfg["serviceMail"];
00758   if(tmp_node) {
00759     support_mail_address((std::string)tmp_node);
00760     if(support_mail_address().empty()) {
00761       logger.msg(Arc::ERROR,"serviceMail is empty");
00762       return false;
00763     };
00764   }
00765 
00766   /*
00767   LRMS
00768     type
00769     defaultShare
00770   */
00771   tmp_node = cfg["LRMS"];
00772   if(tmp_node) {
00773     default_lrms = (std::string)(tmp_node["type"]);
00774     if(default_lrms.empty()) {
00775       logger.msg(Arc::ERROR,"type in LRMS is missing"); return false;
00776     };
00777     default_queue = (std::string)(tmp_node["defaultShare"]);
00778     check_lrms_backends(default_lrms);
00779     runtime_config_dir((std::string)(tmp_node["runtimeDir"]));
00780   } else {
00781     logger.msg(Arc::ERROR,"LRMS is missing"); return false;
00782   }
00783 
00784   /*
00785   authPlugin (timeout,onSuccess=PASS,FAIL,LOG,onFailure=FAIL,PASS,LOG,onTimeout=FAIL,PASS,LOG)
00786     state
00787     command
00788   */
00789   tmp_node = cfg["authPlugin"];
00790   for(;tmp_node;++tmp_node) {
00791     std::string state_name = tmp_node["state"];
00792     if(state_name.empty()) {
00793       logger.msg(Arc::ERROR,"state name for authPlugin is missing");
00794       return false;
00795     };
00796     std::string command = tmp_node["command"];
00797     if(state_name.empty()) {
00798       logger.msg(Arc::ERROR,"command for authPlugin is missing");
00799       return false;
00800     };
00801     std::string options;
00802     Arc::XMLNode onode;
00803     onode = tmp_node.Attribute("timeout");
00804     if(onode) options+="timeout="+(std::string)onode;
00805     onode = tmp_node.Attribute("onSuccess");
00806     if(onode) options+="onsuccess="+Arc::lower((std::string)onode);
00807     onode = tmp_node.Attribute("onFailure");
00808     if(onode) options+="onfailure="+Arc::lower((std::string)onode);
00809     onode = tmp_node.Attribute("onTimeout");
00810     if(onode) options+="ontimeout="+Arc::lower((std::string)onode);
00811     if(!plugins.add(state_name.c_str(),options.c_str(),command.c_str())) {
00812       logger.msg(Arc::ERROR,"Failed to register plugin for state %s",state_name);
00813       return false;
00814     };
00815   };
00816 
00817   /*
00818   localCred (timeout)
00819     command
00820   */
00821   tmp_node = cfg["localCred"];
00822   if(tmp_node) {
00823     std::string command = tmp_node["command"];
00824     if(command.empty()) {
00825       logger.msg(Arc::ERROR,"command for localCred is missing");
00826       return false;
00827     };
00828     std::string options;
00829     Arc::XMLNode onode;
00830     onode = tmp_node.Attribute("timeout");
00831     if(!onode) {
00832       logger.msg(Arc::ERROR,"timeout for localCred is missing");
00833       return false;
00834     };
00835     int to;
00836     if(!elementtoint(onode,NULL,to,&logger)) {
00837       logger.msg(Arc::ERROR,"timeout for localCred is incorrect number");
00838       return false;
00839     };
00840     cred_plugin = command;
00841     cred_plugin.timeout(to);
00842   }
00843 
00844   /*
00845   control
00846     username
00847     controlDir
00848     sessionRootDir
00849     cache
00850       location
00851         path
00852         link
00853       highWatermark
00854       lowWatermark
00855     defaultTTL
00856     defaultTTR
00857     maxReruns
00858     noRootPower
00859     diskSpace
00860   */
00861 
00862   tmp_node = cfg["control"];
00863   if(!tmp_node) {
00864     logger.msg(Arc::ERROR,"At least one control element must be present");
00865     return false;
00866   };
00867   for(;tmp_node;++tmp_node) {
00868     std::string control_dir = tmp_node["controlDir"];
00869     if(control_dir.empty()) {
00870       logger.msg(Arc::ERROR,"controlDir is missing"); return false;
00871     };
00872     if(control_dir == "*") control_dir="";
00873     session_roots.clear();
00874     Arc::XMLNode session_node = tmp_node["sessionRootDir"];
00875     std::string session_root;
00876     for (;session_node; ++session_node) {
00877       session_root = std::string(session_node);
00878       if(session_root.empty()) {
00879         logger.msg(Arc::ERROR,"sessionRootDir is missing"); return false;
00880       };
00881       if (session_root.find(' ') != std::string::npos)
00882         session_root = session_root.substr(0, session_root.find(' '));
00883       session_roots.push_back(session_root);
00884     }
00885     last_control_dir = control_dir;
00886     bool strict_session = false;
00887     if(!elementtobool(tmp_node,"noRootPower",strict_session,&logger)) return false;
00888     unsigned int default_reruns = DEFAULT_JOB_RERUNS;
00889     unsigned int default_ttl = DEFAULT_KEEP_FINISHED;
00890     unsigned int default_ttr = DEFAULT_KEEP_DELETED;
00891     int default_diskspace = DEFAULT_DISKSPACE;
00892     if(!elementtoint(tmp_node,"maxReruns",default_reruns,&logger)) return false;
00893     if(!elementtoint(tmp_node,"defaultTTL",default_ttl,&logger)) return false;
00894     if(!elementtoint(tmp_node,"defaultTTR",default_ttr,&logger)) return false;
00895     if(!elementtoint(tmp_node,"defaultDiskSpace",default_diskspace,&logger)) return false;
00896     Arc::XMLNode unode = tmp_node["username"];
00897     std::list<std::string> userlist;
00898     for(;unode;++unode) {
00899       std::string username = unode;
00900       if(username.empty()) {
00901         logger.msg(Arc::ERROR,"username in control is empty"); return false;
00902       };
00903       if(username == "*") {  /* add all gridmap users */
00904         if(!gridmap_user_list(userlist)) {
00905           logger.msg(Arc::ERROR,"Can't read users in gridmap file %s",globus_gridmap());
00906           return false;
00907         };
00908         continue;
00909       };
00910       if(username == ".") {  /* accept all users in this control directory */
00911          /* !!!!!!! substitutions involving user names won't work !!!!!!!  */
00912          if(superuser) { username=""; }
00913          else { username=my_username; };
00914       };
00915       userlist.push_back(username);
00916     };
00917     if(userlist.size() == 0) {
00918       logger.msg(Arc::ERROR,"No username entries in control"); return false;
00919     };
00920     for(std::list<std::string>::iterator username = userlist.begin();
00921                    username != userlist.end();++username) {
00922       /* add new user to list */
00923       if(superuser || (my_username == *username)) {
00924         if(users.HasUser(*username)) { /* first is best */
00925           continue;
00926         };
00927         JobUsers::iterator user=users.AddUser(*username,&cred_plugin,
00928                                      control_dir,&session_roots);
00929         if(user == users.end()) { /* bad bad user */
00930           logger.msg(Arc::WARNING,"Warning: creation of user \"%s\" failed",*username);
00931         }
00932         else {
00933           std::string control_dir_ = control_dir;
00934           user->SetLRMS(default_lrms,default_queue);
00935           user->SetKeepFinished(default_ttl);
00936           user->SetKeepDeleted(default_ttr);
00937           user->SetReruns(default_reruns);
00938           user->SetDiskSpace(default_diskspace);
00939           user->substitute(control_dir_);
00940           for(std::vector<std::string>::iterator i = session_roots.begin(); i != session_roots.end(); i++) {
00941             user->substitute(*i);
00942           }
00943           user->SetControlDir(control_dir_);
00944           user->SetSessionRoot(session_roots);
00945           user->SetStrictSession(strict_session);
00946           // get cache parameters for this user
00947           try {
00948             CacheConfig * cache_config = new CacheConfig(user->UnixName());
00949             user->SetCacheParams(cache_config);
00950           }
00951           catch (CacheConfigException e) {
00952             logger.msg(Arc::ERROR, "Error with cache configuration: %s", e.what());
00953             return false;
00954           }
00955           /* add helper to poll for finished jobs */
00956           std::string cmd_ = nordugrid_libexec_loc();
00957           make_escaped_string(control_dir_);
00958           cmd_+="/scan-"+default_lrms+"-job";
00959           make_escaped_string(cmd_);
00960           cmd_+=" ";
00961           cmd_+=control_dir_;
00962           user->add_helper(cmd_);
00963           /* creating empty list of jobs */
00964           JobsList *jobs = new JobsList(*user,plugins);
00965           (*user)=jobs; /* back-associate jobs with user :) */
00966         };
00967       };
00968     };
00969   };
00970   /*
00971   helperUtility
00972     username
00973     command
00974   */
00975   tmp_node = cfg["helperUtility"];
00976   for(;tmp_node;++tmp_node) {
00977     std::string command = tmp_node["command"];
00978     if(command.empty()) {
00979       logger.msg(Arc::ERROR,"command in helperUtility is missing");
00980       return false;
00981     };
00982     Arc::XMLNode unode = tmp_node["username"];
00983     for(;unode;++unode) {
00984       std::string username = unode;
00985       if(username.empty()) {
00986         logger.msg(Arc::ERROR,"username in helperUtility is empty");
00987         return false;
00988       };
00989       if(username == "*") {  /* go through all configured users */
00990         for(JobUsers::iterator user=users.begin();user!=users.end();++user) {
00991           if(!(user->has_helpers())) {
00992             std::string command_=command;
00993             user->substitute(command_);
00994             user->add_helper(command_);
00995           };
00996         };
00997       }
00998       else if(username == ".") { /* special helper */
00999         // Take parameters of last control
01000         std::string control_dir_ = last_control_dir;
01001         my_user.SetLRMS(default_lrms,default_queue);
01002         my_user.substitute(control_dir_);
01003         my_user.SetSessionRoot(session_roots);
01004         my_user.SetControlDir(control_dir_);
01005         std::string command_=command;
01006         users.substitute(command_);
01007         my_user.substitute(command_);
01008         my_user.add_helper(command_);
01009       }
01010       else {
01011         /* look for that user */
01012         JobUsers::iterator user=users.find(username);
01013         if(user == users.end()) {
01014           logger.msg(Arc::ERROR,"User %s for helperUtility is not configured",
01015                      username);
01016           return false;
01017         };
01018         std::string command_=command;
01019         user->substitute(command_);
01020         user->add_helper(command_);
01021       };
01022     };
01023   };
01024   return true;
01025 }
01026 
01027 bool print_serviced_users(const JobUsers &users) {
01028   for(JobUsers::const_iterator user = users.begin();user!=users.end();++user) {
01029     logger.msg(Arc::INFO,"Added user : %s",user->UnixName());
01030     for(std::vector<std::string>::const_iterator i = user->SessionRoots().begin(); i != user->SessionRoots().end(); i++)
01031       logger.msg(Arc::INFO,"\tSession root dir : %s",*i);
01032     logger.msg(Arc::INFO,"\tControl dir      : %s",user->ControlDir());
01033     logger.msg(Arc::INFO,"\tdefault LRMS     : %s",user->DefaultLRMS());
01034     logger.msg(Arc::INFO,"\tdefault queue    : %s",user->DefaultQueue());
01035     logger.msg(Arc::INFO,"\tdefault ttl      : %u",user->KeepFinished());
01036 
01037     CacheConfig * cache_config = user->CacheParams();
01038 
01039     if(!cache_config) {
01040       logger.msg(Arc::INFO,"No valid caches found in configuration, caching is disabled");
01041       continue;
01042     }
01043 
01044     std::vector<std::string> conf_caches = cache_config->getCacheDirs();
01045     std::vector<std::string> remote_conf_caches = cache_config->getRemoteCacheDirs();
01046     if(conf_caches.empty()) {
01047       logger.msg(Arc::INFO,"No valid caches found in configuration, caching is disabled");
01048       continue;
01049     }
01050     // list each cache
01051     for (std::vector<std::string>::iterator i = conf_caches.begin(); i != conf_caches.end(); i++) {
01052       logger.msg(Arc::INFO, "\tCache            : %s", (*i).substr(0, (*i).find(" ")));
01053       if ((*i).find(" ") != std::string::npos)
01054         logger.msg(Arc::INFO, "\tCache link dir   : %s", (*i).substr((*i).find_last_of(" ")+1, (*i).length()-(*i).find_last_of(" ")+1));
01055     }
01056     // list each remote cache
01057     for (std::vector<std::string>::iterator i = remote_conf_caches.begin(); i != remote_conf_caches.end(); i++) {
01058       logger.msg(Arc::INFO, "\tRemote cache     : %s", (*i).substr(0, (*i).find(" ")));
01059       if ((*i).find(" ") != std::string::npos) 
01060         logger.msg(Arc::INFO, "\tRemote cache link: %s", (*i).substr((*i).find_last_of(" ")+1, (*i).length()-(*i).find_last_of(" ")+1));
01061     }
01062     if (cache_config->cleanCache())
01063       logger.msg(Arc::INFO, "\tCache cleaning enabled");
01064     else
01065       logger.msg(Arc::INFO, "\tCache cleaning disabled");
01066   };
01067   return true;
01068 }
01069