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.