redfish-virtual-media: allow a link to raw configdrive image
For historical reasons we always base64+gzip configdrives, even when accessing them via a URL. This change allows binary images to work for the redfish-virtual-media case. Change-Id: If19144de800b67275e3f8fb297f0a5c4a54b2981
This commit is contained in:
parent
5640860c81
commit
bb318008b9
doc/source/admin/drivers
ironic
@ -272,7 +272,19 @@ 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.
|
||||
for nodes that have a free virtual USB slot:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
baremetal node deploy <node name or UUID> \
|
||||
--config-drive '{"meta_data": {...}, "user_data": "..."}'
|
||||
|
||||
or via a link to a raw image:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
baremetal node deploy <node name or UUID> \
|
||||
--config-drive http://example.com/config.img
|
||||
|
||||
Layer 3 or DHCP-less ramdisk booting
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -580,3 +580,9 @@ def wrap_ipv6(ip):
|
||||
if ipaddress.ip_address(ip).version == 6:
|
||||
return "[%s]" % ip
|
||||
return ip
|
||||
|
||||
|
||||
def file_mime_type(path):
|
||||
"""Gets a mime type of the given file."""
|
||||
return execute('file', '--brief', '--mime-type', path,
|
||||
use_standard_locale=True)[0].strip()
|
||||
|
@ -29,6 +29,7 @@ from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import images
|
||||
from ironic.common import swift
|
||||
from ironic.common import utils
|
||||
from ironic.conf import CONF
|
||||
from ironic.drivers.modules import boot_mode_utils
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
@ -311,10 +312,17 @@ def prepare_configdrive_image(task, content):
|
||||
"""
|
||||
with tempfile.TemporaryFile(dir=CONF.tempdir) as comp_tmpfile_obj:
|
||||
if '://' in content:
|
||||
with tempfile.TemporaryFile(dir=CONF.tempdir) as tmpfile2:
|
||||
with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as tmpfile2:
|
||||
images.fetch_into(task.context, content, tmpfile2)
|
||||
tmpfile2.seek(0)
|
||||
base64.decode(tmpfile2, comp_tmpfile_obj)
|
||||
tmpfile2.flush()
|
||||
|
||||
if utils.file_mime_type(tmpfile2.name) == "text/plain":
|
||||
tmpfile2.seek(0)
|
||||
base64.decode(tmpfile2, comp_tmpfile_obj)
|
||||
else:
|
||||
# A binary image, use it as it is.
|
||||
return prepare_disk_image(task, tmpfile2.name,
|
||||
prefix='configdrive')
|
||||
else:
|
||||
comp_tmpfile_obj.write(base64.b64decode(content))
|
||||
comp_tmpfile_obj.seek(0)
|
||||
|
@ -20,6 +20,7 @@ from unittest import mock
|
||||
from oslo_utils import importutils
|
||||
|
||||
from ironic.common import images
|
||||
from ironic.common import utils
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.drivers.modules import image_utils
|
||||
from ironic.tests.unit.db import base as db_base
|
||||
@ -304,9 +305,11 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
|
||||
result = image_utils.prepare_configdrive_image(task, encoded)
|
||||
self.assertEqual(expected_url, result)
|
||||
|
||||
@mock.patch.object(utils, 'execute', autospec=True)
|
||||
@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):
|
||||
def test_prepare_configdrive_image_url(self, mock_prepare, mock_fetch,
|
||||
mock_execute):
|
||||
content = 'https://swift/path'
|
||||
expected_url = 'https://a.b/c.f?e=f'
|
||||
encoded = b'H4sIAPJ8418C/0vOzytJzSsBAKkwxf4HAAAA'
|
||||
@ -322,6 +325,33 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
|
||||
|
||||
mock_fetch.side_effect = _fetch
|
||||
mock_prepare.side_effect = _prepare
|
||||
mock_execute.return_value = 'text/plain', ''
|
||||
|
||||
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(utils, 'execute', autospec=True)
|
||||
@mock.patch.object(images, 'fetch_into', autospec=True)
|
||||
@mock.patch.object(image_utils, 'prepare_disk_image', autospec=True)
|
||||
def test_prepare_configdrive_image_binary_url(self, mock_prepare,
|
||||
mock_fetch, mock_execute):
|
||||
content = 'https://swift/path'
|
||||
expected_url = 'https://a.b/c.f?e=f'
|
||||
|
||||
def _fetch(context, image_href, image_file):
|
||||
self.assertEqual(content, image_href)
|
||||
image_file.write(b'content')
|
||||
|
||||
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
|
||||
mock_execute.return_value = 'application/octet-stream'
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
|
Loading…
x
Reference in New Issue
Block a user