Replace parse_root_device_hints with the ironic-lib version one
This patch is replacing the parse_root_device_hints() method from deploy_utils.py with the ironic-lib version. The parse_root_device_hints() method is only being used to verify the syntax of the root device hints, finding/matching a disk with the hints is performed by IPA. The ironic-lib version also does add support for using operators such as (>=, >, <, etc...) to finding a suitable disk device. Closes-Bug: #1561137 Depends-On: Id93dd0360137df600f5a656348279e56c6b84bf9 Change-Id: I4516d9f1f1733be26ae603b70c1e59ccf19e0448
This commit is contained in:
parent
652a4b40d4
commit
2383d8d014
@ -13,6 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from ironic_lib import metrics_utils
|
from ironic_lib import metrics_utils
|
||||||
|
from ironic_lib import utils as il_utils
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import units
|
from oslo_utils import units
|
||||||
@ -394,7 +395,14 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
|
|||||||
|
|
||||||
check_image_size(task, image_source)
|
check_image_size(task, image_source)
|
||||||
# Validate the root device hints
|
# Validate the root device hints
|
||||||
deploy_utils.parse_root_device_hints(node)
|
try:
|
||||||
|
root_device = node.properties.get('root_device')
|
||||||
|
il_utils.parse_root_device_hints(root_device)
|
||||||
|
except ValueError as e:
|
||||||
|
raise exception.InvalidParameterValue(
|
||||||
|
_('Failed to validate the root device hints for node '
|
||||||
|
'%(node)s. Error: %(error)s') % {'node': node.uuid,
|
||||||
|
'error': e})
|
||||||
|
|
||||||
# Validate node capabilities
|
# Validate node capabilities
|
||||||
deploy_utils.validate_capabilities(node)
|
deploy_utils.validate_capabilities(node)
|
||||||
|
@ -26,7 +26,6 @@ from oslo_serialization import jsonutils
|
|||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
import six
|
import six
|
||||||
from six.moves.urllib import parse
|
|
||||||
|
|
||||||
from ironic.common import dhcp_factory
|
from ironic.common import dhcp_factory
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
@ -691,60 +690,6 @@ def try_set_boot_device(task, device, persistent=True):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def parse_root_device_hints(node):
|
|
||||||
"""Parse the root_device property of a node.
|
|
||||||
|
|
||||||
Parse the root_device property of a node and make it a flat string
|
|
||||||
to be passed via the PXE config.
|
|
||||||
|
|
||||||
:param node: a single Node.
|
|
||||||
:returns: A flat string with the following format
|
|
||||||
opt1=value1,opt2=value2. Or None if the
|
|
||||||
Node contains no hints.
|
|
||||||
:raises: InvalidParameterValue, if some information is invalid.
|
|
||||||
|
|
||||||
"""
|
|
||||||
root_device = node.properties.get('root_device')
|
|
||||||
if not root_device:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Find invalid hints for logging
|
|
||||||
invalid_hints = set(root_device) - VALID_ROOT_DEVICE_HINTS
|
|
||||||
if invalid_hints:
|
|
||||||
raise exception.InvalidParameterValue(
|
|
||||||
_('The hints "%(invalid_hints)s" are invalid. '
|
|
||||||
'Valid hints are: "%(valid_hints)s"') %
|
|
||||||
{'invalid_hints': ', '.join(invalid_hints),
|
|
||||||
'valid_hints': ', '.join(VALID_ROOT_DEVICE_HINTS)})
|
|
||||||
|
|
||||||
if 'size' in root_device:
|
|
||||||
try:
|
|
||||||
int(root_device['size'])
|
|
||||||
except ValueError:
|
|
||||||
raise exception.InvalidParameterValue(
|
|
||||||
_('Root device hint "size" is not an integer value.'))
|
|
||||||
|
|
||||||
if 'rotational' in root_device:
|
|
||||||
try:
|
|
||||||
strutils.bool_from_string(root_device['rotational'], strict=True)
|
|
||||||
except ValueError:
|
|
||||||
raise exception.InvalidParameterValue(
|
|
||||||
_('Root device hint "rotational" is not a boolean value.'))
|
|
||||||
|
|
||||||
hints = []
|
|
||||||
for key, value in sorted(root_device.items()):
|
|
||||||
# NOTE(lucasagomes): We can't have spaces in the PXE config
|
|
||||||
# file, so we are going to url/percent encode the value here
|
|
||||||
# and decode on the other end.
|
|
||||||
if isinstance(value, six.string_types):
|
|
||||||
value = value.strip()
|
|
||||||
value = parse.quote(value)
|
|
||||||
|
|
||||||
hints.append("%s=%s" % (key, value))
|
|
||||||
|
|
||||||
return ','.join(hints)
|
|
||||||
|
|
||||||
|
|
||||||
def is_secure_boot_requested(node):
|
def is_secure_boot_requested(node):
|
||||||
"""Returns True if secure_boot is requested for deploy.
|
"""Returns True if secure_boot is requested for deploy.
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import os
|
|||||||
|
|
||||||
from ironic_lib import disk_utils
|
from ironic_lib import disk_utils
|
||||||
from ironic_lib import metrics_utils
|
from ironic_lib import metrics_utils
|
||||||
from ironic_lib import utils as ironic_utils
|
from ironic_lib import utils as il_utils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
from six.moves.urllib import parse
|
from six.moves.urllib import parse
|
||||||
@ -134,7 +134,7 @@ def destroy_images(node_uuid):
|
|||||||
|
|
||||||
:param node_uuid: the uuid of the ironic node.
|
:param node_uuid: the uuid of the ironic node.
|
||||||
"""
|
"""
|
||||||
ironic_utils.unlink_without_raise(_get_image_file_path(node_uuid))
|
il_utils.unlink_without_raise(_get_image_file_path(node_uuid))
|
||||||
utils.rmtree_without_raise(_get_image_dir_path(node_uuid))
|
utils.rmtree_without_raise(_get_image_dir_path(node_uuid))
|
||||||
InstanceImageCache().clean_up()
|
InstanceImageCache().clean_up()
|
||||||
|
|
||||||
@ -353,7 +353,14 @@ def validate(task):
|
|||||||
# TODO(lucasagomes): Validate the format of the URL
|
# TODO(lucasagomes): Validate the format of the URL
|
||||||
deploy_utils.get_ironic_api_url()
|
deploy_utils.get_ironic_api_url()
|
||||||
# Validate the root device hints
|
# Validate the root device hints
|
||||||
deploy_utils.parse_root_device_hints(task.node)
|
try:
|
||||||
|
root_device = task.node.properties.get('root_device')
|
||||||
|
il_utils.parse_root_device_hints(root_device)
|
||||||
|
except ValueError as e:
|
||||||
|
raise exception.InvalidParameterValue(
|
||||||
|
_('Failed to validate the root device hints for node '
|
||||||
|
'%(node)s. Error: %(error)s') % {'node': task.node.uuid,
|
||||||
|
'error': e})
|
||||||
deploy_utils.parse_instance_info(task.node)
|
deploy_utils.parse_instance_info(task.node)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1383,45 +1383,6 @@ class OtherFunctionTestCase(db_base.DbTestCase):
|
|||||||
actual = utils.get_dev('1.2.3.4', 5678, 'iqn.fake', 9)
|
actual = utils.get_dev('1.2.3.4', 5678, 'iqn.fake', 9)
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_parse_root_device_hints(self):
|
|
||||||
self.node.properties['root_device'] = {
|
|
||||||
'wwn': '123456', 'model': 'foo-model', 'size': 123,
|
|
||||||
'serial': 'foo-serial', 'vendor': 'foo-vendor', 'name': '/dev/sda',
|
|
||||||
'wwn_with_extension': '123456111', 'wwn_vendor_extension': '111',
|
|
||||||
'rotational': True,
|
|
||||||
}
|
|
||||||
expected = ('model=foo-model,name=/dev/sda,rotational=True,'
|
|
||||||
'serial=foo-serial,size=123,vendor=foo-vendor,wwn=123456,'
|
|
||||||
'wwn_vendor_extension=111,wwn_with_extension=123456111')
|
|
||||||
result = utils.parse_root_device_hints(self.node)
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
|
||||||
def test_parse_root_device_hints_string_space(self):
|
|
||||||
self.node.properties['root_device'] = {'model': 'fake model'}
|
|
||||||
expected = 'model=fake%20model'
|
|
||||||
result = utils.parse_root_device_hints(self.node)
|
|
||||||
self.assertEqual(expected, result)
|
|
||||||
|
|
||||||
def test_parse_root_device_hints_no_hints(self):
|
|
||||||
self.node.properties = {}
|
|
||||||
result = utils.parse_root_device_hints(self.node)
|
|
||||||
self.assertIsNone(result)
|
|
||||||
|
|
||||||
def test_parse_root_device_hints_invalid_hints(self):
|
|
||||||
self.node.properties['root_device'] = {'vehicle': 'Owlship'}
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
utils.parse_root_device_hints, self.node)
|
|
||||||
|
|
||||||
def test_parse_root_device_hints_invalid_size(self):
|
|
||||||
self.node.properties['root_device'] = {'size': 'not-int'}
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
utils.parse_root_device_hints, self.node)
|
|
||||||
|
|
||||||
def test_parse_root_device_hints_invalid_rotational(self):
|
|
||||||
self.node.properties['root_device'] = {'rotational': 'not-boolean'}
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
utils.parse_root_device_hints, self.node)
|
|
||||||
|
|
||||||
@mock.patch.object(utils, 'LOG', autospec=True)
|
@mock.patch.object(utils, 'LOG', autospec=True)
|
||||||
@mock.patch.object(manager_utils, 'node_power_action', autospec=True)
|
@mock.patch.object(manager_utils, 'node_power_action', autospec=True)
|
||||||
@mock.patch.object(task_manager.TaskManager, 'process_event',
|
@mock.patch.object(task_manager.TaskManager, 'process_event',
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Adds support for using operators with the root device hints mechanism.
|
||||||
|
The currently supported operators are, ``=``, ``==``, ``!=``, ``>=``,
|
||||||
|
``<=``, ``>``, ``<``, ``s==``, ``s!=``, ``s>=``, ``s>``, ``s<=``,
|
||||||
|
``s<``, ``<in>``, ``<all-in>`` and ``<or>``.
|
Loading…
Reference in New Issue
Block a user