Exemplo n.º 1
0
// An entity (e.g. GlobusJob, GlobusResource object) should call this
// function when it wants to use a proxy and have it managed by
// ProxyManager. job_ad contains attributes related to the proxy to be
// used. error allows the function to return an error message if proxy
// acquisition fails. notify_tid is a timer id that
// will be signalled when something interesting happens with the proxy
// (it's about to expire or has been refreshed). A Proxy struct will be
// returned. When the Proxy is no longer needed, ReleaseProxy() should be
// called with it. If no notifications are desired, give a
// negative number for notify_tid or omit it. Note the the Proxy returned
// is a shared data-structure and shouldn't be delete'd or modified by
// the caller.
// If AcquireProxy() encounters an error, it will store an error message
// in the error parameter and return NULL. If the job ad doesn't contain
// any proxy-related attributes, AcquireProxy() will store the empty
// string in the error parameter and return NULL.
Proxy *
AcquireProxy( const ClassAd *job_ad, std::string &error,
			  TimerHandlercpp func_ptr, Service *data  )
{
	if ( proxymanager_initialized == false ) {
		error = "Internal Error: ProxyManager not initialized";
		return NULL;
	}

	int expire_time;
	Proxy *proxy = NULL;
	ProxySubject *proxy_subject = NULL;
	char *subject_name = NULL;
	char *fqan = NULL;
	char *email = NULL;
	char *first_fqan = NULL;
	std::string proxy_path;
	std::string owner;
	char *param_str = NULL;
	bool has_voms_attrs = false;

	if ( job_ad->LookupString( ATTR_OWNER, owner ) ) {
		std::string param_name;
		formatstr( param_name, "JOB_PROXY_OVERRIDE_FILE_%s", owner.c_str() );
		param_str = param( param_name.c_str() );
	}
	if ( param_str == NULL ) {
		param_str = param( "JOB_PROXY_OVERRIDE_FILE" );
	}
	if ( param_str ) {
		proxy_path = param_str;
		free( param_str );
	} else if ( job_ad->LookupString( ATTR_X509_USER_PROXY,
									  proxy_path ) == 0 ) {

		// Special handling for "use best proxy"
		job_ad->LookupString( ATTR_X509_USER_PROXY_FQAN, &fqan );
		job_ad->LookupString( ATTR_X509_USER_PROXY_FIRST_FQAN, &first_fqan );
		job_ad->LookupString( ATTR_X509_USER_PROXY_SUBJECT, &subject_name );
		job_ad->LookupString( ATTR_X509_USER_PROXY_EMAIL, &email );
		if ( subject_name ) {
			if ( fqan == NULL ) {
				fqan = strdup( subject_name );
			} else {
				has_voms_attrs = true;
			}
			if ( SubjectsByName.lookup( HashKey(fqan),
										proxy_subject ) != 0 ) {
				// We don't know about this proxy subject yet,
				// create a new ProxySubject and fill it out
				std::string tmp;
				proxy_subject = new ProxySubject;
				proxy_subject->subject_name = strdup( subject_name );
				if (email)
					proxy_subject->email = strdup( email );
				else
					proxy_subject->email = NULL;
				proxy_subject->fqan = fqan ? strdup( fqan ) : NULL;
				proxy_subject->first_fqan = first_fqan ? strdup( first_fqan ) : NULL;
				proxy_subject->has_voms_attrs = has_voms_attrs;

				// Create a master proxy for our new ProxySubject
				Proxy *new_master = new Proxy;
				new_master->id = next_proxy_id++;
				formatstr( tmp, "%s/master_proxy.%d", masterProxyDirectory,
							 new_master->id );
				new_master->proxy_filename = strdup( tmp.c_str() );
				new_master->num_references = 0;
				new_master->subject = proxy_subject;
				//SetMasterProxy( new_master, proxy );
				new_master->expiration_time = -1;
				new_master->near_expired = true;
				ProxiesByFilename.insert( HashKey(new_master->proxy_filename),
										  new_master );

				proxy_subject->master_proxy = new_master;

				SubjectsByName.insert(HashKey(proxy_subject->fqan),
									  proxy_subject);
			}
			// Now that we have a proxy_subject, return it's master proxy
			proxy = proxy_subject->master_proxy;
			proxy->num_references++;
			if ( func_ptr ) {
				Callback cb;
				cb.m_func_ptr = func_ptr;
				cb.m_data = data;
				if ( proxy->m_callbacks.IsMember( cb ) == false ) {
					proxy->m_callbacks.Append( cb );
				}
			}
			free( subject_name );
			if ( email )
				free( email );
			free( fqan );
			free( first_fqan );
			return proxy;

		}

		free( subject_name );
		free( email );
		free( fqan );
		free( first_fqan );
		//sprintf( error, "%s is not set in the job ad", ATTR_X509_USER_PROXY );
		error = "";
		return NULL;
	}

	// If Condor-C submitted the job, the proxy_path is relative to the
	// spool directory.  For the purposes of this function, extend the
	// proxy path with the ATTR_JOB_IWD
	if (proxy_path[0] != DIR_DELIM_CHAR) {
		std::string iwd;
		job_ad->LookupString(ATTR_JOB_IWD, iwd);
		if (!iwd.empty()) {
			std::stringstream ss;
			ss << iwd << DIR_DELIM_CHAR << proxy_path;
			proxy_path = ss.str();
		}
	}

	if ( ProxiesByFilename.lookup( HashKey(proxy_path.c_str()), proxy ) == 0 ) {
		// We already know about this proxy,
		// use the existing Proxy struct
		proxy->num_references++;
		if ( func_ptr ) {
			Callback cb;
			cb.m_func_ptr = func_ptr;
			cb.m_data = data;
			if ( proxy->m_callbacks.IsMember( cb ) == false ) {
				proxy->m_callbacks.Append( cb );
			}
		}
		return proxy;

	} else {

		// We don't know about this proxy yet,
		// find the proxy's expiration time and subject name
		expire_time = x509_proxy_expiration_time( proxy_path.c_str() );
		if ( expire_time < 0 ) {
			dprintf( D_ALWAYS, "Failed to get expiration time of proxy %s\n",
					 proxy_path.c_str() );
			error = "Failed to get expiration time of proxy";
			return NULL;
		}
		subject_name = x509_proxy_identity_name( proxy_path.c_str() );
		if ( subject_name == NULL ) {
			dprintf( D_ALWAYS, "Failed to get identity of proxy %s\n",
					 proxy_path.c_str() );
			error = "Failed to get identity of proxy";
			return NULL;
		}

		email = x509_proxy_email( proxy_path.c_str() );

		fqan = NULL;
#if defined(HAVE_EXT_GLOBUS)
		int rc = extract_VOMS_info_from_file( proxy_path.c_str(), 0, NULL,
											  &first_fqan, &fqan );
		if ( rc != 0 && rc != 1 ) {
			dprintf( D_ALWAYS, "Failed to get voms info of proxy %s\n",
					 proxy_path.c_str() );
			error = "Failed to get voms info of proxy";
			free( subject_name );
			free( email );
			return NULL;
		}
#endif
		if ( fqan ) {
			has_voms_attrs = true;
		} else {
			fqan = strdup( subject_name );
		}

		// Create a Proxy struct for our new proxy and populate it
		proxy = new Proxy;
		proxy->proxy_filename = strdup(proxy_path.c_str());
		proxy->num_references = 1;
		proxy->expiration_time = expire_time;
		proxy->near_expired = (expire_time - time(NULL)) <= minProxy_time;
		proxy->id = next_proxy_id++;
		if ( func_ptr ) {
			Callback cb;
			cb.m_func_ptr = func_ptr;
			cb.m_data = data;
			if ( proxy->m_callbacks.IsMember( cb ) == false ) {
				proxy->m_callbacks.Append( cb );
			}
		}

		ProxiesByFilename.insert(HashKey(proxy_path.c_str()), proxy);

		if ( SubjectsByName.lookup( HashKey(fqan), proxy_subject ) != 0 ) {
			// We don't know about this proxy subject yet,
			// create a new ProxySubject and fill it out
			std::string tmp;
			proxy_subject = new ProxySubject;
			proxy_subject->subject_name = strdup( subject_name );
			proxy_subject->email = email ? strdup( email ) : NULL;
			proxy_subject->fqan = strdup( fqan );
			proxy_subject->first_fqan = first_fqan ? strdup( first_fqan ) : NULL;
			proxy_subject->has_voms_attrs = true;

			// Create a master proxy for our new ProxySubject
			Proxy *new_master = new Proxy;
			new_master->id = next_proxy_id++;
			formatstr( tmp, "%s/master_proxy.%d", masterProxyDirectory,
						 new_master->id );
			new_master->proxy_filename = strdup( tmp.c_str() );
			new_master->num_references = 0;
			new_master->subject = proxy_subject;
			SetMasterProxy( new_master, proxy );
			ProxiesByFilename.insert( HashKey(new_master->proxy_filename),
									  new_master );

			proxy_subject->master_proxy = new_master;

			SubjectsByName.insert(HashKey(proxy_subject->fqan),
								  proxy_subject);
		}

		proxy_subject->proxies.Append( proxy );

		proxy->subject = proxy_subject;

		// If the new Proxy is longer-lived than the current master proxy for
		// this subject, copy it for the new master.
		if ( proxy->expiration_time > proxy_subject->master_proxy->expiration_time ) {
			SetMasterProxy( proxy_subject->master_proxy, proxy );
		}

		free( subject_name );
		free( email );
		free( fqan );
		free( first_fqan );
	}

		// MyProxy crap
	std::string buff;
	if ( job_ad->LookupString( ATTR_MYPROXY_HOST_NAME, buff ) ) {

		int cluster;
		int proc;

		ASSERT( job_ad->LookupInteger( ATTR_CLUSTER_ID, cluster ) );
		ASSERT( job_ad->LookupInteger( ATTR_PROC_ID, proc ) );

		MyProxyEntry * myProxyEntry =new MyProxyEntry();

		myProxyEntry->last_invoked_time=0;
		myProxyEntry->get_delegation_pid=FALSE;
		myProxyEntry->get_delegation_err_fd=-1;
		myProxyEntry->get_delegation_err_filename=NULL;
		myProxyEntry->myproxy_server_dn=NULL;
		myProxyEntry->myproxy_password=NULL;
		myProxyEntry->myproxy_credential_name=NULL;

		myProxyEntry->myproxy_host=strdup(buff.c_str());
		myProxyEntry->cluster_id = cluster;
		myProxyEntry->proc_id = proc;

		// Get optional MYPROXY_SERVER_DN attribute
		if (job_ad->LookupString (ATTR_MYPROXY_SERVER_DN, buff)) {
			myProxyEntry->myproxy_server_dn=strdup(buff.c_str());
		}

		if (job_ad->LookupString (ATTR_MYPROXY_CRED_NAME, buff)) {
			myProxyEntry->myproxy_credential_name=strdup(buff.c_str());
		}

		if (job_ad->LookupInteger (ATTR_MYPROXY_REFRESH_THRESHOLD, myProxyEntry->refresh_threshold)) {
			//myProxyEntry->refresh_threshold=atoi(buff);	// In minutes
			dprintf (D_FULLDEBUG, "MyProxy Refresh Threshold %d\n",myProxyEntry->refresh_threshold);
		} else {
			myProxyEntry->refresh_threshold = 4*60;	// default 4 hrs
			dprintf (D_FULLDEBUG, "MyProxy Refresh Threshold %d (default)\n",myProxyEntry->refresh_threshold);
		}

		if (job_ad->LookupInteger (ATTR_MYPROXY_NEW_PROXY_LIFETIME, myProxyEntry->new_proxy_lifetime)) {
			//myProxyEntry->new_proxy_lifetime=atoi(buff); // In hours
			dprintf (D_FULLDEBUG, "MyProxy New Proxy Lifetime %d\n",myProxyEntry->new_proxy_lifetime);
		} else {
			myProxyEntry->new_proxy_lifetime = 12; // default 12 hrs
			dprintf (D_FULLDEBUG, "MyProxy New Proxy Lifetime %d (default)\n",myProxyEntry->new_proxy_lifetime);
		}

		dprintf (D_FULLDEBUG,
				 "Adding new MyProxy entry for proxy %s : host=%s, cred name=%s\n",
				 proxy->proxy_filename,
				 myProxyEntry->myproxy_host,
				 (myProxyEntry->myproxy_credential_name!=NULL)?(myProxyEntry->myproxy_credential_name):"<default>");
		proxy->myproxy_entries.Prepend (myProxyEntry); // Add at the top of the list, so it'll be used first

		// See if we already have a MyProxy entry for the given host/credential name
		/*int found = FALSE;
		MyProxyEntry * currentMyProxyEntry = NULL;
		jobProxy->myproxy_entries.Rewind();
			while (jobProxy->myproxy_entries.Next (currentMyProxyEntry)) {
			if (strcmp (currentMyProxyEntry->myproxy_host, myProxyEntry->myproxy_host)) {
				continue;
			}
				if (myProxyEntry->myproxy_credential_name == NULL || myProxyEntry->myproxy_credential_name == NULL) {
				if (myProxyEntry->myproxy_credential_name != NULL || myProxyEntry->myproxy_credential_name != NULL) {
					// One credential name is NULL, the other is not
					continue;
				}
			} else {
				if (strcmp (currentMyProxyEntry->myproxy_credential_name, myProxyEntry->myproxy_credential_name))  {
					// credential names non-null and not-equal
					continue;
				}
			}

			// If we've gotten this far, we've got a match
			found = TRUE;
			break;
		}

		//... If we don't, insert it
		if (!found) {
			dprintf (D_FULLDEBUG,
					 "Adding new MyProxy entry for proxy %s : host=%s, cred name=%s\n",
					 jobProxy->proxy_filename,
					 myProxyEntry->myproxy_host,
					 (myProxyEntry->myproxy_credential_name!=NULL)?(myProxyEntry->myproxy_credential_name):"<default>");
			jobProxy->myproxy_entries.Append (myProxyEntry);
		} else {
			// No need to insert this
			delete myProxyEntry;
		}*/
	}

	return proxy;
}
int
handle_gahp_command(char ** argv, int argc) {
	// Assume it's been verified

	if (strcasecmp (argv[0], GAHP_COMMAND_JOB_REMOVE)==0) {
		int req_id = 0;
		int cluster_id, proc_id;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_job_id (argv[3], &cluster_id, &proc_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createRemoveRequest(
				req_id,
				cluster_id,
				proc_id,
				argv[4]));
		return TRUE;
	} else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_HOLD)==0) {
		int req_id = 0;
		int cluster_id, proc_id;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_job_id (argv[3], &cluster_id, &proc_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createHoldRequest(
				req_id,
				cluster_id,
				proc_id,
				argv[4]));
		return TRUE;

	} else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_RELEASE)==0) {

		int req_id = 0;
		int cluster_id, proc_id;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_job_id (argv[3], &cluster_id, &proc_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createReleaseRequest(
				req_id,
				cluster_id,
				proc_id,
				argv[4]));
		return TRUE;

	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_STATUS_CONSTRAINED) ==0) {

		int req_id;

		if (!(argc == 4 &&
			get_int (argv[1], &req_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		char * constraint = argv[3];


		enqueue_command (
			SchedDRequest::createStatusConstrainedRequest(
				req_id,
				constraint));

		return TRUE;
	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_UPDATE_CONSTRAINED) ==0) {
		int req_id;
		ClassAd * classad;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_class_ad (argv[4], &classad))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		char * constraint = argv[3];

		enqueue_command (
			SchedDRequest::createUpdateConstrainedRequest(
				req_id,
				constraint,
				classad));

		delete classad;
		return TRUE;

	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_UPDATE) ==0) {

		int req_id;
		ClassAd * classad;
		int cluster_id, proc_id;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_job_id (argv[3], &cluster_id, &proc_id) &&
			get_class_ad (argv[4], &classad))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		//char * constraint = argv[3];

		enqueue_command (
			SchedDRequest::createUpdateRequest(
				req_id,
				cluster_id,
				proc_id,
				classad));

		delete classad;
		return TRUE;
	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_SUBMIT) ==0) {
		int req_id;
		ClassAd * classad;

		if (!(argc == 4 &&
			get_int (argv[1], &req_id) &&
			get_class_ad (argv[3], &classad))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createSubmitRequest(
				req_id,
				classad));

		delete classad;
		return TRUE;
	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_UPDATE_LEASE) ==0) {
		int req_id;
		int num_jobs;

		if (!(argc >= 4 &&
			get_int (argv[1], &req_id) &&
			get_int (argv[3], &num_jobs))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		job_expiration * expirations = new job_expiration[num_jobs];
		int i;
		for (i=0; i<num_jobs; i++) {
			if (!get_job_id(argv[4+i*2], 
							&(expirations[i].cluster),
							&(expirations[i].proc))) {
				delete[] expirations;
				return FALSE;
			}

			if (!get_ulong (argv[4+i*2+1], &(expirations[i].expiration))) {
				delete [] expirations;
				return FALSE;
			}
		}	

		enqueue_command (
			SchedDRequest::createUpdateLeaseRequest(
													req_id,
													num_jobs,
													expirations));

		delete [] expirations;
		return TRUE;
	}  else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_STAGE_IN) ==0) {
		int req_id;
		ClassAd * classad;

		if (!(argc == 4 &&
			get_int (argv[1], &req_id) &&
			get_class_ad (argv[3], &classad))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createJobStageInRequest(
				req_id,
				classad));

		delete classad;
		return TRUE;
	} else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_STAGE_OUT) ==0) {
		int req_id;
		int cluster_id, proc_id;

		if (!(argc == 4 &&
			  get_int (argv[1], &req_id) &&
			  get_job_id (argv[3], &cluster_id, &proc_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createJobStageOutRequest(
				req_id,
				cluster_id,
				proc_id));

		return TRUE;
	} else if (strcasecmp (argv[0], GAHP_COMMAND_JOB_REFRESH_PROXY)==0) {
		int req_id = 0;
		int cluster_id, proc_id;

		if (!(argc == 5 &&
			get_int (argv[1], &req_id) &&
			get_job_id (argv[3], &cluster_id, &proc_id))) {

			dprintf (D_ALWAYS, "Invalid args to %s\n", argv[0]);
			return FALSE;
		}

		enqueue_command (
			SchedDRequest::createRefreshProxyRequest(
				req_id,
				cluster_id,
				proc_id,
				argv[4]));
		return TRUE;
	} else if (strcasecmp (argv[0], GAHP_COMMAND_INITIALIZE_FROM_FILE)==0) {
		static bool init_done = false;

		if ( init_done == false ) {
			SetEnv( "X509_USER_PROXY", argv[1] );
			UnsetEnv( "X509_USER_CERT" );
			UnsetEnv( "X509_USER_KEY" );
			proxySubjectName = x509_proxy_identity_name( argv[1] );
			if ( !proxySubjectName ) {
				dprintf( D_ALWAYS, "Failed to query certificate identity "
						 "from %s\n",  argv[1] );
				return TRUE;
			}
			Reconfig();
			init_done = true;
		}
		return TRUE;
	}

	dprintf (D_ALWAYS, "Invalid command %s\n", argv[0]);
	return FALSE;
}