Add validation of 'ilo_deploy_iso' in deploy.validate()

iLO virtual media based drivers use ISO image supplied as
'ilo_deploy_iso' in node's 'driver_info' to boot node during
provisioning process. This parameter was not getting validated
during deploy.validate() call.

This change fixes the issue.

Change-Id: I8fc4a89621e09281349f88c32ed77d24aa11355b
Closes-Bug: #1592335
This commit is contained in:
Shivanand Tendulker 2016-06-15 01:29:12 -07:00
parent c263af664c
commit 2eab1ee09a
3 changed files with 157 additions and 0 deletions

View File

@ -20,8 +20,10 @@ from oslo_log import log as logging
from ironic.common import boot_devices
from ironic.common import exception
from ironic.common.glance_service import service_utils
from ironic.common.i18n import _
from ironic.common.i18n import _LW
from ironic.common import image_service
from ironic.common import states
from ironic.conductor import task_manager
from ironic.conductor import utils as manager_utils
@ -143,11 +145,53 @@ def _disable_secure_boot_if_supported(task):
task.node.uuid)
def _validate(task):
"""Validate the prerequisites for virtual media based deploy.
This method validates whether the 'driver_info' property of the
supplied node contains the required information for this driver.
:param task: a TaskManager instance containing the node to act on.
:raises: InvalidParameterValue if any parameters are incorrect
:raises: MissingParameterValue if some mandatory information
is missing on the node
"""
node = task.node
ilo_common.parse_driver_info(node)
if 'ilo_deploy_iso' not in node.driver_info:
raise exception.MissingParameterValue(_(
"Missing 'ilo_deploy_iso' parameter in node's 'driver_info'."))
deploy_iso = node.driver_info['ilo_deploy_iso']
if not service_utils.is_glance_image(deploy_iso):
try:
image_service.HttpImageService().validate_href(deploy_iso)
except exception.ImageRefValidationFailed:
raise exception.InvalidParameterValue(_(
"Virtual media deploy accepts only Glance images or "
"HTTP(S) as driver_info['ilo_deploy_iso']. Either '%s' "
"is not a glance UUID or not a valid HTTP(S) URL or "
"the given URL is not reachable.") % deploy_iso)
class IloVirtualMediaIscsiDeploy(iscsi_deploy.ISCSIDeploy):
def get_properties(self):
return {}
def validate(self, task):
"""Validate the prerequisites for virtual media based deploy.
This method validates whether the 'driver_info' property of the
supplied node contains the required information for this driver.
:param task: a TaskManager instance containing the node to act on.
:raises: InvalidParameterValue if any parameters are incorrect
:raises: MissingParameterValue if some mandatory information
is missing on the node
"""
_validate(task)
super(IloVirtualMediaIscsiDeploy, self).validate(task)
@task_manager.require_exclusive_lock
def tear_down(self, task):
"""Tear down a previous deployment on the task's node.
@ -200,6 +244,20 @@ class IloVirtualMediaAgentDeploy(agent.AgentDeploy):
"""
return ilo_boot.COMMON_PROPERTIES
def validate(self, task):
"""Validate the prerequisites for virtual media based deploy.
This method validates whether the 'driver_info' property of the
supplied node contains the required information for this driver.
:param task: a TaskManager instance containing the node to act on.
:raises: InvalidParameterValue if any parameters are incorrect
:raises: MissingParameterValue if some mandatory information
is missing on the node
"""
_validate(task)
super(IloVirtualMediaAgentDeploy, self).validate(task)
@task_manager.require_exclusive_lock
def tear_down(self, task):
"""Tear down a previous deployment on the task's node.

View File

@ -20,6 +20,8 @@ import six
from ironic.common import boot_devices
from ironic.common import exception
from ironic.common.glance_service import service_utils
from ironic.common import image_service
from ironic.common import states
from ironic.conductor import task_manager
from ironic.conductor import utils as manager_utils
@ -188,6 +190,72 @@ class IloDeployPrivateMethodsTestCase(db_base.DbTestCase):
self.assertIsNone(bootmode)
self.assertNotIn('deploy_boot_mode', task.node.instance_info)
@mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True,
autospec=True)
def test__validate_MissingParam(self, mock_parse_driver_info):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
self.assertRaisesRegex(exception.MissingParameterValue,
"Missing 'ilo_deploy_iso'",
ilo_deploy._validate, task)
mock_parse_driver_info.assert_called_once_with(task.node)
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True,
autospec=True)
def test__validate_valid_uuid(self, mock_parse_driver_info,
mock_is_glance_image):
mock_is_glance_image.return_value = True
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
deploy_iso = '8a81759a-f29b-454b-8ab3-161c6ca1882c'
task.node.driver_info['ilo_deploy_iso'] = deploy_iso
ilo_deploy._validate(task)
mock_parse_driver_info.assert_called_once_with(task.node)
mock_is_glance_image.assert_called_once_with(deploy_iso)
@mock.patch.object(image_service.HttpImageService, 'validate_href',
spec_set=True, autospec=True)
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True,
autospec=True)
def test__validate_InvalidParam(self, mock_parse_driver_info,
mock_is_glance_image,
mock_validate_href):
deploy_iso = 'http://abc.org/image/qcow2'
mock_validate_href.side_effect = iter(
[exception.ImageRefValidationFailed(
image_href='http://abc.org/image/qcow2', reason='fail')])
mock_is_glance_image.return_value = False
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.driver_info['ilo_deploy_iso'] = deploy_iso
self.assertRaisesRegex(exception.InvalidParameterValue,
"Virtual media deploy accepts",
ilo_deploy._validate, task)
mock_parse_driver_info.assert_called_once_with(task.node)
mock_validate_href.assert_called_once_with(mock.ANY, deploy_iso)
@mock.patch.object(image_service.HttpImageService, 'validate_href',
spec_set=True, autospec=True)
@mock.patch.object(service_utils, 'is_glance_image', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True,
autospec=True)
def test__validate_valid_url(self, mock_parse_driver_info,
mock_is_glance_image,
mock_validate_href):
deploy_iso = 'http://abc.org/image/deploy.iso'
mock_is_glance_image.return_value = False
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.driver_info['ilo_deploy_iso'] = deploy_iso
ilo_deploy._validate(task)
mock_parse_driver_info.assert_called_once_with(task.node)
mock_validate_href.assert_called_once_with(mock.ANY, deploy_iso)
class IloVirtualMediaIscsiDeployTestCase(db_base.DbTestCase):
@ -197,6 +265,19 @@ class IloVirtualMediaIscsiDeployTestCase(db_base.DbTestCase):
self.node = obj_utils.create_test_node(
self.context, driver='iscsi_ilo', driver_info=INFO_DICT)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'validate', spec_set=True,
autospec=True)
@mock.patch.object(ilo_deploy, '_validate', spec_set=True,
autospec=True)
def test_validate(self,
mock_validate,
iscsi_validate):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.driver.deploy.validate(task)
mock_validate.assert_called_once_with(task)
iscsi_validate.assert_called_once_with(mock.ANY, task)
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,
autospec=True)
@mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down', spec_set=True,
@ -314,6 +395,19 @@ class IloVirtualMediaAgentDeployTestCase(db_base.DbTestCase):
self.node = obj_utils.create_test_node(
self.context, driver='agent_ilo', driver_info=INFO_DICT)
@mock.patch.object(agent.AgentDeploy, 'validate', spec_set=True,
autospec=True)
@mock.patch.object(ilo_deploy, '_validate', spec_set=True,
autospec=True)
def test_validate(self,
mock_validate,
agent_validate):
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.driver.deploy.validate(task)
mock_validate.assert_called_once_with(task)
agent_validate.assert_called_once_with(mock.ANY, task)
@mock.patch.object(agent.AgentDeploy, 'tear_down', spec_set=True,
autospec=True)
@mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True,

View File

@ -0,0 +1,5 @@
---
fixes:
- A node using 'agent_ilo' or 'iscsi_ilo' driver has
their 'driver_info/ilo_deploy_iso' field validated
during node validate. This closes bug #1592335.