diff --git a/modules/cloud_budget/src/Form/CloudBudgetDeleteMultipleForm.php b/modules/cloud_budget/src/Form/CloudBudgetDeleteMultipleForm.php
index 1beb4231..9e2e5e93 100644
--- a/modules/cloud_budget/src/Form/CloudBudgetDeleteMultipleForm.php
+++ b/modules/cloud_budget/src/Form/CloudBudgetDeleteMultipleForm.php
@@ -2,13 +2,13 @@
 
 namespace Drupal\cloud_budget\Form;
 
+use Drupal\cloud\Entity\CloudContentEntityBase;
+use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
+use Drupal\cloud\Traits\CloudDeleteMultipleFormTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TempStore\PrivateTempStoreFactory;
-use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
-use Drupal\cloud\Traits\CloudDeleteMultipleFormTrait;
-use Drupal\cloud\Entity\CloudContentEntityBase;
 
 /**
  * Provides an entities deletion confirmation form.
@@ -18,7 +18,7 @@ class CloudBudgetDeleteMultipleForm extends CloudBudgetProcessMultipleForm {
   use CloudDeleteMultipleFormTrait;
 
   /**
-   * Constructs a new K8sDeleteMultipleForm object.
+   * Constructs a new CloudBudgetProcessMultipleForm object.
    *
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
@@ -44,13 +44,15 @@ class CloudBudgetDeleteMultipleForm extends CloudBudgetProcessMultipleForm {
       $messenger,
       $cloud_config_plugin_manager
     );
+
+    // Set the temp_store_factory.
     $this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
   }
 
   /**
    * {@inheritdoc}
    */
-  protected function processCloudResource(CloudContentEntityBase $entity) {
+  protected function processCloudResource(CloudContentEntityBase $entity) : bool {
     return TRUE;
   }
 
diff --git a/modules/cloud_budget/src/Form/CloudBudgetProcessMultipleForm.php b/modules/cloud_budget/src/Form/CloudBudgetProcessMultipleForm.php
index 8a6d7448..b3bd9c57 100644
--- a/modules/cloud_budget/src/Form/CloudBudgetProcessMultipleForm.php
+++ b/modules/cloud_budget/src/Form/CloudBudgetProcessMultipleForm.php
@@ -5,14 +5,14 @@ namespace Drupal\cloud_budget\Form;
 use Drupal\cloud\Form\CloudProcessMultipleForm;
 
 /**
- * Provides an entities deletion confirmation form.
+ * Provide a confirmation form of bulk operation for cloud budgets.
  */
 abstract class CloudBudgetProcessMultipleForm extends CloudProcessMultipleForm {
 
   /**
    * {@inheritdoc}
    */
-  public function getBaseFormId() {
+  public function getBaseFormId() : string {
 
     return 'cloud_budget_process_multiple_confirm_form';
   }
diff --git a/src/Entity/CloudConfig.php b/src/Entity/CloudConfig.php
index 5249e385..a1f26460 100644
--- a/src/Entity/CloudConfig.php
+++ b/src/Entity/CloudConfig.php
@@ -77,7 +77,7 @@ use Drupal\user\UserInterface;
  *   field_ui_base_route = "entity.cloud_config_type.edit_form"
  * )
  */
-class CloudConfig extends RevisionableContentEntityBase implements CloudConfigInterface, CloudContextInterface {
+class CloudConfig extends CloudContentEntityBase implements CloudConfigInterface, CloudContextInterface {
 
   use EntityChangedTrait;
 
diff --git a/src/Entity/CloudContentEntityBase.php b/src/Entity/CloudContentEntityBase.php
index 6f93b7f4..59bfaf7c 100644
--- a/src/Entity/CloudContentEntityBase.php
+++ b/src/Entity/CloudContentEntityBase.php
@@ -3,7 +3,7 @@
 namespace Drupal\cloud\Entity;
 
 use Drupal\Core\Entity\RevisionableInterface;
-use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\RevisionableContentEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\user\EntityOwnerInterface;
 use Drupal\user\UserInterface;
@@ -14,7 +14,7 @@ use Drupal\user\UserInterface;
  * The main purpose of this class is to provide the
  * cloud_context as a parameter in urlRouteParameters method.
  */
-class CloudContentEntityBase extends ContentEntityBase implements EntityOwnerInterface, CloudContextInterface {
+class CloudContentEntityBase extends RevisionableContentEntityBase implements EntityOwnerInterface, CloudContextInterface {
 
   /**
    * {@inheritdoc}
@@ -132,16 +132,20 @@ class CloudContentEntityBase extends ContentEntityBase implements EntityOwnerInt
    * {@inheritdoc}
    */
   public function save() {
-    $this->updateCache();
+    self::updateCache();
     return parent::save();
   }
 
   /**
    * Clear caches to refresh action links.
    */
-  private function updateCache() {
+  private static function updateCache() {
     // Clear caches to refresh action links.
-    \Drupal::cache('render')->deleteAll();
+    // Clear block and menu cache.
+    \Drupal::cache('menu')->invalidateAll();
+    \Drupal::service('cache.render')->deleteAll();
+    \Drupal::service('router.builder')->rebuild();
+    \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions();
   }
 
 }
diff --git a/src/Entity/CloudServerTemplate.php b/src/Entity/CloudServerTemplate.php
index 3c111d44..d1c2e3ed 100644
--- a/src/Entity/CloudServerTemplate.php
+++ b/src/Entity/CloudServerTemplate.php
@@ -80,7 +80,7 @@ use Drupal\user\UserInterface;
  *   field_ui_base_route = "entity.cloud_server_template_type.edit_form"
  * )
  */
-class CloudServerTemplate extends RevisionableContentEntityBase implements CloudServerTemplateInterface {
+class CloudServerTemplate extends CloudContentEntityBase implements CloudServerTemplateInterface {
 
   use EntityChangedTrait;
 
@@ -346,14 +346,14 @@ class CloudServerTemplate extends RevisionableContentEntityBase implements Cloud
    */
   public function save() {
     $return = parent::save();
-    $this->updateCache();
+    self::updateCache();
     return $return;
   }
 
   /**
    * Clear the menu, render cache and rebuild the routers.
    */
-  private function updateCache() {
+  private static function updateCache() {
     // Clear block and menu cache.
     \Drupal::cache('menu')->invalidateAll();
     \Drupal::service('cache.render')->deleteAll();
diff --git a/src/Form/CloudConfigDeleteMultipleForm.php b/src/Form/CloudConfigDeleteMultipleForm.php
index 38470e3e..b76050ab 100644
--- a/src/Form/CloudConfigDeleteMultipleForm.php
+++ b/src/Form/CloudConfigDeleteMultipleForm.php
@@ -2,22 +2,23 @@
 
 namespace Drupal\cloud\Form;
 
+use Drupal\cloud\Entity\CloudContentEntityBase;
+use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
+use Drupal\cloud\Traits\CloudDeleteMultipleFormTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Messenger\MessengerInterface;
-use Drupal\Core\Url;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TempStore\PrivateTempStoreFactory;
-use Drupal\cloud\Entity\CloudConfig;
-use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
 
 /**
  * Provides an entities deletion confirmation form.
  */
 class CloudConfigDeleteMultipleForm extends CloudConfigProcessMultipleForm {
 
+  use CloudDeleteMultipleFormTrait;
+
   /**
-   * Constructs a new AwsCloudProcessMultiple object.
+   * Constructs a new CloudConfigDeleteMultipleForm object.
    *
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
@@ -43,135 +44,16 @@ class CloudConfigDeleteMultipleForm extends CloudConfigProcessMultipleForm {
       $messenger,
       $cloud_config_plugin_manager
     );
-    $this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getBaseFormId() {
-
-    return 'aws_cloud_process_multiple_confirm_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-
-    // Get entity type ID from the route because ::buildForm has not yet been
-    // called.
-    $entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
-    return $entity_type_id . '_delete_multiple_confirm_form';
-  }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getConfirmText() {
-
-    return $this->t('Delete');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-
-    return $this->formatPlural(count($this->selection),
-      'Are you sure you want to delete this @item?',
-      'Are you sure you want to delete these @items?', [
-        '@item' => $this->entityType->getSingularLabel(),
-        '@items' => $this->entityType->getPluralLabel(),
-      ]
-    );
+    // Set the temp_store_factory.
+    $this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getCancelUrl() {
-
-    $route = \Drupal::routeMatch();
-    $cloud_context = $route->getParameter('cloud_context');
-    return new Url(
-      'entity.' . $this->entityTypeId . '.collection',
-      ['cloud_context' => $cloud_context]
-    );
-  }
-
-  /**
-   * Process entity.
-   *
-   * @param \Drupal\cloud\Entity\CloudConfig $entity
-   *   An entity object.
-   */
-  protected function processEntity(CloudConfig $entity) {
-
-    $entity->delete();
-  }
-
-  /**
-   * Process an entity and related AWS resource.
-   *
-   * @param \Drupal\cloud\Entity\CloudConfig $entity
-   *   An entity object.
-   *
-   * @return bool
-   *   Succeeded or failed.
-   */
-  protected function process(CloudConfig $entity) {
-
-    $message = $this->t('The @type "@label" has been deleted.', [
-      '@type'  => $entity->getEntityType()->getLabel(),
-      '@label' => $entity->label(),
-    ]);
-
-    $this->processEntity($entity);
-    $this->messenger->addMessage($message);
+  protected function processCloudResource(CloudContentEntityBase $entity) : bool {
     return TRUE;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-
-    parent::submitForm($form, $form_state);
-
-    // Clear block and menu cache.
-    CloudConfig::updateCache();
-  }
-
-  /**
-   * Returns the message to show the user after an item was processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item processed message.
-   */
-  protected function getProcessedMessage($count) {
-
-    return $this->formatPlural($count, 'Deleted @count item.', 'Deleted @count items.');
-  }
-
-  /**
-   * Returns the message to show the user when an item has not been processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item inaccessible message.
-   */
-  protected function getInaccessibleMessage($count) {
-
-    return $this->formatPlural($count,
-      "@count item has not been deleted because you do not have the necessary permissions.",
-      "@count items have not been deleted because you do not have the necessary permissions."
-    );
-  }
-
 }
diff --git a/src/Form/CloudConfigProcessMultipleForm.php b/src/Form/CloudConfigProcessMultipleForm.php
index a5b66449..1eca5f5e 100644
--- a/src/Form/CloudConfigProcessMultipleForm.php
+++ b/src/Form/CloudConfigProcessMultipleForm.php
@@ -2,326 +2,17 @@
 
 namespace Drupal\cloud\Form;
 
-use Drupal\Core\Entity\EntityTypeManager;
-use Drupal\Core\Form\BaseFormIdInterface;
-use Drupal\Core\Form\ConfirmFormBase;
-use Drupal\Core\Messenger\MessengerInterface;
-use Drupal\Core\TypedData\TranslatableInterface;
-use Drupal\Core\Url;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\TempStore\PrivateTempStoreFactory;
-use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\cloud\Entity\CloudConfig;
-
 /**
- * Provides an entities deletion confirmation form.
+ * Provide a confirmation form of bulk operation for cloud service providers.
  */
-abstract class CloudConfigProcessMultipleForm extends ConfirmFormBase implements BaseFormIdInterface {
-
-  /**
-   * The current user.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManager
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The tempstore.
-   *
-   * @var \Drupal\Core\TempStore\SharedTempStore
-   */
-  protected $tempStore;
-
-  /**
-   * The messenger service.
-   *
-   * @var \Drupal\Core\Messenger\MessengerInterface
-   */
-  protected $messenger;
-
-  /**
-   * The entity type ID.
-   *
-   * @var string
-   */
-  protected $entityTypeId;
-
-  /**
-   * The selection, in the entity_id => langcodes format.
-   *
-   * @var array
-   */
-  protected $selection = [];
-
-  /**
-   * The entity type definition.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeInterface
-   */
-  protected $entityType;
-
-  /**
-   * The cloud service provider plugin manager (CloudConfigPluginManager).
-   *
-   * @var \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface
-   */
-  protected $cloudConfigPluginManager;
-
-  /**
-   * The temp store key name.
-   *
-   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
-   */
-  protected $tempStoreKey;
-
-  /**
-   * Constructs a new CloudProcessMultiple object.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
-   *   The tempstore factory.
-   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
-   *   The messenger service.
-   * @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
-   *   The cloud service provider plugin manager (CloudConfigPluginManager).
-   */
-  public function __construct(AccountInterface $current_user,
-                              EntityTypeManager $entity_type_manager,
-                              PrivateTempStoreFactory $temp_store_factory,
-                              MessengerInterface $messenger,
-                              CloudConfigPluginManagerInterface $cloud_config_plugin_manager) {
-
-    $this->entityTypeManager = $entity_type_manager;
-    $this->currentUser = $current_user;
-    $entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
-    $this->tempStoreKey = $this->currentUser->id() . ':' . $entity_type_id;
-    $this->tempStore = $temp_store_factory->get($this->tempStoreKey);
-    $this->messenger = $messenger;
-    $this->cloudConfigPluginManager = $cloud_config_plugin_manager;
-  }
+abstract class CloudConfigProcessMultipleForm extends CloudProcessMultipleForm {
 
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container) {
-
-    return new static(
-      $container->get('current_user'),
-      $container->get('entity_type.manager'),
-      $container->get('tempstore.private'),
-      $container->get('messenger'),
-      $container->get('plugin.manager.cloud_config_plugin')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getBaseFormId() {
-
-    return 'aws_cloud_process_multiple_confirm_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-
-    // Get entity type ID from the route because ::buildForm has not yet been
-    // called.
-    $entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
-    return $entity_type_id . '_process_multiple_confirm_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-
-    return $this->formatPlural(count($this->selection),
-      'Are you sure you want to process this @item?',
-      'Are you sure you want to process these @items?', [
-        '@item' => $this->entityType->getSingularLabel(),
-        '@items' => $this->entityType->getPluralLabel(),
-      ]
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCancelUrl() {
-
-    $route = \Drupal::routeMatch();
-    $cloud_context = $route->getParameter('cloud_context');
-    return new Url(
-      'entity.' . $this->entityTypeId . '.collection',
-      ['cloud_context' => $cloud_context]
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
-    $this->entityTypeId = $entity_type_id;
-    $this->entityType = $this->entityTypeManager->getDefinition($this->entityTypeId);
-    $this->selection = $this->tempStore->get($this->tempStoreKey);
-    if (empty($this->entityTypeId) || empty($this->selection)) {
-      return new RedirectResponse($this->getCancelUrl()
-        ->setAbsolute()
-        ->toString());
-    }
-
-    $items = [];
-    $entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple(array_keys($this->selection));
-    foreach ($this->selection as $id => $selected_langcodes) {
-      $entity = $entities[$id];
-      foreach ($selected_langcodes as $langcode) {
-        $key = $id . ':' . $langcode;
-        if ($entity instanceof TranslatableInterface) {
-          $entity = $entity->getTranslation($langcode);
-          $default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
-
-          // Build a nested list of translations that will be processed if the
-          // entity has multiple translations.
-          $entity_languages = $entity->getTranslationLanguages();
-          if (count($entity_languages) > 1 && $entity->isDefaultTranslation()) {
-            $names = [];
-            foreach ($entity_languages as $translation_langcode => $language) {
-              $names[] = $language->getName();
-              unset($items[$id . ':' . $translation_langcode]);
-            }
-            $items[$default_key] = [
-              'label' => [
-                '#markup' => $this->t(
-                  '@label (Original translation) - <em>The following @entity_type translations will be processed:</em>',
-                  [
-                    '@label' => $entity->label(),
-                    '@entity_type' => $this->entityType->getSingularLabel(),
-                  ]),
-              ],
-              'deleted_translations' => [
-                '#theme' => 'item_list',
-                '#items' => $names,
-              ],
-            ];
-          }
-          elseif (!isset($items[$default_key])) {
-            $items[$key] = $entity->label();
-          }
-        }
-        elseif (!isset($items[$key])) {
-          $items[$key] = $entity->label();
-        }
-      }
-    }
-
-    $form = parent::buildForm($form, $form_state);
-    $form['entities'] = [
-      '#theme' => 'item_list',
-      '#items' => $items,
-    ];
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-
-    $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
-    $entities = $storage->loadMultiple(array_keys($this->selection));
-    $total_count = 0;
-    foreach ($entities as $entity) {
-      if ($this->process($entity)) {
-        $total_count++;
-      }
-    }
-
-    if ($total_count) {
-      $this->messenger->addStatus($this->getProcessedMessage($total_count));
-    }
-
-    $this->tempStore->delete($this->currentUser->id());
-    $form_state->setRedirectUrl($this->getCancelUrl());
-  }
-
-  /**
-   * Process entity.
-   *
-   * @param \Drupal\cloud\Entity\CloudConfig $entity
-   *   An entity object.
-   *
-   * @return bool
-   *   Succeeded or failed.
-   */
-  abstract protected function processEntity(CloudConfig $entity);
-
-  /**
-   * Process an entity and related AWS resource.
-   *
-   * @param \Drupal\cloud\Entity\CloudConfig $entity
-   *   An entity object.
-   *
-   * @return bool
-   *   Succeeded or failed.
-   */
-  protected function process(CloudConfig $entity) {
-
-    $message = $this->t('The @type "@label" has been processed.', [
-      '@type'  => $entity->getEntityType()->getLabel(),
-      '@label' => $entity->label(),
-    ]);
-
-    $this->processEntity($entity);
-    $this->messenger->addMessage($message);
-    return TRUE;
-  }
-
-  /**
-   * Returns the message to show the user after an item was processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item processed message.
-   */
-  protected function getProcessedMessage($count) {
-
-    return $this->formatPlural($count, 'Processed @count item.', 'Processed @count items.');
-  }
-
-  /**
-   * Returns the message to show the user when an item has not been processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item inaccessible message.
-   */
-  protected function getInaccessibleMessage($count) {
+  public function getBaseFormId() : string {
 
-    return $this->formatPlural($count,
-      "@count item has not been processed because you do not have the necessary permissions.",
-      "@count items have not been processed because you do not have the necessary permissions."
-    );
+    return 'cloud_config_process_multiple_confirm_form';
   }
 
 }
diff --git a/src/Form/CloudProcessMultipleForm.php b/src/Form/CloudProcessMultipleForm.php
index f1a37c8f..f58f0fd0 100644
--- a/src/Form/CloudProcessMultipleForm.php
+++ b/src/Form/CloudProcessMultipleForm.php
@@ -2,20 +2,19 @@
 
 namespace Drupal\cloud\Form;
 
+use Drupal\cloud\Entity\CloudContentEntityBase;
+use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
 use Drupal\Core\Entity\EntityTypeManager;
 use Drupal\Core\Form\BaseFormIdInterface;
 use Drupal\Core\Form\ConfirmFormBase;
-use Drupal\Core\Messenger\MessengerInterface;
-use Drupal\Core\TypedData\TranslatableInterface;
-use Drupal\Core\Url;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TempStore\PrivateTempStoreFactory;
-
-use Drupal\cloud\Entity\CloudContentEntityBase;
-use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
-use Symfony\Component\HttpFoundation\RedirectResponse;
+use Drupal\Core\TypedData\TranslatableInterface;
+use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
  * Provides an entities deletion confirmation form.
@@ -139,7 +138,7 @@ abstract class CloudProcessMultipleForm extends ConfirmFormBase implements BaseF
   /**
    * {@inheritdoc}
    */
-  public function getFormId() {
+  public function getFormId() : string {
 
     // Get entity type ID from the route because ::buildForm has not yet been
     // called.
diff --git a/src/Form/CloudServerTemplateDeleteMultipleForm.php b/src/Form/CloudServerTemplateDeleteMultipleForm.php
index dcb6b0cc..cefe1d2a 100644
--- a/src/Form/CloudServerTemplateDeleteMultipleForm.php
+++ b/src/Form/CloudServerTemplateDeleteMultipleForm.php
@@ -2,8 +2,9 @@
 
 namespace Drupal\cloud\Form;
 
-use Drupal\cloud\Entity\CloudServerTemplate;
+use Drupal\cloud\Entity\CloudContentEntityBase;
 use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
+use Drupal\cloud\Traits\CloudDeleteMultipleFormTrait;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -14,8 +15,10 @@ use Drupal\Core\TempStore\PrivateTempStoreFactory;
  */
 class CloudServerTemplateDeleteMultipleForm extends CloudServerTemplateProcessMultipleForm {
 
+  use CloudDeleteMultipleFormTrait;
+
   /**
-   * Constructs a new CloudProcessMultiple object.
+   * Constructs a new CloudServerTemplateDeleteMultipleForm object.
    *
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
@@ -47,33 +50,9 @@ class CloudServerTemplateDeleteMultipleForm extends CloudServerTemplateProcessMu
   }
 
   /**
-   * Process entity.
-   *
-   * @param \Drupal\cloud\Entity\CloudServerTemplate $entity
-   *   An entity object.
-   */
-  protected function processEntity(CloudServerTemplate $entity) {
-    $entity->delete();
-  }
-
-  /**
-   * Process an entity and related AWS resource.
-   *
-   * @param \Drupal\cloud\Entity\CloudServerTemplate $entity
-   *   An entity object.
-   *
-   * @return bool
-   *   Succeeded or failed.
+   * {@inheritdoc}
    */
-  protected function process(CloudServerTemplate $entity) {
-
-    $message = $this->t('The @type "@label" has been processed.', [
-      '@type'  => $entity->getEntityType()->getLabel(),
-      '@label' => $entity->label(),
-    ]);
-
-    $this->processEntity($entity);
-    $this->messenger->addMessage($message);
+  protected function processCloudResource(CloudContentEntityBase $entity) : bool {
     return TRUE;
   }
 
diff --git a/src/Form/CloudServerTemplateProcessMultipleForm.php b/src/Form/CloudServerTemplateProcessMultipleForm.php
index f21c1456..a1c2a6aa 100644
--- a/src/Form/CloudServerTemplateProcessMultipleForm.php
+++ b/src/Form/CloudServerTemplateProcessMultipleForm.php
@@ -2,312 +2,17 @@
 
 namespace Drupal\cloud\Form;
 
-use Drupal\cloud\Entity\CloudServerTemplate;
-use Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface;
-use Drupal\Core\Entity\EntityTypeManager;
-use Drupal\Core\Form\BaseFormIdInterface;
-use Drupal\Core\Form\ConfirmFormBase;
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Messenger\MessengerInterface;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\TempStore\PrivateTempStoreFactory;
-use Drupal\Core\TypedData\TranslatableInterface;
-use Drupal\Core\Url;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\HttpFoundation\RedirectResponse;
-
 /**
- * Provide a generic bulk operation form for cloud server templates.
+ * Provide a confirmation form of bulk operation for cloud server templates.
  */
-abstract class CloudServerTemplateProcessMultipleForm extends ConfirmFormBase implements BaseFormIdInterface {
-
-  /**
-   * The current user.
-   *
-   * @var \Drupal\Core\Session\AccountInterface
-   */
-  protected $currentUser;
-
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManager
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The tempstore.
-   *
-   * @var \Drupal\Core\TempStore\SharedTempStore
-   */
-  protected $tempStore;
-
-  /**
-   * The messenger service.
-   *
-   * @var \Drupal\Core\Messenger\MessengerInterface
-   */
-  protected $messenger;
-
-  /**
-   * The entity type ID.
-   *
-   * @var string
-   */
-  protected $entityTypeId;
-
-  /**
-   * The selection, in the entity_id => langcodes format.
-   *
-   * @var array
-   */
-  protected $selection = [];
-
-  /**
-   * The entity type definition.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeInterface
-   */
-  protected $entityType;
-
-  /**
-   * The cloud service provider plugin manager (CloudConfigPluginManager).
-   *
-   * @var \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface
-   */
-  protected $cloudConfigPluginManager;
-
-  /**
-   * The temp store key name.
-   *
-   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
-   */
-  protected $tempStoreKey;
-
-  /**
-   * Constructs a new CloudProcessMultiple object.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $current_user
-   *   The current user.
-   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
-   *   The entity type manager.
-   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
-   *   The tempstore factory.
-   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
-   *   The messenger service.
-   * @param \Drupal\cloud\Plugin\cloud\config\CloudConfigPluginManagerInterface $cloud_config_plugin_manager
-   *   The cloud service provider plugin manager (CloudConfigPluginManager).
-   */
-  public function __construct(AccountInterface $current_user,
-                              EntityTypeManager $entity_type_manager,
-                              PrivateTempStoreFactory $temp_store_factory,
-                              MessengerInterface $messenger,
-                              CloudConfigPluginManagerInterface $cloud_config_plugin_manager) {
-    $this->entityTypeManager = $entity_type_manager;
-    $this->currentUser = $current_user;
-    $entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
-    $this->tempStoreKey = $this->currentUser->id() . ':' . $entity_type_id;
-    $this->tempStore = $temp_store_factory->get($this->tempStoreKey);
-    $this->messenger = $messenger;
-    $this->cloudConfigPluginManager = $cloud_config_plugin_manager;
-
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-
-    return new static(
-      $container->get('current_user'),
-      $container->get('entity_type.manager'),
-      $container->get('tempstore.private'),
-      $container->get('messenger'),
-      $container->get('plugin.manager.cloud_config_plugin')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-
-    return $this->formatPlural(count($this->selection),
-      'Are you sure you want to process this @item?',
-      'Are you sure you want to process these @items?', [
-        '@item' => $this->entityType->getSingularLabel(),
-        '@items' => $this->entityType->getPluralLabel(),
-      ]
-    );
-  }
+abstract class CloudServerTemplateProcessMultipleForm extends CloudProcessMultipleForm {
 
   /**
    * {@inheritdoc}
    */
-  public function getCancelUrl() {
+  public function getBaseFormId() : string {
 
-    $route = \Drupal::routeMatch();
-    $cloud_context = $route->getParameter('cloud_context');
-    return new Url(
-      'entity.' . $this->entityTypeId . '.collection',
-      ['cloud_context' => $cloud_context]
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
-    $this->entityTypeId = $entity_type_id;
-    $this->entityType = $this->entityTypeManager->getDefinition($this->entityTypeId);
-    $this->selection = $this->tempStore->get($this->tempStoreKey);
-    if (empty($this->entityTypeId) || empty($this->selection)) {
-      return new RedirectResponse($this->getCancelUrl()
-        ->setAbsolute()
-        ->toString());
-    }
-
-    $items = [];
-    $entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple(array_keys($this->selection));
-    foreach ($this->selection as $id => $selected_langcodes) {
-      $entity = $entities[$id];
-      foreach ($selected_langcodes as $langcode) {
-        $key = $id . ':' . $langcode;
-        if ($entity instanceof TranslatableInterface) {
-          $entity = $entity->getTranslation($langcode);
-          $default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
-
-          // Build a nested list of translations that will be processed if the
-          // entity has multiple translations.
-          $entity_languages = $entity->getTranslationLanguages();
-          if (count($entity_languages) > 1 && $entity->isDefaultTranslation()) {
-            $names = [];
-            foreach ($entity_languages as $translation_langcode => $language) {
-              $names[] = $language->getName();
-              unset($items[$id . ':' . $translation_langcode]);
-            }
-            $items[$default_key] = [
-              'label' => [
-                '#markup' => $this->t(
-                  '@label (Original translation) - <em>The following @entity_type translations will be processed:</em>',
-                  [
-                    '@label' => $entity->label(),
-                    '@entity_type' => $this->entityType->getSingularLabel(),
-                  ]),
-              ],
-              'deleted_translations' => [
-                '#theme' => 'item_list',
-                '#items' => $names,
-              ],
-            ];
-          }
-          elseif (!isset($items[$default_key])) {
-            $items[$key] = $entity->label();
-          }
-        }
-        elseif (!isset($items[$key])) {
-          $items[$key] = $entity->label();
-        }
-      }
-    }
-
-    $form = parent::buildForm($form, $form_state);
-    $form['entities'] = [
-      '#theme' => 'item_list',
-      '#items' => $items,
-    ];
-
-    return $form;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function submitForm(array &$form, FormStateInterface $form_state) {
-
-    $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
-    $entities = $storage->loadMultiple(array_keys($this->selection));
-    $total_count = 0;
-    foreach ($entities as $entity) {
-      if ($this->process($entity)) {
-        $total_count++;
-      }
-    }
-
-    if ($total_count) {
-      $this->messenger->addStatus($this->getProcessedMessage($total_count));
-    }
-
-    $this->tempStore->delete($this->currentUser->id());
-    $form_state->setRedirectUrl($this->getCancelUrl());
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getBaseFormId() {
     return 'cloud_server_template_process_multiple_confirm_form';
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-
-    // Get entity type ID from the route because ::buildForm has not yet been
-    // called.
-    $entity_type_id = $this->getRouteMatch()->getParameter('entity_type_id');
-    return $entity_type_id . '_process_multiple_confirm_form';
-  }
-
-  /**
-   * Process entity.
-   *
-   * @param \Drupal\cloud\Entity\CloudServerTemplate $entity
-   *   An entity object.
-   */
-  abstract protected function processEntity(CloudServerTemplate $entity);
-
-  /**
-   * Process an entity and related AWS resource.
-   *
-   * @param \Drupal\cloud\Entity\CloudServerTemplate $entity
-   *   An entity object.
-   *
-   * @return bool
-   *   Succeeded or failed.
-   */
-  abstract protected function process(CloudServerTemplate $entity);
-
-  /**
-   * Returns the message to show the user after an item was processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item processed message.
-   */
-  protected function getProcessedMessage($count) {
-
-    return $this->formatPlural($count, 'Processed @count item.', 'Processed @count items.');
-  }
-
-  /**
-   * Returns the message to show the user when an item has not been processed.
-   *
-   * @param int $count
-   *   Count of processed translations.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   The item inaccessible message.
-   */
-  protected function getInaccessibleMessage($count) {
-
-    return $this->formatPlural($count,
-      "@count item has not been processed because you do not have the necessary permissions.",
-      "@count items have not been processed because you do not have the necessary permissions."
-    );
-  }
-
 }
diff --git a/src/Traits/CloudDeleteMultipleFormTrait.php b/src/Traits/CloudDeleteMultipleFormTrait.php
index 775fea63..9a804f28 100644
--- a/src/Traits/CloudDeleteMultipleFormTrait.php
+++ b/src/Traits/CloudDeleteMultipleFormTrait.php
@@ -13,7 +13,7 @@ trait CloudDeleteMultipleFormTrait {
   /**
    * {@inheritdoc}
    */
-  public function getFormId() {
+  public function getFormId() : string {
 
     // Get entity type ID from the route because ::buildForm has not yet been
     // called.
