2015-07-28 15:41:35 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
package org.gcube.vremanagement.executor.pluginmanager;
|
|
|
|
|
2016-09-22 11:31:05 +02:00
|
|
|
import java.util.Calendar;
|
2015-07-28 15:41:35 +02:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.UUID;
|
|
|
|
|
2017-02-01 17:58:52 +01:00
|
|
|
import org.gcube.accounting.datamodel.UsageRecord.OperationResult;
|
2017-09-13 14:16:02 +02:00
|
|
|
import org.gcube.accounting.datamodel.usagerecords.JobUsageRecord;
|
2017-02-01 17:58:52 +01:00
|
|
|
import org.gcube.accounting.persistence.AccountingPersistence;
|
|
|
|
import org.gcube.accounting.persistence.AccountingPersistenceFactory;
|
2017-09-13 14:16:02 +02:00
|
|
|
import org.gcube.common.authorization.client.Constants;
|
|
|
|
import org.gcube.common.authorization.library.AuthorizationEntry;
|
|
|
|
import org.gcube.common.authorization.library.provider.ClientInfo;
|
2017-05-18 17:33:07 +02:00
|
|
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
2017-02-01 17:58:52 +01:00
|
|
|
import org.gcube.documentstore.exception.InvalidValueException;
|
2017-09-13 14:16:02 +02:00
|
|
|
import org.gcube.smartgears.ContextProvider;
|
2017-02-01 17:58:52 +01:00
|
|
|
import org.gcube.vremanagement.executor.SmartExecutorInitializator;
|
2015-07-28 15:41:35 +02:00
|
|
|
import org.gcube.vremanagement.executor.exception.AlreadyInFinalStateException;
|
2016-09-22 11:31:05 +02:00
|
|
|
import org.gcube.vremanagement.executor.exception.InvalidPluginStateEvolutionException;
|
2015-07-28 15:41:35 +02:00
|
|
|
import org.gcube.vremanagement.executor.plugin.Plugin;
|
|
|
|
import org.gcube.vremanagement.executor.plugin.PluginDeclaration;
|
|
|
|
import org.gcube.vremanagement.executor.plugin.PluginState;
|
2015-10-06 14:32:36 +02:00
|
|
|
import org.gcube.vremanagement.executor.plugin.PluginStateEvolution;
|
2015-07-28 15:41:35 +02:00
|
|
|
import org.gcube.vremanagement.executor.plugin.PluginStateNotification;
|
2017-02-01 17:58:52 +01:00
|
|
|
import org.gcube.vremanagement.executor.plugin.Ref;
|
|
|
|
import org.gcube.vremanagement.executor.plugin.RunOn;
|
|
|
|
import org.gcube.vremanagement.executor.scheduledtask.ScheduledTask;
|
2015-07-28 15:41:35 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
/**
|
2017-02-01 17:01:15 +01:00
|
|
|
* @author Luca Frosini (ISTI - CNR)
|
2015-07-28 15:41:35 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
public class RunnablePlugin<T extends Plugin<? extends PluginDeclaration>> implements Runnable {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Logger
|
|
|
|
*/
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(RunnablePlugin.class);
|
|
|
|
|
|
|
|
protected final T plugin;
|
|
|
|
|
|
|
|
protected final Map<String, Object> inputs;
|
|
|
|
|
|
|
|
protected final UUID uuid;
|
|
|
|
protected final int iterationNumber;
|
|
|
|
protected final List<PluginStateNotification> pluginStateNotifications;
|
|
|
|
|
2017-05-18 17:33:07 +02:00
|
|
|
protected final String token;
|
|
|
|
|
2016-09-22 11:31:05 +02:00
|
|
|
protected PluginStateEvolution actualStateEvolution;
|
2015-07-28 15:41:35 +02:00
|
|
|
|
|
|
|
public RunnablePlugin(T plugin, Map<String, Object> inputs,
|
2017-05-18 17:33:07 +02:00
|
|
|
UUID uuid, int iterationNumber, List<PluginStateNotification> pluginStateNotifications, String token){
|
2015-07-28 15:41:35 +02:00
|
|
|
this.plugin = plugin;
|
2016-09-22 11:31:05 +02:00
|
|
|
this.plugin.setPercentageSetter(new PercentageSetterImpl<T>(this));
|
2015-07-28 15:41:35 +02:00
|
|
|
this.inputs = inputs;
|
|
|
|
this.uuid = uuid;
|
|
|
|
this.iterationNumber = iterationNumber;
|
|
|
|
this.pluginStateNotifications = pluginStateNotifications;
|
2017-05-18 17:33:07 +02:00
|
|
|
this.token = token;
|
|
|
|
try {
|
|
|
|
SecurityTokenProvider.instance.set(token);
|
|
|
|
}catch (Exception e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
2015-07-28 15:41:35 +02:00
|
|
|
try {
|
|
|
|
setState(PluginState.CREATED);
|
2016-09-22 11:31:05 +02:00
|
|
|
} catch (AlreadyInFinalStateException | InvalidPluginStateEvolutionException e) {
|
2017-05-18 17:33:07 +02:00
|
|
|
logger.error(" --- You should not be here. Seem that the {} is suspended before the instance is created. This is really STRANGE.",
|
2015-07-28 15:41:35 +02:00
|
|
|
uuid);
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run(){
|
2017-09-13 14:16:02 +02:00
|
|
|
String pluginName = plugin.getPluginDeclaration().getName();
|
2017-05-18 17:33:07 +02:00
|
|
|
|
2017-04-13 16:38:27 +02:00
|
|
|
logger.info("{} : {} is going to be launched (UUID={}, iterationNumber={}) with the following inputs {}",
|
2017-09-13 14:16:02 +02:00
|
|
|
pluginName, plugin.getPluginDeclaration().getVersion(),
|
2017-04-13 16:38:27 +02:00
|
|
|
uuid, iterationNumber, inputs);
|
2017-09-13 14:16:02 +02:00
|
|
|
|
|
|
|
JobUsageRecord jobUsageRecord = new JobUsageRecord();
|
|
|
|
|
|
|
|
long startTime = actualStateEvolution.getTimestamp();
|
2017-02-01 17:58:52 +01:00
|
|
|
|
2015-07-28 15:41:35 +02:00
|
|
|
try {
|
2017-05-18 17:33:07 +02:00
|
|
|
SmartExecutorInitializator.setContext(token);
|
|
|
|
|
2015-07-28 15:41:35 +02:00
|
|
|
setState(PluginState.RUNNING);
|
2017-02-01 17:58:52 +01:00
|
|
|
|
2017-09-13 14:16:02 +02:00
|
|
|
jobUsageRecord.setJobName(pluginName);
|
2017-02-01 17:58:52 +01:00
|
|
|
|
2017-02-03 16:29:25 +01:00
|
|
|
RunOn runOn = ScheduledTask.generateRunOn();
|
|
|
|
Ref hnRef = runOn.getHostingNode();
|
2017-09-13 14:16:02 +02:00
|
|
|
jobUsageRecord.setHost(hnRef.getAddress());
|
2017-02-01 17:58:52 +01:00
|
|
|
|
2017-09-13 14:16:02 +02:00
|
|
|
|
|
|
|
ClientInfo clientInfo = SmartExecutorInitializator.getClientInfo();
|
|
|
|
String consumerId = clientInfo.getId();
|
|
|
|
jobUsageRecord.setConsumerId(consumerId);
|
|
|
|
|
|
|
|
try {
|
|
|
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
|
|
|
String callerQualifier = authorizationEntry.getQualifier();
|
|
|
|
jobUsageRecord.setCallerQualifier(callerQualifier);
|
|
|
|
}catch (Exception e) {
|
|
|
|
jobUsageRecord.setCallerQualifier("UNKNOWN");
|
2017-02-01 17:58:52 +01:00
|
|
|
}
|
2017-09-13 14:16:02 +02:00
|
|
|
|
|
|
|
jobUsageRecord.setServiceClass(ContextProvider.get().configuration().serviceClass());
|
|
|
|
jobUsageRecord.setServiceName(ContextProvider.get().configuration().name());
|
|
|
|
|
2017-02-01 17:58:52 +01:00
|
|
|
|
2017-02-01 17:01:15 +01:00
|
|
|
this.plugin.setUUID(uuid);
|
|
|
|
this.plugin.setIterationNumber(iterationNumber);
|
|
|
|
this.plugin.launch(inputs);
|
2015-07-28 15:41:35 +02:00
|
|
|
setState(PluginState.DONE);
|
|
|
|
} catch (AlreadyInFinalStateException e1) {
|
|
|
|
return;
|
|
|
|
} catch(Exception e) {
|
|
|
|
logger.trace(String.format("Thread %s failed", this.toString()),e);
|
|
|
|
try {
|
2016-09-22 11:31:05 +02:00
|
|
|
setState(PluginState.FAILED, e);
|
|
|
|
} catch (AlreadyInFinalStateException | InvalidPluginStateEvolutionException e1) {
|
2015-07-28 15:41:35 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
throw new RuntimeException(e);
|
2017-02-01 17:58:52 +01:00
|
|
|
}finally {
|
|
|
|
AccountingPersistence accountingPersistence =
|
|
|
|
AccountingPersistenceFactory.getPersistence();
|
|
|
|
try {
|
2017-09-13 14:16:02 +02:00
|
|
|
long endTime = actualStateEvolution.getTimestamp();
|
|
|
|
long duration = endTime - startTime;
|
|
|
|
jobUsageRecord.setDuration(duration);
|
2017-02-01 17:58:52 +01:00
|
|
|
|
|
|
|
PluginState pluginState = actualStateEvolution.getPluginState();
|
|
|
|
switch (pluginState) {
|
|
|
|
case DONE:
|
2017-09-13 14:16:02 +02:00
|
|
|
jobUsageRecord.setOperationResult(OperationResult.SUCCESS);
|
2017-02-01 17:58:52 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2017-09-13 14:16:02 +02:00
|
|
|
jobUsageRecord.setOperationResult(OperationResult.FAILED);
|
2017-02-01 17:58:52 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-09-13 14:16:02 +02:00
|
|
|
accountingPersistence.account(jobUsageRecord);
|
2017-02-01 17:58:52 +01:00
|
|
|
|
|
|
|
} catch (InvalidValueException e) {
|
2017-09-13 14:16:02 +02:00
|
|
|
logger.error("Unable to account {}", jobUsageRecord, e);
|
2017-02-01 17:58:52 +01:00
|
|
|
}
|
2017-09-13 14:16:02 +02:00
|
|
|
|
2016-09-22 11:31:05 +02:00
|
|
|
}
|
2015-07-28 15:41:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the plugin
|
|
|
|
*/
|
|
|
|
public T getPlugin() {
|
|
|
|
return plugin;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the launchInputs
|
|
|
|
*/
|
|
|
|
public Map<String, Object> getInputs() {
|
|
|
|
return inputs;
|
|
|
|
}
|
|
|
|
|
2016-09-22 11:31:05 +02:00
|
|
|
protected synchronized void setPercentage(Integer percentage) throws AlreadyInFinalStateException, InvalidPluginStateEvolutionException {
|
|
|
|
PluginState pluginState = actualStateEvolution.getPluginState();
|
|
|
|
if(pluginState != PluginState.RUNNING){
|
|
|
|
throw new InvalidPluginStateEvolutionException("Percentage can be set only for runnign plugin");
|
|
|
|
}
|
|
|
|
setState(pluginState, percentage, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setState(PluginState pluginState) throws AlreadyInFinalStateException, InvalidPluginStateEvolutionException {
|
|
|
|
Integer percentage = 0;
|
|
|
|
if(actualStateEvolution!=null){
|
|
|
|
percentage = actualStateEvolution.getPercentage();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pluginState==PluginState.DONE){
|
|
|
|
percentage = 100;
|
|
|
|
}
|
|
|
|
setState(pluginState, percentage, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setState(PluginState pluginState, Exception e) throws AlreadyInFinalStateException, InvalidPluginStateEvolutionException {
|
|
|
|
Integer percentage = 0;
|
|
|
|
if(actualStateEvolution!=null){
|
|
|
|
percentage = actualStateEvolution.getPercentage();
|
|
|
|
}
|
|
|
|
|
|
|
|
Exception exception = null;
|
|
|
|
if(pluginState == PluginState.FAILED){
|
|
|
|
exception = new Exception(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
setState(pluginState, percentage, exception);
|
|
|
|
}
|
2015-07-28 15:41:35 +02:00
|
|
|
/**
|
|
|
|
* It is up to the plugin update the State of the Running Plugin using
|
|
|
|
* this facilities function.
|
|
|
|
* @param pluginState
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
2016-09-22 11:31:05 +02:00
|
|
|
protected void setState(PluginState pluginState, Integer percentage, Exception exception) throws AlreadyInFinalStateException, InvalidPluginStateEvolutionException {
|
|
|
|
long timestamp = Calendar.getInstance().getTimeInMillis();
|
|
|
|
if(actualStateEvolution!=null && actualStateEvolution.getPluginState().isFinalState()){
|
2015-07-28 15:41:35 +02:00
|
|
|
logger.trace("At {} Trying to set {} in {} state, but it was already in the final state {}", timestamp,
|
2016-09-22 11:31:05 +02:00
|
|
|
uuid, pluginState.toString(), actualStateEvolution.toString());
|
2015-07-28 15:41:35 +02:00
|
|
|
throw new AlreadyInFinalStateException();
|
|
|
|
}
|
2016-09-22 11:31:05 +02:00
|
|
|
|
|
|
|
PluginStateEvolution pluginStateEvolution = new PluginStateEvolution(uuid, iterationNumber, timestamp, plugin.getPluginDeclaration(), pluginState, percentage);
|
2015-07-28 15:41:35 +02:00
|
|
|
|
|
|
|
for(PluginStateNotification pluginStateNotification : pluginStateNotifications){
|
|
|
|
String pluginStateNotificationName = pluginStateNotification.getClass().getSimpleName();
|
|
|
|
try {
|
2016-09-22 11:31:05 +02:00
|
|
|
logger.debug("Notifing Plugin State Evolution {} to {}.", pluginStateEvolution, pluginStateNotificationName);
|
|
|
|
pluginStateNotification.pluginStateEvolution(pluginStateEvolution, exception);
|
2015-07-28 15:41:35 +02:00
|
|
|
} catch(Exception e) {
|
2016-09-22 11:31:05 +02:00
|
|
|
logger.error("Unable to Notify Plugin State Evolution {} to {}.",
|
2015-10-06 14:32:36 +02:00
|
|
|
pluginStateEvolution, pluginStateNotificationName);
|
2015-07-28 15:41:35 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-22 11:31:05 +02:00
|
|
|
actualStateEvolution = pluginStateEvolution;
|
2015-07-28 15:41:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString(){
|
|
|
|
return String.format("UUID : %s, Iteration : %d, Plugin : %s",
|
|
|
|
uuid.toString(), iterationNumber,
|
|
|
|
plugin.getPluginDeclaration().getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-10-27 14:07:42 +02:00
|
|
|
* Stop the Plugin setting state to {@link PluginState#STOPPED}
|
2015-07-28 15:41:35 +02:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public void stop() throws Exception {
|
|
|
|
try{
|
|
|
|
setState(PluginState.STOPPED);
|
|
|
|
plugin.stop();
|
|
|
|
}catch(AlreadyInFinalStateException e){}
|
|
|
|
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|