Allow usage of virtual media via System
DMTF now changes their Virtual Media URI to support Systems. Redfish driver now support this resource to boot, so it is needed that Ironic have a way to use it. Closes-Bug: #2039458 Change-Id: I66e8edb847e93f96374072525222f05e7561fb07
This commit is contained in:
parent
2f3448a421
commit
6d046ad7b4
@ -167,10 +167,36 @@ def _test_retry(exception):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@tenacity.retry(retry=tenacity.retry_if_exception(_test_retry),
|
def _has_vmedia_via_systems(system):
|
||||||
stop=tenacity.stop_after_attempt(3),
|
"""Indicates if virtual media is available trough Systems
|
||||||
wait=tenacity.wait_fixed(3),
|
|
||||||
reraise=True)
|
:param system: A redfish System object
|
||||||
|
:return: True if the System has virtual media, else False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
system.virtual_media
|
||||||
|
return True
|
||||||
|
except sushy.exceptions.MissingAttributeError:
|
||||||
|
return False
|
||||||
|
except AttributeError:
|
||||||
|
# NOTE(wncslln): In case of older versions of sushy are
|
||||||
|
# used.
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _has_vmedia_via_manager(manager):
|
||||||
|
"""Indicates if virtual media is available in the Manager
|
||||||
|
|
||||||
|
:param manager: A redfish System object
|
||||||
|
:return: True if the System has virtual media, else False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
manager.virtual_media
|
||||||
|
return True
|
||||||
|
except sushy.exceptions.MissingAttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _insert_vmedia(task, managers, boot_url, boot_device):
|
def _insert_vmedia(task, managers, boot_url, boot_device):
|
||||||
"""Insert bootable ISO image into virtual CD or DVD
|
"""Insert bootable ISO image into virtual CD or DVD
|
||||||
|
|
||||||
@ -182,73 +208,105 @@ def _insert_vmedia(task, managers, boot_url, boot_device):
|
|||||||
:raises: InvalidParameterValue, if no suitable virtual CD or DVD is
|
:raises: InvalidParameterValue, if no suitable virtual CD or DVD is
|
||||||
found on the node.
|
found on the node.
|
||||||
"""
|
"""
|
||||||
err_msg = None
|
err_msgs = []
|
||||||
for manager in managers:
|
system = redfish_utils.get_system(task.node)
|
||||||
for v_media in manager.virtual_media.get_members():
|
if _has_vmedia_via_systems(system):
|
||||||
if boot_device not in v_media.media_types:
|
inserted = _insert_vmedia_in_resource(task, system, boot_url,
|
||||||
# NOTE(janders): this conditional allows v_media that only
|
boot_device, err_msgs)
|
||||||
# support DVD MediaType and NOT CD to also be used.
|
if inserted:
|
||||||
# if v_media.media_types contains sushy.VIRTUAL_MEDIA_DVD
|
|
||||||
# we follow the usual steps of checking if v_media is inserted
|
|
||||||
# and if not, attempt to insert it. Otherwise we skip to the
|
|
||||||
# next v_media device, if any
|
|
||||||
# This is needed to add support to Cisco UCSB and UCSX blades
|
|
||||||
# reference: https://bugs.launchpad.net/ironic/+bug/2031595
|
|
||||||
if (boot_device == sushy.VIRTUAL_MEDIA_CD
|
|
||||||
and sushy.VIRTUAL_MEDIA_DVD in v_media.media_types):
|
|
||||||
LOG.debug("While looking for %(requested_device)s virtual "
|
|
||||||
"media device, found %(available_device)s "
|
|
||||||
"instead. Attempting to configure it.",
|
|
||||||
{'requested_device': sushy.VIRTUAL_MEDIA_CD,
|
|
||||||
'available_device': sushy.VIRTUAL_MEDIA_DVD})
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if v_media.inserted:
|
|
||||||
if v_media.image == boot_url:
|
|
||||||
LOG.debug("Boot media %(boot_url)s is already "
|
|
||||||
"inserted into %(boot_device)s for node "
|
|
||||||
"%(node)s", {'node': task.node.uuid,
|
|
||||||
'boot_url': boot_url,
|
|
||||||
'boot_device': boot_device})
|
|
||||||
return
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
v_media.insert_media(boot_url, inserted=True,
|
|
||||||
write_protected=True)
|
|
||||||
# NOTE(janders): On Cisco UCSB and UCSX blades there are several
|
|
||||||
# vMedia devices. Some of those are only meant for internal use
|
|
||||||
# by CIMC vKVM - attempts to InsertMedia into those will result
|
|
||||||
# in BadRequestError. We catch the exception here so that we don't
|
|
||||||
# fail out and try the next available device instead, if available.
|
|
||||||
except sushy.exceptions.BadRequestError:
|
|
||||||
err_msg = ("Inserting virtual media into %(boot_device)s "
|
|
||||||
"failed for node %(node)s, moving to next virtual "
|
|
||||||
"media device, if available",
|
|
||||||
{'node': task.node.uuid,
|
|
||||||
'boot_device': boot_device})
|
|
||||||
LOG.warning(err_msg)
|
|
||||||
continue
|
|
||||||
except sushy.exceptions.ServerSideError as e:
|
|
||||||
e.node_uuid = task.node.uuid
|
|
||||||
raise
|
|
||||||
|
|
||||||
LOG.info("Inserted boot media %(boot_url)s into "
|
|
||||||
"%(boot_device)s for node "
|
|
||||||
"%(node)s", {'node': task.node.uuid,
|
|
||||||
'boot_url': boot_url,
|
|
||||||
'boot_device': boot_device})
|
|
||||||
return
|
return
|
||||||
if (err_msg is not None):
|
else:
|
||||||
|
for manager in managers:
|
||||||
|
inserted = _insert_vmedia_in_resource(task, manager, boot_url,
|
||||||
|
boot_device, err_msgs)
|
||||||
|
if inserted:
|
||||||
|
return
|
||||||
|
|
||||||
|
if err_msgs:
|
||||||
exc_msg = ("All virtual media mount attempts failed. "
|
exc_msg = ("All virtual media mount attempts failed. "
|
||||||
"Most recent error: ", err_msg)
|
"Most recent error: ", err_msgs[-1])
|
||||||
else:
|
else:
|
||||||
exc_msg = 'No suitable virtual media device found'
|
exc_msg = 'No suitable virtual media device found'
|
||||||
raise exception.InvalidParameterValue(exc_msg)
|
raise exception.InvalidParameterValue(exc_msg)
|
||||||
|
|
||||||
|
|
||||||
|
@tenacity.retry(retry=tenacity.retry_if_exception(_test_retry),
|
||||||
|
stop=tenacity.stop_after_attempt(3),
|
||||||
|
wait=tenacity.wait_fixed(3),
|
||||||
|
reraise=True)
|
||||||
|
def _insert_vmedia_in_resource(task, resource, boot_url, boot_device,
|
||||||
|
err_msgs):
|
||||||
|
"""Insert virtual media from a given redfish resource (System/Manager)
|
||||||
|
|
||||||
|
:param task: A task from TaskManager.
|
||||||
|
:param resource: A redfish resource either a System or Manager.
|
||||||
|
:param boot_url: URL to a bootable ISO image
|
||||||
|
:param boot_device: sushy boot device e.g. `VIRTUAL_MEDIA_CD`,
|
||||||
|
`VIRTUAL_MEDIA_DVD` or `VIRTUAL_MEDIA_FLOPPY`
|
||||||
|
:param err_msgs: A list that will contain all errors found
|
||||||
|
:raises: InvalidParameterValue, if no suitable virtual CD or DVD is
|
||||||
|
found on the node.
|
||||||
|
"""
|
||||||
|
for v_media in resource.virtual_media.get_members():
|
||||||
|
if boot_device not in v_media.media_types:
|
||||||
|
# NOTE(janders): this conditional allows v_media that only
|
||||||
|
# support DVD MediaType and NOT CD to also be used.
|
||||||
|
# if v_media.media_types contains sushy.VIRTUAL_MEDIA_DVD
|
||||||
|
# we follow the usual steps of checking if v_media is inserted
|
||||||
|
# and if not, attempt to insert it. Otherwise we skip to the
|
||||||
|
# next v_media device, if any
|
||||||
|
# This is needed to add support to Cisco UCSB and UCSX blades
|
||||||
|
# reference: https://bugs.launchpad.net/ironic/+bug/2031595
|
||||||
|
if (boot_device == sushy.VIRTUAL_MEDIA_CD
|
||||||
|
and sushy.VIRTUAL_MEDIA_DVD in v_media.media_types):
|
||||||
|
LOG.debug("While looking for %(requested_device)s virtual "
|
||||||
|
"media device, found %(available_device)s "
|
||||||
|
"instead. Attempting to configure it.",
|
||||||
|
{'requested_device': sushy.VIRTUAL_MEDIA_CD,
|
||||||
|
'available_device': sushy.VIRTUAL_MEDIA_DVD})
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if v_media.inserted:
|
||||||
|
if v_media.image == boot_url:
|
||||||
|
LOG.debug("Boot media %(boot_url)s is already "
|
||||||
|
"inserted into %(boot_device)s for node "
|
||||||
|
"%(node)s", {'node': task.node.uuid,
|
||||||
|
'boot_url': boot_url,
|
||||||
|
'boot_device': boot_device})
|
||||||
|
return True
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
v_media.insert_media(boot_url, inserted=True,
|
||||||
|
write_protected=True)
|
||||||
|
# NOTE(janders): On Cisco UCSB and UCSX blades there are several
|
||||||
|
# vMedia devices. Some of those are only meant for internal use
|
||||||
|
# by CIMC vKVM - attempts to InsertMedia into those will result
|
||||||
|
# in BadRequestError. We catch the exception here so that we don't
|
||||||
|
# fail out and try the next available device instead, if available.
|
||||||
|
except sushy.exceptions.BadRequestError:
|
||||||
|
err_msg = ("Inserting virtual media into %(boot_device)s "
|
||||||
|
"failed for node %(node)s, moving to next virtual "
|
||||||
|
"media device, if available",
|
||||||
|
{'node': task.node.uuid,
|
||||||
|
'boot_device': boot_device})
|
||||||
|
err_msgs.append(err_msg)
|
||||||
|
LOG.warning(err_msg)
|
||||||
|
continue
|
||||||
|
except sushy.exceptions.ServerSideError as e:
|
||||||
|
e.node_uuid = task.node.uuid
|
||||||
|
raise
|
||||||
|
|
||||||
|
LOG.info("Inserted boot media %(boot_url)s into "
|
||||||
|
"%(boot_device)s for node "
|
||||||
|
"%(node)s", {'node': task.node.uuid,
|
||||||
|
'boot_url': boot_url,
|
||||||
|
'boot_device': boot_device})
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _eject_vmedia(task, managers, boot_device=None):
|
def _eject_vmedia(task, managers, boot_device=None):
|
||||||
"""Eject virtual CDs and DVDs
|
"""Eject virtual CDs and DVDs
|
||||||
|
|
||||||
@ -262,37 +320,66 @@ def _eject_vmedia(task, managers, boot_device=None):
|
|||||||
found on the node.
|
found on the node.
|
||||||
"""
|
"""
|
||||||
found = False
|
found = False
|
||||||
|
system = redfish_utils.get_system(task.node)
|
||||||
|
# NOTE(wncslln): we will attempt to eject virtual media in Systems
|
||||||
|
# and in Managers.
|
||||||
|
if _has_vmedia_via_systems(system):
|
||||||
|
ejected = _eject_vmedia_from_resource(task, resource=system,
|
||||||
|
boot_device=boot_device)
|
||||||
|
if ejected:
|
||||||
|
found = True
|
||||||
|
|
||||||
for manager in managers:
|
for manager in managers:
|
||||||
for v_media in manager.virtual_media.get_members():
|
if _has_vmedia_via_manager(manager):
|
||||||
if boot_device and boot_device not in v_media.media_types:
|
ejected = _eject_vmedia_from_resource(task, resource=manager,
|
||||||
# NOTE(iurygregory): this conditional allows v_media that only
|
boot_device=boot_device)
|
||||||
# support DVD MediaType and NOT CD to also be used.
|
if ejected:
|
||||||
# if v_media.media_types contains sushy.VIRTUAL_MEDIA_DVD
|
|
||||||
# we follow the usual steps of checking if v_media is inserted
|
|
||||||
# and eject it. Otherwise we skip to the
|
|
||||||
# next v_media device, if any.
|
|
||||||
# This is needed to add support to Cisco UCSB and UCSX blades
|
|
||||||
# reference: https://bugs.launchpad.net/ironic/+bug/2039042
|
|
||||||
if (boot_device == sushy.VIRTUAL_MEDIA_CD
|
|
||||||
and sushy.VIRTUAL_MEDIA_DVD in v_media.media_types):
|
|
||||||
LOG.debug('While looking for %(requested_device)s virtual '
|
|
||||||
'media device, found %(available_device)s '
|
|
||||||
'instead. Attempting to use it to eject media.',
|
|
||||||
{'requested_device': sushy.VIRTUAL_MEDIA_CD,
|
|
||||||
'available_device': sushy.VIRTUAL_MEDIA_DVD})
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
inserted = v_media.inserted
|
|
||||||
|
|
||||||
if inserted:
|
|
||||||
v_media.eject_media()
|
|
||||||
found = True
|
found = True
|
||||||
|
continue
|
||||||
|
|
||||||
LOG.info("Boot media is%(already)s ejected from "
|
return found
|
||||||
"%(boot_device)s for node %(node)s"
|
|
||||||
"", {'node': task.node.uuid,
|
|
||||||
'already': '' if inserted else ' already',
|
def _eject_vmedia_from_resource(task, resource, boot_device=None):
|
||||||
'boot_device': v_media.name})
|
"""Eject virtual media from a given redfish resource (System/Manager)
|
||||||
|
|
||||||
|
:param task: A task from TaskManager.
|
||||||
|
:param resource: A redfish resource either a System or Manager.
|
||||||
|
:param boot_device: sushy boot device e.g. `VIRTUAL_MEDIA_CD`,
|
||||||
|
`VIRTUAL_MEDIA_DVD` or `VIRTUAL_MEDIA_FLOPPY` or `None` to
|
||||||
|
eject everything (default).
|
||||||
|
:return: True if any device was ejected, else False
|
||||||
|
"""
|
||||||
|
found = False
|
||||||
|
for v_media in resource.virtual_media.get_members():
|
||||||
|
if boot_device and boot_device not in v_media.media_types:
|
||||||
|
# NOTE(iurygregory): this conditional allows v_media that only
|
||||||
|
# support DVD MediaType and NOT CD to also be used.
|
||||||
|
# if v_media.media_types contains sushy.VIRTUAL_MEDIA_DVD
|
||||||
|
# we follow the usual steps of checking if v_media is inserted
|
||||||
|
# and eject it. Otherwise we skip to the
|
||||||
|
# next v_media device, if any.
|
||||||
|
# This is needed to add support to Cisco UCSB and UCSX blades
|
||||||
|
# reference: https://bugs.launchpad.net/ironic/+bug/2039042
|
||||||
|
if (boot_device == sushy.VIRTUAL_MEDIA_CD
|
||||||
|
and sushy.VIRTUAL_MEDIA_DVD in v_media.media_types):
|
||||||
|
LOG.debug('While looking for %(requested_device)s virtual '
|
||||||
|
'media device, found %(available_device)s '
|
||||||
|
'instead. Attempting to use it to eject media.',
|
||||||
|
{'requested_device': sushy.VIRTUAL_MEDIA_CD,
|
||||||
|
'available_device': sushy.VIRTUAL_MEDIA_DVD})
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
inserted = v_media.inserted
|
||||||
|
if inserted:
|
||||||
|
v_media.eject_media()
|
||||||
|
found = True
|
||||||
|
|
||||||
|
LOG.info("Boot media is%(already)s ejected from "
|
||||||
|
"%(boot_device)s for node %(node)s"
|
||||||
|
"", {'node': task.node.uuid,
|
||||||
|
'already': '' if inserted else ' already',
|
||||||
|
'boot_device': v_media.name})
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
|
||||||
@ -318,8 +405,8 @@ def eject_vmedia(task, boot_device=None):
|
|||||||
image_utils.cleanup_iso_image(task)
|
image_utils.cleanup_iso_image(task)
|
||||||
|
|
||||||
|
|
||||||
def _has_vmedia_device(managers, boot_device, inserted=None):
|
def _has_vmedia_device(managers, boot_device, inserted=None, system=None):
|
||||||
"""Indicate if device exists at any of the managers
|
"""Indicate if device exists at any of the managers or system
|
||||||
|
|
||||||
:param managers: A list of System managers.
|
:param managers: A list of System managers.
|
||||||
:param boot_device: One or more sushy boot device e.g. `VIRTUAL_MEDIA_CD`,
|
:param boot_device: One or more sushy boot device e.g. `VIRTUAL_MEDIA_CD`,
|
||||||
@ -333,14 +420,23 @@ def _has_vmedia_device(managers, boot_device, inserted=None):
|
|||||||
boot_device = [boot_device]
|
boot_device = [boot_device]
|
||||||
|
|
||||||
for dev in boot_device:
|
for dev in boot_device:
|
||||||
for manager in managers:
|
if _has_vmedia_via_systems(system):
|
||||||
for v_media in manager.virtual_media.get_members():
|
for v_media in system.virtual_media.get_members():
|
||||||
if dev not in v_media.media_types:
|
if dev not in v_media.media_types:
|
||||||
continue
|
continue
|
||||||
if (inserted is not None
|
if (inserted is not None
|
||||||
and bool(v_media.inserted) is not inserted):
|
and bool(v_media.inserted) is not inserted):
|
||||||
continue
|
continue
|
||||||
return dev
|
return dev
|
||||||
|
else:
|
||||||
|
for manager in managers:
|
||||||
|
for v_media in manager.virtual_media.get_members():
|
||||||
|
if dev not in v_media.media_types:
|
||||||
|
continue
|
||||||
|
if (inserted is not None
|
||||||
|
and bool(v_media.inserted) is not inserted):
|
||||||
|
continue
|
||||||
|
return dev
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -526,13 +622,14 @@ class RedfishVirtualMediaBoot(base.BootInterface):
|
|||||||
return
|
return
|
||||||
|
|
||||||
d_info = _parse_driver_info(node)
|
d_info = _parse_driver_info(node)
|
||||||
managers = redfish_utils.get_system(task.node).managers
|
system = redfish_utils.get_system(task.node)
|
||||||
|
managers = system.managers
|
||||||
|
|
||||||
self._validate_vendor(task, managers)
|
self._validate_vendor(task, managers)
|
||||||
|
|
||||||
if manager_utils.is_fast_track(task):
|
if manager_utils.is_fast_track(task):
|
||||||
if _has_vmedia_device(managers, sushy.VIRTUAL_MEDIA_CD,
|
if _has_vmedia_device(managers, sushy.VIRTUAL_MEDIA_CD,
|
||||||
inserted=True):
|
inserted=True, system=system):
|
||||||
LOG.debug('Fast track operation for node %s, not inserting '
|
LOG.debug('Fast track operation for node %s, not inserting '
|
||||||
'any devices', node.uuid)
|
'any devices', node.uuid)
|
||||||
return
|
return
|
||||||
@ -570,7 +667,8 @@ class RedfishVirtualMediaBoot(base.BootInterface):
|
|||||||
removable = _has_vmedia_device(
|
removable = _has_vmedia_device(
|
||||||
managers,
|
managers,
|
||||||
# Prefer USB devices since floppies are outdated
|
# Prefer USB devices since floppies are outdated
|
||||||
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY])
|
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY],
|
||||||
|
system=system)
|
||||||
if removable:
|
if removable:
|
||||||
floppy_ref = image_utils.prepare_floppy_image(
|
floppy_ref = image_utils.prepare_floppy_image(
|
||||||
task, params=ramdisk_params)
|
task, params=ramdisk_params)
|
||||||
|
@ -635,7 +635,7 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
||||||
mock__has_vmedia_device, mock_prepare_deploy_iso,
|
mock__has_vmedia_device, mock_prepare_deploy_iso,
|
||||||
mock_prepare_floppy_image, mock_node_set_boot_device):
|
mock_prepare_floppy_image, mock_node_set_boot_device):
|
||||||
|
system = mock_system.return_value
|
||||||
managers = mock_system.return_value.managers
|
managers = mock_system.return_value.managers
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=False) as task:
|
shared=False) as task:
|
||||||
@ -658,7 +658,8 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
mock__has_vmedia_device.assert_called_once_with(
|
mock__has_vmedia_device.assert_called_once_with(
|
||||||
managers,
|
managers,
|
||||||
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY])
|
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY],
|
||||||
|
system=system)
|
||||||
|
|
||||||
eject_calls = [
|
eject_calls = [
|
||||||
mock.call(task, managers, dev)
|
mock.call(task, managers, dev)
|
||||||
@ -708,7 +709,7 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
||||||
mock__has_vmedia_device, mock_prepare_deploy_iso,
|
mock__has_vmedia_device, mock_prepare_deploy_iso,
|
||||||
mock_prepare_floppy_image, mock_node_set_boot_device):
|
mock_prepare_floppy_image, mock_node_set_boot_device):
|
||||||
|
system = mock_system.return_value
|
||||||
managers = mock_system.return_value.managers
|
managers = mock_system.return_value.managers
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=False) as task:
|
shared=False) as task:
|
||||||
@ -731,7 +732,8 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
mock__has_vmedia_device.assert_called_once_with(
|
mock__has_vmedia_device.assert_called_once_with(
|
||||||
managers,
|
managers,
|
||||||
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY])
|
[sushy.VIRTUAL_MEDIA_USBSTICK, sushy.VIRTUAL_MEDIA_FLOPPY],
|
||||||
|
system=system)
|
||||||
|
|
||||||
eject_calls = [
|
eject_calls = [
|
||||||
mock.call(task, managers, dev)
|
mock.call(task, managers, dev)
|
||||||
@ -834,7 +836,7 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
||||||
mock__has_vmedia_device,
|
mock__has_vmedia_device,
|
||||||
mock_prepare_deploy_iso, mock_node_set_boot_device):
|
mock_prepare_deploy_iso, mock_node_set_boot_device):
|
||||||
|
system = mock_system.return_value
|
||||||
managers = mock_system.return_value.managers
|
managers = mock_system.return_value.managers
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=False) as task:
|
shared=False) as task:
|
||||||
@ -844,7 +846,8 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
task.driver.boot.prepare_ramdisk(task, {})
|
task.driver.boot.prepare_ramdisk(task, {})
|
||||||
|
|
||||||
mock__has_vmedia_device.assert_called_once_with(
|
mock__has_vmedia_device.assert_called_once_with(
|
||||||
managers, sushy.VIRTUAL_MEDIA_CD, inserted=True)
|
managers, sushy.VIRTUAL_MEDIA_CD, inserted=True,
|
||||||
|
system=system)
|
||||||
|
|
||||||
mock_node_power_action.assert_not_called()
|
mock_node_power_action.assert_not_called()
|
||||||
mock__eject_vmedia.assert_not_called()
|
mock__eject_vmedia.assert_not_called()
|
||||||
@ -870,7 +873,7 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
mock__parse_driver_info, mock__insert_vmedia, mock__eject_vmedia,
|
||||||
mock__has_vmedia_device,
|
mock__has_vmedia_device,
|
||||||
mock_prepare_deploy_iso, mock_node_set_boot_device):
|
mock_prepare_deploy_iso, mock_node_set_boot_device):
|
||||||
|
system = mock_system.return_value
|
||||||
managers = mock_system.return_value.managers
|
managers = mock_system.return_value.managers
|
||||||
with task_manager.acquire(self.context, self.node.uuid,
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
shared=False) as task:
|
shared=False) as task:
|
||||||
@ -883,7 +886,8 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
task.driver.boot.prepare_ramdisk(task, {})
|
task.driver.boot.prepare_ramdisk(task, {})
|
||||||
|
|
||||||
mock__has_vmedia_device.assert_called_once_with(
|
mock__has_vmedia_device.assert_called_once_with(
|
||||||
managers, sushy.VIRTUAL_MEDIA_CD, inserted=True)
|
managers, sushy.VIRTUAL_MEDIA_CD, inserted=True,
|
||||||
|
system=system)
|
||||||
|
|
||||||
mock_node_power_action.assert_called_once_with(
|
mock_node_power_action.assert_called_once_with(
|
||||||
task, states.POWER_OFF)
|
task, states.POWER_OFF)
|
||||||
@ -1338,10 +1342,13 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock__eject_vmedia.assert_has_calls(eject_calls)
|
mock__eject_vmedia.assert_has_calls(eject_calls)
|
||||||
mock_secure_boot.assert_called_once_with(task)
|
mock_secure_boot.assert_called_once_with(task)
|
||||||
|
|
||||||
def test__insert_vmedia_anew(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew(self, mock_sys, mock_vmd_sys):
|
||||||
|
|
||||||
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:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
@ -1362,8 +1369,10 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
self.assertFalse(mock_vmedia_floppy.insert_media.call_count)
|
self.assertFalse(mock_vmedia_floppy.insert_media.call_count)
|
||||||
|
|
||||||
def test__insert_vmedia_anew_dvd(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew_dvd(self, mock_sys, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_dvd = mock.MagicMock(
|
mock_vmedia_dvd = mock.MagicMock(
|
||||||
@ -1382,8 +1391,10 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
'img-url', inserted=True, write_protected=True)
|
'img-url', inserted=True, write_protected=True)
|
||||||
|
|
||||||
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
def test__insert_vmedia_anew_dvd_retry(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew_dvd_retry(self, mock_sys, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_dvd_1 = mock.MagicMock(
|
mock_vmedia_dvd_1 = mock.MagicMock(
|
||||||
@ -1409,10 +1420,12 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
self.assertEqual(mock_vmedia_dvd_2.insert_media.call_count, 1)
|
self.assertEqual(mock_vmedia_dvd_2.insert_media.call_count, 1)
|
||||||
|
|
||||||
def test__insert_vmedia_already_inserted(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_already_inserted(self, mock_sys, mock_vmd_sys):
|
||||||
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:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=True,
|
inserted=True,
|
||||||
image='img-url',
|
image='img-url',
|
||||||
@ -1428,10 +1441,12 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
self.assertFalse(mock_vmedia_cd.insert_media.call_count)
|
self.assertFalse(mock_vmedia_cd.insert_media.call_count)
|
||||||
|
|
||||||
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
def test__insert_vmedia_while_ejecting(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_while_ejecting(self, mock_sys, mock_vmd_sys):
|
||||||
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:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
image='img-url',
|
image='img-url',
|
||||||
@ -1453,8 +1468,10 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
self.assertEqual(mock_vmedia_cd.insert_media.call_count, 2)
|
self.assertEqual(mock_vmedia_cd.insert_media.call_count, 2)
|
||||||
|
|
||||||
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
def test__insert_vmedia_bad_device(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_bad_device(self, mock_sys, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_floppy = mock.MagicMock(
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
@ -1472,10 +1489,11 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
def test_eject_vmedia_everything(self, mock_redfish_utils,
|
def test_eject_vmedia_everything(self, mock_redfish_utils, mock_vmd_sys,
|
||||||
mock_cleanup_iso, mock_cleanup_disk):
|
mock_cleanup_iso, mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
@ -1507,10 +1525,11 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
def test_eject_vmedia_specific(self, mock_redfish_utils,
|
def test_eject_vmedia_specific(self, mock_redfish_utils, mock_vmd_sys,
|
||||||
mock_cleanup_iso, mock_cleanup_disk):
|
mock_cleanup_iso, mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
@ -1538,14 +1557,16 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
@mock.patch.object(redfish_boot.LOG, 'debug', autospec=True)
|
@mock.patch.object(redfish_boot.LOG, 'debug', autospec=True)
|
||||||
@mock.patch.object(redfish_boot.LOG, 'info', autospec=True)
|
@mock.patch.object(redfish_boot.LOG, 'info', autospec=True)
|
||||||
def test_eject_vmedia_with_dvd_cisco_ucs(self, mock_log_info,
|
def test_eject_vmedia_with_dvd_cisco_ucs(self, mock_log_info,
|
||||||
mock_log_debug,
|
mock_log_debug,
|
||||||
|
mock_vmd_sys,
|
||||||
mock_redfish_utils,
|
mock_redfish_utils,
|
||||||
mock_cleanup_iso,
|
mock_cleanup_iso,
|
||||||
mock_cleanup_disk):
|
mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
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:
|
||||||
mock_vmedia_dvd_1 = mock.MagicMock(
|
mock_vmedia_dvd_1 = mock.MagicMock(
|
||||||
@ -1573,11 +1594,13 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
mock_cleanup_iso.assert_called_once_with(task)
|
mock_cleanup_iso.assert_called_once_with(task)
|
||||||
mock_cleanup_disk.assert_not_called()
|
mock_cleanup_disk.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
def test_eject_vmedia_not_inserted(self, mock_redfish_utils):
|
def test_eject_vmedia_not_inserted(self, mock_redfish_utils, mock_vmd_sys):
|
||||||
|
|
||||||
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:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
@ -1598,11 +1621,13 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
||||||
self.assertFalse(mock_vmedia_floppy.eject_media.call_count)
|
self.assertFalse(mock_vmedia_floppy.eject_media.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
def test_eject_vmedia_unknown(self, mock_redfish_utils):
|
def test_eject_vmedia_unknown(self, mock_redfish_utils, mock_vmd_sys):
|
||||||
|
|
||||||
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:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
@ -1619,7 +1644,9 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
||||||
|
|
||||||
def test__has_vmedia_device(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
def test__has_vmedia_device(self, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
@ -1645,7 +1672,9 @@ class RedfishVirtualMediaBootTestCase(db_base.DbTestCase):
|
|||||||
redfish_boot._has_vmedia_device(
|
redfish_boot._has_vmedia_device(
|
||||||
[mock_manager], sushy.VIRTUAL_MEDIA_USBSTICK))
|
[mock_manager], sushy.VIRTUAL_MEDIA_USBSTICK))
|
||||||
|
|
||||||
def test__has_vmedia_device_inserted(self):
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
def test__has_vmedia_device_inserted(self, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
mock_vmedia_cd = mock.MagicMock(
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
inserted=False,
|
inserted=False,
|
||||||
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
@ -2512,3 +2541,426 @@ class RedfishHTTPBootTestCase(db_base.DbTestCase):
|
|||||||
|
|
||||||
mock_secure_boot.assert_called_once_with(task)
|
mock_secure_boot.assert_called_once_with(task)
|
||||||
mock_cleanup_disk_image.assert_not_called()
|
mock_cleanup_disk_image.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch('oslo_utils.eventletutils.EventletEvent.wait',
|
||||||
|
lambda *args, **kwargs: None)
|
||||||
|
class RedfishVirtualMediaBootViaSystemTestCase(db_base.DbTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(RedfishVirtualMediaBootViaSystemTestCase, self).setUp()
|
||||||
|
self.config(enabled_hardware_types=['redfish'],
|
||||||
|
enabled_power_interfaces=['redfish'],
|
||||||
|
enabled_boot_interfaces=['redfish-virtual-media'],
|
||||||
|
enabled_management_interfaces=['redfish'],
|
||||||
|
enabled_inspect_interfaces=['redfish'],
|
||||||
|
enabled_bios_interfaces=['redfish'])
|
||||||
|
self.node = obj_utils.create_test_node(
|
||||||
|
self.context, driver='redfish', driver_info=INFO_DICT)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew(self, mock_system, mock_vmd_sys):
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system.return_value.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy]
|
||||||
|
|
||||||
|
redfish_boot._insert_vmedia(
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
mock_vmedia_cd.insert_media.assert_called_once_with(
|
||||||
|
'img-url', inserted=True, write_protected=True)
|
||||||
|
|
||||||
|
self.assertFalse(mock_vmedia_floppy.insert_media.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew_dvd(self, mock_system, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_dvd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system.return_value.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_dvd]
|
||||||
|
|
||||||
|
redfish_boot._insert_vmedia(
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
mock_vmedia_dvd.insert_media.assert_called_once_with(
|
||||||
|
'img-url', inserted=True, write_protected=True)
|
||||||
|
|
||||||
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_anew_dvd_retry(self, mock_system, mock_vmd_sys):
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_dvd_1 = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_vmedia_dvd_2 = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
def clear_and_raise(*args, **kwargs):
|
||||||
|
mock_vmedia_dvd_1.insert_media.side_effect = None
|
||||||
|
raise sushy.exceptions.BadRequestError(
|
||||||
|
"POST", 'img-url', mock.MagicMock())
|
||||||
|
mock_vmedia_dvd_1.insert_media.side_effect = clear_and_raise
|
||||||
|
mock_system.return_value.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_dvd_1, mock_vmedia_dvd_2]
|
||||||
|
|
||||||
|
redfish_boot._insert_vmedia(
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
self.assertEqual(mock_vmedia_dvd_2.insert_media.call_count, 1)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_already_inserted(self, mock_sys, mock_vmd_sys):
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = False
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
image='img-url',
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_manager.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd]
|
||||||
|
|
||||||
|
redfish_boot._insert_vmedia(
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
self.assertFalse(mock_vmedia_cd.insert_media.call_count)
|
||||||
|
|
||||||
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_while_ejecting(self, mock_system, mock_vmd_sys):
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
image='img-url',
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD],
|
||||||
|
)
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
def clear_and_raise(*args, **kwargs):
|
||||||
|
mock_vmedia_cd.insert_media.side_effect = None
|
||||||
|
raise sushy.exceptions.ServerSideError(
|
||||||
|
"POST", 'img-url', mock.MagicMock())
|
||||||
|
mock_vmedia_cd.insert_media.side_effect = clear_and_raise
|
||||||
|
mock_system.return_value.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd]
|
||||||
|
|
||||||
|
redfish_boot._insert_vmedia(
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
self.assertEqual(mock_vmedia_cd.insert_media.call_count, 2)
|
||||||
|
|
||||||
|
@mock.patch('time.sleep', lambda *args, **kwargs: None)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
|
||||||
|
def test__insert_vmedia_bad_device(self, mock_sys, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_floppy]
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InvalidParameterValue,
|
||||||
|
redfish_boot._insert_vmedia,
|
||||||
|
task, [mock_manager], 'img-url', sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
def test_eject_vmedia_everything(self, mock_redfish_utils, mock_vmd_sys,
|
||||||
|
mock_cleanup_iso, mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
mock_vmedia_dvd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value = mock_system
|
||||||
|
mock_system.managers = [
|
||||||
|
mock_manager]
|
||||||
|
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy, mock_vmedia_dvd]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task)
|
||||||
|
|
||||||
|
mock_vmedia_cd.eject_media.assert_called_once_with()
|
||||||
|
mock_vmedia_floppy.eject_media.assert_called_once_with()
|
||||||
|
mock_vmedia_dvd.eject_media.assert_called_once_with()
|
||||||
|
mock_cleanup_iso.assert_called_once_with(task)
|
||||||
|
mock_cleanup_disk.assert_called_once_with(task,
|
||||||
|
prefix='configdrive')
|
||||||
|
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_manager', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
def test_eject_vmedia_from_all_resources(self, mock_redfish_utils,
|
||||||
|
mock_vmd_sys, mock_vmd_mg,
|
||||||
|
mock_cleanup_iso,
|
||||||
|
mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmd_mg.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
mock_vmedia_dvd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value = mock_system
|
||||||
|
mock_system.managers = [
|
||||||
|
mock_manager]
|
||||||
|
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_floppy, mock_vmedia_dvd]
|
||||||
|
mock_manager.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task)
|
||||||
|
|
||||||
|
mock_vmedia_cd.eject_media.assert_called_once_with()
|
||||||
|
mock_vmedia_floppy.eject_media.assert_called_once_with()
|
||||||
|
mock_vmedia_dvd.eject_media.assert_called_once_with()
|
||||||
|
mock_cleanup_iso.assert_called_once_with(task)
|
||||||
|
mock_cleanup_disk.assert_called_once_with(task,
|
||||||
|
prefix='configdrive')
|
||||||
|
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
def test_eject_vmedia_specific(self, mock_redfish_utils, mock_vmd_sys,
|
||||||
|
mock_cleanup_iso, mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value = mock_system
|
||||||
|
mock_system.managers = [
|
||||||
|
mock_manager]
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task, sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
mock_vmedia_cd.eject_media.assert_called_once_with()
|
||||||
|
self.assertFalse(mock_vmedia_floppy.eject_media.call_count)
|
||||||
|
mock_cleanup_iso.assert_called_once_with(task)
|
||||||
|
mock_cleanup_disk.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_disk_image', autospec=True)
|
||||||
|
@mock.patch.object(image_utils, 'cleanup_iso_image', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot.LOG, 'debug', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot.LOG, 'info', autospec=True)
|
||||||
|
def test_eject_vmedia_with_dvd_cisco_ucs(self, mock_log_info,
|
||||||
|
mock_log_debug,
|
||||||
|
mock_vmd_sys,
|
||||||
|
mock_redfish_utils,
|
||||||
|
mock_cleanup_iso,
|
||||||
|
mock_cleanup_disk):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmedia_dvd_1 = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
mock_vmedia_dvd_2 = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_DVD])
|
||||||
|
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value = mock_system
|
||||||
|
mock_system.managers = [
|
||||||
|
mock_manager]
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_dvd_1, mock_vmedia_dvd_2]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task, sushy.VIRTUAL_MEDIA_CD)
|
||||||
|
|
||||||
|
mock_vmedia_dvd_1.eject_media.assert_called_once_with()
|
||||||
|
mock_vmedia_dvd_2.eject_media.assert_called_once_with()
|
||||||
|
|
||||||
|
self.assertEqual(mock_log_info.call_count, 2)
|
||||||
|
self.assertEqual(mock_log_debug.call_count, 3)
|
||||||
|
mock_cleanup_iso.assert_called_once_with(task)
|
||||||
|
mock_cleanup_disk.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
def test_eject_vmedia_not_inserted(self, mock_redfish_utils, mock_vmd_sys):
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy]
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value.managers = [
|
||||||
|
mock_manager]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task)
|
||||||
|
|
||||||
|
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
||||||
|
self.assertFalse(mock_vmedia_floppy.eject_media.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
@mock.patch.object(redfish_boot, 'redfish_utils', autospec=True)
|
||||||
|
def test_eject_vmedia_unknown(self, mock_redfish_utils, mock_vmd_sys):
|
||||||
|
|
||||||
|
with task_manager.acquire(self.context, self.node.uuid,
|
||||||
|
shared=True) as task:
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd]
|
||||||
|
|
||||||
|
mock_redfish_utils.get_system.return_value.managers = [
|
||||||
|
mock_manager]
|
||||||
|
|
||||||
|
redfish_boot.eject_vmedia(task)
|
||||||
|
|
||||||
|
self.assertFalse(mock_vmedia_cd.eject_media.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
def test__has_vmedia_device(self, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
sushy.VIRTUAL_MEDIA_CD,
|
||||||
|
redfish_boot._has_vmedia_device(
|
||||||
|
[mock_manager], sushy.VIRTUAL_MEDIA_CD,
|
||||||
|
system=mock_system))
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
redfish_boot._has_vmedia_device(
|
||||||
|
[mock_manager], sushy.VIRTUAL_MEDIA_CD,
|
||||||
|
inserted=True, system=mock_system))
|
||||||
|
|
||||||
|
self.assertFalse(
|
||||||
|
redfish_boot._has_vmedia_device(
|
||||||
|
[mock_manager], sushy.VIRTUAL_MEDIA_USBSTICK,
|
||||||
|
system=mock_system))
|
||||||
|
|
||||||
|
@mock.patch.object(redfish_boot, '_has_vmedia_via_systems', autospec=True)
|
||||||
|
def test__has_vmedia_device_inserted(self, mock_vmd_sys):
|
||||||
|
mock_vmd_sys.return_value = True
|
||||||
|
mock_vmedia_cd = mock.MagicMock(
|
||||||
|
inserted=False,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_CD])
|
||||||
|
mock_vmedia_floppy = mock.MagicMock(
|
||||||
|
inserted=True,
|
||||||
|
media_types=[sushy.VIRTUAL_MEDIA_FLOPPY])
|
||||||
|
|
||||||
|
mock_manager = mock.MagicMock()
|
||||||
|
mock_system = mock.MagicMock()
|
||||||
|
mock_system.virtual_media.get_members.return_value = [
|
||||||
|
mock_vmedia_cd, mock_vmedia_floppy]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
sushy.VIRTUAL_MEDIA_FLOPPY,
|
||||||
|
redfish_boot._has_vmedia_device(
|
||||||
|
[mock_manager], sushy.VIRTUAL_MEDIA_FLOPPY,
|
||||||
|
inserted=True, system=mock_system))
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes Redfish virtual media boot on BMCs that only expose the VirtualMedia
|
||||||
|
resource on Systems instead of Managers. For more informations, you can see
|
||||||
|
`bug 2039458 <https://bugs.launchpad.net/sushy/+bug/2039458>`_.
|
@ -46,6 +46,6 @@ psutil>=3.2.2 # BSD
|
|||||||
futurist>=1.2.0 # Apache-2.0
|
futurist>=1.2.0 # Apache-2.0
|
||||||
tooz>=2.7.0 # Apache-2.0
|
tooz>=2.7.0 # Apache-2.0
|
||||||
openstacksdk>=0.48.0 # Apache-2.0
|
openstacksdk>=0.48.0 # Apache-2.0
|
||||||
sushy>=4.7.0
|
sushy>=4.8.0
|
||||||
construct>=2.9.39 # MIT
|
construct>=2.9.39 # MIT
|
||||||
netaddr>=0.9.0 # BSD
|
netaddr>=0.9.0 # BSD
|
||||||
|
Loading…
Reference in New Issue
Block a user