ClassAd *CollectorEngine::
collect (int command, Sock *sock, const condor_sockaddr& from, int &insert)
{
	ClassAd	*clientAd;
	ClassAd	*rval;

	_condor_auto_accum_runtime<collector_runtime_probe> rt(CollectorEngine_ruc_runtime);
	double rt_last = rt.begin;

		// Avoid lengthy blocking on communication with our peer.
		// This command-handler should not get called until data
		// is ready to read.
	sock->timeout(1);

	// get the ad
	clientAd = new ClassAd;
	if (!clientAd) return 0;

	if( !getClassAdEx(sock, *clientAd, m_get_ad_options) )
	{
		dprintf (D_ALWAYS,"Command %d on Sock not followed by ClassAd (or timeout occured)\n",
				command);
		delete clientAd;
		sock->end_of_message();
		return 0;
	}

	double delta_time = rt.tick(rt_last);
	CollectorEngine_ruc_getAd_runtime.Add(delta_time);

	// insert the authenticated user into the ad itself
	const char* authn_user = sock->getFullyQualifiedUser();
	if (authn_user) {
		clientAd->Assign("AuthenticatedIdentity", authn_user);
		clientAd->Assign("AuthenticationMethod", sock->getAuthenticationMethodUsed());
	} else {
		// remove it from the ad if it's not authenticated.
		clientAd->Delete("AuthenticatedIdentity");
		clientAd->Delete("AuthenticationMethod");
	}

	CollectorEngine_ruc_authid_runtime.Add(rt.tick(rt_last));

	rval = collect(command, clientAd, from, insert, sock);
	CollectorEngine_ruc_collect_runtime.Add(rt.tick(rt_last));

	// Don't leak the ad on error!
	if ( ! rval ) {
		delete clientAd;
	}

	// get the end_of_message()
	if (!sock->end_of_message())
	{
		dprintf(D_FULLDEBUG,"Warning: Command %d; maybe shedding data on eom\n",
				 command);
	}
	
	return rval;
}
Beispiel #2
0
void ScheddStatistics::Unpublish(ClassAd & ad) const
{
   ad.Delete("StatsLifetime");
   ad.Delete("StatsLastUpdateTime");
   ad.Delete("RecentStatsLifetime");
   ad.Delete("RecentStatsTickTime");
   ad.Delete("RecentWindowMax");
   Pool.Unpublish(ad);
}
Beispiel #3
0
void stats_recent_counter_timer::Unpublish(ClassAd & ad, const char * pattr) const
{
   ad.Delete(pattr);
   MyString attr;
   attr.sprintf("Recent%s",pattr);
   ad.Delete(attr.Value());
   attr.sprintf("Recent%sRuntime",pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6); // +6 to skip "Recent" prefix
}
Beispiel #4
0
void stats_entry_sum_ema_rate<T>::Unpublish(ClassAd & ad, const char * pattr) const {
	ad.Delete(pattr);
	for(size_t i=ema.size(); i--;) {
		stats_ema_config::horizon_config &config = ema_config->horizons[i];
		std::string attr_name;
		size_t pattr_len;
		if( (pattr_len=strlen(pattr)) >= 7 && strcmp(pattr+pattr_len-7,"Seconds")==0 ) {
			formatstr(attr_name,"%.*sLoad_%s",(int)(pattr_len-7),pattr,config.horizon_name.c_str());
		}
		else {
			formatstr(attr_name,"%sPerSecond_%s",pattr,config.horizon_name.c_str());
		}
		ad.Delete(attr_name.c_str());
	}
}
Beispiel #5
0
int
LogDeleteAttribute::Play(void *data_structure)
{
	ClassAdHashTable *table = (ClassAdHashTable *)data_structure;
	ClassAd *ad = 0;
	if (table->lookup(HashKey(key), ad) < 0)
		return -1;

#if defined(HAVE_DLOPEN)
	ClassAdLogPluginManager::DeleteAttribute(key, name);
#endif

	return ad->Delete(name);
}
ClassAd *CollectorEngine::
collect (int command, Sock *sock, const condor_sockaddr& from, int &insert)
{
	ClassAd	*clientAd;
	ClassAd	*rval;

		// Avoid lengthy blocking on communication with our peer.
		// This command-handler should not get called until data
		// is ready to read.
	sock->timeout(1);

	clientAd = new ClassAd;
	if (!clientAd) return 0;

	// get the ad
	if( !clientAd->initFromStream(*sock) )
	{
		dprintf (D_ALWAYS,"Command %d on Sock not follwed by ClassAd (or timeout occured)\n",
				command);
		delete clientAd;
		sock->end_of_message();
		return 0;
	}

	// insert the authenticated user into the ad itself
	const char* authn_user = sock->getFullyQualifiedUser();
	if (authn_user) {
		clientAd->Assign("AuthenticatedIdentity", authn_user);
	} else {
		// remove it from the ad if it's not authenticated.
		clientAd->Delete("AuthenticatedIdentity");
	}

	rval = collect(command, clientAd, from, insert, sock);

	// Don't leak the ad on error!
	if ( ! rval ) {
		delete clientAd;
	}

	// get the end_of_message()
	if (!sock->end_of_message())
	{
		dprintf(D_FULLDEBUG,"Warning: Command %d; maybe shedding data on eom\n",
				 command);
	}
	
	return rval;
}
Beispiel #7
0
void DaemonCore::Stats::Unpublish(ClassAd & ad) const
{
   ad.Delete("DCStatsLifetime");
   ad.Delete("DCStatsLastUpdateTime");
   ad.Delete("DCRecentStatsLifetime");
   ad.Delete("DCRecentStatsTickTime");
   ad.Delete("DCRecentWindowMax");
   ad.Delete("DaemonCoreDutyCycle");
   ad.Delete("RecentDaemonCoreDutyCycle");
   Pool.Unpublish(ad);
}
Beispiel #8
0
void StatisticsPool::Unpublish(ClassAd & ad) const
{
   pubitem item;
   MyString name;

   // boo! HashTable doesn't support const, so I have to remove const from this
   // to make the compiler happy.
   StatisticsPool * pthis = const_cast<StatisticsPool*>(this);
   pthis->pub.startIterations();
   while (pthis->pub.iterate(name,item)) 
      {
      const char * pattr = item.pattr ? item.pattr : name.Value();
      if (item.Unpublish) 
         {
         stats_entry_base * probe = (stats_entry_base *)item.pitem;
         (probe->*(item.Unpublish))(ad, pattr);
         }
      else
         ad.Delete(pattr);
      }
}
/*! handle a log Entry: work with a job queue collection.
 *  (not with DBMS directry)
 */
QuillErrCode
JobQueueDBManager::processLogEntry(int op_type, JobQueueCollection* jobQueue)
{
	char *key, *mytype, *targettype, *name, *value;
	key = mytype = targettype = name = value = NULL;
	QuillErrCode st = QUILL_SUCCESS;

	int job_id_type;
	char cid[512];
	char pid[512];

		// REMEMBER:
		//	each get*ClassAdBody() funtion allocates the memory of 
		// 	parameters. Therefore, they all must be deallocated here,
		// and they are at the end of the routine
	switch(op_type) {
	case CondorLogOp_NewClassAd: {
		if (caLogParser->getNewClassAdBody(key, mytype, targettype) == QUILL_FAILURE)
			{
				st = QUILL_FAILURE;
				break;
			}
		job_id_type = getProcClusterIds(key, cid, pid);
		ClassAd* ad = new ClassAd();
		SetMyTypeName(*ad, "Job");
		SetTargetTypeName(*ad, "Machine");

		switch(job_id_type) {
		case IS_CLUSTER_ID:
			jobQueue->insertClusterAd(cid, ad);
			break;

		case IS_PROC_ID:
			jobQueue->insertProcAd(cid, pid, ad);
			break;

		default:
			dprintf(D_ALWAYS, "[QUILL++] New ClassAd --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}

		break;
	}
	case CondorLogOp_DestroyClassAd: {
		if (caLogParser->getDestroyClassAdBody(key) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;		
		}

		job_id_type = getProcClusterIds(key, cid, pid);

		switch(job_id_type) {
		case IS_CLUSTER_ID:
			jobQueue->removeClusterAd(cid);
			break;

		case IS_PROC_ID: {
			ClassAd *clusterad = jobQueue->find(cid);
			ClassAd *procad = jobQueue->find(cid,pid);
			if(!clusterad || !procad) {
			    dprintf(D_ALWAYS, 
						"[QUILL++] Destroy ClassAd --- Cannot find clusterad "
						"or procad in memory job queue");
				st = QUILL_FAILURE; 
				break;
			}

			jobQueue->removeProcAd(cid, pid);
			
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Destroy ClassAd --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}

		break;
	}
	case CondorLogOp_SetAttribute: {	
		if (caLogParser->getSetAttributeBody(key, name, value) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;
		}
						
		job_id_type = getProcClusterIds(key, cid, pid);

		char tmp[512];

		snprintf(tmp, 512, "%s = %s", name, value);

		switch (job_id_type) {
		case IS_CLUSTER_ID: {
			ClassAd* ad = jobQueue->findClusterAd(cid);
			if (ad != NULL) {
				ad->Insert(tmp);
			}
			else {
				dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Cluster Ad[%s]\n", cid);
			}
			break;
		}
		case IS_PROC_ID: {
			ClassAd* ad = jobQueue->findProcAd(cid, pid);
			if (ad != NULL) {
				ad->Insert(tmp);
			}
			else {
				dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Proc Ad[%s.%s]\n", cid, pid);
			}
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Set Attribute --- ERROR\n");
			st = QUILL_FAILURE; 
			break;
		}
		break;
	}
	case CondorLogOp_DeleteAttribute: {
		if (caLogParser->getDeleteAttributeBody(key, name) == QUILL_FAILURE) {
			st = QUILL_FAILURE; 
			break;
		}

		job_id_type = getProcClusterIds(key, cid, pid);

		switch(job_id_type) {
		case IS_CLUSTER_ID: {
			ClassAd* ad = jobQueue->findClusterAd(cid);
			ad->Delete(name);
			break;
		}
		case IS_PROC_ID: {
			ClassAd* ad = jobQueue->findProcAd(cid, pid);
			ad->Delete(name);
			break;
		}
		default:
			dprintf(D_ALWAYS, "[QUILL++] Delete Attribute --- ERROR\n");
			st = QUILL_FAILURE; 
		}
		break;
	}
	case CondorLogOp_BeginTransaction:
		st = processBeginTransaction(true);
		break;
	case CondorLogOp_EndTransaction:
		st = processEndTransaction(true);
		break;
			// skip the log historical sequence number command
	case CondorLogOp_LogHistoricalSequenceNumber:
		break;
	default:
		printf("[QUILL++] Unsupported Job Queue Command\n");
		st = QUILL_FAILURE; 
		break;
	}

		// pointers are release
	if (key != NULL) free(key);
	if (mytype != NULL) free(mytype);
	if (targettype != NULL) free(targettype);
	if (name != NULL) free(name);
	if (value != NULL) free(value);
	return st;
}
Beispiel #10
0
void MachAttributes::init_machine_resources() {
    // defines the space of local machine resources, and their quantity
    m_machres_map.clear();

    // this may be filled from resource inventory scripts
    m_machres_attr.Clear();

    // these are reserved for standard/fixed resources
    std::set<string> fixedRes;
    fixedRes.insert("cpu");
    fixedRes.insert("cpus");
    fixedRes.insert("disk");
    fixedRes.insert("swap");
    fixedRes.insert("mem");
    fixedRes.insert("memory");
    fixedRes.insert("ram");

    // get the list of defined local resource names:
    char* ptmp = param("MACHINE_RESOURCE_NAMES");
    string resnames;
    if (NULL != ptmp) {
        // if admin defined MACHINE_RESOURCE_NAMES, then use this list
        // as the source of expected custom machine resources
        resnames = ptmp;
        free(ptmp);
    } else {
        // otherwise, build the list of custom machine resources from
        // all occurrences of MACHINE_RESOURCE_<resname>
        std::set<string> resset;
        Regex re;
        int err = 0;
        const char* pszMsg = 0;
        const string prefix = "MACHINE_RESOURCE_";
        const string invprefix = "INVENTORY_";
        const string restr = prefix + "(.+)";
        ASSERT(re.compile(restr.c_str(), &pszMsg, &err, PCRE_CASELESS));
	std::vector<std::string> resdef;
        const int n = param_names_matching(re, resdef);
        for (int j = 0;  j < n;  ++j) {
            string rname = resdef[j].substr(prefix.length());
            string testinv = rname.substr(0, invprefix.length());
            if (0 == strcasecmp(testinv.c_str(), invprefix.c_str())) {
                // if something was defined via MACHINE_RESOURCE_INVENTORY_<rname>, strip "INVENTORY_"
                rname = rname.substr(invprefix.length());
            }
            std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower);
            resset.insert(rname);
        }
        for (std::set<string>::iterator j(resset.begin());  j != resset.end();  ++j) {
            resnames += " ";
            resnames += *j;
        }
    }

    // scan the list of local resources, to obtain their quantity and associated attributes (if any)
    StringList reslist(resnames.c_str());
    reslist.rewind();
    while (const char* rnp = reslist.next()) {
        string rname(rnp);
        std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower);
        if (fixedRes.count(rname) > 0) {
            EXCEPT("pre-defined resource name '%s' is reserved", rname.c_str());
        }

        // If MACHINE_RESOURCE_<rname> is present, use that and move on:
        string pname;
        formatstr(pname, "MACHINE_RESOURCE_%s", rname.c_str());
        char* machresp = param(pname.c_str());
        if (machresp) {
            int v = param_integer(pname.c_str(), 0, 0, INT_MAX);
            m_machres_map[rname] = v;
            free(machresp);
            continue;
        }

        // current definition of REMIND macro is not working with gcc
        #pragma message("MACHINE_RESOURCE_INVENTORY_<rname> is deprecated, and will be removed when a solution using '|' in config files is fleshed out")
        // if we didn't find MACHINE_RESOURCE_<rname>, then try MACHINE_RESOURCE_INVENTORY_<rname>
        formatstr(pname, "MACHINE_RESOURCE_INVENTORY_%s", rname.c_str());
        char* invscriptp = param(pname.c_str());
        if (NULL == invscriptp) {
            EXCEPT("Missing configuration for local machine resource %s", rname.c_str());
        }

        // if there is an inventory script, then attempt to execute it and use its output to
        // identify the local resource quantity, and any associated attributes:
        string invscript = invscriptp;
        free(invscriptp);

        ArgList invcmd;
        StringList invcmdal(invscript.c_str());
        invcmdal.rewind();
        while (char* invarg = invcmdal.next()) {
            invcmd.AppendArg(invarg);
        }
        FILE* fp = my_popen(invcmd, "r", FALSE);
        if (NULL == fp) {
            EXCEPT("Failed to execute local resource inventory script \"%s\"\n", invscript.c_str());
        }

        ClassAd invad;
        char invline[1000];
        while (fgets(invline, sizeof(invline), fp)) {
            if (!invad.Insert(invline)) {
                dprintf(D_ALWAYS, "Failed to insert \"%s\" into machine resource attributes: ignoring\n", invline);
            }
        }
        my_pclose(fp);

        // require the detected machine resource to be present as an attribute
        string ccname(rname.c_str());
        *(ccname.begin()) = toupper(*(ccname.begin()));
        string detname;
        formatstr(detname, "%s%s", ATTR_DETECTED_PREFIX, ccname.c_str());
        int v = 0;
        if (!invad.LookupInteger(detname.c_str(), v)) {
            EXCEPT("Missing required attribute \"%s = <n>\" from output of %s\n", detname.c_str(),  invscript.c_str());
        }

        // success
        m_machres_map[rname] = v;
        invad.Delete(rname.c_str());
        m_machres_attr.Update(invad);
    }

    for (slotres_map_t::iterator j(m_machres_map.begin());  j != m_machres_map.end();  ++j) {
        dprintf(D_ALWAYS, "Local machine resource %s = %d\n", j->first.c_str(), int(j->second));
    }
}
Beispiel #11
0
template <> void stats_entry_recent<Probe>::Unpublish(ClassAd& ad, const char * pattr) const
{
   MyString attr;
   ad.Delete(pattr);
   attr.sprintf("Recent%s", pattr);
   ad.Delete(attr.Value());

   attr.sprintf("Recent%sCount", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
   attr.sprintf("Recent%sSum", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
   attr.sprintf("Recent%sAvg", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
   attr.sprintf("Recent%sMin", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
   attr.sprintf("Recent%sMax", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
   attr.sprintf("Recent%sStd", pattr);
   ad.Delete(attr.Value());
   ad.Delete(attr.Value()+6);
}
Beispiel #12
0
int
CondorQ::fetchQueueFromHostAndProcessV2(const char *host,
					const char *constraint,
					StringList &attrs,
					int fetch_opts,
					int match_limit,
					condor_q_process_func process_func,
					void * process_func_data,
					int connect_timeout,
					int useFastPath,
					CondorError *errstack,
					ClassAd ** psummary_ad)
{
	classad::ClassAdParser parser;
	classad::ExprTree *expr = NULL;
	parser.ParseExpression(constraint, expr);
	if (!expr) return Q_INVALID_REQUIREMENTS;

	classad::ClassAd request_ad;  // query ad to send to schedd
	ClassAd *ad = NULL;	// job ad result

	request_ad.Insert(ATTR_REQUIREMENTS, expr);

	char *projection = attrs.print_to_delimed_string("\n");
	if (projection) {
		request_ad.InsertAttr(ATTR_PROJECTION, projection);
		free(projection);
	}

	bool want_authentication = false;
	if (fetch_opts == fetch_DefaultAutoCluster) {
		request_ad.InsertAttr("QueryDefaultAutocluster", true);
		request_ad.InsertAttr("MaxReturnedJobIds", 2); // TODO: make this settable by caller of this function.
	} else if (fetch_opts == fetch_GroupBy) {
		request_ad.InsertAttr("ProjectionIsGroupBy", true);
		request_ad.InsertAttr("MaxReturnedJobIds", 2); // TODO: make this settable by caller of this function.
	} else {
		if (fetch_opts & fetch_MyJobs) {
			const char * owner = my_username();
			if (owner) { request_ad.InsertAttr("Me", owner); }
			request_ad.InsertAttr("MyJobs", owner ? "(Owner == Me)" : "true");
			want_authentication = true;
		}
		if (fetch_opts & fetch_SummaryOnly) {
			request_ad.InsertAttr("SummaryOnly", true);
		}
		if (fetch_opts & fetch_IncludeClusterAd) {
			request_ad.InsertAttr("IncludeClusterAd", true);
		}
	}

	if (match_limit >= 0) {
		request_ad.InsertAttr(ATTR_LIMIT_RESULTS, match_limit);
	}

	// determine if authentication can/will happen.  three reasons why it might not:
	// 1) security negotiation is disabled (NEVER or OPTIONAL for outgoing connections)
	// 2) Authentication is disabled (NEVER) by the client
	// 3) Authentication is disabled (NEVER) by the server.  this is actually impossible to
	//    get correct without actually querying the server but we make an educated guess by
	//    paraming the READ auth level.
	bool can_auth = true;
	char *paramer = NULL;

	paramer = SecMan::getSecSetting ("SEC_%s_NEGOTIATION", CLIENT_PERM);
	if (paramer != NULL) {
		char p = toupper(paramer[0]);
		free(paramer);
		if (p == 'N' || p == 'O') {
			// authentication will not happen since no security negotiation will occur
			can_auth = false;
		}
	}

	paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION", CLIENT_PERM);
	if (paramer != NULL) {
		char p = toupper(paramer[0]);
		free(paramer);
		if (p == 'N') {
			// authentication will not happen since client doesn't allow it.
			can_auth = false;
		}
	}

	// authentication will not happen since server probably doesn't allow it.
	// on the off chance that someone's config manages to trick us, leave an
	// undocumented knob as a last resort to disable our inference.
	if (param_boolean("CONDOR_Q_INFER_SCHEDD_AUTHENTICATION", true)) {
		paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION", READ);
		if (paramer != NULL) {
			char p = toupper(paramer[0]);
			free(paramer);
			if (p == 'N') {
				can_auth = false;
			}
		}

		paramer = SecMan::getSecSetting ("SCHEDD.SEC_%s_AUTHENTICATION", READ);
		if (paramer != NULL) {
			char p = toupper(paramer[0]);
			free(paramer);
			if (p == 'N') {
				can_auth = false;
			}
		}
	}

	if (!can_auth) {
		dprintf (D_ALWAYS, "detected that authentication will not happen.  falling back to QUERY_JOB_ADS without authentication.\n");
	}

	DCSchedd schedd(host);
	int cmd = QUERY_JOB_ADS;
	if (want_authentication && can_auth && (useFastPath > 2)) {
		cmd = QUERY_JOB_ADS_WITH_AUTH;
	}
	Sock* sock;
	if (!(sock = schedd.startCommand(cmd, Stream::reli_sock, connect_timeout, errstack))) return Q_SCHEDD_COMMUNICATION_ERROR;

	classad_shared_ptr<Sock> sock_sentry(sock);

	if (!putClassAd(sock, request_ad) || !sock->end_of_message()) return Q_SCHEDD_COMMUNICATION_ERROR;
	dprintf(D_FULLDEBUG, "Sent classad to schedd\n");

	int rval = 0;
	do {
		ad = new ClassAd();
		if ( ! getClassAd(sock, *ad) || ! sock->end_of_message()) {
			rval = Q_SCHEDD_COMMUNICATION_ERROR;
			break;
		}
		dprintf(D_FULLDEBUG, "Got classad from schedd.\n");
		long long intVal;
		if (ad->EvaluateAttrInt(ATTR_OWNER, intVal) && (intVal == 0))
		{ // Last ad.
			sock->close();
			dprintf(D_FULLDEBUG, "Ad was last one from schedd.\n");
			std::string errorMsg;
			if (ad->EvaluateAttrInt(ATTR_ERROR_CODE, intVal) && intVal && ad->EvaluateAttrString(ATTR_ERROR_STRING, errorMsg))
			{
				if (errstack) errstack->push("TOOL", intVal, errorMsg.c_str());
				rval = Q_REMOTE_ERROR;
			}
			if (psummary_ad && rval == 0) {
				std::string val;
				if (ad->LookupString(ATTR_MY_TYPE, val) && val == "Summary") {
					ad->Delete(ATTR_OWNER); // remove the bogus owner attribute
					*psummary_ad = ad; // return the final ad, because it has summary information
					ad = NULL; // so we don't delete it below.
				}
			}
			break;
		}
		// Note: According to condor_q.h, process_func() will return false if taking
		// ownership of ad, so only delete if it returns true, else set to NULL
		// so we don't delete it here.  Either way, next set ad to NULL since either
		// it has been deleted or will be deleted later by process_func().
		if (process_func(process_func_data, ad)) {
			delete ad;
		}
		ad = NULL;
	} while (true);

	// Make sure ad is not leaked no matter how we break out of the above loop.
	delete ad;

	return rval;
}