From cf0e519a0e300879cb0e83d1aa02e649d82c0c92 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 7 Oct 2020 08:15:47 -0700 Subject: [PATCH] Allow excluding image type capabilities During the implementation of blueprint request-filter-image-types, I left a FIXME to follow-up and add an ability for an operator to configure compute nodes to not expose image formats that they *can* support, for situations where they may not be desired. Consider a remote compute node which *can* support raw images, but for which you want to require that the user use qcow2 for transfer efficiency. This adds a new compute-level config option which allows excluding image types, which will be filtered out of the traits list in a general way, to avoid having to honor the list in each driver. Change-Id: Iabe6246dba212b1a287a82cc0cf16e2e8c8a24b8 --- nova/conf/compute.py | 21 +++++++++++++++++++ nova/tests/unit/virt/test_virt.py | 14 +++++++++++++ nova/virt/driver.py | 18 ++++++++++++++++ nova/virt/libvirt/driver.py | 5 ----- ...-type-exclusion-list-dac61a747a1140a3.yaml | 9 ++++++++ 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/image-type-exclusion-list-dac61a747a1140a3.yaml diff --git a/nova/conf/compute.py b/nova/conf/compute.py index dbdd051d9fdb..3b288e06e6ea 100644 --- a/nova/conf/compute.py +++ b/nova/conf/compute.py @@ -979,6 +979,27 @@ Additional documentation is available here: https://docs.openstack.org/nova/latest/admin/managing-resource-providers.html +"""), + cfg.ListOpt('image_type_exclude_list', + default=[], + help=""" +A list of image formats that should not be advertised as supported by this +compute node. + +In some situations, it may be desirable to have a compute node +refuse to support an expensive or complex image format. This factors into +the decisions made by the scheduler about which compute node to select when +booted with a given image. + +Possible values: + +* Any glance image ``disk_format`` name (i.e. ``raw``, ``qcow2``, etc) + +Related options: + +* ``[scheduler]query_placement_for_image_type_support`` - enables + filtering computes based on supported image types, which is required + to be enabled for this to take effect. """), ] diff --git a/nova/tests/unit/virt/test_virt.py b/nova/tests/unit/virt/test_virt.py index 6e817d5f1004..eddb6ac925d2 100644 --- a/nova/tests/unit/virt/test_virt.py +++ b/nova/tests/unit/virt/test_virt.py @@ -16,11 +16,13 @@ import io import mock +import os_traits import six from nova import test from nova.virt.disk import api as disk_api from nova.virt import driver +from nova.virt import fake PROC_MOUNTS_CONTENTS = """rootfs / rootfs rw 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 @@ -89,6 +91,18 @@ class TestVirtDriver(test.NoDBTestCase): self.assertTrue(driver.swap_is_usable({'device_name': '/dev/sdb', 'swap_size': 1})) + def test_image_type_exclude_list(self): + fake_driver = fake.FakeDriver(None) + + traits = fake_driver.capabilities_as_traits() + self.assertTrue(traits[os_traits.COMPUTE_IMAGE_TYPE_RAW]) + self.assertFalse(traits[os_traits.COMPUTE_IMAGE_TYPE_VHD]) + + self.flags(image_type_exclude_list='raw', group='compute') + traits = fake_driver.capabilities_as_traits() + self.assertFalse(traits[os_traits.COMPUTE_IMAGE_TYPE_RAW]) + self.assertFalse(traits[os_traits.COMPUTE_IMAGE_TYPE_VHD]) + class FakeMount(object): def __init__(self, image, mount_dir, partition=None, device=None): diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 86db4b8bd07d..12b00a97146f 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -134,6 +134,20 @@ CAPABILITY_TRAITS_MAP = { } +def _check_image_type_exclude_list(capability, supported): + """Enforce the exclusion list on image_type capabilites. + + :param capability: The supports_image_type_foo capability being checked + :param supported: The flag indicating whether the virt driver *can* + support the given image type. + :returns: True if the virt driver *can* support the image type and + if it is not listed in the config to be excluded. + """ + image_type = capability.replace('supports_image_type_', '') + return (supported and + image_type not in CONF.compute.image_type_exclude_list) + + class ComputeDriver(object): """Base class for compute drivers. @@ -1113,6 +1127,10 @@ class ComputeDriver(object): """ traits = {} for capability, supported in self.capabilities.items(): + if capability.startswith('supports_image_type_'): + supported = _check_image_type_exclude_list(capability, + supported) + if capability in CAPABILITY_TRAITS_MAP: traits[CAPABILITY_TRAITS_MAP[capability]] = supported diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index f1d16ce71aa1..529b7f809f99 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -291,11 +291,6 @@ class LibvirtDriver(driver.ComputeDriver): "supports_image_type_aki": True, "supports_image_type_ari": True, "supports_image_type_ami": True, - # FIXME(danms): I can see a future where people might want to - # configure certain compute nodes to not allow giant raw images - # to be booted (like nodes that are across a WAN). Thus, at some - # point we may want to be able to _not_ expose "supports raw" on - # some nodes by policy. Until then, raw is always supported. "supports_image_type_raw": True, "supports_image_type_iso": True, # NOTE(danms): Certain backends do not work with complex image diff --git a/releasenotes/notes/image-type-exclusion-list-dac61a747a1140a3.yaml b/releasenotes/notes/image-type-exclusion-list-dac61a747a1140a3.yaml new file mode 100644 index 000000000000..a0cbbae12792 --- /dev/null +++ b/releasenotes/notes/image-type-exclusion-list-dac61a747a1140a3.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + A ``[compute]image_type_exclusion_list`` configuration option was + added to remove supported image types from being advertised by a + compute node as supported. This is to be used in conjunction with + ``[scheduler]query_placement_for_image_type_support`` to prevent + instances from booting on a compute node with a given image type, + even if the underlying hypervisor supports it.