Commit 3272b2f6 authored by xiaohua guan's avatar xiaohua guan Committed by Yas Naoi
Browse files

Issue #3313353 by Xiaohua Guan, yas: Add the OpenStack Port edit form

parent 1c24294a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -645,7 +645,7 @@ class OpenStackPort extends CloudContentEntityBase implements OpenStackPortInter
    return [
      'normal' => t('Normal'),
      'direct' => t('Direct'),
      'direct_physical' => t('Direct Physical'),
      'direct-physical' => t('Direct Physical'),
      'macvtap' => t('MacVTap'),
      'baremetal' => t('Bare Metal'),
      'virtio-forwarder' => t('Virtio Forwarder'),
+1 −1
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ class OpenStackPortCreateForm extends AwsCloudContentForm {
      '#states'        => [
        'visible' => [
          [
            ':input[name=port_security]' => ['checked' => TRUE],
            ':input[name=port_security_enabled]' => ['checked' => TRUE],
          ],
        ],
      ],
+287 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\openstack\Form;

use Drupal\openstack\Service\OpenStackServiceFactoryInterface;
use Drupal\aws_cloud\Form\Ec2\AwsCloudContentForm;
use Drupal\aws_cloud\Service\AwsCloud\AwsCloudOperationsServiceInterface;
use Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface;
use Drupal\aws_cloud\Traits\AwsCloudFormTrait;
use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
use Drupal\cloud\Service\EntityLinkRendererInterface;
use Drupal\cloud\Service\Util\EntityLinkWithNameHtmlGenerator;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
use Drupal\Core\Render\Renderer;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\cloud\Service\CloudServiceInterface;
use Drupal\cloud\Traits\CloudContentEntityTrait;
use Drupal\openstack\Entity\OpenStackPort;
use Drupal\openstack\Traits\OpenStackFormTrait;
use Drupal\openstack\Service\OpenStackOperationsServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form controller for the Port entity edit form.
 *
 * @ingroup openstack
 */
class OpenStackPortEditForm extends AwsCloudContentForm {

  use AwsCloudFormTrait;
  use CloudContentEntityTrait;
  use OpenStackFormTrait;

  /**
   * The OpenStack Service Factory.
   *
   * @var \Drupal\openstack\Service\OpenStackServiceFactoryInterface
   */
  protected $openStackServiceFactory;

  /**
   * The OpenStack operations Service.
   *
   * @var \Drupal\openstack\Service\OpenStackOperationsServiceInterface
   */
  protected $openStackOperationsService;

  /**
   * OpenStackPortCreateForm constructor.
   *
   * @param \Drupal\aws_cloud\Service\AwsCloud\AwsCloudOperationsServiceInterface $aws_cloud_operations_service
   *   The AWS Cloud Operations service.
   * @param \Drupal\openstack\Service\OpenStackServiceFactoryInterface $openstack_service_factory
   *   Object for interfacing with OpenStack Service.
   * @param \Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface $ec2_service
   *   The AWS Cloud or OpenStack EC2 Service.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Messenger\Messenger $messenger
   *   The Messenger Service.
   * @param \Drupal\cloud\Service\EntityLinkRendererInterface $entity_link_renderer
   *   The entity link render service.
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   The Entity Type Manager.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cacheRender
   *   A cache backend interface instance.
   * @param \Drupal\Core\Plugin\CachedDiscoveryClearerInterface $plugin_cache_clearer
   *   A plugin cache clear instance.
   * @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
   *   The cloud service provider plugin manager (CloudConfigPluginManager).
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter.
   * @param \Drupal\Core\Render\Renderer $renderer
   *   The general renderer.
   * @param \Drupal\cloud\Service\CloudServiceInterface $cloud_service
   *   The Cloud service.
   * @param \Drupal\openstack\Service\OpenStackOperationsServiceInterface $openstack_operations_service
   *   The OpenStack Operations service.
   */
  public function __construct(
    AwsCloudOperationsServiceInterface $aws_cloud_operations_service,
    OpenStackServiceFactoryInterface $openstack_service_factory,
    Ec2ServiceInterface $ec2_service,
    EntityRepositoryInterface $entity_repository,
    EntityTypeBundleInfoInterface $entity_type_bundle_info,
    TimeInterface $time,
    Messenger $messenger,
    EntityLinkRendererInterface $entity_link_renderer,
    EntityTypeManager $entity_type_manager,
    CacheBackendInterface $cacheRender,
    CachedDiscoveryClearerInterface $plugin_cache_clearer,
    CloudConfigPluginManagerInterface $cloud_config_plugin_manager,
    AccountInterface $current_user,
    RouteMatchInterface $route_match,
    DateFormatterInterface $date_formatter,
    Renderer $renderer,
    CloudServiceInterface $cloud_service,
    OpenStackOperationsServiceInterface $openstack_operations_service) {

    parent::__construct(
      $ec2_service,
      $entity_repository,
      $entity_type_bundle_info,
      $time,
      $messenger,
      $entity_link_renderer,
      $entity_type_manager,
      $cacheRender,
      $plugin_cache_clearer,
      $cloud_config_plugin_manager,
      $current_user,
      $route_match,
      $date_formatter,
      $renderer,
      $cloud_service
    );

    $this->openStackServiceFactory = $openstack_service_factory;
    $this->openStackOperationsService = $openstack_operations_service;
  }

  /**
   * Dependency Injection.
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   Instance of ContainerInterface.
   *
   * @return \Drupal\openstack\Entity\OpenStackPortEditForm
   *   return created object.
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('aws_cloud.operations'),
      $container->get('openstack.factory'),
      $container->get('openstack.ec2'),
      $container->get('entity.repository'),
      $container->get('entity_type.bundle.info'),
      $container->get('datetime.time'),
      $container->get('messenger'),
      $container->get('entity.link_renderer'),
      $container->get('entity_type.manager'),
      $container->get('cache.render'),
      $container->get('plugin.cache_clearer'),
      $container->get('plugin.manager.cloud_config_plugin'),
      $container->get('current_user'),
      $container->get('current_route_match'),
      $container->get('date.formatter'),
      $container->get('renderer'),
      $container->get('cloud'),
      $container->get('openstack.operations')
    );
  }

  /**
   * Overrides Drupal\Core\Entity\EntityFormController::buildForm().
   *
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   * @param string $cloud_context
   *   A cloud_context string value from URL "path".
   *
   * @return array
   *   Array of form object.
   */
  public function buildForm(array $form, FormStateInterface $form_state, $cloud_context = ''): array {
    // Switch OpenStack EC2 or REST service based on $cloud_context.
    $this->ec2Service = $this->openStackServiceFactory->get($cloud_context);
    $form = parent::buildForm($form, $form_state, $cloud_context);
    $entity = $this->entity;

    $entity = $this->entity;
    if (!$this->updateEntityBuildForm($entity)) {
      return $this->redirectUrl;
    }

    $weight = -50;

    $form['port'] = [
      '#type' => 'details',
      '#title' => $this->t('@title', ['@title' => $entity->getEntityType()->getSingularLabel()]),
      '#open' => TRUE,
      '#weight' => $weight++,
    ];

    $form['port']['name'] = [
      '#type'          => 'textfield',
      '#title'         => $this->t('Name'),
      '#maxlength'     => 255,
      '#size'          => 60,
      '#default_value' => $entity->label(),
      '#weight'        => -5,
      '#required'      => TRUE,
    ];

    $form['port']['network_id'] = $this->entityLinkRenderer->renderFormElements(
      $entity->getNetworkId(),
      'openstack_network',
      'network_id',
      ['#title' => $this->getItemTitle($this->t('Network'))],
      '',
      EntityLinkWithNameHtmlGenerator::class
    );

    $form['port']['admin_state_up'] = [
      '#type'          => 'checkbox',
      '#title'         => $this->t('Enable Admin State'),
      '#description'   => $this->t('When the admin state of the port is enabled, the networking service forward packets on the port. Otherwise, it does not forward any packets on the port.'),
      '#default_value' => $entity->getAdminStateUp(),
      '#weight'        => -5,
      '#required'      => FALSE,
    ];

    $form['port']['binding_vnic_type'] = [
      '#type'          => 'select',
      '#title'         => $this->t('VNIC Type'),
      '#description'   => $this->t('The VNIC type that is bound to the port.'),
      '#options'       => OpenStackPort::getVnicTypeAllowedValues(),
      '#default_value' => $entity->getBindingVnicType(),
      '#required'      => FALSE,
    ];

    $form['port']['port_security_enabled'] = [
      '#type'          => 'checkbox',
      '#title'         => $this->t('Port Security'),
      '#description'   => $this->t('Enable security rules for the port.'),
      '#default_value' => $entity->getPortSecurityEnabled(),
      '#required'      => FALSE,
    ];

    $default_values = [];
    foreach ($entity->getSecurityGroups() ?: [] as $item) {
      $default_values[] = $item['value'];
    }
    $options = $this->getSecurityGroupOptions($cloud_context);
    $form['port']['security_groups'] = [
      '#type'          => 'select',
      '#title'         => $this->t('Security Group'),
      '#options'       => $options,
      '#multiple'      => TRUE,
      '#default_value' => $default_values,
      '#required'      => FALSE,
      '#states'        => [
        'visible' => [
          [
            ':input[name=port_security_enabled]' => ['checked' => TRUE],
          ],
        ],
      ],
    ];

    $this->addOthersFieldset($form, $weight++, $cloud_context);

    return $form;
  }

  /**
   * Submit handler.
   *
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   */
  public function save(array $form, FormStateInterface $form_state): void {
    $this->openStackOperationsService->editOpenStackPort($this->entity, $form, $form_state);
  }

}
+69 −4
Original line number Diff line number Diff line
@@ -1204,13 +1204,13 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
      // Delete old tags.
      $this->ec2Service->deleteTags(
        [
          'NetworkId' => $entity->getNetworkId(),
          'NetworkId'   => $entity->getSubnetId(),
          'EntityType'  => $entity->getEntityTypeId(),
        ]);
      $this->awsCloudOperationsService->updateNameAndCreatedByTags($entity, $entity->getNetworkId());
      $this->awsCloudOperationsService->updateNameAndCreatedByTags($entity, $entity->getSubnetId());
    }

    // Update the Network entity.
    // Update the Subnet entity.
    $this->ec2Service->updateSubnets([
      'SubnetId' => $entity->getSubnetId(),
    ]);
@@ -1223,6 +1223,71 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function editOpenStackPort(OpenStackPortInterface $entity, array &$form, FormStateInterface $form_state): bool {
    $this->entity = $entity;

    $this->ec2Service = $this->openStackServiceFactory->get($entity->getCloudContext());
    $this->awsCloudOperationsService->setEc2Service($this->ec2Service);

    $this->awsCloudOperationsService->trimTextfields($entity, $form, $form_state);

    $form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);

    $this->ec2Service->setCloudContext($entity->getCloudContext());

    $params = [
      'PortId' => $entity->getPortId(),
      'Name' => $entity->getName(),
      'AdminStateUp' => $entity->getAdminStateUp(),
      'BindingVnicType' => $entity->getBindingVnicType(),
    ];

    // Port security.
    $params['PortSecurityEnabled'] = !empty($entity->getPortSecurityEnabled());
    $params['SecurityGroups'] = !empty($entity->getPortSecurityEnabled())
      ? array_keys($form_state->getValue('security_groups'))
      : [];

    $result = $this->ec2Service->updatePort($params);

    if ($result === NULL) {
      $this->processOperationErrorStatus($entity, 'updated');
      return FALSE;
    }

    if (!empty($result['SendToWorker'])) {
      $this->processOperationStatus($entity, 'updated remotely');
      return TRUE;
    }

    $entity->save();

    if ($this->ec2Service instanceof OpenStackRestService) {
      // Delete old tags.
      $this->ec2Service->deleteTags(
        [
          'PortId'     => $entity->getPortId(),
          'EntityType' => $entity->getEntityTypeId(),
        ]);
      $this->awsCloudOperationsService->updateNameAndCreatedByTags($entity, $entity->getPortId());
    }

    // Update the Port entity.
    $this->ec2Service->updatePorts([
      'PortId' => $entity->getPortId(),
    ]);

    $this->processOperationStatus($entity, 'updated');

    $this->clearCacheValues($entity->getCacheTags());
    $this->dispatchSaveEvent($entity);

    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
+15 −0
Original line number Diff line number Diff line
@@ -305,6 +305,21 @@ interface OpenStackOperationsServiceInterface {
   */
  public function editOpenStackSubnet(OpenStackSubnetInterface $entity, array &$form, FormStateInterface $form_state): bool;

  /**
   * Edit an OpenStack Port.
   *
   * @param \Drupal\openstack\Entity\OpenStackPortInterface $entity
   *   The OpenStack network entity.
   * @param array $form
   *   Array of form object.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current form state.
   *
   * @return bool
   *   TRUE when the process succeeds.
   */
  public function editOpenStackPort(OpenStackPortInterface $entity, array &$form, FormStateInterface $form_state): bool;

  /**
   * Delete an OpenStack Network.
   *
Loading