Merge "Implements validate_rescue() for IRMCVirtualMediaBoot"
This commit is contained in:
commit
d13713acf5
@ -58,6 +58,12 @@ REQUIRED_PROPERTIES = {
|
||||
"Required."),
|
||||
}
|
||||
|
||||
RESCUE_PROPERTIES = {
|
||||
'irmc_rescue_iso': _("UUID (from Glance) of the rescue ISO. Only "
|
||||
"required if rescue mode is being used and ironic "
|
||||
"is managing booting the rescue ramdisk.")
|
||||
}
|
||||
|
||||
OPTIONAL_PROPERTIES = {
|
||||
'irmc_pci_physical_ids':
|
||||
_("Physical IDs of PCI cards. A dictionary of pairs of resource UUID "
|
||||
@ -96,7 +102,7 @@ def _parse_config_option():
|
||||
raise exception.InvalidParameterValue(msg)
|
||||
|
||||
|
||||
def _parse_driver_info(node):
|
||||
def _parse_driver_info(node, mode='deploy'):
|
||||
"""Gets the driver specific Node deployment info.
|
||||
|
||||
This method validates whether the 'driver_info' property of the
|
||||
@ -104,6 +110,9 @@ def _parse_driver_info(node):
|
||||
for this driver to deploy images to the node.
|
||||
|
||||
:param node: a target node of the deployment
|
||||
:param mode: Label indicating a deploy or rescue operation being
|
||||
carried out on the node. Supported values are
|
||||
'deploy' and 'rescue'. Defaults to 'deploy'.
|
||||
:returns: the driver_info values of the node.
|
||||
:raises: MissingParameterValue, if any of the required parameters are
|
||||
missing.
|
||||
@ -113,19 +122,26 @@ def _parse_driver_info(node):
|
||||
d_info = node.driver_info
|
||||
deploy_info = {}
|
||||
|
||||
deploy_info['irmc_deploy_iso'] = d_info.get('irmc_deploy_iso')
|
||||
error_msg = _("Error validating iRMC virtual media deploy. Some parameters"
|
||||
" were missing in node's driver_info")
|
||||
if mode == 'deploy':
|
||||
image_iso = d_info.get('irmc_deploy_iso')
|
||||
deploy_info['irmc_deploy_iso'] = image_iso
|
||||
else:
|
||||
image_iso = d_info.get('irmc_rescue_iso')
|
||||
deploy_info['irmc_rescue_iso'] = image_iso
|
||||
|
||||
error_msg = (_("Error validating iRMC virtual media for %s. Some "
|
||||
"parameters were missing in node's driver_info") % mode)
|
||||
deploy_utils.check_for_missing_params(deploy_info, error_msg)
|
||||
|
||||
if service_utils.is_image_href_ordinary_file_name(
|
||||
deploy_info['irmc_deploy_iso']):
|
||||
deploy_iso = os.path.join(CONF.irmc.remote_image_share_root,
|
||||
deploy_info['irmc_deploy_iso'])
|
||||
if not os.path.isfile(deploy_iso):
|
||||
msg = (_("Deploy ISO file, %(deploy_iso)s, "
|
||||
if service_utils.is_image_href_ordinary_file_name(image_iso):
|
||||
image_iso_file = os.path.join(CONF.irmc.remote_image_share_root,
|
||||
image_iso)
|
||||
if not os.path.isfile(image_iso_file):
|
||||
msg = (_("%(mode)s ISO file, %(iso_file)s, "
|
||||
"not found for node: %(node)s.") %
|
||||
{'deploy_iso': deploy_iso, 'node': node.uuid})
|
||||
{'mode': mode.capitalize(),
|
||||
'iso_file': image_iso_file,
|
||||
'node': node.uuid})
|
||||
raise exception.InvalidParameterValue(msg)
|
||||
|
||||
return deploy_info
|
||||
@ -185,13 +201,16 @@ def _parse_deploy_info(node):
|
||||
return deploy_info
|
||||
|
||||
|
||||
def _setup_deploy_iso(task, ramdisk_options):
|
||||
def _setup_vmedia(task, mode, ramdisk_options):
|
||||
"""Attaches virtual media and sets it as boot device.
|
||||
|
||||
This method attaches the given deploy ISO as virtual media, prepares the
|
||||
arguments for ramdisk in virtual media floppy.
|
||||
This method attaches the deploy or rescue ISO as virtual media, prepares
|
||||
the arguments for ramdisk in virtual media floppy.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:param mode: Label indicating a deploy or rescue operation being
|
||||
carried out on the node. Supported values are
|
||||
'deploy' and 'rescue'.
|
||||
:param ramdisk_options: the options to be passed to the ramdisk in virtual
|
||||
media floppy.
|
||||
:raises: ImageRefValidationFailed if no image service can handle specified
|
||||
@ -201,35 +220,31 @@ def _setup_deploy_iso(task, ramdisk_options):
|
||||
:raises: InvalidParameterValue if the validation of the
|
||||
PowerInterface or ManagementInterface fails.
|
||||
"""
|
||||
d_info = task.node.driver_info
|
||||
|
||||
deploy_iso_href = d_info['irmc_deploy_iso']
|
||||
if service_utils.is_image_href_ordinary_file_name(deploy_iso_href):
|
||||
deploy_iso_file = deploy_iso_href
|
||||
if mode == 'rescue':
|
||||
iso = task.node.driver_info['irmc_rescue_iso']
|
||||
else:
|
||||
deploy_iso_file = _get_deploy_iso_name(task.node)
|
||||
deploy_iso_fullpathname = os.path.join(
|
||||
CONF.irmc.remote_image_share_root, deploy_iso_file)
|
||||
images.fetch(task.context, deploy_iso_href, deploy_iso_fullpathname)
|
||||
iso = task.node.driver_info['irmc_deploy_iso']
|
||||
|
||||
_setup_vmedia_for_boot(task, deploy_iso_file, ramdisk_options)
|
||||
if service_utils.is_image_href_ordinary_file_name(iso):
|
||||
iso_file = iso
|
||||
else:
|
||||
iso_file = _get_iso_name(task.node, label=mode)
|
||||
iso_fullpathname = os.path.join(
|
||||
CONF.irmc.remote_image_share_root, iso_file)
|
||||
images.fetch(task.context, iso, iso_fullpathname)
|
||||
|
||||
_setup_vmedia_for_boot(task, iso_file, ramdisk_options)
|
||||
manager_utils.node_set_boot_device(task, boot_devices.CDROM)
|
||||
|
||||
|
||||
def _get_deploy_iso_name(node):
|
||||
"""Returns the deploy ISO file name for a given node.
|
||||
def _get_iso_name(node, label):
|
||||
"""Returns the ISO file name for a given node.
|
||||
|
||||
:param node: the node for which ISO file name is to be provided.
|
||||
:param label: a string used as a base name for the ISO file.
|
||||
"""
|
||||
return "deploy-%s.iso" % node.uuid
|
||||
|
||||
|
||||
def _get_boot_iso_name(node):
|
||||
"""Returns the boot ISO file name for a given node.
|
||||
|
||||
:param node: the node for which ISO file name is to be provided.
|
||||
"""
|
||||
return "boot-%s.iso" % node.uuid
|
||||
return "%s-%s.iso" % (label, node.uuid)
|
||||
|
||||
|
||||
def _prepare_boot_iso(task, root_uuid):
|
||||
@ -253,7 +268,7 @@ def _prepare_boot_iso(task, root_uuid):
|
||||
if service_utils.is_image_href_ordinary_file_name(boot_iso_href):
|
||||
driver_internal_info['irmc_boot_iso'] = boot_iso_href
|
||||
else:
|
||||
boot_iso_filename = _get_boot_iso_name(task.node)
|
||||
boot_iso_filename = _get_iso_name(task.node, label='boot')
|
||||
boot_iso_fullpathname = os.path.join(
|
||||
CONF.irmc.remote_image_share_root, boot_iso_filename)
|
||||
images.fetch(task.context, boot_iso_href, boot_iso_fullpathname)
|
||||
@ -271,13 +286,13 @@ def _prepare_boot_iso(task, root_uuid):
|
||||
ramdisk_href = (task.node.instance_info.get('ramdisk') or
|
||||
image_properties['ramdisk_id'])
|
||||
|
||||
deploy_iso_filename = _get_deploy_iso_name(task.node)
|
||||
deploy_iso_filename = _get_iso_name(task.node, label='deploy')
|
||||
deploy_iso = ('file://' + os.path.join(
|
||||
CONF.irmc.remote_image_share_root, deploy_iso_filename))
|
||||
boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node)
|
||||
kernel_params = CONF.pxe.pxe_append_params
|
||||
|
||||
boot_iso_filename = _get_boot_iso_name(task.node)
|
||||
boot_iso_filename = _get_iso_name(task.node, label='boot')
|
||||
boot_iso_fullpathname = os.path.join(
|
||||
CONF.irmc.remote_image_share_root, boot_iso_filename)
|
||||
|
||||
@ -399,7 +414,8 @@ def _cleanup_vmedia_boot(task):
|
||||
_detach_virtual_fd(node)
|
||||
|
||||
_remove_share_file(_get_floppy_image_name(node))
|
||||
_remove_share_file(_get_deploy_iso_name(node))
|
||||
_remove_share_file(_get_iso_name(node, label='deploy'))
|
||||
_remove_share_file(_get_iso_name(node, label='rescue'))
|
||||
|
||||
|
||||
def _remove_share_file(share_filename):
|
||||
@ -408,7 +424,7 @@ def _remove_share_file(share_filename):
|
||||
:param share_filename: a file name to be removed.
|
||||
"""
|
||||
share_fullpathname = os.path.join(
|
||||
CONF.irmc.remote_image_share_name, share_filename)
|
||||
CONF.irmc.remote_image_share_root, share_filename)
|
||||
ironic_utils.unlink_without_raise(share_fullpathname)
|
||||
|
||||
|
||||
@ -877,6 +893,9 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
super(IRMCVirtualMediaBoot, self).__init__()
|
||||
|
||||
def get_properties(self):
|
||||
# TODO(tiendc): COMMON_PROPERTIES should also include rescue
|
||||
# related properties (RESCUE_PROPERTIES). We can add them in Rocky,
|
||||
# when classic drivers get removed.
|
||||
return COMMON_PROPERTIES
|
||||
|
||||
@METRICS.timer('IRMCVirtualMediaBoot.validate')
|
||||
@ -913,13 +932,13 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
|
||||
@METRICS.timer('IRMCVirtualMediaBoot.prepare_ramdisk')
|
||||
def prepare_ramdisk(self, task, ramdisk_params):
|
||||
"""Prepares the deploy ramdisk using virtual media.
|
||||
"""Prepares the deploy or rescue ramdisk using virtual media.
|
||||
|
||||
Prepares the options for the deployment ramdisk, sets the node to boot
|
||||
from virtual media cdrom.
|
||||
Prepares the options for the deploy or rescue ramdisk, sets the node
|
||||
to boot from virtual media cdrom.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:param ramdisk_params: the options to be passed to the deploy ramdisk.
|
||||
:param ramdisk_params: the options to be passed to the ramdisk.
|
||||
:raises: ImageRefValidationFailed if no image service can handle
|
||||
specified href.
|
||||
:raises: ImageCreationFailed, if it failed while creating the floppy
|
||||
@ -930,11 +949,12 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
"""
|
||||
|
||||
# NOTE(TheJulia): If this method is being called by something
|
||||
# aside from deployment and clean, such as conductor takeover, we
|
||||
# should treat this as a no-op and move on otherwise we would modify
|
||||
# the state of the node due to virtual media operations.
|
||||
if (task.node.provision_state != states.DEPLOYING and
|
||||
task.node.provision_state != states.CLEANING):
|
||||
# aside from deployment, clean and rescue, such as conductor takeover,
|
||||
# we should treat this as a no-op and move on otherwise we would
|
||||
# modify the state of the node due to virtual media operations.
|
||||
if task.node.provision_state not in (states.DEPLOYING,
|
||||
states.CLEANING,
|
||||
states.RESCUING):
|
||||
return
|
||||
|
||||
# NOTE(tiendc): Before deploying, we need to backup BIOS config
|
||||
@ -951,14 +971,19 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
deploy_nic_mac = deploy_utils.get_single_nic_with_vif_port_id(task)
|
||||
ramdisk_params['BOOTIF'] = deploy_nic_mac
|
||||
|
||||
_setup_deploy_iso(task, ramdisk_params)
|
||||
if task.node.provision_state == states.RESCUING:
|
||||
mode = 'rescue'
|
||||
else:
|
||||
mode = 'deploy'
|
||||
|
||||
_setup_vmedia(task, mode, ramdisk_params)
|
||||
|
||||
@METRICS.timer('IRMCVirtualMediaBoot.clean_up_ramdisk')
|
||||
def clean_up_ramdisk(self, task):
|
||||
"""Cleans up the boot of ironic ramdisk.
|
||||
|
||||
This method cleans up the environment that was setup for booting the
|
||||
deploy ramdisk.
|
||||
deploy or rescue ramdisk.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:returns: None
|
||||
@ -1018,10 +1043,18 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
if deploy_utils.is_secure_boot_requested(task.node):
|
||||
irmc_common.set_secure_boot_mode(task.node, enable=False)
|
||||
|
||||
_remove_share_file(_get_boot_iso_name(task.node))
|
||||
_remove_share_file(_get_iso_name(task.node, label='boot'))
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info.pop('irmc_boot_iso', None)
|
||||
|
||||
# When rescue, this function is called. But we need to retain the
|
||||
# root_uuid_or_disk_id to use on unrescue (see prepare_instance).
|
||||
boot_local_or_iwdi = (
|
||||
deploy_utils.get_boot_option(task.node) == "local" or
|
||||
driver_internal_info.get('is_whole_disk_image'))
|
||||
if task.node.provision_state != states.RESCUING or boot_local_or_iwdi:
|
||||
driver_internal_info.pop('root_uuid_or_disk_id', None)
|
||||
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
_cleanup_vmedia_boot(task)
|
||||
@ -1035,6 +1068,18 @@ class IRMCVirtualMediaBoot(base.BootInterface, IRMCVolumeBootMixIn):
|
||||
manager_utils.node_set_boot_device(task, boot_devices.CDROM,
|
||||
persistent=True)
|
||||
|
||||
@METRICS.timer('IRMCVirtualMediaBoot.validate_rescue')
|
||||
def validate_rescue(self, task):
|
||||
"""Validate that the node has required properties for rescue.
|
||||
|
||||
:param task: a TaskManager instance with the node being checked
|
||||
:raises: MissingParameterValue if node is missing one or more required
|
||||
parameters
|
||||
:raises: InvalidParameterValue, if any of the parameters have invalid
|
||||
value.
|
||||
"""
|
||||
_parse_driver_info(task.node, mode='rescue')
|
||||
|
||||
|
||||
class IRMCPXEBoot(pxe.PXEBoot):
|
||||
"""iRMC PXE boot."""
|
||||
|
@ -111,7 +111,8 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
self.node.driver_info['irmc_deploy_iso'] = 'deploy.iso'
|
||||
driver_info_expected = {'irmc_deploy_iso': 'deploy.iso'}
|
||||
|
||||
driver_info_actual = irmc_boot._parse_driver_info(self.node)
|
||||
driver_info_actual = irmc_boot._parse_driver_info(self.node,
|
||||
mode='deploy')
|
||||
|
||||
isfile_mock.assert_called_once_with(
|
||||
'/remote_image_share_root/deploy.iso')
|
||||
@ -123,17 +124,18 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
self, is_image_href_ordinary_file_name_mock):
|
||||
"""With required 'irmc_deploy_iso' not in share."""
|
||||
self.node.driver_info[
|
||||
'irmc_deploy_iso'] = 'bc784057-a140-4130-add3-ef890457e6b3'
|
||||
driver_info_expected = {'irmc_deploy_iso':
|
||||
'irmc_rescue_iso'] = 'bc784057-a140-4130-add3-ef890457e6b3'
|
||||
driver_info_expected = {'irmc_rescue_iso':
|
||||
'bc784057-a140-4130-add3-ef890457e6b3'}
|
||||
is_image_href_ordinary_file_name_mock.return_value = False
|
||||
|
||||
driver_info_actual = irmc_boot._parse_driver_info(self.node)
|
||||
driver_info_actual = irmc_boot._parse_driver_info(self.node,
|
||||
mode='rescue')
|
||||
|
||||
self.assertEqual(driver_info_expected, driver_info_actual)
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', spec_set=True, autospec=True)
|
||||
def test__parse_driver_info_with_deploy_iso_invalid(self, isfile_mock):
|
||||
def test__parse_driver_info_with_iso_invalid(self, isfile_mock):
|
||||
"""With required 'irmc_deploy_iso' non existed."""
|
||||
isfile_mock.return_value = False
|
||||
|
||||
@ -146,19 +148,19 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
|
||||
e = self.assertRaises(exception.InvalidParameterValue,
|
||||
irmc_boot._parse_driver_info,
|
||||
task.node)
|
||||
task.node, mode='deploy')
|
||||
self.assertEqual(error_msg, str(e))
|
||||
|
||||
def test__parse_driver_info_with_deploy_iso_missing(self):
|
||||
"""With required 'irmc_deploy_iso' empty."""
|
||||
self.node.driver_info['irmc_deploy_iso'] = None
|
||||
def test__parse_driver_info_with_iso_missing(self):
|
||||
"""With required 'irmc_rescue_iso' empty."""
|
||||
self.node.driver_info['irmc_rescue_iso'] = None
|
||||
|
||||
error_msg = ("Error validating iRMC virtual media deploy. Some"
|
||||
error_msg = ("Error validating iRMC virtual media for rescue. Some"
|
||||
" parameters were missing in node's driver_info."
|
||||
" Missing are: ['irmc_deploy_iso']")
|
||||
" Missing are: ['irmc_rescue_iso']")
|
||||
e = self.assertRaises(exception.MissingParameterValue,
|
||||
irmc_boot._parse_driver_info,
|
||||
self.node)
|
||||
self.node, mode='rescue')
|
||||
self.assertEqual(error_msg, str(e))
|
||||
|
||||
def test__parse_instance_info_with_boot_iso_file_name_ok(self):
|
||||
@ -274,7 +276,7 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
@mock.patch.object(images, 'fetch', spec_set=True,
|
||||
autospec=True)
|
||||
def test__setup_deploy_iso_with_file(self,
|
||||
def test__setup_vmedia_with_file_deploy(self,
|
||||
fetch_mock,
|
||||
setup_vmedia_mock,
|
||||
set_boot_device_mock):
|
||||
@ -282,7 +284,8 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
shared=False) as task:
|
||||
task.node.driver_info['irmc_deploy_iso'] = 'deploy_iso_filename'
|
||||
ramdisk_opts = {'a': 'b'}
|
||||
irmc_boot._setup_deploy_iso(task, ramdisk_opts)
|
||||
irmc_boot._setup_vmedia(task, mode='deploy',
|
||||
ramdisk_options=ramdisk_opts)
|
||||
|
||||
self.assertFalse(fetch_mock.called)
|
||||
|
||||
@ -299,7 +302,33 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
@mock.patch.object(images, 'fetch', spec_set=True,
|
||||
autospec=True)
|
||||
def test_setup_deploy_iso_with_image_service(
|
||||
def test__setup_vmedia_with_file_rescue(self,
|
||||
fetch_mock,
|
||||
setup_vmedia_mock,
|
||||
set_boot_device_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.node.driver_info['irmc_rescue_iso'] = 'rescue_iso_filename'
|
||||
ramdisk_opts = {'a': 'b'}
|
||||
irmc_boot._setup_vmedia(task, mode='rescue',
|
||||
ramdisk_options=ramdisk_opts)
|
||||
|
||||
self.assertFalse(fetch_mock.called)
|
||||
|
||||
setup_vmedia_mock.assert_called_once_with(
|
||||
task,
|
||||
'rescue_iso_filename',
|
||||
ramdisk_opts)
|
||||
set_boot_device_mock.assert_called_once_with(task,
|
||||
boot_devices.CDROM)
|
||||
|
||||
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(irmc_boot, '_setup_vmedia_for_boot', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(images, 'fetch', spec_set=True,
|
||||
autospec=True)
|
||||
def test_setup_vmedia_with_image_service_deploy(
|
||||
self,
|
||||
fetch_mock,
|
||||
setup_vmedia_mock,
|
||||
@ -310,7 +339,8 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
shared=False) as task:
|
||||
task.node.driver_info['irmc_deploy_iso'] = 'glance://deploy_iso'
|
||||
ramdisk_opts = {'a': 'b'}
|
||||
irmc_boot._setup_deploy_iso(task, ramdisk_opts)
|
||||
irmc_boot._setup_vmedia(task, mode='deploy',
|
||||
ramdisk_options=ramdisk_opts)
|
||||
|
||||
fetch_mock.assert_called_once_with(
|
||||
task.context,
|
||||
@ -324,14 +354,41 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.CDROM)
|
||||
|
||||
def test__get_deploy_iso_name(self):
|
||||
actual = irmc_boot._get_deploy_iso_name(self.node)
|
||||
expected = "deploy-%s.iso" % self.node.uuid
|
||||
self.assertEqual(expected, actual)
|
||||
@mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(irmc_boot, '_setup_vmedia_for_boot', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(images, 'fetch', spec_set=True,
|
||||
autospec=True)
|
||||
def test_setup_vmedia_with_image_service_rescue(
|
||||
self,
|
||||
fetch_mock,
|
||||
setup_vmedia_mock,
|
||||
set_boot_device_mock):
|
||||
CONF.irmc.remote_image_share_root = '/'
|
||||
|
||||
def test__get_boot_iso_name(self):
|
||||
actual = irmc_boot._get_boot_iso_name(self.node)
|
||||
expected = "boot-%s.iso" % self.node.uuid
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.node.driver_info['irmc_rescue_iso'] = 'glance://rescue_iso'
|
||||
ramdisk_opts = {'a': 'b'}
|
||||
irmc_boot._setup_vmedia(task, mode='rescue',
|
||||
ramdisk_options=ramdisk_opts)
|
||||
|
||||
fetch_mock.assert_called_once_with(
|
||||
task.context,
|
||||
'glance://rescue_iso',
|
||||
"/rescue-%s.iso" % self.node.uuid)
|
||||
|
||||
setup_vmedia_mock.assert_called_once_with(
|
||||
task,
|
||||
"rescue-%s.iso" % self.node.uuid,
|
||||
ramdisk_opts)
|
||||
set_boot_device_mock.assert_called_once_with(
|
||||
task, boot_devices.CDROM)
|
||||
|
||||
def test__get_iso_name(self):
|
||||
actual = irmc_boot._get_iso_name(self.node, label='deploy')
|
||||
expected = "deploy-%s.iso" % self.node.uuid
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@mock.patch.object(images, 'create_boot_iso', spec_set=True, autospec=True)
|
||||
@ -599,7 +656,7 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
task.node,
|
||||
'bootable_iso_filename')
|
||||
|
||||
@mock.patch.object(irmc_boot, '_get_deploy_iso_name', spec_set=True,
|
||||
@mock.patch.object(irmc_boot, '_get_iso_name', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(irmc_boot, '_get_floppy_image_name', spec_set=True,
|
||||
autospec=True)
|
||||
@ -614,7 +671,7 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
_detach_virtual_fd_mock,
|
||||
_remove_share_file_mock,
|
||||
_get_floppy_image_name_mock,
|
||||
_get_deploy_iso_name_mock):
|
||||
_get_iso_name_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
irmc_boot._cleanup_vmedia_boot(task)
|
||||
@ -622,20 +679,23 @@ class IRMCDeployPrivateMethodsTestCase(db_base.DbTestCase):
|
||||
_detach_virtual_cd_mock.assert_called_once_with(task.node)
|
||||
_detach_virtual_fd_mock.assert_called_once_with(task.node)
|
||||
_get_floppy_image_name_mock.assert_called_once_with(task.node)
|
||||
_get_deploy_iso_name_mock.assert_called_once_with(task.node)
|
||||
self.assertTrue(_remove_share_file_mock.call_count, 2)
|
||||
_get_iso_name_mock.assert_has_calls(
|
||||
[mock.call(task.node, label='deploy'),
|
||||
mock.call(task.node, label='rescue')])
|
||||
self.assertTrue(_remove_share_file_mock.call_count, 3)
|
||||
_remove_share_file_mock.assert_has_calls(
|
||||
[mock.call(_get_floppy_image_name_mock(task.node)),
|
||||
mock.call(_get_deploy_iso_name_mock(task.node))])
|
||||
mock.call(_get_iso_name_mock(task.node, label='deploy')),
|
||||
mock.call(_get_iso_name_mock(task.node, label='rescue'))])
|
||||
|
||||
@mock.patch.object(ironic_utils, 'unlink_without_raise', spec_set=True,
|
||||
autospec=True)
|
||||
def test__remove_share_file(self, unlink_without_raise_mock):
|
||||
CONF.irmc.remote_image_share_name = '/'
|
||||
CONF.irmc.remote_image_share_root = '/share'
|
||||
|
||||
irmc_boot._remove_share_file("boot.iso")
|
||||
|
||||
unlink_without_raise_mock.assert_called_once_with('/boot.iso')
|
||||
unlink_without_raise_mock.assert_called_once_with('/share/boot.iso')
|
||||
|
||||
@mock.patch.object(irmc_common, 'get_irmc_client', spec_set=True,
|
||||
autospec=True)
|
||||
@ -833,9 +893,18 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
irmc_boot.check_share_fs_mounted_patcher.start()
|
||||
self.addCleanup(irmc_boot.check_share_fs_mounted_patcher.stop)
|
||||
super(IRMCVirtualMediaBootTestCase, self).setUp()
|
||||
mgr_utils.mock_the_extension_manager(driver="iscsi_irmc")
|
||||
self.config(enabled_hardware_types=['irmc'],
|
||||
enabled_boot_interfaces=['irmc-virtual-media'],
|
||||
enabled_console_interfaces=['ipmitool-socat'],
|
||||
enabled_deploy_interfaces=['iscsi'],
|
||||
enabled_inspect_interfaces=['irmc'],
|
||||
enabled_management_interfaces=['irmc'],
|
||||
enabled_power_interfaces=['irmc'],
|
||||
enabled_raid_interfaces=['no-raid'],
|
||||
enabled_rescue_interfaces=['agent'],
|
||||
enabled_vendor_interfaces=['no-vendor'])
|
||||
self.node = obj_utils.create_test_node(
|
||||
self.context, driver='iscsi_irmc', driver_info=INFO_DICT)
|
||||
self.context, driver='irmc', driver_info=INFO_DICT)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'validate_image_properties',
|
||||
spec_set=True, autospec=True)
|
||||
@ -915,14 +984,15 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
|
||||
@mock.patch.object(irmc_management, 'backup_bios_config', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(irmc_boot, '_setup_deploy_iso',
|
||||
@mock.patch.object(irmc_boot, '_setup_vmedia',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'get_single_nic_with_vif_port_id',
|
||||
spec_set=True, autospec=True)
|
||||
def _test_prepare_ramdisk(self,
|
||||
get_single_nic_with_vif_port_id_mock,
|
||||
_setup_deploy_iso_mock,
|
||||
mock_backup_bios):
|
||||
_setup_vmedia_mock,
|
||||
mock_backup_bios,
|
||||
mode='deploy'):
|
||||
instance_info = self.node.instance_info
|
||||
instance_info['irmc_boot_iso'] = 'glance://abcdef'
|
||||
instance_info['image_source'] = '6b2f0c0c-79e8-4db6-842e-43c9764204af'
|
||||
@ -938,8 +1008,8 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
expected_ramdisk_opts = {'a': 'b', 'BOOTIF': '12:34:56:78:90:ab'}
|
||||
get_single_nic_with_vif_port_id_mock.assert_called_once_with(
|
||||
task)
|
||||
_setup_deploy_iso_mock.assert_called_once_with(
|
||||
task, expected_ramdisk_opts)
|
||||
_setup_vmedia_mock.assert_called_once_with(
|
||||
task, mode, expected_ramdisk_opts)
|
||||
self.assertEqual('glance://abcdef',
|
||||
self.node.instance_info['irmc_boot_iso'])
|
||||
provision_state = task.node.provision_state
|
||||
@ -951,12 +1021,17 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
self.node.save()
|
||||
self._test_prepare_ramdisk()
|
||||
|
||||
def test_prepare_ramdisk_glance_image_rescuing(self):
|
||||
self.node.provision_state = states.RESCUING
|
||||
self.node.save()
|
||||
self._test_prepare_ramdisk(mode='rescue')
|
||||
|
||||
def test_prepare_ramdisk_glance_image_cleaning(self):
|
||||
self.node.provision_state = states.CLEANING
|
||||
self.node.save()
|
||||
self._test_prepare_ramdisk()
|
||||
|
||||
@mock.patch.object(irmc_boot, '_setup_deploy_iso', spec_set=True,
|
||||
@mock.patch.object(irmc_boot, '_setup_vmedia', spec_set=True,
|
||||
autospec=True)
|
||||
def test_prepare_ramdisk_not_deploying_not_cleaning(self, mock_is_image):
|
||||
"""Ensure deploy ops are blocked when not deploying and not cleaning"""
|
||||
@ -1037,7 +1112,7 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
task.driver.boot.clean_up_instance(task)
|
||||
|
||||
_remove_share_file_mock.assert_called_once_with(
|
||||
irmc_boot._get_boot_iso_name(task.node))
|
||||
irmc_boot._get_iso_name(task.node, label='boot'))
|
||||
self.assertNotIn('irmc_boot_iso',
|
||||
task.node.driver_internal_info)
|
||||
self.assertNotIn('root_uuid_or_disk_id',
|
||||
@ -1208,6 +1283,35 @@ class IRMCVirtualMediaBootTestCase(db_base.DbTestCase):
|
||||
self.assertFalse(mock_set_secure_boot_mode.called)
|
||||
mock_cleanup_vmedia_boot.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', return_value=True,
|
||||
autospec=True)
|
||||
def test_validate_rescue(self, mock_isfile):
|
||||
driver_info = self.node.driver_info
|
||||
driver_info['irmc_rescue_iso'] = 'rescue.iso'
|
||||
self.node.driver_info = driver_info
|
||||
self.node.save()
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
task.driver.boot.validate_rescue(task)
|
||||
|
||||
def test_validate_rescue_no_rescue_ramdisk(self):
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
self.assertRaisesRegex(exception.MissingParameterValue,
|
||||
'Missing.*irmc_rescue_iso',
|
||||
task.driver.boot.validate_rescue, task)
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', return_value=False,
|
||||
autospec=True)
|
||||
def test_validate_rescue_ramdisk_not_exist(self, mock_isfile):
|
||||
driver_info = self.node.driver_info
|
||||
driver_info['irmc_rescue_iso'] = 'rescue.iso'
|
||||
self.node.driver_info = driver_info
|
||||
self.node.save()
|
||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
||||
self.assertRaisesRegex(exception.InvalidParameterValue,
|
||||
'Rescue ISO file, .*'
|
||||
'not found for node: .*',
|
||||
task.driver.boot.validate_rescue, task)
|
||||
|
||||
|
||||
class IRMCPXEBootTestCase(db_base.DbTestCase):
|
||||
|
||||
|
@ -128,7 +128,8 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
||||
enabled_inspect_interfaces=['irmc'],
|
||||
enabled_management_interfaces=['irmc'],
|
||||
enabled_power_interfaces=['irmc'],
|
||||
enabled_raid_interfaces=['no-raid', 'agent'])
|
||||
enabled_raid_interfaces=['no-raid', 'agent'],
|
||||
enabled_rescue_interfaces=['no-rescue', 'agent'])
|
||||
|
||||
def test_default_interfaces(self):
|
||||
node = obj_utils.create_test_node(self.context, driver='irmc')
|
||||
@ -147,6 +148,8 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
||||
irmc.power.IRMCPower)
|
||||
self.assertIsInstance(task.driver.raid,
|
||||
noop.NoRAID)
|
||||
self.assertIsInstance(task.driver.rescue,
|
||||
noop.NoRescue)
|
||||
|
||||
def test_override_with_inspector(self):
|
||||
self.config(enabled_inspect_interfaces=['inspector', 'irmc'])
|
||||
@ -170,3 +173,29 @@ class IRMCHardwareTestCase(db_base.DbTestCase):
|
||||
irmc.power.IRMCPower)
|
||||
self.assertIsInstance(task.driver.raid,
|
||||
agent.AgentRAID)
|
||||
self.assertIsInstance(task.driver.rescue,
|
||||
noop.NoRescue)
|
||||
|
||||
def test_override_with_agent_rescue(self):
|
||||
node = obj_utils.create_test_node(
|
||||
self.context, driver='irmc',
|
||||
deploy_interface='direct',
|
||||
rescue_interface='agent',
|
||||
raid_interface='agent')
|
||||
with task_manager.acquire(self.context, node.id) as task:
|
||||
self.assertIsInstance(task.driver.boot,
|
||||
irmc.boot.IRMCVirtualMediaBoot)
|
||||
self.assertIsInstance(task.driver.console,
|
||||
ipmitool.IPMISocatConsole)
|
||||
self.assertIsInstance(task.driver.deploy,
|
||||
agent.AgentDeploy)
|
||||
self.assertIsInstance(task.driver.inspect,
|
||||
irmc.inspect.IRMCInspect)
|
||||
self.assertIsInstance(task.driver.management,
|
||||
irmc.management.IRMCManagement)
|
||||
self.assertIsInstance(task.driver.power,
|
||||
irmc.power.IRMCPower)
|
||||
self.assertIsInstance(task.driver.raid,
|
||||
agent.AgentRAID)
|
||||
self.assertIsInstance(task.driver.rescue,
|
||||
agent.AgentRescue)
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for rescue interface ``agent`` for ``irmc`` hardware type
|
||||
when corresponding boot interface is ``irmc-virtual-media``.
|
||||
The supported values of rescue interface for ``irmc`` hardware type
|
||||
are ``agent`` and ``no-rescue``. The default value is ``no-rescue``.
|
Loading…
x
Reference in New Issue
Block a user