tapis_job-1.4.1-alpha1/src/Form/JobRestartForm.php
src/Form/JobRestartForm.php
<?php
namespace Drupal\tapis_job\Form;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\tapis_app\DrupalIds as AppDrupalIds;
use Drupal\tapis_job\TapisJobInterface;
use Drupal\tapis_job\TapisProvider\TapisJobProviderInterface;
use Drupal\tapis_system\DrupalIds as SystemDrupalIds;
use Drupal\tapis_tenant\Exception\TapisException;
use Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface;
use Drupal\webform\Entity\WebformSubmission;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class JobRestartForm.
*
* This class is used to create a form that allows a user to restart a job.
*
* @package Drupal\tapis_job\Form
*/
class JobRestartForm extends FormBase {
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected AccountProxyInterface $currentUser;
/**
* The Tapis site tenant provider.
*
* @var \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface
*/
protected TapisSiteTenantProviderInterface $tapisSiteTenantProvider;
/**
* The messenger interface.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The Tapis job provider.
*
* @var \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface
*/
protected TapisJobProviderInterface $tapisJobProvider;
/**
* Constructs a new AppLaunchForm object.
*
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
* @param \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface $tapisSiteTenantProvider
* The Tapis site tenant provider.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
* @param \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface $tapisJobProvider
* The Tapis job provider.
*/
public function __construct(AccountProxyInterface $current_user,
TapisSiteTenantProviderInterface $tapisSiteTenantProvider,
EntityTypeManagerInterface $entityTypeManager,
MessengerInterface $messenger,
TapisJobProviderInterface $tapisJobProvider) {
$this->currentUser = $current_user;
$this->tapisSiteTenantProvider = $tapisSiteTenantProvider;
$this->entityTypeManager = $entityTypeManager;
$this->messenger = $messenger;
$this->tapisJobProvider = $tapisJobProvider;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('current_user'),
$container->get("tapis_tenant.tapis_site_tenant_provider"),
$container->get('entity_type.manager'),
$container->get('messenger'),
$container->get('tapis_job.tapis_job_provider')
);
}
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'tapis_job_restart_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, TapisJobInterface $tapis_job = NULL) {
if (!$tapis_job) {
return;
}
$form_state->set("tapis_job_id", $tapis_job->id());
$node = $tapis_job->getApp();
$form['#tree'] = TRUE;
if (!$node) {
return;
}
// If (!\Drupal::currentUser()->hasPermission("create job")) {.
if (!$this->currentUser->hasPermission("create job")) {
// Disable the entire form.
$form['#disabled'] = TRUE;
// \Drupal::messenger()
// ->addError("You do not have permission to launch this app.");
$this->messenger->addError("You do not have permission to launch this app.");
return $form;
}
// Check if the app's Tapis tenant's Tapis site is in maintenance mode.
// $tapisSiteTenantProvider =
// \Drupal::service("tapis_tenant.tapis_site_tenant_provider");.
$tenantId = $node->get(AppDrupalIds::APP_TENANT)->first()->getValue()['target_id'];
if ($this->tapisSiteTenantProvider->isTenantInMaintenanceMode($tenantId)) {
$form['message'] = [
'#type' => 'markup',
'#markup' => '<p>This job cannot be cloned because its site is in maintenance mode.</p>',
];
return $form;
}
if (!$this->tapisJobProvider->checkAccessForAppAndSystem($node)) {
$form['message'] = [
'#type' => 'markup',
'#markup' => '<b>You do not have permission to launch this app.</b>',
];
return $form;
}
$appInputType = $node->get(AppDrupalIds::APP_INPUT_TYPE)->getValue()[0]['value'];
$useBatchScheduler = $node->get(AppDrupalIds::APP_USE_BATCH_SCHEDULER)->getValue()[0]['value'];
$form_state->set("app_id", $node->id());
$form_state->set("is_restart_form", TRUE);
// @todo Include app *version* input
// Didn't include this right now, since this relies on
// storing the app entity's versionable data within Drupal
// instead of exclusively within Tapis.
$systemOptions = [];
$availableSystemEntities = $node->get(AppDrupalIds::APP_AVAILABLE_SYSTEMS)->referencedEntities() ?? [];
foreach ($availableSystemEntities as $availableSystemEntity) {
// Check if the user can access this system.
if (!$availableSystemEntity->access("view")) {
// The current user doesn't have the permission to view this system,
// so remove this system from the list of available options.
continue;
}
$systemOptions[$availableSystemEntity->id()] = $this->t('@label', ['@label' => $availableSystemEntity->label()]);
}
$defaultSystemOption = NULL;
$defaultSystemEntity = $tapis_job->getSystem();
if ($defaultSystemEntity) {
// For restart forms,
// the default system is the system the original job was run on.
$defaultSystemOption = $defaultSystemEntity->id();
}
if (!$systemOptions) {
// The user doesn't have permission
// to any of the allowed systems for this app.
$form['error_message'] = ['#markup' => "Unfortunately, you cannot run this app, since you don't have access to any of the allowed systems for this app."];
return $form;
}
$originalTapisJobDefinition = $this->tapisJobProvider->getJob($tenantId, $tapis_job->getTapisUUID(), $tapis_job->getOwnerId());
$webformId = $tapis_job->getWebformSubmissionId();
if ($appInputType === "flexible_parameters" && $webformId) {
$webform_id = $node->get(AppDrupalIds::APP_WEBFORM)->first()->getValue()['target_id'];
// Get the webform entity.
$webform = $this->entityTypeManager->getStorage('webform')->load($webform_id);
// Get our handler for this webform by its id.
try {
$handler = $webform->getHandler('tapis_job_osp_webform_launch_app_');
$dryrun_handler = $webform->getHandler('tapis_job_osp_webform_dry_run_app_');
$regular_handler_enabled = $handler && $handler->isEnabled();
$dryrun_handler_enabled = $dryrun_handler && $dryrun_handler->isEnabled();
// Exactly one of the handlers should be enabled.
$valid_handler = ($regular_handler_enabled || $dryrun_handler_enabled) && !($regular_handler_enabled && $dryrun_handler_enabled);
if (!$valid_handler) {
// The webform doesn't have the handler we need,
// so we can't render it.
$form['error_message'] = ['#markup' => "Unable to run this app, since the form for this app is not configured correctly."];
return $form;
}
// Make sure that the last handler is the one we need.
$all_handlers = $webform->getHandlers();
$last_handler_id = NULL;
foreach ($all_handlers as $current_handler_id => $current_handler) {
// Only consider the handler if it's enabled.
if ($current_handler->isEnabled()) {
$last_handler_id = $current_handler_id;
}
}
if ($last_handler_id !== 'tapis_job_osp_webform_launch_app_' && $last_handler_id !== 'tapis_job_osp_webform_dry_run_app_') {
$form['error_message'] = ['#markup' => "Unable to run this app, since the form for this app is not configured correctly."];
return $form;
}
}
catch (\Exception $e) {
$form['error_message'] = ['#markup' => "Unable to run this app, since the form for this app is not configured correctly."];
return $form;
}
$webform_submission = WebformSubmission::load($webformId);
$webform_submission_data = $webform_submission ? $webform_submission->getData() : [];
$webform_submission_data['is_restart_form'] = TRUE;
$webform_submission_data['tapis_job_id'] = $tapis_job->id();
$form['webform'] = [
'#type' => 'webform',
'#webform' => $webform_id,
'#default_data' => $webform_submission_data,
'#lazy' => TRUE,
];
}
else {
$uniqueJobName = $this->tapisJobProvider->generateUniqueJobName($node->label());
$form['job_name'] = [
'#type' => 'textfield',
'#title' => $this->t('Job name'),
'#description' => $this->t('Specify a name for this job'),
'#default_value' => $uniqueJobName,
'#required' => TRUE,
];
$form['system'] = [
'#type' => 'select',
'#title' => ('System'),
'#options' => $systemOptions,
'#required' => TRUE,
'#ajax' => $useBatchScheduler ? [
'callback' => '::systemAjaxCallback',
'event' => 'change',
'wrapper' => 'osp_app_job_system_info_wrapper',
] : NULL,
// Make this disabled since it's a restart form
// (if defaultSystemOption is not NULL)
// we're disabling this because we don't want the user
// to change the system for a restart form.
'#disabled' => $defaultSystemOption !== NULL,
];
if ($defaultSystemOption !== NULL) {
$form['system']['#default_value'] = $defaultSystemOption;
}
// @todo Add a default batch logical queue field for apps in their create/edit forms (iff they use a batch scheduler)
// and make that overridable at jobs (caveat: apps
// may run on different systems, so the default batch logical queue
// may not be available on all systems)
if ($useBatchScheduler) {
$selected_system_id = $form_state->getValue("system") ?: $defaultSystemOption;
// $system_node = \Drupal::entityTypeManager()->getStorage('node')->load($selected_system_id);
$system_node = $this->entityTypeManager->getStorage('node')->load($selected_system_id);
$batch_logical_queues = $system_node->get(SystemDrupalIds::SYSTEM_BATCH_LOGICAL_QUEUES)->referencedEntities() ?? [];
$blq_options = [];
$default_system_blq_name = $originalTapisJobDefinition['execSystemLogicalQueue'] ?? $system_node->get(SystemDrupalIds::SYSTEM_DEFAULT_BATCH_LOGICAL_QUEUE)->getValue()[0]['value'];
$default_system_blq_id = NULL;
foreach ($batch_logical_queues as $batch_logical_queue) {
$blq_options[$batch_logical_queue->id()] = $batch_logical_queue->label();
if ($batch_logical_queue->getName() === $default_system_blq_name) {
$default_system_blq_id = $batch_logical_queue->id();
}
}
$form['batch_logical_queue_id'] = [
'#type' => 'select',
'#title' => $this->t('Batch logical queue'),
'#description' => $this->t('The batch logical queue to run this app on'),
'#required' => TRUE,
'#options' => $blq_options,
'#default_value' => $default_system_blq_id,
'#prefix' => '<div id="osp_app_job_system_info_wrapper">',
'#suffix' => '</div>',
];
$default_batch_allocation_id = NULL;
$originalJobParameterSetString = $originalTapisJobDefinition['parameterSet'] ?? '[]';
// Log the type of the originalJobParameterSetString.
$originalJobParameterSet = json_decode($originalJobParameterSetString, TRUE);
if (array_key_exists('schedulerOptions', $originalJobParameterSet)) {
$originalJobSchedulerOptions = $originalJobParameterSet['schedulerOptions'] ?? [];
// Go through the array of $originalJobSchedulerOptions
// and find the object with property 'name' set to '--tapis-profile'.
foreach ($originalJobSchedulerOptions as $originalJobSchedulerOption) {
// Check if $originalJobSchedulerOption['arg']
// starts with '--account '.
if (strpos($originalJobSchedulerOption['arg'], '--account ') === 0) {
$default_batch_allocation_id = $originalJobSchedulerOption['arg'];
// Replace '--account ' with an empty string in the allocation ID.
$default_batch_allocation_id = str_replace('--account ', '', $default_batch_allocation_id);
break;
}
}
}
$form['batch_allocation_id'] = [
'#type' => 'textfield',
'#title' => $this->t('Allocation'),
'#description' => $this->t('The allocation ID to use for running this app'),
'#required' => TRUE,
'#default_value' => $default_batch_allocation_id,
];
}
$user_can_override_num_nodes = boolval($node->get(AppDrupalIds::OVERRIDE_NUM_NODES)->getValue()[0]['value']);
$user_can_override_cores_per_node = boolval($node->get(AppDrupalIds::OVERRIDE_CORES_PER_NODE)->getValue()[0]['value']);
$user_can_override_memory = boolval($node->get(AppDrupalIds::OVERRIDE_MEMORY)->getValue()[0]['value']);
$user_can_override_max_runtime = boolval($node->get(AppDrupalIds::OVERRIDE_MAX_RUNTIME)->getValue()[0]['value']);
if ($user_can_override_num_nodes) {
// Num nodes.
$form[AppDrupalIds::APP_NUM_NODES] = [
'#type' => 'textfield',
'#attributes' => [
// Insert space before attribute name :)
' type' => 'number',
],
'#title' => 'Number of nodes',
'#default_value' => $originalTapisJobDefinition['nodeCount'] ?? intval($node->get(AppDrupalIds::APP_NUM_NODES)->getValue()[0]['value'] ?: 1),
'#required' => TRUE,
];
}
if ($user_can_override_cores_per_node) {
// Cores per node.
$form[AppDrupalIds::APP_CORES_PER_NODE] = [
'#type' => 'textfield',
'#attributes' => [
// Insert space before attribute name :)
' type' => 'number',
],
'#title' => 'Cores per node',
'#default_value' => $originalTapisJobDefinition['coresPerNode'] ?? intval($node->get(AppDrupalIds::APP_CORES_PER_NODE)->getValue()[0]['value'] ?: 1),
'#required' => TRUE,
];
}
if ($user_can_override_max_runtime) {
// Max runtime.
$form[AppDrupalIds::APP_MAX_MINUTES] = [
'#type' => 'textfield',
'#attributes' => [
// Insert space before attribute name :)
' type' => 'number',
],
'#title' => 'Max. runtime',
'#default_value' => $originalTapisJobDefinition['maxMinutes'] ?? intval($node->get(AppDrupalIds::APP_MAX_MINUTES)->getValue()[0]['value'] ?: 10),
'#required' => TRUE,
'#field_suffix' => 'minutes',
];
}
if ($user_can_override_memory) {
// Max memory.
$form[AppDrupalIds::APP_MEMORY_MB] = [
'#type' => 'textfield',
'#attributes' => [
// Insert space before attribute name :)
' type' => 'number',
],
'#title' => 'Memory',
'#default_value' => $originalTapisJobDefinition['memoryMB'] ?? intval($node->get(AppDrupalIds::APP_MEMORY_MB)->getValue()[0]['value'] ?: 100),
'#required' => TRUE,
'#field_suffix' => 'MBs',
];
}
$form['launch'] = [
'#type' => 'submit',
'#value' => $this->t('Launch app'),
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function systemAjaxCallback(array &$form, FormStateInterface $form_state) {
return $form['batch_logical_queue_id'];
}
/**
* Validate the form.
*
* (check if the user has a system credential for the selected system, etc.)
*
* @param array $form
* Form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* Form state.
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$tapis_app_id = $form_state->get("app_id");
// $app = \Drupal::entityTypeManager()
// ->getStorage('node')->load($tapis_app_id);
$app = $this->entityTypeManager->getStorage('node')->load($tapis_app_id);
$jobNames = $this->tapisJobProvider->getAllJobNames();
$jobName = $form_state->getValue("job_name") ?? $app->getTitle();
if (in_array($jobName, $jobNames)) {
$form_state->setErrorByName("job_name",
$this->t("The job name, '@jobName', already exists. Please change it.",
['@jobName' => $jobName]));
$form_state->setRebuild();
return;
}
$useBatchScheduler = boolval($app->get(AppDrupalIds::APP_USE_BATCH_SCHEDULER)->getValue()[0]['value']);
$appInputType = $app->get(AppDrupalIds::APP_INPUT_TYPE)->getValue()[0]['value'];
// If this is a batch app, load the selected batch logical queue and then
// check if all the runtime parameters are valid.
$batch_logical_queue_id = $form_state->getValue("batch_logical_queue_id");
if ($useBatchScheduler && $batch_logical_queue_id && $appInputType !== "flexible_parameters") {
// $batch_logical_queue = \Drupal::entityTypeManager()->getStorage('storage')->load($batch_logical_queue_id);
/** @var \Drupal\storage\Entity\Storage $batch_logical_queue */
$batch_logical_queue = $this->entityTypeManager->getStorage('storage')->load($batch_logical_queue_id);
$batch_logical_queue_max_runtime = $batch_logical_queue->get(SystemDrupalIds::SYSTEM_BLQ_MAX_TIME)->getValue()[0]['value'];
$batch_logical_queue_max_nodes = $batch_logical_queue->get(SystemDrupalIds::SYSTEM_BLQ_MAX_NODES)->getValue()[0]['value'];
$batch_logical_queue_max_cores_per_node = $batch_logical_queue->get(SystemDrupalIds::SYSTEM_BLQ_MAX_CORES_PER_NODE)->getValue()[0]['value'];
$batch_logical_queue_max_memory_per_node = $batch_logical_queue->get(SystemDrupalIds::SYSTEM_BLQ_MAX_MEMORY)->getValue()[0]['value'];
$user_can_override_num_nodes = boolval($app->get(AppDrupalIds::OVERRIDE_NUM_NODES)->getValue()[0]['value']);
$user_can_override_cores_per_node = boolval($app->get(AppDrupalIds::OVERRIDE_CORES_PER_NODE)->getValue()[0]['value']);
$user_can_override_memory = boolval($app->get(AppDrupalIds::OVERRIDE_MEMORY)->getValue()[0]['value']);
$user_can_override_max_runtime = boolval($app->get(AppDrupalIds::OVERRIDE_MAX_RUNTIME)->getValue()[0]['value']);
if ($user_can_override_num_nodes) {
$num_nodes = $form_state->getValue(AppDrupalIds::APP_NUM_NODES);
if ($num_nodes > $batch_logical_queue_max_nodes) {
$form_state->setErrorByName(AppDrupalIds::APP_NUM_NODES, $this->t("The number of nodes you specified is greater than the maximum number of nodes allowed for this batch logical queue."));
}
}
if ($user_can_override_cores_per_node) {
$cores_per_node = $form_state->getValue(AppDrupalIds::APP_CORES_PER_NODE);
if ($cores_per_node && ($cores_per_node > $batch_logical_queue_max_cores_per_node)) {
$form_state->setErrorByName(AppDrupalIds::APP_CORES_PER_NODE, $this->t("The number of cores per node you specified is greater than the maximum number of cores per node allowed for this batch logical queue."));
}
}
if ($user_can_override_memory) {
$memory = $form_state->getValue(AppDrupalIds::APP_MEMORY_MB);
if ($memory && ($memory > $batch_logical_queue_max_memory_per_node)) {
$form_state->setErrorByName(AppDrupalIds::APP_MEMORY_MB, $this->t("The amount of memory you specified is greater than the maximum amount of memory allowed for this batch logical queue."));
}
}
if ($user_can_override_max_runtime) {
$max_runtime = $form_state->getValue(AppDrupalIds::APP_MAX_MINUTES);
if ($max_runtime && ($max_runtime > $batch_logical_queue_max_runtime)) {
$form_state->setErrorByName(AppDrupalIds::APP_MAX_MINUTES, $this->t("The maximum runtime you specified is greater than the maximum runtime allowed for this batch logical queue."));
}
}
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
try {
// /** @var \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface */
// $tapisJobProvider = \Drupal::service("tapis_job.tapis_job_provider");
$app_id = $form_state->get("app_id");
$tapis_job_id = $form_state->get("tapis_job_id");
/** @var \Drupal\node\NodeInterface $app */
// $app = \Drupal::entityTypeManager()
// ->getStorage('node')->load($app_id);
$app = $this->entityTypeManager->getStorage('node')->load($app_id);
$tenantId = $app->get(AppDrupalIds::APP_TENANT)->first()->getValue()['target_id'];
$useBatchScheduler = boolval($app->get(AppDrupalIds::APP_USE_BATCH_SCHEDULER)->getValue()[0]['value']);
// $original_job = \Drupal::entityTypeManager()->getStorage('tapis_job')->load($tapis_job_id);
/** @var \Drupal\tapis_job\TapisJobInterface $original_job */
$original_job = $this->entityTypeManager->getStorage('tapis_job')->load($tapis_job_id);
$originalJobUUID = $original_job->getTapisUUID();
$originalJobObject = $this->tapisJobProvider->getJob($tenantId, $originalJobUUID, $original_job->getOwnerId());
$originalJobExecDir = $originalJobObject['execSystemExecDir'];
$appInputType = $app->get(AppDrupalIds::APP_INPUT_TYPE)->getValue()[0]['value'];
if ($appInputType === "flexible_parameters") {
return;
}
$jobName = $form_state->getValue("job_name") ?? $app->getTitle();
$appType = $app->get(AppDrupalIds::APP_TYPE)->getValue()[0]['value'];
$system_id = $form_state->getValue("system");
// $system = \Drupal::entityTypeManager()
// ->getStorage('node')->load($system_id);
$system = $this->entityTypeManager->getStorage('node')->load($system_id);
$systemTapisId = $system->get(SystemDrupalIds::SYSTEM_TAPIS_ID)->getValue()[0]['value'];
$batch_logical_queue_id = $form_state->getValue("batch_logical_queue_id");
if ($batch_logical_queue_id) {
// $batch_logical_queue_entity = \Drupal::entityTypeManager()->getStorage('storage')->load($batch_logical_queue_id);
/** @var \Drupal\storage\Entity\Storage $batch_logical_queue_entity */
$batch_logical_queue_entity = $this->entityTypeManager->getStorage('storage')->load($batch_logical_queue_id);
$batch_logical_queue_id = $batch_logical_queue_entity->getName();
}
$batch_allocation_id = $form_state->getValue("batch_allocation_id");
/** @var \Drupal\tapis_job\Entity\TapisJob $job */
// $job = \Drupal::entityTypeManager()->getStorage('tapis_job')->create([
// 'uid' => ['target_id' => \Drupal::currentUser()->id()],
$job = $this->entityTypeManager->getStorage('tapis_job')->create([
'tenant' => ['target_id' => $tenantId],
'app' => ['target_id' => $app_id],
'system' => ['target_id' => $system_id],
'label' => $jobName,
'uid' => ['target_id' => $this->currentUser->id()],
]);
if ($useBatchScheduler && $batch_logical_queue_id) {
$job->setCustomProperties([
'execSystemLogicalQueue' => $batch_logical_queue_id,
]);
}
if ($useBatchScheduler && $batch_allocation_id) {
$job->setAllocationId($batch_allocation_id);
}
if ($appType === "web" || $appType === "vnc") {
$proxyId = $this->tapisJobProvider->createNewSatelliteToken($tenantId);
$job->setProxyId($proxyId);
}
// Custom job resources.
$user_can_override_num_nodes = boolval($app->get(AppDrupalIds::OVERRIDE_NUM_NODES)->getValue()[0]['value']);
$user_can_override_cores_per_node = boolval($app->get(AppDrupalIds::OVERRIDE_CORES_PER_NODE)->getValue()[0]['value']);
$user_can_override_memory = boolval($app->get(AppDrupalIds::OVERRIDE_MEMORY)->getValue()[0]['value']);
$user_can_override_max_runtime = boolval($app->get(AppDrupalIds::OVERRIDE_MAX_RUNTIME)->getValue()[0]['value']);
$customJobResources = [];
if ($user_can_override_num_nodes) {
// Num nodes.
$customJobResources[AppDrupalIds::APP_NUM_NODES] = $form_state->getValue(AppDrupalIds::APP_NUM_NODES);
}
if ($user_can_override_cores_per_node) {
// Cores per node.
$customJobResources[AppDrupalIds::APP_CORES_PER_NODE] = $form_state->getValue(AppDrupalIds::APP_CORES_PER_NODE);
}
if ($user_can_override_max_runtime) {
// Max runtime.
$customJobResources[AppDrupalIds::APP_MAX_MINUTES] = $form_state->getValue(AppDrupalIds::APP_MAX_MINUTES);
}
if ($user_can_override_memory) {
// Max memory.
$customJobResources[AppDrupalIds::APP_MEMORY_MB] = $form_state->getValue(AppDrupalIds::APP_MEMORY_MB);
}
$job->setCustomJobResources($customJobResources);
$this->tapisJobProvider->backupJobFilesBeforeRestart($tenantId, $systemTapisId, $originalJobUUID, $originalJobExecDir, $original_job->getOwnerId());
$job->setOriginalJobForRestart($original_job);
$tapisJobDefinition = $job->toJSON();
$job->setTapisDefinition($tapisJobDefinition);
$job->save();
$form_state->setRedirect('entity.tapis_job.canonical', ['tapis_job' => $job->id()]);
}
catch (\Exception | \Throwable $e) {
if ($e instanceof TapisException || strpos(strtolower($e->getMessage()), 'tapis') !== FALSE) {
if ($e instanceof TapisException) {
$exception_message = "The app could not be launched: " . $e->getPrimaryMessage() ?: "The app could not be launched.";
}
else {
$exception_message = "The app could not be launched.";
}
$details = [
'#type' => 'details',
'#title' => 'Additional Details',
'#open' => FALSE,
'#children' => $e->getMessage(),
];
$container = [
'#type' => 'container',
'#attributes' => ['class' => ['my-message-container']],
'#children' => [
'message' => [
'#markup' => $exception_message,
// Add a <p> tag before the message text.
'#prefix' => '<p>',
// Add a </p> tag after the message text.
'#suffix' => '</p>',
],
'details' => $details,
],
];
$this
->messenger()
->addError($container);
}
else {
$this
->messenger()
->addError($this
->t("The app could not be launched. Please try again."));
}
$form_state
->setRebuild();
}
}
}
