Fix broken <range-in> in root device hints

Closes-Bug: #2117514
Change-Id: I3747230c788def8a484b7c65ab60b998b3661ae9
Signed-off-by: Dmitry Tantsur <dtantsur@protonmail.com>
Signed-off-by: Riccardo Pittau <elfosardo@gmail.com>
This commit is contained in:
Dmitry Tantsur
2025-07-22 19:23:23 +02:00
committed by Riccardo Pittau
parent 77bd8c988d
commit 322a10dcfb
4 changed files with 32 additions and 2 deletions

View File

@@ -15,7 +15,11 @@ which disk it should pick for the deployment. The list of supported hints is:
provided to the operating system which do not match or align to physical
disks in a system.
* size (INT): size of the device in GiB
* size (INT or range): size of the device in GiB or range boundaries in GiB
size accepts a single int value representing the size of the device in
GiB, or a range of two values representing the lower and higher acceptable
sizes in GiB for the device using the special operator <range-in>, e.g.
size: <range-in> ( 10 100 )
.. note::
A node's 'local_gb' property is often set to a value 1 GiB less than the
@@ -103,6 +107,8 @@ and ``s==`` (for string values). The supported operators are:
* ``<all-in>`` all elements contained in collection
* ``<or>`` find one of these
* ``<range-in>`` range boundaries in GiB, boundary condition could be
inclusive \'[\' or exclusive \'(\'.
Examples are:

View File

@@ -953,7 +953,12 @@ def parse_root_device_hints(root_device):
for name, expression in root_device.items():
hint_type = VALID_ROOT_DEVICE_HINTS[name]
if hint_type is str:
hint_info = _extract_hint_operator_and_values(expression,
name)
operator = hint_info['op']
if name == 'size' and operator == '<range-in>':
pass
elif hint_type is str:
if not isinstance(expression, str):
raise ValueError(
_('Root device hint "%(name)s" is not a string value. '
@@ -1049,6 +1054,8 @@ def find_devices_by_hints(devices, root_device_hints):
# Since we don't support units yet we expect the size
# in GiB for now
device_value = device_value / units.Gi
if hint_value.startswith('<range-in>'):
device_value = str(device_value)
LOG.debug('Trying to match the device hint "%(hint)s" '
'with a value of "%(hint_value)s" against the same '

View File

@@ -910,6 +910,12 @@ class ParseRootDeviceTestCase(base.TestCase):
self.assertEqual(
expected, utils._extract_hint_operator_and_values(123, 'size'))
def test_extract_hint_operator_and_values_range_in(self):
expected = {'op': '<range-in>', 'values': ['( 100 200 )']}
self.assertEqual(
expected, utils._extract_hint_operator_and_values(
'<range-in> ( 100 200 )', 'size'))
def test__append_operator_to_hints(self):
root_device = {'serial': 'foo', 'size': 12345,
'model': 'foo model', 'rotational': True}
@@ -978,6 +984,11 @@ class MatchRootDeviceTestCase(base.TestCase):
dev = utils.match_root_device_hints(self.devices, root_device_hints)
self.assertEqual('/dev/sdb', dev['name'])
def test_match_root_device_hints_range_in(self):
root_device_hints = {'size': '<range-in> ( 10 100 )'}
dev = utils.match_root_device_hints(self.devices, root_device_hints)
self.assertEqual('/dev/sda', dev['name'])
def test_match_root_device_hints_rotational(self):
root_device_hints = {'rotational': False}
dev = utils.match_root_device_hints(self.devices, root_device_hints)

View File

@@ -0,0 +1,6 @@
---
fixes:
- |
Fixes an issue with <range in> operator in root device hint. Now it's
possible to use the range operator correctly, specifying a two values
range that includes the size of the root device in GiB.