Merge "Follow up to root device hints in instance_info"

This commit is contained in:
Zuul 2020-01-27 16:35:42 +00:00 committed by Gerrit Code Review
commit 8169f2532b
9 changed files with 57 additions and 30 deletions

View File

@ -48,6 +48,10 @@ That will guarantee that Bare Metal service will pick the disk device that
has the ``wwn`` equal to the specified wwn value, or fail the deployment if it has the ``wwn`` equal to the specified wwn value, or fail the deployment if it
can not be found. can not be found.
.. note::
Starting with the Ussuri release, root device hints can be specified
per-instance, see :doc:`/install/standalone`.
The hints can have an operator at the beginning of the value string. If The hints can have an operator at the beginning of the value string. If
no operator is specified the default is ``==`` (for numerical values) no operator is specified the default is ``==`` (for numerical values)
and ``s==`` (for string values). The supported operators are: and ``s==`` (for string values). The supported operators are:

View File

@ -152,6 +152,15 @@ Steps to start a deployment are pretty similar to those when using Compute:
--instance-info ramdisk=$RAMDISK \ --instance-info ramdisk=$RAMDISK \
--instance-info root_gb=10 --instance-info root_gb=10
#. Starting with the Ussuri release, you can set :ref:`root device hints
<root-device-hints>` per instance::
openstack baremetal node set $NODE_UUID \
--instance-info root_device='{"wwn": "0x4000cca77fc4dba1"}'
This setting overrides any previous setting in ``properties`` and will be
removed on undeployment.
#. Validate that all parameters are correct:: #. Validate that all parameters are correct::
openstack baremetal node validate $NODE_UUID openstack baremetal node validate $NODE_UUID

View File

@ -15,7 +15,6 @@
from urllib import parse as urlparse from urllib import parse as urlparse
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
@ -431,15 +430,7 @@ 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
try: deploy_utils.get_root_device_for_deploy(node)
root_device = deploy_utils.get_root_device_for_deploy(node)
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_image_proxies(node) validate_image_proxies(node)
@METRICS.timer('AgentDeploy.deploy') @METRICS.timer('AgentDeploy.deploy')

View File

@ -229,15 +229,10 @@ def _parse_partitioning_info(node):
def _parse_root_device_hints(node): def _parse_root_device_hints(node):
"""Convert string with hints to dict. """ """Convert string with hints to dict. """
root_device = deploy_utils.get_root_device_for_deploy(node) parsed_hints = deploy_utils.get_root_device_for_deploy(node)
if not root_device: if not parsed_hints:
return {} return {}
try:
parsed_hints = irlib_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})
root_device_hints = {} root_device_hints = {}
advanced = {} advanced = {}
for hint, value in parsed_hints.items(): for hint, value in parsed_hints.items():

View File

@ -1503,6 +1503,24 @@ def set_async_step_flags(node, reboot=None, skip_current_step=None,
def get_root_device_for_deploy(node): def get_root_device_for_deploy(node):
"""Get a root device requested for deployment or None.""" """Get a root device requested for deployment or None.
return (node.instance_info.get('root_device')
or node.properties.get('root_device')) :raises: InvalidParameterValue on invalid hints.
:return: Parsed root device hints or None if no hints were provided.
"""
hints = node.instance_info.get('root_device')
if not hints:
hints = node.properties.get('root_device')
if not hints:
return
source = 'properties'
else:
source = 'instance_info'
try:
return il_utils.parse_root_device_hints(hints)
except ValueError as e:
raise exception.InvalidParameterValue(
_('Failed to validate the root device hints %(hints)s (from the '
'node\'s %(source)s) for node %(node)s. Error: %(error)s') %
{'node': node.uuid, 'hints': hints, 'source': source, 'error': e})

View File

@ -17,7 +17,6 @@ from urllib import parse as urlparse
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 il_utils
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
@ -320,14 +319,7 @@ 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
try: deploy_utils.get_root_device_for_deploy(task.node)
root_device = deploy_utils.get_root_device_for_deploy(task.node)
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)

View File

@ -369,6 +369,22 @@ class TestAnsibleMethods(AnsibleDeployTestCaseBase):
self.assertEqual( self.assertEqual(
expected, ansible_deploy._parse_root_device_hints(task.node)) expected, ansible_deploy._parse_root_device_hints(task.node))
def test__parse_root_device_hints_override(self):
hints = {"wwn": "fake wwn", "size": "12345", "rotational": True,
"serial": "HELLO"}
expected = {"wwn": "fake wwn", "size": 12345, "rotational": True,
"serial": "hello"}
props = self.node.properties
props['root_device'] = {'size': 'no idea'}
self.node.properties = props
iinfo = self.node.instance_info
iinfo['root_device'] = hints
self.node.instance_info = iinfo
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertEqual(
expected, ansible_deploy._parse_root_device_hints(task.node))
def test__parse_root_device_hints_fail_advanced(self): def test__parse_root_device_hints_fail_advanced(self):
hints = {"wwn": "s!= fake wwn", hints = {"wwn": "s!= fake wwn",
"size": ">= 12345", "size": ">= 12345",

View File

@ -281,6 +281,7 @@ class TestAgentDeploy(db_base.DbTestCase):
self, pxe_boot_validate_mock, show_mock, validate_http_mock): self, pxe_boot_validate_mock, show_mock, validate_http_mock):
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
task.node.properties['root_device'] = {'size': 42}
task.node.instance_info['root_device'] = {'size': 'not-int'} task.node.instance_info['root_device'] = {'size': 'not-int'}
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
task.driver.deploy.validate, task) task.driver.deploy.validate, task)

View File

@ -579,6 +579,7 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
mock_get_url.return_value = 'http://spam.ham/baremetal' mock_get_url.return_value = 'http://spam.ham/baremetal'
with task_manager.acquire(self.context, self.node.uuid, with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task: shared=True) as task:
task.node.properties['root_device'] = {'size': 42}
task.node.instance_info['root_device'] = {'size': 'not-int'} task.node.instance_info['root_device'] = {'size': 'not-int'}
self.assertRaises(exception.InvalidParameterValue, self.assertRaises(exception.InvalidParameterValue,
iscsi_deploy.validate, task) iscsi_deploy.validate, task)