only safety check bootable files created from glance
For blank files that are created by nova such as swap disks and ephemeral disks we do not need need to safety check them as they always are just bare filesystems. In the future we should refactor the qcow imagebackend to not require backing files for swap and ephemeral disks but for now we simply disable the check to workaround the addition of the gpt image inspector and the incompatiblity with vfat. future versions of oslo will account for vfat boot recored. this is a minimal patch to avoid needing a new oslo release for 2024.2 Closes-Bug: #2079850 Change-Id: I7df3d9859aa4be3a012ff919f375a7a3d9992af4
This commit is contained in:
parent
e310049eab
commit
8de15e9a27
nova
tests
fixtures
functional/regressions
unit/virt/libvirt
virt/libvirt
4
nova/tests/fixtures/libvirt_imagebackend.py
vendored
4
nova/tests/fixtures/libvirt_imagebackend.py
vendored
@ -215,7 +215,9 @@ class LibvirtImageBackendFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
return image_init
|
return image_init
|
||||||
|
|
||||||
def _fake_cache(self, fetch_func, filename, size=None, *args, **kwargs):
|
def _fake_cache(
|
||||||
|
self, fetch_func, filename, size=None, safe=False, *args,
|
||||||
|
**kwargs):
|
||||||
# Execute the template function so we can test the arguments it was
|
# Execute the template function so we can test the arguments it was
|
||||||
# called with.
|
# called with.
|
||||||
fetch_func(target=filename, *args, **kwargs)
|
fetch_func(target=filename, *args, **kwargs)
|
||||||
|
@ -3,6 +3,8 @@ import functools
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
|
|
||||||
from oslo_utils.fixture import uuidsentinel as uuids
|
from oslo_utils.fixture import uuidsentinel as uuids
|
||||||
@ -11,7 +13,6 @@ from oslo_utils import units
|
|||||||
|
|
||||||
import nova.conf
|
import nova.conf
|
||||||
|
|
||||||
from nova import exception
|
|
||||||
from nova import objects
|
from nova import objects
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.virt.libvirt import driver
|
from nova.virt.libvirt import driver
|
||||||
@ -53,17 +54,16 @@ class TestBugBackingFilePartitionTables(test.NoDBTestCase):
|
|||||||
file_path = os.path.join(self.base_dir.path, 'test_file')
|
file_path = os.path.join(self.base_dir.path, 'test_file')
|
||||||
libvirt_utils.create_image(file_path, 'raw', '64M')
|
libvirt_utils.create_image(file_path, 'raw', '64M')
|
||||||
self.assertTrue(os.path.exists(file_path))
|
self.assertTrue(os.path.exists(file_path))
|
||||||
# nova should ensure that any file we create has a partition table
|
# FIXME(sean-k-mooney): oslo currently detect vfat as an mbr partition
|
||||||
# inspector = format_inspector.GPTInspector.from_file(file_path)
|
|
||||||
# self.assertIsNotNone(inspector)
|
|
||||||
# inspector.safety_check()
|
|
||||||
|
|
||||||
# however the libvirt_utils.create_image method does not create a
|
|
||||||
# partition table so we should expect this to fail
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
format_inspector.ImageFormatError,
|
format_inspector.ImageFormatError,
|
||||||
format_inspector.GPTInspector.from_file, file_path)
|
format_inspector.GPTInspector.from_file, file_path)
|
||||||
|
|
||||||
|
# nova files should pass the RawFileInspector safety check
|
||||||
|
inspector = format_inspector.RawFileInspector.from_file(file_path)
|
||||||
|
self.assertIsNotNone(inspector)
|
||||||
|
inspector.safety_check()
|
||||||
|
|
||||||
def test_cache_file(self):
|
def test_cache_file(self):
|
||||||
"""Test the qcow2 cache interaction for ephemeral disks
|
"""Test the qcow2 cache interaction for ephemeral disks
|
||||||
|
|
||||||
@ -85,8 +85,11 @@ class TestBugBackingFilePartitionTables(test.NoDBTestCase):
|
|||||||
os_type=None, is_block_dev=False)
|
os_type=None, is_block_dev=False)
|
||||||
# this need to be multiples of 1G
|
# this need to be multiples of 1G
|
||||||
size = 1 * units.Gi
|
size = 1 * units.Gi
|
||||||
fname = "ephemeral_%s_%s" % (size, ".qcow")
|
fname = "ephemeral_%s_%s" % (size, ".img")
|
||||||
e = self.assertRaises(exception.InvalidDiskInfo,
|
with mock.patch.object(
|
||||||
image.cache, fetch_func=fn, context=None, filename=fname,
|
imagebackend, '_update_utime_ignore_eacces') as m:
|
||||||
size=size, ephemeral_size=1)
|
|
||||||
self.assertIn("Base image failed safety check", str(e))
|
image.cache(
|
||||||
|
fetch_func=fn, context=None, filename=fname,
|
||||||
|
size=size, ephemeral_size=1, safe=True)
|
||||||
|
m.assert_called_once()
|
||||||
|
@ -14903,6 +14903,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
'qcow2',
|
'qcow2',
|
||||||
virt_disk_size,
|
virt_disk_size,
|
||||||
backing_file=backfile_path,
|
backing_file=backfile_path,
|
||||||
|
safe=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch('nova.virt.libvirt.imagebackend.Image.exists',
|
@mock.patch('nova.virt.libvirt.imagebackend.Image.exists',
|
||||||
@ -15054,12 +15055,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
'qcow2',
|
'qcow2',
|
||||||
disk_info_byname['disk']['virt_disk_size'],
|
disk_info_byname['disk']['virt_disk_size'],
|
||||||
backing_file=root_backing,
|
backing_file=root_backing,
|
||||||
|
safe=False
|
||||||
),
|
),
|
||||||
mock.call(
|
mock.call(
|
||||||
CONF.instances_path + '/disk.local',
|
CONF.instances_path + '/disk.local',
|
||||||
'qcow2',
|
'qcow2',
|
||||||
disk_info_byname['disk.local']['virt_disk_size'],
|
disk_info_byname['disk.local']['virt_disk_size'],
|
||||||
backing_file=ephemeral_backing,
|
backing_file=ephemeral_backing,
|
||||||
|
safe=True
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -16626,7 +16629,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
context=self.context)
|
context=self.context)
|
||||||
backend.disks['disk.swap'].cache.assert_called_once_with(
|
backend.disks['disk.swap'].cache.assert_called_once_with(
|
||||||
fetch_func=mock.ANY, filename='swap_%i' % expected,
|
fetch_func=mock.ANY, filename='swap_%i' % expected,
|
||||||
size=expected * units.Mi, context=self.context, swap_mb=expected)
|
size=expected * units.Mi, context=self.context, swap_mb=expected,
|
||||||
|
safe=True)
|
||||||
|
|
||||||
@mock.patch.object(nova.virt.libvirt.imagebackend.Image, 'cache')
|
@mock.patch.object(nova.virt.libvirt.imagebackend.Image, 'cache')
|
||||||
def test_create_vz_container_with_swap(self, mock_cache):
|
def test_create_vz_container_with_swap(self, mock_cache):
|
||||||
@ -16711,7 +16715,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
backend.disks['disk.eph0'].cache.assert_called_once_with(
|
backend.disks['disk.eph0'].cache.assert_called_once_with(
|
||||||
fetch_func=mock.ANY, context=self.context,
|
fetch_func=mock.ANY, context=self.context,
|
||||||
filename=filename, size=100 * units.Gi, ephemeral_size=mock.ANY,
|
filename=filename, size=100 * units.Gi, ephemeral_size=mock.ANY,
|
||||||
specified_fs=None)
|
specified_fs=None, safe=True)
|
||||||
|
|
||||||
def test_create_image_resize_snap_backend(self):
|
def test_create_image_resize_snap_backend(self):
|
||||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||||
|
@ -514,7 +514,7 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
|
|
||||||
image.cache(fn, self.TEMPLATE)
|
image.cache(fn, self.TEMPLATE)
|
||||||
|
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
mock_exists.assert_has_calls(exist_calls)
|
mock_exists.assert_has_calls(exist_calls)
|
||||||
|
|
||||||
@mock.patch.object(os.path, 'exists')
|
@mock.patch.object(os.path, 'exists')
|
||||||
@ -545,7 +545,7 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
|
|
||||||
image.cache(fn, self.TEMPLATE)
|
image.cache(fn, self.TEMPLATE)
|
||||||
|
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
mock_exists.assert_has_calls(exist_calls)
|
mock_exists.assert_has_calls(exist_calls)
|
||||||
|
|
||||||
@mock.patch.object(os.path, 'exists')
|
@mock.patch.object(os.path, 'exists')
|
||||||
@ -587,7 +587,8 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
|
|
||||||
mock_verify.assert_called_once_with(self.TEMPLATE_PATH, self.SIZE)
|
mock_verify.assert_called_once_with(self.TEMPLATE_PATH, self.SIZE)
|
||||||
mock_create.assert_called_once_with(
|
mock_create.assert_called_once_with(
|
||||||
self.PATH, 'qcow2', self.SIZE, backing_file=self.TEMPLATE_PATH)
|
self.PATH, 'qcow2', self.SIZE, backing_file=self.TEMPLATE_PATH,
|
||||||
|
safe=False)
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
||||||
mock_exist.assert_has_calls(exist_calls)
|
mock_exist.assert_has_calls(exist_calls)
|
||||||
self.assertTrue(mock_sync.called)
|
self.assertTrue(mock_sync.called)
|
||||||
@ -828,7 +829,7 @@ class LvmTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
|
|
||||||
image.cache(fn, self.TEMPLATE)
|
image.cache(fn, self.TEMPLATE)
|
||||||
|
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
||||||
mock_exists.assert_has_calls(exist_calls)
|
mock_exists.assert_has_calls(exist_calls)
|
||||||
|
|
||||||
@ -1369,7 +1370,7 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
image.cache(fn, self.TEMPLATE)
|
image.cache(fn, self.TEMPLATE)
|
||||||
|
|
||||||
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
mock_img_exist.assert_called_with()
|
mock_img_exist.assert_called_with()
|
||||||
mock_os_exist.assert_has_calls([
|
mock_os_exist.assert_has_calls([
|
||||||
mock.call(self.TEMPLATE_DIR), mock.call(self.TEMPLATE_PATH)
|
mock.call(self.TEMPLATE_DIR), mock.call(self.TEMPLATE_PATH)
|
||||||
@ -1392,7 +1393,7 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
mock_os_exist.assert_has_calls([
|
mock_os_exist.assert_has_calls([
|
||||||
mock.call(self.TEMPLATE_DIR), mock.call(self.TEMPLATE_PATH)
|
mock.call(self.TEMPLATE_DIR), mock.call(self.TEMPLATE_PATH)
|
||||||
])
|
])
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
|
|
||||||
@mock.patch.object(os.path, 'exists', return_value=True)
|
@mock.patch.object(os.path, 'exists', return_value=True)
|
||||||
@mock.patch.object(imagebackend.Rbd, 'exists', return_value=True)
|
@mock.patch.object(imagebackend.Rbd, 'exists', return_value=True)
|
||||||
@ -2078,7 +2079,7 @@ class PloopTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||||||
|
|
||||||
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
mock_ensure.assert_called_once_with(self.TEMPLATE_DIR)
|
||||||
mock_exists.assert_has_calls(exist_calls)
|
mock_exists.assert_has_calls(exist_calls)
|
||||||
fn.assert_called_once_with(target=self.TEMPLATE_PATH)
|
fn.assert_called_once_with(target=self.TEMPLATE_PATH, safe=False)
|
||||||
|
|
||||||
@mock.patch.object(imagebackend.Ploop, 'get_disk_size',
|
@mock.patch.object(imagebackend.Ploop, 'get_disk_size',
|
||||||
return_value=2048)
|
return_value=2048)
|
||||||
|
@ -4926,7 +4926,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
'%dG' % ephemeral_size,
|
'%dG' % ephemeral_size,
|
||||||
specified_fs)
|
specified_fs)
|
||||||
return
|
return
|
||||||
libvirt_utils.create_image(target, 'raw', f'{ephemeral_size}G')
|
libvirt_utils.create_image(
|
||||||
|
target, 'raw', f'{ephemeral_size}G', safe=True)
|
||||||
|
|
||||||
# Run as root only for block devices.
|
# Run as root only for block devices.
|
||||||
disk_api.mkfs(os_type, fs_label, target, run_as_root=is_block_dev,
|
disk_api.mkfs(os_type, fs_label, target, run_as_root=is_block_dev,
|
||||||
@ -5169,11 +5170,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
vm_mode=vm_mode)
|
vm_mode=vm_mode)
|
||||||
fname = "ephemeral_%s_%s" % (ephemeral_gb, file_extension)
|
fname = "ephemeral_%s_%s" % (ephemeral_gb, file_extension)
|
||||||
size = ephemeral_gb * units.Gi
|
size = ephemeral_gb * units.Gi
|
||||||
disk_image.cache(fetch_func=fn,
|
disk_image.cache(
|
||||||
context=context,
|
fetch_func=fn, context=context, filename=fname, size=size,
|
||||||
filename=fname,
|
ephemeral_size=ephemeral_gb, safe=True)
|
||||||
size=size,
|
|
||||||
ephemeral_size=ephemeral_gb)
|
|
||||||
|
|
||||||
for idx, eph in enumerate(driver.block_device_info_get_ephemerals(
|
for idx, eph in enumerate(driver.block_device_info_get_ephemerals(
|
||||||
block_device_info)):
|
block_device_info)):
|
||||||
@ -5195,12 +5194,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
vm_mode=vm_mode)
|
vm_mode=vm_mode)
|
||||||
size = eph['size'] * units.Gi
|
size = eph['size'] * units.Gi
|
||||||
fname = "ephemeral_%s_%s" % (eph['size'], file_extension)
|
fname = "ephemeral_%s_%s" % (eph['size'], file_extension)
|
||||||
disk_image.cache(fetch_func=fn,
|
disk_image.cache(
|
||||||
context=context,
|
fetch_func=fn, context=context, filename=fname, size=size,
|
||||||
filename=fname,
|
ephemeral_size=eph['size'], specified_fs=specified_fs,
|
||||||
size=size,
|
safe=True)
|
||||||
ephemeral_size=eph['size'],
|
|
||||||
specified_fs=specified_fs)
|
|
||||||
|
|
||||||
if swap_mb > 0:
|
if swap_mb > 0:
|
||||||
size = swap_mb * units.Mi
|
size = swap_mb * units.Mi
|
||||||
@ -5208,9 +5205,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
swap = image('disk.swap', disk_info_mapping=disk_info_mapping)
|
swap = image('disk.swap', disk_info_mapping=disk_info_mapping)
|
||||||
# Short circuit the exists() tests if we already created a disk
|
# Short circuit the exists() tests if we already created a disk
|
||||||
created_disks = created_disks or not swap.exists()
|
created_disks = created_disks or not swap.exists()
|
||||||
swap.cache(fetch_func=self._create_swap, context=context,
|
swap.cache(
|
||||||
filename="swap_%s" % swap_mb,
|
fetch_func=self._create_swap, context=context,
|
||||||
size=size, swap_mb=swap_mb)
|
filename="swap_%s" % swap_mb, size=size, swap_mb=swap_mb,
|
||||||
|
safe=True)
|
||||||
|
|
||||||
if created_disks:
|
if created_disks:
|
||||||
LOG.debug('Created local disks', instance=instance)
|
LOG.debug('Created local disks', instance=instance)
|
||||||
@ -11650,14 +11648,16 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
os_type=instance.os_type,
|
os_type=instance.os_type,
|
||||||
filename=cache_name,
|
filename=cache_name,
|
||||||
size=info['virt_disk_size'],
|
size=info['virt_disk_size'],
|
||||||
ephemeral_size=info['virt_disk_size'] / units.Gi)
|
ephemeral_size=info['virt_disk_size'] / units.Gi,
|
||||||
|
safe=True)
|
||||||
elif cache_name.startswith('swap'):
|
elif cache_name.startswith('swap'):
|
||||||
flavor = instance.get_flavor()
|
flavor = instance.get_flavor()
|
||||||
swap_mb = flavor.swap
|
swap_mb = flavor.swap
|
||||||
disk.cache(fetch_func=self._create_swap,
|
disk.cache(fetch_func=self._create_swap,
|
||||||
filename="swap_%s" % swap_mb,
|
filename="swap_%s" % swap_mb,
|
||||||
size=swap_mb * units.Mi,
|
size=swap_mb * units.Mi,
|
||||||
swap_mb=swap_mb)
|
swap_mb=swap_mb,
|
||||||
|
safe=True)
|
||||||
else:
|
else:
|
||||||
self._try_fetch_image_cache(disk,
|
self._try_fetch_image_cache(disk,
|
||||||
libvirt_utils.fetch_image,
|
libvirt_utils.fetch_image,
|
||||||
|
@ -135,7 +135,8 @@ class Image(metaclass=abc.ABCMeta):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
"""Create image from template.
|
"""Create image from template.
|
||||||
|
|
||||||
Contains specific behavior for each image type.
|
Contains specific behavior for each image type.
|
||||||
@ -144,6 +145,7 @@ class Image(metaclass=abc.ABCMeta):
|
|||||||
Should accept `target` argument.
|
Should accept `target` argument.
|
||||||
:base: Template name
|
:base: Template name
|
||||||
:size: Size of created image in bytes
|
:size: Size of created image in bytes
|
||||||
|
:safe: True if image contains a safe filesystem
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
@ -263,7 +265,8 @@ class Image(metaclass=abc.ABCMeta):
|
|||||||
def exists(self):
|
def exists(self):
|
||||||
return os.path.exists(self.path)
|
return os.path.exists(self.path)
|
||||||
|
|
||||||
def cache(self, fetch_func, filename, size=None, *args, **kwargs):
|
def cache(self, fetch_func, filename, size=None, safe=False, *args,
|
||||||
|
**kwargs):
|
||||||
"""Creates image from template.
|
"""Creates image from template.
|
||||||
|
|
||||||
Ensures that template and image not already exists.
|
Ensures that template and image not already exists.
|
||||||
@ -298,8 +301,9 @@ class Image(metaclass=abc.ABCMeta):
|
|||||||
fetch_func(target=target, *args, **kwargs)
|
fetch_func(target=target, *args, **kwargs)
|
||||||
|
|
||||||
if not self.exists() or not os.path.exists(base):
|
if not self.exists() or not os.path.exists(base):
|
||||||
self.create_image(fetch_func_sync, base, size,
|
self.create_image(
|
||||||
*args, **kwargs)
|
fetch_func_sync, base, size, safe=safe, *args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
if size:
|
if size:
|
||||||
# create_image() only creates the base image if needed, so
|
# create_image() only creates the base image if needed, so
|
||||||
@ -593,7 +597,8 @@ class Flat(Image):
|
|||||||
if os.path.exists(self.path):
|
if os.path.exists(self.path):
|
||||||
self.driver_format = self.resolve_driver_format()
|
self.driver_format = self.resolve_driver_format()
|
||||||
|
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
filename = self._get_lock_name(base)
|
filename = self._get_lock_name(base)
|
||||||
|
|
||||||
@utils.synchronized(filename, external=True, lock_path=self.lock_path)
|
@utils.synchronized(filename, external=True, lock_path=self.lock_path)
|
||||||
@ -663,13 +668,14 @@ class Qcow2(Image):
|
|||||||
self.disk_info_path = os.path.join(os.path.dirname(path), 'disk.info')
|
self.disk_info_path = os.path.join(os.path.dirname(path), 'disk.info')
|
||||||
self.resolve_driver_format()
|
self.resolve_driver_format()
|
||||||
|
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
filename = self._get_lock_name(base)
|
filename = self._get_lock_name(base)
|
||||||
|
|
||||||
@utils.synchronized(filename, external=True, lock_path=self.lock_path)
|
@utils.synchronized(filename, external=True, lock_path=self.lock_path)
|
||||||
def create_qcow2_image(base, target, size):
|
def create_qcow2_image(base, target, size, safe=False):
|
||||||
libvirt_utils.create_image(
|
libvirt_utils.create_image(
|
||||||
target, 'qcow2', size, backing_file=base)
|
target, 'qcow2', size, backing_file=base, safe=safe)
|
||||||
|
|
||||||
# Download the unmodified base image unless we already have a copy.
|
# Download the unmodified base image unless we already have a copy.
|
||||||
if not os.path.exists(base):
|
if not os.path.exists(base):
|
||||||
@ -679,7 +685,9 @@ class Qcow2(Image):
|
|||||||
# before we inspect it for other attributes. We do this each time
|
# before we inspect it for other attributes. We do this each time
|
||||||
# because additional safety checks could have been added since we
|
# because additional safety checks could have been added since we
|
||||||
# downloaded the image.
|
# downloaded the image.
|
||||||
if not CONF.workarounds.disable_deep_image_inspection:
|
# NOTE(sean-k-mooney) If the image was created by nova as a swap
|
||||||
|
# or ephemeral disk it is safe to skip the deep inspection.
|
||||||
|
if not CONF.workarounds.disable_deep_image_inspection and not safe:
|
||||||
inspector = format_inspector.detect_file_format(base)
|
inspector = format_inspector.detect_file_format(base)
|
||||||
try:
|
try:
|
||||||
inspector.safety_check()
|
inspector.safety_check()
|
||||||
@ -724,7 +732,7 @@ class Qcow2(Image):
|
|||||||
|
|
||||||
if not os.path.exists(self.path):
|
if not os.path.exists(self.path):
|
||||||
with fileutils.remove_path_on_error(self.path):
|
with fileutils.remove_path_on_error(self.path):
|
||||||
create_qcow2_image(base, self.path, size)
|
create_qcow2_image(base, self.path, size, safe=safe)
|
||||||
|
|
||||||
def resize_image(self, size):
|
def resize_image(self, size):
|
||||||
image = imgmodel.LocalFileImage(self.path, imgmodel.FORMAT_QCOW2)
|
image = imgmodel.LocalFileImage(self.path, imgmodel.FORMAT_QCOW2)
|
||||||
@ -800,7 +808,8 @@ class Lvm(Image):
|
|||||||
def _can_fallocate(self):
|
def _can_fallocate(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
def encrypt_lvm_image():
|
def encrypt_lvm_image():
|
||||||
dmcrypt.create_volume(self.path.rpartition('/')[2],
|
dmcrypt.create_volume(self.path.rpartition('/')[2],
|
||||||
self.lv_path,
|
self.lv_path,
|
||||||
@ -997,7 +1006,8 @@ class Rbd(Image):
|
|||||||
LOG.warning("Ignoring failure to remove %(path)s: "
|
LOG.warning("Ignoring failure to remove %(path)s: "
|
||||||
"%(error)s", {'path': base, 'error': e})
|
"%(error)s", {'path': base, 'error': e})
|
||||||
|
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
|
|
||||||
if not self.exists():
|
if not self.exists():
|
||||||
self._remove_non_raw_cache_image(base)
|
self._remove_non_raw_cache_image(base)
|
||||||
@ -1272,7 +1282,8 @@ class Ploop(Image):
|
|||||||
|
|
||||||
# Create new ploop disk (in case of epehemeral) or
|
# Create new ploop disk (in case of epehemeral) or
|
||||||
# copy ploop disk from glance image
|
# copy ploop disk from glance image
|
||||||
def create_image(self, prepare_template, base, size, *args, **kwargs):
|
def create_image(
|
||||||
|
self, prepare_template, base, size, safe=False, *args, **kwargs):
|
||||||
filename = os.path.basename(base)
|
filename = os.path.basename(base)
|
||||||
|
|
||||||
# Copy main file of ploop disk, restore DiskDescriptor.xml for it
|
# Copy main file of ploop disk, restore DiskDescriptor.xml for it
|
||||||
|
@ -133,7 +133,8 @@ def create_image(
|
|||||||
disk_format: str,
|
disk_format: str,
|
||||||
disk_size: ty.Optional[ty.Union[str, int]],
|
disk_size: ty.Optional[ty.Union[str, int]],
|
||||||
backing_file: ty.Optional[str] = None,
|
backing_file: ty.Optional[str] = None,
|
||||||
encryption: ty.Optional[EncryptionOptions] = None
|
encryption: ty.Optional[EncryptionOptions] = None,
|
||||||
|
safe: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Disk image creation with qemu-img
|
"""Disk image creation with qemu-img
|
||||||
:param path: Desired location of the disk image
|
:param path: Desired location of the disk image
|
||||||
@ -147,6 +148,7 @@ def create_image(
|
|||||||
:param backing_file: (Optional) Backing file to use.
|
:param backing_file: (Optional) Backing file to use.
|
||||||
:param encryption: (Optional) Dict detailing various encryption attributes
|
:param encryption: (Optional) Dict detailing various encryption attributes
|
||||||
such as the format and passphrase.
|
such as the format and passphrase.
|
||||||
|
:param safe: If True, the image is know to be safe.
|
||||||
"""
|
"""
|
||||||
cmd = [
|
cmd = [
|
||||||
'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'create', '-f', disk_format
|
'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'create', '-f', disk_format
|
||||||
@ -157,7 +159,10 @@ def create_image(
|
|||||||
# before we inspect it for other attributes. We do this each time
|
# before we inspect it for other attributes. We do this each time
|
||||||
# because additional safety checks could have been added since we
|
# because additional safety checks could have been added since we
|
||||||
# downloaded the image.
|
# downloaded the image.
|
||||||
if not CONF.workarounds.disable_deep_image_inspection:
|
# Note(sean-k-mooney): We only need to perform the safety check for
|
||||||
|
# the backing file if the image is not created by nova for swap or
|
||||||
|
# ephemeral disks.
|
||||||
|
if not CONF.workarounds.disable_deep_image_inspection and not safe:
|
||||||
inspector = format_inspector.detect_file_format(backing_file)
|
inspector = format_inspector.detect_file_format(backing_file)
|
||||||
try:
|
try:
|
||||||
inspector.safety_check()
|
inspector.safety_check()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user