libvirt: Add a default VirtIO-RNG device to guests

tl;dr: We're adding the default VirtIO-RNG device to ensure guests are
       not starved of entropy (and thus not hang) during boot time.

Background
----------

From Nova Git history, commit b94550f419 ("libvirt: configuration
element for a random number generator device") _did_ add a default RNG
device (but with its entropy source to the undesirable '/dev/random').
However, the default RNG device was immediately removed in another
commit (605677c -- "libvirt: remove explicit /dev/random rng default"),
with this rationale:

    libvirt (or rather qemu) will default to /dev/random if no rng device
    path is specified [...]

    It's preferable for us to not duplicate this default to allow for a
    future where libvirt or the hypervisor needs to make more intelligent
    decisions about the default device to use.

The above reasoning doesn't hold up, because:

(a) libvirt does not make "policy" decisions, such as choosing an
    entropy source (or any other such).  Therefore Nova, as a management
    application, should make the decision here.

(b) More importantly, when QEMU exposes a VirtIO-RNG device to the
    guest, that device needs a source of entropy; and QEMU by default
    uses the legacy and problematic `/dev/random` as the source —
    instead of the preferred `/dev/urandom`.  So QEMU's default for
    VirtIO-RNG devices is not sufficient, and Nova should not rely on
    it.  (Discussion[+] on 'qemu-devel' list to consider changing QEMU's
    default.)

                    * * *

In this patch:

  - Make Nova configure a VirtIO-RNG device by default for guests.
    (Which will be using `/dev/urandom` as the default entropy source.)
    This will also work for Windows guests, when using VirtIO-Win
    drivers[*] on the Linux host.

  - The 'hw_rng_model' image metadata property is now rendered
    (temporarily) useless -- as it's not used anywhere outside the
    _add_rng_device() method.  But we don't want to deprecate it yet, as
    we may extend it (see code comment for details); docucment that.

[*] https://docs.pagure.org/docs-fedora/create-windows-vms-using-virtio.html
[+] https://lists.nongnu.org/archive/html/qemu-devel/2018-09/msg02724.html
    -- "[RFC] Virtio RNG: Consider changing the default entropy source to
    /dev/urandom?"

Closes-Bug: #1789868

Change-Id: I28e66c9640c38d23b8c0dbd0b05f5260bfcf6d30
Signed-off-by: Kashyap Chamarthy <kchamart@redhat.com>
This commit is contained in:
Kashyap Chamarthy 2018-09-20 11:16:40 +02:00
parent 093e65c2ca
commit de512f2c02
5 changed files with 145 additions and 87 deletions

View File

@ -480,6 +480,20 @@ class OSType(BaseNovaEnum):
class RNGModel(BaseNovaEnum):
# NOTE(kchamart): Along with "virtio", we may need to extend this (if a
# good reason shows up) to allow two more values for VirtIO
# transitional and non-transitional devices (available since libvirt
# 5.2.0):
#
# - virtio-transitional
# - virtio-nontransitional
#
# This allows one to choose whether you want to have compatibility
# with older guest operating systems. The value you select will in
# turn decide the kind of PCI topology the guest will get.
#
# Details:
# https://libvirt.org/formatdomain.html#elementsVirtioTransitional
VIRTIO = "virtio"
ALL = (VIRTIO,)

View File

@ -359,6 +359,12 @@ class ImageMetaProps(base.NovaObject):
'hw_rescue_device': fields.BlockDeviceTypeField(),
# name of the RNG device type eg virtio
# NOTE(kchamart): Although this is currently not used anymore,
# we should not remove / deprecate it yet, as we are likely to
# extend this field to allow two more values to support "VirtIO
# transitional/non-transitional devices" (refer to the note in
# RNGModel() class in nova/objects/fields.py), and thus expose
# to the user again.
'hw_rng_model': fields.RNGModelField(),
# boolean 'true' or 'false' to enable HPET

View File

@ -2486,7 +2486,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(cfg.os_type, fields.VMMode.HVM)
self.assertEqual(cfg.os_boot_dev, ["hd"])
self.assertIsNone(cfg.os_root)
self.assertEqual(len(cfg.devices), 9)
self.assertEqual(len(cfg.devices), 10)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -2504,6 +2504,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[9],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(len(cfg.metadata), 1)
self.assertIsInstance(cfg.metadata[0],
@ -4533,7 +4535,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(cfg.os_type, fields.VMMode.HVM)
self.assertEqual(cfg.os_boot_dev, ["hd"])
self.assertIsNone(cfg.os_root)
self.assertEqual(len(cfg.devices), 9)
self.assertEqual(len(cfg.devices), 10)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -4551,6 +4553,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[9],
vconfig.LibvirtConfigMemoryBalloon)
def test_get_guest_config_with_root_device_name(self):
@ -5001,7 +5005,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = self._get_guest_config_with_graphics()
self.assertEqual(len(cfg.devices), 6)
self.assertEqual(len(cfg.devices), 7)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5013,6 +5017,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[4],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, 'vnc')
@ -5028,7 +5034,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = self._get_guest_config_with_graphics()
self.assertEqual(len(cfg.devices), 7)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5042,6 +5048,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, "tablet")
@ -5060,7 +5068,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = self._get_guest_config_with_graphics()
self.assertEqual(len(cfg.devices), 7)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5074,6 +5082,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, 'tablet')
@ -5095,7 +5105,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
expect = {"ppc": "vga", "ppc64": "vga",
"ppc64le": "vga", "aarch64": "virtio"}
video_type = expect.get(blockinfo.libvirt_utils.get_arch({}), "qxl")
self.assertEqual(len(cfg.devices), 7)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5109,6 +5119,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].target_name, "com.redhat.spice.0")
@ -5228,7 +5240,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(7, len(cfg.devices))
self.assertEqual(8, len(cfg.devices))
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5242,6 +5254,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("tcp", cfg.devices[2].type)
@ -5262,7 +5276,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(9, len(cfg.devices))
self.assertEqual(10, len(cfg.devices))
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5280,6 +5294,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[9],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("tcp", cfg.devices[2].type)
@ -5320,7 +5336,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta,
disk_info)
self.assertEqual(9, len(cfg.devices), cfg.devices)
self.assertEqual(10, len(cfg.devices), cfg.devices)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5338,6 +5354,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[9],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("tcp", cfg.devices[2].type)
@ -5693,7 +5711,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(len(cfg.devices), 9)
self.assertEqual(len(cfg.devices), 10)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5711,6 +5729,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[9],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, "tablet")
@ -5733,7 +5753,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertEqual(len(cfg.devices), 8)
self.assertEqual(len(cfg.devices), 9)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5747,11 +5767,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestWatchdog)
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestWatchdog)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("none", cfg.devices[6].action)
self.assertEqual("none", cfg.devices[7].action)
def _test_get_guest_usb_tablet(self, vnc_enabled, spice_enabled, os_type,
agent_enabled=False, image_meta=None):
@ -5885,7 +5907,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(8, len(cfg.devices))
self.assertEqual(9, len(cfg.devices))
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5899,11 +5921,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestWatchdog)
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestWatchdog)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("none", cfg.devices[6].action)
self.assertEqual("none", cfg.devices[7].action)
def test_get_guest_config_with_watchdog_overrides_flavor(self):
self.flags(virt_type='kvm', group='libvirt')
@ -5923,7 +5947,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(8, len(cfg.devices))
self.assertEqual(9, len(cfg.devices))
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -5937,11 +5961,12 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestWatchdog)
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestWatchdog)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual("pause", cfg.devices[6].action)
self.assertEqual("pause", cfg.devices[7].action)
def test_get_guest_config_with_video_driver_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
@ -5952,43 +5977,45 @@ class LibvirtConnTestCase(test.NoDBTestCase,
"disk_format": "raw",
"properties": {"hw_video_model": "vmvga"}})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertEqual(len(cfg.devices), 7)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[2],
vconfig.LibvirtConfigGuestSerial)
self.assertIsInstance(cfg.devices[3],
vconfig.LibvirtConfigGuestInput)
self.assertIsInstance(cfg.devices[4],
vconfig.LibvirtConfigGuestGraphics)
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[4].type, "vnc")
self.assertEqual(cfg.devices[5].type, "vmvga")
def test_get_guest_config_with_qga_through_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_qemu_guest_agent": "yes"}})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[2],
vconfig.LibvirtConfigGuestSerial)
self.assertIsInstance(cfg.devices[3],
vconfig.LibvirtConfigGuestInput)
self.assertIsInstance(cfg.devices[4],
vconfig.LibvirtConfigGuestGraphics)
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[4].type, "vnc")
self.assertEqual(cfg.devices[5].type, "vmvga")
def test_get_guest_config_with_qga_through_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_qemu_guest_agent": "yes"}})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertEqual(len(cfg.devices), 9)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -6004,6 +6031,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestChannel)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[8],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, "tablet")
@ -6050,7 +6079,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [],
image_meta, disk_info)
self.assertEqual(len(cfg.devices), 7)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -6064,6 +6093,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[4].type, "spice")
@ -6233,7 +6264,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
instance_ref,
image_meta)
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertEqual(len(cfg.devices), 7)
self.assertEqual(len(cfg.devices), 8)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertIsInstance(cfg.devices[1],
@ -6247,6 +6278,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsInstance(cfg.devices[5],
vconfig.LibvirtConfigGuestVideo)
self.assertIsInstance(cfg.devices[6],
vconfig.LibvirtConfigGuestRng)
self.assertIsInstance(cfg.devices[7],
vconfig.LibvirtConfigMemoryBalloon)
self.assertEqual(cfg.devices[3].type, "tablet")
@ -6258,10 +6291,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
instance_ref.flavor.extra_specs = {'hw_rng:allowed': 'True'}
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_rng_model": "virtio"}})
"disk_format": "raw"})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
@ -6296,9 +6327,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
instance_ref.flavor.extra_specs = {'hw_rng:allowed': 'False'}
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_rng_model": "virtio"}})
"disk_format": "raw"})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
@ -6326,12 +6357,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
instance_ref.flavor.extra_specs = {'hw_rng:allowed': 'True',
'hw_rng:rate_bytes': '1024',
instance_ref.flavor.extra_specs = {'hw_rng:rate_bytes': '1024',
'hw_rng:rate_period': '2'}
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_rng_model": "virtio"}})
"disk_format": "raw"})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
@ -6371,10 +6400,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
instance_ref.flavor.extra_specs = {'hw_rng:allowed': 'True'}
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_rng_model": "virtio"}})
"disk_format": "raw"})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
@ -6413,10 +6440,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
instance_ref.flavor.extra_specs = {'hw_rng:allowed': 'True'}
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_rng_model": "virtio"}})
"disk_format": "raw"})
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
@ -7074,8 +7099,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
_fake_network_info(self),
image_meta, disk_info)
self.assertTrue(mock_path_exists.called)
mock_path_exists.assert_any_call(
libvirt_driver.DEFAULT_UEFI_LOADER_PATH['aarch64'][0])
expected = mock.call(libvirt_driver.
DEFAULT_UEFI_LOADER_PATH['aarch64'][0])
self.assertIn(expected, mock_path_exists.mock_calls)
self.assertEqual(cfg.os_mach_type, "virt")
num_ports = 0
@ -7120,8 +7146,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = self._get_guest_config_with_graphics()
self.assertTrue(mock_path_exists.called)
mock_path_exists.assert_any_call(
libvirt_driver.DEFAULT_UEFI_LOADER_PATH['aarch64'][0])
expected = mock.call(libvirt_driver.
DEFAULT_UEFI_LOADER_PATH['aarch64'][0])
self.assertIn(expected, mock_path_exists.mock_calls)
self.assertEqual(cfg.os_mach_type, "virt")
usbhost_exists = False

View File

@ -5109,21 +5109,23 @@ class LibvirtDriver(driver.ComputeDriver):
guest.add_device(qga)
def _add_rng_device(self, guest, flavor, image_meta):
rng_is_virtio = image_meta.properties.get('hw_rng_model') == 'virtio'
rng_allowed_str = flavor.extra_specs.get('hw_rng:allowed', '')
rng_allowed_str = flavor.extra_specs.get('hw_rng:allowed', 'True')
rng_allowed = strutils.bool_from_string(rng_allowed_str)
if rng_is_virtio and rng_allowed:
rng_device = vconfig.LibvirtConfigGuestRng()
rate_bytes = flavor.extra_specs.get('hw_rng:rate_bytes', 0)
period = flavor.extra_specs.get('hw_rng:rate_period', 0)
if rate_bytes:
rng_device.rate_bytes = int(rate_bytes)
rng_device.rate_period = int(period)
rng_path = CONF.libvirt.rng_dev_path
if (rng_path and not os.path.exists(rng_path)):
raise exception.RngDeviceNotExist(path=rng_path)
rng_device.backend = rng_path
guest.add_device(rng_device)
if not rng_allowed:
return
rng_device = vconfig.LibvirtConfigGuestRng()
rate_bytes = flavor.extra_specs.get('hw_rng:rate_bytes', 0)
period = flavor.extra_specs.get('hw_rng:rate_period', 0)
if rate_bytes:
rng_device.rate_bytes = int(rate_bytes)
rng_device.rate_period = int(period)
rng_path = CONF.libvirt.rng_dev_path
if (rng_path and not os.path.exists(rng_path)):
raise exception.RngDeviceNotExist(path=rng_path)
rng_device.backend = rng_path
guest.add_device(rng_device)
def _add_virtio_serial_controller(self, guest, instance):
virtio_controller = vconfig.LibvirtConfigGuestController()

View File

@ -0,0 +1,9 @@
---
features:
- |
When using the libvirt driver, Nova instances will now get a
VirtIO-RNG (Random Number Generator) device by default. This is to
ensure guests are not starved of entropy during boot time. In case
you want to *disallow* setting an RNG device for some reason, it can
be done by setting the flavor Extra Spec property ``hw_rng:allowed``
to ``False``.