app/libraries/ExperimentUtilities.php (1,176 lines of code) (raw):

<?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; } } }