void VMUniverseMgr::killVM(const char *matchstring) { if ( !matchstring ) { return; } if( !m_vm_type.Length() || !m_vmgahp_server.Length() ) { return; } // vmgahp is daemonCore, so we need to add -f -t options of daemonCore. // Then, try to execute vmgahp with // vmtype <vmtype> match <string>" ArgList systemcmd; systemcmd.AppendArg(m_vmgahp_server); systemcmd.AppendArg("-f"); char *gahp_log_file = param("VM_GAHP_LOG"); if( gahp_log_file ) { free(gahp_log_file); }else { systemcmd.AppendArg("-t"); } systemcmd.AppendArg("-M"); systemcmd.AppendArg(VMGAHP_KILL_MODE); systemcmd.AppendArg("vmtype"); systemcmd.AppendArg(m_vm_type); systemcmd.AppendArg("match"); systemcmd.AppendArg(matchstring); #if !defined(WIN32) if( can_switch_ids() ) { MyString tmp_str; tmp_str.formatstr("%d", (int)get_condor_uid()); SetEnv("VMGAHP_USER_UID", tmp_str.Value()); } #endif // execute vmgahp with root privilege priv_state priv = set_root_priv(); int ret = my_system(systemcmd); // restore privilege set_priv(priv); if( ret == 0 ) { dprintf( D_ALWAYS, "VMUniverseMgr::killVM() is called with " "'%s'\n", matchstring ); }else { dprintf( D_ALWAYS, "VMUniverseMgr::killVM() failed!\n"); } return; }
bool SpooledJobFiles::chownSpoolDirectoryToCondor(ClassAd const *job_ad) { bool result = true; #ifndef WIN32 std::string sandbox; int cluster=-1,proc=-1; job_ad->LookupInteger(ATTR_CLUSTER_ID,cluster); job_ad->LookupInteger(ATTR_PROC_ID,proc); getJobSpoolPath(cluster, proc, sandbox); uid_t src_uid = 0; uid_t dst_uid = get_condor_uid(); gid_t dst_gid = get_condor_gid(); MyString jobOwner; job_ad->LookupString( ATTR_OWNER, jobOwner ); passwd_cache* p_cache = pcache(); if( p_cache->get_user_uid( jobOwner.Value(), src_uid ) ) { if( ! recursive_chown(sandbox.c_str(), src_uid, dst_uid, dst_gid, true) ) { dprintf( D_FULLDEBUG, "(%d.%d) Failed to chown %s from " "%d to %d.%d. User may run into permissions " "problems when fetching sandbox.\n", cluster, proc, sandbox.c_str(), src_uid, dst_uid, dst_gid ); result = false; } } else { dprintf( D_ALWAYS, "(%d.%d) Failed to find UID and GID " "for user %s. Cannot chown \"%s\". User may " "run into permissions problems when fetching " "job sandbox.\n", cluster, proc, jobOwner.Value(), sandbox.c_str() ); result = false; } #endif return result; }
void initialize_uids(void) { #if defined(WIN32) #include "my_username.h" char *name = NULL; char *domain = NULL; name = my_username(); domain = my_domainname(); caller_name = name; job_user_name = name; if ( !init_user_ids(name, domain ) ) { // shouldn't happen - we always can get our own token vmprintf(D_ALWAYS, "Could not initialize user_priv with our own token!\n"); } vmprintf(D_ALWAYS, "Initialize Uids: caller=%s@%s, job user=%s@%s\n", caller_name.Value(), domain, job_user_name.Value(), domain); if( name ) { free(name); } if( domain ) { free(domain); } return; #else // init_user_ids was called in main_pre_dc_init() vmprintf(D_ALWAYS, "Initial UID/GUID=%d/%d, EUID/EGUID=%d/%d, " "Condor UID/GID=%d,%d\n", (int)getuid(), (int)getuid(), (int)geteuid(), (int)getegid(), (int)get_condor_uid(), (int)get_condor_gid()); vmprintf(D_ALWAYS, "Initialize Uids: caller=%s, job user=%s\n", caller_name.Value(), job_user_name.Value()); return; #endif }
void check_uid_for_privsep() { #if !defined(WIN32) if (param_boolean("PRIVSEP_ENABLED", false) && (getuid() == 0)) { uid_t condor_uid = get_condor_uid(); if (condor_uid == 0) { EXCEPT("PRIVSEP_ENABLED set, but current UID is 0 " "and condor UID is also set to root"); } dprintf(D_ALWAYS, "PRIVSEP_ENABLED set, but UID is 0; " "will drop to UID %u and restart\n", (unsigned)condor_uid); daemons.CleanupBeforeRestart(); set_condor_priv_final(); daemons.ExecMaster(); EXCEPT("attempt to restart (via exec) failed (%s)", strerror(errno)); } #endif }
UserProc::UserProc( STARTUP_INFO &s ) : cluster( s.cluster ), proc( s.proc ), m_a_out( NULL ), core_name( NULL ), uid( s.uid ), gid( s.gid ), v_pid( s.virt_pid ), pid( 0 ), job_class( s.job_class ), state( NEW ), user_time( 0 ), sys_time( 0 ), exit_status_valid( FALSE ), exit_status( 0 ), ckpt_wanted( s.ckpt_wanted ), soft_kill_sig( s.soft_kill_sig ), new_ckpt_created( FALSE ), ckpt_transferred( FALSE ), core_created( FALSE ), core_transferred( FALSE ), exit_requested( FALSE ), image_size( -1 ), guaranteed_user_time( 0 ), guaranteed_sys_time( 0 ), pids_suspended( -1 ) { MyString buf; mode_t omask; cmd = new char [ strlen(s.cmd) + 1 ]; strcpy( cmd, s.cmd ); // Since we are adding to the argument list, we may need to deal // with platform-specific arg syntax in the user's args in order // to successfully merge them with the additional args. args.SetArgV1SyntaxToCurrentPlatform(); MyString args_errors; if(!args.AppendArgsV1or2Raw(s.args_v1or2,&args_errors)) { EXCEPT("ERROR: Failed to parse arguments string: %s\n%s", args_errors.Value(),s.args_v1or2); } // set up environment as an object MyString env_errors; if(!env_obj.MergeFromV1or2Raw( s.env_v1or2,&env_errors )) { EXCEPT("ERROR: Failed to parse environment string: %s\n%s", env_errors.Value(),s.env_v1or2); } // add name of SMP slot (from startd) into environment setSlotEnv(&env_obj); /* Port regulation for user job */ int low_port, high_port; // assume outgoing port range if (get_port_range(TRUE, &low_port, &high_port) == TRUE) { buf.formatstr( "_condor_LOWPORT=%d", low_port); env_obj.SetEnv(buf.Value()); buf.formatstr( "_condor_HIGHPORT=%d", high_port); env_obj.SetEnv(buf.Value()); } /* end - Port regulation for user job */ if( param_boolean("BIND_ALL_INTERFACES", true) ) { buf.formatstr( "_condor_BIND_ALL_INTERFACES=TRUE" ); } else { buf.formatstr( "_condor_BIND_ALL_INTERFACES=FALSE" ); } env_obj.SetEnv(buf.Value()); // Generate a directory where process can run and do its checkpointing omask = umask(0); buf.formatstr( "dir_%d", getpid() ); local_dir = new char [ buf.Length() + 1 ]; strcpy( local_dir, buf.Value() ); if (privsep_enabled()) { // the Switchboard expects a full path to privsep_create_dir MyString local_dir_path; local_dir_path.formatstr("%s/%s", Execute, local_dir); if (!privsep_create_dir(get_condor_uid(), local_dir_path.Value())) { EXCEPT("privsep_create_dir failure"); } if (chmod(local_dir_path.Value(), LOCAL_DIR_MODE) == -1) { EXCEPT("chmod failure after privsep_create_dir"); } } else { if( mkdir(local_dir,LOCAL_DIR_MODE) < 0 ) { EXCEPT( "mkdir(%s,0%o)", local_dir, LOCAL_DIR_MODE ); } } (void)umask(omask); // Now that we know what the local_dir is, put the path into // the environment so the job knows where it is MyString scratch_env; scratch_env.formatstr("CONDOR_SCRATCH_DIR=%s/%s",Execute,local_dir); env_obj.SetEnv(scratch_env.Value()); buf.formatstr( "%s/condor_exec.%d.%d", local_dir, cluster, proc ); cur_ckpt = new char [ buf.Length() + 1 ]; strcpy( cur_ckpt, buf.Value() ); // Find out if user wants checkpointing #if defined(NO_CKPT) ckpt_wanted = FALSE; dprintf(D_ALWAYS, "This platform doesn't implement checkpointing yet\n" ); #else ckpt_wanted = s.ckpt_wanted; #endif restart = s.is_restart; coredump_limit_exists = s.coredump_limit_exists; coredump_limit = s.coredump_limit; }
static void check_execute_dir_perms( char const *exec_path ) { struct stat st; if (stat(exec_path, &st) < 0) { EXCEPT( "stat exec path (%s), errno: %d (%s)", exec_path, errno, strerror( errno ) ); } // in PrivSep mode, the EXECUTE directory must be trusted by // the PrivSep kernel. we can't determine this ourselves in general // (since the PrivSep Switchboard can be recompiled to trust // non-root users), so we'll have to be satisfied for now that we // could stat its path // if (privsep_enabled()) { return; } // the following logic sets up the new_mode variable, depending // on the execute dir's current perms. if new_mode is set non-zero, // it means we need to do a chmod // mode_t new_mode = 0; #if defined(WIN32) mode_t desired_mode = _S_IREAD | _S_IWRITE; if ((st.st_mode & desired_mode) != desired_mode) { new_mode = st.st_mode | desired_mode; } #else // we want to avoid having our execute directory world-writable // if possible. it's possible if the execute directory is owned // by condor and either: // - we're not switching UIDs. in this case, job sandbox dirs // will just be owned by the condor UID, so we just need // owner-writability // - there's no root squash on the execute dir (since then we // can do a mkdir as the condor UID then a chown to the job // owner UID) // // additionally, the GLEXEC_JOB feature requires world-writability // on the execute dir // bool glexec_job = param_boolean("GLEXEC_JOB", false); if ((st.st_uid == get_condor_uid()) && (!can_switch_ids() || not_root_squashed(exec_path)) && !glexec_job) { // do the chown unless the current mode is exactly 755 // if ((st.st_mode & 07777) != 0755) { new_mode = 0755; } } else { // do the chown if the mode doesn't already include 1777 // if ((st.st_mode & 01777) != 01777) { new_mode = 01777; } if (!glexec_job) { dprintf(D_ALWAYS, "WARNING: %s root-squashed or not condor-owned: " "requiring world-writability\n", exec_path); } } #endif // now do a chmod if needed // if (new_mode != 0) { dprintf(D_FULLDEBUG, "Changing permission on %s\n", exec_path); if (chmod(exec_path, new_mode) < 0) { EXCEPT( "chmod exec path (%s), errno: %d (%s)", exec_path, errno, strerror( errno ) ); } } }
bool VMGahpServer::startUp(Env *job_env, const char *workingdir, int nice_inc, FamilyInfo *family_info) { //check if we already have spawned a vmgahp server if( m_vmgahp_pid > 0 ) { //vmgahp is already running return true; } if( !m_job_ad ) { start_err_msg = "No JobAd in VMGahpServer::startUp()"; dprintf(D_ALWAYS,"%s\n", start_err_msg.Value()); return false; } MyString JobName; if( m_vmgahp_server.IsEmpty() ) { start_err_msg = "No path for vmgahp in VMGahpServer::startUp()"; dprintf(D_ALWAYS,"%s\n", start_err_msg.Value()); return false; } JobName = m_vmgahp_server; // Create two pairs of pipes which we will use to int stdin_pipefds[2]; int stdout_pipefds[2]; int stderr_pipefds[2]; if(!daemonCore->Create_Pipe(stdin_pipefds, true, // read end registerable false, // write end not registerable false, // read end blocking false // write end blocking )) { start_err_msg = "unable to create pipe to stdin of VM gahp"; dprintf(D_ALWAYS,"%s\n", start_err_msg.Value()); return false; } if(!daemonCore->Create_Pipe(stdout_pipefds, true, //read end registerable false, // write end not registerable false, // read end blocking false // write end blocking )) { // blocking read start_err_msg = "unable to create pipe to stdout of VM gahp"; dprintf(D_ALWAYS,"%s\n", start_err_msg.Value()); return false; } if( m_include_gahp_log ) { if(!daemonCore->Create_Pipe(stderr_pipefds, true, // read end registerable false, // write end not registerable true, // read end non-blocking true // write end non-blocking )) { // nonblocking read start_err_msg = "unable to create pipe to stderr of VM gahp"; dprintf(D_ALWAYS,"%s\n", start_err_msg.Value()); return false; } } int io_redirect[3]; io_redirect[0] = stdin_pipefds[0]; //stdin gets read side of in pipe io_redirect[1] = stdout_pipefds[1]; //stdout gets write side of out pipe if( m_include_gahp_log ) { io_redirect[2] = stderr_pipefds[1]; //stderr gets write side of err pipe } else { int null_fd = safe_open_wrapper_follow(NULL_FILE, O_WRONLY | O_APPEND, 0666); if( null_fd < 0 ) { start_err_msg = "unable to open null file for stderr of VM gahp"; dprintf(D_ALWAYS,"Failed to open '%s':%s (errno %d)\n", NULL_FILE, strerror(errno), errno); return false; } io_redirect[2] = null_fd; } // Set Arguments ArgList vmgahp_args; vmgahp_args.SetArgV1SyntaxToCurrentPlatform(); vmgahp_args.AppendArg(m_vmgahp_server.Value()); // Add daemonCore options vmgahp_args.AppendArg("-f"); if( m_include_gahp_log ) { vmgahp_args.AppendArg("-t"); } vmgahp_args.AppendArg("-M"); vmgahp_args.AppendArg(VMGAHP_STANDALONE_MODE); MyString args_string; vmgahp_args.GetArgsStringForDisplay(&args_string, 1); dprintf( D_ALWAYS, "About to exec %s %s\n", JobName.Value(), args_string.Value() ); #if !defined(WIN32) uid_t vmgahp_user_uid = (uid_t) -1; gid_t vmgahp_user_gid = (gid_t) -1; if( can_switch_ids() ) { // Condor runs as root vmgahp_user_uid = get_user_uid(); vmgahp_user_gid = get_user_gid(); } else if (Starter->condorPrivSepHelper() != NULL) { vmgahp_user_uid = Starter->condorPrivSepHelper()->get_uid(); char* user_name; if (!pcache()->get_user_name(vmgahp_user_uid, user_name)) { EXCEPT("unable to get user name for UID %u", vmgahp_user_uid); } if (!pcache()->get_user_ids(user_name, vmgahp_user_uid, vmgahp_user_gid)) { EXCEPT("unable to get GID for UID %u", vmgahp_user_uid); } free(user_name); } else { // vmgahp may have setuid-root (e.g. vmgahp for Xen) vmgahp_user_uid = get_condor_uid(); vmgahp_user_gid = get_condor_gid(); } // Setup vmgahp user uid/gid if( vmgahp_user_uid > 0 ) { if( vmgahp_user_gid <= 0 ) { vmgahp_user_gid = vmgahp_user_uid; } MyString tmp_str; tmp_str.sprintf("%d", (int)vmgahp_user_uid); job_env->SetEnv("VMGAHP_USER_UID", tmp_str.Value()); tmp_str.sprintf("%d", (int)vmgahp_user_gid); job_env->SetEnv("VMGAHP_USER_GID", tmp_str.Value()); } #endif job_env->SetEnv("VMGAHP_VMTYPE", m_vm_type.Value()); job_env->SetEnv("VMGAHP_WORKING_DIR", workingdir); // Grab the full environment back out of the Env object if(IsFulldebug(D_FULLDEBUG)) { MyString env_str; job_env->getDelimitedStringForDisplay(&env_str); dprintf(D_FULLDEBUG, "Env = %s\n", env_str.Value()); } priv_state vmgahp_priv = PRIV_ROOT; #if defined(WIN32) // TODO.. // Currently vmgahp for VMware VM universe can't run as user on Windows. // It seems like a bug of VMware. VMware command line tool such as "vmrun" // requires Administrator privilege. // -jaeyoung 06/15/07 if( strcasecmp(m_vm_type.Value(), CONDOR_VM_UNIVERSE_VMWARE ) == MATCH ) { vmgahp_priv = PRIV_UNKNOWN; } #endif m_vmgahp_pid = daemonCore->Create_Process( JobName.Value(), //Name of executable vmgahp_args, //Args vmgahp_priv, //Priv state 1, //id for our registered reaper FALSE, //do not want a command port job_env, //env workingdir, //cwd family_info, //family_info NULL, //network sockets to inherit io_redirect, //redirect stdin/out/err NULL, nice_inc ); //NOTE: Create_Process() saves the errno for us if it is an //"interesting" error. char const *create_process_error = NULL; if(m_vmgahp_pid == FALSE && errno) create_process_error = strerror(errno); // Now that the VMGAHP server is running, close the sides of // the pipes we gave away to the server, and stash the ones // we want to keep in an object data member. daemonCore->Close_Pipe(io_redirect[0]); daemonCore->Close_Pipe(io_redirect[1]); if( m_include_gahp_log ) { daemonCore->Close_Pipe(io_redirect[2]); } else { close(io_redirect[2]); } if ( m_vmgahp_pid == FALSE ) { m_vmgahp_pid = -1; start_err_msg = "Failed to start vm-gahp server"; dprintf(D_ALWAYS, "%s (%s)\n", start_err_msg.Value(), m_vmgahp_server.Value()); if(create_process_error) { MyString err_msg = "Failed to execute '"; err_msg += m_vmgahp_server.Value(), err_msg += "'"; if(!args_string.IsEmpty()) { err_msg += " with arguments "; err_msg += args_string.Value(); } err_msg += ": "; err_msg += create_process_error; dprintf(D_ALWAYS, "Failed to start vmgahp server (%s)\n", err_msg.Value()); } return false; } dprintf(D_ALWAYS, "VMGAHP server pid=%d\n", m_vmgahp_pid); m_vmgahp_writefd = stdin_pipefds[1]; m_vmgahp_readfd = stdout_pipefds[0]; if( m_include_gahp_log ) { m_vmgahp_errorfd = stderr_pipefds[0]; } // Now initialization is done m_is_initialized = true; // print initial stderr messages from vmgahp printSystemErrorMsg(); // Read the initial greeting from the vm-gahp, which is the version if( command_version() == false ) { start_err_msg = "Internal vmgahp server error"; dprintf(D_ALWAYS,"Failed to read vmgahp server version\n"); printSystemErrorMsg(); cleanup(); return false; } dprintf(D_FULLDEBUG,"VMGAHP server version: %s\n", m_vmgahp_version.Value()); // Now see what commands this server supports. if( command_commands() == false ) { start_err_msg = "Internal vmgahp server error"; dprintf(D_ALWAYS,"Failed to read supported commands from vmgahp server\n"); printSystemErrorMsg(); cleanup(); return false; } // Now see what virtual machine types this server supports if( command_support_vms() == false ) { start_err_msg = "Internal vmgahp server error"; dprintf(D_ALWAYS,"Failed to read supported vm types from vmgahp server\n"); printSystemErrorMsg(); cleanup(); return false; } int result = -1; if( m_include_gahp_log ) { result = daemonCore->Register_Pipe(m_vmgahp_errorfd, "m_vmgahp_errorfd", static_cast<PipeHandlercpp>(&VMGahpServer::err_pipe_ready), "VMGahpServer::err_pipe_ready",this); if( result == -1 ) { dprintf(D_ALWAYS,"Failed to register vmgahp stderr pipe\n"); if(m_stderr_tid != -1) { daemonCore->Cancel_Timer(m_stderr_tid); m_stderr_tid = -1; } m_stderr_tid = daemonCore->Register_Timer(2, 2, (TimerHandlercpp)&VMGahpServer::err_pipe_ready, "VMGahpServer::err_pipe_ready",this); if( m_stderr_tid == -1 ) { start_err_msg = "Internal vmgahp server error"; dprintf(D_ALWAYS,"Failed to register stderr timer\n"); printSystemErrorMsg(); cleanup(); return false; } } } // try to turn on vmgahp async notification mode if ( !command_async_mode_on() ) { // not supported, set a poll interval m_is_async_mode = false; setPollInterval(m_pollInterval); } else { // command worked... register the pipe and stop polling result = daemonCore->Register_Pipe(m_vmgahp_readfd, "m_vmgahp_readfd", static_cast<PipeHandlercpp>(&VMGahpServer::pipe_ready), "VMGahpServer::pipe_ready",this); if( result == -1 ) { // failed to register the pipe for some reason; fall // back on polling (yuck). dprintf(D_ALWAYS,"Failed to register vmgahp Read pipe\n"); m_is_async_mode = false; setPollInterval(m_pollInterval); } else { // pipe is registered. stop polling. setPollInterval(0); m_is_async_mode = true; } } return true; }
void VMGahpServer::killVM(void) { if( m_vm_type.IsEmpty() || m_vmgahp_server.IsEmpty() ) { return; } if( m_workingdir.IsEmpty() ) { dprintf(D_ALWAYS, "VMGahpServer::killVM() : no workingdir\n"); return; } MyString matchstring; if( (strcasecmp(m_vm_type.Value(), CONDOR_VM_UNIVERSE_XEN ) == MATCH) || (strcasecmp(m_vm_type.Value(), CONDOR_VM_UNIVERSE_KVM ) == MATCH) ) { if( create_name_for_VM(m_job_ad, matchstring) == false ) { dprintf(D_ALWAYS, "VMGahpServer::killVM() : " "cannot make the name of VM\n"); return; } } else { // Except Xen, we need the path of working directory of Starter // in order to destroy a VM. matchstring = m_workingdir; } if( matchstring.IsEmpty() ) { dprintf(D_ALWAYS, "VMGahpServer::killVM() : empty matchstring\n"); return; } // vmgahp is daemonCore, so we need to add -f -t options of daemonCore. // Then, try to execute vmgahp with // vmtype <vmtype> match <string>" ArgList systemcmd; systemcmd.AppendArg(m_vmgahp_server); systemcmd.AppendArg("-f"); if( m_include_gahp_log ) { systemcmd.AppendArg("-t"); } systemcmd.AppendArg("-M"); systemcmd.AppendArg(VMGAHP_KILL_MODE); systemcmd.AppendArg("vmtype"); systemcmd.AppendArg(m_vm_type); systemcmd.AppendArg("match"); systemcmd.AppendArg(matchstring); #if !defined(WIN32) if( can_switch_ids() ) { MyString tmp_str; tmp_str.sprintf("%d", (int)get_condor_uid()); SetEnv("VMGAHP_USER_UID", tmp_str.Value()); } else if (Starter->condorPrivSepHelper() != NULL) { MyString tmp_str; tmp_str.sprintf("%d", (int)Starter->condorPrivSepHelper()->get_uid()); SetEnv("VMGAHP_USER_UID", tmp_str.Value()); } #endif priv_state oldpriv; if( (strcasecmp(m_vm_type.Value(), CONDOR_VM_UNIVERSE_XEN ) == MATCH) || (strcasecmp(m_vm_type.Value(), CONDOR_VM_UNIVERSE_KVM ) == MATCH) ) { oldpriv = set_root_priv(); } else { oldpriv = set_user_priv(); } int ret = my_system(systemcmd); set_priv(oldpriv); if( ret == 0 ) { dprintf( D_FULLDEBUG, "VMGahpServer::killVM() is called with " "'%s'\n", matchstring.Value()); } else { dprintf( D_FULLDEBUG, "VMGahpServer::killVM() failed!\n"); } return; }
bool ProcFamilyProxy::start_procd() { // we'll only start one ProcD // ASSERT(m_procd_pid == -1); // now, we build up an ArgList for the procd // MyString exe; ArgList args; // path to the executable // char* path = param("PROCD"); if (path == NULL) { dprintf(D_ALWAYS, "start_procd: PROCD not defined in configuration\n"); return false; } exe = path; args.AppendArg(condor_basename(path)); free(path); // the procd's address // args.AppendArg("-A"); args.AppendArg(m_procd_addr); // the (optional) procd log file // if (m_procd_log.Length() > 0) { args.AppendArg("-L"); args.AppendArg(m_procd_log); } // the (optional) procd log file size // char *procd_log_size = param("MAX_PROCD_LOG"); if (procd_log_size != NULL) { args.AppendArg("-R"); args.AppendArg(procd_log_size); free(procd_log_size); } Env env; // The procd can't param, so pass this via the environment if (param_boolean("USE_PSS", false)) { env.SetEnv("_condor_USE_PSS=TRUE"); } // the (optional) maximum snapshot interval // (the procd will default to every minute) // char* max_snapshot_interval = param("PROCD_MAX_SNAPSHOT_INTERVAL"); if (max_snapshot_interval != NULL) { args.AppendArg("-S"); args.AppendArg(max_snapshot_interval); free(max_snapshot_interval); } // (optional) make the procd sleep on startup so a // debugger can attach // bool debug = param_boolean("PROCD_DEBUG", false); if (debug) { args.AppendArg("-D"); } #if !defined(WIN32) // On UNIX, we need to tell the procd to allow connections from the // condor user // args.AppendArg("-C"); args.AppendArg(get_condor_uid()); #endif #if defined(WIN32) // on Windows, we need to tell the procd what program to use to send // softkills // char* softkill_path = param("WINDOWS_SOFTKILL"); if ( softkill_path == NULL ) { dprintf(D_ALWAYS, "WINDOWS_SOFTKILL undefined; " "ProcD won't be able to send WM_CLOSE to jobs\n"); } else { args.AppendArg("-K"); args.AppendArg(softkill_path); free(softkill_path); } #endif #if defined(LINUX) // enable group-based tracking if a group ID range is given in the // config file // if (param_boolean("USE_GID_PROCESS_TRACKING", false)) { if (!can_switch_ids() && !privsep_enabled()) { EXCEPT("USE_GID_PROCESS_TRACKING enabled, but can't modify " "the group list of our children unless running as " "root or using PrivSep"); } int min_tracking_gid = param_integer("MIN_TRACKING_GID", 0); if (min_tracking_gid == 0) { EXCEPT("USE_GID_PROCESS_TRACKING enabled, " "but MIN_TRACKING_GID is %d\n", min_tracking_gid); } int max_tracking_gid = param_integer("MAX_TRACKING_GID", 0); if (max_tracking_gid == 0) { EXCEPT("USE_GID_PROCESS_TRACKING enabled, " "but MAX_TRACKING_GID is %d\n", max_tracking_gid); } if (min_tracking_gid > max_tracking_gid) { EXCEPT("invalid tracking gid range: %d - %d\n", min_tracking_gid, max_tracking_gid); } args.AppendArg("-G"); args.AppendArg(min_tracking_gid); args.AppendArg(max_tracking_gid); } #endif // for the GLEXEC_JOB feature, we'll need to pass the ProcD paths // to glexec and the condor_glexec_kill script // if (param_boolean("GLEXEC_JOB", false)) { args.AppendArg("-I"); char* libexec = param("LIBEXEC"); if (libexec == NULL) { EXCEPT("GLEXEC_JOB is defined, but LIBEXEC not configured"); } MyString glexec_kill; glexec_kill.formatstr("%s/condor_glexec_kill", libexec); free(libexec); args.AppendArg(glexec_kill.Value()); char* glexec = param("GLEXEC"); if (glexec == NULL) { EXCEPT("GLEXEC_JOB is defined, but GLEXEC not configured"); } args.AppendArg(glexec); free(glexec); int glexec_retries = param_integer("GLEXEC_RETRIES",3,0); int glexec_retry_delay = param_integer("GLEXEC_RETRY_DELAY",5,0); args.AppendArg(glexec_retries); args.AppendArg(glexec_retry_delay); } // done constructing the argument list; now register a reaper for // notification when the procd exits // if (m_reaper_id == FALSE) { m_reaper_id = daemonCore->Register_Reaper( "condor_procd reaper", (ReaperHandlercpp)&ProcFamilyProxyReaperHelper::procd_reaper, "condor_procd reaper", m_reaper_helper ); } if (m_reaper_id == FALSE) { dprintf(D_ALWAYS, "start_procd: unable to register a reaper for the procd\n"); return false; } // we start the procd with a pipe coming back to us on its stderr. // the procd will close this pipe after it starts listening for // commands. // int pipe_ends[2]; if (daemonCore->Create_Pipe(pipe_ends) == FALSE) { dprintf(D_ALWAYS, "start_procd: error creating pipe for the procd\n"); return false; } int std_io[3]; std_io[0] = -1; std_io[1] = -1; std_io[2] = pipe_ends[1]; // use Create_Process to start the procd // if (privsep_enabled()) { m_procd_pid = privsep_spawn_procd(exe.Value(), args, std_io, m_reaper_id); } else { m_procd_pid = daemonCore->Create_Process(exe.Value(), args, PRIV_ROOT, m_reaper_id, FALSE, &env, NULL, NULL, NULL, std_io); } if (m_procd_pid == FALSE) { dprintf(D_ALWAYS, "start_procd: unable to execute the procd\n"); daemonCore->Close_Pipe(pipe_ends[0]); daemonCore->Close_Pipe(pipe_ends[1]); m_procd_pid = -1; return false; } // now close the pipe end we handed to the child and then block on the // pipe until it closes (which tells us the procd is listening for // commands) // if (daemonCore->Close_Pipe(pipe_ends[1]) == FALSE) { dprintf(D_ALWAYS, "error closing procd's pipe end\n"); daemonCore->Shutdown_Graceful(m_procd_pid); daemonCore->Close_Pipe(pipe_ends[0]); m_procd_pid = -1; return false; } const int MAX_PROCD_ERR_LEN = 80; char err_msg[MAX_PROCD_ERR_LEN + 1]; int ret = daemonCore->Read_Pipe(pipe_ends[0], err_msg, MAX_PROCD_ERR_LEN); if (ret != 0) { daemonCore->Shutdown_Graceful(m_procd_pid); daemonCore->Close_Pipe(pipe_ends[0]); m_procd_pid = -1; if (ret == -1) { dprintf(D_ALWAYS, "start_procd: error reading pipe from procd\n"); return false; } err_msg[ret] = '\0'; dprintf(D_ALWAYS, "start_procd: error received from procd: %s\n", err_msg); return false; } if (daemonCore->Close_Pipe(pipe_ends[0]) == FALSE) { dprintf(D_ALWAYS, "start_procd: error closing pipe to procd\n"); daemonCore->Shutdown_Graceful(m_procd_pid); m_procd_pid = -1; return false; } // OK, the ProcD's up and running! // return true; }
/** * merge_stderr_with_stdout is intended for clients of this function * that wish to have the old behavior, where stderr and stdout were * both added to the same StringList. */ int systemCommand( ArgList &args, priv_state priv, StringList *cmd_out, StringList * cmd_in, StringList *cmd_err, bool merge_stderr_with_stdout) { int result = 0; FILE *fp = NULL; FILE * fp_for_stdin = NULL; FILE * childerr = NULL; MyString line; char buff[1024]; StringList *my_cmd_out = cmd_out; priv_state prev = PRIV_UNKNOWN; int stdout_pipes[2]; int stdin_pipes[2]; int pid; bool use_privsep = false; switch ( priv ) { case PRIV_ROOT: prev = set_root_priv(); break; case PRIV_USER: case PRIV_USER_FINAL: prev = set_user_priv(); #if !defined(WIN32) if ( privsep_enabled() && (job_user_uid != get_condor_uid()) ) { use_privsep = true; } #endif break; default: // Stay as Condor user ; } #if defined(WIN32) if((cmd_in != NULL) || (cmd_err != NULL)) { vmprintf(D_ALWAYS, "Invalid use of systemCommand() in Windows.\n"); return -1; } //if ( use_privsep ) { // fp = privsep_popen(args, "r", want_stderr, job_user_uid); //} //else { fp = my_popen( args, "r", merge_stderr_with_stdout ); //} #else // The old way of doing things (and the Win32 way of doing // things) // fp = my_popen( args, "r", want_stderr ); if((cmd_err != NULL) && merge_stderr_with_stdout) { vmprintf(D_ALWAYS, "Invalid use of systemCommand().\n"); return -1; } PrivSepForkExec psforkexec; char ** args_array = args.GetStringArray(); int error_pipe[2]; // AIX 5.2, Solaris 5.9, HPUX 11 don't have AF_LOCAL if(pipe(stdin_pipes) < 0) { vmprintf(D_ALWAYS, "Error creating pipe: %s\n", strerror(errno)); deleteStringArray( args_array ); return -1; } if(pipe(stdout_pipes) < 0) { vmprintf(D_ALWAYS, "Error creating pipe: %s\n", strerror(errno)); close(stdin_pipes[0]); close(stdin_pipes[1]); deleteStringArray( args_array ); return -1; } if ( use_privsep ) { if(!psforkexec.init()) { vmprintf(D_ALWAYS, "my_popenv failure on %s\n", args_array[0]); close(stdin_pipes[0]); close(stdin_pipes[1]); close(stdout_pipes[0]); close(stdout_pipes[1]); deleteStringArray( args_array ); return -1; } } if(cmd_err != NULL) { if(pipe(error_pipe) < 0) { vmprintf(D_ALWAYS, "Could not open pipe for error output: %s\n", strerror(errno)); close(stdin_pipes[0]); close(stdin_pipes[1]); close(stdout_pipes[0]); close(stdout_pipes[1]); deleteStringArray( args_array ); return -1; } } // Now fork and do what my_popen used to do pid = fork(); if(pid < 0) { vmprintf(D_ALWAYS, "Error forking: %s\n", strerror(errno)); close(stdin_pipes[0]); close(stdin_pipes[1]); close(stdout_pipes[0]); close(stdout_pipes[1]); if(cmd_err != NULL) { close(error_pipe[0]); close(error_pipe[1]); } deleteStringArray( args_array ); return -1; } if(pid == 0) { close(stdout_pipes[0]); close(stdin_pipes[1]); dup2(stdout_pipes[1], STDOUT_FILENO); dup2(stdin_pipes[0], STDIN_FILENO); if(merge_stderr_with_stdout) dup2(stdout_pipes[1], STDERR_FILENO); else if(cmd_err != NULL) { close(error_pipe[0]); dup2(error_pipe[1], STDERR_FILENO); } uid_t euid = geteuid(); gid_t egid = getegid(); seteuid( 0 ); setgroups( 1, &egid ); setgid( egid ); setuid( euid ); install_sig_handler(SIGPIPE, SIG_DFL); sigset_t sigs; sigfillset(&sigs); sigprocmask(SIG_UNBLOCK, &sigs, NULL); MyString cmd = args_array[0]; if ( use_privsep ) { ArgList al; psforkexec.in_child(cmd, al); deleteStringArray( args_array ); args_array = al.GetStringArray(); } execvp(cmd.Value(), args_array); vmprintf(D_ALWAYS, "Could not execute %s: %s\n", args_array[0], strerror(errno)); exit(-1); } close(stdin_pipes[0]); close(stdout_pipes[1]); fp_for_stdin = fdopen(stdin_pipes[1], "w"); fp = fdopen(stdout_pipes[0], "r"); if(cmd_err != NULL) { close(error_pipe[1]); childerr = fdopen(error_pipe[0],"r"); if(childerr == 0) { vmprintf(D_ALWAYS, "Could not open pipe for reading child error output: %s\n", strerror(errno)); close(error_pipe[0]); close(stdin_pipes[1]); close(stdout_pipes[0]); fclose(fp); fclose(fp_for_stdin); deleteStringArray( args_array ); return -1; } } if ( use_privsep ) { FILE* _fp = psforkexec.parent_begin(); privsep_exec_set_uid(_fp, job_user_uid); privsep_exec_set_path(_fp, args_array[0]); privsep_exec_set_args(_fp, args); Env env; env.MergeFrom(environ); privsep_exec_set_env(_fp, env); privsep_exec_set_iwd(_fp, "."); privsep_exec_set_inherit_fd(_fp, 1); privsep_exec_set_inherit_fd(_fp, 2); privsep_exec_set_inherit_fd(_fp, 0); if (!psforkexec.parent_end()) { vmprintf(D_ALWAYS, "my_popenv failure on %s\n", args_array[0]); fclose(fp); fclose(fp_for_stdin); if (childerr) { fclose(childerr); } deleteStringArray( args_array ); return -1; } } deleteStringArray( args_array ); #endif set_priv( prev ); if ( fp == NULL ) { MyString args_string; args.GetArgsStringForDisplay( &args_string, 0 ); vmprintf( D_ALWAYS, "Failed to execute command: %s\n", args_string.Value() ); if (childerr) fclose(childerr); return -1; } if(cmd_in != NULL) { cmd_in->rewind(); char * tmp; while((tmp = cmd_in->next()) != NULL) { fprintf(fp_for_stdin, "%s\n", tmp); fflush(fp_for_stdin); } } if (fp_for_stdin) { // So that we will not be waiting for output while the // script waits for stdin to be closed. fclose(fp_for_stdin); } if ( my_cmd_out == NULL ) { my_cmd_out = new StringList(); } while ( fgets( buff, sizeof(buff), fp ) != NULL ) { line += buff; if ( line.chomp() ) { my_cmd_out->append( line.Value() ); line = ""; } } if(cmd_err != NULL) { while(fgets(buff, sizeof(buff), childerr) != NULL) { line += buff; if(line.chomp()) { cmd_err->append(line.Value()); line = ""; } } fclose(childerr); } #if defined(WIN32) result = my_pclose( fp ); #else // Why close first? Just in case the child process is waiting // on a read, and we have nothing more to send it. It will // now receive a SIGPIPE. fclose(fp); if(waitpid(pid, &result, 0) < 0) { vmprintf(D_ALWAYS, "Unable to wait: %s\n", strerror(errno)); if ( cmd_out == NULL ) { delete my_cmd_out; } return -1; } #endif if( result != 0 ) { MyString args_string; args.GetArgsStringForDisplay(&args_string,0); vmprintf(D_ALWAYS, "Command returned non-zero: %s\n", args_string.Value()); my_cmd_out->rewind(); const char *next_line; while ( (next_line = my_cmd_out->next()) ) { vmprintf( D_ALWAYS, " %s\n", next_line ); } } if ( cmd_out == NULL ) { delete my_cmd_out; } return result; }
int Condor_Auth_X509::nameGssToLocal(const char * GSSClientname) { //this might need to change with SSLK5 stuff //just extract username from /CN=<username>@<domain,etc> OM_uint32 major_status = GSS_S_COMPLETE; char *tmp_user = NULL; char local_user[USER_NAME_MAX]; // windows gsi does not currently include this function. we use it on // unix, but implement our own on windows for now. #ifdef WIN32 major_status = condor_gss_assist_gridmap(GSSClientname, &tmp_user); #else // Switched the unix map function to _map_and_authorize, which allows access // to the Globus callout infrastructure. if (m_mapping == NULL) { // Size of hash table is purposely initialized small to prevent this // from hogging memory. This will, of course, grow at large sites. m_mapping = new GlobusMappingTable(53, hashFuncString, updateDuplicateKeys); } const char *auth_name_to_map; const char *fqan = getFQAN(); if (fqan && fqan[0]) { auth_name_to_map = fqan; } else { auth_name_to_map = GSSClientname; } globus_mapping_entry_ptr value; time_t now = 0; time_t gsi_cache_expiry = param_integer("GSS_ASSIST_GRIDMAP_CACHE_EXPIRATION", 0); if (gsi_cache_expiry && (m_mapping->lookup(auth_name_to_map, value) == 0)) { now = time(NULL); if (now < value->expiry_time) { dprintf(D_SECURITY, "Using Globus mapping result from the cache.\n"); if (value->name.size()) { tmp_user = strdup(value->name.c_str()); } else { major_status = GSS_S_FAILURE; } } } if ((tmp_user == NULL) && (major_status == GSS_S_COMPLETE)) { char condor_str[] = "condor"; major_status = globus_gss_assist_map_and_authorize( context_handle, condor_str, // Requested service name NULL, // Requested user name; NULL for non-specified local_user, USER_NAME_MAX-1); // Leave one space at end of buffer, just-in-case // Defensive programming: to protect against buffer overruns in the // unknown globus mapping module, make sure we are at least nul-term'd local_user[USER_NAME_MAX-1] = '\0'; // More defensive programming: There is a bug in LCMAPS, (which is possibly // called by a globus callout) that sometimes returns with the euid set to // root (!?!). As a safeguard, We check for that here and return to the // condor euid. This is done "outside" of the condor priv stack since this // is essentially undoing a side effect of the library call, not // intentionally changing priv state. if (geteuid() == 0) { dprintf(D_ALWAYS, "WARNING: globus returned with euid 0\n"); // attempt to undo if (seteuid(get_condor_uid())) { // complain loudly, but continue dprintf(D_ALWAYS, "ERROR: something has gone terribly wrong: errno %i\n", errno); } } if (now == 0) { now = time(NULL); } value.reset(new globus_mapping_entry_t); value->expiry_time = now + gsi_cache_expiry; // The special name of "" indicates failed mapping. if (major_status == GSS_S_COMPLETE) { value->name = local_user; } m_mapping->insert(auth_name_to_map, value); } #endif if (tmp_user) { strcpy( local_user, tmp_user ); free(tmp_user); tmp_user = NULL; } if ( major_status != GSS_S_COMPLETE) { setRemoteUser("gsi"); setRemoteDomain( UNMAPPED_DOMAIN ); return 0; } MyString user; MyString domain; Authentication::split_canonical_name( local_user, user, domain ); setRemoteUser (user.Value()); setRemoteDomain(domain.Value()); setAuthenticatedName(GSSClientname); return 1; }
static bool createJobSpoolDirectory(ClassAd const *job_ad,priv_state desired_priv_state,char const *spool_path) { int cluster=-1,proc=-1; job_ad->LookupInteger(ATTR_CLUSTER_ID,cluster); job_ad->LookupInteger(ATTR_PROC_ID,proc); #ifndef WIN32 uid_t spool_path_uid; #endif StatInfo si( spool_path ); if( si.Error() == SINoFile ) { if(!mkdir_and_parents_if_needed(spool_path,0755,PRIV_CONDOR) ) { dprintf( D_ALWAYS, "Failed to create spool directory for job %d.%d: " "mkdir(%s): %s (errno %d)\n", cluster, proc, spool_path, strerror(errno), errno ); return false; } #ifndef WIN32 spool_path_uid = get_condor_uid(); #endif } else { #ifndef WIN32 // spool_path already exists, check owner spool_path_uid = si.GetOwner(); #endif } if( !can_switch_ids() || desired_priv_state == PRIV_UNKNOWN || desired_priv_state == PRIV_CONDOR ) { return true; // no need/desire for chowning } ASSERT( desired_priv_state == PRIV_USER ); #ifndef WIN32 MyString owner; job_ad->LookupString( ATTR_OWNER, owner ); uid_t src_uid = get_condor_uid(); uid_t dst_uid; gid_t dst_gid; passwd_cache* p_cache = pcache(); if( !p_cache->get_user_ids(owner.Value(), dst_uid, dst_gid) ) { dprintf( D_ALWAYS, "(%d.%d) Failed to find UID and GID for " "user %s. Cannot chown %s to user.\n", cluster, proc, owner.Value(), spool_path ); return false; } if( (spool_path_uid != dst_uid) && !recursive_chown(spool_path,src_uid,dst_uid,dst_gid,true) ) { dprintf( D_ALWAYS, "(%d.%d) Failed to chown %s from %d to %d.%d.\n", cluster, proc, spool_path, src_uid, dst_uid, dst_gid ); return false; } #else /* WIN32 */ MyString owner; job_ad->LookupString(ATTR_OWNER, owner); MyString nt_domain; job_ad->LookupString(ATTR_NT_DOMAIN, nt_domain); if(!recursive_chown(spool_path, owner.Value(), nt_domain.Value())) { dprintf( D_ALWAYS, "(%d.%d) Failed to chown %s from to %d\\%d.\n", cluster, proc, spool_path, nt_domain.Value(), owner.Value() ); return false; } #endif return true; // All happy paths lead here }
bool VMUniverseMgr::testVMGahp(const char* gahppath, const char* vmtype) { m_needCheck = false; if( !m_starter_has_vmcode ) { return false; } if( !gahppath || !vmtype ) { return false; } #if defined(WIN32) // On Windows machine, the option that Starter log file includes // logs from vmgahp causes deadlock even if the option works well // on Linux machine. I guess that is due to Windows Pipes but // I don't know the exact reason. // Until the problem is solved, // this option will be disabled on Windows machine. char *need_log_file = param("VM_GAHP_LOG"); if( need_log_file ) { free(need_log_file); }else { dprintf( D_ALWAYS, "To support vm universe, '%s' must be defined " "in condor config file, which is a log file for vmgahp.\n", "VM_GAHP_LOG"); return false; } #endif // vmgahp is daemonCore, so we need to add -f -t options of daemonCore. // Then, try to execute vmgahp with // vmtype <vmtype>" // and grab the output as a ClassAd ArgList systemcmd; systemcmd.AppendArg(gahppath); systemcmd.AppendArg("-f"); char *gahp_log_file = param("VM_GAHP_LOG"); if( gahp_log_file ) { free(gahp_log_file); }else { systemcmd.AppendArg("-t"); } systemcmd.AppendArg("-M"); systemcmd.AppendArg(VMGAHP_TEST_MODE); systemcmd.AppendArg("vmtype"); systemcmd.AppendArg(vmtype); #if !defined(WIN32) if( can_switch_ids() ) { MyString tmp_str; tmp_str.formatstr("%d", (int)get_condor_uid()); SetEnv("VMGAHP_USER_UID", tmp_str.Value()); } #endif priv_state prev_priv; if( (strcasecmp(vmtype, CONDOR_VM_UNIVERSE_XEN) == MATCH) || (strcasecmp(vmtype, CONDOR_VM_UNIVERSE_KVM) == MATCH) ) { // Xen requires root privilege prev_priv = set_root_priv(); }else { prev_priv = set_condor_priv(); } FILE* fp = NULL; fp = my_popen(systemcmd, "r", FALSE ); set_priv(prev_priv); if( !fp ) { dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", gahppath ); return false; } bool read_something = false; char buf[2048]; m_vmgahp_info.Clear(); while( fgets(buf, 2048, fp) ) { if( !m_vmgahp_info.Insert(buf) ) { dprintf( D_ALWAYS, "Failed to insert \"%s\" into VMInfo, " "ignoring invalid parameter\n", buf ); continue; } read_something = true; } my_pclose( fp ); if( !read_something ) { MyString args_string; systemcmd.GetArgsStringForDisplay(&args_string,0); dprintf( D_ALWAYS, "Warning: '%s' did not produce any valid output.\n", args_string.Value()); if( (strcasecmp(vmtype, CONDOR_VM_UNIVERSE_XEN) == 0) ) { MyString err_msg; err_msg += "\n#######################################################\n"; err_msg += "##### Make sure the followings "; err_msg += "to use VM universe for Xen\n"; err_msg += "### - The owner of script progrm like "; err_msg += "'condor_vm_xen.sh' must be root\n"; err_msg += "### - The script program must be executable\n"; err_msg += "### - Other writable bit for the above files is "; err_msg += "not allowed.\n"; err_msg += "#########################################################\n"; dprintf( D_ALWAYS, "%s", err_msg.Value()); } else if( (strcasecmp(vmtype, CONDOR_VM_UNIVERSE_KVM) == 0)) { MyString err_msg; err_msg += "\n#######################################################\n"; err_msg += "##### Make sure the followings "; err_msg += "to use VM universe for KVM\n"; err_msg += "### - The owner of script progrm like "; err_msg += "'condor_vm_xen.sh' must be root\n"; err_msg += "### - The script program must be executable\n"; err_msg += "### - Other writable bit for the above files is "; err_msg += "not allowed.\n"; err_msg += "#########################################################\n"; dprintf( D_ALWAYS, "%s", err_msg.Value()); }else if( strcasecmp(vmtype, CONDOR_VM_UNIVERSE_VMWARE ) == 0 ) { MyString err_msg; MyString err_msg2; err_msg += "\n#######################################################\n"; err_msg += "##### Make sure the followings "; err_msg += "to use VM universe for VMware\n"; if( can_switch_ids() ) { // Condor runs as root err_msg += "### - The script program like 'condor_vm_vmware'"; err_msg += " must be readable for anybody.\n"; } err_msg += "### - Check the path of vmware-cmd, vmrun, and mkisofs "; err_msg += "in 'condor_vm_vmware\n'"; err_msg += "#########################################################\n"; dprintf( D_ALWAYS, "%s", err_msg.Value()); } return false; } // For debug printVMGahpInfo(D_ALWAYS); // Read vm_type MyString tmp_vmtype; if( m_vmgahp_info.LookupString( ATTR_VM_TYPE, tmp_vmtype) != 1 ) { dprintf( D_ALWAYS, "There is no %s in the output of vmgahp. " "So VM Universe will be disabled\n", ATTR_VM_TYPE); return false; } if( strcasecmp(tmp_vmtype.Value(), vmtype) != 0 ) { dprintf( D_ALWAYS, "The vmgahp(%s) doesn't support this vmtype(%s)\n", gahppath, vmtype); return false; } dprintf( D_ALWAYS, "VMType('%s') is supported\n", vmtype); // Read vm_memory if( m_vmgahp_info.LookupInteger(ATTR_VM_MEMORY, m_vm_max_memory) != 1 ) { dprintf( D_ALWAYS, "There is no %s in the output of vmgahp\n",ATTR_VM_MEMORY); return false; } if( m_vm_max_memory == 0 ) { dprintf( D_ALWAYS, "There is no sufficient memory for virtual machines\n"); return false; } dprintf( D_ALWAYS, "The maximum available memory for vm universe is " "set to %d MB\n", m_vm_max_memory); // Read vm_networking bool tmp_networking = false; MyString tmp_networking_types; m_vmgahp_info.LookupBool(ATTR_VM_NETWORKING, tmp_networking); if( tmp_networking ) { if( m_vmgahp_info.LookupString( ATTR_VM_NETWORKING_TYPES, tmp_networking_types) != 1 ) { tmp_networking = false; m_vmgahp_info.Assign(ATTR_VM_NETWORKING, false); } } m_vm_networking = param_boolean("VM_NETWORKING",false); if( m_vm_networking ) { if( !tmp_networking ) { dprintf( D_ALWAYS, "Even if VM_NETWORKING is TRUE in condor config," " VM_NETWORKING is disabled because vmgahp doesn't " "support VM_NETWORKING\n"); m_vm_networking = false; } } if( m_vm_networking == false ) { dprintf( D_ALWAYS, "VM networking is disabled\n"); }else { dprintf( D_ALWAYS, "VM networking is enabled\n"); dprintf( D_ALWAYS, "Supported networking types are %s\n", tmp_networking_types.Value()); } // Now, we received correct information from vmgahp m_vm_type = tmp_vmtype; m_vmgahp_server = gahppath; return true; }