示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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
}
示例#4
0
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
}
示例#5
0
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;
}
示例#6
0
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 ) );
		}
	}
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
/**
 * 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;
}
示例#11
0
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;
}
示例#12
0
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
}
示例#13
0
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;
}