/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive.scheduler.policy.ram;
import org.apache.log4j.Logger;
import org.objectweb.proactive.ActiveObjectCreationException;
import org.objectweb.proactive.api.PAActiveObject;
import org.objectweb.proactive.core.node.Node;
import org.objectweb.proactive.core.node.NodeException;
import org.ow2.proactive.scheduler.descriptor.EligibleTaskDescriptor;
import org.ow2.proactive.scheduler.policy.ExtendedSchedulerPolicy;
import org.ow2.proactive.utils.NodeSet;
/**
*
* This Policy is designed to handle preallocation of RAM into a node machine.
* When the task contains the generic information ALLOC_RAM_GIGABYTES,
* this policy will return false if there is not enough RAM available
* or true if there is RAM available (in this last case it will set the ALLOC_RAM_GIGABYTES property at node level to book the RAM in the node machine)
*
* It's important to set the ALLOC_RAM_GIGABYTES task property to 0 in the clean script to release the preallocation. For example for a groovy clean script :
* org.objectweb.proactive.api.PAActiveObject.getNode().setProperty("ALLOC_RAM_GIGABYTES","0");
*
*/
public class RamSchedulingPolicy extends ExtendedSchedulerPolicy {
private static final Logger logger = Logger.getLogger(RamSchedulingPolicy.class);
public static final String RAM_VARIABLE_NAME = "ALLOC_RAM_GIGABYTES";
@Override
public boolean isTaskExecutable(NodeSet selectedNodes, EligibleTaskDescriptor task) {
logger.debug("Selected Nodes: " + selectedNodes);
logger.debug("Analysing task: " + task.getInternal().getName());
String allocRam = task.getInternal().getRuntimeGenericInformation().get(RAM_VARIABLE_NAME);
if (allocRam != null) {
try {
return canRunTaskOnNode(selectedNodes, task, Double.parseDouble(allocRam));
} catch (NumberFormatException nfe) {
logger.error("allocRam : " + allocRam + " is not a number");
throw new RuntimeException(nfe);
}
} else {
return true;
}
}
private boolean canRunTaskOnNode(NodeSet selectedNodes, EligibleTaskDescriptor task, double neededRam) {
Node n = selectedNodes.get(0);
try {
double freeRam = getFreeRamFromNode(n);
logger.debug("Free Ram for node (" + n.getNodeInformation().getName() + ") : " + freeRam +
" , neededRam : " + neededRam);
if (freeRam >= neededRam) {
logger.debug("Task " + task.getInternal().getName() + " can execute on " + n);
n.setProperty(RAM_VARIABLE_NAME, "" + neededRam);
return true;
}
} catch (Exception e) {
logger.error("Error while setting the property " + RAM_VARIABLE_NAME);
throw new RuntimeException(e);
}
return false;
}
private double getFreeRamFromNode(Node n) throws ActiveObjectCreationException, NodeException {
RamCompute ramCompute = PAActiveObject.newActive(RamCompute.class, new Object[] {}, n);
double freeRam = ramCompute.getAvailableRAMInGB();
try {
PAActiveObject.terminateActiveObject(ramCompute, true);
} catch (Exception e) {
logger.warn("Error while terminating Active Object", e);
}
return freeRam;
}
}