Merge "Add transform_image_metadata request filter"
This commit is contained in:
commit
9d212738be
@ -198,7 +198,17 @@ flavor/image. If an aggregate is configured with a property with key
|
||||
and/or image metadata must also contain ``trait:$TRAIT_NAME=required`` to be
|
||||
eligible to be scheduled to hosts in that aggregate. More technical details
|
||||
at https://docs.openstack.org/nova/latest/reference/isolate-aggregates.html
|
||||
""")
|
||||
"""),
|
||||
cfg.BoolOpt("image_metadata_prefilter",
|
||||
default=False,
|
||||
help="""
|
||||
This setting causes the scheduler to transform well known image metadata
|
||||
properties into placement required traits to filter host based on image
|
||||
metadata. This feature requires host support and is currently supported by the
|
||||
following compute drivers:
|
||||
|
||||
- ``libvirt.LibvirtDriver`` (since Ussuri (21.0.0))
|
||||
"""),
|
||||
]
|
||||
|
||||
filter_scheduler_group = cfg.OptGroup(name="filter_scheduler",
|
||||
|
@ -193,6 +193,47 @@ def require_image_type_support(ctxt, request_spec):
|
||||
return True
|
||||
|
||||
|
||||
@trace_request_filter
|
||||
def transform_image_metadata(ctxt, request_spec):
|
||||
"""Transform image metadata to required traits.
|
||||
|
||||
This will modify the request_spec to request hosts that support
|
||||
virtualisation capabilities based on the image metadata properties.
|
||||
"""
|
||||
if not CONF.scheduler.image_metadata_prefilter:
|
||||
return False
|
||||
|
||||
prefix_map = {
|
||||
'hw_cdrom_bus': 'COMPUTE_STORAGE_BUS',
|
||||
'hw_disk_bus': 'COMPUTE_STORAGE_BUS',
|
||||
'hw_video_model': 'COMPUTE_GRAPHICS_MODEL',
|
||||
'hw_vif_model': 'COMPUTE_NET_VIF_MODEL',
|
||||
}
|
||||
|
||||
trait_names = []
|
||||
|
||||
for key, prefix in prefix_map.items():
|
||||
if key in request_spec.image.properties:
|
||||
value = request_spec.image.properties.get(key).replace(
|
||||
'-', '_').upper()
|
||||
trait_name = f'{prefix}_{value}'
|
||||
if not hasattr(os_traits, trait_name):
|
||||
LOG.error(('Computed trait name %r is not valid; '
|
||||
'is os-traits up to date?'), trait_name)
|
||||
return False
|
||||
|
||||
trait_names.append(trait_name)
|
||||
|
||||
for trait_name in trait_names:
|
||||
LOG.debug(
|
||||
'transform_image_metadata request filter added required '
|
||||
'trait %s', trait_name
|
||||
)
|
||||
request_spec.root_required.add(trait_name)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@trace_request_filter
|
||||
def compute_status_filter(ctxt, request_spec):
|
||||
"""Pre-filter compute node resource providers using COMPUTE_STATUS_DISABLED
|
||||
@ -215,6 +256,7 @@ ALL_REQUEST_FILTERS = [
|
||||
require_image_type_support,
|
||||
compute_status_filter,
|
||||
isolate_aggregates,
|
||||
transform_image_metadata,
|
||||
]
|
||||
|
||||
|
||||
|
@ -12,11 +12,13 @@
|
||||
|
||||
import mock
|
||||
import os_traits as ot
|
||||
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from nova import context as nova_context
|
||||
from nova import exception
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.scheduler import request_filter
|
||||
from nova import test
|
||||
@ -400,3 +402,36 @@ class TestRequestFilter(test.NoDBTestCase):
|
||||
log_lines = [c[0][0] for c in mock_log.debug.call_args_list]
|
||||
self.assertIn('added forbidden trait', log_lines[0])
|
||||
self.assertIn('took %.1f seconds', log_lines[1])
|
||||
|
||||
@mock.patch.object(request_filter, 'LOG', new=mock.Mock())
|
||||
def test_transform_image_metadata(self):
|
||||
self.flags(image_metadata_prefilter=True, group='scheduler')
|
||||
properties = objects.ImageMetaProps(
|
||||
hw_disk_bus=objects.fields.DiskBus.SATA,
|
||||
hw_cdrom_bus=objects.fields.DiskBus.IDE,
|
||||
hw_video_model=objects.fields.VideoModel.QXL,
|
||||
hw_vif_model=network_model.VIF_MODEL_VIRTIO
|
||||
)
|
||||
reqspec = objects.RequestSpec(
|
||||
image=objects.ImageMeta(properties=properties),
|
||||
flavor=objects.Flavor(extra_specs={}),
|
||||
)
|
||||
self.assertTrue(
|
||||
request_filter.transform_image_metadata(None, reqspec)
|
||||
)
|
||||
expected = {
|
||||
'COMPUTE_GRAPHICS_MODEL_QXL',
|
||||
'COMPUTE_NET_VIF_MODEL_VIRTIO',
|
||||
'COMPUTE_STORAGE_BUS_IDE',
|
||||
'COMPUTE_STORAGE_BUS_SATA',
|
||||
}
|
||||
self.assertEqual(expected, reqspec.root_required)
|
||||
|
||||
def test_transform_image_metadata__disabled(self):
|
||||
self.flags(image_metadata_prefilter=False, group='scheduler')
|
||||
reqspec = objects.RequestSpec(flavor=objects.Flavor(extra_specs={}))
|
||||
# Assert that we completely skip the filter if disabled
|
||||
self.assertFalse(
|
||||
request_filter.transform_image_metadata(self.context, reqspec)
|
||||
)
|
||||
self.assertEqual(set(), reqspec.root_required)
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A new image metadata prefilter has been added to allow translation of
|
||||
hypervisor-specific device model requests to standard traits. When this
|
||||
feature is enabled, nova is able to utilize placement to select hosts that
|
||||
are capable of emulating the requested devices, avoiding hosts that
|
||||
could not support the request. This feature is currently supported by the
|
||||
libvirt driver and can be enabled by configuring the
|
||||
``[scheduler]/image_metadata_prefilter`` to ``True`` in the controller
|
||||
``nova.conf``.
|
Loading…
Reference in New Issue
Block a user