2018-01-10 17:33:26 +01:00
|
|
|
package org.gcube.vremanagement.executor.rest;
|
|
|
|
|
|
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
import javax.ws.rs.Consumes;
|
|
|
|
import javax.ws.rs.DELETE;
|
|
|
|
import javax.ws.rs.GET;
|
2019-02-25 18:28:49 +01:00
|
|
|
import javax.ws.rs.HttpMethod;
|
2018-01-10 17:33:26 +01:00
|
|
|
import javax.ws.rs.POST;
|
|
|
|
import javax.ws.rs.Path;
|
|
|
|
import javax.ws.rs.PathParam;
|
|
|
|
import javax.ws.rs.Produces;
|
|
|
|
import javax.ws.rs.QueryParam;
|
2019-08-02 17:50:39 +02:00
|
|
|
import javax.ws.rs.core.Context;
|
2018-01-10 17:33:26 +01:00
|
|
|
import javax.ws.rs.core.MediaType;
|
2019-08-02 17:50:39 +02:00
|
|
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
|
|
|
import javax.ws.rs.core.UriInfo;
|
2018-01-10 17:33:26 +01:00
|
|
|
|
2018-02-15 17:00:01 +01:00
|
|
|
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
|
2018-01-10 17:33:26 +01:00
|
|
|
import org.gcube.vremanagement.executor.ResourceInitializer;
|
2019-08-02 17:50:39 +02:00
|
|
|
import org.gcube.vremanagement.executor.annotation.PURGE;
|
2018-01-10 17:33:26 +01:00
|
|
|
import org.gcube.vremanagement.executor.api.rest.RestConstants;
|
2019-08-02 18:29:38 +02:00
|
|
|
import org.gcube.vremanagement.executor.api.rest.SmartExecutor;
|
2018-01-10 17:33:26 +01:00
|
|
|
import org.gcube.vremanagement.executor.api.types.LaunchParameter;
|
|
|
|
import org.gcube.vremanagement.executor.exception.ExecutorException;
|
|
|
|
import org.gcube.vremanagement.executor.exception.InputsNullException;
|
|
|
|
import org.gcube.vremanagement.executor.exception.InvalidInputsException;
|
|
|
|
import org.gcube.vremanagement.executor.exception.SchedulePersistenceException;
|
|
|
|
import org.gcube.vremanagement.executor.exception.SchedulerNotFoundException;
|
|
|
|
import org.gcube.vremanagement.executor.json.SEMapper;
|
|
|
|
import org.gcube.vremanagement.executor.persistence.SmartExecutorPersistenceConnector;
|
|
|
|
import org.gcube.vremanagement.executor.persistence.SmartExecutorPersistenceFactory;
|
|
|
|
import org.gcube.vremanagement.executor.plugin.PluginStateEvolution;
|
|
|
|
import org.gcube.vremanagement.executor.scheduler.SmartExecutorScheduler;
|
|
|
|
import org.gcube.vremanagement.executor.scheduler.SmartExecutorSchedulerFactory;
|
|
|
|
import org.quartz.SchedulerException;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
|
|
|
|
|
@Path(RestConstants.PLUGINS_PATH_PART)
|
2019-08-02 18:29:38 +02:00
|
|
|
public class RestSmartExecutor implements SmartExecutor {
|
2018-01-10 17:33:26 +01:00
|
|
|
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(RestSmartExecutor.class);
|
|
|
|
|
2019-08-02 17:50:39 +02:00
|
|
|
private static final String UUID_PATH_PARAM = "UUID";
|
|
|
|
private static final String PLUGIN_NAME_PATH_PARAM = "NAME";
|
|
|
|
|
|
|
|
protected static final String LOCATION_HEADER = "Location";
|
|
|
|
|
|
|
|
@Context
|
|
|
|
protected UriInfo uriInfo;
|
|
|
|
|
|
|
|
protected void setCalledMethod(String method) {
|
|
|
|
logger.trace("Going to set calledMethod as {}", method);
|
|
|
|
CalledMethodProvider.instance.set(method);
|
|
|
|
logger.info("{}", uriInfo.getAbsolutePath());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected ResponseBuilder addLocation(ResponseBuilder responseBuilder, String id) {
|
|
|
|
return responseBuilder.header(LOCATION_HEADER,
|
|
|
|
String.format("%s/%s", uriInfo.getAbsolutePath().toString(), id));
|
|
|
|
}
|
2018-01-10 17:33:26 +01:00
|
|
|
|
2019-08-01 16:30:16 +02:00
|
|
|
@GET
|
|
|
|
@Path("")
|
|
|
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
|
|
|
public String getAvailablePlugins() throws ExecutorException {
|
2019-08-02 17:50:39 +02:00
|
|
|
setCalledMethod(HttpMethod.GET.getClass().getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART);
|
|
|
|
return "[]";
|
|
|
|
}
|
|
|
|
|
|
|
|
@GET
|
|
|
|
@Path("/{" + PLUGIN_NAME_PATH_PARAM + "}/" + RestConstants.EXECUTIONS_PATH_PART)
|
|
|
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
|
|
|
public String getLaunches(@PathParam(PLUGIN_NAME_PATH_PARAM) String pluginName) throws ExecutorException {
|
2019-08-02 17:50:39 +02:00
|
|
|
setCalledMethod(HttpMethod.GET.getClass().getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART + "/"
|
|
|
|
+ pluginName + "/" + RestConstants.EXECUTIONS_PATH_PART);
|
2019-08-01 16:30:16 +02:00
|
|
|
return "[]";
|
|
|
|
}
|
|
|
|
|
2018-01-10 17:33:26 +01:00
|
|
|
@POST
|
2019-08-02 17:50:39 +02:00
|
|
|
@Path("/{" + PLUGIN_NAME_PATH_PARAM + "}/" + RestConstants.EXECUTIONS_PATH_PART)
|
2018-01-10 17:33:26 +01:00
|
|
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
|
|
|
@Produces(MediaType.TEXT_PLAIN)
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
2018-01-10 17:33:26 +01:00
|
|
|
public String launch(@PathParam(PLUGIN_NAME_PATH_PARAM) String pluginName, String launchParameterString)
|
|
|
|
throws ExecutorException {
|
2019-08-02 17:50:39 +02:00
|
|
|
setCalledMethod(HttpMethod.POST.getClass().getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART + "/"
|
|
|
|
+ pluginName + "/" + RestConstants.EXECUTIONS_PATH_PART);
|
2018-02-15 17:00:01 +01:00
|
|
|
|
2018-01-10 17:33:26 +01:00
|
|
|
try {
|
|
|
|
logger.info("Requested to launch {} ({})", pluginName, launchParameterString);
|
|
|
|
LaunchParameter launchParameter = SEMapper.unmarshal(LaunchParameter.class, launchParameterString);
|
|
|
|
if(pluginName == null) {
|
|
|
|
String error = String.format("Plugin Name provided in the URL (%s) cannot be null", pluginName);
|
|
|
|
logger.error(error);
|
|
|
|
throw new InputsNullException(error);
|
|
|
|
}
|
|
|
|
if(pluginName.compareTo(launchParameter.getPluginName()) != 0) {
|
|
|
|
String error = String.format(
|
|
|
|
"Plugin Name provided in the URL (%s) does not match with the one provided in %s (%s)",
|
|
|
|
pluginName, LaunchParameter.class.getSimpleName(), launchParameter.getPluginName());
|
|
|
|
logger.error(error);
|
|
|
|
throw new InvalidInputsException(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
SmartExecutorScheduler smartExecutorScheduler = SmartExecutorSchedulerFactory.getSmartExecutorScheduler();
|
|
|
|
UUID uuid = smartExecutorScheduler.schedule(launchParameter, null);
|
|
|
|
|
|
|
|
logger.info("{} ({}) has been lauched with uuid {}", pluginName, launchParameterString, uuid);
|
|
|
|
|
|
|
|
return uuid.toString();
|
|
|
|
} catch(ExecutorException e) {
|
|
|
|
throw e;
|
|
|
|
} catch(Exception e) {
|
|
|
|
throw new ExecutorException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@GET
|
2019-08-02 17:50:39 +02:00
|
|
|
@Path("/{" + PLUGIN_NAME_PATH_PARAM + "}/" + RestConstants.EXECUTIONS_PATH_PART + "/" + "{" + UUID_PATH_PARAM + "}")
|
2018-01-10 17:33:26 +01:00
|
|
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
2018-01-10 17:33:26 +01:00
|
|
|
public String getPluginStateEvolution(@PathParam(PLUGIN_NAME_PATH_PARAM) String pluginName,
|
|
|
|
@PathParam(UUID_PATH_PARAM) String executionIdentifier,
|
2019-08-02 17:50:39 +02:00
|
|
|
@QueryParam(RestConstants.ITERATION_PARAM) Integer iteration) throws ExecutorException {
|
2018-02-15 17:00:01 +01:00
|
|
|
|
2019-08-02 17:50:39 +02:00
|
|
|
setCalledMethod(HttpMethod.GET.getClass().getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART + "/"
|
|
|
|
+ pluginName + "/" + RestConstants.EXECUTIONS_PATH_PART + "/{" + UUID_PATH_PARAM + "}");
|
2018-02-15 17:00:01 +01:00
|
|
|
|
2018-01-10 17:33:26 +01:00
|
|
|
PluginStateEvolution pluginStateEvolution = null;
|
|
|
|
try {
|
2018-02-15 17:00:01 +01:00
|
|
|
SmartExecutorPersistenceConnector persistenceConnector = SmartExecutorPersistenceFactory
|
|
|
|
.getPersistenceConnector();
|
|
|
|
pluginStateEvolution = persistenceConnector.getPluginInstanceState(UUID.fromString(executionIdentifier),
|
2019-08-02 17:50:39 +02:00
|
|
|
iteration);
|
2018-02-15 17:00:01 +01:00
|
|
|
logger.info("{} for {} (iteration n. {}) is {}", PluginStateEvolution.class.getSimpleName(),
|
2019-08-02 17:50:39 +02:00
|
|
|
executionIdentifier, iteration, pluginStateEvolution);
|
2018-01-10 17:33:26 +01:00
|
|
|
} catch(ExecutorException e) {
|
|
|
|
throw e;
|
|
|
|
} catch(Exception e) {
|
|
|
|
throw new ExecutorException(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pluginName.compareTo(pluginStateEvolution.getPluginDeclaration().getName()) != 0) {
|
|
|
|
String error = String.format(
|
|
|
|
"Plugin Name provided in the URL (%s) does not match with the one got from %s (%s)", pluginName,
|
|
|
|
PluginStateEvolution.class.getSimpleName(), pluginStateEvolution.getPluginDeclaration().getName());
|
|
|
|
throw new InvalidInputsException(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
return SEMapper.marshal(pluginStateEvolution);
|
|
|
|
} catch(JsonProcessingException e) {
|
|
|
|
throw new ExecutorException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@DELETE
|
2019-08-02 17:50:39 +02:00
|
|
|
@Path("/{" + PLUGIN_NAME_PATH_PARAM + "}/" + RestConstants.EXECUTIONS_PATH_PART + "/" + "{" + UUID_PATH_PARAM + "}")
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
2018-01-10 17:33:26 +01:00
|
|
|
public boolean delete(@PathParam(PLUGIN_NAME_PATH_PARAM) String pluginName,
|
|
|
|
@PathParam(UUID_PATH_PARAM) String executionIdentifier,
|
2019-08-02 17:50:39 +02:00
|
|
|
@QueryParam(RestConstants.UNSCHEDULE_PARAM) Boolean unschedule) throws ExecutorException {
|
2018-02-15 17:00:01 +01:00
|
|
|
|
2019-08-02 17:50:39 +02:00
|
|
|
if(unschedule) {
|
|
|
|
setCalledMethod(PURGE.class.getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART + "/" + pluginName
|
|
|
|
+ "/" + RestConstants.EXECUTIONS_PATH_PART + "/{" + UUID_PATH_PARAM + "}");
|
|
|
|
} else {
|
|
|
|
setCalledMethod(HttpMethod.DELETE.getClass().getSimpleName() + " /" + RestConstants.PLUGINS_PATH_PART + "/"
|
|
|
|
+ pluginName + "/" + RestConstants.EXECUTIONS_PATH_PART + "/{" + UUID_PATH_PARAM + "}");
|
|
|
|
}
|
2018-01-10 17:33:26 +01:00
|
|
|
try {
|
2019-08-02 17:50:39 +02:00
|
|
|
if(unschedule == null) {
|
|
|
|
unschedule = false;
|
2018-01-10 17:33:26 +01:00
|
|
|
}
|
|
|
|
|
2019-08-02 17:50:39 +02:00
|
|
|
logger.info("Requested to delete for {} with UUID {}{}", pluginName, executionIdentifier,
|
|
|
|
unschedule ? "globally" : "");
|
2018-01-10 17:33:26 +01:00
|
|
|
|
|
|
|
boolean currentStopped = true;
|
|
|
|
try {
|
2018-02-15 17:00:01 +01:00
|
|
|
SmartExecutorScheduler smartExecutorScheduler = SmartExecutorSchedulerFactory
|
|
|
|
.getSmartExecutorScheduler();
|
|
|
|
UUID uuid = UUID.fromString(executionIdentifier);
|
2019-08-02 17:50:39 +02:00
|
|
|
smartExecutorScheduler.stop(uuid, unschedule);
|
2018-02-15 17:00:01 +01:00
|
|
|
} catch(SchedulerNotFoundException e) {
|
2018-01-10 17:33:26 +01:00
|
|
|
// currentStopped = true;
|
|
|
|
logger.error("Error unscheduling task {}", executionIdentifier, e);
|
|
|
|
throw new ExecutorException(e);
|
2018-02-15 17:00:01 +01:00
|
|
|
} catch(SchedulerException e) {
|
2018-01-10 17:33:26 +01:00
|
|
|
// currentStopped = false;
|
|
|
|
logger.error("Error unscheduling task {}", executionIdentifier, e);
|
|
|
|
throw new ExecutorException(e);
|
2018-02-15 17:00:01 +01:00
|
|
|
} catch(SchedulePersistenceException e) {
|
2018-01-10 17:33:26 +01:00
|
|
|
// currentStopped = true;
|
|
|
|
logger.error("Error removing scheduled task from persistence.", e);
|
2018-02-15 17:00:01 +01:00
|
|
|
} catch(ExecutorException e) {
|
2018-01-10 17:33:26 +01:00
|
|
|
throw e;
|
2018-02-15 17:00:01 +01:00
|
|
|
} catch(Exception e) {
|
2018-01-10 17:33:26 +01:00
|
|
|
// currentStopped = false;
|
|
|
|
logger.error("Error unscheduling task {}", executionIdentifier, e);
|
|
|
|
throw new ExecutorException(e);
|
|
|
|
}
|
2018-02-15 17:00:01 +01:00
|
|
|
logger.info("{} with UUID {} was{} stopped successfully", pluginName, executionIdentifier,
|
|
|
|
currentStopped ? "" : " NOT");
|
2018-01-10 17:33:26 +01:00
|
|
|
return currentStopped;
|
|
|
|
} catch(ExecutorException e) {
|
|
|
|
throw e;
|
|
|
|
} catch(Exception e) {
|
|
|
|
throw new ExecutorException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-02 17:50:39 +02:00
|
|
|
@PURGE
|
|
|
|
@Path("/{" + PLUGIN_NAME_PATH_PARAM + "}/" + RestConstants.EXECUTIONS_PATH_PART + "/" + "{" + UUID_PATH_PARAM + "}")
|
2019-08-02 18:29:38 +02:00
|
|
|
@Override
|
2019-08-02 17:50:39 +02:00
|
|
|
public boolean purge(@PathParam(PLUGIN_NAME_PATH_PARAM) String pluginName,
|
|
|
|
@PathParam(UUID_PATH_PARAM) String executionIdentifier) throws ExecutorException {
|
|
|
|
return delete(pluginName, executionIdentifier, true);
|
2018-01-10 17:33:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|