// 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; }