def test_execute_command_with_params_and_vcetner_data_model_with_session_inject(self): # arrange def fake_command_with_connection_return_true_1(si, vcenter_data_model, session, fake1, fake2): return True def fake_command_with_connection_return_true_2(si, session, vcenter_data_model, fake1, fake2): return True wrapper = CommandWrapper(pv_service=self.pv_service, cloud_shell_helper=self.cloud_shell_helper, resource_model_parser= self.resource_model_parser, context_based_logger_factory=Mock()) context = self._create_resource_command_context() # act res_1 = wrapper.execute_command_with_connection(context, fake_command_with_connection_return_true_1, 'param 1', 'param2') res_2 = wrapper.execute_command_with_connection(context, fake_command_with_connection_return_true_2, 'param 1', 'param2') # assert self.assertTrue(res_1) self.assertTrue(res_2)
def test_execute_command_with_params_and_vcetner_data_model_with_session_inject( self): # arrange def fake_command_with_connection_return_true_1(si, vcenter_data_model, session, fake1, fake2): return True def fake_command_with_connection_return_true_2(si, session, vcenter_data_model, fake1, fake2): return True wrapper = CommandWrapper( pv_service=self.pv_service, cloud_shell_helper=self.cloud_shell_helper, resource_model_parser=self.resource_model_parser, context_based_logger_factory=Mock()) context = self._create_resource_command_context() # act res_1 = wrapper.execute_command_with_connection( context, fake_command_with_connection_return_true_1, 'param 1', 'param2') res_2 = wrapper.execute_command_with_connection( context, fake_command_with_connection_return_true_2, 'param 1', 'param2') # assert self.assertTrue(res_1) self.assertTrue(res_2)
def test_execute_command_with_params(self): # arrange def fake_command_with_connection_return_true(si, fake1, fake2): return True wrapper = CommandWrapper(pv_service=self.pv_service, cloud_shell_helper=self.cloud_shell_helper, resource_model_parser= self.resource_model_parser, context_based_logger_factory=Mock()) context = self._create_resource_command_context() # act res = wrapper.execute_command_with_connection(context, fake_command_with_connection_return_true, 'param 1', 'param2') # assert self.assertTrue(res)
def test_execute_command_with_params(self): # arrange def fake_command_with_connection_return_true(si, fake1, fake2): return True wrapper = CommandWrapper( pv_service=self.pv_service, cloud_shell_helper=self.cloud_shell_helper, resource_model_parser=self.resource_model_parser, context_based_logger_factory=Mock()) context = self._create_resource_command_context() # act res = wrapper.execute_command_with_connection( context, fake_command_with_connection_return_true, 'param 1', 'param2') # assert self.assertTrue(res)
def test_execute_command_with_params(self): # arrange def fake_command_with_connection_return_true(si, fake1, fake2): return True with patch( 'cloudshell.cp.vcenter.common.wrappers.command_wrapper.CloudShellSessionContext' ) as session: wrapper = CommandWrapper( pv_service=self.pv_service, resource_model_parser=self.resource_model_parser, context_based_logger_factory=Mock()) context = self._create_resource_command_context() # act res = wrapper.execute_command_with_connection( context, fake_command_with_connection_return_true, 'param 1', 'param2') # assert self.assertTrue(res) session.assert_called_with(context)
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 :param context: models.QualiDriverModels.InitCommandContext """ self.cs_helper = CloudshellDriverHelper() synchronous_task_waiter = SynchronousTaskWaiter() 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) vm_deployer = VirtualMachineDeployer( pv_service=pv_service, name_generator=generate_unique_name, ovf_service=ovf_service, cs_helper=self.cs_helper, resource_model_parser=ResourceModelParser()) 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, cloud_shell_helper=self.cs_helper, 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) # 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) ip_manager = VMIPManager() # Refresh IP command self.refresh_ip_command = RefreshIpCommand( pyvmomi_service=pv_service, resource_model_parser=ResourceModelParser(), ip_manager=ip_manager) # 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) 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 deploy_from_template(self, context, deploy_data): """ Deploy From Template Command, will deploy vm from template :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: {"template_resource_model": {"vm_location": "", "vcenter_name": "VMware vCenter", "refresh_ip_timeout": "600", "auto_delete": "True", "vm_storage": "", "auto_power_on": "True", "autoload": "True", "ip_regex": "", "auto_power_off": "True", "vcenter_template": "Alex\\test", "vm_cluster": "", "vm_resource_pool": "", "wait_for_ip": "True"}, "app_name": "Temp"} :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) data_holder.template_resource_model.vcenter_template = \ back_slash_to_front_converter(data_holder.template_resource_model.vcenter_template) # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_from_template, data_holder) return set_command_result(result=result, unpicklable=False) def deploy_clone_from_vm(self, context, deploy_data): """ Deploy Cloned VM From VM Command, will deploy vm from template :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: {"template_resource_model": {"vm_location": "", "vcenter_name": "VMware vCenter", "refresh_ip_timeout": "600", "auto_delete": "True", "vm_storage": "", "auto_power_on": "True", "autoload": "True", "ip_regex": "", "auto_power_off": "True", "vcenter_template": "Alex\\test", "vm_cluster": "", "vm_resource_pool": "", "wait_for_ip": "True"}, "app_name": "Temp"} :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) data_holder.template_resource_model.vcenter_vm = \ back_slash_to_front_converter(data_holder.template_resource_model.vcenter_vm) # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_clone_from_vm, data_holder) return set_command_result(result=result, unpicklable=False) def deploy_from_linked_clone(self, context, deploy_data): """ Deploy Cloned VM From VM Command, will deploy vm from template :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: {"template_resource_model": {"vm_location": "", "vcenter_name": "VMware vCenter", "refresh_ip_timeout": "600", "auto_delete": "True", "vm_storage": "", "auto_power_on": "True", "autoload": "True", "ip_regex": "", "auto_power_off": "True", "vcenter_template": "Alex\\test", "vm_cluster": "", "vm_resource_pool": "", "wait_for_ip": "True"}, "app_name": "Temp"} :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) if not data_holder.template_resource_model.vcenter_vm: raise ValueError('Please insert vm to deploy from') data_holder.template_resource_model.vcenter_vm = \ back_slash_to_front_converter(data_holder.template_resource_model.vcenter_vm) if not data_holder.template_resource_model.vcenter_vm_snapshot: raise ValueError('Please insert snapshot to deploy from') data_holder.template_resource_model.vcenter_vm_snapshot = \ back_slash_to_front_converter(data_holder.template_resource_model.vcenter_vm_snapshot) # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_from_linked_clone, data_holder) return set_command_result(result=result, unpicklable=False) def deploy_from_image(self, context, deploy_data): """ Deploy From Image Command, will deploy vm from ovf image :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: { "image_url": "c:\image.ovf" or "\\nas\shared\image.ovf" or "http://192.168.65.88/ovf/Debian%2064%20-%20Yoav.ovf", "cluster_name": "QualiSB Cluster", "resource_pool": "LiverPool", "datastore_name": "eric ds cluster", "datacenter_name": "QualiSB" "power_on": False "app_name": "appName" "user_arguments": ["--compress=9", " --schemaValidate", "--etc"] } :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_from_image, data_holder, context.resource) return set_command_result(result=result, unpicklable=False) # 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 destroy_vm_only(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.destroy_vm_only, 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 models.QualiDriverModels.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.vm_uuid, resource_details.fullname, cancellation_context) 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 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 save_snapshot(self, context, snapshot_name): """ 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 :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) 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 = date.today() 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)
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)
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 :param context: models.QualiDriverModels.InitCommandContext """ self.cs_helper = CloudshellDriverHelper() pv_service = pyVmomiService(SmartConnect, Disconnect) synchronous_task_waiter = SynchronousTaskWaiter() 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) vm_deployer = VirtualMachineDeployer(pv_service=pv_service, name_generator=generate_unique_name, ovf_service=ovf_service, cs_helper=self.cs_helper, resource_model_parser=ResourceModelParser()) 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, cloud_shell_helper=self.cs_helper, 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) # 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=ResourceModelParser()) 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 deploy_from_template(self, context, deploy_data): """ Deploy From Template Command, will deploy vm from template :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: {"template_resource_model": {"vm_location": "", "vcenter_name": "VMware vCenter", "refresh_ip_timeout": "600", "auto_delete": "True", "vm_storage": "", "auto_power_on": "True", "autoload": "True", "ip_regex": "", "auto_power_off": "True", "vcenter_template": "Alex\\test", "vm_cluster": "", "vm_resource_pool": "", "wait_for_ip": "True"}, "app_name": "Temp"} :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) data_holder.template_resource_model.vcenter_template = \ data_holder.template_resource_model.vcenter_template.replace('\\', '/') # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_from_template, data_holder, context.resource) return set_command_result(result=result, unpicklable=False) def deploy_from_image(self, context, deploy_data): """ Deploy From Image Command, will deploy vm from ovf image :param models.QualiDriverModels.ResourceCommandContext context: the context of the command :param str deploy_data: represent a json of the parameters, example: { "image_url": "c:\image.ovf" or "\\nas\shared\image.ovf" or "http://192.168.65.88/ovf/Debian%2064%20-%20Yoav.ovf", "cluster_name": "QualiSB Cluster", "resource_pool": "LiverPool", "datastore_name": "eric ds cluster", "datacenter_name": "QualiSB" "power_on": False "app_name": "appName" "user_arguments": ["--compress=9", " --schemaValidate", "--etc"] } :return str deploy results """ # get command parameters from the environment data = jsonpickle.decode(deploy_data) data_holder = DeployDataHolder(data) # execute command result = self.command_wrapper.execute_command_with_connection( context, self.deploy_command.execute_deploy_from_image, data_holder, context.resource) return set_command_result(result=result, unpicklable=False) # 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 destroy_vm(self, context, ports): """ Destroy Vm Command, will destroy the vm and 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) reservation_id = context.remote_reservation.reservation_id # execute command res = self.command_wrapper.execute_command_with_connection( context, self.destroy_virtual_machine_command.destroy, resource_details.vm_uuid, resource_details.fullname, reservation_id) return set_command_result(result=res, unpicklable=False) # remote command def destroy_vm_only(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) reservation_id = context.remote_reservation.reservation_id # execute command res = self.command_wrapper.execute_command_with_connection( context, self.destroy_virtual_machine_command.destroy_vm_only, resource_details.vm_uuid, resource_details.fullname, reservation_id) 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 models.QualiDriverModels.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.vm_uuid, resource_details.fullname, cancellation_context) 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 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)