class VCenterShellDriver(ResourceDriverInterface): def cleanup(self): pass def __init__(self): """ ctor must be without arguments, it is created with reflection at run time """ self.request_parser = DriverRequestParser() self.command_orchestrator = CommandOrchestrator( ) # type: CommandOrchestrator self.deployments = dict() self.deployments[ 'vCenter Clone VM From VM'] = self.deploy_clone_from_vm self.deployments[ 'VCenter Deploy VM From Linked Clone'] = self.deploy_from_linked_clone self.deployments[ 'vCenter VM From Template'] = self.deploy_from_template self.deployments['vCenter VM From Image'] = self.deploy_from_image def initialize(self, **kwargs): pass def ApplyConnectivityChanges(self, context, request): return self.command_orchestrator.connect_bulk(context, request) def disconnect_all(self, context, ports): return self.command_orchestrator.disconnect_all(context, ports) def disconnect(self, context, ports, network_name): return self.command_orchestrator.disconnect(context, ports, network_name) def DeleteInstance(self, context, ports): return self.command_orchestrator.DeleteInstance(context, ports) def remote_refresh_ip(self, context, cancellation_context, ports): return self.command_orchestrator.refresh_ip(context, cancellation_context, ports) def PowerOff(self, context, ports): return self.command_orchestrator.power_off(context, ports) # the name is by the Qualisystems conventions def PowerOn(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.command_orchestrator.power_on(context, ports) # the name is by the Qualisystems conventions def PowerCycle(self, context, ports, delay): return self.command_orchestrator.power_cycle(context, ports, delay) def Deploy(self, context, request=None, cancellation_context=None): """ :param ResourceCommandContext context: :param str request: json string to be parsed :param cancellation_context: :return: """ RESOURCE_POOL_ATTR = "App Pool Name" CP_RESTRICTED_ATTR = "Restricted App Model Pools" api = CloudShellSessionContext(context).get_api() res_id = context.reservation.reservation_id # VALIDATE THAT CLOUD PROVIDER RESOURCE HAS POOL LIST Attribute cp_attrs = context.resource.attributes try: cp_pool_list_val = cp_attrs[CP_RESTRICTED_ATTR] except KeyError: pass else: api.WriteMessageToReservationOutput(res_id, "=== full request json ===") api.WriteMessageToReservationOutput(res_id, request) request_obj = json.loads(request) request_action_params = request_obj["driverRequest"]["actions"][0][ "actionParams"] app_name = request_action_params["appName"] deployment = request_action_params["deployment"] app_resource = request_action_params["appResource"] app_resource_attrs = app_resource["attributes"] pool_attr_search = [ attr for attr in app_resource_attrs if attr["attributeName"] == RESOURCE_POOL_ATTR ] if pool_attr_search: app_pool_attr_val = pool_attr_search[0]["attributeValue"] restricted_attrs_dict = get_cp_restricted_attrs_dict( cp_pool_list_val) try: app_pool_limit = restricted_attrs_dict[app_pool_attr_val] except KeyError: not_found_msg = "{} pool name key not in cp restricted list {}".format( app_pool_attr_val, restricted_attrs_dict) api.WriteMessageToReservationOutput(res_id, not_found_msg) else: # count deployed apps all_generic_app_resources = api.FindResources( resourceFamily="Generic App Family").Resources # collect matching apps matching_apps = [] for resource in all_generic_app_resources: attrs = api.GetResourceDetails( resource.Name).ResourceAttributes attr_search = [ attr for attr in attrs if attr.Name == RESOURCE_POOL_ATTR ] if attr_search: attr_val = attr_search[0].Value if attr_val == app_pool_attr_val: matching_apps.append(resource) # PERFORM VALIDATION if len(matching_apps) >= int(app_pool_limit): matching_app_names = [r.Name for r in matching_apps] exc_msg = "Can not deploy '{}'. The pool '{}' has reached it's limit of {}. Current Apps in Pool: {}".format( app_name, app_pool_attr_val, app_pool_limit, matching_app_names) api.WriteMessageToReservationOutput( res_id, '<span style="color:red">{}</span>'.format( exc_msg)) raise AppLimitDeploymentError(exc_msg) actions = self.request_parser.convert_driver_request_to_actions( request) deploy_action = single(actions, lambda x: isinstance(x, DeployApp)) deployment_name = deploy_action.actionParams.deployment.deploymentPath if deployment_name in self.deployments.keys(): deploy_method = self.deployments[deployment_name] deploy_result = deploy_method(context, deploy_action, cancellation_context) return DriverResponse([deploy_result]).to_driver_response_json() else: raise Exception('Could not find the deployment') def SaveApp(self, context, request, cancellation_context=None): actions = self.request_parser.convert_driver_request_to_actions( request) save_actions = [x for x in actions if isinstance(x, SaveApp)] save_app_results = self.command_orchestrator.save_sandbox( context, save_actions, cancellation_context) return DriverResponse(save_app_results).to_driver_response_json() def DeleteSavedApps(self, context, request, cancellation_context=None): actions = self.request_parser.convert_driver_request_to_actions( request) delete_actions = [x for x in actions if isinstance(x, DeleteSavedApp)] save_app_results = self.command_orchestrator.delete_saved_sandbox( context, delete_actions, cancellation_context) return DriverResponse(save_app_results).to_driver_response_json() def deploy_from_template(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_from_template( context, deploy_action, cancellation_context) def deploy_clone_from_vm(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_clone_from_vm( context, deploy_action, cancellation_context) def deploy_from_linked_clone(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_from_linked_clone( context, deploy_action, cancellation_context) def deploy_from_image(self, context, deploy_action, cancellation_context): if cancellation_context is None: cancellation_context = CancellationContext() return self.command_orchestrator.deploy_from_image( context, deploy_action, cancellation_context) def get_inventory(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ validator = VCenterAutoModelDiscovery() return validator.validate_and_discover(context) def remote_save_snapshot(self, context, ports, snapshot_name, save_memory): """ Saves virtual machine to a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :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: """ return self.command_orchestrator.save_snapshot(context, snapshot_name, save_memory) def remote_restore_snapshot(self, context, ports, snapshot_name): """ Restores virtual machine from a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: Snapshot name to restore from :type snapshot_name: str :return: """ return self.command_orchestrator.restore_snapshot( context, snapshot_name) def remote_get_snapshots(self, context, ports): """ Returns list of snapshots :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :return: list """ return self.command_orchestrator.get_snapshots(context) def orchestration_save(self, context, ports, mode="shallow", custom_params=None): return self.command_orchestrator.orchestration_save( context, mode, custom_params) def orchestration_restore(self, context, ports, saved_details): return self.command_orchestrator.orchestration_restore( context, saved_details) def get_vm_uuid(self, context, vm_name): return self.command_orchestrator.get_vm_uuid_by_name(context, vm_name) def GetVmDetails(self, context, cancellation_context, requests): return self.command_orchestrator.get_vm_details( context, cancellation_context, requests)
class TestCommandOrchestrator(TestCase): def setUp(self): self.resource = create_autospec(ResourceInfo) self.resource.ResourceModelName = 'VMwarev Center' self.resource.ResourceAttributes = { 'User': '******', 'Password': '******', 'Default dvSwitch': 'switch1', 'Holding Network': 'anetwork', 'Default Port Group Location': 'Quali', 'VM Cluster': 'Quali', 'VM Location': 'Quali', 'VM Resource Pool': 'Quali', 'VM Storage': 'Quali', 'Shutdown Method': 'hard', 'OVF Tool Path': 'C\\program files\ovf', 'Execution Server Selector': '', 'Reserved Networks': 'vlan65', 'Default Datacenter': 'QualiSB' } self.context = Mock() session = Mock() remote_resource = Mock() remote_resource.fullname = 'this is full name of the remote resource' remote_resource.uuid = 'this is full uuis of the remote resource' self.connection_details = Mock() self.context.resource = self.resource self.context.remote_endpoints = [self.resource] self.command_orchestrator = CommandOrchestrator() self.command_orchestrator.command_wrapper.execute_command_with_connection = Mock( return_value=True) self.command_orchestrator.cs_helper = Mock() self.command_orchestrator.cs_helper.get_session = Mock( return_value=session) self.command_orchestrator.cs_helper.get_connection_details = Mock( return_value=self.connection_details) self.ports = [Mock()] self.command_orchestrator._parse_remote_model = Mock( return_value=remote_resource) def test_disconnect_all(self): # act self.command_orchestrator.disconnect_all(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_disconnect(self): # act self.command_orchestrator.disconnect(self.context, self.ports, 'network') # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_destroy_vm_only(self): # act self.command_orchestrator.destroy_vm_only(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_template(self): # act self.command_orchestrator.deploy_from_template( self.context, '{"name": "name", "template_resource_model": {"vcenter_template": ""}}' ) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_vm_from_vm(self): # act self.command_orchestrator.deploy_clone_from_vm( self.context, '{"name": "name", "template_resource_model": {"vcenter_vm": ""}}') # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_snapshot(self): # act self.command_orchestrator.deploy_from_linked_clone( self.context, '{"name": "name", "template_resource_model": {"vcenter_vm": "name", "vcenter_vm_snapshot": "snap"}}' ) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_image(self): # act self.command_orchestrator.deploy_from_image(self.context, '{"name": "name"}') # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_off(self): # act self.command_orchestrator.power_off(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_on(self): # act self.command_orchestrator.power_on(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_cycle(self): # act self.command_orchestrator.power_cycle(self.context, self.ports, 0.0001) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_refresh_ip(self): # act cancellation_context = object() self.command_orchestrator.refresh_ip( self.context, cancellation_context=cancellation_context, ports=self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_get_uuid(self): self.command_orchestrator.get_vm_uuid_by_name(self.context, 'Name') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_save_snapshot(self): self.command_orchestrator.save_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_restore_snapshot(self): self.command_orchestrator.restore_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_get_snapshots(self): self.command_orchestrator.get_snapshots(self.context) self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_orchestration_save(self): # Arrange with patch(SAVE_SNAPSHOT) as save_snapshot_mock: save_snapshot_mock.return_value = '"new_snapshot"' remote_command_context = create_autospec( ResourceRemoteCommandContext) remote_command_context.resource = create_autospec( ResourceContextDetails) remote_command_context.resource.fullname = 'vcenter' endpoint = create_autospec(ResourceContextDetails) endpoint.fullname = 'vm_111' endpoint.app_context = create_autospec(AppContext) endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}' remote_command_context.remote_endpoints = [endpoint] # Act saved_result = CommandOrchestrator().orchestration_save( context=remote_command_context, mode='shallow', custom_params=None) # Assert save_snapshot_mock.assert_called_once() saved_result_dict = jsonpickle.decode(saved_result) self.assertEqual( saved_result_dict['saved_artifacts_info']['saved_artifact'] ['artifact_type'], 'vcenter_snapshot') self.assertEqual( saved_result_dict['saved_artifacts_info']['saved_artifact'] ['identifier'], 'new_snapshot') self.assertEqual( saved_result_dict['saved_artifacts_info']['resource_name'], 'vcenter') self.assertIsNotNone( saved_result_dict['saved_artifacts_info']['created_date']) def test_orchestration_restore(self): # Arrange with patch(RESTORE_SNAPSHOT) as mock_restore_snapshot: # Act self.command_orchestrator.orchestration_restore( self.context, '''{ "saved_artifacts_info": { "resource_name": "ex cillum sed laboris", "created_date": "4313-10-12T18:03:15.053Z", "restore_rules": { "requires_same_resource": false }, "saved_artifact": { "artifact_type": "veniam in qui", "identifier": "deserunt1" } } }''') # Assert mock_restore_snapshot.assert_called_once_with( context=self.context, snapshot_name='deserunt1')
class VCenterShellDriver (ResourceDriverInterface): def cleanup(self): pass def __init__(self): """ ctor must be without arguments, it is created with reflection at run time """ self.command_orchestrator = CommandOrchestrator() # type: CommandOrchestrator def initialize(self): pass def ApplyConnectivityChanges(self, context, request): return self.command_orchestrator.connect_bulk(context, request) def disconnect_all(self, context, ports): return self.command_orchestrator.disconnect_all(context, ports) def disconnect(self, context, ports, network_name): return self.command_orchestrator.disconnect(context, ports, network_name) def destroy_vm(self, context, ports): return self.command_orchestrator.destroy_vm(context, ports) def destroy_vm_only(self, context, ports): return self.command_orchestrator.destroy_vm_only(context, ports) def remote_refresh_ip(self, context, cancellation_context, ports): return self.command_orchestrator.refresh_ip(context, cancellation_context, ports) def PowerOff(self, context, ports): return self.command_orchestrator.power_off(context, ports) # the name is by the Qualisystems conventions def PowerOn(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.command_orchestrator.power_on(context, ports) # the name is by the Qualisystems conventions def PowerCycle(self, context, ports, delay): return self.command_orchestrator.power_cycle(context, ports, delay) def deploy_from_template(self, context, deploy_data): return self.command_orchestrator.deploy_from_template(context, deploy_data) def deploy_from_image(self, context, deploy_data): return self.command_orchestrator.deploy_from_image(context, deploy_data) def get_inventory(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ validator = VCenterAutoModelDiscovery() return validator.validate_and_discover(context)
class VCenterShellDriver(ResourceDriverInterface): def cleanup(self): pass def __init__(self): """ ctor must be without arguments, it is created with reflection at run time """ self.command_orchestrator = CommandOrchestrator( ) # type: CommandOrchestrator def initialize(self): pass def ApplyConnectivityChanges(self, context, request): return self.command_orchestrator.connect_bulk(context, request) def disconnect_all(self, context, ports): return self.command_orchestrator.disconnect_all(context, ports) def disconnect(self, context, ports, network_name): return self.command_orchestrator.disconnect(context, ports, network_name) def destroy_vm_only(self, context, ports): return self.command_orchestrator.destroy_vm_only(context, ports) def remote_refresh_ip(self, context, cancellation_context, ports): return self.command_orchestrator.refresh_ip(context, cancellation_context, ports) def PowerOff(self, context, ports): return self.command_orchestrator.power_off(context, ports) # the name is by the Qualisystems conventions def PowerOn(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.command_orchestrator.power_on(context, ports) # the name is by the Qualisystems conventions def PowerCycle(self, context, ports, delay): return self.command_orchestrator.power_cycle(context, ports, delay) def deploy_from_template(self, context, deploy_data): return self.command_orchestrator.deploy_from_template( context, deploy_data) def deploy_clone_from_vm(self, context, deploy_data): return self.command_orchestrator.deploy_clone_from_vm( context, deploy_data) def deploy_from_linked_clone(self, context, deploy_data): return self.command_orchestrator.deploy_from_linked_clone( context, deploy_data) def deploy_from_image(self, context, deploy_data): return self.command_orchestrator.deploy_from_image( context, deploy_data) def get_inventory(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ validator = VCenterAutoModelDiscovery() return validator.validate_and_discover(context) def remote_save_snapshot(self, context, ports, snapshot_name): """ Saves virtual machine to a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: snapshot name to save to :type snapshot_name: str :return: """ return self.command_orchestrator.save_snapshot(context, snapshot_name) def remote_restore_snapshot(self, context, ports, snapshot_name): """ Restores virtual machine from a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: Snapshot name to restore from :type snapshot_name: str :return: """ return self.command_orchestrator.restore_snapshot( context, snapshot_name) def remote_get_snapshots(self, context, ports): """ Returns list of snapshots :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :return: list """ return self.command_orchestrator.get_snapshots(context) def orchestration_save(self, context, ports, mode="shallow", custom_params=None): return self.command_orchestrator.orchestration_save( context, mode, custom_params) def orchestration_restore(self, context, ports, saved_details): return self.command_orchestrator.orchestration_restore( context, saved_details) def get_vm_uuid(self, context, vm_name): return self.command_orchestrator.get_vm_uuid_by_name(context, vm_name)
class TestCommandOrchestrator(TestCase): def setUp(self): self.resource = create_autospec(ResourceInfo) self.resource.ResourceModelName = 'VMwarev Center' self.resource.ResourceAttributes = {'User': '******', 'Password': '******', 'Default dvSwitch': 'switch1', 'Holding Network': 'anetwork', 'Default Port Group Location': 'Quali', 'VM Cluster': 'Quali', 'VM Location': 'Quali', 'VM Resource Pool': 'Quali', 'VM Storage': 'Quali', 'Shutdown Method': 'hard', 'OVF Tool Path': 'C\\program files\ovf', 'Execution Server Selector': '', 'Reserved Networks': 'vlan65', 'Default Datacenter': 'QualiSB' } self.context = Mock() session = Mock() remote_resource = Mock() remote_resource.fullname = 'this is full name of the remote resource' remote_resource.uuid = 'this is full uuis of the remote resource' self.connection_details = Mock() self.context.resource = self.resource self.context.remote_endpoints = [self.resource] self.command_orchestrator = CommandOrchestrator() self.command_orchestrator.command_wrapper.execute_command_with_connection = Mock(return_value=True) self.command_orchestrator.cs_helper = Mock() self.command_orchestrator.cs_helper.get_session = Mock(return_value=session) self.command_orchestrator.cs_helper.get_connection_details = Mock(return_value=self.connection_details) self.ports = [Mock()] self.command_orchestrator._parse_remote_model = Mock(return_value=remote_resource) def test_disconnect_all(self): # act self.command_orchestrator.disconnect_all(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_disconnect(self): # act self.command_orchestrator.disconnect(self.context, self.ports, 'network') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_destroy_vm(self): # act self.command_orchestrator.destroy_vm(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_from_template(self): # act self.command_orchestrator.deploy_from_template(self.context, '{"name": "name", "template_resource_model": {"vcenter_template": ""}}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_from_image(self): # act self.command_orchestrator.deploy_from_image(self.context, '{"name": "name"}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_off(self): # act self.command_orchestrator.power_off(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_on(self): # act self.command_orchestrator.power_on(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_cycle(self): # act self.command_orchestrator.power_cycle(self.context, self.ports, 0.0001) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_refresh_ip(self): # act cancellation_context = object() self.command_orchestrator.refresh_ip(self.context, cancellation_context=cancellation_context, ports=self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called)
class TestCommandOrchestrator(TestCase): def setUp(self): self.deploy_action = DeployApp() self.deploy_action.actionId = '0a21384c-5620-4e6a-b162-c726681865a9' self.deploy_action.actionParams = DeployAppParams() self.deploy_action.actionParams.appName = 'myApp' self.deploy_action.actionParams.appResource = AppResourceInfo() self.deploy_action.actionParams.appResource.attributes = { "Public IP": "", "Password": "******", "User": "******" } self.deploy_action.actionParams.deployment = DeployAppDeploymentInfo() self.deploy_action.actionParams.deployment.deploymentPath = 'deployment model name' self.deploy_action.actionParams.deployment.attributes = { "Default Datacenter": "", "Auto Power Off": "True", "Auto Power On": "True", "Wait for IP": "True", "VM Cluster": "", "VM Location": "", "VM Storage": "", "VM Resource Pool": "", "vCenter Image": "c:\\tinyvm1.ova", "vCenter Image Arguments": "", "IP Regex": "", "Refresh IP Timeout": "600", "Auto Delete": "True", "Autoload": "True", "VCenter VM": "sds", "VCenter VM Snapshot": "sds", "VCenter Template": "dsds", "Behavior during save": "Powered Off" } self.resource = create_autospec(ResourceInfo) self.resource.name = 'Cloud1' self.resource.ResourceModelName = 'VMwarev Center' self.resource.ResourceAttributes = { 'User': '******', 'Password': '******', 'Default dvSwitch': 'switch1', 'Holding Network': 'anetwork', 'Default Port Group Location': 'Quali', 'VM Cluster': 'Quali', 'VM Location': 'Quali', 'VM Resource Pool': 'Quali', 'VM Storage': 'Quali', 'Shutdown Method': 'hard', 'OVF Tool Path': 'C\\program files\ovf', 'Execution Server Selector': '', 'Reserved Networks': 'vlan65', 'Default Datacenter': 'QualiSB' } self.context = Mock() session = Mock() remote_resource = Mock() remote_resource.fullname = 'this is full name of the remote resource' remote_resource.uuid = 'this is full uuis of the remote resource' self.connection_details = Mock() self.context.resource = self.resource self.context.resource.app_context = Mock() self.context.remote_endpoints = Mock() self.context.remote_endpoints = [self.resource] self.command_orchestrator = CommandOrchestrator() self.command_orchestrator.command_wrapper.execute_command_with_connection = Mock( return_value=DeployAppResult()) self.ports = [Mock()] self.command_orchestrator._parse_remote_model = Mock( return_value=remote_resource) def test_disconnect_all(self): # act self.command_orchestrator.disconnect_all(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_disconnect(self): # act self.command_orchestrator.disconnect(self.context, self.ports, 'network') # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_DeleteInstance(self): # act self.command_orchestrator.DeleteInstance(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_template(self): # act cancellation_context = object() self.command_orchestrator.deploy_from_template(self.context, self.deploy_action, cancellation_context) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_vm_from_vm(self): # act cancellation_context = object() self.command_orchestrator.deploy_clone_from_vm(self.context, self.deploy_action, cancellation_context) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_snapshot(self): # act cancellation_context = object() self.command_orchestrator.deploy_from_linked_clone( self.context, self.deploy_action, cancellation_context) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_deploy_from_image(self): # act cancellation_context = object() self.command_orchestrator.deploy_from_image(self.context, self.deploy_action, cancellation_context) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_off(self): # act self.command_orchestrator.power_off(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_on(self): # act self.command_orchestrator.power_on(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_power_cycle(self): # act self.command_orchestrator.power_cycle(self.context, self.ports, 0.0001) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_refresh_ip(self): # act cancellation_context = object() self.command_orchestrator.refresh_ip( self.context, cancellation_context=cancellation_context, ports=self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_get_uuid(self): self.command_orchestrator.get_vm_uuid_by_name(self.context, 'Name') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_save_snapshot(self): self.command_orchestrator.save_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_restore_snapshot(self): self.command_orchestrator.restore_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_get_snapshots(self): self.command_orchestrator.get_snapshots(self.context) self.assertTrue(self.command_orchestrator.command_wrapper. execute_command_with_connection.called) def test_orchestration_save_double_quotes_in_snapshot_name_should_be_stripped( self): # Arrange with patch(SAVE_SNAPSHOT) as save_snapshot_mock: save_snapshot_mock.return_value = '"new_snapshot"' remote_command_context = create_autospec( ResourceRemoteCommandContext) remote_command_context.resource = create_autospec( ResourceContextDetails) remote_command_context.resource.fullname = 'vcenter' endpoint = create_autospec(ResourceContextDetails) endpoint.fullname = 'vm_111' endpoint.app_context = create_autospec(AppContext) endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}' remote_command_context.remote_endpoints = [endpoint] # Act saved_result = CommandOrchestrator().orchestration_save( context=remote_command_context, mode='shallow', custom_params=None) # Assert save_snapshot_mock.assert_called_once() saved_result_dict = jsonpickle.decode(saved_result) self.assertEqual( saved_result_dict['saved_artifacts_info']['saved_artifact'] ['artifact_type'], 'vcenter_snapshot') self.assertEqual( saved_result_dict['saved_artifacts_info']['saved_artifact'] ['identifier'], 'new_snapshot') self.assertEqual( saved_result_dict['saved_artifacts_info']['resource_name'], 'vcenter') self.assertIsNotNone( saved_result_dict['saved_artifacts_info']['created_date']) @freeze_time("1984-12-31 11:12:13.4567") def test_orchestration_save_snapshot_name_should_contain_full_datetime( self): # Arrange with patch(SAVE_SNAPSHOT) as save_snapshot_mock: save_snapshot_mock.return_value = '"new_snapshot"' remote_command_context = create_autospec( ResourceRemoteCommandContext) remote_command_context.resource = create_autospec( ResourceContextDetails) remote_command_context.resource.fullname = 'vcenter' endpoint = create_autospec(ResourceContextDetails) endpoint.fullname = 'vm_111' endpoint.app_context = create_autospec(AppContext) endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}' remote_command_context.remote_endpoints = [endpoint] # Act CommandOrchestrator().orchestration_save( context=remote_command_context, mode='shallow', custom_params=None) # Assert args, kwargs = save_snapshot_mock.call_args self.assertEqual(kwargs['snapshot_name'], "84_12_31 11_12_13_456700") def test_orchestration_restore(self): # Arrange with patch(RESTORE_SNAPSHOT) as mock_restore_snapshot: # Act self.command_orchestrator.orchestration_restore( self.context, '''{ "saved_artifacts_info": { "resource_name": "ex cillum sed laboris", "created_date": "4313-10-12T18:03:15.053Z", "restore_rules": { "requires_same_resource": false }, "saved_artifact": { "artifact_type": "veniam in qui", "identifier": "deserunt1" } } }''') # Assert mock_restore_snapshot.assert_called_once_with( context=self.context, snapshot_name='deserunt1')
class VCenterShellDriver (ResourceDriverInterface): def cleanup(self): pass def __init__(self): """ ctor must be without arguments, it is created with reflection at run time """ self.command_orchestrator = CommandOrchestrator() # type: CommandOrchestrator def initialize(self): pass def ApplyConnectivityChanges(self, context, request): return self.command_orchestrator.connect_bulk(context, request) def disconnect_all(self, context, ports): return self.command_orchestrator.disconnect_all(context, ports) def disconnect(self, context, ports, network_name): return self.command_orchestrator.disconnect(context, ports, network_name) def destroy_vm_only(self, context, ports): return self.command_orchestrator.destroy_vm_only(context, ports) def remote_refresh_ip(self, context, cancellation_context, ports): return self.command_orchestrator.refresh_ip(context, cancellation_context, ports) def PowerOff(self, context, ports): return self.command_orchestrator.power_off(context, ports) # the name is by the Qualisystems conventions def PowerOn(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.command_orchestrator.power_on(context, ports) # the name is by the Qualisystems conventions def PowerCycle(self, context, ports, delay): return self.command_orchestrator.power_cycle(context, ports, delay) def deploy_from_template(self, context, deploy_data): return self.command_orchestrator.deploy_from_template(context, deploy_data) def deploy_clone_from_vm(self, context, deploy_data): return self.command_orchestrator.deploy_clone_from_vm(context, deploy_data) def deploy_from_linked_clone(self, context, deploy_data): return self.command_orchestrator.deploy_from_linked_clone(context, deploy_data) def deploy_from_image(self, context, deploy_data): return self.command_orchestrator.deploy_from_image(context, deploy_data) def get_inventory(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ validator = VCenterAutoModelDiscovery() return validator.validate_and_discover(context) def remote_save_snapshot(self, context, ports, snapshot_name): """ Saves virtual machine to a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: snapshot name to save to :type snapshot_name: str :return: """ return self.command_orchestrator.save_snapshot(context, snapshot_name) def remote_restore_snapshot(self, context, ports, snapshot_name): """ Restores virtual machine from a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: Snapshot name to restore from :type snapshot_name: str :return: """ return self.command_orchestrator.restore_snapshot(context, snapshot_name) def remote_get_snapshots(self, context, ports): """ Returns list of snapshots :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :return: list """ return self.command_orchestrator.get_snapshots(context) def orchestration_save(self, context, ports, mode="shallow", custom_params=None): return self.command_orchestrator.orchestration_save(context, mode, custom_params) def orchestration_restore(self, context, ports, saved_details): return self.command_orchestrator.orchestration_restore(context, saved_details) def get_vm_uuid(self, context, vm_name): return self.command_orchestrator.get_vm_uuid_by_name(context, vm_name)
class VCenterShellDriver(ResourceDriverInterface): def cleanup(self): pass def __init__(self): """ ctor must be without arguments, it is created with reflection at run time """ self.request_parser = DriverRequestParser() self.command_orchestrator = CommandOrchestrator( ) # type: CommandOrchestrator self.deployments = dict() self.deployments[ 'vCenter Clone VM From VM'] = self.deploy_clone_from_vm self.deployments[ 'VCenter Deploy VM From Linked Clone'] = self.deploy_from_linked_clone self.deployments[ 'vCenter VM From Template'] = self.deploy_from_template self.deployments['vCenter VM From Image'] = self.deploy_from_image def initialize(self, **kwargs): pass def ApplyConnectivityChanges(self, context, request): return self.command_orchestrator.connect_bulk(context, request) def disconnect_all(self, context, ports): return self.command_orchestrator.disconnect_all(context, ports) def disconnect(self, context, ports, network_name): return self.command_orchestrator.disconnect(context, ports, network_name) def DeleteInstance(self, context, ports): return self.command_orchestrator.DeleteInstance(context, ports) def remote_refresh_ip(self, context, cancellation_context, ports): return self.command_orchestrator.refresh_ip(context, cancellation_context, ports) def PowerOff(self, context, ports): return self.command_orchestrator.power_off(context, ports) # the name is by the Qualisystems conventions def PowerOn(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.command_orchestrator.power_on(context, ports) # the name is by the Qualisystems conventions def PowerCycle(self, context, ports, delay): return self.command_orchestrator.power_cycle(context, ports, delay) def Deploy(self, context, request=None, cancellation_context=None): actions = self.request_parser.convert_driver_request_to_actions( request) deploy_action = single(actions, lambda x: isinstance(x, DeployApp)) deployment_name = deploy_action.actionParams.deployment.deploymentPath if deployment_name in self.deployments.keys(): deploy_method = self.deployments[deployment_name] deploy_result = deploy_method(context, deploy_action, cancellation_context) return DriverResponse([deploy_result]).to_driver_response_json() else: raise Exception('Could not find the deployment') def SaveApp(self, context, request, cancellation_context=None): actions = self.request_parser.convert_driver_request_to_actions( request) save_actions = [x for x in actions if isinstance(x, SaveApp)] save_app_results = self.command_orchestrator.save_sandbox( context, save_actions, cancellation_context) return DriverResponse(save_app_results).to_driver_response_json() def DeleteSavedApps(self, context, request, cancellation_context=None): actions = self.request_parser.convert_driver_request_to_actions( request) delete_actions = [x for x in actions if isinstance(x, DeleteSavedApp)] save_app_results = self.command_orchestrator.delete_saved_sandbox( context, delete_actions, cancellation_context) return DriverResponse(save_app_results).to_driver_response_json() def deploy_from_template(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_from_template( context, deploy_action, cancellation_context) def deploy_clone_from_vm(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_clone_from_vm( context, deploy_action, cancellation_context) def deploy_from_linked_clone(self, context, deploy_action, cancellation_context): return self.command_orchestrator.deploy_from_linked_clone( context, deploy_action, cancellation_context) def deploy_from_image(self, context, deploy_action, cancellation_context): if cancellation_context is None: cancellation_context = CancellationContext() return self.command_orchestrator.deploy_from_image( context, deploy_action, cancellation_context) def get_inventory(self, context): """ :type context: models.QualiDriverModels.AutoLoadCommandContext """ validator = VCenterAutoModelDiscovery() return validator.validate_and_discover(context) def remote_save_snapshot(self, context, ports, snapshot_name, save_memory): """ Saves virtual machine to a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :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: """ return self.command_orchestrator.save_snapshot(context, snapshot_name, save_memory) def remote_restore_snapshot(self, context, ports, snapshot_name): """ Restores virtual machine from a snapshot :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :param snapshot_name: Snapshot name to restore from :type snapshot_name: str :return: """ return self.command_orchestrator.restore_snapshot( context, snapshot_name) def remote_get_snapshots(self, context, ports): """ Returns list of snapshots :param context: resource context of the vCenterShell :type context: models.QualiDriverModels.ResourceCommandContext :param ports:list[string] ports: the ports of the connection between the remote resource and the local resource :type ports: list[string] :return: list """ return self.command_orchestrator.get_snapshots(context) def orchestration_save(self, context, ports, mode="shallow", custom_params=None): return self.command_orchestrator.orchestration_save( context, mode, custom_params) def orchestration_restore(self, context, ports, saved_details): return self.command_orchestrator.orchestration_restore( context, saved_details) def get_vm_uuid(self, context, vm_name): return self.command_orchestrator.get_vm_uuid_by_name(context, vm_name) def GetVmDetails(self, context, cancellation_context, requests): return self.command_orchestrator.get_vm_details( context, cancellation_context, requests)
class TestCommandOrchestrator(TestCase): def setUp(self): self.resource = create_autospec(ResourceInfo) self.resource.ResourceModelName = 'VMwarev Center' self.resource.ResourceAttributes = {'User': '******', 'Password': '******', 'Default dvSwitch': 'switch1', 'Holding Network': 'anetwork', 'Default Port Group Location': 'Quali', 'VM Cluster': 'Quali', 'VM Location': 'Quali', 'VM Resource Pool': 'Quali', 'VM Storage': 'Quali', 'Shutdown Method': 'hard', 'OVF Tool Path': 'C\\program files\ovf', 'Execution Server Selector': '', 'Reserved Networks': 'vlan65', 'Default Datacenter': 'QualiSB' } self.context = Mock() session = Mock() remote_resource = Mock() remote_resource.fullname = 'this is full name of the remote resource' remote_resource.uuid = 'this is full uuis of the remote resource' self.connection_details = Mock() self.context.resource = self.resource self.context.resource.app_context = Mock() self.context.remote_endpoints = Mock() self.context.remote_endpoints = [self.resource] self.command_orchestrator = CommandOrchestrator() self.command_orchestrator.command_wrapper.execute_command_with_connection = Mock(return_value=True) self.command_orchestrator.cs_helper = Mock() self.command_orchestrator.cs_helper.get_session = Mock(return_value=session) self.command_orchestrator.cs_helper.get_connection_details = Mock(return_value=self.connection_details) self.ports = [Mock()] self.command_orchestrator._parse_remote_model = Mock(return_value=remote_resource) def test_disconnect_all(self): # act self.command_orchestrator.disconnect_all(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_disconnect(self): # act self.command_orchestrator.disconnect(self.context, self.ports, 'network') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_destroy_vm_only(self): # act self.command_orchestrator.destroy_vm_only(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_from_template(self): # act self.command_orchestrator.deploy_from_template(self.context, '{"name": "name", "template_resource_model": {"vcenter_template": ""}}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_vm_from_vm(self): # act self.command_orchestrator.deploy_clone_from_vm(self.context, '{"name": "name", "template_resource_model": {"vcenter_vm": ""}}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_from_snapshot(self): # act self.command_orchestrator.deploy_from_linked_clone(self.context, '{"name": "name", "template_resource_model": {"vcenter_vm": "name", "vcenter_vm_snapshot": "snap"}}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_deploy_from_image(self): # act self.command_orchestrator.deploy_from_image(self.context, '{"name": "name"}') # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_off(self): # act self.command_orchestrator.power_off(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_on(self): # act self.command_orchestrator.power_on(self.context, self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_power_cycle(self): # act self.command_orchestrator.power_cycle(self.context, self.ports, 0.0001) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_refresh_ip(self): # act cancellation_context = object() self.command_orchestrator.refresh_ip(self.context, cancellation_context=cancellation_context, ports=self.ports) # assert self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_get_uuid(self): self.command_orchestrator.get_vm_uuid_by_name(self.context, 'Name') self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_save_snapshot(self): self.command_orchestrator.save_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_restore_snapshot(self): self.command_orchestrator.restore_snapshot(self.context, 'new_snapshot') self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_get_snapshots(self): self.command_orchestrator.get_snapshots(self.context) self.assertTrue(self.command_orchestrator.command_wrapper.execute_command_with_connection.called) def test_orchestration_save_double_quotes_in_snapshot_name_should_be_stripped(self): # Arrange with patch(SAVE_SNAPSHOT) as save_snapshot_mock: save_snapshot_mock.return_value = '"new_snapshot"' remote_command_context = create_autospec(ResourceRemoteCommandContext) remote_command_context.resource = create_autospec(ResourceContextDetails) remote_command_context.resource.fullname = 'vcenter' endpoint = create_autospec(ResourceContextDetails) endpoint.fullname = 'vm_111' endpoint.app_context = create_autospec(AppContext) endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}' remote_command_context.remote_endpoints = [endpoint] # Act saved_result = CommandOrchestrator().orchestration_save(context=remote_command_context, mode='shallow', custom_params=None) # Assert save_snapshot_mock.assert_called_once() saved_result_dict = jsonpickle.decode(saved_result) self.assertEqual(saved_result_dict['saved_artifacts_info']['saved_artifact']['artifact_type'], 'vcenter_snapshot') self.assertEqual(saved_result_dict['saved_artifacts_info']['saved_artifact']['identifier'], 'new_snapshot') self.assertEqual(saved_result_dict['saved_artifacts_info']['resource_name'], 'vcenter') self.assertIsNotNone(saved_result_dict['saved_artifacts_info']['created_date']) @freeze_time("1984-12-31 11:12:13.4567") def test_orchestration_save_snapshot_name_should_contain_full_datetime(self): # Arrange with patch(SAVE_SNAPSHOT) as save_snapshot_mock: save_snapshot_mock.return_value = '"new_snapshot"' remote_command_context = create_autospec(ResourceRemoteCommandContext) remote_command_context.resource = create_autospec(ResourceContextDetails) remote_command_context.resource.fullname = 'vcenter' endpoint = create_autospec(ResourceContextDetails) endpoint.fullname = 'vm_111' endpoint.app_context = create_autospec(AppContext) endpoint.app_context.deployed_app_json = '{"vmdetails": {"uid": "vm_uuid1"}}' remote_command_context.remote_endpoints = [endpoint] # Act CommandOrchestrator().orchestration_save(context=remote_command_context, mode='shallow', custom_params=None) # Assert args, kwargs = save_snapshot_mock.call_args self.assertEqual(kwargs['snapshot_name'], "84_12_31 11_12_13_456700") def test_orchestration_restore(self): # Arrange with patch(RESTORE_SNAPSHOT) as mock_restore_snapshot: # Act self.command_orchestrator.orchestration_restore(self.context, '''{ "saved_artifacts_info": { "resource_name": "ex cillum sed laboris", "created_date": "4313-10-12T18:03:15.053Z", "restore_rules": { "requires_same_resource": false }, "saved_artifact": { "artifact_type": "veniam in qui", "identifier": "deserunt1" } } }''') # Assert mock_restore_snapshot.assert_called_once_with(context=self.context, snapshot_name='deserunt1')