dataminer-pool-manager/src/main/java/org/gcube/dataanalysis/dataminer/poolmanager/service/DMPMJob.java

274 lines
8.2 KiB
Java
Raw Normal View History

package org.gcube.dataanalysis.dataminer.poolmanager.service;
import java.io.File;
import java.io.FileOutputStream;
2023-01-18 17:56:48 +01:00
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.UUID;
2023-01-18 17:56:48 +01:00
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.dataanalysis.dataminer.poolmanager.ansible.AnsibleWorker;
import org.gcube.dataanalysis.dataminer.poolmanager.ansiblebridge.AnsibleBridge;
import org.gcube.dataanalysis.dataminer.poolmanager.clients.configuration.Configuration;
2023-01-18 17:56:48 +01:00
import org.gcube.dataanalysis.dataminer.poolmanager.datamodel.Algorithm;
import org.gcube.dataanalysis.dataminer.poolmanager.datamodel.Cluster;
import org.gcube.dataanalysis.dataminer.poolmanager.service.exceptions.AnsibleException;
import org.gcube.dataanalysis.dataminer.poolmanager.service.exceptions.UndefinedDependenciesException;
import org.gcube.dataanalysis.dataminer.poolmanager.util.CheckMethod;
import org.gcube.dataanalysis.dataminer.poolmanager.util.NotificationHelper;
import org.gcube.dataanalysis.dataminer.poolmanager.util.SVNUpdater;
import org.gcube.dataanalysis.dataminer.poolmanager.util.SendMail;
import org.gcube.dataanalysis.dataminer.poolmanager.util.exception.DMPMException;
import org.gcube.dataanalysis.dataminer.poolmanager.util.exception.EMailException;
import org.gcube.dataanalysis.dataminer.poolmanager.util.exception.GenericException;
2023-01-18 17:56:48 +01:00
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2023-01-18 17:56:48 +01:00
public abstract class DMPMJob {
private Configuration configuration;
private String dmpmHomeDirectory;
private SVNUpdater svnUpdater;
private File jobLogs;
private String id;
private Algorithm algorithm;
private Cluster cluster;
private String vREName;
private String category;
private String algorithm_type;
private Logger logger;
private enum STATUS
2023-01-18 17:56:48 +01:00
{
PROGRESS ("IN PROGRESS"),
COMPLETED ("COMPLETED"),
FAILED ("FAILED");
private String status;
STATUS (String status)
2023-01-18 17:56:48 +01:00
{
this.status = status;
2023-01-18 17:56:48 +01:00
}
}
public DMPMJob(SVNUpdater svnUpdater,Configuration configuration,Algorithm algorithm, Cluster cluster,String vREName,
2023-01-18 17:56:48 +01:00
String category, String algorithm_type){
this.logger = LoggerFactory.getLogger(DMPMJob.class);
this.configuration = configuration;
this.algorithm = algorithm;
this.cluster = cluster;
this.vREName = vREName;
this.category = category;
this.algorithm_type = algorithm_type;
this.svnUpdater = svnUpdater;
this.dmpmHomeDirectory = new String (System.getProperty("user.home")+File.separator+"dataminer-pool-manager");
this.id = UUID.randomUUID().toString();
2023-01-18 17:56:48 +01:00
//TODO: dmpm work directory should be loaded from configuration file
this.jobLogs = new File(this.dmpmHomeDirectory+File.separator+"jobs");
this.jobLogs.mkdirs();
2023-01-18 17:56:48 +01:00
}
public String start()
2023-01-18 17:56:48 +01:00
{
setStatusInformation(STATUS.PROGRESS);
2023-01-18 17:56:48 +01:00
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
2023-01-18 17:56:48 +01:00
} catch (Exception e) {
e.printStackTrace();
2023-01-18 17:56:48 +01:00
}
}
}).start();
return this.id;
2023-01-18 17:56:48 +01:00
}
protected AnsibleWorker createWorker(Algorithm algo,
Cluster dataminerCluster,
boolean includeAlgorithmDependencies,
2023-01-18 17:56:48 +01:00
String user){
AnsibleBridge ansibleBridge = new AnsibleBridge(this.dmpmHomeDirectory);
2023-01-18 17:56:48 +01:00
try {
return ansibleBridge.createWorker(algo, dataminerCluster, includeAlgorithmDependencies, user);
2023-01-18 17:56:48 +01:00
} catch (IOException e) {
e.printStackTrace();
2023-01-18 17:56:48 +01:00
}
return null;
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
public void setStatusInformation(STATUS exitStatus) {
try
2023-01-18 17:56:48 +01:00
{
File statusFile = new File (this.jobLogs,this.id + "_exitStatus");
2023-01-18 17:56:48 +01:00
//File m = new File ( this.jobLogs + File.separator + this.id + "_exitStatus");
PrintWriter writer = new PrintWriter(statusFile, "UTF-8");
writer.println(exitStatus.status);
writer.close();
2023-01-18 17:56:48 +01:00
} catch (Exception e)
{
this.logger.error ("Unable to update exit status file with status "+exitStatus.status,e);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}
private void updateLogFile (File logFile, String message)
2023-01-18 17:56:48 +01:00
{
try
2023-01-18 17:56:48 +01:00
{
PrintWriter writer = new PrintWriter(logFile,"UTF-8");
writer.print(message);
writer.close();
2023-01-18 17:56:48 +01:00
} catch (Exception e)
{
this.logger.error("Unable to log the error message: "+message,e);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}
protected abstract void execute ();
private void preInstallation (SendMail sm,NotificationHelper nh, File logFile ) throws GenericException, EMailException,UndefinedDependenciesException
2023-01-18 17:56:48 +01:00
{
this.logger.debug("Checking dependencies...");
Collection<String> undefinedDependencies = this.svnUpdater.getUndefinedDependencies(
this.svnUpdater.getDependencyFile(this.algorithm.getLanguage()),
this.algorithm.getDependencies());
if (!undefinedDependencies.isEmpty())
2023-01-18 17:56:48 +01:00
{
this.logger.debug("Some dependencies are not defined");
throw new UndefinedDependenciesException(undefinedDependencies);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}
private String installation (SendMail sm,NotificationHelper nh,CheckMethod methodChecker,File logFile ) throws DMPMException
2023-01-18 17:56:48 +01:00
{
this.logger.debug("Installation process started");
methodChecker.deleteFiles(this.algorithm/*, env*/);
int ret = this.executeAnsibleWorker(createWorker(this.algorithm, this.cluster, false, "root"),logFile);
this.logger.debug("Return code= "+ret);
if (ret != 0) throw new AnsibleException(ret);
else
2023-01-18 17:56:48 +01:00
{
this.logger.debug("Operation completed");
2023-01-18 17:56:48 +01:00
//this.setStatusInformation(STATUS.PROGRESS);
this.logger.debug("Checking the method...");
methodChecker.checkMethod(this.configuration.getHost(), SecurityTokenProvider.instance.get());
methodChecker.copyAlgorithms(this.algorithm);
this.logger.debug("Method OK and algo exists");
this.logger.debug("Interface check ok!");
this.logger.debug("Both the files exist at the correct path!");
boolean algorithmListResult = this.svnUpdater.updateSVNAlgorithmList(this.algorithm, this.vREName,this.category, this.algorithm_type,
this.algorithm.getFullname());
this.setStatusInformation(STATUS.COMPLETED);
return algorithmListResult ?"":"\nWARNING: algorithm list could not be updated on SVN";
2023-01-18 17:56:48 +01:00
}
}
protected void execute(NotificationHelper nh, CheckMethod methodChecker)
2023-01-18 17:56:48 +01:00
{
SendMail sm = new SendMail();
File logFile = new File(this.jobLogs,this.id);
try
2023-01-18 17:56:48 +01:00
{
2023-01-18 17:56:48 +01:00
try {
this.logger.debug("Pre installation operations");
preInstallation(sm, nh, logFile);
this.logger.debug("Pre installation operation completed");
this.logger.debug("Installation...");
String warning = installation(sm, nh, methodChecker, logFile);
this.logger.debug("Installation completed");
this.logger.debug("Warning message "+warning);
this.setStatusInformation(STATUS.COMPLETED);
String bodyResponse = NotificationHelper.getSuccessBody(warning+"\n\n"+this.buildInfo());
sm.sendNotification(nh.getSuccessSubject() + " for "+this.algorithm.getName()+ " algorithm", bodyResponse);
2023-01-18 17:56:48 +01:00
} catch (DMPMException dmpme)
{
this.logger.error("Operation failed: "+dmpme.getMessage());
this.logger.error("Exception: ",dmpme);
this.setStatusInformation(STATUS.FAILED);
String errorMessage = "\n"+NotificationHelper.getFailedBody(dmpme.getErrorMessage()+"\n\n"+this.buildInfo());
this.updateLogFile(logFile, errorMessage);
sm.sendNotification(nh.getFailedSubject() +" for "+this.algorithm.getName()+ " algorithm", errorMessage);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
} catch (EMailException eme)
{
this.logger.error("Unable to send notification email",eme);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}
protected int executeAnsibleWorker(AnsibleWorker worker, File logFile) throws GenericException
2023-01-18 17:56:48 +01:00
{
try
2023-01-18 17:56:48 +01:00
{
FileOutputStream fos = new FileOutputStream(logFile, true);
PrintStream ps = new PrintStream(fos);
2023-01-18 17:56:48 +01:00
// File m = new File(this.jobLogs + File.separator + this.id + "_exitStatus");
// PrintWriter fos2 = new PrintWriter(m, "UTF-8");
return worker.execute(ps);
2023-01-18 17:56:48 +01:00
} catch (Exception e)
{
throw new GenericException(e);
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
public String buildInfo() {
return
"\n"+
"Algorithm details:\n"+"\n"+
"User: "+this.algorithm.getFullname()+"\n"+
"Algorithm name: "+this.algorithm.getName()+"\n"+
"Staging DataMiner Host: "+ this.configuration.getHost()+"\n"+
"Caller VRE: "+ScopeProvider.instance.get()+"\n"+
"Target VRE: "+this.vREName+"\n";
2023-01-18 17:56:48 +01:00
}
2023-01-18 17:56:48 +01:00
}