Merge "Allow usage of virtual media via System"
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -333,8 +420,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`,
|
||||||
@@ -348,14 +435,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
|
||||||
|
|
||||||
|
|
||||||
@@ -541,13 +637,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
|
||||||
@@ -585,7 +682,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
|
||||||
|
Reference in New Issue
Block a user