From 08e8bdf2711d717adc1028b5acecd81e4ce71572 Mon Sep 17 00:00:00 2001 From: Kiran Pawar Date: Tue, 29 Mar 2022 17:29:01 +0000 Subject: [PATCH] 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 --- nova/compute/manager.py | 1 + nova/tests/unit/virt/vmwareapi/test_vmops.py | 26 ++++++++++++------- nova/virt/vmwareapi/driver.py | 4 +++ nova/virt/vmwareapi/vmops.py | 6 +++++ ...iple-of-4-validation-9740bf60d59ce5e2.yaml | 7 +++++ 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/vmware-add-ram-size-multiple-of-4-validation-9740bf60d59ce5e2.yaml diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f885d95c4dfb..d02a5a11d5b5 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2711,6 +2711,7 @@ class ComputeManager(manager.Manager): with excutils.save_and_reraise_exception(): self._build_resources_cleanup(instance, network_info) except (exception.UnexpectedTaskStateError, + exception.InstanceUnacceptable, exception.OverQuota, exception.InvalidBDM) as e: self._build_resources_cleanup(instance, network_info) raise exception.BuildAbortException(instance_uuid=instance.uuid, diff --git a/nova/tests/unit/virt/vmwareapi/test_vmops.py b/nova/tests/unit/virt/vmwareapi/test_vmops.py index f84c113758f8..b5318dbbf445 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vmops.py +++ b/nova/tests/unit/virt/vmwareapi/test_vmops.py @@ -166,7 +166,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): "projectid:fake_project\n" "projectname:None\n" "flavor:name:m1.micro\n" - "flavor:memory_mb:6\n" + "flavor:memory_mb:8\n" "flavor:vcpus:28\n" "flavor:ephemeral_gb:8128\n" "flavor:root_gb:496\n" @@ -1138,6 +1138,14 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): mock_attach_cdrom_to_vm.assert_called_once_with( 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.object(vmops.LOG, 'debug') @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): # Validate that the extra specs are parsed correctly flavor = objects.Flavor(name='my-flavor', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2227,7 +2235,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): flavor_extra_specs = {'quota:cpu_limit': 7, 'quota:cpu_reservation': 6} flavor = objects.Flavor(name='my-flavor', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2280,7 +2288,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): 'quota:cpu_reservation': 6, 'hw_video:ram_max_mb': 100} flavor = objects.Flavor(name='my-flavor', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2692,7 +2700,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): def test_get_storage_policy_none(self): flavor = objects.Flavor(name='m1.small', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2706,7 +2714,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): def test_get_storage_policy_extra_specs(self): extra_specs = {'vmware:storage_policy': 'flavor-policy'} flavor = objects.Flavor(name='m1.small', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2781,7 +2789,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): def test_get_instance_metadata(self): flavor = objects.Flavor(id=7, name='m1.small', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, @@ -2796,7 +2804,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): "projectid:fake_project\n" "projectname:None\n" "flavor:name:m1.small\n" - "flavor:memory_mb:6\n" + "flavor:memory_mb:8\n" "flavor:vcpus:28\n" "flavor:ephemeral_gb:8128\n" "flavor:root_gb:496\n" @@ -2913,7 +2921,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase): def test_get_cores_per_socket(self): extra_specs = {'hw:cpu_sockets': 7} flavor = objects.Flavor(name='m1.small', - memory_mb=6, + memory_mb=8, vcpus=28, root_gb=496, ephemeral_gb=8128, diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index 66ad1df9b184..5e2ecfa6c383 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -519,6 +519,10 @@ class VMwareVCDriver(driver.ComputeDriver): # where cpu traits are added. In the vmware world, this is where we # 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, admin_password, allocations, network_info=None, block_device_info=None, power_on=True, accel_info=None): diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index f99290573ab5..7da453bdb165 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -729,6 +729,12 @@ class VMwareVMOps(object): if new_size is not None: 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, admin_password, network_info, block_device_info=None): diff --git a/releasenotes/notes/vmware-add-ram-size-multiple-of-4-validation-9740bf60d59ce5e2.yaml b/releasenotes/notes/vmware-add-ram-size-multiple-of-4-validation-9740bf60d59ce5e2.yaml new file mode 100644 index 000000000000..16bab162bb63 --- /dev/null +++ b/releasenotes/notes/vmware-add-ram-size-multiple-of-4-validation-9740bf60d59ce5e2.yaml @@ -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.