vmware:add support for the hw_video_ram image property

Added create of a video card config spec and validation check
if the image meta video ram("hw_video_ram") is bigger than the
maximum allowed "hw_video:ram_max_mb" from the flavor.

Change-Id: I944d7e9235790cb2a4a21318c029d51012d157b0
This commit is contained in:
mmidolesov 2018-04-25 05:44:51 -07:00
parent 3b77a1825c
commit 38aa83b7fc
5 changed files with 143 additions and 2 deletions

View File

@ -300,11 +300,15 @@ Hardware video RAM
image. Used in conjunction with the ``hw_video_ram`` image property.
``hw_video_ram`` must be less than or equal to ``hw_video:ram_max_mb``.
This is currently only supported by the libvirt driver.
This is currently supported by the libvirt and the vmware drivers.
See https://libvirt.org/formatdomain.html#elementsVideo for more information
on how this is used to set the ``vram`` attribute with the libvirt driver.
See https://pubs.vmware.com/vi-sdk/visdk250/ReferenceGuide/vim.vm.device.VirtualVideoCard.html
for more information on how this is used to set the ``videoRamSizeInKB`` attribute with
the vmware driver.
Watchdog behavior
For the libvirt driver, you can enable and set the behavior of a virtual
hardware watchdog device for each flavor. Watchdog devices keep an eye on the

View File

@ -2192,6 +2192,104 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
flavor_extra_specs = self._vmops._get_extra_specs(flavor, None)
self._validate_extra_specs(expected, flavor_extra_specs)
"""
The test covers the negative failure scenario, where `hw_video_ram`,
coming from the image is bigger than the maximum allowed video ram from
the flavor.
"""
def test_video_ram(self):
meta_dict = {'id': self._image_id, 'properties': {'hw_video_ram': 120}}
image_meta, flavor = self._get_image_and_flavor_for_test_video(
meta_dict)
self.assertRaises(exception.RequestedVRamTooHigh,
self._vmops._get_extra_specs,
flavor,
image_meta)
"""
Testing VM provisioning result in the case where `hw_video_ram`,
coming from the image is not specified. This is a success scenario,
in the case where `hw_video_ram` property is not set.
"""
def test_video_ram_if_none(self):
meta_dict = {'id': self._image_id, 'properties': {}}
image_meta, flavor = self._get_image_and_flavor_for_test_video(
meta_dict)
extra_specs = self._vmops._get_extra_specs(flavor, image_meta)
self.assertIsNone(extra_specs.hw_video_ram)
"""
Testing VM provisioning result in the case where `hw_video:ram_max_mb`,
coming from the flavor is not specified. This is a success scenario,
in the case where `hw_video_ram` property is not set.
"""
def test_max_video_ram_none(self):
meta_dict = {'id': self._image_id, 'properties': {'hw_video_ram': 120}}
image_meta = objects.ImageMeta.from_dict(meta_dict)
flavor_extra_specs = {'quota:cpu_limit': 7,
'quota:cpu_reservation': 6}
flavor = objects.Flavor(name='my-flavor',
memory_mb=6,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
swap=33550336,
extra_specs=flavor_extra_specs)
self.assertRaises(exception.RequestedVRamTooHigh,
self._vmops._get_extra_specs,
flavor,
image_meta)
"""
Testing VM provisioning result in the case where `hw_video_ram`,
coming from the image is less than the maximum allowed video ram from
the flavor. This is a success scenario, in the case where `hw_video_ram`
property is set in the extra spec.
"""
def test_success_video_ram(self):
expected_video_ram = 90
meta_dict = {'id': self._image_id, 'properties': {
'hw_video_ram': expected_video_ram}}
image_meta, flavor = self._get_image_and_flavor_for_test_video(
meta_dict)
extra_specs = self._vmops._get_extra_specs(flavor, image_meta)
self.assertEqual(self._calculate_expected_fake_video_ram(
expected_video_ram), extra_specs.hw_video_ram)
"""
Testing VM provisioning result in the case where `hw_video_ram`,
coming from the image is equal to 0. This is a success scenario, in the
case where `hw_video_ram` property is not set in the extra spec.
"""
def test_zero_video_ram(self):
meta_dict = {'id': self._image_id, 'properties': {'hw_video_ram': 0}}
image_meta, flavor = self._get_image_and_flavor_for_test_video(
meta_dict)
extra_specs = self._vmops._get_extra_specs(flavor, image_meta)
self.assertIsNone(extra_specs.hw_video_ram)
def _calculate_expected_fake_video_ram(self, amount):
return amount * units.Mi / units.Ki
def _get_image_and_flavor_for_test_video(self, meta_dict):
image_meta = objects.ImageMeta.from_dict(meta_dict)
flavor_extra_specs = {'quota:cpu_limit': 7,
'quota:cpu_reservation': 6,
'hw_video:ram_max_mb': 100}
flavor = objects.Flavor(name='my-flavor',
memory_mb=6,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
swap=33550336,
extra_specs=flavor_extra_specs)
return image_meta, flavor
def test_extra_specs_cpu_limit(self):
flavor_extra_specs = {'quota:cpu_limit': 7}
cpu_limits = vm_util.Limits(limit=7)

View File

@ -92,7 +92,7 @@ class ExtraSpecs(object):
def __init__(self, cpu_limits=None, hw_version=None,
storage_policy=None, cores_per_socket=None,
memory_limits=None, disk_io_limits=None,
vif_limits=None, firmware=None):
vif_limits=None, firmware=None, hw_video_ram=None):
"""ExtraSpecs object holds extra_specs for the instance."""
self.cpu_limits = cpu_limits or Limits()
self.memory_limits = memory_limits or Limits()
@ -102,6 +102,7 @@ class ExtraSpecs(object):
self.storage_policy = storage_policy
self.cores_per_socket = cores_per_socket
self.firmware = firmware
self.hw_video_ram = hw_video_ram
def vm_refs_cache_reset():
@ -257,6 +258,11 @@ def get_vm_create_spec(client_factory, instance, data_store_name,
if serial_port_spec:
devices.append(serial_port_spec)
virtual_device_config_spec = create_video_card_spec(client_factory,
extra_specs)
if virtual_device_config_spec:
devices.append(virtual_device_config_spec)
config_spec.deviceChange = devices
# add vm-uuid and iface-id.x values for Neutron
@ -298,6 +304,18 @@ def get_vm_create_spec(client_factory, instance, data_store_name,
return config_spec
def create_video_card_spec(client_factory, extra_specs):
if extra_specs.hw_video_ram:
video_card = client_factory.create('ns0:VirtualMachineVideoCard')
video_card.videoRamSizeInKB = extra_specs.hw_video_ram
video_card.key = -1
virtual_device_config_spec = client_factory.create(
'ns0:VirtualDeviceConfigSpec')
virtual_device_config_spec.operation = "add"
virtual_device_config_spec.device = video_card
return virtual_device_config_spec
def create_serial_port_spec(client_factory):
"""Creates config spec for serial port."""
if not CONF.vmware.serial_port_service_uri:

View File

@ -327,6 +327,16 @@ class VMwareVMOps(object):
extra_specs.firmware = 'bios'
hw_version = flavor.extra_specs.get('vmware:hw_version')
extra_specs.hw_version = hw_version
video_ram = image_meta.properties.get('hw_video_ram', 0)
max_vram = int(flavor.extra_specs.get('hw_video:ram_max_mb', 0))
if video_ram > max_vram:
raise exception.RequestedVRamTooHigh(req_vram=video_ram,
max_vram=max_vram)
if video_ram and max_vram:
extra_specs.hw_video_ram = video_ram * units.Mi / units.Ki
if CONF.vmware.pbm_enabled:
storage_policy = flavor.extra_specs.get('vmware:storage_policy',
CONF.vmware.pbm_default_policy)

View File

@ -0,0 +1,11 @@
---
features:
- |
For the VMware vCenter driver, added support for the configured video ram ``hw_video_ram`` from the image,
which will be checked against the maximum allowed video ram ``hw_video:ram_max_mb``
from the flavor.
If the selected video ram from the image is less than or equal to the maximum allowed ram,
the ``videoRamSizeInKB`` will be set.
If the selected ram is more than the maximum allowed one, then server creation will fail for the given
image and flavor.
If the maximum allowed video ram is not set in the flavor we do not set ``videoRamSizeInKB`` in the VM.