diff options
author | Arnaud Legendre <arnaudleg@gmail.com> | 2014-11-24 14:29:07 -0800 |
---|---|---|
committer | Gary Kotton <gkotton@vmware.com> | 2015-03-20 07:53:20 -0700 |
commit | e7ae5bb7fbdd5b79bde8937958dd0a645554a5f0 (patch) | |
tree | 2eba4bf2054ec20ec731f8440f43dda1aef04dd7 /nova | |
parent | 37a6c601f37790a94b6e2db7f4fa41f143b9caa8 (diff) | |
download | nova-e7ae5bb7fbdd5b79bde8937958dd0a645554a5f0.tar.gz |
VMware: Consume the oslo.vmware objects
oslo.vmware now contains the datastore and datacenter objects.
This patch gets rid of the nova datastore object and leverages
oslo.vmware.
Co-authored-by: Gary Kotton <gkotton@vmware.com>
Change-Id: I3f1e65dec1500afb58dcb841991ac976887de09d
Diffstat (limited to 'nova')
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/fake.py | 6 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_driver_api.py | 46 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_ds_util.py | 197 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_ds_util_datastore_selection.py | 13 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_imagecache.py | 21 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_vm_util.py | 4 | ||||
-rw-r--r-- | nova/tests/unit/virt/vmwareapi/test_vmops.py | 23 | ||||
-rw-r--r-- | nova/virt/vmwareapi/ds_util.py | 165 | ||||
-rw-r--r-- | nova/virt/vmwareapi/vmops.py | 37 |
9 files changed, 93 insertions, 419 deletions
diff --git a/nova/tests/unit/virt/vmwareapi/fake.py b/nova/tests/unit/virt/vmwareapi/fake.py index c2ded60a59..1e22ec97e7 100644 --- a/nova/tests/unit/virt/vmwareapi/fake.py +++ b/nova/tests/unit/virt/vmwareapi/fake.py @@ -26,10 +26,10 @@ from oslo_serialization import jsonutils from oslo_utils import units from oslo_utils import uuidutils from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from nova import exception from nova.virt.vmwareapi import constants -from nova.virt.vmwareapi import ds_util _CLASSES = ['Datacenter', 'Datastore', 'ResourcePool', 'VirtualMachine', 'Network', 'HostSystem', 'HostNetworkSystem', 'Task', 'session', @@ -967,9 +967,9 @@ def create_vm(uuid=None, name=None, devices = [] if vmPathName is None: - vm_path = ds_util.DatastorePath(_db_content['Datastore'].values()[0]) + vm_path = ds_obj.DatastorePath(_db_content['Datastore'].values()[0]) else: - vm_path = ds_util.DatastorePath.parse(vmPathName) + vm_path = ds_obj.DatastorePath.parse(vmPathName) if res_pool_ref is None: res_pool_ref = _db_content['ResourcePool'].keys()[0] diff --git a/nova/tests/unit/virt/vmwareapi/test_driver_api.py b/nova/tests/unit/virt/vmwareapi/test_driver_api.py index 09bae43caf..aabb1103e9 100644 --- a/nova/tests/unit/virt/vmwareapi/test_driver_api.py +++ b/nova/tests/unit/virt/vmwareapi/test_driver_api.py @@ -32,6 +32,7 @@ from oslo_utils import timeutils from oslo_utils import units from oslo_utils import uuidutils from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from oslo_vmware import pbm from oslo_vmware import vim from oslo_vmware import vim_util as oslo_vim_util @@ -58,7 +59,6 @@ from nova import utils as nova_utils from nova.virt import driver as v_driver from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import driver -from nova.virt.vmwareapi import ds_util from nova.virt.vmwareapi import error_util from nova.virt.vmwareapi import imagecache from nova.virt.vmwareapi import images @@ -521,7 +521,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): self.assertEqual(len(uuids), 0) def _cached_files_exist(self, exists=True): - cache = ds_util.DatastorePath(self.ds, 'vmware_base', + cache = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.vmdk' % self.fake_image_uuid) if exists: @@ -541,7 +541,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): mock_from_image.return_value = img_props self._create_vm() - path = ds_util.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) + path = ds_obj.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) vmwareapi_fake.assertPathExists(self, str(path)) self._cached_files_exist() @@ -559,10 +559,10 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): mock_from_image.return_value = img_props self._create_vm() - path = ds_util.DatastorePath(self.ds, 'vmware_base', + path = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.vmdk' % self.fake_image_uuid) - root = ds_util.DatastorePath(self.ds, 'vmware_base', + root = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.80.vmdk' % self.fake_image_uuid) vmwareapi_fake.assertPathExists(self, str(path)) @@ -571,23 +571,23 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): def _iso_disk_type_created(self, instance_type='m1.large'): self.image['disk_format'] = 'iso' self._create_vm(instance_type=instance_type) - path = ds_util.DatastorePath(self.ds, 'vmware_base', + path = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.iso' % self.fake_image_uuid) vmwareapi_fake.assertPathExists(self, str(path)) def test_iso_disk_type_created(self): self._iso_disk_type_created() - path = ds_util.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) + path = ds_obj.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) vmwareapi_fake.assertPathExists(self, str(path)) def test_iso_disk_type_created_with_root_gb_0(self): self._iso_disk_type_created(instance_type='m1.micro') - path = ds_util.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) + path = ds_obj.DatastorePath(self.ds, self.uuid, '%s.vmdk' % self.uuid) vmwareapi_fake.assertPathNotExists(self, str(path)) def test_iso_disk_cdrom_attach(self): - iso_path = ds_util.DatastorePath(self.ds, 'vmware_base', + iso_path = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.iso' % self.fake_image_uuid) @@ -614,10 +614,10 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): self.flags(force_config_drive=True) iso_path = [ - ds_util.DatastorePath(self.ds, 'vmware_base', + ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.iso' % self.fake_image_uuid), - ds_util.DatastorePath(self.ds, 'fake-config-drive')] + ds_obj.DatastorePath(self.ds, 'fake-config-drive')] self.iso_index = 0 def fake_create_config_drive(instance, injected_files, password, @@ -640,7 +640,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): def test_ephemeral_disk_attach(self): self._create_vm(ephemeral=50) - path = ds_util.DatastorePath(self.ds, self.uuid, + path = ds_obj.DatastorePath(self.ds, self.uuid, 'ephemeral_0.vmdk') vmwareapi_fake.assertPathExists(self, str(path)) @@ -653,24 +653,24 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): 'size': 25}] bdi = {'ephemerals': ephemerals} self._create_vm(bdi=bdi, ephemeral=50) - path = ds_util.DatastorePath(self.ds, self.uuid, + path = ds_obj.DatastorePath(self.ds, self.uuid, 'ephemeral_0.vmdk') vmwareapi_fake.assertPathExists(self, str(path)) - path = ds_util.DatastorePath(self.ds, self.uuid, + path = ds_obj.DatastorePath(self.ds, self.uuid, 'ephemeral_1.vmdk') vmwareapi_fake.assertPathExists(self, str(path)) def test_ephemeral_disk_attach_from_bdii_with_no_ephs(self): bdi = {'ephemerals': []} self._create_vm(bdi=bdi, ephemeral=50) - path = ds_util.DatastorePath(self.ds, self.uuid, + path = ds_obj.DatastorePath(self.ds, self.uuid, 'ephemeral_0.vmdk') vmwareapi_fake.assertPathExists(self, str(path)) def test_cdrom_attach_with_config_drive(self): self.flags(force_config_drive=True) - iso_path = ds_util.DatastorePath(self.ds, 'fake-config-drive') + iso_path = ds_obj.DatastorePath(self.ds, 'fake-config-drive') self.cd_attach_called = False def fake_create_config_drive(instance, injected_files, password, @@ -789,7 +789,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): self._check_vm_info(info, power_state.RUNNING) def test_spawn_disk_extend_exists(self): - root = ds_util.DatastorePath(self.ds, 'vmware_base', + root = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.80.vmdk' % self.fake_image_uuid) @@ -825,7 +825,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): mock_get_dc.return_value = dc_val self._create_vm() iid = img_props.image_id - cached_image = ds_util.DatastorePath(self.ds, 'vmware_base', + cached_image = ds_obj.DatastorePath(self.ds, 'vmware_base', iid, '%s.80.vmdk' % iid) mock_extend.assert_called_once_with( self.instance, self.instance.root_gb * units.Mi, @@ -964,11 +964,11 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): mock_from_image.return_value = img_props - cached_image = ds_util.DatastorePath(self.ds, 'vmware_base', + cached_image = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.80.vmdk' % self.fake_image_uuid) - tmp_file = ds_util.DatastorePath(self.ds, 'vmware_base', + tmp_file = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, '%s.80-flat.vmdk' % self.fake_image_uuid) @@ -1533,7 +1533,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): data_store_name, folder, instance_uuid, cookies): self.assertTrue(uuidutils.is_uuid_like(instance['uuid'])) - return str(ds_util.DatastorePath(data_store_name, + return str(ds_obj.DatastorePath(data_store_name, instance_uuid, 'fake.iso')) self.stubs.Set(self.conn._vmops, '_create_config_drive', @@ -1905,7 +1905,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): _fake_get_timestamp_filename) def _timestamp_file_exists(self, exists=True): - timestamp = ds_util.DatastorePath(self.ds, 'vmware_base', + timestamp = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, self._get_timestamp_filename() + '/') if exists: @@ -1940,7 +1940,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): def test_timestamp_file_removed_aging(self, mock_get_by_inst): self._timestamp_file_removed() ts = self._get_timestamp_filename() - ts_path = ds_util.DatastorePath(self.ds, 'vmware_base', + ts_path = ds_obj.DatastorePath(self.ds, 'vmware_base', self.fake_image_uuid, ts + '/') vmwareapi_fake._add_file(str(ts_path)) self._timestamp_file_exists() diff --git a/nova/tests/unit/virt/vmwareapi/test_ds_util.py b/nova/tests/unit/virt/vmwareapi/test_ds_util.py index 0823a5527f..e0985d92ee 100644 --- a/nova/tests/unit/virt/vmwareapi/test_ds_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_ds_util.py @@ -18,7 +18,7 @@ import re import mock from oslo_utils import units from oslo_vmware import exceptions as vexc -from testtools import matchers +from oslo_vmware.objects import datastore as ds_obj from nova import exception from nova import test @@ -51,7 +51,7 @@ class DsUtilTestCase(test.NoDBTestCase): mock.patch.object(self.session, '_call_method', fake_call_method) ) as (_wait_for_task, _call_method): - ds_path = ds_util.DatastorePath('ds', 'fake/path') + ds_path = ds_obj.DatastorePath('ds', 'fake/path') ds_util.file_delete(self.session, ds_path, 'fake-dc-ref') _wait_for_task.assert_has_calls([ @@ -75,8 +75,8 @@ class DsUtilTestCase(test.NoDBTestCase): mock.patch.object(self.session, '_call_method', fake_call_method) ) as (_wait_for_task, _call_method): - src_ds_path = ds_util.DatastorePath('ds', 'fake/path', 'src_file') - dst_ds_path = ds_util.DatastorePath('ds', 'fake/path', 'dst_file') + src_ds_path = ds_obj.DatastorePath('ds', 'fake/path', 'src_file') + dst_ds_path = ds_obj.DatastorePath('ds', 'fake/path', 'dst_file') ds_util.file_copy(self.session, str(src_ds_path), 'fake-src-dc-ref', str(dst_ds_path), 'fake-dst-dc-ref') @@ -101,8 +101,8 @@ class DsUtilTestCase(test.NoDBTestCase): mock.patch.object(self.session, '_call_method', fake_call_method) ) as (_wait_for_task, _call_method): - src_ds_path = ds_util.DatastorePath('ds', 'tmp/src') - dst_ds_path = ds_util.DatastorePath('ds', 'base/dst') + src_ds_path = ds_obj.DatastorePath('ds', 'tmp/src') + dst_ds_path = ds_obj.DatastorePath('ds', 'base/dst') ds_util.file_move(self.session, 'fake-dc-ref', src_ds_path, dst_ds_path) _wait_for_task.assert_has_calls([ @@ -172,7 +172,7 @@ class DsUtilTestCase(test.NoDBTestCase): with mock.patch.object(self.session, '_call_method', fake_call_method): - ds_path = ds_util.DatastorePath('ds', 'fake/path') + ds_path = ds_obj.DatastorePath('ds', 'fake/path') ds_util.mkdir(self.session, ds_path, 'fake-dc-ref') def test_file_exists(self): @@ -209,7 +209,7 @@ class DsUtilTestCase(test.NoDBTestCase): fake_call_method), mock.patch.object(self.session, '_wait_for_task', fake_wait_for_task)): - ds_path = ds_util.DatastorePath('ds', 'fake/path') + ds_path = ds_obj.DatastorePath('ds', 'fake/path') file_exists = ds_util.file_exists(self.session, 'fake-browser', ds_path, 'fake-file') self.assertTrue(file_exists) @@ -234,7 +234,7 @@ class DsUtilTestCase(test.NoDBTestCase): fake_call_method), mock.patch.object(self.session, '_wait_for_task', fake_wait_for_task)): - ds_path = ds_util.DatastorePath('ds', 'fake/path') + ds_path = ds_obj.DatastorePath('ds', 'fake/path') file_exists = ds_util.file_exists(self.session, 'fake-browser', ds_path, 'fake-file') self.assertFalse(file_exists) @@ -445,182 +445,3 @@ class DsUtilTestCase(test.NoDBTestCase): "normal", "VMFS", datastore_regex)) - - -class DatastoreTestCase(test.NoDBTestCase): - def test_ds(self): - ds = ds_util.Datastore( - "fake_ref", "ds_name", 2 * units.Gi, 1 * units.Gi) - self.assertEqual('ds_name', ds.name) - self.assertEqual('fake_ref', ds.ref) - self.assertEqual(2 * units.Gi, ds.capacity) - self.assertEqual(1 * units.Gi, ds.freespace) - - def test_ds_invalid_space(self): - self.assertRaises(ValueError, ds_util.Datastore, - "fake_ref", "ds_name", 1 * units.Gi, 2 * units.Gi) - self.assertRaises(ValueError, ds_util.Datastore, - "fake_ref", "ds_name", None, 2 * units.Gi) - - def test_ds_no_capacity_no_freespace(self): - ds = ds_util.Datastore("fake_ref", "ds_name") - self.assertIsNone(ds.capacity) - self.assertIsNone(ds.freespace) - - def test_ds_invalid(self): - self.assertRaises(ValueError, ds_util.Datastore, None, "ds_name") - self.assertRaises(ValueError, ds_util.Datastore, "fake_ref", None) - - def test_build_path(self): - ds = ds_util.Datastore("fake_ref", "ds_name") - ds_path = ds.build_path("some_dir", "foo.vmdk") - self.assertEqual('[ds_name] some_dir/foo.vmdk', str(ds_path)) - - -class DatastorePathTestCase(test.NoDBTestCase): - - def test_ds_path(self): - p = ds_util.DatastorePath('dsname', 'a/b/c', 'file.iso') - self.assertEqual('[dsname] a/b/c/file.iso', str(p)) - self.assertEqual('a/b/c/file.iso', p.rel_path) - self.assertEqual('a/b/c', p.parent.rel_path) - self.assertEqual('[dsname] a/b/c', str(p.parent)) - self.assertEqual('dsname', p.datastore) - self.assertEqual('file.iso', p.basename) - self.assertEqual('a/b/c', p.dirname) - - def test_ds_path_no_ds_name(self): - bad_args = [ - ('', ['a/b/c', 'file.iso']), - (None, ['a/b/c', 'file.iso'])] - for t in bad_args: - self.assertRaises( - ValueError, ds_util.DatastorePath, - t[0], *t[1]) - - def test_ds_path_invalid_path_components(self): - bad_args = [ - ('dsname', [None]), - ('dsname', ['', None]), - ('dsname', ['a', None]), - ('dsname', ['a', None, 'b']), - ('dsname', [None, '']), - ('dsname', [None, 'b'])] - - for t in bad_args: - self.assertRaises( - ValueError, ds_util.DatastorePath, - t[0], *t[1]) - - def test_ds_path_no_subdir(self): - args = [ - ('dsname', ['', 'x.vmdk']), - ('dsname', ['x.vmdk'])] - - canonical_p = ds_util.DatastorePath('dsname', 'x.vmdk') - self.assertEqual('[dsname] x.vmdk', str(canonical_p)) - self.assertEqual('', canonical_p.dirname) - self.assertEqual('x.vmdk', canonical_p.basename) - self.assertEqual('x.vmdk', canonical_p.rel_path) - for t in args: - p = ds_util.DatastorePath(t[0], *t[1]) - self.assertEqual(str(canonical_p), str(p)) - - def test_ds_path_ds_only(self): - args = [ - ('dsname', []), - ('dsname', ['']), - ('dsname', ['', ''])] - - canonical_p = ds_util.DatastorePath('dsname') - self.assertEqual('[dsname]', str(canonical_p)) - self.assertEqual('', canonical_p.rel_path) - self.assertEqual('', canonical_p.basename) - self.assertEqual('', canonical_p.dirname) - for t in args: - p = ds_util.DatastorePath(t[0], *t[1]) - self.assertEqual(str(canonical_p), str(p)) - self.assertEqual(canonical_p.rel_path, p.rel_path) - - def test_ds_path_equivalence(self): - args = [ - ('dsname', ['a/b/c/', 'x.vmdk']), - ('dsname', ['a/', 'b/c/', 'x.vmdk']), - ('dsname', ['a', 'b', 'c', 'x.vmdk']), - ('dsname', ['a/b/c', 'x.vmdk'])] - - canonical_p = ds_util.DatastorePath('dsname', 'a/b/c', 'x.vmdk') - for t in args: - p = ds_util.DatastorePath(t[0], *t[1]) - self.assertEqual(str(canonical_p), str(p)) - self.assertEqual(canonical_p.datastore, p.datastore) - self.assertEqual(canonical_p.rel_path, p.rel_path) - self.assertEqual(str(canonical_p.parent), str(p.parent)) - - def test_ds_path_non_equivalence(self): - args = [ - # leading slash - ('dsname', ['/a', 'b', 'c', 'x.vmdk']), - ('dsname', ['/a/b/c/', 'x.vmdk']), - ('dsname', ['a/b/c', '/x.vmdk']), - # leading space - ('dsname', ['a/b/c/', ' x.vmdk']), - ('dsname', ['a/', ' b/c/', 'x.vmdk']), - ('dsname', [' a', 'b', 'c', 'x.vmdk']), - # trailing space - ('dsname', ['/a/b/c/', 'x.vmdk ']), - ('dsname', ['a/b/c/ ', 'x.vmdk'])] - - canonical_p = ds_util.DatastorePath('dsname', 'a/b/c', 'x.vmdk') - for t in args: - p = ds_util.DatastorePath(t[0], *t[1]) - self.assertNotEqual(str(canonical_p), str(p)) - - def test_ds_path_hashable(self): - ds1 = ds_util.DatastorePath('dsname', 'path') - ds2 = ds_util.DatastorePath('dsname', 'path') - - # If the above objects have the same hash, they will only be added to - # the set once - self.assertThat(set([ds1, ds2]), matchers.HasLength(1)) - - def test_equal(self): - a = ds_util.DatastorePath('ds_name', 'a') - b = ds_util.DatastorePath('ds_name', 'a') - self.assertEqual(a, b) - - def test_join(self): - p = ds_util.DatastorePath('ds_name', 'a') - ds_path = p.join('b') - self.assertEqual('[ds_name] a/b', str(ds_path)) - - p = ds_util.DatastorePath('ds_name', 'a') - ds_path = p.join() - self.assertEqual('[ds_name] a', str(ds_path)) - - bad_args = [ - [None], - ['', None], - ['a', None], - ['a', None, 'b']] - for arg in bad_args: - self.assertRaises(ValueError, p.join, *arg) - - def test_ds_path_parse(self): - p = ds_util.DatastorePath.parse('[dsname]') - self.assertEqual('dsname', p.datastore) - self.assertEqual('', p.rel_path) - - p = ds_util.DatastorePath.parse('[dsname] folder') - self.assertEqual('dsname', p.datastore) - self.assertEqual('folder', p.rel_path) - - p = ds_util.DatastorePath.parse('[dsname] folder/file') - self.assertEqual('dsname', p.datastore) - self.assertEqual('folder/file', p.rel_path) - - for p in [None, '']: - self.assertRaises(ValueError, ds_util.DatastorePath.parse, p) - - for p in ['bad path', '/a/b/c', 'a/b/c']: - self.assertRaises(IndexError, ds_util.DatastorePath.parse, p) diff --git a/nova/tests/unit/virt/vmwareapi/test_ds_util_datastore_selection.py b/nova/tests/unit/virt/vmwareapi/test_ds_util_datastore_selection.py index cfa71f4135..dcaf023155 100644 --- a/nova/tests/unit/virt/vmwareapi/test_ds_util_datastore_selection.py +++ b/nova/tests/unit/virt/vmwareapi/test_ds_util_datastore_selection.py @@ -15,6 +15,7 @@ import collections import re from oslo_utils import units +from oslo_vmware.objects import datastore as ds_obj from nova import test from nova.virt.vmwareapi import ds_util @@ -62,7 +63,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): def test_filter_datastores_simple(self): datastores = self.build_result_set(self.data) - best_match = ds_util.Datastore(ref='fake_ref', name='ds', + best_match = ds_obj.Datastore(ref='fake_ref', name='ds', capacity=0, freespace=0) rec = ds_util._select_datastore(None, datastores, best_match) @@ -76,7 +77,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): data = [] datastores = self.build_result_set(data) - best_match = ds_util.Datastore(ref='fake_ref', name='ds', + best_match = ds_obj.Datastore(ref='fake_ref', name='ds', capacity=0, freespace=0) rec = ds_util._select_datastore(None, datastores, best_match) @@ -86,7 +87,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): datastores = self.build_result_set(self.data) datastore_regex = re.compile('no_match.*') - best_match = ds_util.Datastore(ref='fake_ref', name='ds', + best_match = ds_obj.Datastore(ref='fake_ref', name='ds', capacity=0, freespace=0) rec = ds_util._select_datastore(None, datastores, best_match, @@ -110,7 +111,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): datastores = self.build_result_set(data) datastore_regex = re.compile('.*-good$') - best_match = ds_util.Datastore(ref='fake_ref', name='ds', + best_match = ds_obj.Datastore(ref='fake_ref', name='ds', capacity=0, freespace=0) rec = ds_util._select_datastore(None, datastores, best_match, @@ -136,7 +137,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): prop_names = ['summary.type', 'summary.name', 'summary.capacity', 'summary.freeSpace'] datastores = self.build_result_set(data, prop_names) - best_match = ds_util.Datastore(ref='fake_ref', name='ds', + best_match = ds_obj.Datastore(ref='fake_ref', name='ds', capacity=0, freespace=0) rec = ds_util._select_datastore(None, datastores, best_match) @@ -155,7 +156,7 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase): datastore_regex = re.compile('.*-good$') # the current best match is better than all candidates - best_match = ds_util.Datastore(ref='ds-100', name='best-ds-good', + best_match = ds_obj.Datastore(ref='ds-100', name='best-ds-good', capacity=20 * units.Gi, freespace=19 * units.Gi) rec = ds_util._select_datastore(None, datastores, diff --git a/nova/tests/unit/virt/vmwareapi/test_imagecache.py b/nova/tests/unit/virt/vmwareapi/test_imagecache.py index f0c6caf18f..b492f21a1f 100644 --- a/nova/tests/unit/virt/vmwareapi/test_imagecache.py +++ b/nova/tests/unit/virt/vmwareapi/test_imagecache.py @@ -18,6 +18,7 @@ import datetime import mock from oslo_config import cfg from oslo_utils import timeutils +from oslo_vmware.objects import datastore as ds_obj from nova import objects from nova import test @@ -67,13 +68,13 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): self.exists = False self._imagecache.timestamp_cleanup( 'fake-dc-ref', 'fake-ds-browser', - ds_util.DatastorePath('fake-ds', 'fake-path')) + ds_obj.DatastorePath('fake-ds', 'fake-path')) self.assertEqual(0, _file_delete.call_count) self.exists = True self._imagecache.timestamp_cleanup( 'fake-dc-ref', 'fake-ds-browser', - ds_util.DatastorePath('fake-ds', 'fake-path')) - expected_ds_path = ds_util.DatastorePath( + ds_obj.DatastorePath('fake-ds', 'fake-path')) + expected_ds_path = ds_obj.DatastorePath( 'fake-ds', 'fake-path', self._file_name) _file_delete.assert_called_once_with(self._session, expected_ds_path, 'fake-dc-ref') @@ -94,12 +95,12 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): self.exists = True ts = self._imagecache._get_timestamp( 'fake-ds-browser', - ds_util.DatastorePath('fake-ds', 'fake-path')) + ds_obj.DatastorePath('fake-ds', 'fake-path')) self.assertEqual(self._file_name, ts) self.exists = False ts = self._imagecache._get_timestamp( 'fake-ds-browser', - ds_util.DatastorePath('fake-ds', 'fake-path')) + ds_obj.DatastorePath('fake-ds', 'fake-path')) self.assertIsNone(ts) def test_get_timestamp_filename(self): @@ -141,7 +142,7 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): fake_get_sub_folders) ) as (_get_dynamic, _get_sub_folders): fake_ds_ref = fake.ManagedObjectReference('fake-ds-ref') - datastore = ds_util.Datastore(name='ds', ref=fake_ds_ref) + datastore = ds_obj.Datastore(name='ds', ref=fake_ds_ref) ds_path = datastore.build_path('base_folder') images = self._imagecache._list_datastore_images( ds_path, datastore) @@ -161,7 +162,7 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): image_id = "fake_image_id" dc_ref = "fake_dc_ref" fake_ds_ref = mock.Mock() - ds = ds_util.Datastore( + ds = ds_obj.Datastore( ref=fake_ds_ref, name='fake_ds', capacity=1, freespace=1) @@ -224,7 +225,7 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): ) as (_get_ds_browser, _get_timestamp, _mkdir, _file_delete, _timestamp_cleanup): timeutils.set_time_override(override_time=self._time) - datastore = ds_util.Datastore(name='ds', ref='fake-ds-ref') + datastore = ds_obj.Datastore(name='ds', ref='fake-ds-ref') dc_info = vmops.DcInfo(ref='dc_ref', name='name', vmFolder='vmFolder') self._get_timestamp_called = 0 @@ -233,7 +234,7 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): self._imagecache.used_images = set(['fake-image-4']) self._imagecache._age_cached_images( 'fake-context', datastore, dc_info, - ds_util.DatastorePath('fake-ds', 'fake-path')) + ds_obj.DatastorePath('fake-ds', 'fake-path')) self.assertEqual(3, self._get_timestamp_called) @mock.patch.object(objects.block_device.BlockDeviceMappingList, @@ -273,7 +274,7 @@ class ImageCacheManagerTestCase(test.NoDBTestCase): all_instances = [fake_instance.fake_instance_obj(None, **instance) for instance in instances] self.images = set(['1', '2']) - datastore = ds_util.Datastore(name='ds', ref='fake-ds-ref') + datastore = ds_obj.Datastore(name='ds', ref='fake-ds-ref') dc_info = vmops.DcInfo(ref='dc_ref', name='name', vmFolder='vmFolder') datastores_info = [(datastore, dc_info)] diff --git a/nova/tests/unit/virt/vmwareapi/test_vm_util.py b/nova/tests/unit/virt/vmwareapi/test_vm_util.py index 66ca991ed7..81dd85c985 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vm_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_vm_util.py @@ -20,6 +20,7 @@ import contextlib import mock from oslo_utils import uuidutils from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from oslo_vmware import pbm from nova import exception @@ -29,7 +30,6 @@ from nova.tests.unit import fake_instance from nova.tests.unit.virt.vmwareapi import fake from nova.tests.unit.virt.vmwareapi import stubs from nova.virt.vmwareapi import driver -from nova.virt.vmwareapi import ds_util from nova.virt.vmwareapi import vm_util @@ -1096,7 +1096,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): self.assertEqual('vmx-08', result.version) def test_vm_create_spec_with_profile_spec(self): - datastore = ds_util.Datastore('fake-ds-ref', 'fake-ds-name') + datastore = ds_obj.Datastore('fake-ds-ref', 'fake-ds-name') extra_specs = vm_util.ExtraSpecs() create_spec = vm_util.get_vm_create_spec(fake.FakeFactory(), self._instance, diff --git a/nova/tests/unit/virt/vmwareapi/test_vmops.py b/nova/tests/unit/virt/vmwareapi/test_vmops.py index ec3a93162f..93d485562b 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vmops.py +++ b/nova/tests/unit/virt/vmwareapi/test_vmops.py @@ -18,6 +18,7 @@ import mock from oslo_utils import units from oslo_utils import uuidutils from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from nova.compute import power_state from nova import context @@ -62,7 +63,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): self._virtapi = mock.Mock() self._image_id = nova.tests.unit.image.fake.get_valid_image_id() fake_ds_ref = vmwareapi_fake.ManagedObjectReference('fake-ds') - self._ds = ds_util.Datastore( + self._ds = ds_obj.Datastore( ref=fake_ds_ref, name='fake_ds', capacity=10 * units.Gi, freespace=10 * units.Gi) @@ -160,7 +161,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): ref=dc_ref, name='fake-name', vmFolder='fake-folder') - path = ds_util.DatastorePath(ds_name, base_name) + path = ds_obj.DatastorePath(ds_name, base_name) return ds_name, ds_ref, ops, path, dc_ref @mock.patch.object(ds_util, 'mkdir') @@ -367,7 +368,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): _volumeops = mock.Mock() self._vmops._volumeops = _volumeops - ds = ds_util.Datastore('fake-ref', 'ds1') + ds = ds_obj.Datastore('fake-ref', 'ds1') mock_get_ds_by_ref.return_value = ds mock_find_rescue.return_value = 'fake-rescue-device' mock_get_boot_spec.return_value = 'fake-boot-spec' @@ -522,7 +523,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): fake_get_extra_specs, power_on): """Tests the finish_revert_migration method on vmops.""" - datastore = ds_util.Datastore(ref='fake-ref', name='fake') + datastore = ds_obj.Datastore(ref='fake-ref', name='fake') device = vmwareapi_fake.DataObject() backing = vmwareapi_fake.DataObject() backing.datastore = datastore.ref @@ -571,7 +572,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): fake_get_browser.assert_called_once_with('fake-ref') fake_original_exists.assert_called_once_with( self._session, 'fake-browser', - ds_util.DatastorePath(datastore.name, 'uuid'), + ds_obj.DatastorePath(datastore.name, 'uuid'), 'original.vmdk') mock_detach_disk.assert_called_once_with('fake-ref', @@ -622,7 +623,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): @mock.patch.object(ds_util, 'disk_copy') def test_resize_disk(self, fake_disk_copy, fake_disk_move, fake_extend): - datastore = ds_util.Datastore(ref='fake-ref', name='fake') + datastore = ds_obj.Datastore(ref='fake-ref', name='fake') device = vmwareapi_fake.DataObject() backing = vmwareapi_fake.DataObject() backing.datastore = datastore.ref @@ -675,7 +676,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): fake_original_exists, fake_disk_delete): """Tests the confirm_migration method on vmops.""" - datastore = ds_util.Datastore(ref='fake-ref', name='fake') + datastore = ds_obj.Datastore(ref='fake-ref', name='fake') device = vmwareapi_fake.DataObject() backing = vmwareapi_fake.DataObject() backing.datastore = datastore.ref @@ -703,7 +704,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): fake_get_browser.assert_called_once_with('fake-ref') fake_original_exists.assert_called_once_with( self._session, 'fake-browser', - ds_util.DatastorePath(datastore.name, 'uuid'), + ds_obj.DatastorePath(datastore.name, 'uuid'), 'original.vmdk') fake_disk_delete.assert_called_once_with( self._session, dc_info.ref, '[fake] uuid/original.vmdk') @@ -1425,8 +1426,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): self._vmops._volumeops = mock.Mock() mock_attach_disk_to_vm = self._vmops._volumeops.attach_disk_to_vm - path = str(ds_util.DatastorePath(vi.datastore.name, 'fake_uuid', - 'fake-filename')) + path = str(ds_obj.DatastorePath(vi.datastore.name, 'fake_uuid', + 'fake-filename')) self._vmops._create_and_attach_ephemeral_disk(self._instance, 'fake-vm-ref', vi.dc_info, 1, @@ -1831,7 +1832,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): sparse_disk_path = "[%s] vmware_temp/tmp-uuid/%s/tmp-sparse.vmdk" % ( self._ds.name, self._image_id) - tmp_image_ds_loc = ds_util.DatastorePath.parse(sparse_disk_path) + tmp_image_ds_loc = ds_obj.DatastorePath.parse(sparse_disk_path) self._vmops._cache_sparse_image(vi, tmp_image_ds_loc) diff --git a/nova/virt/vmwareapi/ds_util.py b/nova/virt/vmwareapi/ds_util.py index 118c14e4d0..d447715594 100644 --- a/nova/virt/vmwareapi/ds_util.py +++ b/nova/virt/vmwareapi/ds_util.py @@ -16,10 +16,9 @@ Datastore utility functions """ -import posixpath - from oslo_log import log as logging from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from oslo_vmware import pbm from nova import exception @@ -34,156 +33,6 @@ ALL_SUPPORTED_DS_TYPES = frozenset([constants.DATASTORE_TYPE_VMFS, constants.DATASTORE_TYPE_VSAN]) -class Datastore(object): - - def __init__(self, ref, name, capacity=None, freespace=None): - """Datastore object holds ref and name together for convenience. - - :param ref: a vSphere reference to a datastore - :param name: vSphere unique name for this datastore - :param capacity: (optional) capacity in bytes of this datastore - :param freespace: (optional) free space in bytes of datastore - """ - if name is None: - raise ValueError(_("Datastore name cannot be None")) - if ref is None: - raise ValueError(_("Datastore reference cannot be None")) - if freespace is not None and capacity is None: - raise ValueError(_("Invalid capacity")) - if capacity is not None and freespace is not None: - if capacity < freespace: - raise ValueError(_("Capacity is smaller than free space")) - - self._ref = ref - self._name = name - self._capacity = capacity - self._freespace = freespace - - @property - def ref(self): - return self._ref - - @property - def name(self): - return self._name - - @property - def capacity(self): - return self._capacity - - @property - def freespace(self): - return self._freespace - - def build_path(self, *paths): - """Constructs and returns a DatastorePath. - - :param paths: list of path components, for constructing a path relative - to the root directory of the datastore - :return: a DatastorePath object - """ - return DatastorePath(self._name, *paths) - - def __str__(self): - return '[%s]' % self._name - - -class DatastorePath(object): - """Class for representing a directory or file path in a vSphere datatore. - - This provides various helper methods to access components and useful - variants of the datastore path. - - Example usage: - - DatastorePath("datastore1", "_base/foo", "foo.vmdk") creates an - object that describes the "[datastore1] _base/foo/foo.vmdk" datastore - file path to a virtual disk. - - Note: - - * Datastore path representations always uses forward slash as separator - (hence the use of the posixpath module). - * Datastore names are enclosed in square brackets. - * Path part of datastore path is relative to the root directory - of the datastore, and is always separated from the [ds_name] part with - a single space. - - """ - - VMDK_EXTENSION = "vmdk" - - def __init__(self, datastore_name, *paths): - if datastore_name is None or datastore_name == '': - raise ValueError(_("datastore name empty")) - self._datastore_name = datastore_name - self._rel_path = '' - if paths: - if None in paths: - raise ValueError(_("path component cannot be None")) - self._rel_path = posixpath.join(*paths) - - def __str__(self): - """Full datastore path to the file or directory.""" - if self._rel_path != '': - return "[%s] %s" % (self._datastore_name, self.rel_path) - return "[%s]" % self._datastore_name - - def __repr__(self): - return "%s(%s, %s)" % (self.__class__.__name__, - self.datastore, self.rel_path) - - @property - def datastore(self): - return self._datastore_name - - @property - def parent(self): - return DatastorePath(self.datastore, posixpath.dirname(self._rel_path)) - - @property - def basename(self): - return posixpath.basename(self._rel_path) - - @property - def dirname(self): - return posixpath.dirname(self._rel_path) - - @property - def rel_path(self): - return self._rel_path - - def join(self, *paths): - if paths: - if None in paths: - raise ValueError(_("path component cannot be None")) - return DatastorePath(self.datastore, - posixpath.join(self._rel_path, *paths)) - return self - - def __eq__(self, other): - return (isinstance(other, DatastorePath) and - self._datastore_name == other._datastore_name and - self._rel_path == other._rel_path) - - def __hash__(self): - return str(self).__hash__() - - @classmethod - def parse(cls, datastore_path): - """Constructs a DatastorePath object given a datastore path string.""" - if not datastore_path: - raise ValueError(_("datastore path empty")) - - spl = datastore_path.split('[', 1)[1].split(']', 1) - path = "" - if len(spl) == 1: - datastore_name = spl[0] - else: - datastore_name, path = spl - return cls(datastore_name, path.strip()) - - # NOTE(mdbooth): this convenience function is temporarily duplicated in # vm_util. The correct fix is to handle paginated results as they are returned # from the relevant vim_util function. However, vim_util is currently @@ -224,7 +73,7 @@ def _select_datastore(session, data_stores, best_match, datastore_regex=None, propdict = vm_util.propset_dict(obj_content.propSet) if _is_datastore_valid(propdict, datastore_regex, allowed_ds_types): - new_ds = Datastore( + new_ds = ds_obj.Datastore( ref=obj_content.obj, name=propdict['summary.name'], capacity=propdict['summary.capacity'], @@ -317,9 +166,9 @@ def get_datastore_by_ref(session, ds_ref): props = session._call_method(vim_util, "get_object_properties", None, ds_ref, "Datastore", lst_properties) query = vm_util.get_values_from_object_properties(session, props) - return Datastore(ds_ref, query["summary.name"], - capacity=query["summary.capacity"], - freespace=query["summary.freeSpace"]) + return ds_obj.Datastore(ds_ref, query["summary.name"], + capacity=query["summary.capacity"], + freespace=query["summary.freeSpace"]) def _get_allowed_datastores(data_stores, datastore_regex): @@ -333,8 +182,8 @@ def _get_allowed_datastores(data_stores, datastore_regex): if _is_datastore_valid(propdict, datastore_regex, ALL_SUPPORTED_DS_TYPES): - allowed.append(Datastore(ref=obj_content.obj, - name=propdict['summary.name'])) + allowed.append(ds_obj.Datastore(ref=obj_content.obj, + name=propdict['summary.name'])) return allowed diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 9fef93be4c..c228100a3c 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -32,6 +32,7 @@ from oslo_utils import strutils from oslo_utils import units from oslo_utils import uuidutils from oslo_vmware import exceptions as vexc +from oslo_vmware.objects import datastore as ds_obj from nova.api.metadata import base as instance_metadata from nova import compute @@ -196,7 +197,7 @@ class VMwareVMOps(object): # Clean up files created during the extend operation files = [name.replace(".vmdk", "-flat.vmdk"), name] for file in files: - ds_path = ds_util.DatastorePath.parse(file) + ds_path = ds_obj.DatastorePath.parse(file) self._delete_datastore_file(ds_path, dc_ref) LOG.debug("Extended root virtual disk") @@ -531,8 +532,8 @@ class VMwareVMOps(object): size = eph['size'] * units.Mi at = eph.get('disk_bus', adapter_type) filename = vm_util.get_ephemeral_name(idx) - path = str(ds_util.DatastorePath(datastore.name, folder, - filename)) + path = str(ds_obj.DatastorePath(datastore.name, folder, + filename)) self._create_and_attach_ephemeral_disk(instance, vm_ref, dc_info, size, at, path) @@ -541,8 +542,8 @@ class VMwareVMOps(object): if not ephemerals and instance.ephemeral_gb: size = instance.ephemeral_gb * units.Mi filename = vm_util.get_ephemeral_name(0) - path = str(ds_util.DatastorePath(datastore.name, folder, - filename)) + path = str(ds_obj.DatastorePath(datastore.name, folder, + filename)) self._create_and_attach_ephemeral_disk(instance, vm_ref, dc_info, size, adapter_type, path) @@ -884,7 +885,7 @@ class VMwareVMOps(object): vm_config_pathname = query.get('config.files.vmPathName') vm_ds_path = None if vm_config_pathname is not None: - vm_ds_path = ds_util.DatastorePath.parse( + vm_ds_path = ds_obj.DatastorePath.parse( vm_config_pathname) # Power off the VM if it is in PoweredOn state. @@ -1108,16 +1109,16 @@ class VMwareVMOps(object): root_disk_in_kb = flavor['root_gb'] * units.Mi ds_ref = vmdk.device.backing.datastore dc_info = self.get_datacenter_ref_and_name(ds_ref) - folder = ds_util.DatastorePath.parse(vmdk.path).dirname - datastore = ds_util.DatastorePath.parse(vmdk.path).datastore - resized_disk = str(ds_util.DatastorePath(datastore, folder, + folder = ds_obj.DatastorePath.parse(vmdk.path).dirname + datastore = ds_obj.DatastorePath.parse(vmdk.path).datastore + resized_disk = str(ds_obj.DatastorePath(datastore, folder, 'resized.vmdk')) ds_util.disk_copy(self._session, dc_info.ref, vmdk.path, str(resized_disk)) self._extend_virtual_disk(instance, root_disk_in_kb, resized_disk, dc_info.ref) self._volumeops.detach_disk_from_vm(vm_ref, instance, vmdk.device) - original_disk = str(ds_util.DatastorePath(datastore, folder, + original_disk = str(ds_obj.DatastorePath(datastore, folder, 'original.vmdk')) ds_util.disk_move(self._session, dc_info.ref, vmdk.path, original_disk) @@ -1197,10 +1198,10 @@ class VMwareVMOps(object): uuid=instance.uuid) ds_ref = vmdk.device.backing.datastore dc_info = self.get_datacenter_ref_and_name(ds_ref) - folder = ds_util.DatastorePath.parse(vmdk.path).dirname - datastore = ds_util.DatastorePath.parse(vmdk.path).datastore - original_disk = ds_util.DatastorePath(datastore, folder, - 'original.vmdk') + folder = ds_obj.DatastorePath.parse(vmdk.path).dirname + datastore = ds_obj.DatastorePath.parse(vmdk.path).datastore + original_disk = ds_obj.DatastorePath(datastore, folder, + 'original.vmdk') ds_browser = self._get_ds_browser(ds_ref) if ds_util.file_exists(self._session, ds_browser, original_disk.parent, @@ -1228,9 +1229,9 @@ class VMwareVMOps(object): uuid=instance.uuid) ds_ref = vmdk.device.backing.datastore dc_info = self.get_datacenter_ref_and_name(ds_ref) - folder = ds_util.DatastorePath.parse(vmdk.path).dirname - datastore = ds_util.DatastorePath.parse(vmdk.path).datastore - original_disk = ds_util.DatastorePath(datastore, folder, + folder = ds_obj.DatastorePath.parse(vmdk.path).dirname + datastore = ds_obj.DatastorePath.parse(vmdk.path).datastore + original_disk = ds_obj.DatastorePath(datastore, folder, 'original.vmdk') ds_browser = self._get_ds_browser(ds_ref) if ds_util.file_exists(self._session, ds_browser, @@ -1478,7 +1479,7 @@ class VMwareVMOps(object): exists. If this throws and exception 'FileAlreadyExistsException' then the folder already exists on the datastore. """ - path = ds_util.DatastorePath(ds_name, folder) + path = ds_obj.DatastorePath(ds_name, folder) dc_info = self.get_datacenter_ref_and_name(ds_ref) try: ds_util.mkdir(self._session, path, dc_info.ref) |