Skip to content

Commit

Permalink
Merge pull request #940 from QualiSystems/feature/delete_saved_sandbox
Browse files Browse the repository at this point in the history
Feature/delete saved sandbox
  • Loading branch information
nahumtimerman committed Jun 26, 2018
2 parents c9b9cfc + 52ec50b commit 1b3c2f4
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 55 deletions.
30 changes: 27 additions & 3 deletions package/cloudshell/cp/vcenter/commands/command_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
from cloudshell.cp.vcenter.commands.restore_snapshot import SnapshotRestoreCommand
from cloudshell.cp.vcenter.commands.save_snapshot import SaveSnapshotCommand
from cloudshell.cp.vcenter.commands.retrieve_snapshots import RetrieveSnapshotsCommand
from cloudshell.cp.vcenter.commands.save_app import SaveAppCommand
from cloudshell.cp.vcenter.commands.save_sandbox import SaveAppCommand
from cloudshell.cp.vcenter.commands.delete_saved_sandbox import DeleteSavedSandboxCommand
from cloudshell.cp.vcenter.common.cloud_shell.resource_remover import CloudshellResourceRemover
from cloudshell.cp.vcenter.common.model_factory import ResourceModelParser
from cloudshell.cp.vcenter.common.utilites.command_result import set_command_result, get_result_from_command_output
Expand Down Expand Up @@ -166,6 +167,15 @@ def __init__(self):
cancellation_service=cancellation_service,
port_group_configurer=virtual_machine_port_group_configurer)

self.delete_saved_sandbox_command = DeleteSavedSandboxCommand(pyvmomi_service=pv_service,
task_waiter=synchronous_task_waiter,
deployer=vm_deployer,
resource_model_parser=self.resource_model_parser,
snapshot_saver=self.snapshot_saver,
folder_manager=self.folder_manager,
cancellation_service=cancellation_service,
port_group_configurer=virtual_machine_port_group_configurer)

def connect_bulk(self, context, request):
results = self.command_wrapper.execute_command_with_connection(
context,
Expand All @@ -178,9 +188,9 @@ def connect_bulk(self, context, request):
driver_response_root.driverResponse = driver_response
return set_command_result(result=driver_response_root, unpicklable=False)

def save_app(self, context, save_actions, cancellation_context):
def save_sandbox(self, context, save_actions, cancellation_context):
"""
Save App command, persists an artifact of an existing VM, from which a new vm can be restored
Save sandbox command, persists an artifact of existing VMs, from which new vms can be restored
:param ResourceCommandContext context:
:param list[SaveApp] save_actions:
:param CancellationContext cancellation_context:
Expand All @@ -191,6 +201,20 @@ def save_app(self, context, save_actions, cancellation_context):
save_app_results = connection
return save_app_results

def delete_saved_sandbox(self, context, delete_saved_apps, cancellation_context):
"""
Delete a saved sandbox, along with any vms associated with it
:param ResourceCommandContext context:
:param list[DeleteSavedApp] delete_saved_apps:
:param CancellationContext cancellation_context:
:return: list[SaveAppResult] save_app_results
"""
connection = self.command_wrapper.execute_command_with_connection(context,
self.delete_saved_sandbox_command.delete_sandbox,
delete_saved_apps, cancellation_context)
delete_saved_apps_results = connection
return delete_saved_apps_results

def deploy_from_template(self, context, deploy_action, cancellation_context):
"""
Deploy From Template Command, will deploy vm from template
Expand Down
124 changes: 124 additions & 0 deletions package/cloudshell/cp/vcenter/commands/delete_saved_sandbox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import copy
from itertools import groupby

from cloudshell.cp.core.models import ActionResultBase

from cloudshell.cp.vcenter.common.utilites.savers.artifact_saver import ArtifactHandler, UnsupportedArtifactHandler
from cloudshell.cp.vcenter.common.vcenter.task_waiter import SynchronousTaskWaiter
from cloudshell.cp.vcenter.common.vcenter.vmomi_service import pyVmomiService

import os
from multiprocessing.pool import ThreadPool


class DeleteSavedSandboxCommand:
def __init__(self, pyvmomi_service, task_waiter, deployer, resource_model_parser, snapshot_saver, folder_manager,
cancellation_service, port_group_configurer):
"""
:param pyvmomi_service:
:type pyvmomi_service: pyVmomiService
:param task_waiter: Waits for the task to be completed
:param folder_manager: cloudshell.cp.vcenter.common.vcenter.folder_manager.FolderManager
:type task_waiter: SynchronousTaskWaiter
"""
self.pyvmomi_service = pyvmomi_service
self.task_waiter = task_waiter
self.deployer = deployer
self.resource_model_parser = resource_model_parser
self.snapshot_saver = snapshot_saver
self.folder_manager = folder_manager
SAVE_APPS_THREAD_POOL_SIZE = int(os.getenv('SaveAppsThreadPoolSize', 10))
self._pool = ThreadPool(SAVE_APPS_THREAD_POOL_SIZE)
self.cs = cancellation_service
self.pg = port_group_configurer

def delete_sandbox(self, si, logger, vcenter_data_model, delete_sandbox_actions, cancellation_context):
"""
Cretaes an artifact of an app, that can later be restored
:param vcenter_data_model: VMwarevCenterResourceModel
:param vim.ServiceInstance si: py_vmomi service instance
:type si: vim.ServiceInstance
:param logger: Logger
:type logger: cloudshell.core.logger.qs_logger.get_qs_logger
:param list[SaveApp] delete_sandbox_actions:
:param cancellation_context:
"""
results = []

logger.info('Save apps command starting on ' + vcenter_data_model.default_datacenter)

if not delete_sandbox_actions:
raise Exception('Failed to save app, missing data in request.')

actions_grouped_by_save_types = groupby(delete_sandbox_actions, lambda x: x.actionParams.saveDeploymentModel)
artifactHandlersToActions = {ArtifactHandler.factory(k,
self.pyvmomi_service,
vcenter_data_model,
si,
logger,
self.deployer,
None,
self.resource_model_parser,
self.snapshot_saver,
self.task_waiter,
self.folder_manager,
self.pg): list(g)
for k, g in actions_grouped_by_save_types}

self._validate_save_deployment_models(artifactHandlersToActions, delete_sandbox_actions, results)

error_results = [r for r in results if not r.success]
if not error_results:
results = self._execute_delete_saved_sandbox(artifactHandlersToActions,
cancellation_context,
logger,
results)

return results

def _validate_save_deployment_models(self, artifactHandlersToActions, delete_sandbox_actions, results):
unsupported_save_deployment_models = [a.unsupported_save_type for a in artifactHandlersToActions.keys() if
isinstance(a, UnsupportedArtifactHandler)]
if unsupported_save_deployment_models:
for action in delete_sandbox_actions:
results.append(
ActionResultBase(type='DeleteSavedAppResult',
actionId=action.actionId,
success=False,
infoMessage='Unsupported save deployment models: {0}'.format(
', '.join(unsupported_save_deployment_models)))
)

def _execute_delete_saved_sandbox(self, artifactHandlersToActions, cancellation_context, logger, results):
for artifactHandler in artifactHandlersToActions.keys():
delete_sandbox_results = artifactHandler.delete(artifactHandlersToActions[artifactHandler], cancellation_context)
results.extend(delete_sandbox_results)
return results

def _destroy(self, (artifactSaver, action)):
artifactSaver.destroy(save_action=action)
return ActionResultBase(action.actionId,
success=False,
errorMessage='Save app action {0} was cancelled'.format(action.actionId),
infoMessage='')

def _validate_supported_artifact_handlers(self, artifactHandlersToActions, logger, results):
unsupported_handlers = [saver for saver in artifactHandlersToActions.keys() if
isinstance(saver, UnsupportedArtifactHandler)]
if unsupported_handlers:
log_error_message = "Unsupported save type was included in delete saved app request: {0}" \
.format(', '.join({saver.unsupported_save_type for saver in unsupported_handlers}))
logger.error(log_error_message)

for artifact_handler in artifactHandlersToActions.keys():
if artifact_handler in unsupported_handlers:
result_error_message = 'Unsupported save type ' + artifact_handler.unsupported_save_type
else:
result_error_message = ''

delete_saved_app_actions = artifactHandlersToActions[artifact_handler]
for action in delete_saved_app_actions:
results.append(ActionResultBase(action.actionId,
success=False,
errorMessage=result_error_message))
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from cloudshell.cp.core.models import SaveApp, SaveAppResult

from cloudshell.cp.vcenter.common.utilites.savers.artifact_saver import ArtifactSaver, UnsupportedArtifactSaver
from cloudshell.cp.vcenter.common.utilites.savers.artifact_saver import ArtifactHandler, UnsupportedArtifactHandler
from cloudshell.cp.vcenter.common.vcenter.task_waiter import SynchronousTaskWaiter
from cloudshell.cp.vcenter.common.vcenter.vmomi_service import pyVmomiService

Expand Down Expand Up @@ -55,18 +55,18 @@ def save_app(self, si, logger, vcenter_data_model, reservation_id, save_app_acti
raise Exception('Failed to save app, missing data in request.')

actions_grouped_by_save_types = groupby(save_app_actions, lambda x: x.actionParams.saveDeploymentModel)
artifactSaversToActions = {ArtifactSaver.factory(k,
self.pyvmomi_service,
vcenter_data_model,
si,
logger,
self.deployer,
reservation_id,
self.resource_model_parser,
self.snapshot_saver,
self.task_waiter,
self.folder_manager,
self.port_group_configurer): list(g)
artifactSaversToActions = {ArtifactHandler.factory(k,
self.pyvmomi_service,
vcenter_data_model,
si,
logger,
self.deployer,
reservation_id,
self.resource_model_parser,
self.snapshot_saver,
self.task_waiter,
self.folder_manager,
self.port_group_configurer): list(g)
for k, g in actions_grouped_by_save_types}

self.validate_requested_save_types_supported(artifactSaversToActions,
Expand Down Expand Up @@ -145,7 +145,7 @@ def _destroy(self, (artifactSaver, action)):

def validate_requested_save_types_supported(self, artifactSaversToActions, logger, results):
unsupported_savers = [saver for saver in artifactSaversToActions.keys() if
isinstance(saver, UnsupportedArtifactSaver)]
isinstance(saver, UnsupportedArtifactHandler)]
if unsupported_savers:
log_error_message = "Unsupported save type was included in save app request: {0}" \
.format(', '.join({saver.unsupported_save_type for saver in unsupported_savers}))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
from cloudshell.cp.vcenter.common.utilites.savers.linked_clone_artifact_saver import LinkedCloneArtifactSaver
from cloudshell.cp.vcenter.common.utilites.savers.linked_clone_artifact_saver import LinkedCloneArtifactHandler


class ArtifactSaver(object):
class ArtifactHandler(object):
@staticmethod
def factory(saveDeploymentModel, pv_service, vcenter_data_model, si, logger, deployer, reservation_id,
resource_model_parser, snapshot_saver, task_waiter, folder_manager, port_configurer):
if saveDeploymentModel == 'VCenter Deploy VM From Linked Clone':
return LinkedCloneArtifactSaver(pv_service, vcenter_data_model, si, logger, deployer, reservation_id,
resource_model_parser, snapshot_saver, task_waiter, folder_manager,
port_configurer)
return UnsupportedArtifactSaver(saveDeploymentModel)
return LinkedCloneArtifactHandler(pv_service, vcenter_data_model, si, logger, deployer, reservation_id,
resource_model_parser, snapshot_saver, task_waiter, folder_manager,
port_configurer)
return UnsupportedArtifactHandler(saveDeploymentModel)


class UnsupportedArtifactSaver(object):
class UnsupportedArtifactHandler(object):
def __init__(self, saveDeploymentModel):
self.unsupported_save_type = saveDeploymentModel
Loading

0 comments on commit 1b3c2f4

Please sign in to comment.