Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/delete saved sandbox #940

Merged
merged 5 commits into from
Jun 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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