diff --git a/doc/source/install/include/root-device-hints.inc b/doc/source/install/include/root-device-hints.inc index 89c2e770ec..9aafa16dd5 100644 --- a/doc/source/install/include/root-device-hints.inc +++ b/doc/source/install/include/root-device-hints.inc @@ -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 , e.g. + size: ( 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 elements contained in collection * ```` find one of these + * ```` range boundaries in GiB, boundary condition could be + inclusive \'[\' or exclusive \'(\'. Examples are: diff --git a/ironic/common/utils.py b/ironic/common/utils.py index b126668558..32fab032a4 100644 --- a/ironic/common/utils.py +++ b/ironic/common/utils.py @@ -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 == '': + 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(''): + 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 ' diff --git a/ironic/tests/unit/common/test_utils.py b/ironic/tests/unit/common/test_utils.py index 2da8f05af7..a1ee3a3d72 100644 --- a/ironic/tests/unit/common/test_utils.py +++ b/ironic/tests/unit/common/test_utils.py @@ -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': '', 'values': ['( 100 200 )']} + self.assertEqual( + expected, utils._extract_hint_operator_and_values( + ' ( 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': ' ( 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) diff --git a/releasenotes/notes/fix-hint-range-in-1056204234c24661.yaml b/releasenotes/notes/fix-hint-range-in-1056204234c24661.yaml new file mode 100644 index 0000000000..fef16f452d --- /dev/null +++ b/releasenotes/notes/fix-hint-range-in-1056204234c24661.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes an issue with 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.