cloud-8.x-2.0-beta1/modules/cloud_service_providers/aws_cloud/src/Form/Ec2/ElasticIpAssociateForm.php

modules/cloud_service_providers/aws_cloud/src/Form/Ec2/ElasticIpAssociateForm.php
<?php

namespace Drupal\aws_cloud\Form\Ec2;

use Drupal\aws_cloud\Entity\Ec2\Instance;
use Drupal\aws_cloud\Entity\Ec2\NetworkInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Associate Elastic IP address.
 */
class ElasticIpAssociateForm extends AwsDeleteForm {

  /**
   * {@inheritdoc}
   */
  public function getQuestion() {
    /* @var \Drupal\aws_cloud\Entity\Ec2\ElasticIp $entity */
    $entity = $this->entity;
    return $this->t('Select the instance OR network interface to which you want to associate this Elastic IP address (@ip_address).', [
      '@ip_address' => $entity->getPublicIp(),
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription() {
    return '';
  }

  /**
   * {@inheritdoc}
   */
  public function getConfirmText() {
    return t('Associate');
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    if ($this->entity->getAssociationId() != NULL) {
      $form['error'] = [
        '#markup' => '<div>' . $this->t('Elastic IP is already associated.') . '</div>',
      ];
      unset($form['actions']['submit']);
    }
    else {
      $form['#attached']['library'][] = 'aws_cloud/aws_cloud_elastic_ips';
      $form['resource_type'] = [
        '#type' => 'select',
        '#title' => $this->t('Resource type'),
        '#options' => [
          'instance' => $this->t('Instance'),
          'network_interface' => $this->t('Network Interface'),
        ],
        '#description' => $this->t('Choose the type of resource to which to associate the Elastic IP address.'),
        '#default_value' => 'instance',
      ];

      $form['instance_ip_container'] = [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'instance-ip-container',
        ],
      ];

      $form['instance_ip_container']['instance_id'] = [
        '#type' => 'select',
        '#title' => $this->t('Instance'),
        '#options' => $this->getUnassociatedInstances(),
        '#ajax' => [
          'callback' => '::getPrivateIpsAjaxCallback',
          'event' => 'change',
          'wrapper' => 'instance-ip-container',
          'progress' => [
            'type' => 'throbber',
            'message' => $this->t('Retrieving...'),
          ],
        ],
      ];

      $form['instance_ip_container']['instance_private_ip'] = [
        '#type' => 'select',
        '#title' => $this->t('Private IP'),
        '#description' => $this->t('The private IP address to which to associate the Elastic IP address. Only private IP addresses that do not already have an Elastic IP associated with them are available.'),
        '#options' => [
          '-1' => $this->t('Select a private IP.'),
        ],
      ];

      $form['network_interface_ip_container'] = [
        '#type' => 'container',
        '#attributes' => [
          'id' => 'network-interface-ip-container',
        ],
      ];

      $form['network_interface_ip_container']['network_interface_id'] = [
        '#type' => 'select',
        '#title' => $this->t('Network interface'),
        '#options' => $this->getUnassociatedNetworkInterfaces(),
        '#ajax' => [
          'callback' => '::getNetworkIpsAjaxCallback',
          'event' => 'change',
          'wrapper' => 'network-interface-ip-container',
          'progress' => [
            'type' => 'throbber',
            'message' => $this->t('Retrieving...'),
          ],
        ],
      ];
      $form['network_interface_ip_container']['network_private_ip'] = [
        '#type' => 'select',
        '#title' => $this->t('Private IP'),
        '#description' => $this->t('The private IP address to which to associate the Elastic IP address. Only private IP addresses that do not already have an Elastic IP associated with them are available.'),
        '#options' => [
          '-1' => $this->t('Select a private IP.'),
        ],
      ];

      // Ajax support: Look at the instance value, and rebuild the private_ip
      // options.
      $instance = $form_state->getValue('instance_id');
      if (isset($instance)) {
        if ($instance != -1) {
          $ips = $this->getPrivateIps($instance);
          $form['instance_ip_container']['instance_private_ip']['#options'] = $ips;
        }
        else {
          $form['instance_ip_container']['instance_private_ip']['#options'] = [
            '-1' => $this->t('Select a private IP.'),
          ];
        }
      }

      // Ajax support: Look at network interface value and rebuild the private
      // IP portion of the form.
      $network_interface = $form_state->getValue('network_interface_id');
      if (isset($network_interface)) {
        if ($network_interface != -1) {
          $ips = $this->getNetworkPrivateIps($network_interface);
          $form['network_interface_ip_container']['network_private_ip']['#options'] = $ips;
        }
        else {
          $form['network_interface_ip_container']['network_private_ip']['#options'] = [
            '-1' => $this->t('Select a private IP.'),
          ];
        }
      }
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if ($form_state->getValue('resource_type') == 'instance') {
      if ($form_state->getValue('instance_id') == -1) {
        // Error out.
        $form_state->setErrorByName('instance_id', $this->t('Instance ID is empty.'));
      }
      if ($form_state->getValue('instance_private_ip') == -1) {
        // Error out.
        $form_state->setErrorByName('instance_private_ip', $this->t('Private IP is empty.'));
      }
    }
    else {
      if ($form_state->getValue('network_interface_id') == -1) {
        $form_state->setErrorByName('network_interface_id', $this->t('Network interface is empty.'));
      }
      if ($form_state->getValue('network_private_ip') == -1) {
        $form_state->setErrorByName('network_private_ip', $this->t('Private IP is empty.'));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->ec2Service->setCloudContext($this->entity->getCloudContext());

    // Determine if elastic_ip is attaching to instance or network_interface.
    if ($form_state->getValue('resource_type') == 'instance') {
      $instance_id = $form_state->getValue('instance_id');
      $private_ip = $form_state->getValue('instance_private_ip');
      if ($instance_id != -1) {
        $instance = Instance::load($instance_id);

        // Refresh network interfaces.
        $this->ec2Service->updateNetworkInterfaces();

        $network_interface = $this->getNetworkInterfaceByPrivateIp($private_ip);
        if (!empty($network_interface)) {
          $result = $this->ec2Service->associateAddress([
            'AllocationId' => $this->entity->getAllocationId(),
            'NetworkInterfaceId' => $network_interface->getNetworkInterfaceId(),
            'PrivateIpAddress' => $private_ip,
          ]);

          if (!empty($result)) {
            $message = $this->t('Elastic IP @ip_address associated with @private_ip for instance: @instance', [
              '@ip_address' => $this->entity->getPublicIp(),
              '@instance' => $instance->getName(),
              '@private_ip' => $private_ip,
            ]);
            $this->updateElasticIpEntity($message);
            $this->clearCacheValues();
          }
          else {
            $this->messenger->addError($this->t('Unable to associate Elastic IP.'));
          }
        }
        else {
          $this->messenger->addError($this->t('Unable to load network interface by private IP.'));
        }
      }
      else {
        $this->messenger->addError($this->t('Unable to load instance ID. No association performed.'));
      }
    }
    else {
      $network_interface_id = $form_state->getValue('network_interface_id');
      $network_private_ip = $form_state->getValue('network_private_ip');

      if ($network_interface_id != -1) {
        $network_interface = NetworkInterface::load($network_interface_id);
        $result = $this->ec2Service->associateAddress([
          'AllocationId' => $this->entity->getAllocationId(),
          'NetworkInterfaceId' => $network_interface->getNetworkInterfaceId(),
          'PrivateIpAddress' => $network_private_ip,
        ]);

        if ($result != NULL) {
          $message = $this->t('Elastic IP @ip_address associated with @private_ip for network interface: @network_interface_id', [
            '@ip_address' => $this->entity->getPublicIp(),
            '@network_interface_id' => $network_interface->getNetworkInterfaceId(),
            '@private_ip' => $network_private_ip,
          ]);
          $this->updateElasticIpEntity($message);
          $this->clearCacheValues();
        }
        else {
          $this->messenger->addError($this->t('Unable to associate Elastic IP.'));
        }
      }
      else {
        $this->messenger->addError($this->t('Unable to load instance ID. No association performed.'));
      }
    }

    $form_state->setRedirect('entity.aws_cloud_elastic_ip.canonical', [
      'cloud_context' => $this->entity->getCloudContext(),
      'aws_cloud_elastic_ip' => $this->entity->id(),
    ]);
  }

  /**
   * Helper function to update the current aws_cloud_elastic_ip entity.
   *
   * @param string $message
   *   Message to display to use.
   */
  private function updateElasticIpEntity($message) {
    $this->messenger->addMessage($message);

    // Update the following entities from EC2.
    $this->ec2Service->updateElasticIp();
    $this->ec2Service->updateInstances();
    $this->ec2Service->updateNetworkInterfaces();
  }

  /**
   * Ajax callback when the instance dropdown changes.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state interface element.
   *
   * @return mixed
   *   Form element for instance_ip_container.
   */
  public function getPrivateIpsAjaxCallback(array $form, FormStateInterface $form_state) {
    return $form['instance_ip_container'];
  }

  /**
   * Ajax callback when the network interface dropdown changes.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state interface element.
   *
   * @return mixed
   *   Form element for network_interface_ip_container.
   */
  public function getNetworkIpsAjaxCallback(array $form, FormStateInterface $form_state) {
    return $form['network_interface_ip_container'];
  }

  /**
   * Helper function that loads all the private IPs for an instance.
   *
   * @param int $instance_id
   *   The instance ID.
   *
   * @return array
   *   An array of IP addresses.
   */
  private function getPrivateIps($instance_id) {
    $instance = Instance::load($instance_id);
    $ips = explode(', ', $instance->getPrivateIps());
    foreach ($ips as $ip) {
      // Check if the IP is in the Elastic IP table.
      $result = $this->entityTypeManager
        ->getStorage('aws_cloud_elastic_ip')
        ->loadByProperties([
          'private_ip_address' => $ip,
        ]);

      if (count($result) == 0) {
        $private_ips[$ip] = $ip;
      }
    }
    return $private_ips;
  }

  /**
   * Helper function to load primary and secondary private IPs.
   *
   * @param int $network_interface_id
   *   The network interface ID.
   *
   * @return array
   *   An array of IP addresses.
   */
  private function getNetworkPrivateIps($network_interface_id) {
    /* @var \Drupal\aws_cloud\Entity\Ec2\NetworkInterface $network_interface */
    $network_interface = NetworkInterface::load($network_interface_id);
    $association_id = $network_interface->getAssociationId();
    $secondary_association_id = $network_interface->getSecondaryAssociationId();
    if (is_null($association_id)) {
      $ips[$network_interface->getPrimaryPrivateIp()] = $network_interface->getPrimaryPrivateIp();
    }
    if (is_null($secondary_association_id) && !empty($network_interface->getSecondaryPrivateIps())) {
      $ips[$network_interface->getSecondaryPrivateIps()] = $network_interface->getSecondaryPrivateIps();
    }
    return $ips;
  }

  /**
   * Query the database for instances that do not have Elastic IPs.
   *
   * @return array
   *   An array of instances formatted for a dropdown.
   */
  private function getUnassociatedInstances() {
    $instances['-1'] = $this->t('Select an instance.');
    $account = \Drupal::currentUser();

    $query = $this->entityTypeManager
      ->getStorage('aws_cloud_instance')
      ->getQuery()
      ->condition('cloud_context', $this->entity->getCloudContext());

    if (!$account->hasPermission('view any aws cloud instance')) {
      $query->condition('uid', $account->id());
    }

    $results = $query->execute();

    foreach ($results as $result) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\Instance $instance */
      $instance = Instance::load($result);
      $private_ips = explode(', ', $instance->getPrivateIps());

      foreach ($private_ips as $private_ip) {
        $elastic_ips = $this->entityTypeManager
          ->getStorage('aws_cloud_elastic_ip')
          ->loadbyProperties([
            'private_ip_address' => $private_ip,
          ]);
        if (count($elastic_ips) == 0) {
          /* @var \Drupal\aws_cloud\Entity\Ec2\Instance $result */
          $instances[$instance->id()] = $this->t('%name - %instance_id', [
            '%name' => $instance->getName(),
            '%instance_id' => $instance->getInstanceId(),
          ]);
        }
      }
    }
    return $instances;
  }

  /**
   * Get a network interface given a private_ip address.
   *
   * @param string $private_ip
   *   The private IP used to look up the network interface.
   *
   * @return bool|mixed
   *   False if no network interface found.  The network interface object if
   *   found.
   */
  private function getNetworkInterfaceByPrivateIp($private_ip) {
    $network_interface = FALSE;
    $results = $this->entityTypeManager
      ->getStorage('aws_cloud_network_interface')
      ->loadByProperties([
        'primary_private_ip' => $private_ip,
      ]);
    if (count($results) == 1) {
      $network_interface = array_shift($results);
    }
    return $network_interface;
  }

  /**
   * Query the database for unassociated network interfaces IPs.
   *
   * @return array
   *   An array of instances formatted for a dropdown.
   */
  private function getUnassociatedNetworkInterfaces() {
    $interfaces['-1'] = $this->t('Select a network interface.');
    $results = $this->entityTypeManager
      ->getStorage('aws_cloud_network_interface')
      ->getQuery('OR')
      ->notExists('association_id')
      ->notExists('secondary_association_id')
      ->execute();

    foreach ($results as $result) {
      /* @var \Drupal\aws_cloud\Entity\Ec2\NetworkInterface $interface */
      $interface = NetworkInterface::load($result);
      if ($interface->getCloudContext() == $this->entity->getCloudContext()) {
        $interfaces[$interface->id()] = $this->t('%name - %interface_id', [
          '%name' => $interface->getName(),
          '%interface_id' => $interface->getNetworkInterfaceId(),
        ]);
      }
    }
    return $interfaces;
  }

}

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

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