Back to index

nordugrid-arc-nox  1.1.0~rc6
users.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 /* 
00005   Filename: users.cc
00006   keeps list of users
00007 */
00008 
00009 #include <sys/stat.h>
00010 #include <sys/types.h>
00011 #include <unistd.h>
00012 #include <errno.h>
00013 #include <pwd.h>
00014 #include <arc/StringConv.h>
00015 #include <arc/Logger.h>
00016 #include <arc/Utils.h>
00017 
00018 #include <string>
00019 #include <list>
00020 
00021 #include "../conf/conf.h"
00022 #include "../run/run_parallel.h"
00023 #include "../misc/escaped.h"
00024 #include "../jobs/states.h"
00025 #include "../conf/environment.h"
00026 #include "users.h"
00027 
00028 static Arc::Logger& logger = Arc::Logger::getRootLogger();
00029 static std::string empty_string("");
00030 
00031 JobUser::JobUser(void) {
00032   control_dir="";
00033   unix_name=""; home=""; uid=0; gid=0;
00034   cache_params=NULL;
00035   valid=false; jobs=NULL;
00036   keep_finished=DEFAULT_KEEP_FINISHED;
00037   keep_deleted=DEFAULT_KEEP_DELETED;
00038   cred_plugin=NULL;
00039   strict_session=false;
00040   sharelevel=jobinfo_share_private;
00041 }
00042 
00043 void JobUser::SetLRMS(const std::string &lrms_name,const std::string &queue_name) {
00044   default_lrms=lrms_name;
00045   default_queue=queue_name;
00046 }
00047 
00048 void JobUser::SetControlDir(const std::string &dir) {
00049   if(dir.length() == 0) {
00050     control_dir=home + "/.jobstatus";
00051   }
00052   else { control_dir=dir; };
00053 }
00054 
00055 void JobUser::SetSessionRoot(const std::string &dir) {
00056   session_roots.clear();
00057   if(dir.length() == 0 || dir == "*") { session_roots.push_back(home + "/.jobs"); }
00058   else { session_roots.push_back(dir); };
00059 }
00060 
00061 void JobUser::SetSessionRoot(const std::vector<std::string> &dirs) {
00062   session_roots.clear();
00063   if (dirs.empty()) {
00064     std::string dir;
00065     SetSessionRoot(dir);
00066   } else {
00067     for (std::vector<std::string>::const_iterator i = dirs.begin(); i != dirs.end(); i++) {
00068       if (*i == "*") session_roots.push_back(home + "/.jobs");
00069       else session_roots.push_back(*i);
00070     }
00071   }
00072 }
00073 
00074 const std::string & JobUser::SessionRoot(std::string job_id) const {
00075   if (session_roots.size() == 0) return empty_string;
00076   if (session_roots.size() == 1 || job_id.empty()) return session_roots[0];
00077   // search for this jobid's session dir
00078   struct stat st;
00079   for (std::vector<std::string>::const_iterator i = session_roots.begin(); i != session_roots.end(); i++) {
00080     std::string sessiondir(*i + '/' + job_id);
00081     if (stat(sessiondir.c_str(), &st) == 0 && S_ISDIR(st.st_mode))
00082       return *i;
00083   }
00084   return empty_string; // not found
00085 }
00086 
00087 void JobUser::SetCacheParams(CacheConfig* params) {
00088   std::vector<std::string> cache_dirs = params->getCacheDirs();
00089   for (std::vector<std::string>::iterator i = cache_dirs.begin(); i != cache_dirs.end(); i++) {
00090     substitute(*i);
00091   }
00092   params->setCacheDirs(cache_dirs);
00093   std::vector<std::string> drain_cache_dirs = params->getDrainingCacheDirs();
00094   for (std::vector<std::string>::iterator i = drain_cache_dirs.begin(); i != drain_cache_dirs.end(); i++) {
00095     substitute(*i);
00096   }
00097   params->setDrainingCacheDirs(drain_cache_dirs);
00098   cache_params = params;
00099 }
00100 
00101 bool JobUser::CreateDirectories(void) {
00102   bool res = true;
00103   if(control_dir.length() != 0) {
00104     if(mkdir(control_dir.c_str(),S_IRWXU) != 0) {
00105       if(errno != EEXIST) res=false;
00106     } else {
00107       (chown(control_dir.c_str(),uid,gid) != 0);
00108       if(uid == 0) {
00109         chmod(control_dir.c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
00110       } else {
00111         chmod(control_dir.c_str(),S_IRUSR | S_IWUSR | S_IXUSR);
00112       };
00113     };
00114     if(mkdir((control_dir+"/logs").c_str(),S_IRWXU) != 0) {
00115       if(errno != EEXIST) res=false;
00116     } else {
00117       (chown((control_dir+"/logs").c_str(),uid,gid) != 0);
00118     };
00119   };
00120   if(session_roots.size() != 0) {
00121     for(std::vector<std::string>::iterator i = session_roots.begin(); i != session_roots.end(); i++) {
00122       if(mkdir(i->c_str(),S_IRWXU) != 0) {
00123         if(errno != EEXIST) res=false;
00124       } else {
00125         (chown(i->c_str(),uid,gid) != 0);
00126         if(uid == 0) {
00127           chmod(i->c_str(),S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
00128         } else {
00129           chmod(i->c_str(),S_IRUSR | S_IWUSR | S_IXUSR);
00130         };
00131       };
00132     };
00133   };
00134   return res;
00135 }
00136 
00137 /*
00138   %R - session root
00139   %r - list of session roots
00140   %C - control dir
00141   %c - list of control dirs
00142   %U - username
00143   %u - userid
00144   %g - groupid
00145   %H - home dir
00146   %Q - default queue
00147   %L - default lrms
00148   %W - installation path
00149   %G - globus path
00150 */
00151 
00152 bool JobUser::substitute(std::string& param) const {
00153   std::string::size_type curpos=0;
00154   for(;;) {
00155     if(curpos >= param.length()) break;
00156     std::string::size_type pos = param.find('%',curpos);
00157     if(pos == std::string::npos) break;
00158     pos++; if(pos>=param.length()) break;
00159     if(param[pos] == '%') { curpos=pos+1; continue; };
00160     std::string to_put;
00161     switch(param[pos]) {
00162       case 'R': to_put=SessionRoot(); break;
00163       case 'C': to_put=ControlDir(); break;
00164       case 'U': to_put=UnixName(); break;
00165       case 'H': to_put=Home(); break;
00166       case 'Q': to_put=DefaultQueue(); break;
00167       case 'L': to_put=DefaultLRMS(); break;
00168       case 'u': to_put=Arc::tostring(get_uid()); break;
00169       case 'g': to_put=Arc::tostring(get_gid()); break;
00170       case 'W': to_put=nordugrid_loc(); break;
00171       case 'G': to_put=globus_loc(); break;
00172       default: to_put=param.substr(pos-1,2);
00173     };
00174     curpos=pos+1+(to_put.length() - 2);
00175     param.replace(pos-1,2,to_put);
00176   };
00177   return true;
00178 }
00179 
00180 bool JobUsers::substitute(std::string& param) const {
00181   std::string session_roots = "";
00182   std::string control_dirs = "";
00183   for(JobUsers::const_iterator i = begin();i!=end();++i) {
00184     std::string tmp_s;
00185     tmp_s = i->SessionRoot();
00186     make_escaped_string(tmp_s);
00187     tmp_s=tmp_s+" ";
00188     if(session_roots.find(tmp_s) == std::string::npos) session_roots+=tmp_s;
00189     tmp_s = i->ControlDir();
00190     make_escaped_string(tmp_s);
00191     tmp_s=tmp_s+" ";
00192     if(control_dirs.find(tmp_s) == std::string::npos) control_dirs+=tmp_s;
00193   };
00194   std::string::size_type curpos=0;
00195   for(;;) {
00196     if(curpos >= param.length()) break;
00197     std::string::size_type pos = param.find('%',curpos);
00198     if(pos == std::string::npos) break;
00199     pos++; if(pos>=param.length()) break;
00200     if(param[pos] == '%') { curpos=pos+1; continue; };
00201     std::string to_put;
00202     switch(param[pos]) {
00203       case 'r': to_put=session_roots; break;
00204       case 'c': to_put=control_dirs; break;
00205       default: to_put=param.substr(pos-1,2);
00206     };
00207     curpos=pos+1+(to_put.length() - 2);
00208     param.replace(pos-1,2,to_put);
00209   };
00210   return true;
00211 }
00212 
00213 JobUser::JobUser(uid_t uid_,RunPlugin* cred) {
00214   struct passwd pw_;
00215   struct passwd *pw;
00216   char buf[BUFSIZ];
00217   uid=uid_;
00218   valid=false;
00219   cred_plugin=cred;
00220   /* resolve name */
00221   if(uid_ == 0) {
00222     unix_name="";  
00223     gid=0;
00224     home="/tmp";
00225     valid=true;
00226   }
00227   else {
00228     getpwuid_r(uid_,&pw_,buf,BUFSIZ,&pw);
00229     if(pw != NULL) {
00230       unix_name=pw->pw_name;  
00231       gid=pw->pw_gid;
00232       home=pw->pw_dir;
00233       valid=true;
00234     };
00235   };
00236   jobs=NULL;
00237   cache_params=NULL;
00238   SetControlDir("");
00239   SetSessionRoot("");
00240   SetLRMS("","");
00241   keep_finished=DEFAULT_KEEP_FINISHED;
00242   keep_deleted=DEFAULT_KEEP_DELETED;
00243   strict_session=false;
00244   sharelevel=jobinfo_share_private;
00245 }
00246 
00247 JobUser::JobUser(const std::string &u_name,RunPlugin* cred) {
00248   struct passwd pw_;
00249   struct passwd *pw;
00250   char buf[BUFSIZ];
00251   unix_name=u_name;  
00252   cred_plugin=cred;
00253   valid=false;
00254   /* resolve name */
00255   if(u_name.length() == 0) {
00256     uid=0;  
00257     gid=0;
00258     home="/tmp";
00259     valid=true;
00260   }
00261   else {
00262     getpwnam_r(u_name.c_str(),&pw_,buf,BUFSIZ,&pw);
00263     if(pw != NULL) {
00264       uid=pw->pw_uid;
00265       gid=pw->pw_gid;
00266       home=pw->pw_dir;
00267       valid=true;
00268     };
00269   };
00270   SetControlDir("");
00271   SetSessionRoot("");
00272   SetLRMS("","");
00273   jobs=NULL;
00274   cache_params=NULL;
00275   keep_finished=DEFAULT_KEEP_FINISHED;
00276   keep_deleted=DEFAULT_KEEP_DELETED;
00277   strict_session=false;
00278   sharelevel=jobinfo_share_private;
00279 }
00280 
00281 JobUser::JobUser(const JobUser &user) {
00282   uid=user.uid; gid=user.gid;
00283   unix_name=user.unix_name;  
00284   control_dir=user.control_dir;
00285   home=user.home;
00286   jobs=user.jobs;
00287   session_roots=user.session_roots;
00288   default_lrms=user.default_lrms;
00289   default_queue=user.default_queue;
00290   valid=user.valid;
00291   keep_finished=user.keep_finished;
00292   keep_deleted=user.keep_deleted;
00293   cache_params=user.cache_params;
00294   cred_plugin=user.cred_plugin;
00295   strict_session=user.strict_session;
00296   sharelevel=user.sharelevel;
00297 }
00298 
00299 JobUser::~JobUser(void) { 
00300   delete cache_params;
00301 }
00302 
00303 JobUsers::JobUsers(void) {
00304 }
00305 
00306 JobUsers::~JobUsers(void) {
00307 }
00308 
00309 JobUsers::iterator JobUsers::AddUser(const std::string &unix_name,RunPlugin* cred_plugin,const std::string &control_dir, const std::vector<std::string> *session_roots) {
00310   JobUser user(unix_name,cred_plugin);
00311   user.SetControlDir(control_dir);
00312   if(session_roots) user.SetSessionRoot(*session_roots);
00313   if(user.is_valid()) { return users.insert(users.end(),user); };
00314   return users.end();
00315 }
00316 
00317 std::string JobUsers::ControlDir(iterator user) {
00318   if(user == users.end()) return std::string("");
00319   return (*user).ControlDir();
00320 }
00321 
00322 JobUsers::iterator JobUsers::find(const std::string user) {
00323   iterator i;
00324   for(i=users.begin();i!=users.end();++i) {
00325     if((*i) == user) break;
00326   };
00327   return i;
00328 }
00329 
00330 std::string JobUsers::ControlDir(const std::string user) {
00331   for(iterator i=users.begin();i!=users.end();++i) {
00332     if((*i) == user) return (*i).ControlDir();
00333   };
00334   return std::string("");
00335 }
00336 
00337 #ifndef NO_GLOBUS_CODE
00338 
00339 /* change effective user - real switch is done only if running as root */
00340 bool JobUser::SwitchUser(bool su) const {
00341   std::string uid_s = Arc::tostring(uid);
00342   if(!Arc::SetEnv("USER_ID",uid_s)) if(!su) return false;
00343   if(!Arc::SetEnv("USER_NAME",unix_name)) if(!su) return false;
00344   /* set proper umask */
00345   umask(0177);
00346   if(!su) return true;
00347   uid_t cuid;
00348   if(((cuid=getuid()) != 0) && (uid != 0)) {
00349     if(cuid != uid) return false;
00350   };
00351   if(uid != 0) {
00352     setgid(gid); /* this is not an error if group failed, not a big deal */
00353     if(setuid(uid) != 0) return false;
00354   };
00355   return true;
00356 }
00357 
00358 bool JobUser::run_helpers(void) {
00359 //  if(unix_name.length() == 0) { /* special users can not run helpers */
00360 //    return true;  
00361 //  };
00362   bool started = true;
00363   for(std::list<JobUserHelper>::iterator i=helpers.begin();i!=helpers.end();++i) {
00364     started &= i->run(*this);
00365   };
00366   return started;
00367 }
00368 
00369 bool JobUsers::run_helpers(void) {
00370   for(iterator i=users.begin();i!=users.end();++i) {
00371     i->run_helpers();
00372   };
00373   return true;
00374 }
00375 #endif // NO_GLOBUS_CODE
00376 
00377 JobUserHelper::JobUserHelper(const std::string &cmd) {
00378   command=cmd;
00379   proc=NULL;
00380 }
00381   
00382 JobUserHelper::~JobUserHelper(void) {
00383 #ifndef NO_GLOBUS_CODE
00384     if(proc != NULL) {
00385       delete proc;
00386       proc=NULL;
00387     };
00388 #endif
00389 }
00390 
00391 #ifndef NO_GLOBUS_CODE
00392 bool JobUserHelper::run(JobUser &user) {
00393     if(proc != NULL) {
00394       if(proc->Running()) {
00395         return true; /* it is already/still running */
00396       };
00397       delete proc;
00398       proc=NULL;
00399     };
00400     /* start/restart */
00401     if(command.length() == 0) return true;  /* has anything to run ? */
00402     char* args[100]; /* up to 98 arguments should be enough */
00403     std::string args_s = command;
00404     std::string arg_s;
00405     int n;
00406     for(n=0;n<99;n++) {
00407       arg_s=config_next_arg(args_s);
00408       if(arg_s.length() == 0) break;
00409       args[n]=strdup(arg_s.c_str());
00410     };
00411     args[n]=NULL;
00412     logger.msg(Arc::VERBOSE,"Starting helper process (%s): %s",
00413                user.UnixName().c_str(),command.c_str());
00414     std::string helper_id="helper."+user.UnixName();
00415     bool started=RunParallel::run(user,helper_id.c_str(),args,&proc);
00416     for(n=0;n<99;n++) {
00417       if(args[n] == NULL) break;
00418       free(args[n]);
00419     };
00420     if(started) return true;
00421     if(proc && (*proc)) return true;
00422     if(proc) { delete proc; proc=NULL; };
00423     logger.msg(Arc::ERROR,"Helper process start failed (%s): %s",
00424                user.UnixName().c_str(),command.c_str());
00425     /* start failed */
00426     /* doing nothing - maybe in the future */
00427     return false;
00428 }
00429 #endif
00430