From 564f8d140fd8a968e55b1aee57200b9f015bee6d Mon Sep 17 00:00:00 2001 From: Kartik Bommepally Date: Tue, 3 Sep 2013 05:12:33 -0700 Subject: [PATCH] VMware driver: Fix for invalid datastore selection Added filter to ignore datastores that are not mounted, in-accessible and read-only for volume creation. Without this VMware's VC/ESX driver can choose such datastore with higher invalid capacity value as returned by the server for volume creation. Also using parent's self.mox object in the test cases rather than creating a new mox.Mox obj everytime. Fixes bug: 1220217 Change-Id: If8319562ddc11fc31eb928b3807aead2b11b94bc --- cinder/tests/test_vmware_vmdk.py | 183 ++++++++++++++-------- cinder/volume/drivers/vmware/volumeops.py | 47 +++++- 2 files changed, 159 insertions(+), 71 deletions(-) diff --git a/cinder/tests/test_vmware_vmdk.py b/cinder/tests/test_vmware_vmdk.py index c684f767ba2..bc2c097e0f3 100644 --- a/cinder/tests/test_vmware_vmdk.py +++ b/cinder/tests/test_vmware_vmdk.py @@ -150,7 +150,7 @@ def fail(self): def test_create_session(self): """Test create_session.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.ReplayAll() @@ -160,7 +160,7 @@ def test_create_session(self): def test_do_setup(self): """Test do_setup.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'session') self._driver.session = self._session m.ReplayAll() @@ -188,7 +188,7 @@ def test_create_volume(self): def test_success_wait_for_task(self): """Test successful wait_for_task.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim result = FakeMor('VirtualMachine', 'my_vm') @@ -206,7 +206,7 @@ def test_success_wait_for_task(self): def test_failed_wait_for_task(self): """Test failed wait_for_task.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim failed_task_info = FakeTaskInfo('failed') @@ -224,7 +224,7 @@ def test_failed_wait_for_task(self): def test_get_backing(self): """Test get_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -238,7 +238,7 @@ def test_get_backing(self): def test_delete_backing(self): """Test delete_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -254,7 +254,7 @@ def test_delete_backing(self): def test_delete_volume_without_backing(self): """Test delete_volume without backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -269,7 +269,7 @@ def test_delete_volume_without_backing(self): def test_delete_volume_with_backing(self): """Test delete_volume with backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops @@ -307,7 +307,7 @@ def test_terminate_connection(self): def test_get_host(self): """Test get_host.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -322,7 +322,7 @@ def test_get_host(self): def test_get_hosts(self): """Test get_hosts.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -334,9 +334,62 @@ def test_get_hosts(self): m.UnsetStubs() m.VerifyAll() + def test_is_valid_with_accessible_attr(self): + """Test _is_valid with accessible attribute.""" + m = self.mox + m.StubOutWithMock(api.VMwareAPISession, 'vim') + self._session.vim = self._vim + m.StubOutWithMock(self._session, 'invoke_api') + datastore = FakeMor('Datastore', 'my_ds') + mntInfo = FakeObject() + mntInfo.accessMode = "readWrite" + mntInfo.accessible = True + host = FakeMor('HostSystem', 'my_host') + host_mount = FakeObject() + host_mount.key = host + host_mount.mountInfo = mntInfo + host_mounts = FakeObject() + host_mounts.DatastoreHostMount = [host_mount] + self._session.invoke_api(vim_util, 'get_object_property', + self._vim, datastore, + 'host').AndReturn(host_mounts) + + m.ReplayAll() + self.assertTrue(self._volumeops._is_valid(datastore, host)) + m.UnsetStubs() + m.VerifyAll() + + def test_is_valid_without_accessible_attr(self): + """Test _is_valid without accessible attribute.""" + m = self.mox + m.StubOutWithMock(api.VMwareAPISession, 'vim') + self._session.vim = self._vim + m.StubOutWithMock(self._session, 'invoke_api') + datastore = FakeMor('Datastore', 'my_ds') + mntInfo = FakeObject() + mntInfo.accessMode = "readWrite" + host = FakeMor('HostSystem', 'my_host') + host_mount = FakeObject() + host_mount.key = host + host_mount.mountInfo = mntInfo + host_mounts = FakeObject() + host_mounts.DatastoreHostMount = [host_mount] + self._session.invoke_api(vim_util, 'get_object_property', + self._vim, datastore, + 'host').AndReturn(host_mounts) + m.StubOutWithMock(self._volumeops, 'get_summary') + summary = FakeObject() + summary.accessible = True + self._volumeops.get_summary(datastore).AndReturn(summary) + + m.ReplayAll() + self.assertTrue(self._volumeops._is_valid(datastore, host)) + m.UnsetStubs() + m.VerifyAll() + def test_get_dss_rp(self): """Test get_dss_rp.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -361,7 +414,7 @@ def test_get_parent(self): self.assertEqual(parent, child) # Recursive - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -378,7 +431,7 @@ def test_get_parent(self): def test_get_dc(self): """Test get_dc.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._volumeops, '_get_parent') self._volumeops._get_parent(mox.IgnoreArg(), 'Datacenter') @@ -389,7 +442,7 @@ def test_get_dc(self): def test_get_vmfolder(self): """Test get_vmfolder.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -404,7 +457,7 @@ def test_get_vmfolder(self): def test_create_backing(self): """Test create_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -433,7 +486,7 @@ def test_create_backing(self): def test_get_datastore(self): """Test get_datastore.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -451,7 +504,7 @@ def test_get_datastore(self): def test_get_summary(self): """Test get_summary.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -466,7 +519,7 @@ def test_get_summary(self): def test_init_conn_with_instance_and_backing(self): """Test initialize_connection with instance and backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -491,7 +544,7 @@ def test_init_conn_with_instance_and_backing(self): def test_get_volume_group_folder(self): """Test _get_volume_group_folder.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops datacenter = FakeMor('Datacenter', 'my_dc') @@ -505,7 +558,7 @@ def test_get_volume_group_folder(self): def test_select_datastore_summary(self): """Test _select_datastore_summary.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops datastore1 = FakeMor('Datastore', 'my_ds_1') @@ -542,7 +595,7 @@ def test_select_datastore_summary(self): def test_get_folder_ds_summary(self): """Test _get_folder_ds_summary.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops size = 1 @@ -572,7 +625,7 @@ def test_get_disk_type(self): def test_init_conn_with_instance_no_backing(self): """Test initialize_connection with instance and without backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -614,7 +667,7 @@ def test_init_conn_with_instance_no_backing(self): def test_init_conn_without_instance(self): """Test initialize_connection without instance and a backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -635,7 +688,7 @@ def test_init_conn_without_instance(self): def test_create_snapshot_operation(self): """Test volumeops.create_snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -658,7 +711,7 @@ def test_create_snapshot_operation(self): def test_create_snapshot_without_backing(self): """Test vmdk.create_snapshot without backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -673,7 +726,7 @@ def test_create_snapshot_without_backing(self): def test_create_snapshot_with_backing(self): """Test vmdk.create_snapshot with backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -710,7 +763,7 @@ def test_get_snapshot_from_tree(self): def test_get_snapshot(self): """Test get_snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -732,7 +785,7 @@ def test_get_snapshot(self): def test_delete_snapshot_not_present(self): """Test volumeops.delete_snapshot, when not present.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._volumeops, 'get_snapshot') name = 'snapshot_name' backing = FakeMor('VirtualMachine', 'my_back') @@ -745,7 +798,7 @@ def test_delete_snapshot_not_present(self): def test_delete_snapshot_when_present(self): """Test volumeops.delete_snapshot, when it is present.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -768,7 +821,7 @@ def test_delete_snapshot_when_present(self): def test_delete_snapshot_without_backing(self): """Test delete_snapshot without backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -783,7 +836,7 @@ def test_delete_snapshot_without_backing(self): def test_delete_snapshot_with_backing(self): """Test delete_snapshot with backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -803,7 +856,7 @@ def test_delete_snapshot_with_backing(self): def test_create_cloned_volume_without_backing(self): """Test create_cloned_volume without a backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -820,7 +873,7 @@ def test_create_cloned_volume_without_backing(self): def test_get_path_name(self): """Test get_path_name.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -840,8 +893,8 @@ def __init__(self, path=None): m.VerifyAll() def test_delete_file(self): - """Test delete_file.""" - m = mox.Mox() + """Test _delete_file.""" + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -860,7 +913,7 @@ def test_delete_file(self): def test_copy_backing(self): """Test copy_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -880,7 +933,7 @@ def test_copy_backing(self): def test_register_backing(self): """Test register_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -903,7 +956,7 @@ def test_register_backing(self): def test_clone_backing_by_copying(self): """Test _clone_backing_by_copying.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops volume = FakeObject() @@ -942,7 +995,7 @@ def test_clone_backing_by_copying(self): def test_create_cloned_volume_with_backing(self): """Test create_cloned_volume with a backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -961,7 +1014,7 @@ def test_create_cloned_volume_with_backing(self): def test_create_volume_from_snapshot_without_backing(self): """Test create_volume_from_snapshot without a backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -978,7 +1031,7 @@ def test_create_volume_from_snapshot_without_backing(self): def test_create_volume_from_snap_without_backing_snap(self): """Test create_volume_from_snapshot without a backing snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops backing = FakeMor('VirtualMachine', 'my_vm') @@ -999,7 +1052,7 @@ def test_create_volume_from_snap_without_backing_snap(self): def test_revert_to_snapshot(self): """Test revert_to_snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1018,7 +1071,7 @@ def test_revert_to_snapshot(self): def test_create_volume_from_snapshot(self): """Test create_volume_from_snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops backing = FakeMor('VirtualMachine', 'my_vm') @@ -1049,7 +1102,7 @@ def test_create_volume_from_snapshot(self): def test_get_entity_name(self): """Test volumeops get_entity_name.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1064,7 +1117,7 @@ def test_get_entity_name(self): def test_get_vmdk_path(self): """Test volumeops get_vmdk_path.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1098,7 +1151,7 @@ class VirtualDiskFlatVer2BackingInfo: def test_copy_vmdk_file(self): """Test copy_vmdk_file.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1121,7 +1174,7 @@ def test_copy_vmdk_file(self): def test_delete_vmdk_file(self): """Test delete_vmdk_file.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1160,7 +1213,7 @@ def test_split_datastore_path(self): def test_copy_image_to_volume_non_vmdk(self): """Test copy_image_to_volume for a non-vmdk disk format.""" - m = mox.Mox() + m = self.mox image_id = 'image-123456789' image_meta = FakeObject() image_meta['disk_format'] = 'novmdk' @@ -1177,7 +1230,7 @@ def test_copy_image_to_volume_non_vmdk(self): def test_copy_image_to_volume_vmdk(self): """Test copy_image_to_volume with an acceptable vmdk disk format.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'session') self._driver.session = self._session m.StubOutWithMock(api.VMwareAPISession, 'vim') @@ -1239,7 +1292,7 @@ def test_copy_image_to_volume_vmdk(self): def test_copy_volume_to_image_non_vmdk(self): """Test copy_volume_to_image for a non-vmdk disk format.""" - m = mox.Mox() + m = self.mox image_meta = FakeObject() image_meta['disk_format'] = 'novmdk' volume = FakeObject() @@ -1255,7 +1308,7 @@ def test_copy_volume_to_image_non_vmdk(self): def test_copy_volume_to_image_vmdk(self): """Test copy_volume_to_image for a valid vmdk disk format.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'session') self._driver.session = self._session m.StubOutWithMock(api.VMwareAPISession, 'vim') @@ -1347,7 +1400,7 @@ def setUp(self): def test_create_folder_not_present(self): """Test create_folder when not present.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1366,7 +1419,7 @@ def test_create_folder_not_present(self): def test_create_folder_already_present(self): """Test create_folder when already present.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1388,7 +1441,7 @@ def test_create_folder_already_present(self): def test_relocate_backing(self): """Test relocate_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._volumeops, '_get_relocate_spec') @@ -1414,7 +1467,7 @@ def test_relocate_backing(self): def test_move_backing_to_folder(self): """Test move_backing_to_folder.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(api.VMwareAPISession, 'vim') self._session.vim = self._vim m.StubOutWithMock(self._session, 'invoke_api') @@ -1433,7 +1486,7 @@ def test_move_backing_to_folder(self): def test_init_conn_with_instance_and_backing(self): """Test initialize_connection with instance and backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -1465,7 +1518,7 @@ def test_init_conn_with_instance_and_backing(self): def test_get_volume_group_folder(self): """Test _get_volume_group_folder.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops datacenter = FakeMor('Datacenter', 'my_dc') @@ -1482,7 +1535,7 @@ def test_get_volume_group_folder(self): def test_init_conn_with_instance_and_backing_and_relocation(self): """Test initialize_connection with backing being relocated.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -1527,7 +1580,7 @@ def test_init_conn_with_instance_and_backing_and_relocation(self): def test_get_folder(self): """Test _get_folder.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._volumeops, '_get_parent') self._volumeops._get_parent(mox.IgnoreArg(), 'Folder') @@ -1538,7 +1591,7 @@ def test_get_folder(self): def test_volumeops_clone_backing(self): """Test volumeops.clone_backing.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._volumeops, '_get_parent') backing = FakeMor('VirtualMachine', 'my_back') folder = FakeMor('Folder', 'my_fol') @@ -1569,7 +1622,7 @@ def test_volumeops_clone_backing(self): def test_clone_backing_linked(self): """Test _clone_backing with clone type - linked.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'clone_backing') @@ -1588,7 +1641,7 @@ def test_clone_backing_linked(self): def test_clone_backing_full(self): """Test _clone_backing with clone type - full.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_host') @@ -1622,7 +1675,7 @@ def test_clone_backing_full(self): def test_create_volume_from_snapshot(self): """Test create_volume_from_snapshot.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -1647,7 +1700,7 @@ def test_create_volume_from_snapshot(self): def test_create_cloned_volume_with_backing(self): """Test create_cloned_volume with clone type - full.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') @@ -1667,7 +1720,7 @@ def test_create_cloned_volume_with_backing(self): def test_create_lined_cloned_volume_with_backing(self): """Test create_cloned_volume with clone type - linked.""" - m = mox.Mox() + m = self.mox m.StubOutWithMock(self._driver.__class__, 'volumeops') self._driver.volumeops = self._volumeops m.StubOutWithMock(self._volumeops, 'get_backing') diff --git a/cinder/volume/drivers/vmware/volumeops.py b/cinder/volume/drivers/vmware/volumeops.py index aee517c31e4..06b332b9ffb 100644 --- a/cinder/volume/drivers/vmware/volumeops.py +++ b/cinder/volume/drivers/vmware/volumeops.py @@ -110,18 +110,47 @@ def get_hosts(self): return self._session.invoke_api(vim_util, 'get_objects', self._session.vim, 'HostSystem') + def _is_valid(self, datastore, host): + """Check if host's datastore is accessible, mounted and writable. + + :param datastore: Reference to the datastore entity + :param host: Reference to the host entity + :return: True if datastore can be used for volume creation + """ + + host_mounts = self._session.invoke_api(vim_util, 'get_object_property', + self._session.vim, datastore, + 'host') + for host_mount in host_mounts.DatastoreHostMount: + if host_mount.key.value == host.value: + mntInfo = host_mount.mountInfo + writable = mntInfo.accessMode == "readWrite" + # If mounted attribute is not set, then default is True + mounted = True + if hasattr(mntInfo, "mounted"): + mounted = mntInfo.mounted + if hasattr(mntInfo, "accessible"): + accessible = mntInfo.accessible + else: + # If accessible attribute is not set, we look at summary + summary = self.get_summary(datastore) + accessible = summary.accessible + return (accessible and mounted and writable) + return False + def get_dss_rp(self, host): - """Get datastores and resource pool of the host. + """Get accessible datastores and resource pool of the host. :param host: Managed object reference of the host - :return: Datastores mounted to the host and resource pool to which + :return: Datastores accessible to the host and resource pool to which the host belongs to """ + props = self._session.invoke_api(vim_util, 'get_object_properties', self._session.vim, host, ['datastore', 'parent']) # Get datastores and compute resource or cluster compute resource - datastores = None + datastores = [] compute_resource = None for elem in props: for prop in elem.propSet: @@ -129,17 +158,22 @@ def get_dss_rp(self, host): datastores = prop.val.ManagedObjectReference elif prop.name == 'parent': compute_resource = prop.val + # Filter datastores based on if it is accessible, mounted and writable + valid_dss = [] + for datastore in datastores: + if self._is_valid(datastore, host): + valid_dss.append(datastore) # Get resource pool from compute resource or cluster compute resource resource_pool = self._session.invoke_api(vim_util, 'get_object_property', self._session.vim, compute_resource, 'resourcePool') - if not datastores: - msg = _("There are no datastores present under %s.") + if not valid_dss: + msg = _("There are no valid datastores present under %s.") LOG.error(msg % host) raise error_util.VimException(msg % host) - return (datastores, resource_pool) + return (valid_dss, resource_pool) def _get_parent(self, child, parent_type): """Get immediate parent of given type via 'parent' property. @@ -149,6 +183,7 @@ def _get_parent(self, child, parent_type): :return: Immediate parent of specific type up the hierarchy via 'parent' property """ + if not child: return None if child._type == parent_type: