Allow reading root_device from instance_info

For the future deployment API we need to be able to set root_device
per deployment in addition to per node. This change adds it.

Change-Id: I1dd046c2e5fca211a84290bac8daa7550b21614f
Depends-On: https://review.opendev.org/701043
Story: #2006910
Task: #37556
This commit is contained in:
Dmitry Tantsur 2020-01-03 17:59:03 +01:00
parent 2a43e371f1
commit 42dc9787e5
8 changed files with 53 additions and 3 deletions

View File

@ -432,7 +432,7 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
check_image_size(task, image_source)
# Validate the root device hints
try:
root_device = node.properties.get('root_device')
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(

View File

@ -229,7 +229,7 @@ def _parse_partitioning_info(node):
def _parse_root_device_hints(node):
"""Convert string with hints to dict. """
root_device = node.properties.get('root_device')
root_device = deploy_utils.get_root_device_for_deploy(node)
if not root_device:
return {}
try:

View File

@ -1509,3 +1509,9 @@ def set_async_step_flags(node, reboot=None, skip_current_step=None,
info[fields['polling']] = polling
node.driver_internal_info = info
node.save()
def get_root_device_for_deploy(node):
"""Get a root device requested for deployment or None."""
return (node.instance_info.get('root_device')
or node.properties.get('root_device'))

View File

@ -321,7 +321,7 @@ def validate(task):
deploy_utils.get_ironic_api_url()
# Validate the root device hints
try:
root_device = task.node.properties.get('root_device')
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(

View File

@ -356,6 +356,19 @@ class TestAnsibleMethods(AnsibleDeployTestCaseBase):
self.assertEqual(
expected, ansible_deploy._parse_root_device_hints(task.node))
def test__parse_root_device_hints_iinfo(self):
hints = {"wwn": "fake wwn", "size": "12345", "rotational": True,
"serial": "HELLO"}
expected = {"wwn": "fake wwn", "size": 12345, "rotational": True,
"serial": "hello"}
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):
hints = {"wwn": "s!= fake wwn",
"size": ">= 12345",

View File

@ -273,6 +273,22 @@ class TestAgentDeploy(db_base.DbTestCase):
show_mock.assert_called_once_with(self.context, 'fake-image')
validate_http_mock.assert_called_once_with(task.node)
@mock.patch.object(agent, 'validate_http_provisioning_configuration',
autospec=True)
@mock.patch.object(images, 'image_show', autospec=True)
@mock.patch.object(pxe.PXEBoot, 'validate', autospec=True)
def test_validate_invalid_root_device_hints_iinfo(
self, pxe_boot_validate_mock, show_mock, validate_http_mock):
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
task.node.instance_info['root_device'] = {'size': 'not-int'}
self.assertRaises(exception.InvalidParameterValue,
task.driver.deploy.validate, task)
pxe_boot_validate_mock.assert_called_once_with(
task.driver.boot, task)
show_mock.assert_called_once_with(self.context, 'fake-image')
validate_http_mock.assert_called_once_with(task.node)
@mock.patch.object(agent, 'validate_http_provisioning_configuration',
autospec=True)
@mock.patch.object(images, 'image_show', autospec=True)

View File

@ -574,6 +574,15 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
self.assertRaises(exception.InvalidParameterValue,
iscsi_deploy.validate, task)
@mock.patch('ironic.drivers.modules.deploy_utils.get_ironic_api_url')
def test_validate_invalid_root_device_hints_iinfo(self, mock_get_url):
mock_get_url.return_value = 'http://spam.ham/baremetal'
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
task.node.instance_info['root_device'] = {'size': 'not-int'}
self.assertRaises(exception.InvalidParameterValue,
iscsi_deploy.validate, task)
class ISCSIDeployTestCase(db_base.DbTestCase):

View File

@ -0,0 +1,6 @@
---
features:
- |
Allows reading the ``root_device`` from ``instance_info``, overriding
the value in ``properties``. This enables per-instance root device
settings and requires the Ussuri release of ironic-python-agent.