smart-executor-client/src/main/java/org/gcube/vremanagement/executor/client/SmartExecutorClientImpl.java

333 lines
11 KiB
Java

package org.gcube.vremanagement.executor.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
import org.gcube.common.gxhttp.reference.GXConnection;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.vremanagement.executor.api.rest.RestConstants;
import org.gcube.vremanagement.executor.api.rest.SmartExecutor;
import org.gcube.vremanagement.executor.api.types.LaunchParameter;
import org.gcube.vremanagement.executor.exception.ExecutorException;
import org.gcube.vremanagement.executor.json.SEMapper;
import org.gcube.vremanagement.executor.plugin.PluginDeclaration;
import org.gcube.vremanagement.executor.plugin.PluginStateEvolution;
import org.gcube.vremanagement.executor.plugin.ScheduledTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class SmartExecutorClientImpl implements SmartExecutorClient {
private static final Logger logger = LoggerFactory.getLogger(SmartExecutorClientImpl.class);
public static final String PATH_SEPARATOR = "/";
protected String pluginName;
protected String host;
protected String address;
@Override
public String getHost() {
return host;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
this.host = address.split("(http)s{0,1}://")[1].split(":")[0];
}
public String getPluginName() {
return pluginName;
}
public void setPluginName(String pluginName) {
this.pluginName = pluginName;
}
protected static StringBuilder getStringBuilder(InputStream inputStream) throws IOException {
StringBuilder result = new StringBuilder();
try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
}
return result;
}
protected String parseHttpURLConnection(HttpURLConnection connection) throws WebApplicationException {
try {
int responseCode = connection.getResponseCode();
// String responseMessage = connection.getResponseMessage();
if(connection.getRequestMethod().compareTo(HTTPMETHOD.HEAD.toString()) == 0) {
if(responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
return null;
}
if(responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
throw new NotFoundException();
}
if(responseCode == HttpURLConnection.HTTP_FORBIDDEN) {
throw new ForbiddenException();
}
}
if(responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) {
InputStream inputStream = connection.getErrorStream();
StringBuilder result = getStringBuilder(inputStream);
String res = result.toString();
throw new WebApplicationException(res, responseCode);
}
StringBuilder result = getStringBuilder(connection.getInputStream());
return result.toString();
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new WebApplicationException(e);
} finally {
connection.disconnect();
}
}
private void checkPluginName(String pluginName) throws ExecutorException {
if(pluginName.compareTo(this.pluginName) != 0) {
throw new ExecutorException(
String.format("The client has been instantiated for %s so it cannot be used to launch %s",
this.pluginName, pluginName));
}
}
@Override
public String getAvailablePlugins() {
try {
logger.info("Going to get Available Plugins on {}", host);
GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address);
gxHTTPStringRequest.from(SmartExecutorClient.class.getSimpleName());
gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8);
gxHTTPStringRequest.path(RestConstants.PLUGINS_PATH_PART);
HttpURLConnection httpURLConnection = gxHTTPStringRequest.get();
String pluginList = parseHttpURLConnection(httpURLConnection);
logger.info("Available Plugins on {} are {}", host, pluginList);
return pluginList;
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public List<PluginDeclaration> getPlugins() throws IOException {
String pluginList = getAvailablePlugins();
return SEMapper.getInstance().unmarshalList(PluginDeclaration.class,pluginList);
}
private String getScheduledTask(String name) {
try {
logger.info("Going to get orphan scheduled tasks");
GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address);
gxHTTPStringRequest.from(SmartExecutorClient.class.getSimpleName());
gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8);
gxHTTPStringRequest.path(RestConstants.PLUGINS_PATH_PART);
gxHTTPStringRequest.path(name);
gxHTTPStringRequest.path(RestConstants.EXECUTIONS_PATH_PART);
HttpURLConnection httpURLConnection = gxHTTPStringRequest.get();
String orphanList = parseHttpURLConnection(httpURLConnection);
logger.info("Orphan schadule task are {}", orphanList);
return orphanList;
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getOrphanLaunches() {
return getScheduledTask(SmartExecutor.ORPHAN_PATH_PARAM);
}
@Override
public List<ScheduledTask> getOrphanScheduledLaunches() throws IOException {
String orphanList = getOrphanLaunches();
return SEMapper.getInstance().unmarshalList(ScheduledTask.class, orphanList);
}
@Override
public String getLaunches() {
return getScheduledTask(pluginName);
}
@Override
public List<ScheduledTask> getScheduledLaunches() throws IOException {
String launchesList = getLaunches();
return SEMapper.getInstance().unmarshalList(ScheduledTask.class, launchesList);
}
@Override
public String launch(String launchParameter) {
try {
logger.info("Going to launch plugin {} on {} with parameters {} ", pluginName, host, launchParameter);
GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address);
gxHTTPStringRequest.from(SmartExecutorClient.class.getSimpleName());
gxHTTPStringRequest.header("Content-Type", GXConnection.APPLICATION_JSON_CHARSET_UTF_8);
gxHTTPStringRequest.header("Accept", "text/plain");
gxHTTPStringRequest.path(RestConstants.PLUGINS_PATH_PART);
gxHTTPStringRequest.path(pluginName);
gxHTTPStringRequest.path(RestConstants.EXECUTIONS_PATH_PART);
HttpURLConnection httpURLConnection = gxHTTPStringRequest.post(launchParameter);
String uuid = parseHttpURLConnection(httpURLConnection);
logger.debug("Plugin {} launched on host {}. UUID to monitor the execution is {} ", pluginName, host, uuid);
return uuid;
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public UUID launch(LaunchParameter launchParameter) {
try {
checkPluginName(launchParameter.getPluginName());
String uuid = launch(SEMapper.getInstance().marshal(launchParameter));
return UUID.fromString(uuid);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getPluginStateEvolution(String executionIdentifier) {
return getPluginStateEvolution(executionIdentifier, -1);
}
@Override
public String getPluginStateEvolution(String executionIdentifier, int iterationNumber) {
try {
logger.info("Going to get {} of {} with UUID {} ", PluginStateEvolution.class.getSimpleName(), pluginName,
executionIdentifier);
GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address);
gxHTTPStringRequest.from(SmartExecutorClient.class.getSimpleName());
gxHTTPStringRequest.header("Accept", GXConnection.APPLICATION_JSON_CHARSET_UTF_8);
gxHTTPStringRequest.path(RestConstants.PLUGINS_PATH_PART);
gxHTTPStringRequest.path(pluginName);
gxHTTPStringRequest.path(RestConstants.EXECUTIONS_PATH_PART);
gxHTTPStringRequest.path(executionIdentifier);
if(iterationNumber > 0) {
Map<String,String> parameters = new HashMap<>();
parameters.put(RestConstants.ITERATION_PARAM, Integer.toString(iterationNumber));
gxHTTPStringRequest.queryParams(parameters);
}
HttpURLConnection httpURLConnection = gxHTTPStringRequest.get();
String pluginStateEvolution = parseHttpURLConnection(httpURLConnection);
return pluginStateEvolution;
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public PluginStateEvolution getPluginStateEvolution(UUID executionIdentifier) {
return getPluginStateEvolution(executionIdentifier, -1);
}
@Override
public PluginStateEvolution getPluginStateEvolution(UUID executionIdentifier, int iterationNumber) {
try {
String pluginStateEvolution = getPluginStateEvolution(executionIdentifier.toString(), iterationNumber);
return SEMapper.getInstance().unmarshal(PluginStateEvolution.class, pluginStateEvolution);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public boolean delete(String executionIdentifier) {
return delete(executionIdentifier.toString(), true);
}
@Override
public boolean delete(String executionIdentifier, boolean unschedule) {
try {
logger.info("Going to stop plugin {} with UUID {} on host {}", pluginName, executionIdentifier, host);
GXHTTPStringRequest gxHTTPStringRequest = GXHTTPStringRequest.newRequest(address);
gxHTTPStringRequest.from(SmartExecutorClient.class.getSimpleName());
gxHTTPStringRequest.header("Accept", "text/plain");
gxHTTPStringRequest.path(RestConstants.PLUGINS_PATH_PART);
gxHTTPStringRequest.path(pluginName);
gxHTTPStringRequest.path(RestConstants.EXECUTIONS_PATH_PART);
gxHTTPStringRequest.path(executionIdentifier);
Map<String,String> parameters = new HashMap<>();
parameters.put(RestConstants.UNSCHEDULE_PARAM, Boolean.toString(unschedule));
gxHTTPStringRequest.queryParams(parameters);
HttpURLConnection httpURLConnection = gxHTTPStringRequest.delete();
String stoppedString = parseHttpURLConnection(httpURLConnection);
Boolean stopped = Boolean.valueOf(stoppedString);
logger.debug("Plugin {} with UUID {} {} stopped on host {}", pluginName, executionIdentifier,
stopped ? "successfully" : "was not", host);
return stopped;
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public boolean delete(UUID executionIdentifier) {
return delete(executionIdentifier.toString(), true);
}
@Override
public boolean delete(UUID executionIdentifier, boolean unschedule) {
return delete(executionIdentifier.toString(), unschedule);
}
}