Merge "Use an ImageCache for provided boot/deploy ISO images"
This commit is contained in:
commit
b33783281b
@ -92,14 +92,6 @@ For example,
|
||||
--instance-info boot_iso=http://path/to/boot.iso
|
||||
baremetal node deploy <NODE>
|
||||
|
||||
By default the Bare Metal service will cache the ISO locally and serve from its
|
||||
HTTP server. If you want to avoid that, set the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
baremetal node set <NODE> \
|
||||
--instance-info ramdisk_image_download_source=http
|
||||
|
||||
.. warning::
|
||||
This feature, when utilized with the ``ipxe`` ``boot_interface``,
|
||||
will only allow a kernel and ramdisk to be booted from the
|
||||
@ -113,6 +105,18 @@ HTTP server. If you want to avoid that, set the following:
|
||||
This is a limitation of iPXE and the overall boot process of the
|
||||
operating system where memory allocated by iPXE is released.
|
||||
|
||||
By default the Bare Metal service will cache the ISO locally and serve from its
|
||||
HTTP server. If you want to avoid that, set the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
baremetal node set <NODE> \
|
||||
--instance-info ramdisk_image_download_source=http
|
||||
|
||||
ISO images are also cached across deployments, similarly to how it is done for
|
||||
normal instance images. The URL together with the last modified response header
|
||||
are used to determine if an image needs updating.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
|
@ -212,6 +212,21 @@ opts = [
|
||||
'url directly, or if ironic should cache the image on '
|
||||
'the conductor and serve it from ironic\'s own http '
|
||||
'server.')),
|
||||
cfg.StrOpt('iso_master_path',
|
||||
default='/var/lib/ironic/master_iso_images',
|
||||
help=_('On the ironic-conductor node, directory where master '
|
||||
'ISO images are stored on disk. '
|
||||
'Setting to the empty string disables image caching.')),
|
||||
cfg.IntOpt('iso_cache_size',
|
||||
default=20480,
|
||||
help=_('Maximum size (in MiB) of cache for master ISO images, '
|
||||
'including those in use.')),
|
||||
# 10080 here is 1 week - 60*24*7. It is entirely arbitrary in the absence
|
||||
# of a facility to disable the ttl entirely.
|
||||
cfg.IntOpt('iso_cache_ttl',
|
||||
default=10080,
|
||||
help=_('Maximum TTL (in minutes) for old master ISO images in '
|
||||
'cache.')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ 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
|
||||
from ironic.drivers.modules import image_cache
|
||||
from ironic.drivers import utils as driver_utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
@ -226,6 +227,19 @@ class ImageHandler(object):
|
||||
return image_url
|
||||
|
||||
|
||||
@image_cache.cleanup(priority=75)
|
||||
class ISOImageCache(image_cache.ImageCache):
|
||||
|
||||
def __init__(self):
|
||||
master_path = CONF.deploy.iso_master_path or None
|
||||
super(self.__class__, self).__init__(
|
||||
master_path,
|
||||
# MiB -> B
|
||||
cache_size=CONF.deploy.iso_cache_size * 1024 * 1024,
|
||||
# min -> sec
|
||||
cache_ttl=CONF.deploy.iso_cache_ttl * 60)
|
||||
|
||||
|
||||
def _get_name(node, prefix='', suffix=''):
|
||||
"""Get an object name for a given node.
|
||||
|
||||
@ -467,10 +481,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href,
|
||||
|
||||
boot_mode = boot_mode_utils.get_boot_mode(task.node)
|
||||
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=CONF.tempdir, suffix='.iso') as boot_fileobj:
|
||||
with tempfile.TemporaryDirectory(dir=CONF.tempdir) as boot_file_dir:
|
||||
|
||||
boot_iso_tmp_file = boot_fileobj.name
|
||||
boot_iso_tmp_file = os.path.join(boot_file_dir, 'boot.iso')
|
||||
if base_iso:
|
||||
# NOTE(dtantsur): this should be "params or inject_files", but
|
||||
# params are always populated in the calling code.
|
||||
@ -479,7 +492,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href,
|
||||
'%(node)s, custom configuration will not be available',
|
||||
{'boot_mode': boot_mode, 'node': task.node.uuid,
|
||||
'iso': base_iso})
|
||||
images.fetch_into(task.context, base_iso, boot_iso_tmp_file)
|
||||
|
||||
ISOImageCache().fetch_image(base_iso, boot_iso_tmp_file,
|
||||
ctx=task.context, force_raw=False)
|
||||
else:
|
||||
if is_ramdisk_boot:
|
||||
kernel_params = "root=/dev/ram0 text "
|
||||
|
@ -671,10 +671,10 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
|
||||
|
||||
@mock.patch.object(image_utils.ImageHandler, 'publish_image',
|
||||
autospec=True)
|
||||
@mock.patch.object(images, 'fetch_into', autospec=True)
|
||||
@mock.patch.object(image_utils, 'ISOImageCache', autospec=True)
|
||||
@mock.patch.object(images, 'create_boot_iso', autospec=True)
|
||||
def test__prepare_iso_image_bootable_iso_file(self, mock_create_boot_iso,
|
||||
mock_fetch,
|
||||
mock_cache,
|
||||
mock_publish_image):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=True) as task:
|
||||
@ -684,8 +684,8 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
|
||||
task, 'http://kernel/img', 'http://ramdisk/img',
|
||||
bootloader_href=None, root_uuid=task.node.uuid,
|
||||
base_iso=base_image_url)
|
||||
mock_fetch.assert_called_once_with(task.context,
|
||||
base_image_url, mock.ANY)
|
||||
mock_cache.return_value.fetch_image.assert_called_once_with(
|
||||
base_image_url, mock.ANY, ctx=task.context, force_raw=False)
|
||||
mock_create_boot_iso.assert_not_called()
|
||||
|
||||
@mock.patch.object(images, 'get_temp_url_for_glance_image',
|
||||
|
7
releasenotes/notes/iso-cache-5330b63c9e3a02db.yaml
Normal file
7
releasenotes/notes/iso-cache-5330b63c9e3a02db.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
ISO images provided via ``instance_info/boot_iso`` or
|
||||
`instance_info/deploy_iso`` are now cached in a similar way to normal
|
||||
instance images. Set ``[deploy]iso_master_path`` to an empty string
|
||||
to disable.
|
Loading…
x
Reference in New Issue
Block a user