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();
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc