Beispiel #1
0
/**
 * @brief
 * 		do an initial check to see if a resresv can fit into a node partition
 *        based on the meta data we keep.
 *
 * @param[in]	policy	-	policy info
 * @param[in]	np	-	node partition to check
 * @param[in]	resresv	-	job/resv to see if it can fit
 * @param[in]	flags	-	check_flags
 *							COMPARE_TOTAL - compare with resources_available value
 *							RETURN_ALL_ERR - return all the errors, not just the first failure
 * @param[in]	err	-	schd_error structure to return why job/resv can't fit
 *
 * @return	int
 * @retval	1	: can fit
 * @retval	0	: can't fit
 * @retval	-1	: on error
 */
int
resresv_can_fit_nodepart(status *policy, node_partition *np, resource_resv *resresv,
	int flags, schd_error *err)
{
	int i;
	schd_error *prev_err = NULL;
	int can_fit = 1;
	int pass_flags;
	resource_req *req;
	selspec *spec = NULL;
	place *pl = NULL;


	if (policy == NULL || np == NULL || resresv == NULL || err == NULL)
		return -1;

	pass_flags = flags|UNSET_RES_ZERO;

	/* Check 1: Based on the flag check if there are any nodes available or if
	 * they are free.
	 */
	if (flags & COMPARE_TOTAL) {
		/* Check that node partition must have one or more nodes inside it */
		if (np->tot_nodes == 0) {
			set_schd_error_codes(err, NEVER_RUN, NO_TOTAL_NODES);
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	} else {
		/* Check is there at least 1 node in the free state */
		if (np->free_nodes == 0) {
			set_schd_error_codes(err, NOT_RUN, NO_FREE_NODES);
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	}

	/* Check 2: v/scatter - If we're scattering or requesting exclusive nodes
	 * we know we need at least as many nodes as requested chunks */
	if (resresv->place_spec->scatter || resresv->place_spec->vscatter) {
		int nodect;
		enum sched_error error_code;
		enum schd_err_status status_code;
		if ( (flags & COMPARE_TOTAL) ) {
			nodect = np->tot_nodes;
			error_code = NO_TOTAL_NODES;
			status_code = NEVER_RUN;
		} else {
			nodect = np->free_nodes;
			error_code = NO_FREE_NODES;
			status_code = NOT_RUN;
		}

		if (nodect < resresv->select->total_chunks) {
			set_schd_error_codes(err, status_code, error_code);
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	}

	/* Check 3: Job Wide RASSN resources(e.g., ncpus, mem).  We only check
	 * resources that the server has summed over the select statement.  We
	 * know these came from the nodes so should be checked on the nodes.  Other
	 * resources are for server/queue and so we ignore them here
	 */
	if (resresv->is_job && resresv->job != NULL && resresv->job->resreq_rel != NULL)
		req = resresv->job->resreq_rel;
	else
		req = resresv->resreq;
	if (check_avail_resources(np->res, req,
				pass_flags, policy->resdef_to_check_rassn_select,
				INSUFFICIENT_RESOURCE, err) == 0) {
		if ((flags & RETURN_ALL_ERR)) {
			can_fit = 0;
			err->next = new_schd_error();
			prev_err = err;
			err = err->next;
		} else
			return 0;
	}

	/* Check 4: Chunk level resources: Check each chunk compared to the meta data
	 *          This is mostly for non-consumables.  Booleans are always honored
	 *	      on nodes regardless if they are in the resources line.  This is a
	 *	      grandfathering in from the old nodespec properties.
	 */
	/* The call to get_resresv_spec is needed here because we are checking for resources on each
	 * chunk. For jobs that already have execselect specification defined we only need to
	 * traverse through those chunks.
	 * get_resresv_spec sets the spec value to execselect/select depending on whether execselect
	 * was set or not.
	 */
	get_resresv_spec(resresv, &spec, &pl);
	for (i = 0; spec->chunks[i] != NULL; i++) {
		if (check_avail_resources(np->res, spec->chunks[i]->req,
					pass_flags | CHECK_ALL_BOOLS, policy->resdef_to_check,
					INSUFFICIENT_RESOURCE, err) == 0) {
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	}
	if((flags&RETURN_ALL_ERR)) {
		if(prev_err != NULL) {
			prev_err->next = NULL;
			free(err);
		}
		return can_fit;
	}
	return 1;
}
Beispiel #2
0
/**
 * @brief
 * 		do an initial check to see if a resresv can fit into a node partition
 *        based on the meta data we keep.
 *
 * @param[in]	policy	-	policy info
 * @param[in]	np	-	node partition to check
 * @param[in]	resresv	-	job/resv to see if it can fit
 * @param[in]	flags	-	check_flags
 *							COMPARE_TOTAL - compare with resources_available value
 *							RETURN_ALL_ERR - return all the errors, not just the first failure
 * @param[in]	err	-	schd_error structure to return why job/resv can't fit
 *
 * @return	int
 * @retval	1	: can fit
 * @retval	0	: can't fit
 * @retval	-1	: on error
 */
int
resresv_can_fit_nodepart(status *policy, node_partition *np, resource_resv *resresv,
	int flags, schd_error *err)
{
	int i;
	schd_error *prev_err = NULL;
	int can_fit = 1;
	int pass_flags;
	
	
	if (policy == NULL || np == NULL || resresv == NULL || err == NULL)
		return -1;
	
	pass_flags = flags|UNSET_RES_ZERO;
	
	/* Check 1: is there at least 1 node in the free state */
	if (!(flags & COMPARE_TOTAL) && np->free_nodes == 0) {
		set_schd_error_codes(err, NOT_RUN, NO_FREE_NODES);
		if ((flags & RETURN_ALL_ERR)) {
			can_fit = 0;
			err->next = new_schd_error();
			prev_err = err;
			err = err->next;
		} else
			return 0;
	}

	/* Check 2: v/scatter - If we're scattering or requesting exclusive nodes
	 * we know we need at least as many nodes as requested chunks */
	if (resresv->place_spec->scatter || resresv->place_spec->vscatter) {
		int nodect;
		enum sched_error error_code;
		enum schd_err_status status_code;
		if ( (flags & COMPARE_TOTAL) ) {
			nodect = np->tot_nodes;
			error_code = NO_TOTAL_NODES;
			status_code = NEVER_RUN;
		} else {
			nodect = np->free_nodes;
			error_code = NO_FREE_NODES;
			status_code = NOT_RUN;
		}

		if (nodect < resresv->select->total_chunks) {
			set_schd_error_codes(err, status_code, error_code);
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	}

	/* Check 3: Job Wide RASSN resources(e.g., ncpus, mem).  We only check
	 * resources that the server has summed over the select statement.  We
	 * know these came from the nodes so should be checked on the nodes.  Other
	 * resources are for server/queue and so we ignore them here
	 */
	if (check_avail_resources(np->res, resresv->resreq,
				pass_flags, policy->resdef_to_check_rassn,
				INSUFFICIENT_RESOURCE, err) == 0) {
		if ((flags & RETURN_ALL_ERR)) {
			can_fit = 0;
			err->next = new_schd_error();
			prev_err = err;
			err = err->next;
		} else
			return 0;
	}

	/* Check 4: Chunk level resources: Check each chunk compared to the meta data
	 *          This is mostly for non-consumables.  Booleans are always honored
	 *	      on nodes regardless if they are in the resources line.  This is a
	 *	      grandfathering in from the old nodespec properties.
	 */
	for (i = 0; resresv->select->chunks[i] != NULL; i++) {
		if (check_avail_resources(np->res, resresv->select->chunks[i]->req,
					pass_flags | CHECK_ALL_BOOLS, policy->resdef_to_check,
					INSUFFICIENT_RESOURCE, err) == 0) {
			if ((flags & RETURN_ALL_ERR)) {
				can_fit = 0;
				err->next = new_schd_error();
				prev_err = err;
				err = err->next;
			} else
				return 0;
		}
	}
	if((flags&RETURN_ALL_ERR)) {
		if(prev_err != NULL) {
			prev_err->next = NULL;
			free(err);
		}
		return can_fit;
	}
	return 1;
}