Merge "Follow-up for ramdisk deploy configdrive support"

This commit is contained in:
Zuul 2021-01-21 14:06:14 +00:00 committed by Gerrit Code Review
commit 5640860c81
7 changed files with 55 additions and 19 deletions

View File

@ -272,8 +272,7 @@ parameter injection, as such the ``[instance_info]/kernel_append_params``
setting is ignored.
Configuration drives are supported starting with the Wallaby release
for nodes that have a free virtual USB slot. The configuration option
``[deploy]configdrive_use_object_store`` must be set to ``False`` for now.
for nodes that have a free virtual USB slot.
Layer 3 or DHCP-less ramdisk booting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -346,7 +346,7 @@ def create_esp_image_for_uefi(
raise exception.ImageCreationFailed(image_type='iso', error=e)
def fetch(context, image_href, path, force_raw=False):
def fetch_into(context, image_href, image_file):
# TODO(vish): Improve context handling and add owner and auth data
# when it is added to glance. Right now there is no
# auth checking in glance, so we assume that access was
@ -357,9 +357,13 @@ def fetch(context, image_href, path, force_raw=False):
{'image_service': image_service.__class__,
'image_href': image_href})
image_service.download(image_href, image_file)
def fetch(context, image_href, path, force_raw=False):
with fileutils.remove_path_on_error(path):
with open(path, "wb") as image_file:
image_service.download(image_href, image_file)
fetch_into(context, image_href, image_file)
if force_raw:
image_to_raw(image_href, path, "%s.part" % path)

View File

@ -299,20 +299,26 @@ def cleanup_floppy_image(task):
def prepare_configdrive_image(task, content):
"""Prepare an image with configdrive.
Decodes base64 contents and writes it into a disk image that can be
attached e.g. to a virtual USB device. Images stored in Swift are
downloaded first.
:param task: a TaskManager instance containing the node to act on.
:param content: Config drive as a base64-encoded string.
:raises: ImageCreationFailed, if it failed while creating the image.
:raises: SwiftOperationError, if any operation with Swift fails.
:returns: image URL for the image.
"""
# FIXME(dtantsur): download and convert?
if '://' in content:
raise exception.ImageCreationFailed(
_('URLs are not supported for configdrive images yet'))
with tempfile.TemporaryFile(dir=CONF.tempdir) as comp_tmpfile_obj:
comp_tmpfile_obj.write(base64.b64decode(content))
if '://' in content:
with tempfile.TemporaryFile(dir=CONF.tempdir) as tmpfile2:
images.fetch_into(task.context, content, tmpfile2)
tmpfile2.seek(0)
base64.decode(tmpfile2, comp_tmpfile_obj)
else:
comp_tmpfile_obj.write(base64.b64decode(content))
comp_tmpfile_obj.seek(0)
gz = gzip.GzipFile(fileobj=comp_tmpfile_obj, mode='rb')
with tempfile.NamedTemporaryFile(
dir=CONF.tempdir, suffix='.img') as image_tmpfile_obj:

View File

@ -58,12 +58,15 @@ class PXERamdiskDeploy(agent_base.AgentBaseMixin, agent_base.HeartbeatMixin,
@base.deploy_step(priority=100)
@task_manager.require_exclusive_lock
def deploy(self, task):
if 'configdrive' in task.node.instance_info:
LOG.warning('A configuration drive is present with '
'in the deployment request of node %(node)s. '
'The configuration drive will be ignored for '
'this deployment.',
{'node': task.node})
if ('configdrive' in task.node.instance_info
and 'ramdisk_boot_configdrive' not in
task.driver.boot.capabilities):
# TODO(dtantsur): make it an actual error?
LOG.warning('A configuration drive is present in the ramdisk '
'deployment request of node %(node)s with boot '
'interface %(drv)s. The configuration drive will be '
'ignored for this deployment.',
{'node': task.node, 'drv': task.node.boot_interface})
manager_utils.node_power_action(task, states.POWER_OFF)
# Tenant neworks must enable connectivity to the boot
# location, as reboot() can otherwise be very problematic.

View File

@ -308,7 +308,8 @@ class RedfishVirtualMediaBoot(base.BootInterface):
`[instance_info]image_source` node property.
"""
capabilities = ['iscsi_volume_boot', 'ramdisk_boot']
capabilities = ['iscsi_volume_boot', 'ramdisk_boot',
'ramdisk_boot_configdrive']
def __init__(self):
"""Initialize the Redfish virtual media boot interface.

View File

@ -304,6 +304,30 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
result = image_utils.prepare_configdrive_image(task, encoded)
self.assertEqual(expected_url, result)
@mock.patch.object(images, 'fetch_into', autospec=True)
@mock.patch.object(image_utils, 'prepare_disk_image', autospec=True)
def test_prepare_configdrive_image_url(self, mock_prepare, mock_fetch):
content = 'https://swift/path'
expected_url = 'https://a.b/c.f?e=f'
encoded = b'H4sIAPJ8418C/0vOzytJzSsBAKkwxf4HAAAA'
def _fetch(context, image_href, image_file):
self.assertEqual(content, image_href)
image_file.write(encoded)
def _prepare(task, content, prefix):
with open(content, 'rb') as fp:
self.assertEqual(b'content', fp.read())
return expected_url
mock_fetch.side_effect = _fetch
mock_prepare.side_effect = _prepare
with task_manager.acquire(self.context, self.node.uuid,
shared=True) as task:
result = image_utils.prepare_configdrive_image(task, content)
self.assertEqual(expected_url, result)
@mock.patch.object(image_utils.ImageHandler, 'unpublish_image',
autospec=True)
def test_cleanup_iso_image(self, mock_unpublish):

View File

@ -3,5 +3,4 @@ features:
- |
Supports attaching configdrives when doing ``ramdisk`` deploy with the
``redfish-virtual-media`` boot. A configdrive is attached to a free USB
slot. Swift must not be used for configdrive storage (this limitation will
be fixed later).
slot.