Merge "VMware: ephemeral disk support"

This commit is contained in:
Jenkins 2014-12-05 13:39:52 +00:00 committed by Gerrit Code Review
commit e6983a1ff5
6 changed files with 172 additions and 7 deletions

View File

@ -385,12 +385,15 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
'flavorid': '1', 'vcpu_weight': None, 'id': 2}
def _create_instance(self, node=None, set_image_ref=True,
uuid=None, instance_type='m1.large'):
uuid=None, instance_type='m1.large',
ephemeral=None):
if not node:
node = self.node_name
if not uuid:
uuid = uuidutils.generate_uuid()
self.type_data = self._get_instance_type_by_name(instance_type)
if ephemeral is not None:
self.type_data['ephemeral_gb'] = ephemeral
values = {'name': 'fake_name',
'id': 1,
'uuid': uuid,
@ -416,17 +419,19 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
self.context, **values)
def _create_vm(self, node=None, num_instances=1, uuid=None,
instance_type='m1.large', powered_on=True):
instance_type='m1.large', powered_on=True,
ephemeral=None, bdi=None):
"""Create and spawn the VM."""
if not node:
node = self.node_name
self._create_instance(node=node, uuid=uuid,
instance_type=instance_type)
instance_type=instance_type,
ephemeral=ephemeral)
self.assertIsNone(vm_util.vm_ref_cache_get(self.uuid))
self.conn.spawn(self.context, self.instance, self.image,
injected_files=[], admin_password=None,
network_info=self.network_info,
block_device_info=None)
block_device_info=bdi)
self._check_vm_record(num_instances=num_instances,
powered_on=powered_on)
self.assertIsNotNone(vm_util.vm_ref_cache_get(self.uuid))
@ -644,6 +649,35 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
self._create_vm()
self.assertEqual(self.iso_index, 2)
def test_ephemeral_disk_attach(self):
self._create_vm(ephemeral=50)
path = ds_util.DatastorePath(self.ds, self.uuid,
'ephemeral_0.vmdk')
self.assertTrue(vmwareapi_fake.get_file(str(path)))
def test_ephemeral_disk_attach_from_bdi(self):
ephemerals = [{'device_type': 'disk',
'disk_bus': 'lsiLogic',
'size': 25},
{'device_type': 'disk',
'disk_bus': 'lsiLogic',
'size': 25}]
bdi = {'ephemerals': ephemerals}
self._create_vm(bdi=bdi, ephemeral=50)
path = ds_util.DatastorePath(self.ds, self.uuid,
'ephemeral_0.vmdk')
self.assertTrue(vmwareapi_fake.get_file(str(path)))
path = ds_util.DatastorePath(self.ds, self.uuid,
'ephemeral_1.vmdk')
self.assertTrue(vmwareapi_fake.get_file(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,
'ephemeral_0.vmdk')
self.assertTrue(vmwareapi_fake.get_file(str(path)))
def test_cdrom_attach_with_config_drive(self):
self.flags(force_config_drive=True)

View File

@ -1089,6 +1089,10 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
'fake_policy')
self.assertIsNone(profile_spec)
def test_get_ephemeral_name(self):
filename = vm_util.get_ephemeral_name(0)
self.assertEqual('ephemeral_0.vmdk', filename)
@mock.patch.object(driver.VMwareAPISession, 'vim', stubs.fake_vim_prop)
class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase):

View File

@ -739,7 +739,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def test_use_iso_image_without_root_disk(self):
self._test_use_iso_image(with_root_disk=False)
def _verify_spawn_method_calls(self, mock_call_method):
def _verify_spawn_method_calls(self, mock_call_method, extras=None):
# TODO(vui): More explicit assertions of spawn() behavior
# are waiting on additional refactoring pertaining to image
# handling/manipulation. Till then, we continue to assert on the
@ -753,6 +753,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
'SearchDatastore_Task',
'ExtendVirtualDisk_Task',
]
if extras:
expected_methods.extend(extras)
recorded_methods = [c[1][1] for c in mock_call_method.mock_calls]
self.assertEqual(expected_methods, recorded_methods)
@ -875,7 +877,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
else:
self.assertFalse(mock_power_on_instance.called)
if block_device_info:
if (block_device_info and
'block_device_mapping' in block_device_info):
root_disk = block_device_info['block_device_mapping'][0]
mock_attach = self._vmops._volumeops.attach_root_volume
mock_attach.assert_called_once_with(
@ -899,7 +902,10 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
upload_file_name,
cookies='Fake-CookieJar')
self.assertTrue(len(_wait_for_task.mock_calls) > 0)
self._verify_spawn_method_calls(_call_method)
extras = None
if block_device_info and 'ephemerals' in block_device_info:
extras = ['CreateVirtualDisk_Task']
self._verify_spawn_method_calls(_call_method, extras)
dc_ref = 'fake_dc_ref'
source_file = unicode('[fake_ds] vmware_base/%s/%s.vmdk' %
@ -992,6 +998,82 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
self._test_spawn(block_device_info=block_device_info,
config_drive=True)
def test_spawn_with_block_device_info_ephemerals(self):
ephemerals = [{'device_type': 'disk',
'disk_bus': 'virtio',
'device_name': '/dev/vdb',
'size': 1}]
block_device_info = {'ephemerals': ephemerals}
self._test_spawn(block_device_info=block_device_info)
def _get_fake_vi(self):
image_info = images.VMwareImage(
image_id=self._image_id,
file_size=7,
linked_clone=False)
vi = vmops.VirtualMachineInstanceConfigInfo(
self._instance, 'fake_uuid', image_info,
self._ds, self._dc_info, mock.Mock())
return vi
@mock.patch.object(vm_util, 'create_virtual_disk')
def test_create_and_attach_ephemeral_disk(self, mock_create):
vi = self._get_fake_vi()
self._vmops._volumeops = mock.Mock()
mock_attach_disk_to_vm = self._vmops._volumeops.attach_disk_to_vm
self._vmops._create_and_attach_ephemeral_disk(self._instance,
'fake-vm-ref',
vi, 1,
'fake-adapter-type',
'fake-filename')
path = str(ds_util.DatastorePath(vi.datastore.name, 'fake_uuid',
'fake-filename'))
mock_create.assert_called_once_with(
self._session, self._dc_info.ref, 'fake-adapter-type',
'thin', path, 1)
mock_attach_disk_to_vm.assert_called_once_with(
'fake-vm-ref', self._instance, 'fake-adapter-type',
'thin', path, 1, False)
def test_create_ephemeral_with_bdi(self):
ephemerals = [{'device_type': 'disk',
'disk_bus': 'virtio',
'device_name': '/dev/vdb',
'size': 1}]
block_device_info = {'ephemerals': ephemerals}
vi = self._get_fake_vi()
with mock.patch.object(
self._vmops, '_create_and_attach_ephemeral_disk') as mock_caa:
self._vmops._create_ephemeral(block_device_info,
self._instance,
'fake-vm-ref',
vi)
mock_caa.assert_called_once_with(self._instance, 'fake-vm-ref',
vi, 1 * units.Mi, 'virtio',
'ephemeral_0.vmdk')
def _test_create_ephemeral_from_instance(self, bdi):
vi = self._get_fake_vi()
with mock.patch.object(
self._vmops, '_create_and_attach_ephemeral_disk') as mock_caa:
self._vmops._create_ephemeral(bdi,
self._instance,
'fake-vm-ref',
vi)
mock_caa.assert_called_once_with(self._instance, 'fake-vm-ref',
vi, 1 * units.Mi, 'lsiLogic',
'ephemeral_0.vmdk')
def test_create_ephemeral_with_bdi_but_no_ephemerals(self):
block_device_info = {'ephemerals': []}
self._instance.ephemeral_gb = 1
self._test_create_ephemeral_from_instance(block_device_info)
def test_create_ephemeral_with_no_bdi(self):
self._instance.ephemeral_gb = 1
self._test_create_ephemeral_from_instance(None)
def test_build_virtual_machine(self):
image_id = nova.tests.unit.image.fake.get_valid_image_id()
image = images.VMwareImage(image_id=image_id)

View File

@ -22,6 +22,7 @@ DISK_FORMAT_ISO = 'iso'
DISK_FORMAT_VMDK = 'vmdk'
DISK_FORMATS_ALL = [DISK_FORMAT_ISO, DISK_FORMAT_VMDK]
DISK_TYPE_THIN = 'thin'
DISK_TYPE_SPARSE = 'sparse'
DISK_TYPE_THIN = 'thin'
DISK_TYPE_PREALLOCATED = 'preallocated'

View File

@ -1481,3 +1481,7 @@ def power_off_instance(session, instance, vm_ref=None):
LOG.debug("Powered off the VM", instance=instance)
except vexc.InvalidPowerStateException:
LOG.debug("VM already powered off", instance=instance)
def get_ephemeral_name(id):
return 'ephemeral_%d.vmdk' % id

View File

@ -477,6 +477,43 @@ class VMwareVMOps(object):
LOG.debug("Cleaning up location %s", str(tmp_dir_loc))
self._delete_datastore_file(str(tmp_dir_loc), vi.dc_info.ref)
def _create_and_attach_ephemeral_disk(self, instance, vm_ref, vi, size,
adapter_type, filename):
path = str(ds_util.DatastorePath(vi.datastore.name, instance.uuid,
filename))
disk_type = constants.DISK_TYPE_THIN
vm_util.create_virtual_disk(
self._session, vi.dc_info.ref,
adapter_type,
disk_type,
path,
size)
self._volumeops.attach_disk_to_vm(
vm_ref, vi.instance,
adapter_type, disk_type,
path, size, False)
def _create_ephemeral(self, bdi, instance, vm_ref, vi):
ephemerals = None
if bdi is not None:
ephemerals = driver.block_device_info_get_ephemerals(bdi)
for idx, eph in enumerate(ephemerals):
size = eph['size'] * units.Mi
adapter_type = eph.get('disk_bus', vi.ii.adapter_type)
filename = vm_util.get_ephemeral_name(idx)
self._create_and_attach_ephemeral_disk(instance, vm_ref, vi,
size, adapter_type,
filename)
# There may be block devices defined but no ephemerals. In this case
# we need to allocate a ephemeral disk if required
if not ephemerals and instance.ephemeral_gb:
size = instance.ephemeral_gb * units.Mi
filename = vm_util.get_ephemeral_name(0)
self._create_and_attach_ephemeral_disk(instance, vm_ref, vi,
size, vi.ii.adapter_type,
filename)
def spawn(self, context, instance, image_meta, injected_files,
admin_password, network_info, block_device_info=None,
instance_name=None, power_on=True):
@ -552,6 +589,9 @@ class VMwareVMOps(object):
else:
self._use_disk_image_as_full_clone(vm_ref, vi)
# Create ephemeral disks
self._create_ephemeral(block_device_info, instance, vm_ref, vi)
if configdrive.required_by(instance):
self._configure_config_drive(
instance, vm_ref, vi.dc_info, vi.datastore,