/*
* 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.resourcemanager.rmnode;
import java.io.IOException;
import java.io.Serializable;
import java.security.Permission;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import org.objectweb.proactive.core.descriptor.data.VirtualNode;
import org.objectweb.proactive.core.node.Node;
import org.objectweb.proactive.core.node.NodeException;
import org.ow2.proactive.authentication.principals.UserNamePrincipal;
import org.ow2.proactive.jmx.naming.JMXTransportProtocol;
import org.ow2.proactive.permissions.PrincipalPermission;
import org.ow2.proactive.resourcemanager.authentication.Client;
import org.ow2.proactive.resourcemanager.common.NodeState;
import org.ow2.proactive.resourcemanager.nodesource.NodeSource;
import org.ow2.proactive.scripting.Script;
import org.ow2.proactive.scripting.ScriptHandler;
import org.ow2.proactive.scripting.ScriptLoader;
import org.ow2.proactive.scripting.ScriptResult;
import org.ow2.proactive.scripting.SelectionScript;
/**
* Implementation of the RMNode Interface.
* An RMNode is a ProActive node able to execute schedulers tasks.
* So an RMNode is a representation of a ProActive node object with its associated {@link NodeSource},
* and its state in the Resource Manager :<BR>
* -free : node is ready to perform a task.<BR>
* -busy : node is executing a task.<BR>
* -to be released : node is busy and have to be removed at the end of the its current task.<BR>
* -down : node is broken, and not anymore able to perform tasks.<BR><BR>
*
* Resource Manager can select nodes that verify criteria. this selection is implemented with
* {@link SelectionScript} objects. Each node memorize results of executed scripts, in order to
* answer faster to a selection already asked.
*
* @see NodeSource
* @see SelectionScript
*
* @author The ProActive Team
* @since ProActive Scheduling 0.9
*/
public class RMNodeImpl extends AbstractRMNode {
private final static Logger logger = Logger.getLogger(RMNodeImpl.class);
/** HashMap associates a selection Script to its result on the node */
private HashMap<SelectionScript, Integer> scriptStatus;
/** ProActive Node Object of the RMNode */
private Node node;
/** {@link VirtualNode} name of the node */
private String vnodeName = "";
/** Host name of the node */
private String hostName;
/** JVM name of the node */
private String jvmName;
/** Script handled, manage scripts launching and results recovering */
private ScriptHandler handler = null;
/** client taken the node for computations */
private Client owner;
/** Node access permission*/
private Permission nodeAccessPermission;
private String[] jmxUrls;
/** true if node is protected with token */
private boolean protectedByToken = false;
/**
* Constructs a new instance. Initial state is set to {@link NodeState#FREE}.
*
* @param node ProActive node deployed.
* @param nodeSource {@link NodeSource} Stub of NodeSource that handles the Node.
* @param provider the client who deployed the Node.
* @param nodeAccessPermission the permissions associated with the Node.
*/
public RMNodeImpl(Node node, NodeSource nodeSource, Client provider, Permission nodeAccessPermission) {
super(nodeSource, node.getNodeInformation().getName(), node.getNodeInformation().getURL(), provider);
changeState(NodeState.FREE);
this.hostName = node.getNodeInformation().getVMInformation().getHostName();
this.jmxUrls = new String[JMXTransportProtocol.values().length];
this.jvmName = node.getProActiveRuntime().getURL();
this.node = node;
this.nodeAccessPermission = nodeAccessPermission;
this.scriptStatus = new HashMap<>();
}
/**
* @see org.ow2.proactive.resourcemanager.rmnode.RMNode#getNode()
*/
@Override
public Node getNode() {
return this.node;
}
/**
* Returns the Virtual node name of the RMNode.
* @return the Virtual node name of the RMNode.
*/
@Override
public String getVNodeName() {
return this.vnodeName;
}
/**
* Returns the host name of the RMNode.
* @return the host name of the RMNode.
*/
@Override
public String getHostName() {
return this.hostName;
}
/**
* Returns the java virtual machine name of the RMNode.
* @return the java virtual machine name of the RMNode.
*/
@Override
public String getDescriptorVMName() {
return this.jvmName;
}
/**
* Changes the state of this node to {@link NodeState#BUSY}.
*/
@Override
public void setBusy(Client owner) {
changeState(NodeState.BUSY);
this.owner = owner;
}
/**
* Changes the state of this node to {@link NodeState#FREE}.
*/
@Override
public void setFree() {
changeState(NodeState.FREE);
this.owner = null;
}
/**
* Changes the state of this node to {@link NodeState#CONFIGURING}
*/
@Override
public void setConfiguring(Client owner) {
if (!this.isDown()) {
changeState(NodeState.CONFIGURING);
}
}
/**
* Changes the state of this node to {@link NodeState#DOWN}.
*/
@Override
public void setDown() {
changeState(NodeState.DOWN);
}
/**
* Changes the state of this node to {@link NodeState#TO_BE_REMOVED}.
*/
@Override
public void setToRemove() {
changeState(NodeState.TO_BE_REMOVED);
}
/**
* @return true if the node is free, false otherwise.
*/
@Override
public boolean isFree() {
return this.state == NodeState.FREE;
}
/**
* @return true if the node is busy, false otherwise.
*/
@Override
public boolean isBusy() {
return this.state == NodeState.BUSY;
}
/**
* @return true if the node is down, false otherwise.
*/
@Override
public boolean isDown() {
return this.state == NodeState.DOWN;
}
/**
* @return true if the node is 'to be released', false otherwise.
*/
@Override
public boolean isToRemove() {
return this.state == NodeState.TO_BE_REMOVED;
}
/**
* @return true if the node is 'configuring', false otherwise.
*/
@Override
public boolean isConfiguring() {
return this.state == NodeState.CONFIGURING;
}
/**
* @return a String showing information about the node.
*/
@Override
public String getNodeInfo() {
String newLine = System.lineSeparator();
String nodeInfo = "Node " + nodeName + newLine;
nodeInfo += "URL: " + getNodeURL() + newLine;
nodeInfo += "Node source: " + nodeSourceName + newLine;
nodeInfo += "Provider: " + provider.getName() + newLine;
nodeInfo += "Used by: " + (owner == null ? "nobody" : owner.getName()) + newLine;
nodeInfo += "State: " + state + newLine;
nodeInfo += getLockStatus();
nodeInfo += "JMX RMI: " + getJMXUrl(JMXTransportProtocol.RMI) + newLine;
nodeInfo += "JMX RO: " + getJMXUrl(JMXTransportProtocol.RO) + newLine;
return nodeInfo;
}
private void initHandler() throws NodeException {
if (this.handler == null) {
try {
this.handler = ScriptLoader.createHandler(this.node);
} catch (Exception e) {
throw new NodeException("Unable to create Script Handler on node ", e);
}
}
}
/**
* Returns the ProActive stub on the remote script handler.
* @return the ProActive stub on the script handler.
*/
public ScriptHandler getHandler() throws NodeException {
this.initHandler();
return this.handler;
}
/**
* Execute a selection Script in order to test the Node.
* If no script handler is defined, create one, and execute the script.
* @param script Selection script to execute
* @param bindings bindings to use to execute the selection scripts
* @return Result of the test.
*/
@Override
public <T> ScriptResult<T> executeScript(Script<T> script, Map<String, Serializable> bindings) {
try {
this.initHandler();
} catch (NodeException e) {
return new ScriptResult<>(e);
}
if (bindings != null) {
for (String key : bindings.keySet()) {
this.handler.addBinding(key, bindings.get(key));
}
}
return this.handler.handle(script);
}
/**
* Clean the node.
* kill all active objects on the node.
* @throws NodeException
*/
@Override
public synchronized void clean() throws NodeException {
handler = null;
try {
logger.debug(getNodeURL() + " : cleaning");
node.killAllActiveObjects();
} catch (IOException e) {
throw new NodeException("Node is down");
}
}
/**
* Gives the HashMap of all scripts tested with corresponding results.
* @return the HashMap of all scripts tested with corresponding results.
*/
@Override
public HashMap<SelectionScript, Integer> getScriptStatus() {
return this.scriptStatus;
}
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
* @param rmnode the RMNode object to compare
* @return an integer
*/
@Override
public int compareTo(RMNode rmnode) {
int vNodeNameComparison = this.getVNodeName().compareTo(rmnode.getVNodeName());
if (vNodeNameComparison == 0) {
int hostNameComparison = this.getHostName().compareTo(rmnode.getHostName());
if (hostNameComparison == 0) {
int descriptorVmNameComparison = this.getDescriptorVMName().compareTo(rmnode.getDescriptorVMName());
if (descriptorVmNameComparison == 0) {
return this.getNodeURL().compareTo(rmnode.getNodeURL());
} else {
return descriptorVmNameComparison;
}
} else {
return hostNameComparison;
}
} else {
return vNodeNameComparison;
}
}
public void setState(NodeState nodeState) {
this.state = nodeState;
}
/**
* {@inheritDoc}
*/
@Override
public Client getOwner() {
return owner;
}
/**
* {@inheritDoc}
*/
@Override
public Permission getUserPermission() {
return nodeAccessPermission;
}
/**
* {@inheritDoc}
*/
@Override
public Permission getAdminPermission() {
return new PrincipalPermission(provider.getName(),
provider.getSubject().getPrincipals(UserNamePrincipal.class));
}
/**
* {@inheritDoc}
*/
@Override
public void setJMXUrl(JMXTransportProtocol protocol, String address) {
jmxUrls[protocol.ordinal()] = address;
}
@Override
public String getJMXUrl(JMXTransportProtocol protocol) {
return jmxUrls[protocol.ordinal()];
}
@Override
public boolean isProtectedByToken() {
return protectedByToken;
}
public void setProtectedByToken(boolean protectedByToken) {
this.protectedByToken = protectedByToken;
}
@Override
public boolean isDeploying() {
return false;
}
}