304 lines
10 KiB
Java
304 lines
10 KiB
Java
package org.gcube.vremanagement.resourcemanager.impl.deployment;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import org.apache.axis.message.addressing.EndpointReferenceType;
|
|
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
|
import org.gcube.common.core.contexts.GHNContext;
|
|
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
|
import org.gcube.common.core.informationsystem.client.ISClient;
|
|
import org.gcube.common.core.informationsystem.client.queries.GCUBEGHNQuery;
|
|
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
|
import org.gcube.common.core.resources.GCUBERunningInstance;
|
|
import org.gcube.common.core.scope.GCUBEScope;
|
|
import org.gcube.common.core.utils.logging.GCUBELog;
|
|
import org.gcube.common.vremanagement.deployer.stubs.common.PackageInfo;
|
|
import org.gcube.common.vremanagement.deployer.stubs.deployer.DeployParameters;
|
|
import org.gcube.common.vremanagement.deployer.stubs.deployer.DeployerPortType;
|
|
import org.gcube.common.vremanagement.deployer.stubs.deployer.UndeployParameters;
|
|
import org.gcube.common.vremanagement.deployer.stubs.deployer.service.DeployerServiceAddressingLocator;
|
|
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
|
import org.gcube.vremanagement.resourcemanager.impl.contexts.StatefulPortTypeContext;
|
|
|
|
/**
|
|
* A target node for deployment and undeployment operations
|
|
*
|
|
* @author Manuele Simi (ISTI-CNR)
|
|
*
|
|
*/
|
|
public class VirtualNode {
|
|
|
|
/** Object logger */
|
|
protected final GCUBELog logger=new GCUBELog(this);
|
|
|
|
/**the callback identifier to send to the Deployer*/
|
|
private String callbackID;
|
|
|
|
private String ghnID = "";
|
|
|
|
private GCUBEScope scope = null;
|
|
|
|
private boolean isWorking = false;
|
|
|
|
private Set<PackageInfo> packagesToAdd = new HashSet<PackageInfo>();
|
|
|
|
private Set<PackageInfo> packagesToRemove = new HashSet<PackageInfo>();
|
|
|
|
private long lastActivity;
|
|
|
|
//here only for backward compatibility (deserialization will fail)
|
|
private String name = "";
|
|
|
|
//if we do not receive a deployment session from the node after one hour, we assume that the node is not working anymore
|
|
private static final long MAX_ACTIVITY = 3600 * 1000; //1h in milliseconds
|
|
|
|
protected VirtualNode(String ID, GCUBEScope scope) throws NoGHNFoundException {
|
|
this.ghnID = ID;
|
|
this.scope = scope;
|
|
}
|
|
|
|
public void setCallbackID(String id) {
|
|
this.callbackID = id;
|
|
}
|
|
|
|
public String detectName() throws NoGHNFoundException {
|
|
logger.debug("Detecting name for " + this.ghnID);
|
|
if (GHNContext.getContext().getGHNID().compareToIgnoreCase(this.ghnID) == 0)
|
|
throw new NoGHNFoundException ("cannot deploy on the same GHN (ghnID=" + this.ghnID + ") where the Resource Manager is deployed");
|
|
try {
|
|
ISClient client = GHNContext.getImplementation(ISClient.class);
|
|
GCUBEGHNQuery query = client.getQuery(GCUBEGHNQuery.class);
|
|
query.addAtomicConditions(new AtomicCondition("/ID/text()", this.ghnID));
|
|
return client.execute(query, this.scope).get(0).getNodeDescription().getName();
|
|
} catch (Exception e) {
|
|
logger.error("unable to find the target GHN (ghnID=" + this.ghnID + ")", e);
|
|
throw new NoGHNFoundException ("unable to find the target GHN (ghnID=" + this.ghnID + ")");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets the packages to remove in the next {@link #deploy()} invocation
|
|
*
|
|
* @param packages the list of packagesT to add
|
|
*/
|
|
public synchronized void setPackagesToAdd(Set<PackageInfo> packages) {
|
|
//check if there is a node with all the packagesToAdd already scheduled to be deployed
|
|
//if so, the service will be already activated there, therefore there is nothing to do
|
|
if (this.hasPackages(packages))
|
|
return;
|
|
this.packagesToAdd.addAll(packages);
|
|
}
|
|
|
|
/**
|
|
* Gets the packagesToAdd available on this node
|
|
*
|
|
* @return the packagesToAdd
|
|
*/
|
|
protected Set<PackageInfo> getPackages() {
|
|
return this.packagesToAdd;
|
|
}
|
|
|
|
/**
|
|
* Checks if a list of packagesToAdd is already on this node
|
|
*
|
|
* @param packagesToAdd the list of packagesToAdd to check
|
|
* @return true if all the packagesToAdd are already on this node, false otherwise
|
|
*/
|
|
protected boolean hasPackages(Set<PackageInfo> packages) {
|
|
|
|
if (packages.size() == 0)
|
|
return false;
|
|
if (this.packagesToAdd.size() == 0)
|
|
return false;
|
|
input: for (PackageInfo inputPackage : packages) {
|
|
for (PackageInfo nodePackage : this.packagesToAdd) {
|
|
if ( (inputPackage.getServiceClass().compareToIgnoreCase(nodePackage.getServiceClass())==0) &&
|
|
(inputPackage.getServiceName().compareToIgnoreCase(nodePackage.getServiceName())==0) &&
|
|
(inputPackage.getServiceVersion().compareToIgnoreCase(nodePackage.getServiceVersion())==0) &&
|
|
(inputPackage.getName().compareToIgnoreCase(nodePackage.getName())==0) &&
|
|
(inputPackage.getVersion().compareToIgnoreCase(nodePackage.getVersion())==0))
|
|
continue input;
|
|
|
|
}
|
|
return false; //if we arrive here, no matching package has been found
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Gets the node ghnID
|
|
*
|
|
* @return the node ghnID
|
|
*/
|
|
public String getID() {
|
|
return this.ghnID;
|
|
}
|
|
|
|
/**
|
|
* Sends a request to the physical node to deploy the active list of packages to add
|
|
*
|
|
* @throws Exception if the deployment fails
|
|
*/
|
|
public synchronized void deploy(GCUBEScope scope) throws Exception {
|
|
if (packagesToAdd.size() == 0)
|
|
return;
|
|
|
|
if (isWorking && ((System.currentTimeMillis() -this.lastActivity) < MAX_ACTIVITY)) {
|
|
logger.warn("Can't deploy on " + this +", the gHN is already working");
|
|
return;
|
|
}
|
|
|
|
EndpointReferenceType callbackEPR = ServiceContext.getContext().getInstance().getAccessPoint().getEndpoint(StatefulPortTypeContext.getContext().getJNDIName());
|
|
DeployParameters param = new DeployParameters();
|
|
param.set_package(this.packagesToAdd.toArray(new PackageInfo[0]));
|
|
param.setTargetScope(new String[] {scope.toString()});
|
|
param.setCallbackID(callbackID);
|
|
param.setEndpointReference(callbackEPR);
|
|
EndpointReferenceType nodeEPR = this.loadDeployer(this.ghnID);
|
|
logger.trace("Deploying on " + nodeEPR.toString());
|
|
DeployerPortType pt = GCUBERemotePortTypeContext.getProxy(new DeployerServiceAddressingLocator().getDeployerPortTypePort(nodeEPR),
|
|
scope, ServiceContext.getContext());
|
|
pt.deploy(param);
|
|
this.packagesToAdd.clear();
|
|
isWorking = true;//this will prevent further requests to the ghn until the deployment session is received back
|
|
this.lastActivity = System.currentTimeMillis();
|
|
}
|
|
|
|
/**
|
|
* Undeploys the packages from the node
|
|
* @param scope the scope to use for the undeployment
|
|
*
|
|
* @throws Exception if the operation fails
|
|
*/
|
|
public synchronized void undeploy(GCUBEScope scope) throws Exception {
|
|
if (this.packagesToRemove.size() == 0)
|
|
return;
|
|
|
|
if (isWorking && (this.lastActivity - System.currentTimeMillis() < MAX_ACTIVITY)) {
|
|
logger.warn("Can't undeploy from " + this +", the gHN is already working");
|
|
return;
|
|
}
|
|
|
|
EndpointReferenceType callbackEPR = ServiceContext.getContext().getInstance().getAccessPoint().getEndpoint(StatefulPortTypeContext.getContext().getJNDIName());
|
|
UndeployParameters params = new UndeployParameters();
|
|
params.set_package(this.packagesToRemove.toArray(new PackageInfo[0]));
|
|
params.setTargetScope(new String[] {scope.toString()});
|
|
params.setCallbackID(callbackID);
|
|
params.setEndpointReference(callbackEPR);
|
|
EndpointReferenceType nodeEPR = this.loadDeployer(this.ghnID);
|
|
logger.trace("Undeploying from " + nodeEPR.toString() + " in scope " + scope);
|
|
DeployerPortType pt = GCUBERemotePortTypeContext.getProxy(new DeployerServiceAddressingLocator().getDeployerPortTypePort(nodeEPR),
|
|
scope, ServiceContext.getContext());
|
|
pt.undeploy(params);
|
|
this.packagesToRemove.clear();
|
|
isWorking = true;//this will prevent further requests to the ghn until the deployment session is received back
|
|
this.lastActivity = System.currentTimeMillis();
|
|
}
|
|
|
|
/** NoGHNFoundException exception */
|
|
public static class NoGHNFoundException extends Exception {
|
|
private static final long serialVersionUID = 1L;
|
|
public NoGHNFoundException(String message) {super(message);}
|
|
}
|
|
/**
|
|
* Marks the node as not working node
|
|
* (usually called when a closed {@link DeployerReport} is received from the node)
|
|
*/
|
|
public void isNotWorking() {
|
|
this.isWorking = false;
|
|
|
|
}
|
|
|
|
/**
|
|
* Sets the packages to remove in the nect {@link #undeploy()} invocation
|
|
* @param packages the packages to remove from the node
|
|
*/
|
|
public synchronized void setPackagesToRemove(Set<PackageInfo> packages) {
|
|
this.packagesToRemove.addAll(packages);
|
|
}
|
|
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#toString()
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
return "VirtualNode [ghnID=" + ghnID + ", scope="+ scope + "]";
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#hashCode()
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
final int prime = 31;
|
|
int result = 1;
|
|
result = prime * result + ((ghnID == null) ? 0 : ghnID.hashCode());
|
|
return result;
|
|
}
|
|
|
|
/* (non-Javadoc)
|
|
* @see java.lang.Object#equals(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj)
|
|
return true;
|
|
if (obj == null)
|
|
return false;
|
|
if (getClass() != obj.getClass())
|
|
return false;
|
|
VirtualNode other = (VirtualNode) obj;
|
|
if (ghnID == null) {
|
|
if (other.ghnID != null)
|
|
return false;
|
|
} else if (!ghnID.equals(other.ghnID))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Assigns a working scope to the node
|
|
* @param scope the scope to set
|
|
*/
|
|
public void setWorkingScope(GCUBEScope scope) {
|
|
this.scope = scope;
|
|
}
|
|
|
|
/**
|
|
* Gets the packages scheduled for the next deployment on this node
|
|
* @return the set of packages
|
|
*/
|
|
public Set<PackageInfo> getScheduledPackages() {
|
|
return this.packagesToAdd;
|
|
}
|
|
|
|
/**
|
|
* Gets the current scope used on this node
|
|
* @return the current scope
|
|
*/
|
|
public GCUBEScope getWorkingScope() {
|
|
return this.scope;
|
|
}
|
|
|
|
|
|
/**
|
|
* Looks for the Deployer's endpoint to contact
|
|
* @param id the identifier of the gHN
|
|
* @return the endpoint reference of Deployer's portType to contact
|
|
* @throws Exception if the search fails
|
|
*/
|
|
private EndpointReferenceType loadDeployer(String id) throws Exception {
|
|
ISClient client = GHNContext.getImplementation(ISClient.class);
|
|
GCUBERIQuery riquery = client.getQuery(GCUBERIQuery.class);
|
|
riquery.addAtomicConditions(new AtomicCondition("//GHN/@UniqueID", id),
|
|
new AtomicCondition("//ServiceClass", "VREManagement"),
|
|
new AtomicCondition("//ServiceName", "Deployer"));
|
|
List<GCUBERunningInstance> results = client.execute(riquery,ServiceContext.getContext().getScope());
|
|
return results.get(0).getAccessPoint().getEndpoint("gcube/common/vremanagement/Deployer");
|
|
}
|
|
}
|