VMware: Early fail spawn if memory is not multiple of 4.
If instance memory is not multiple of 4, creating instance on ESXi fails with error "['GenericVmConfigFault'] VimFaultException: Memory (RAM) size is invalid.". However this is after instance is built and tried to launch on ESXi. Add check in prepare_for_spawn to trigger failure early and avoid further steps i.e. build as well as launch. Closes-Bug: #1966987 Change-Id: I7ed8ac986283cd455e54e3f18ab955f43b3248d0
This commit is contained in:
parent
a1f006d799
commit
08e8bdf271
@ -2711,6 +2711,7 @@ class ComputeManager(manager.Manager):
|
|||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
self._build_resources_cleanup(instance, network_info)
|
self._build_resources_cleanup(instance, network_info)
|
||||||
except (exception.UnexpectedTaskStateError,
|
except (exception.UnexpectedTaskStateError,
|
||||||
|
exception.InstanceUnacceptable,
|
||||||
exception.OverQuota, exception.InvalidBDM) as e:
|
exception.OverQuota, exception.InvalidBDM) as e:
|
||||||
self._build_resources_cleanup(instance, network_info)
|
self._build_resources_cleanup(instance, network_info)
|
||||||
raise exception.BuildAbortException(instance_uuid=instance.uuid,
|
raise exception.BuildAbortException(instance_uuid=instance.uuid,
|
||||||
|
@ -166,7 +166,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
"projectid:fake_project\n"
|
"projectid:fake_project\n"
|
||||||
"projectname:None\n"
|
"projectname:None\n"
|
||||||
"flavor:name:m1.micro\n"
|
"flavor:name:m1.micro\n"
|
||||||
"flavor:memory_mb:6\n"
|
"flavor:memory_mb:8\n"
|
||||||
"flavor:vcpus:28\n"
|
"flavor:vcpus:28\n"
|
||||||
"flavor:ephemeral_gb:8128\n"
|
"flavor:ephemeral_gb:8128\n"
|
||||||
"flavor:root_gb:496\n"
|
"flavor:root_gb:496\n"
|
||||||
@ -1138,6 +1138,14 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
mock_attach_cdrom_to_vm.assert_called_once_with(
|
mock_attach_cdrom_to_vm.assert_called_once_with(
|
||||||
vm_ref, self._instance, self._ds.ref, str(upload_iso_path))
|
vm_ref, self._instance, self._ds.ref, str(upload_iso_path))
|
||||||
|
|
||||||
|
def test_prepare_for_spawn_invalid_ram(self):
|
||||||
|
instance = self._instance.obj_clone()
|
||||||
|
flavor = objects.Flavor(vcpus=1, memory_mb=6, ephemeral_gb=1,
|
||||||
|
swap=1024, extra_specs={})
|
||||||
|
instance.flavor = flavor
|
||||||
|
self.assertRaises(exception.InstanceUnacceptable,
|
||||||
|
self._vmops.prepare_for_spawn, instance)
|
||||||
|
|
||||||
@mock.patch('nova.image.glance.API.get')
|
@mock.patch('nova.image.glance.API.get')
|
||||||
@mock.patch.object(vmops.LOG, 'debug')
|
@mock.patch.object(vmops.LOG, 'debug')
|
||||||
@mock.patch.object(vmops.VMwareVMOps, '_fetch_image_if_missing')
|
@mock.patch.object(vmops.VMwareVMOps, '_fetch_image_if_missing')
|
||||||
@ -2176,7 +2184,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
def _validate_flavor_extra_specs(self, flavor_extra_specs, expected):
|
def _validate_flavor_extra_specs(self, flavor_extra_specs, expected):
|
||||||
# Validate that the extra specs are parsed correctly
|
# Validate that the extra specs are parsed correctly
|
||||||
flavor = objects.Flavor(name='my-flavor',
|
flavor = objects.Flavor(name='my-flavor',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2227,7 +2235,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
flavor_extra_specs = {'quota:cpu_limit': 7,
|
flavor_extra_specs = {'quota:cpu_limit': 7,
|
||||||
'quota:cpu_reservation': 6}
|
'quota:cpu_reservation': 6}
|
||||||
flavor = objects.Flavor(name='my-flavor',
|
flavor = objects.Flavor(name='my-flavor',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2280,7 +2288,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
'quota:cpu_reservation': 6,
|
'quota:cpu_reservation': 6,
|
||||||
'hw_video:ram_max_mb': 100}
|
'hw_video:ram_max_mb': 100}
|
||||||
flavor = objects.Flavor(name='my-flavor',
|
flavor = objects.Flavor(name='my-flavor',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2692,7 +2700,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
def test_get_storage_policy_none(self):
|
def test_get_storage_policy_none(self):
|
||||||
flavor = objects.Flavor(name='m1.small',
|
flavor = objects.Flavor(name='m1.small',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2706,7 +2714,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
def test_get_storage_policy_extra_specs(self):
|
def test_get_storage_policy_extra_specs(self):
|
||||||
extra_specs = {'vmware:storage_policy': 'flavor-policy'}
|
extra_specs = {'vmware:storage_policy': 'flavor-policy'}
|
||||||
flavor = objects.Flavor(name='m1.small',
|
flavor = objects.Flavor(name='m1.small',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2781,7 +2789,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
def test_get_instance_metadata(self):
|
def test_get_instance_metadata(self):
|
||||||
flavor = objects.Flavor(id=7,
|
flavor = objects.Flavor(id=7,
|
||||||
name='m1.small',
|
name='m1.small',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
@ -2796,7 +2804,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
"projectid:fake_project\n"
|
"projectid:fake_project\n"
|
||||||
"projectname:None\n"
|
"projectname:None\n"
|
||||||
"flavor:name:m1.small\n"
|
"flavor:name:m1.small\n"
|
||||||
"flavor:memory_mb:6\n"
|
"flavor:memory_mb:8\n"
|
||||||
"flavor:vcpus:28\n"
|
"flavor:vcpus:28\n"
|
||||||
"flavor:ephemeral_gb:8128\n"
|
"flavor:ephemeral_gb:8128\n"
|
||||||
"flavor:root_gb:496\n"
|
"flavor:root_gb:496\n"
|
||||||
@ -2913,7 +2921,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||||||
def test_get_cores_per_socket(self):
|
def test_get_cores_per_socket(self):
|
||||||
extra_specs = {'hw:cpu_sockets': 7}
|
extra_specs = {'hw:cpu_sockets': 7}
|
||||||
flavor = objects.Flavor(name='m1.small',
|
flavor = objects.Flavor(name='m1.small',
|
||||||
memory_mb=6,
|
memory_mb=8,
|
||||||
vcpus=28,
|
vcpus=28,
|
||||||
root_gb=496,
|
root_gb=496,
|
||||||
ephemeral_gb=8128,
|
ephemeral_gb=8128,
|
||||||
|
@ -519,6 +519,10 @@ class VMwareVCDriver(driver.ComputeDriver):
|
|||||||
# where cpu traits are added. In the vmware world, this is where we
|
# where cpu traits are added. In the vmware world, this is where we
|
||||||
# would add nested providers representing tenant VDC and similar.
|
# would add nested providers representing tenant VDC and similar.
|
||||||
|
|
||||||
|
def prepare_for_spawn(self, instance):
|
||||||
|
"""Perform pre-checks for spawn."""
|
||||||
|
self._vmops.prepare_for_spawn(instance)
|
||||||
|
|
||||||
def spawn(self, context, instance, image_meta, injected_files,
|
def spawn(self, context, instance, image_meta, injected_files,
|
||||||
admin_password, allocations, network_info=None,
|
admin_password, allocations, network_info=None,
|
||||||
block_device_info=None, power_on=True, accel_info=None):
|
block_device_info=None, power_on=True, accel_info=None):
|
||||||
|
@ -729,6 +729,12 @@ class VMwareVMOps(object):
|
|||||||
if new_size is not None:
|
if new_size is not None:
|
||||||
vi.ii.file_size = new_size
|
vi.ii.file_size = new_size
|
||||||
|
|
||||||
|
def prepare_for_spawn(self, instance):
|
||||||
|
if (int(instance.flavor.memory_mb) % 4 != 0):
|
||||||
|
reason = _("Memory size is not multiple of 4")
|
||||||
|
raise exception.InstanceUnacceptable(instance_id=instance.uuid,
|
||||||
|
reason=reason)
|
||||||
|
|
||||||
def spawn(self, context, instance, image_meta, injected_files,
|
def spawn(self, context, instance, image_meta, injected_files,
|
||||||
admin_password, network_info, block_device_info=None):
|
admin_password, network_info, block_device_info=None):
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
For the VMware ESXi, VM memory should be multiple of 4. Otherwise creating
|
||||||
|
instance on ESXi fails with error "VimFaultException: Memory (RAM) size is
|
||||||
|
invalid.". Instances will now fail to spawn if flavor memory is not a
|
||||||
|
multiple of 4.
|
Loading…
Reference in New Issue
Block a user