Skip to content
Snippets Groups Projects
Commit 6aec28d4 authored by Ryo Yamashita's avatar Ryo Yamashita Committed by Yas Naoi
Browse files

Issue #3283743 by Ryo Yamashita, yas: Add the function to delete OpenStack Instance in the SPA

parent 0a73135a
Branches
Tags
3 merge requests!1316Issue #3310263: Release 4.5.0,!1260Issue #3307397: Release 4.4.0,!1013Issue #3283743: Add the function to delete Openstack Instance in the SPA
......@@ -4,6 +4,7 @@ import K8S_OTHER_TEMPLATE from 'constant/form_template/k8s/other';
import K8S_POD_TEMPLATE from 'constant/form_template/k8s/pod';
import K8S_SCHEDULE_TEMPLATE from 'constant/form_template/k8s/schedule';
import OPENSTACK_IMAGE_TEMPLATE from 'constant/form_template/openstack/image';
import OPENSTACK_INSTANCE_TEMPLATE from 'constant/form_template/openstack/instance';
import OPENSTACK_KEY_PAIR_TEMPLATE from 'constant/form_template/openstack/key_pair';
import VMWARE_VM_TEMPLATE from 'constant/form_template/vmware/vm';
......@@ -14,6 +15,7 @@ const ENTITY_FORM_LIST = [
...K8S_SCHEDULE_TEMPLATE,
// K8S_OTHER_TEMPLATE must be registered after the other K8S_XXX_TEMPLATE.
...K8S_OTHER_TEMPLATE,
...OPENSTACK_INSTANCE_TEMPLATE,
...OPENSTACK_IMAGE_TEMPLATE,
...OPENSTACK_KEY_PAIR_TEMPLATE,
...VMWARE_VM_TEMPLATE,
......
import EntityFormTemplate from 'model/EntityFormTemplate';
const OPENSTACK_INSTANCE_TEMPLATE: EntityFormTemplate[] = [
{
cloudServiceProvider: 'openstack',
entityName: 'instance',
actionType: 'delete',
entityRecords: [
{
type: 'label',
text: 'Are you sure you want to delete the {{name}} {{entityName}}?'
},
],
submitButtonLabel: 'Delete'
}
]
export default OPENSTACK_INSTANCE_TEMPLATE;
......@@ -470,6 +470,20 @@ entity.openstack_entity.count_all:
# OpenStack CxUD REST API.
entity.openstack_instance.delete:
path: '/cloud_dashboard/openstack/{cloud_context}/openstack_instance/{entity_id}/delete'
defaults:
_controller: '\Drupal\openstack\Controller\ApiController::operateEntity'
entity_type_id: openstack_instance
command: delete
methods: [POST]
requirements:
# Use custom access that will check for cloud_context and the desired permission.
# Desired permission is passed as an option in the "perm" variable
_custom_access: '\Drupal\cloud\Controller\CloudConfigController::access'
options:
perm: 'delete any openstack instance+delete own openstack instance'
entity.openstack_image.create:
path: '/cloud_dashboard/openstack/{cloud_context}/openstack_image/create'
defaults:
......
......@@ -514,6 +514,10 @@ class ApiController extends ControllerBase implements ApiControllerInterface {
$form_state = new IntermediateFormState();
$method_name = '';
switch ($command . '_' . $entity_type_id) {
case 'delete_openstack_instance':
$method_name = 'deleteOpenStackInstance';
break;
case 'create_openstack_image':
$original_entity->setName($request->get('name', ''));
$original_entity->setVisibility(!empty($request->get('visibility', '')) ? 'public' : 'private');
......
......@@ -15,7 +15,7 @@ use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
use Drupal\openstack\Service\Ec2\OpenStackService as OpenStackEc2Service;
use Drupal\openstack\Service\OpenStackOperationsServiceInterface;
use Drupal\openstack\Service\OpenStackServiceFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -33,6 +33,13 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
*/
protected $openStackServiceFactory;
/**
* The OpenStack operations Service.
*
* @var \Drupal\openstack\Service\OpenStackOperationsServiceInterface
*/
protected $openStackOperationsService;
/**
* OpenStackInstanceDeleteForm constructor.
*
......@@ -60,6 +67,8 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
* The entity link render service.
* @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
* The cloud service provider plugin manager (CloudConfigPluginManager).
* @param \Drupal\openstack\Service\OpenStackOperationsServiceInterface $openstack_operations_service
* The OpenStack Operations service.
*/
public function __construct(OpenStackServiceFactoryInterface $openstack_service_factory,
Ec2ServiceInterface $ec2_service,
......@@ -72,7 +81,8 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
CacheBackendInterface $cacheRender,
CachedDiscoveryClearerInterface $plugin_cache_clearer,
EntityLinkRendererInterface $entity_link_renderer,
CloudConfigPluginManagerInterface $cloud_config_plugin_manager) {
CloudConfigPluginManagerInterface $cloud_config_plugin_manager,
OpenStackOperationsServiceInterface $openstack_operations_service) {
parent::__construct(
$ec2_service,
$ec2_operations_service,
......@@ -88,6 +98,7 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
);
$this->openStackServiceFactory = $openstack_service_factory;
$this->openStackOperationsService = $openstack_operations_service;
}
/**
......@@ -112,7 +123,8 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
$container->get('cache.render'),
$container->get('plugin.cache_clearer'),
$container->get('entity.link_renderer'),
$container->get('plugin.manager.cloud_config_plugin')
$container->get('plugin.manager.cloud_config_plugin'),
$container->get('openstack.operations')
);
}
......@@ -126,43 +138,8 @@ class OpenStackInstanceDeleteForm extends InstanceDeleteForm {
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
$entity = $this->entity;
// Switch OpenStack EC2 or Rest service based on $entity->getCloudContext().
$this->ec2Service = $this->openStackServiceFactory->get($entity->getCloudContext());
if ($this->ec2Service instanceof OpenStackEc2Service) {
parent::submitForm($form, $form_state);
return;
}
if (!$this->updateEntitySubmitForm($form_state, $entity)) {
return;
}
$this->ec2Service->setCloudContext($entity->getCloudContext());
$result = $this->ec2Service->terminateInstances([
'InstanceId' => $entity->getInstanceId(),
]);
$form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);
if (empty($result)) {
$this->processOperationErrorStatus($entity, 'deleted');
return;
}
if (!empty($result['SendToWorker'])) {
$this->messenger->addStatus($this->t('The @type @label has been deleted remotely.', [
'@type' => $entity->getEntityType()->getSingularLabel(),
'@label' => $entity->getName(),
]));
return;
}
$this->openStackOperationsService->deleteOpenStackInstance($this->entity, $form, $form_state);
$entity->delete();
$this->messenger->addStatus($this->getDeletionMessage());
$this->logDeletionMessage();
$this->clearCacheValues($entity->getCacheTags());
}
}
......@@ -3,6 +3,7 @@
namespace Drupal\openstack\Service;
use Drupal\aws_cloud\Entity\Ec2\ImageInterface;
use Drupal\aws_cloud\Entity\Ec2\InstanceInterface;
use Drupal\aws_cloud\Entity\Ec2\KeyPairInterface;
use Drupal\aws_cloud\Service\Ec2\Ec2ServiceException;
use Drupal\aws_cloud\Service\Ec2\Ec2ServiceInterface;
......@@ -17,6 +18,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\Messenger;
use Drupal\openstack\Service\Rest\OpenStackService as OpenStackRestService;
use Drupal\openstack\Service\Ec2\OpenStackService as OpenStackEc2Service;
/**
* Interacts with OpenStack using OpenStackService API.
......@@ -254,6 +256,112 @@ class OpenStackOperationsService implements OpenStackOperationsServiceInterface
$original_entity->getEntityTypeId());
}
/**
* Delete an Instance.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
private function deleteInstance(array &$form, FormStateInterface $form_state): bool {
/**
* The entity being used by this form.
*
* @var \Drupal\aws_cloud\Entity\Ec2\InstanceInterface|\Drupal\aws_cloud\Entity\Ec2\Instance
*/
$entity = $this->entity;
if (!$this->updateEntitySubmitForm($form_state, $entity)) {
return FALSE;
}
$this->ec2Service->setCloudContext($entity->getCloudContext());
$result = $this->ec2Service->terminateInstances([
'InstanceIds' => [$entity->getInstanceId()],
]);
if (!empty($result['SendToWorker'])) {
$this->processOperationStatus($entity, 'deleted remotely');
$form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);
return TRUE;
}
if (isset($result['TerminatingInstances'][0]['InstanceId'])) {
$entity->delete();
$this->messenger->addStatus($this->getDeletionMessage());
$this->logDeletionMessage();
$this->clearCacheValues($entity->getCacheTags());
$this->dispatchSubmitEvent($entity);
$form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);
}
else {
$this->processOperationErrorStatus($entity, 'deleted');
}
$form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);
return TRUE;
}
/**
* {@inheritdoc}
*/
public function deleteOpenStackInstance(InstanceInterface $entity, array &$form, FormStateInterface $form_state): bool {
try {
$this->entity = $entity;
// Switch OpenStack service based on $entity->getCloudContext().
$this->ec2Service = $this->openStackServiceFactory->get($entity->getCloudContext());
if ($this->ec2Service instanceof OpenStackEc2Service) {
return $this->deleteInstance($form, $form_state);
}
if (!$this->updateEntitySubmitForm($form_state, $entity)) {
return FALSE;
}
$this->ec2Service->setCloudContext($entity->getCloudContext());
$result = $this->ec2Service->terminateInstances([
'InstanceId' => $entity->getInstanceId(),
]);
$form_state->setRedirect("view.{$entity->getEntityTypeId()}.list", ['cloud_context' => $entity->getCloudContext()]);
if (empty($result)) {
$this->processOperationErrorStatus($entity, 'deleted');
return FALSE;
}
if (!empty($result['SendToWorker'])) {
/** @var \Drupal\aws_cloud\Entity\Ec2\Instance|\Drupal\aws_cloud\Entity\Ec2\InstanceInterface $original_entity */
$original_entity = $entity;
$this->messenger->addStatus($this->t('The @type @label has been deleted remotely.', [
'@type' => $original_entity->getEntityType()->getSingularLabel(),
'@label' => $original_entity->getName(),
]));
return TRUE;
}
$entity->delete();
$this->messenger->addStatus($this->getDeletionMessage());
$this->logDeletionMessage();
$this->clearCacheValues($entity->getCacheTags());
return TRUE;
}
catch (Ec2ServiceException $e) {
$this->handleException($e);
return FALSE;
}
}
/**
* Create an Image.
*
......
......@@ -3,6 +3,7 @@
namespace Drupal\openstack\Service;
use Drupal\aws_cloud\Entity\Ec2\ImageInterface;
use Drupal\aws_cloud\Entity\Ec2\InstanceInterface;
use Drupal\aws_cloud\Entity\Ec2\KeyPairInterface;
use Drupal\Core\Form\FormStateInterface;
......@@ -11,6 +12,21 @@ use Drupal\Core\Form\FormStateInterface;
*/
interface OpenStackOperationsServiceInterface {
/**
* Delete an OpenStack Instance.
*
* @param \Drupal\aws_cloud\Entity\Ec2\InstanceInterface $entity
* The OpenStack image 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 deleteOpenStackInstance(InstanceInterface $entity, array &$form, FormStateInterface $form_state): bool;
/**
* Create an OpenStack image.
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment