blob: fd7bd6f3681bcbef469b4f03d266072483b450fc [file] [log] [blame]
<?php
use Airavata\API\Error\AiravataClientException;
use Airavata\API\Error\AiravataSystemException;
use Airavata\API\Error\AuthorizationException;
use Airavata\API\Error\ExperimentNotFoundException;
use Airavata\API\Error\InvalidRequestException;
use Airavata\Facades\Airavata;
use Airavata\Model\Application\Io\DataType;
use Airavata\Model\AppCatalog\AppInterface\ApplicationInterfaceDescription;
use Airavata\Model\Scheduling\ComputationalResourceSchedulingModel;
use Airavata\Model\Experiment\ExperimentModel;
use Airavata\Model\Status\ExperimentState;
use Airavata\Model\Status\ProcessState;
use Airavata\Model\Status\JobState;
use Airavata\Model\Status\TaskState;
use Airavata\Model\Task\TaskTypes;
use Airavata\Model\Experiment\UserConfigurationDataModel;
use Airavata\Model\Data\Replica\DataProductModel;
use Airavata\Model\Data\Replica\DataProductType;
use Airavata\Model\Data\Replica\DataReplicaLocationModel;
use Airavata\Model\Data\Replica\ReplicaLocationCategory;
use Airavata\Model\Data\Replica\ReplicaPersistentType;
use Airavata\Model\Application\Io\InputDataObjectType;
use Airavata\Model\Group\ResourcePermissionType;
class ExperimentUtilities
{
const FILE_UNAVAILABLE_ICON_TOOLTIP = ' <span class="glyphicon glyphicon-warning-sign" data-toggle="tooltip" data-placement="right" title="File is not available for download."></span></p>';
private static $experimentPath;
private static $relativeExperimentDataDir;
/**
* Launch the experiment with the given ID
* @param $expId
*/
public static function launch_experiment($expId)
{
try {
$gatewayId = Config::get('pga_config.airavata')['gateway-id'];
Airavata::launchExperiment(Session::get('authz-token'), $expId, $gatewayId);
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>There was a problem launching the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
CommonUtilities::print_error_message('<p>There was a problem launching the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>ExperimentNotFoundException: ' . $enf->getMessage() . '</p>');
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('<p>There was a problem launching the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('<p>There was a problem launching the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataSystemException: ' . $ase->getMessage() . '</p>');
} catch (Exception $e) {
CommonUtilities::print_error_message('<p>There was a problem launching the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>Exception: ' . $e->getMessage() . '</p>');
}
}
/**
* List the experiment's input files
* @param $experiment
*/
public static function list_input_files($experimentInputs)
{
//$experimentInputs = $experiment->experimentInputs;
//showing experiment inputs in the order defined by the admins.
$order = array();
foreach ($experimentInputs as $index => $input) {
$order[$index] = $input->inputOrder;
}
array_multisort($order, SORT_ASC, $experimentInputs);
$optFilesHtml = "";
if( count( $experimentInputs) > 0 ) {
foreach ($experimentInputs as $input) {
$matchingAppInput = null;
if ($input->type == DataType::URI) {
// Skip inputs that have no value
if ($input->value === null) {
continue;
}
$currentInputPath = ExperimentUtilities::get_data_product_path($input);
if ($currentInputPath) {
$fileName = basename($currentInputPath);
} else {
$fileName = basename($input->value);
}
$path = parse_url($currentInputPath)['path'];
if(file_exists($path)){
echo '<p>' . $input->name . ':&nbsp;<a target="_blank" href="' . URL::to("/") . '/download/?id='
. $input->value . '">' . $fileName . ' <span class="glyphicon glyphicon-new-window"></span></a></p>';
} else {
echo '<p>' . $input->name . ':&nbsp;' . $fileName . self::FILE_UNAVAILABLE_ICON_TOOLTIP;
}
}else if($input->type == DataType::URI_COLLECTION) {
if ($input->value) {
$optFilesHtml = $optFilesHtml . ExperimentUtilities::get_uri_collection_value_display($input->value);
}
} elseif ($input->type == DataType::STRING || $input->type == DataType::INTEGER
|| $input->type == DataType::FLOAT) {
echo '<p>' . $input->name . ':&nbsp;' . $input->value . '</p>';
}
}
if(strlen($optFilesHtml) > 0)
echo '<p> Optional File Inputs:&nbsp;' . $optFilesHtml;
}
}
private static function get_uri_collection_value_display($value) {
$displayHtml = "";
$uriList = $value;
$uriList = preg_split('/,/', $uriList);
foreach($uriList as $uri){
$currentInputPath = "";
if (strpos($uri, "airavata-dp") === 0) {
$dataProductModel = Airavata::getDataProduct(Session::get('authz-token'), $uri);
foreach ($dataProductModel->replicaLocations as $rp) {
if ($rp->replicaLocationCategory == ReplicaLocationCategory::GATEWAY_DATA_STORE) {
$currentInputPath = $rp->filePath;
break;
}
}
$fileName = basename($currentInputPath);
} else {
$fileName = basename($value);
}
$path = parse_url($currentInputPath)['path'];
if(file_exists($path)){
$displayHtml = $displayHtml . '<a target="_blank" href="' . URL::to("/") . '/download/?id='
. $uri . '">' . $fileName . ' <span class="glyphicon glyphicon-new-window"></span></a>&nbsp;';
} else {
$displayHtml = $displayHtml . $fileName . self::FILE_UNAVAILABLE_ICON_TOOLTIP;
}
}
return $displayHtml;
}
/**
* List the process's input files
* @param $experiment
*/
public static function list_process_input_files($processInputs)
{
$order = array();
foreach ($processInputs as $index => $input) {
$order[$index] = $input->inputOrder;
}
array_multisort($order, SORT_ASC, $processInputs);
foreach ($processInputs as $input) {
$matchingAppInput = null;
if ($input->type == DataType::URI) {
$dataRoot = Config::get("pga_config.airavata")["experiment-data-absolute-path"];
if(!ExperimentUtilities::endsWith($dataRoot, "/"))
$dataRoot = $dataRoot . "/";
$filePath = str_replace($dataRoot, "", parse_url($input->value, PHP_URL_PATH));
echo '<p>' . $input->name . ':&nbsp;<a target="_blank" href="' . URL::to("/")
. '/download/?path=' . $filePath . '">' . basename($filePath) . ' <span class="glyphicon glyphicon-new-window"></span></a></p>';
}elseif ($input->type == DataType::STRING || $input->type == DataType::INTEGER
|| $input->type == DataType::FLOAT) {
echo '<p>' . $input->name . ': ' . $input->value . '</p>';
}
}
}
/**
* List the process's output files
* @param $experiment
*/
public static function list_process_output_files($outputs, $status){
if ($status != ProcessState::COMPLETED)
echo "Process hasn't completed. Process Status is : " . ProcessState::$__names[ $status] . '<br/>';
foreach ((array)$outputs as $output) {
if ($output->type == DataType::URI || $output->type == DataType::STDOUT || $output->type == DataType::STDERR) {
$dataRoot = Config::get("pga_config.airavata")["experiment-data-absolute-path"];
if(!ExperimentUtilities::endsWith($dataRoot, "/"))
$dataRoot = $dataRoot . "/";
$filePath = parse_url($output->value, PHP_URL_PATH);
if(file_exists($filePath)){
$filePath = str_replace($dataRoot, "", parse_url($output->value, PHP_URL_PATH));
echo '<p>' . $output->name . ':&nbsp;<a target="_blank" href="' . URL::to("/")
. '/download/?path=' . $filePath . '">' . basename($filePath) . ' <span class="glyphicon glyphicon-new-window"></span></a></p>';
}
} elseif ($output->type == DataType::URI_COLLECTION) {
echo '<p>' . $output->name . ': ' . ExperimentUtilities::get_uri_collection_value_display($output->value) . ' </p>';
} elseif ($output->type == DataType::STRING) {
echo '<p>' . $output->value . '</p>';
}
else
echo 'output : '. $output;
}
}
private static function endsWith($haystack, $needle) {
// search forward starting from end minus needle length characters
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== false);
}
/**
* Get the experiment with the given ID
* @param $expId
* @return null
* @throws ExperimentNotFoundException
*/
public static function get_experiment($expId)
{
try {
if (Session::has("admin") || Session::has("admin-read-only")) {
return Airavata::getExperimentByAdmin(Session::get('authz-token'), $expId);
} else {
return Airavata::getExperiment(Session::get('authz-token'), $expId);
}
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
throw $enf; // rethrow
} catch (AuthorizationException $ae) {
throw $ae; // rethrow
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('AiravataSystemException: ' . $ase->getMessage() . '</p>');
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('TTransportException: ' . $tte->getMessage() . '</p>');
} catch (Exception $e) {
CommonUtilities::print_error_message('Exception: ' . $e->getMessage() . '</p>');
}
}
/**
* Get the detailed tree of an experiment with the given ID
* @param $expId
* @return null
*/
public static function get_detailed_experiment($expId)
{
try {
$detailed_experiment = Airavata::getDetailedExperimentTree(Session::get('authz-token'), $expId);
Log::debug("detailed exp", array($detailed_experiment));
foreach ($detailed_experiment->processes as $index => $process) {
usort($process->tasks, ExperimentUtilities::sortTasksByTaskDagOrder($process->taskDag));
Log::debug("process", array($process, $process->taskDag));
Log::debug("task list", array($process, $process->tasks));
foreach ($process->tasks as $task) {
Log::debug("task", array("taskId" => $task->taskId,
"creationTime" => $task->creationTime, "lastUpdateTime" => $task->lastUpdateTime, "status" => $task->taskStatuses));
// TODO: sort taskStatuses by time and output them
}
}
return $detailed_experiment;
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>ExperimentNotFoundException: ' . $enf->getMessage() . '</p>');
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataSystemException: ' . $ase->getMessage() . '</p>');
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>TTransportException: ' . $tte->getMessage() . '</p>');
} catch (Exception $e) {
CommonUtilities::print_error_message('<p>There was a problem getting the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>Exception: ' . $e->getMessage() . '</p>');
}
}
private static function sortTasksByTaskDagOrder($taskDag)
{
$taskDagArray = preg_split("/,/", $taskDag);
Log::debug("taskDagArray", array($taskDagArray));
return function($task1, $task2) use ($taskDagArray) {
$taskOrder1 = array_search($task1->taskId, $taskDagArray);
$taskOrder2 = array_search($task2->taskId, $taskDagArray);
Log::debug("tasks and order", array($task1->taskId, $taskOrder1, $task2->taskId, $taskOrder2));
return $taskOrder1 - $taskOrder2;
};
}
/**
* Create and configure a new Experiment
* @return Experiment
*/
public static function assemble_experiment()
{
$experimentInputs = array();
$scheduling = new ComputationalResourceSchedulingModel();
$scheduling->totalCPUCount = $_POST['cpu-count'];
$scheduling->nodeCount = $_POST['node-count'];
$scheduling->queueName = $_POST['queue-name'];
$scheduling->wallTimeLimit = $_POST['wall-time'];
$scheduling->totalPhysicalMemory = $_POST['total-physical-memory'];
$scheduling->resourceHostId = $_POST['compute-resource'];
// $scheduling->staticWorkingDir = $_POST['static-working-dir'];
$userConfigData = new UserConfigurationDataModel();
$userConfigData->computationalResourceScheduling = $scheduling;
$userConfigData->storageId = Config::get('pga_config.airavata')['gateway-data-store-resource-id'];
$userConfigData->airavataAutoSchedule = isset($_POST['enable-auto-scheduling']) ? true : false;
if (isset($_POST["userDN"])) {
$userConfigData->generateCert = 1;
$userConfigData->userDN = $_POST["userDN"];
}
$userConfigData->useUserCRPref = isset($_POST['use-user-cr-pref']) ? true : false;
if (isset(Config::get('pga_config.airavata')['group-resource-profile-id'])) {
$userConfigData->groupResourceProfileId = Config::get('pga_config.airavata')['group-resource-profile-id'];
}
ExperimentUtilities::create_experiment_folder_path($_POST['project'], $_POST['experiment-name']);
$userConfigData->experimentDataDir = ExperimentUtilities::$experimentPath;
$applicationInputs = AppUtilities::get_application_inputs($_POST['application']);
$experimentInputs = ExperimentUtilities::process_inputs(ExperimentUtilities::$experimentPath, $applicationInputs, $experimentInputs);
$experiment = new ExperimentModel();
// required
$experiment->projectId = $_POST['project'];
$experiment->userName = Session::get('username');
$experiment->name = $_POST['experiment-name'];
$experiment->gatewayId = Config::get('pga_config.airavata')['gateway-id'];
$experiment->experimentName = $_POST['experiment-name'];
// optional
$experiment->description = $_POST['experiment-description'];
$experiment->executionId = $_POST['application'];
$experiment->userConfigurationData = $userConfigData;
$experiment->experimentInputs = $experimentInputs;
if (isset($_POST["enableEmailNotification"])) {
$experiment->enableEmailNotification = intval($_POST["enableEmailNotification"]);
$experiment->emailAddresses = array_unique(array_filter($_POST["emailAddresses"], "trim"));
}
// adding default experiment outputs for now till prepoulated experiment template is not implemented.
$experiment->experimentOutputs = AppUtilities::get_application_outputs($_POST["application"]);
if ($experimentInputs) {
return $experiment;
}
}
/**
* @param $applicationInputs
* @param $experimentInputs
* @internal param $environmentPath
* @return array
*/
public static function process_inputs($experimentFilePath, $applicationInputs, $experimentInputs)
{
$experimentAssemblySuccessful = true;
$newExperimentInputs = array();
//sending application inputs in the order defined by the admins.
$order = array();
foreach ($applicationInputs as $index => $input) {
$order[$index] = $input->inputOrder;
}
array_multisort($order, SORT_ASC, $applicationInputs);
foreach ($applicationInputs as $applicationInput) {
$experimentInput = $applicationInput;
if (($applicationInput->type == DataType::STRING) ||
($applicationInput->type == DataType::INTEGER) ||
($applicationInput->type == DataType::FLOAT)
) {
if (isset($_POST[$applicationInput->sanitizedFormName]) && (trim($_POST[$applicationInput->sanitizedFormName]) != '')) {
$experimentInput->value = $_POST[$applicationInput->sanitizedFormName];
$experimentInput->type = $applicationInput->type;
} else // use previous value
{
$index = -1;
for ($i = 0; $i < sizeof($experimentInputs); $i++) {
if ($experimentInputs[$i]->name == $applicationInput->name) {
$index = $i;
}
}
if ($index >= 0) {
$experimentInput->value = $experimentInputs[$index]->value;
$experimentInput->type = $applicationInput->type;
}
}
} elseif ($applicationInput->type == DataType::URI) {
if ($_FILES[$applicationInput->sanitizedFormName]['name']) {
$file = $_FILES[$applicationInput->sanitizedFormName];
if ($file['error'] != 0) {
throw new Exception("Failure occurred while uploading file '"
. $file['name'] . "'. File upload error code is " . $file['error'] . ".");
}
//FIX - AIRAVATA - 2674
//Replaced spaces with Underscore
$file['name'] = str_replace(' ', '_', $file['name']);
//
// move file to experiment data directory
//
if (!empty($applicationInput->value)) {
$filePath = $experimentFilePath . $applicationInput->value;
} else {
$filePath = $experimentFilePath . $file['name'];
}
// check if file already exists
if (is_file($filePath)) {
unlink($filePath);
CommonUtilities::print_warning_message('Uploaded file already exists! Overwriting...');
}
$moveFile = move_uploaded_file($file['tmp_name'], $filePath);
if (!$moveFile) {
CommonUtilities::print_error_message('<p>Error moving uploaded file ' . $file['name'] . '!
Please try again later or report a bug using the link in the Help menu.</p>');
$experimentAssemblySuccessful = false;
}
$experimentInput->type = $applicationInput->type;
$dataProductModel = new DataProductModel();
$dataProductModel->gatewayId = Config::get("pga_config.airavata")["gateway-id"];
$dataProductModel->ownerName = Session::get("username");
$dataProductModel->productName = basename($filePath);
$dataProductModel->dataProductType = DataProductType::FILE;
$dataReplicationModel = new DataReplicaLocationModel();
$dataReplicationModel->storageResourceId = Config::get("pga_config.airavata")["gateway-data-store-resource-id"];
$dataReplicationModel->replicaName = basename($filePath) . " gateway data store copy";
$dataReplicationModel->replicaLocationCategory = ReplicaLocationCategory::GATEWAY_DATA_STORE;
$dataReplicationModel->replicaPersistentType = ReplicaPersistentType::TRANSIENT;
$hostName = $_SERVER['SERVER_NAME'];
$dataReplicationModel->filePath = "file://" . $hostName . ":" . $filePath;
$dataProductModel->replicaLocations[] = $dataReplicationModel;
$uri = Airavata::registerDataProduct(Session::get('authz-token'), $dataProductModel);
$experimentInput->value = $uri;
} else {
$index = -1;
for ($i = 0; $i < sizeof($experimentInputs); $i++) {
if ($experimentInputs[$i]->name == $applicationInput->name) {
$index = $i;
}
}
if ($index >= 0) {
$experimentInput->value = $experimentInputs[$index]->value;
$experimentInput->type = $applicationInput->type;
}
}
} else {
CommonUtilities::print_error_message('I cannot accept this input type yet!');
}
$newExperimentInputs[] = $experimentInput;
}
if(isset($_FILES['optInputFiles'])){
$uriList = "";
for($i=0; $i < count($_FILES['optInputFiles']['name']); $i++){
if(!empty($_FILES['optInputFiles']['name'][$i])){
// Check if there is an error with the upload (like if it exceeded upload_max_filesize)
if ($_FILES['optInputFiles']['error'][$i] != 0) {
throw new Exception("Failure occurred while uploading file '"
. $_FILES['optInputFiles']['name'][$i] . "'. File upload error code is " . $_FILES['optInputFiles']['error'][$i] . ".");
}
$filePath = $experimentFilePath . $_FILES['optInputFiles']['name'][$i];
// check if file already exists
if (is_file($filePath)) {
unlink($filePath);
CommonUtilities::print_warning_message('Uploaded file already exists! Overwriting...');
}
$moveFile = move_uploaded_file($_FILES['optInputFiles']['tmp_name'][$i], $filePath);
if (!$moveFile) {
CommonUtilities::print_error_message('<p>Error moving uploaded file ' . $_FILES['optInputFiles']['name'][$i] . '!
Please try again later or report a bug using the link in the Help menu.</p>');
$experimentAssemblySuccessful = false;
}
$dataProductModel = new DataProductModel();
$dataProductModel->gatewayId = Config::get("pga_config.airavata")["gateway-id"];
$dataProductModel->ownerName = Session::get("username");
$dataProductModel->productName = basename($filePath);
$dataProductModel->dataProductType = DataProductType::FILE;
$dataReplicationModel = new DataReplicaLocationModel();
$dataReplicationModel->storageResourceId = Config::get("pga_config.airavata")["gateway-data-store-resource-id"];
$dataReplicationModel->replicaName = basename($filePath) . " gateway data store copy";
$dataReplicationModel->replicaLocationCategory = ReplicaLocationCategory::GATEWAY_DATA_STORE;
$dataReplicationModel->replicaPersistentType = ReplicaPersistentType::TRANSIENT;
$hostName = $_SERVER['SERVER_NAME'];
$dataReplicationModel->filePath = "file://" . $hostName . ":" . $filePath;
$dataProductModel->replicaLocations[] = $dataReplicationModel;
$uri = Airavata::registerDataProduct(Session::get('authz-token'), $dataProductModel);
$uriList = $uriList . $uri . ",";
}
}
if(strlen($uriList) > 0){
$uriList = substr($uriList,0, strlen($uriList) - 1);
$optInput = new InputDataObjectType();
$optInput->name = "Optional-File-Input-List";
$optInput->type = DataType::URI_COLLECTION;
$optInput->value = $uriList;
$newExperimentInputs[] = $optInput;
}
}
if ($experimentAssemblySuccessful) {
return $newExperimentInputs;
} else {
return false;
}
}
public static function create_experiment_folder_path($projectId, $experimentName)
{
do {
$projectId = substr($projectId, 0, -37);
$projectId = preg_replace('/[^a-zA-Z0-9]+/', '_', $projectId);
$experimentName = preg_replace('/[^a-zA-Z0-9]+/', '_', $experimentName);
ExperimentUtilities::$relativeExperimentDataDir = "/" . Session::get('username') . "/" . $projectId . "/"
. $experimentName . time() . '/';
ExperimentUtilities::$experimentPath = Config::get('pga_config.airavata')['experiment-data-absolute-path'] .
ExperimentUtilities::$relativeExperimentDataDir;
} while (is_dir(ExperimentUtilities::$experimentPath)); // if dir already exists, try again
// create upload directory
$old_umask = umask(0);
Log::debug("Creating experiment folder", array(ExperimentUtilities::$experimentPath));
if (!mkdir(ExperimentUtilities::$experimentPath, 0777, true)) {
CommonUtilities::print_error_message('<p>Error creating upload directory!
Please try again later or report a bug using the link in the Help menu.</p>');
$experimentAssemblySuccessful = false;
}
umask($old_umask);
}
/**
* Check the uploaded files for errors
*/
public static function file_upload_successful()
{
$uploadSuccessful = true;
foreach ($_FILES as $file) {
//var_dump($file);
if (!is_array($file) and $file['name']) {
if ($file['error'] > 0) {
$uploadSuccessful = false;
CommonUtilities::print_error_message('<p>Error uploading file ' . $file['name'] . ' !
Please try again later or report a bug using the link in the Help menu.');
}
}else if(is_array($file) and $file['name']){
for($i =0 ; $i< count($file['name']); $i++){
if ($file['error'][$i] > 0) {
$uploadSuccessful = false;
CommonUtilities::print_error_message('<p>Error uploading file ' . $file['name'][$i] . ' !
Please try again later or report a bug using the link in the Help menu.');
}
}
}
}
return $uploadSuccessful;
}
/**
* Update the experiment with the given ID
* @param $expId
* @param $updatedExperiment
*/
public static function update_experiment($expId, $updatedExperiment)
{
try {
Airavata::updateExperiment(Session::get('authz-token'), $expId, $updatedExperiment);
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>There was a problem updating the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
CommonUtilities::print_error_message('<p>There was a problem updating the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>ExperimentNotFoundException: ' . $enf->getMessage() . '</p>');
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('<p>There was a problem updating the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('<p>There was a problem updating the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataSystemException: ' . $ase->getMessage() . '</p>');
}
if(Config::get('pga_config.airavata')["data-sharing-enabled"] && isset($_POST['share-settings'])){
$share = $_POST['share-settings'];
ExperimentUtilities::share_experiment($expId, json_decode($share));
}
}
/**
* Clone the experiment with the given ID
* @param $expId
*/
public static function clone_experiment($expId, $projectId)
{
try {
//create new experiment to receive the clone
if (Session::has("admin") || Session::has("admin-read-only")) {
$experiment = Airavata::getExperimentByAdmin(Session::get('authz-token'), $expId);
$cloneId = Airavata::cloneExperimentByAdmin(Session::get('authz-token'), $expId, 'Clone of ' . $experiment->experimentName, $projectId);
} else {
$experiment = Airavata::getExperiment(Session::get('authz-token'), $expId);
$cloneId = Airavata::cloneExperiment(Session::get('authz-token'), $expId, 'Clone of ' . $experiment->experimentName, $projectId);
}
//updating the experiment inputs and output path
$experiment = Airavata::getExperiment(Session::get('authz-token'), $cloneId);
$experimentInputs = $experiment->experimentInputs;
ExperimentUtilities::create_experiment_folder_path($experiment->projectId, $experiment->experimentName);
$hostName = $_SERVER['SERVER_NAME'];
foreach ($experimentInputs as $experimentInput) {
if ($experimentInput->type == DataType::URI) {
$hostPathConstant = 'file://' . $hostName . ':';
$dataProductModel = Airavata::getDataProduct(Session::get('authz-token'), $experimentInput->value);
$currentInputPath = "";
foreach ($dataProductModel->replicaLocations as $rp) {
if($rp->replicaLocationCategory == ReplicaLocationCategory::GATEWAY_DATA_STORE){
$currentInputPath = $rp->filePath;
break;
}
}
$currentInputPath = str_replace($hostPathConstant, '', $currentInputPath);
$parts = explode('/', rtrim($currentInputPath, '/'));
$fileName = array_pop($parts);
$newInputPath = ExperimentUtilities::$experimentPath . $fileName;
if(parse_url($currentInputPath)){
$currentInputPath = parse_url($currentInputPath, PHP_URL_PATH);
}
if (file_exists($currentInputPath)) {
copy($currentInputPath, $newInputPath);
$dataProductModel = new DataProductModel();
$dataProductModel->gatewayId = Config::get("pga_config.airavata")["gateway-id"];
$dataProductModel->ownerName = Session::get("username");
$dataProductModel->productName = basename($newInputPath);
$dataProductModel->dataProductType = DataProductType::FILE;
$dataReplicationModel = new DataReplicaLocationModel();
$dataReplicationModel->storageResourceId = Config::get("pga_config.airavata")["gateway-data-store-resource-id"];
$dataReplicationModel->replicaName = basename($newInputPath) . " gateway data store copy";
$dataReplicationModel->replicaLocationCategory = ReplicaLocationCategory::GATEWAY_DATA_STORE;
$dataReplicationModel->replicaPersistentType = ReplicaPersistentType::TRANSIENT;
$hostName = $_SERVER['SERVER_NAME'];
$dataReplicationModel->filePath = "file://" . $hostName . ":" . $newInputPath;
$dataProductModel->replicaLocations[] = $dataReplicationModel;
$uri = Airavata::registerDataProduct(Session::get('authz-token'), $dataProductModel);
$experimentInput->value = $uri;
} else {
Log::warning("Input file no longer available at " . $currentInputPath);
$experimentInput->value = null;
}
}
}
$experiment->userConfigurationData->experimentDataDir = ExperimentUtilities::$experimentPath;
$computeResourceId = $experiment->userConfigurationData->computationalResourceScheduling->resourceHostId;
if ($experiment->userConfigurationData->useUserCRPref){
// Check if this user has a user CR preference for the compute
// resource, if not we want to switch this flag to false
$userComputeResourcePreferences = URPUtilities::get_all_validated_user_compute_resource_prefs();
$userHasComputeResourcePreference = array_key_exists($computeResourceId, $userComputeResourcePreferences);
$experiment->userConfigurationData->useUserCRPref = $userHasComputeResourcePreference;
}
// In case the gateway-data-store-resource-id has changed since the
// original experiment was created, update in this experiment
$experiment->userConfigurationData->storageId = Config::get('pga_config.airavata')['gateway-data-store-resource-id'];
if (isset(Config::get('pga_config.airavata')['group-resource-profile-id'])) {
$experiment->userConfigurationData->groupResourceProfileId = Config::get('pga_config.airavata')['group-resource-profile-id'];
}
Airavata::updateExperiment(Session::get('authz-token'), $cloneId, $experiment);
$share = SharingUtilities::getAllUserPermissions($expId);
$share[Session::get('username')] = ["read" => true, "write" => true];
ExperimentUtilities::share_experiment($cloneId, json_decode(json_encode($share)));
return $cloneId;
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>There was a problem cloning the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
CommonUtilities::print_error_message('<p>There was a problem cloning the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>ExperimentNotFoundException: ' . $enf->getMessage() . '</p>');
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('<p>There was a problem cloning the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('<p>There was a problem cloning the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataSystemException: ' . $ase->getMessage() . '</p>');
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('<p>There was a problem cloning the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>TTransportException: ' . $tte->getMessage() . '</p>');
}
}
/**
* Cancel the experiment with the given ID
* Cancel the experiment with the given ID
* @param $expId
*/
public static function cancel_experiment($expId)
{
try {
Airavata::terminateExperiment(Session::get('authz-token'), $expId, Config::get('pga_config.airavata')["gateway-id"]);
CommonUtilities::print_success_message("Experiment canceled!");
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>InvalidRequestException: ' . $ire->getMessage() . '</p>');
} catch (ExperimentNotFoundException $enf) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>ExperimentNotFoundException: ' . $enf->getMessage() . '</p>');
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataClientException: ' . $ace->getMessage() . '</p>');
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>AiravataSystemException: ' . $ase->getMessage() . '</p>');
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>TTransportException: ' . $tte->getMessage() . '</p>');
} catch (Exception $e) {
CommonUtilities::print_error_message('<p>There was a problem canceling the experiment.
Please try again later or submit a bug report using the link in the Help menu.</p>' .
'<p>Exception: ' . $e->getMessage() . '</p>');
}
}
/**
* Create form inputs to accept the inputs to the given application
* @param $id
* @param $experimentInputs
* @param $allowedFileSize maximum file size in megabytes
* @internal param $required
*/
public static function create_inputs($id, $experimentInputs, $allowedFileSize)
{
$inputs = AppUtilities::get_application_inputs($id);
// require if existing input has no value (check $experimentInputs) or file doesn't exist
$required = ' required';
//var_dump( $inputs); echo "<br/>after sort<br/>";
//arranging inputs in ascending order.
foreach ($inputs as $index => $input) {
$order[$index] = $input->inputOrder;
}
if($inputs != null){
array_multisort($order, SORT_ASC, $inputs);
}
// var_dump( $inputs); exit;
foreach ($inputs as $input) {
$disabled = "";
if($input->isReadOnly)
$disabled = "disabled";
if ($experimentInputs !== null) {
foreach ($experimentInputs as $experimentInput) {
if ($input->name === $experimentInput->name && $experimentInput->value !== null) {
if ($experimentInput->type === DataType::URI) {
$path = ExperimentUtilities::get_data_product_path($experimentInput);
// Don't require the input file if there is already an existing value
if ($path !== null && file_exists($path)) {
$required = '';
}
}
}
}
}
switch ($input->type) {
case DataType::STRING:
echo '<div class="form-group">
<label for="experiment-input">' . $input->name . '</label>';
if(!empty($input->value) && count(explode(",", $input->value)) > 1){
echo '<select class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName . '">';
$vals = explode(",", $input->value);
echo '<option value="'.$vals[0].'" selected>'.$vals[0] .'</option>';
for($i=1; $i<count(explode(",", $input->value)); $i++){
echo '<option value="'.$vals[$i].'">'.$vals[$i] .'</option>';
}
echo '</select></div>';
}else{
echo '<input '.$disabled . ' value="' . $input->value . '" type="text" class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName .
'" placeholder="' . $input->userFriendlyDescription . '"' . $required . '>
</div>';
}
break;
case DataType::INTEGER:
echo '<div class="form-group">
<label for="experiment-input">' . $input->name . '</label>';
if(!empty($input->value) && count(explode(",", $input->value)) > 1){
echo '<select class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName . '">';
$vals = explode(",", $input->value);
echo '<option value="'.$vals[0].'" selected>'.$vals[0] .'</option>';
for($i=1; $i<count(explode(",", $input->value)); $i++){
echo '<option value="'.$vals[$i].'">'.$vals[$i] .'</option>';
}
echo '</select>';
}else{
echo '<input '.$disabled . ' value="' . $input->value . '" type="number" class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName .
'" placeholder="' . $input->userFriendlyDescription . '"' . $required . '>
</div>';
}
break;
case DataType::FLOAT:
echo '<div class="form-group">
<label for="experiment-input">' . $input->name . '</label>';
if(!empty($input->value) && count(explode(",", $input->value)) > 1){
echo '<select class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName . '">';
$vals = explode(",", $input->value);
echo '<option value="'.$vals[0].'" selected>'.$vals[0] .'</option>';
for($i=1; $i<count(explode(",", $input->value)); $i++){
echo '<option value="'.$vals[$i].'">'.$vals[$i] .'</option>';
}
echo '</select>';
}else{
echo '<input '.$disabled . ' value="' . $input->value . '" type="number" step="0.01" class="form-control" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName .
'" placeholder="' . $input->userFriendlyDescription . '"' . $required . '>
</div>';
}
break;
case DataType::URI:
echo '<div class="form-group">
<label for="experiment-input">' . $input->name . '</label>
<div data-file-id="' . $input->sanitizedFormName . '" class="readBytesButtons btn btn-default btn-xs"
data-toggle="modal" style="float: right">view file</div>
<div class="file-upload-container">
<input class="file-input" type="file" name="' . $input->sanitizedFormName .
'" id="' . $input->sanitizedFormName . '" ' . $required . '>
<div class="file-upload-max-size">Max Upload Size: ' . $allowedFileSize .'M</div>
</div>
<p class="help-block">' . $input->userFriendlyDescription . '</p>
</div>';
break;
case DataType::URI_COLLECTION:
// Support for URI_COLLECTION is not implemented in PGA, just ignore
break;
default:
CommonUtilities::print_error_message('Input data type not supported!
Please file a bug report using the link in the Help menu.');
break;
}
}
$appInterface = AppUtilities::get_application_interface($id);
if($appInterface->hasOptionalFileInputs){
echo '<div>
<label>Optional Input Files</label>
<div class="file-upload-container">
<input type="file" class="file-input" id="optInputFiles" name="optInputFiles[]" multiple onchange="javascript:updateList()" >
<div class="file-upload-max-size">Max Upload Size: ' . $allowedFileSize .'M</div>
</div>
<div id="optFileList"></div>
</div>';
}
}
/**
* Create a new experiment from the values submitted in the form
* @return null
*/
public static function create_experiment()
{
$experiment = ExperimentUtilities::assemble_experiment();
$expId = null;
try {
if ($experiment) {
$expId = Airavata::createExperiment(Session::get('authz-token'), Session::get("gateway_id"), $experiment);
}
if ($expId) {
/*
CommonUtilities::print_success_message("Experiment {$_POST['experiment-name']} created!" .
' <a href="experiment_summary.php?expId=' . $expId . '">Go to experiment summary page</a>');
*/
} else {
CommonUtilities::print_error_message("Error creating experiment {$_POST['experiment-name']}!");
}
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('InvalidRequestException!<br><br>' . $ire->getMessage());
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('AiravataClientException!<br><br>' . $ace->getMessage());
} catch (AiravataSystemException $ase) {
CommonUtilities::print_error_message('AiravataSystemException!<br><br>' . $ase->getMessage());
}
if(Config::get('pga_config.airavata')["data-sharing-enabled"] && $expId){
$share = $_POST['share-settings'];
ExperimentUtilities::share_experiment($expId, json_decode($share));
}
return $expId;
}
/*
* Required in Experiment Sumamry page.
*
*/
public static function list_output_files($outputs, $status, $process)
{
if ( $status != ExperimentState::COMPLETED)
echo "Experiment hasn't completed. Experiment Status is : " . ExperimentState::$__names[ $status] . '<br/>';
foreach ((array)$outputs as $output) {
if ($output->type == DataType::URI || $output->type == DataType::STDOUT || $output->type == DataType::STDERR) {
if(!empty($output->value) && filter_var($output->value, FILTER_VALIDATE_URL)){
if(strpos($output->value, "airavata-dp") === 0){
$dataProductModel = Airavata::getDataProduct(Session::get('authz-token'), $output->value);
$currentOutputPath = "";
foreach ($dataProductModel->replicaLocations as $rp) {
if($rp->replicaLocationCategory == ReplicaLocationCategory::GATEWAY_DATA_STORE){
$currentOutputPath = $rp->filePath;
break;
}
}
$path = parse_url($currentOutputPath)['path'];
$fileName = basename($currentOutputPath);
if(file_exists($path)){
echo '<p>' . $output->name . ':&nbsp;<a target="_blank" href="' . URL::to("/")
. '/download/?id=' . urlencode($output->value) . '">' . $fileName
. ' <span class="glyphicon glyphicon-new-window"></span></a></p>';
} else {
echo '<p>' . $output->name . ':&nbsp;' . $fileName . self::FILE_UNAVAILABLE_ICON_TOOLTIP . ' </p>';
}
}else {
$fileName = basename($output->value);
if(file_exists($path)){
echo '<p>' . $output->name . ':&nbsp;<a target="_blank" href="' . URL::to("/")
. '/download/?id=' . urlencode($output->value) . '">' . $fileName
. ' <span class="glyphicon glyphicon-new-window"></span></a></p>';
} else {
echo '<p>' . $output->name . ':&nbsp;' . $fileName . self::FILE_UNAVAILABLE_ICON_TOOLTIP . ' </p>';
}
}
}
} elseif ($output->type == DataType::STRING) {
if (strpos($output->value, "parsed-out: ") === 0) {
echo '<p>' . $output->name . ': ' . substr($output->value, 12) . '</p>';
}
} elseif ($output->type == DataType::URI_COLLECTION) {
echo '<p>' . $output->name . ': ' . ExperimentUtilities::get_uri_collection_value_display($output->value) . ' </p>';
} else
echo 'output : ' . $output;
}
}
/*
public static function get_experiment_summary_values($experimentSummary, $forSearch = false)
{
// var_dump( $experimentSummary); exit;
$expVal = array();
$expVal["experimentStatusString"] = "";
$expVal["experimentTimeOfStateChange"] = "";
$expVal["experimentCreationTime"] = "";
$expVal["experimentStatusString"] = $experimentSummary->experimentStatus;
$expVal["experimentTimeOfStateChange"] = $experimentSummary->statusUpdateTime / 1000; // divide by 1000 since timeOfStateChange is in ms
$expVal["experimentCreationTime"] = $experimentSummary->creationTime / 1000; // divide by 1000 since creationTime is in ms
if (!$forSearch) {
$userConfigData = $experimentSummary->userConfigurationData;
$scheduling = $userConfigData->computationalResourceScheduling;
$expVal['scheduling'] = $scheduling;
try {
$expVal["computeResource"] = CRUtilities::get_compute_resource($scheduling->resourceHostId);
} catch (Exception $ex) {
//Error while retrieving CR
$expVal["computeResource"] = "";
}
}
try{
$expVal["applicationInterface"] = AppUtilities::get_application_interface($experimentSummary->executionId);
}catch (Exception $ex){
//Failed retrieving Application Interface (May be it's deleted) Fix for Airavata-1801
$expVal["applicationInterface"] = new ApplicationInterfaceDescription();
$expVal["applicationInterface"]->applicationName = substr($experimentSummary->executionId, -8);
}
switch ($experimentSummary->experimentStatus) {
case 'CREATED':
case 'VALIDATED':
case 'SCHEDULED':
case 'FAILED':
$expVal["editable"] = true;
break;
default:
$expVal["editable"] = false;
break;
}
switch ($experimentSummary->experimentStatus) {
case 'CREATED':
case 'VALIDATED':
case 'SCHEDULED':
case 'LAUNCHED':
case 'EXECUTING':
$expVal["cancelable"] = true;
break;
default:
$expVal["cancelable"] = false;
break;
}
return $expVal;
}
*/
public static function get_experiment_values($experiment, $forSearch = false)
{
$expVal = array();
//$expVal["experimentStatusString"] = "";
$expVal["experimentTimeOfStateChange"] = "";
$expVal["experimentCreationTime"] = "";
$expVal["experimentStates"] = ExperimentState::$__names;
$expVal["processStates"] = ProcessState::$__names;
$expVal["jobStates"] = JobState::$__names;
$expVal["taskStates"] = TaskState::$__names;
$expVal["taskTypes"] = TaskTypes::$__names;
if(Config::get('pga_config.airavata')["data-sharing-enabled"]) {
$can_write = SharingUtilities::userCanWrite(Session::get("username"), $experiment->experimentId);
} else {
$can_write = true;
}
if( is_array( $experiment->experimentStatus ) )
$experimentStatusString = $expVal["experimentStates"][ExperimentUtilities::latestStatus($experiment->experimentStatus)->state];
else {
$experimentStatusString = $experiment->experimentStatus;
}
$expVal["experimentStatusString"] = $experimentStatusString;
if ($experiment->experimentStatus != null) {
$experimentStatus = $experiment->experimentStatus;
if( is_array( $experiment->experimentStatus ) )
$expVal["experimentTimeOfStateChange"] = ExperimentUtilities::latestStatus($experimentStatus)->timeOfStateChange / 1000; // divide by 1000 since timeOfStateChange is in ms
$expVal["experimentCreationTime"] = $experiment->creationTime / 1000; // divide by 1000 since creationTime is in ms
}
if (!$forSearch && is_array( $experiment->experimentStatus) ){
$userConfigData = $experiment->userConfigurationData;
$scheduling = $userConfigData->computationalResourceScheduling;
$expVal['scheduling'] = $scheduling;
try {
$expVal["computeResource"] = CRUtilities::get_compute_resource($scheduling->resourceHostId);
} catch (Exception $ex) {
//Error while retrieving CR
$expVal["computeResource"] = "";
}
}
try{
$expVal["applicationInterface"] = AppUtilities::get_application_interface($experiment->executionId);
}catch (Exception $ex){
//Failed retrieving Application Interface (May be it's deleted) Fix for Airavata-1801
$expVal["applicationInterface"] = new ApplicationInterfaceDescription();
$expVal["applicationInterface"]->applicationName = substr($experiment->executionId, -8);
}
//editable statuses
switch ( $experimentStatusString) {
case 'CREATED':
case 'VALIDATED':
case 'SCHEDULED':
$expVal["editable"] = true && $can_write;
break;
default:
$expVal["editable"] = false;
break;
}
//cancelable statuses
switch ( $experimentStatusString) {
case 'VALIDATED':
case 'SCHEDULED':
case 'LAUNCHED':
case 'EXECUTING':
$expVal["cancelable"] = true && $can_write;
break;
default:
$expVal["cancelable"] = false;
break;
}
return $expVal;
}
/**
* Method to get the job status of an experiment
* @param $experiment
* @return null
*/
public static function get_job_status(ExperimentModel $experiment)
{
$jobStatus = Airavata::getJobStatuses(Session::get('authz-token'), $experiment->experimentId);
//TODO - implement following logic with new data model.
/* if(!empty($experiment->workflowNodeDetailsList)){
if(!empty($experiment->workflowNodeDetailsList[0]->taskDetailsList)){
if(!empty($experiment->workflowNodeDetailsList[0]->taskDetailsList[0]->jobDetailsList)){
$jobStatus = $experiment->workflowNodeDetailsList[0]->taskDetailsList[0]->jobDetailsList[0]->jobStatus;
}
}
}*/
if (isset($jobStatus) && count($jobStatus) > 0) {
$jobState = JobState::$__names[ExperimentUtilities::latestStatus(array_values($jobStatus))->jobState];
} else {
$jobState = null;
}
return $jobState;
}
/**
* Create options for the search key select input
* @param $values
* @param $labels
* @param $disabled
*/
public static function create_options($values, $labels, $disabled)
{
for ($i = 0; $i < sizeof($values); $i++) {
$selected = '';
// if option was previously selected, mark it as selected
if (isset($_POST['search-key'])) {
if ($values[$i] == $_POST['search-key']) {
$selected = 'selected';
}
}
echo '<option value="' . $values[$i] . '" ' . $disabled[$i] . ' ' . $selected . '>' . $labels[$i] . '</option>';
}
}
/**
* Get results of the user's search of experiments with pagination
* @return array|null
*/
public static function get_expsearch_results_with_pagination($inputs, $limit, $offset)
{
$experiments = array();
try {
$filters = array();
if(!empty($inputs["status-type"])){
if ($inputs["status-type"] != "ALL") {
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::STATUS] = $inputs["status-type"];
}
}
if(!empty($inputs["search-key"])){
switch ($inputs["search-key"]) {
case 'experiment-name':
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::EXPERIMENT_NAME] = $inputs["search-value"];
break;
case 'experiment-description':
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::EXPERIMENT_DESC] = $inputs["search-value"];
break;
case 'application':
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::APPLICATION_ID] = $inputs["search-value"];
break;
case 'creation-time':
$timeDifference = Session::get("user_timezone");
$addOrSubtract = "-";
if( $timeDifference > 0)
$addOrSubtract = "+";
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::FROM_DATE] = strtotime( $addOrSubtract . " " . Session::get("user_timezone") . " hours", strtotime($inputs["from-date"]) ) * 1000;
$filters[\Airavata\Model\Experiment\ExperimentSearchFields::TO_DATE] = strtotime( $addOrSubtract . " " . Session::get("user_timezone") . " hours", strtotime($inputs["to-date"]) ) * 1000;
break;
case '':
}
}
$experiments = Airavata::searchExperiments(Session::get('authz-token'),
Session::get('gateway_id'), Session::get('username'), $filters, $limit, $offset);
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('InvalidRequestException!<br><br>' . $ire->getMessage());
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('AiravataClientException!<br><br>' . $ace->getMessage());
} catch (AiravataSystemException $ase) {
if ($ase->airavataErrorType == 2) // 2 = INTERNAL_ERROR
{
CommonUtilities::print_info_message('<p>You have not created any experiments yet, so no results will be returned!</p>
<p>Click <a href="create_experiment.php">here</a> to create an experiment, or
<a href="create_project.php">here</a> to create a new project.</p>');
} else {
CommonUtilities::print_error_message('There was a problem with Airavata. Please try again later or report a bug using the link in the Help menu.');
//print_error_message('AiravataSystemException!<br><br>' . $ase->airavataErrorType . ': ' . $ase->getMessage());
}
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('TTransportException!<br><br>' . $tte->getMessage());
}
//get values of all experiments
$expContainer = array();
$expNum = 0;
foreach ($experiments as $experiment) {
if(Config::get('pga_config.airavata')["data-sharing-enabled"]){
if (SharingUtilities::userCanRead(Session::get('username'), $experiment->experimentId)) {
$expValue = ExperimentUtilities::get_experiment_values($experiment, true);
$expContainer[$expNum]['experiment'] = $experiment;
if ($expValue["experimentStatusString"] == "FAILED")
$expValue["editable"] = false;
$expContainer[$expNum]['expValue'] = $expValue;
$expNum++;
}
}else{
$expValue = ExperimentUtilities::get_experiment_values($experiment, true);
$expContainer[$expNum]['experiment'] = $experiment;
if ($expValue["experimentStatusString"] == "FAILED")
$expValue["editable"] = false;
$expContainer[$expNum]['expValue'] = $expValue;
$expNum++;
}
}
return $expContainer;
}
/**
* Get results of the user's all experiments with pagination.
* Results are ordered creation time DESC
* @return array|null
*/
public static function get_all_user_experiments_with_pagination($limit, $offset)
{
$experiments = array();
try {
$experiments = Airavata::getUserExperiments(Session::get('authz-token'),
Session::get('gateway_id'), Session::get('username'), $limit, $offset
);
} catch (InvalidRequestException $ire) {
CommonUtilities::print_error_message('InvalidRequestException!<br><br>' . $ire->getMessage());
} catch (AiravataClientException $ace) {
CommonUtilities::print_error_message('AiravataClientException!<br><br>' . $ace->getMessage());
} catch (AiravataSystemException $ase) {
if ($ase->airavataErrorType == 2) // 2 = INTERNAL_ERROR
{
CommonUtilities::print_info_message('<p>You have not created any experiments yet, so no results will be returned!</p>
<p>Click <a href="create_experiment.php">here</a> to create an experiment, or
<a href="create_project.php">here</a> to create a new project.</p>');
} else {
CommonUtilities::print_error_message('There was a problem with Airavata. Please try again later or report a bug using the link in the Help menu.');
//print_error_message('AiravataSystemException!<br><br>' . $ase->airavataErrorType . ': ' . $ase->getMessage());
}
} catch (TTransportException $tte) {
CommonUtilities::print_error_message('TTransportException!<br><br>' . $tte->getMessage());
}
//get values of all experiments
$expContainer = array();
$expNum = 0;
foreach ($experiments as $experiment) {
$expValue = ExperimentUtilities::get_experiment_values($experiment, true);
$expContainer[$expNum]['experiment'] = $experiment;
if ($expValue["experimentStatusString"] == "FAILED")
$expValue["editable"] = false;
$expContainer[$expNum]['expValue'] = $expValue;
$expNum++;
}
return $expContainer;
}
public static function getExpStates()
{
$states = ExperimentState::$__names;
//removing UNKNOWN and SUSPENDED states. (AIRAVATA-1756)
$index = array_search('UNKNOWN',$states);
if($index !== FALSE){
unset($states[$index]);
}
$index = array_search('SUSPENDED',$states);
if($index !== FALSE){
unset($states[$index]);
}
return $states;
}
public static function apply_changes_to_experiment($experiment, $input)
{
$experiment->experimentName = $input['experiment-name'];
$experiment->description = rtrim($input['experiment-description']);
// $experiment->projectId = $input['project'];
// $experiment->applicationId = $_POST['application'];
// $experiment->executionId = $_POST['application'];
$userConfigDataUpdated = $experiment->userConfigurationData;
$schedulingUpdated = $userConfigDataUpdated->computationalResourceScheduling;
$schedulingUpdated->resourceHostId = $input['compute-resource'];
$schedulingUpdated->nodeCount = $input['node-count'];
$schedulingUpdated->queueName = $_POST['queue-name'];
$schedulingUpdated->totalCPUCount = $input['cpu-count'];
//$schedulingUpdated->numberOfThreads = $input['threads'];
$schedulingUpdated->wallTimeLimit = $input['wall-time'];
$schedulingUpdated->totalPhysicalMemory = $input['total-physical-memory'];
/*
switch ($_POST['compute-resource'])
{
case 'trestles.sdsc.edu':
$schedulingUpdated->ComputationalProjectAccount = 'sds128';
break;
case 'stampede.tacc.xsede.org':
case 'lonestar.tacc.utexas.edu':
$schedulingUpdated->ComputationalProjectAccount = 'TG-STA110014S';
break;
default:
$schedulingUpdated->ComputationalProjectAccount = 'admin';
}
*/
$userConfigDataUpdated->computationalResourceScheduling = $schedulingUpdated;
$userConfigDataUpdated->airavataAutoSchedule = isset($_POST['enable-auto-scheduling']) ? true : false;
if (isset($input["userDN"])) {
$userConfigDataUpdated->generateCert = 1;
$userConfigDataUpdated->userDN = $input["userDN"];
}
$userConfigDataUpdated->useUserCRPref = isset($_POST['use-user-cr-pref']) ? true : false;
if (isset(Config::get('pga_config.airavata')['group-resource-profile-id'])) {
$userConfigDataUpdated->groupResourceProfileId = Config::get('pga_config.airavata')['group-resource-profile-id'];
}
$experiment->userConfigurationData = $userConfigDataUpdated;
$applicationInputs = AppUtilities::get_application_inputs($experiment->executionId);
$experimentInputs = $experiment->experimentInputs; // get current inputs
$experimentInputs = ExperimentUtilities::process_inputs( $experiment->userConfigurationData->experimentDataDir, $applicationInputs, $experimentInputs); // get new inputs
// var_dump($experimentInputs);
// exit;
if (isset($_POST["enableEmailNotification"])) {
$experiment->enableEmailNotification = intval($_POST["enableEmailNotification"]);
$experiment->emailAddresses = array_unique(array_filter($_POST["emailAddresses"], "trim"));
}
if ($experimentInputs) {
$experiment->experimentInputs = $experimentInputs;
//var_dump($experiment);
return $experiment;
}
}
public static function get_status_color_class( $status)
{
switch ( $status) {
case 'CANCELING':
case 'CANCELED':
case 'UNKNOWN':
$statusClass = 'text-warning';
break;
case 'FAILED':
$statusClass = 'text-danger';
break;
case 'COMPLETED':
$statusClass = 'text-success';
break;
case 'COMPLETE':
$statusClass = 'text-success';
break;
default:
$statusClass = 'text-info';
break;
}
return $statusClass;
}
public static function get_job_details($experimentId)
{
return Airavata::getJobDetails(Session::get('authz-token'), $experimentId);
}
public static function get_transfer_details($experimentId)
{
return Airavata::getDataTransferDetails(Session::get('authz-token'), $experimentId);
}
public static function getQueueDatafromResourceId($crId)
{
$resourceObject = Airavata::getComputeResource(Session::get('authz-token'), $crId);
$queues = $resourceObject->batchQueues;
//Defining maximum allowed value for queue resources
$maxNodeCount = Config::get('pga_config.airavata.max-node-count', null);
$maxCPUCount = Config::get('pga_config.airavata.max-total-cpu-count', null);
$maxWallTimeLimit = Config::get('pga_config.airavata.max-wall-time-limit', null);
foreach($queues as $aQueue){
if($maxNodeCount && $aQueue->maxNodes > $maxNodeCount){
$aQueue->maxNodes = $maxNodeCount;
}
if($maxCPUCount && $aQueue->maxProcessors > $maxCPUCount){
$aQueue->maxProcessors = $maxCPUCount;
}
if($maxWallTimeLimit && $aQueue->maxRunTime > $maxWallTimeLimit){
$aQueue->maxRunTime = $maxWallTimeLimit;
}
}
return $queues;
}
/**
* Create a select input and populate it with applications options
* @param null $id
* @param bool $editable
*/
public static function create_application_select($id = null, $editable = true)
{
$disabled = $editable ? '' : 'disabled';
$applicationIds = AppUtilities::get_all_applications();
uksort($applicationIds, 'strcasecmp');
echo '<select class="form-control" name="application" id="application" required ' . $disabled . '>';
if (count($applicationIds)) {
foreach ((array)$applicationIds as $applicationId => $applicationName) {
$selected = ($applicationId == $id) ? 'selected' : '';
echo '<option value="' . $applicationId . '" ' . $selected . '>' . $applicationName . '</option>';
}
}
echo '</select>';
}
public static function update_experiment_sharing($expId, $users) {
ExperimentUtilities::share_experiment($expId, $users);
}
public static function latestStatus($statusArray) {
return $statusArray ? $statusArray[count($statusArray) - 1] : null;
}
/**
* Set sharing privileges for a given experiment.
* @param $expId
* @param $users A map of username => {read_permission, write_permission}
*/
private static function share_experiment($expId, $users) {
$experiment = ExperimentUtilities::get_experiment($expId);
$users->{$experiment->userName} = new stdClass();
$users->{$experiment->userName}->read = true;
$users->{$experiment->userName}->write = true;
$wadd = array();
$wrevoke = array();
$radd = array();
$rrevoke = array();
foreach ($users as $user => $perms) {
if ($perms->write) {
$wadd[$user] = ResourcePermissionType::WRITE;
}
else {
$wrevoke[$user] = ResourcePermissionType::WRITE;
}
if ($perms->read) {
$radd[$user] = ResourcePermissionType::READ;
}
else {
$rrevoke[$user] = ResourcePermissionType::READ;
}
}
GrouperUtilities::shareResourceWithUsers($expId, $wadd);
GrouperUtilities::revokeSharingOfResourceFromUsers($expId, $wrevoke);
GrouperUtilities::shareResourceWithUsers($expId, $radd);
GrouperUtilities::revokeSharingOfResourceFromUsers($expId, $rrevoke);
}
private static function get_data_product_path($input) {
if ($input->value === null) {
return null;
}
$currentInputPath = "";
if (strpos($input->value, "airavata-dp") === 0) {
$dataProductModel = Airavata::getDataProduct(Session::get('authz-token'), $input->value);
foreach ($dataProductModel->replicaLocations as $rp) {
if ($rp->replicaLocationCategory == ReplicaLocationCategory::GATEWAY_DATA_STORE) {
$currentInputPath = $rp->filePath;
break;
}
}
}
if ($currentInputPath !== "") {
return parse_url($currentInputPath)['path'];
} else {
return null;
}
}
}