Exemple #1
0
class DeployFromImage(ResourceDriverInterface):
    def cleanup(self):
        pass

    def __init__(self):
        self.cs_helper = CloudshellDriverHelper()
        self.resource_model_parser = ResourceModelParser()

    def initialize(self, context):
        pass

    def Deploy(self, context, Name=None):
        """
        Deploys app from image
        :type context: models.QualiDriverModels.ResourceCommandContext
        """
        session = self.cs_helper.get_session(
            context.connectivity.server_address,
            context.connectivity.admin_auth_token, context.reservation.domain)

        # get vCenter resource name, template name, template folder
        vcenter_image_resource_model = \
            self.resource_model_parser.convert_to_resource_model(context.resource,
                                                                 vCenterVMFromImageResourceModel)

        vcenter_res = vcenter_image_resource_model.vcenter_name

        if not Name:
            Name = jsonpickle.decode(
                context.resource.app_context.app_request_json)['name']

        deployment_info = self._get_deployment_info(
            vcenter_image_resource_model, Name)
        result = session.ExecuteCommand(
            context.reservation.reservation_id, vcenter_res,
            "Resource", "deploy_from_image",
            self._get_command_inputs_list(deployment_info), False)
        return result.Output

    def _get_deployment_info(self, image_model, name):
        """
        :type image_model: vCenterVMFromImageResourceModel
        """

        return DeployDataHolder({
            'app_name': name,
            'image_params': image_model
        })

    def _get_command_inputs_list(self, data_holder):
        return [
            InputNameValue('deploy_data',
                           jsonpickle.encode(data_holder, unpicklable=False))
        ]
Exemple #2
0
class DeployFromImage(ResourceDriverInterface):
    def cleanup(self):
        pass

    def __init__(self):
        self.cs_helper = CloudshellDriverHelper()
        self.resource_model_parser = ResourceModelParser()

    def initialize(self, context):
        pass

    def Deploy(self, context, Name=None):
        """
        Deploys app from image
        :type context: models.QualiDriverModels.ResourceCommandContext
        """
        session = self.cs_helper.get_session(context.connectivity.server_address,
                                             context.connectivity.admin_auth_token,
                                             context.reservation.domain)

        # get vCenter resource name, template name, template folder
        vcenter_image_resource_model = \
            self.resource_model_parser.convert_to_resource_model(context.resource,
                                                                 vCenterVMFromImageResourceModel)

        vcenter_res = vcenter_image_resource_model.vcenter_name

        if not Name:
            Name = jsonpickle.decode(context.resource.app_context.app_request_json)['name']

        deployment_info = self._get_deployment_info(vcenter_image_resource_model, Name)
        result = session.ExecuteCommand(context.reservation.reservation_id,
                                        vcenter_res,
                                        "Resource",
                                        "deploy_from_image",
                                        self._get_command_inputs_list(deployment_info),
                                        False)
        return result.Output

    def _get_deployment_info(self, image_model, name):
        """
        :type image_model: vCenterVMFromImageResourceModel
        """

        return DeployDataHolder({'app_name': name,
                                 'image_params': image_model
                                 })

    def _get_command_inputs_list(self, data_holder):
        return [InputNameValue('deploy_data', jsonpickle.encode(data_holder, unpicklable=False))]
    def test_parse_resource_info_model(self):
        resource_model_parser = ResourceModelParser()

        resource_info = create_autospec(ResourceInfo)

        resource_info.ResourceModelName = 'VLAN Auto'
        resource_info.ResourceAttributes = {'Access Mode': 'Trunk', 'VLAN Id': '123', 'Allocation Ranges': '2-4094',
                                            'Virtual Network': '', 'Isolation Level': 'Exclusive'}
        resource_model = resource_model_parser.convert_to_resource_model(resource_info, None)

        self.assertEqual(resource_model.access_mode, 'Trunk')
        self.assertEqual(resource_model.vlan_id, '123')
        self.assertEqual(resource_model.isolation_level, 'Exclusive')
        self.assertEqual(resource_model.allocation_ranges, '2-4094')
        self.assertEqual(resource_model.virtual_network, '')
        self.assertEqual(resource_model.virtual_network_attribute, 'Virtual Network')
Exemple #4
0
class DeployFromTemplateDriver(ResourceDriverInterface):
    def __init__(self):
        self.resource_model_parser = ResourceModelParser()
        self.cs_helper = CloudshellDriverHelper()

    def cleanup(self):
        pass

    def initialize(self, context):
        pass

    def Deploy(self, context, Name=None):
        """
        Deploys app from template
        :type context: models.QualiDriverModels.ResourceCommandContext
        :param Name: Name of the Deployment
        :type Name: str
        :rtype: str
        """
        session = self.cs_helper.get_session(
            context.connectivity.server_address,
            context.connectivity.admin_auth_token, context.reservation.domain)

        vcenter_template_resource_model = \
            self.resource_model_parser.convert_to_resource_model(context.resource,
                                                                 vCenterVMFromTemplateResourceModel)

        if not Name:
            Name = jsonpickle.decode(
                context.resource.app_context.app_request_json)['name']

        deploy_from_template_details = DeployFromTemplateDetails(
            vcenter_template_resource_model, Name)

        params = [
            InputNameValue(
                'deploy_data',
                jsonpickle.encode(deploy_from_template_details,
                                  unpicklable=False))
        ]

        reservation_id = context.reservation.reservation_id
        result = session.ExecuteCommand(
            reservation_id, vcenter_template_resource_model.vcenter_name,
            "Resource", "deploy_from_template", params, False)

        return result.Output
    def test_parse_response_info(self):
        resource_info = create_autospec(ResourceInfo)
        resource_info.ResourceModelName = 'Generic Deployed App'

        vm_uuid_attribute = create_autospec(ResourceAttribute)
        vm_uuid_attribute.Name = 'VM_UUID'
        vm_uuid_attribute.Value = '422258cd-8b76-e375-8c3b-8e1bf86a4713'

        cloud_provider_attribute = create_autospec(ResourceAttribute)
        cloud_provider_attribute.Name = 'Cloud Provider'
        cloud_provider_attribute.Value = 'vCenter'

        resource_info.ResourceAttributes = [vm_uuid_attribute, cloud_provider_attribute]

        resource_model_parser = ResourceModelParser()
        resource_model = resource_model_parser.convert_to_resource_model(resource_info, None)

        self.assertEqual(resource_model.vm_uuid, '422258cd-8b76-e375-8c3b-8e1bf86a4713')
Exemple #6
0
class DeployCloneFromVMDriver(ResourceDriverInterface):
    def __init__(self):
        self.resource_model_parser = ResourceModelParser()
        self.cs_helper = CloudshellDriverHelper()

    def cleanup(self):
        pass

    def initialize(self, context):
        pass

    def Deploy(self, context, Name=None):
        """
        Deploys app from template
        :type context: models.QualiDriverModels.ResourceCommandContext
        :param Name: Name of the Deployment
        :type Name: str
        :rtype: str
        """
        session = self.cs_helper.get_session(context.connectivity.server_address,
                                             context.connectivity.admin_auth_token,
                                             context.reservation.domain)

        vcenter_template_resource_model = \
            self.resource_model_parser.convert_to_resource_model(context.resource,
                                                                 VCenterDeployVMFromLinkedCloneResourceModel)

        if not Name:
            Name = jsonpickle.decode(context.resource.app_context.app_request_json)['name']

        deploy_from_template_details = DeployFromTemplateDetails(vcenter_template_resource_model, Name)

        params = [InputNameValue('deploy_data', jsonpickle.encode(deploy_from_template_details, unpicklable=False))]

        reservation_id = context.reservation.reservation_id
        result = session.ExecuteCommand(reservation_id,
                                        vcenter_template_resource_model.vcenter_name,
                                        "Resource",
                                        "deploy_from_linked_clone",
                                        params,
                                        False)

        return result.Output
    def test_parse_resource_info_model(self):
        resource_model_parser = ResourceModelParser()

        attributes = {
            'Access Mode': 'Trunk',
            'VLAN Id': '123',
            'Allocation Ranges': '2-4094',
            'Virtual Network': '',
            'Isolation Level': 'Exclusive'
        }
        resource_model = resource_model_parser.convert_to_resource_model(
            attributes, VLANAutoResourceModel)

        self.assertEqual(resource_model.access_mode, 'Trunk')
        self.assertEqual(resource_model.vlan_id, '123')
        self.assertEqual(resource_model.isolation_level, 'Exclusive')
        self.assertEqual(resource_model.allocation_ranges, '2-4094')
        self.assertEqual(resource_model.virtual_network, '')
        self.assertEqual(resource_model.virtual_network_attribute,
                         'Virtual Network')
Exemple #8
0
class CommandOrchestrator(object):
    def __init__(self):
        """
        Initialize the driver session, this function is called everytime a new instance of the driver is created
        in here the driver is going to be bootstrapped

        """
        synchronous_task_waiter = SynchronousTaskWaiter()
        cancellation_service = CommandCancellationService()
        pv_service = pyVmomiService(connect=SmartConnect,
                                    disconnect=Disconnect,
                                    task_waiter=synchronous_task_waiter)
        self.resource_model_parser = ResourceModelParser()
        port_group_name_generator = DvPortGroupNameGenerator()

        vnic_to_network_mapper = VnicToNetworkMapper(
            quali_name_generator=port_group_name_generator)
        resource_remover = CloudshellResourceRemover()
        ovf_service = OvfImageDeployerService(self.resource_model_parser)

        self.vm_loader = VMLoader(pv_service)

        ip_manager = VMIPManager()
        vm_details_provider = VmDetailsProvider(pyvmomi_service=pv_service,
                                                ip_manager=ip_manager)

        vm_deployer = VirtualMachineDeployer(
            pv_service=pv_service,
            name_generator=generate_unique_name,
            ovf_service=ovf_service,
            resource_model_parser=self.resource_model_parser,
            vm_details_provider=vm_details_provider)

        dv_port_group_creator = DvPortGroupCreator(
            pyvmomi_service=pv_service,
            synchronous_task_waiter=synchronous_task_waiter)
        virtual_machine_port_group_configurer = \
            VirtualMachinePortGroupConfigurer(pyvmomi_service=pv_service,
                                              synchronous_task_waiter=synchronous_task_waiter,
                                              vnic_to_network_mapper=vnic_to_network_mapper,
                                              vnic_service=VNicService(),
                                              name_gen=port_group_name_generator)
        virtual_switch_to_machine_connector = VirtualSwitchToMachineConnector(
            dv_port_group_creator, virtual_machine_port_group_configurer)

        # Command Wrapper
        self.command_wrapper = CommandWrapper(
            pv_service=pv_service,
            resource_model_parser=self.resource_model_parser,
            context_based_logger_factory=ContextBasedLoggerFactory())
        # Deploy Command
        self.deploy_command = DeployCommand(deployer=vm_deployer)

        # Virtual Switch Revoke
        self.virtual_switch_disconnect_command = \
            VirtualSwitchToMachineDisconnectCommand(
                pyvmomi_service=pv_service,
                port_group_configurer=virtual_machine_port_group_configurer,
                resource_model_parser=self.resource_model_parser)

        # Virtual Switch Connect
        virtual_switch_connect_command = \
            VirtualSwitchConnectCommand(
                pv_service=pv_service,
                virtual_switch_to_machine_connector=virtual_switch_to_machine_connector,
                dv_port_group_name_generator=DvPortGroupNameGenerator(),
                vlan_spec_factory=VlanSpecFactory(),
                vlan_id_range_parser=VLanIdRangeParser())
        self.connection_orchestrator = ConnectionCommandOrchestrator(
            connector=virtual_switch_connect_command,
            disconnector=self.virtual_switch_disconnect_command,
            resource_model_parser=self.resource_model_parser)

        self.folder_manager = FolderManager(
            pv_service=pv_service, task_waiter=synchronous_task_waiter)

        # Destroy VM Command
        self.destroy_virtual_machine_command = \
            DestroyVirtualMachineCommand(pv_service=pv_service,
                                         resource_remover=resource_remover,
                                         disconnector=self.virtual_switch_disconnect_command)
        # Power Command
        self.vm_power_management_command = \
            VirtualMachinePowerManagementCommand(pyvmomi_service=pv_service,
                                                 synchronous_task_waiter=synchronous_task_waiter)

        # Refresh IP command
        self.refresh_ip_command = RefreshIpCommand(
            pyvmomi_service=pv_service,
            resource_model_parser=self.resource_model_parser,
            ip_manager=ip_manager)

        # Get Vm Details command
        self.vm_details = VmDetailsCommand(
            pyvmomi_service=pv_service,
            vm_details_provider=vm_details_provider)

        # Save Snapshot
        self.snapshot_saver = SaveSnapshotCommand(
            pyvmomi_service=pv_service, task_waiter=synchronous_task_waiter)

        # Snapshot Restorer
        self.snapshot_restorer = SnapshotRestoreCommand(
            pyvmomi_service=pv_service, task_waiter=synchronous_task_waiter)

        self.snapshots_retriever = RetrieveSnapshotsCommand(
            pyvmomi_service=pv_service)

        self.save_app_command = SaveAppCommand(
            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)

        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, self.connection_orchestrator.connect_bulk, request)

        driver_response = DriverResponse()
        driver_response.actionResults = results
        driver_response_root = DriverResponseRoot()
        driver_response_root.driverResponse = driver_response
        return set_command_result(result=driver_response_root,
                                  unpicklable=False)

    def save_sandbox(self, context, save_actions, cancellation_context):
        """
        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:
        :return: list[SaveAppResult] save_app_results
        """
        connection = self.command_wrapper.execute_command_with_connection(
            context,
            self.save_app_command.save_app,
            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

        :param CancellationContext cancellation_context:
        :param ResourceCommandContext context: the context of the command
        :param DeployApp deploy_action:
        :return DeployAppResult deploy results
        """
        deploy_from_template_model = self.resource_model_parser.convert_to_resource_model(
            attributes=deploy_action.actionParams.deployment.attributes,
            resource_model_type=vCenterVMFromTemplateResourceModel)
        data_holder = DeployFromTemplateDetails(
            deploy_from_template_model, deploy_action.actionParams.appName)

        deploy_result_action = self.command_wrapper.execute_command_with_connection(
            context, self.deploy_command.execute_deploy_from_template,
            data_holder, cancellation_context, self.folder_manager)

        deploy_result_action.actionId = deploy_action.actionId
        return deploy_result_action

    def deploy_clone_from_vm(self, context, deploy_action,
                             cancellation_context):
        """
        Deploy Cloned VM From VM Command, will deploy vm from template

        :param CancellationContext cancellation_context:
        :param ResourceCommandContext context: the context of the command
        :param DeployApp deploy_action:
        :return DeployAppResult deploy results
        """
        deploy_from_vm_model = self.resource_model_parser.convert_to_resource_model(
            attributes=deploy_action.actionParams.deployment.attributes,
            resource_model_type=vCenterCloneVMFromVMResourceModel)
        data_holder = DeployFromTemplateDetails(
            deploy_from_vm_model, deploy_action.actionParams.appName)

        deploy_result_action = self.command_wrapper.execute_command_with_connection(
            context, self.deploy_command.execute_deploy_clone_from_vm,
            data_holder, cancellation_context, self.folder_manager)

        deploy_result_action.actionId = deploy_action.actionId
        return deploy_result_action

    def deploy_from_linked_clone(self, context, deploy_action,
                                 cancellation_context):
        """
        Deploy Cloned VM From VM Command, will deploy vm from template

        :param CancellationContext cancellation_context:
        :param ResourceCommandContext context: the context of the command
        :param DeployApp deploy_action:
        :return DeployAppResult deploy results
        """
        linked_clone_from_vm_model = self.resource_model_parser.convert_to_resource_model(
            attributes=deploy_action.actionParams.deployment.attributes,
            resource_model_type=VCenterDeployVMFromLinkedCloneResourceModel)
        data_holder = DeployFromTemplateDetails(
            linked_clone_from_vm_model, deploy_action.actionParams.appName)

        if not linked_clone_from_vm_model.vcenter_vm_snapshot:
            raise ValueError(
                'Please insert snapshot to deploy an app from a linked clone')

        deploy_result_action = self.command_wrapper.execute_command_with_connection(
            context, self.deploy_command.execute_deploy_from_linked_clone,
            data_holder, cancellation_context, self.folder_manager)

        deploy_result_action.actionId = deploy_action.actionId
        return deploy_result_action

    def deploy_from_image(self, context, deploy_action, cancellation_context):
        """
        Deploy From Image Command, will deploy vm from ovf image

        :param CancellationContext cancellation_context:
        :param ResourceCommandContext context: the context of the command
        :param DeployApp deploy_action:
        :return str deploy results
        """
        deploy_action.actionParams.deployment.attributes[
            'vCenter Name'] = context.resource.name
        deploy_from_image_model = self.resource_model_parser.convert_to_resource_model(
            attributes=deploy_action.actionParams.deployment.attributes,
            resource_model_type=vCenterVMFromImageResourceModel)
        data_holder = DeployFromImageDetails(
            deploy_from_image_model, deploy_action.actionParams.appName)

        # execute command
        deploy_result_action = self.command_wrapper.execute_command_with_connection(
            context, self.deploy_command.execute_deploy_from_image,
            data_holder, context.resource, cancellation_context,
            self.folder_manager)

        deploy_result_action.actionId = deploy_action.actionId
        return deploy_result_action

    # remote command
    def disconnect_all(self, context, ports):
        """
        Disconnect All Command, will the assign all the vnics on the vm to the default network,
        which is sign to be disconnected

        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """

        resource_details = self._parse_remote_model(context)
        # execute command
        res = self.command_wrapper.execute_command_with_connection(
            context, self.virtual_switch_disconnect_command.disconnect_all,
            resource_details.vm_uuid)
        return set_command_result(result=res, unpicklable=False)

    # remote command
    def disconnect(self, context, ports, network_name):
        """
        Disconnect Command, will disconnect the a specific network that is assign to the vm,
        the command will assign the default network for all the vnics that is assigned to the given network

        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param str network_name: the name of the network to disconnect from
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """
        resource_details = self._parse_remote_model(context)
        # execute command
        res = self.command_wrapper.execute_command_with_connection(
            context, self.virtual_switch_disconnect_command.disconnect,
            resource_details.vm_uuid, network_name)
        return set_command_result(result=res, unpicklable=False)

    # remote command
    def DeleteInstance(self, context, ports):
        """
        Destroy Vm Command, will only destroy the vm and will not remove the resource

        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """
        resource_details = self._parse_remote_model(context)
        # execute command
        res = self.command_wrapper.execute_command_with_connection(
            context, self.destroy_virtual_machine_command.DeleteInstance,
            resource_details.vm_uuid, resource_details.fullname)
        return set_command_result(result=res, unpicklable=False)

    # remote command
    def refresh_ip(self, context, cancellation_context, ports):
        """
        Refresh IP Command, will refresh the ip of the vm and will update it on the resource
        :param ResourceRemoteCommandContext context: the context the command runs on
        :param cancellation_context:
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """
        resource_details = self._parse_remote_model(context)
        # execute command
        res = self.command_wrapper.execute_command_with_connection(
            context, self.refresh_ip_command.refresh_ip, resource_details,
            cancellation_context,
            context.remote_endpoints[0].app_context.app_request_json)
        return set_command_result(result=res, unpicklable=False)

    # remote command
    def power_off(self, context, ports):
        """
        Powers off the remote vm
        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """
        return self._power_command(context, ports,
                                   self.vm_power_management_command.power_off)

    # remote command
    def power_on(self, context, ports):
        """
        Powers on the remote vm
        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        """
        return self._power_command(context, ports,
                                   self.vm_power_management_command.power_on)

    # remote command
    def power_cycle(self, context, ports, delay):
        """
        preforms a restart to the vm
        :param models.QualiDriverModels.ResourceRemoteCommandContext context: the context the command runs on
        :param list[string] ports: the ports of the connection between the remote resource and the local resource, NOT IN USE!!!
        :param number delay: the time to wait between the power on and off
        """
        self.power_off(context, ports)
        time.sleep(float(delay))
        return self.power_on(context, ports)

    def _power_command(self, context, ports, command):
        resource_details = self._parse_remote_model(context)

        # execute command
        res = self.command_wrapper.execute_command_with_connection(
            context, command, resource_details.vm_uuid,
            resource_details.fullname)
        return set_command_result(result=res, unpicklable=False)

    def _parse_remote_model(self, context):
        """
        parse the remote resource model and adds its full name
        :type context: models.QualiDriverModels.ResourceRemoteCommandContext

        """
        if not context.remote_endpoints:
            raise Exception('no remote resources found in context: {0}',
                            jsonpickle.encode(context, unpicklable=False))
        resource = context.remote_endpoints[0]

        dictionary = jsonpickle.decode(resource.app_context.deployed_app_json)
        holder = DeployDataHolder(dictionary)
        app_resource_detail = GenericDeployedAppResourceModel()
        app_resource_detail.vm_uuid = holder.vmdetails.uid
        app_resource_detail.cloud_provider = context.resource.fullname
        app_resource_detail.fullname = resource.fullname
        if hasattr(holder.vmdetails, 'vmCustomParams'):
            app_resource_detail.vm_custom_params = holder.vmdetails.vmCustomParams
        return app_resource_detail

    def power_on_not_roemote(self, context, vm_uuid, resource_fullname):
        # get connection details
        res = self.command_wrapper.execute_command_with_connection(
            context, self.vm_power_management_command.power_on, vm_uuid,
            resource_fullname)
        return set_command_result(result=res, unpicklable=False)

    def get_vm_uuid_by_name(self, context, vm_name):
        res = self.command_wrapper.execute_command_with_connection(
            context, self.vm_loader.load_vm_uuid_by_name, vm_name)
        return set_command_result(result=res, unpicklable=False)

    def get_vm_details(self, context, cancellation_context, requests_json):
        requests = DeployDataHolder(jsonpickle.decode(requests_json)).items
        res = self.command_wrapper.execute_command_with_connection(
            context, self.vm_details.get_vm_details, context.resource,
            requests, cancellation_context)
        return set_command_result(result=res, unpicklable=False)

    def save_snapshot(self, context, snapshot_name, save_memory='No'):
        """
        Saves virtual machine to a snapshot
        :param context: resource context of the vCenterShell
        :type context: models.QualiDriverModels.ResourceCommandContext
        :param snapshot_name: snapshot name to save to
        :type snapshot_name: str
        :param save_memory: Snapshot the virtual machine's memory. Lookup, Yes / No
        :type save_memory: str
        :return:
        """
        resource_details = self._parse_remote_model(context)
        created_snapshot_path = self.command_wrapper.execute_command_with_connection(
            context, self.snapshot_saver.save_snapshot,
            resource_details.vm_uuid, snapshot_name, save_memory)
        return set_command_result(created_snapshot_path)

    def restore_snapshot(self, context, snapshot_name):
        """
        Restores virtual machine from a snapshot
        :param context: resource context of the vCenterShell
        :type context: models.QualiDriverModels.ResourceCommandContext
        :param snapshot_name: snapshot name to save to
        :type snapshot_name: str
        :return:
        """
        resource_details = self._parse_remote_model(context)
        self.command_wrapper.execute_command_with_connection(
            context, self.snapshot_restorer.restore_snapshot,
            resource_details.vm_uuid, resource_details.fullname, snapshot_name)

    def get_snapshots(self, context):
        """
        Returns list of snapshots
        :param context: resource context of the vCenterShell
        :type context: models.QualiDriverModels.ResourceCommandContext
        :return:
        """
        resource_details = self._parse_remote_model(context)
        res = self.command_wrapper.execute_command_with_connection(
            context, self.snapshots_retriever.get_snapshots,
            resource_details.vm_uuid)
        return set_command_result(result=res, unpicklable=False)

    def orchestration_save(self, context, mode="shallow", custom_params=None):
        """
        Creates a snapshot with a unique name and returns SavedResults as JSON
        :param context: resource context of the vCenterShell
        :param mode: Snapshot save mode, default shallow. Currently not it use
        :param custom_params: Set of custom parameter to be supported in the future
        :return: SavedResults serialized as JSON
        :rtype: SavedResults
        """
        resource_details = self._parse_remote_model(context)
        created_date = datetime.now()
        snapshot_name = created_date.strftime('%y_%m_%d %H_%M_%S_%f')
        created_snapshot_path = self.save_snapshot(context=context,
                                                   snapshot_name=snapshot_name)

        created_snapshot_path = self._strip_double_quotes(
            created_snapshot_path)

        orchestration_saved_artifact = OrchestrationSavedArtifact()
        orchestration_saved_artifact.artifact_type = 'vcenter_snapshot'
        orchestration_saved_artifact.identifier = created_snapshot_path

        saved_artifacts_info = OrchestrationSavedArtifactsInfo(
            resource_name=resource_details.cloud_provider,
            created_date=created_date,
            restore_rules={'requires_same_resource': True},
            saved_artifact=orchestration_saved_artifact)

        orchestration_save_result = OrchestrationSaveResult(
            saved_artifacts_info)

        return set_command_result(result=orchestration_save_result,
                                  unpicklable=False)

    @staticmethod
    def _strip_double_quotes(created_snapshot_path):
        if created_snapshot_path.startswith(
                '"') and created_snapshot_path.endswith('"'):
            created_snapshot_path = created_snapshot_path[1:-1]
        return created_snapshot_path

    def orchestration_restore(self, context, saved_details):
        """

        :param context:
        :param saved_details:
        :return:
        """
        saved_artifacts_info = get_result_from_command_output(saved_details)
        snapshot_name = saved_artifacts_info['saved_artifacts_info'][
            'saved_artifact']['identifier']
        return self.restore_snapshot(context=context,
                                     snapshot_name=snapshot_name)