Merge "Per-Property ImageMetaPropsWeigher"
This commit is contained in:
@@ -1086,6 +1086,24 @@ A positive value will favor hosts with the same image properties (packing
|
||||
strategy) while a negative value will follow a spread strategy that will
|
||||
favor hosts not already having instances with those image properties.
|
||||
|
||||
You can also use
|
||||
:oslo.config:option:`filter_scheduler.image_props_weight_setting` config option
|
||||
for defining the exact properties you would like to weigh. For example, if you
|
||||
configure ``os_distro`` to 2 and ``hw_machine_type`` to 0, then the latter
|
||||
property won't be weighed while the former will count twice. Say you configure
|
||||
``os_distro=10,os_secure_boot=1,os_require_quiesce=0``, then when requesting
|
||||
an instance with an image using those properties, then, for each of the
|
||||
instances already running on the host having an image using at least one of
|
||||
those properties, a match of the same ``os_distro`` value (eg. ``windows`` or
|
||||
``linux``) would count 10 times more than a match of the same
|
||||
``os_secure_boot`` value (eg. ``true`` or ``false``), while any matches about
|
||||
the same ``os_require_quiesce`` value wouldn't count.
|
||||
If you define :oslo.config:option:`filter_scheduler.image_props_weight_setting`
|
||||
then any property from the image used for booting wouldn't be counted if not
|
||||
provided in the option value.
|
||||
The resulted host weight would then be multiplied by the value of
|
||||
:oslo.config:option:`filter_scheduler.image_props_weight_multiplier`.
|
||||
|
||||
Utilization-aware scheduling
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -589,6 +589,53 @@ Example:
|
||||
Related options:
|
||||
|
||||
* ``[filter_scheduler] weight_classes``
|
||||
"""),
|
||||
cfg.ListOpt("image_props_weight_setting",
|
||||
default=[],
|
||||
help="""
|
||||
Mapping of image properties to weight modifier.
|
||||
|
||||
This setting specifies the properties to be weighed and the relative ratios for
|
||||
each property. This should be a list of key/value pairs, consisting of a series
|
||||
of one or more 'name=ratio' pairs, separated by commas, where ``name`` is the
|
||||
name of the property to be weighed, and ``ratio`` is the relative weight for
|
||||
that metric.
|
||||
|
||||
Note that if the ratio is set to 0, the property value is ignored, and instead
|
||||
the weight will be set to the value of the
|
||||
``[filter_scheduler] image_props_weight_multiplier`` option.
|
||||
|
||||
As an example, let's consider the case where this option is set to:
|
||||
|
||||
``os_distro=1, hw_machine_type=-1``
|
||||
|
||||
If an instance would boot with an image having ``os_distro=windows`` and
|
||||
``hw_machine_type=q35``, the final host weight will be:
|
||||
|
||||
``(nb_inst(``os_distro=windows``) * 1.0) +
|
||||
(nb_inst(``hw_machine_type=q35``) * -1)``
|
||||
|
||||
where nb_inst(``prop=value``) would give me the number of instances having
|
||||
an image where ``prop`` is set to ``value`` (eg. the number of instances
|
||||
running with ``os_distro=windows``)
|
||||
|
||||
Possible values:
|
||||
|
||||
* A list of zero or more key/value pairs separated by commas, where the key is
|
||||
a string representing the name of a property and the value is a numeric
|
||||
weight for that property. If any value is set to 0, the number of instances
|
||||
match is ignored for that specific property key.
|
||||
If no key/value pairs are provided, then the weigher will compare all the
|
||||
instance's images with the requested image properties, all of them weighed
|
||||
evenly.
|
||||
|
||||
|
||||
The overall host weight will be multiplied by the value of the
|
||||
``[filter_scheduler] image_props_weight_multiplier`` option.
|
||||
|
||||
Related options:
|
||||
|
||||
* ``[filter_scheduler] image_props_weight_multiplier``
|
||||
"""),
|
||||
cfg.FloatOpt("pci_weight_multiplier",
|
||||
default=1.0,
|
||||
|
||||
@@ -30,6 +30,14 @@ CONF = nova.conf.CONF
|
||||
|
||||
|
||||
class ImagePropertiesWeigher(weights.BaseHostWeigher):
|
||||
def __init__(self):
|
||||
self._parse_setting()
|
||||
|
||||
def _parse_setting(self):
|
||||
self.setting = dict(utils.parse_options(
|
||||
CONF.filter_scheduler.image_props_weight_setting,
|
||||
sep='=', converter=float,
|
||||
name="filter_scheduler.image_props_weight_setting"))
|
||||
|
||||
def weight_multiplier(self, host_state):
|
||||
"""Override the weight multiplier."""
|
||||
@@ -81,6 +89,13 @@ class ImagePropertiesWeigher(weights.BaseHostWeigher):
|
||||
|
||||
common_props = requested_props & set(existing_props)
|
||||
|
||||
for prop in common_props:
|
||||
weight += existing_props.count(prop)
|
||||
for (prop, value) in common_props:
|
||||
if self.setting:
|
||||
# Calculate the weigh for each property by what was set
|
||||
# If it wasn't defined, then don't weigh this property.
|
||||
weight += self.setting.get(
|
||||
prop, 0.0) * existing_props.count((prop, value))
|
||||
else:
|
||||
# By default, all properties are weighed evenly.
|
||||
weight += existing_props.count((prop, value))
|
||||
return weight
|
||||
|
||||
@@ -152,3 +152,45 @@ class ImagePropertiesWeigherTestCase(test.NoDBTestCase):
|
||||
self.assertEqual('host3', weights[0].obj.host)
|
||||
mock_fm.assert_has_calls([mock.call(), mock.call(),
|
||||
mock.call(), mock.call()])
|
||||
|
||||
@mock.patch('nova.objects.InstanceList.fill_metadata')
|
||||
def test_multiplier_per_property(self, mock_fm):
|
||||
self.flags(image_props_weight_multiplier=1.0, group='filter_scheduler')
|
||||
hostinfo_list = self._get_all_hosts()
|
||||
|
||||
# For now, don't exclude any property check and boot with an image
|
||||
# using both hw_machine_type and os_distro properties.
|
||||
weights = self.weight_handler.get_weighed_objects(
|
||||
self.weighers, hostinfo_list,
|
||||
weighing_properties=objects.RequestSpec(image=PROP_LIN_PC))
|
||||
# host3 is preferred as it has both of the correct properties with
|
||||
# the right values.
|
||||
# host2 and host4 only support one of each property.
|
||||
expected_weights = [{'weight': 1.0, 'host': 'host3'},
|
||||
{'weight': (1 / 3), 'host': 'host2'},
|
||||
{'weight': (1 / 3), 'host': 'host4'},
|
||||
{'weight': 0.0, 'host': 'host1'}]
|
||||
self.assertEqual(expected_weights, [weigh.to_dict()
|
||||
for weigh in weights])
|
||||
self.assertEqual('host3', weights[0].obj.host)
|
||||
|
||||
# Now, let's exclude hw_machine_type property to be weighed.
|
||||
self.flags(image_props_weight_setting=['os_distro=1',
|
||||
'hw_machine_type=0'],
|
||||
group='filter_scheduler')
|
||||
# Force a refresh of the settings since we updated them
|
||||
self.weighers[0]._parse_setting()
|
||||
weights = self.weight_handler.get_weighed_objects(
|
||||
self.weighers, hostinfo_list,
|
||||
weighing_properties=objects.RequestSpec(image=PROP_LIN_PC))
|
||||
# host3 and host4 have instances with linux distro but we favor
|
||||
# host3 given he has more instances having the same requested property
|
||||
expected_weights = [{'weight': 1.0, 'host': 'host3'},
|
||||
{'weight': 0.5, 'host': 'host4'},
|
||||
{'weight': 0.0, 'host': 'host1'},
|
||||
{'weight': 0.0, 'host': 'host2'}]
|
||||
self.assertEqual(expected_weights, [weigh.to_dict()
|
||||
for weigh in weights])
|
||||
self.assertEqual('host3', weights[0].obj.host)
|
||||
mock_fm.assert_has_calls([mock.call(), mock.call(),
|
||||
mock.call(), mock.call()])
|
||||
|
||||
@@ -11,4 +11,8 @@ features:
|
||||
hosts, modify `image_props_weight_multiplier` to a positive value. If you
|
||||
want to spread instances with the same properties around all hosts, then
|
||||
please modify `image_props_weight_multiplier` to a negative value.
|
||||
|
||||
Another configuration option
|
||||
`[filter_scheduler]/image_props_weight_setting` allows you to define
|
||||
fine-grained weights for each of the properties you actually would like to
|
||||
weigh (eg. `os_distro`). Please refer to the documentation for more details
|
||||
about how to use this configuration option.
|
||||
|
||||
Reference in New Issue
Block a user