Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 876204 Details for
Bug 1078002
CVE-2014-0134 openstack-nova: Nova host data leak to vm instance in rescue mode
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
havana patch
cve-2014-0134-stable-havana.patch (text/plain), 22.90 KB, created by
Garth Mollett
on 2014-03-19 04:55:37 UTC
(
hide
)
Description:
havana patch
Filename:
MIME Type:
Creator:
Garth Mollett
Created:
2014-03-19 04:55:37 UTC
Size:
22.90 KB
patch
obsolete
>From e2527e64f77ca0211c744908031cf056cb144f07 Mon Sep 17 00:00:00 2001 >From: David Ripton <dripton@redhat.com> >Date: Mon, 17 Mar 2014 22:18:05 -0400 >Subject: [PATCH] Persist image format to a file, to prevent attacks based on > changing it > >The attack is based on creating a raw image that looks like a qcow2 >image, and taking advantage of the code that used 'qemu-img info' to >autodetect the image format. > >Now we store the image format to a 'disk.info' file, for Qcow2 and Raw >images, and only autodetect for images that have never been written to >that file. Since glance takes the appropriate security precautions on >image upload, this should be sufficient and backward-compatible. > >Manually resolved one conflict in nova/virt/libvirt/imagebackend.py: >snapshot_delete was removed in icehouse, but is still there in havana > >Change-Id: I2016efdb3f49a44ec4d677ac596eacc97871f30a >Closes-bug: #1221190 >--- > nova/tests/virt/libvirt/test_imagebackend.py | 331 ++++++++++++++++++++++----- > nova/virt/libvirt/imagebackend.py | 57 ++++- > 2 files changed, 324 insertions(+), 64 deletions(-) > >diff --git a/nova/tests/virt/libvirt/test_imagebackend.py b/nova/tests/virt/libvirt/test_imagebackend.py >index 2455ec8..3df22fa 100644 >--- a/nova/tests/virt/libvirt/test_imagebackend.py >+++ b/nova/tests/virt/libvirt/test_imagebackend.py >@@ -16,6 +16,8 @@ > # under the License. > > import os >+import shutil >+import tempfile > > import fixtures > from oslo.config import cfg >@@ -31,7 +33,6 @@ CONF = cfg.CONF > > > class _ImageTestCase(object): >- INSTANCES_PATH = '/instances_path' > > def mock_create_image(self, image): > def create_image(fn, base, size, *args, **kwargs): >@@ -40,10 +41,13 @@ class _ImageTestCase(object): > > def setUp(self): > super(_ImageTestCase, self).setUp() >+ self.INSTANCES_PATH = tempfile.mkdtemp(suffix='instances') > self.flags(disable_process_locking=True, > instances_path=self.INSTANCES_PATH) > self.INSTANCE = {'name': 'instance', > 'uuid': uuidutils.generate_uuid()} >+ self.DISK_INFO_PATH = os.path.join(self.INSTANCES_PATH, >+ self.INSTANCE['uuid'], 'disk.info') > self.NAME = 'fake.vm' > self.TEMPLATE = 'template' > >@@ -61,6 +65,70 @@ class _ImageTestCase(object): > 'nova.virt.libvirt.imagebackend.libvirt_utils', > fake_libvirt_utils)) > >+ def tearDown(self): >+ super(_ImageTestCase, self).tearDown() >+ shutil.rmtree(self.INSTANCES_PATH) >+ >+ def test_prealloc_image(self): >+ CONF.set_override('preallocate_images', 'space') >+ >+ fake_processutils.fake_execute_clear_log() >+ fake_processutils.stub_out_processutils_execute(self.stubs) >+ image = self.image_class(self.INSTANCE, self.NAME) >+ >+ def fake_fetch(target, *args, **kwargs): >+ return >+ >+ self.stubs.Set(os.path, 'exists', lambda _: True) >+ self.stubs.Set(os, 'access', lambda p, w: True) >+ >+ # Call twice to verify testing fallocate is only called once. >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ >+ self.assertEqual(fake_processutils.fake_execute_get_log(), >+ ['fallocate -n -l 1 %s.fallocate_test' % self.PATH, >+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH), >+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH)]) >+ >+ def test_prealloc_image_without_write_access(self): >+ CONF.set_override('preallocate_images', 'space') >+ >+ fake_processutils.fake_execute_clear_log() >+ fake_processutils.stub_out_processutils_execute(self.stubs) >+ image = self.image_class(self.INSTANCE, self.NAME) >+ >+ def fake_fetch(target, *args, **kwargs): >+ return >+ >+ self.stubs.Set(image, 'check_image_exists', lambda: True) >+ self.stubs.Set(image, '_can_fallocate', lambda: True) >+ self.stubs.Set(os.path, 'exists', lambda _: True) >+ self.stubs.Set(os, 'access', lambda p, w: False) >+ >+ # Testing fallocate is only called when user has write access. >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ >+ self.assertEqual(fake_processutils.fake_execute_get_log(), []) >+ >+ >+class RawTestCase(_ImageTestCase, test.NoDBTestCase): >+ >+ SIZE = 1024 >+ >+ def setUp(self): >+ self.image_class = imagebackend.Raw >+ super(RawTestCase, self).setUp() >+ self.stubs.Set(imagebackend.Raw, 'correct_format', lambda _: None) >+ >+ def prepare_mocks(self): >+ fn = self.mox.CreateMockAnything() >+ self.mox.StubOutWithMock(imagebackend.utils.synchronized, >+ '__call__') >+ self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image') >+ self.mox.StubOutWithMock(imagebackend.disk, 'extend') >+ return fn >+ > def test_cache(self): > self.mox.StubOutWithMock(os.path, 'exists') > if self.OLD_STYLE_INSTANCE_PATH: >@@ -128,66 +196,6 @@ class _ImageTestCase(object): > > self.mox.VerifyAll() > >- def test_prealloc_image(self): >- CONF.set_override('preallocate_images', 'space') >- >- fake_processutils.fake_execute_clear_log() >- fake_processutils.stub_out_processutils_execute(self.stubs) >- image = self.image_class(self.INSTANCE, self.NAME) >- >- def fake_fetch(target, *args, **kwargs): >- return >- >- self.stubs.Set(os.path, 'exists', lambda _: True) >- self.stubs.Set(os, 'access', lambda p, w: True) >- >- # Call twice to verify testing fallocate is only called once. >- image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >- image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >- >- self.assertEqual(fake_processutils.fake_execute_get_log(), >- ['fallocate -n -l 1 %s.fallocate_test' % self.PATH, >- 'fallocate -n -l %s %s' % (self.SIZE, self.PATH), >- 'fallocate -n -l %s %s' % (self.SIZE, self.PATH)]) >- >- def test_prealloc_image_without_write_access(self): >- CONF.set_override('preallocate_images', 'space') >- >- fake_processutils.fake_execute_clear_log() >- fake_processutils.stub_out_processutils_execute(self.stubs) >- image = self.image_class(self.INSTANCE, self.NAME) >- >- def fake_fetch(target, *args, **kwargs): >- return >- >- self.stubs.Set(image, 'check_image_exists', lambda: True) >- self.stubs.Set(image, '_can_fallocate', lambda: True) >- self.stubs.Set(os.path, 'exists', lambda _: True) >- self.stubs.Set(os, 'access', lambda p, w: False) >- >- # Testing fallocate is only called when user has write access. >- image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >- >- self.assertEqual(fake_processutils.fake_execute_get_log(), []) >- >- >-class RawTestCase(_ImageTestCase, test.NoDBTestCase): >- >- SIZE = 1024 >- >- def setUp(self): >- self.image_class = imagebackend.Raw >- super(RawTestCase, self).setUp() >- self.stubs.Set(imagebackend.Raw, 'correct_format', lambda _: None) >- >- def prepare_mocks(self): >- fn = self.mox.CreateMockAnything() >- self.mox.StubOutWithMock(imagebackend.utils.synchronized, >- '__call__') >- self.mox.StubOutWithMock(imagebackend.libvirt_utils, 'copy_image') >- self.mox.StubOutWithMock(imagebackend.disk, 'extend') >- return fn >- > def test_create_image(self): > fn = self.prepare_mocks() > fn(target=self.TEMPLATE_PATH, max_size=None, image_id=None) >@@ -222,16 +230,17 @@ class RawTestCase(_ImageTestCase, test.NoDBTestCase): > self.mox.VerifyAll() > > def test_correct_format(self): >- info = self.mox.CreateMockAnything() > self.stubs.UnsetAll() > > self.mox.StubOutWithMock(os.path, 'exists') > self.mox.StubOutWithMock(imagebackend.images, 'qemu_img_info') > > os.path.exists(self.PATH).AndReturn(True) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) > info = self.mox.CreateMockAnything() > info.file_format = 'foo' > imagebackend.images.qemu_img_info(self.PATH).AndReturn(info) >+ os.path.exists(CONF.instances_path).AndReturn(True) > self.mox.ReplayAll() > > image = self.image_class(self.INSTANCE, self.NAME, path=self.PATH) >@@ -239,6 +248,11 @@ class RawTestCase(_ImageTestCase, test.NoDBTestCase): > > self.mox.VerifyAll() > >+ def test_resolve_driver_format(self): >+ image = self.image_class(self.INSTANCE, self.NAME) >+ driver_format = image.resolve_driver_format() >+ self.assertEqual(driver_format, 'raw') >+ > > class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > SIZE = 1024 * 1024 * 1024 >@@ -259,6 +273,77 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > self.mox.StubOutWithMock(imagebackend.disk, 'extend') > return fn > >+ def test_cache(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(CONF.instances_path).AndReturn(True) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(False) >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ >+ def test_cache_image_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(True) >+ os.path.exists(self.TEMPLATE_PATH).AndReturn(True) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ image.cache(None, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ >+ def test_cache_base_dir_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(False) >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ >+ def test_cache_template_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(False) >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ > def test_create_image(self): > fn = self.prepare_mocks() > fn(max_size=None, target=self.TEMPLATE_PATH) >@@ -277,6 +362,8 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > self.mox.StubOutWithMock(os.path, 'exists') > if self.OLD_STYLE_INSTANCE_PATH: > os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) > os.path.exists(self.TEMPLATE_PATH).AndReturn(False) > os.path.exists(self.PATH).AndReturn(False) > os.path.exists(self.PATH).AndReturn(False) >@@ -296,6 +383,8 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size') > if self.OLD_STYLE_INSTANCE_PATH: > os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) > os.path.exists(self.TEMPLATE_PATH).AndReturn(True) > imagebackend.disk.get_disk_size(self.TEMPLATE_PATH > ).AndReturn(self.SIZE) >@@ -314,6 +403,8 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > 'get_disk_backing_file') > if self.OLD_STYLE_INSTANCE_PATH: > os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(CONF.instances_path).AndReturn(True) > os.path.exists(self.TEMPLATE_PATH).AndReturn(False) > os.path.exists(self.PATH).AndReturn(True) > >@@ -340,6 +431,9 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > 'get_disk_backing_file') > if self.OLD_STYLE_INSTANCE_PATH: > os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False) >+ os.path.exists(self.INSTANCES_PATH).AndReturn(True) >+ > os.path.exists(self.TEMPLATE_PATH).AndReturn(False) > os.path.exists(self.PATH).AndReturn(True) > >@@ -353,6 +447,55 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase): > > self.mox.VerifyAll() > >+ def test_resolve_driver_format(self): >+ image = self.image_class(self.INSTANCE, self.NAME) >+ driver_format = image.resolve_driver_format() >+ self.assertEqual(driver_format, 'qcow2') >+ >+ def test_prealloc_image(self): >+ CONF.set_override('preallocate_images', 'space') >+ >+ fake_processutils.fake_execute_clear_log() >+ fake_processutils.stub_out_processutils_execute(self.stubs) >+ image = self.image_class(self.INSTANCE, self.NAME) >+ >+ def fake_fetch(target, *args, **kwargs): >+ return >+ >+ self.stubs.Set(os.path, 'exists', lambda _: True) >+ self.stubs.Set(os, 'access', lambda p, w: True) >+ >+ # Call twice to verify testing fallocate is only called once. >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ >+ self.assertEqual(fake_processutils.fake_execute_get_log(), >+ ['chown root:root %s' % self.DISK_INFO_PATH, >+ 'fallocate -n -l 1 %s.fallocate_test' % self.PATH, >+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH), >+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH)]) >+ >+ def test_prealloc_image_without_write_access(self): >+ CONF.set_override('preallocate_images', 'space') >+ >+ fake_processutils.fake_execute_clear_log() >+ fake_processutils.stub_out_processutils_execute(self.stubs) >+ image = self.image_class(self.INSTANCE, self.NAME) >+ >+ def fake_fetch(target, *args, **kwargs): >+ return >+ >+ self.stubs.Set(image, 'check_image_exists', lambda: True) >+ self.stubs.Set(image, '_can_fallocate', lambda: True) >+ self.stubs.Set(os.path, 'exists', lambda _: True) >+ self.stubs.Set(os, 'access', lambda p, w: False) >+ >+ # Testing fallocate is only called when user has write access. >+ image.cache(fake_fetch, self.TEMPLATE_PATH, self.SIZE) >+ >+ self.assertEqual(fake_processutils.fake_execute_get_log(), >+ ['chown root:root %s' % self.DISK_INFO_PATH]) >+ > > class LvmTestCase(_ImageTestCase, test.NoDBTestCase): > VG = 'FakeVG' >@@ -429,6 +572,56 @@ class LvmTestCase(_ImageTestCase, test.NoDBTestCase): > > self.mox.VerifyAll() > >+ def test_cache(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(False) >+ os.path.exists(self.PATH).AndReturn(False) >+ >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree') >+ imagebackend.fileutils.ensure_tree(self.TEMPLATE_DIR) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ >+ def test_cache_image_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(True) >+ os.path.exists(self.TEMPLATE_PATH).AndReturn(True) >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ image.cache(None, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ >+ def test_cache_base_dir_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ if self.OLD_STYLE_INSTANCE_PATH: >+ os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False) >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ os.path.exists(self.PATH).AndReturn(False) >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree') >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ > def test_create_image(self): > self._create_image(False) > >@@ -594,6 +787,20 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase): > > self.mox.VerifyAll() > >+ def test_cache_base_dir_exists(self): >+ self.mox.StubOutWithMock(os.path, 'exists') >+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True) >+ fn = self.mox.CreateMockAnything() >+ fn(target=self.TEMPLATE_PATH) >+ self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree') >+ self.mox.ReplayAll() >+ >+ image = self.image_class(self.INSTANCE, self.NAME) >+ self.mock_create_image(image) >+ image.cache(fn, self.TEMPLATE) >+ >+ self.mox.VerifyAll() >+ > def test_create_image(self): > fn = self.prepare_mocks() > fn(max_size=None, rbd=self.rbd, target=self.TEMPLATE_PATH) >diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py >index e900789..21c7641 100644 >--- a/nova/virt/libvirt/imagebackend.py >+++ b/nova/virt/libvirt/imagebackend.py >@@ -88,6 +88,11 @@ class Image(object): > self.is_block_dev = is_block_dev > self.preallocate = False > >+ # NOTE(dripton): We store lines of json (path, disk_format) in this >+ # file, for some image types, to prevent attacks based on changing the >+ # disk_format. >+ self.disk_info_path = None >+ > # NOTE(mikal): We need a lock directory which is shared along with > # instance files, to cover the scenario where multiple compute nodes > # are trying to create a base file at the same time >@@ -232,6 +237,46 @@ class Image(object): > def snapshot_delete(self): > raise NotImplementedError() > >+ def _get_driver_format(self): >+ return self.driver_format >+ >+ def resolve_driver_format(self): >+ """Return the driver format for self.path. >+ >+ First checks self.disk_info_path for an entry. >+ If it's not there, calls self._get_driver_format(), and then >+ stores the result in self.disk_info_path >+ >+ See https://bugs.launchpad.net/nova/+bug/1221190 >+ """ >+ @utils.synchronized(self.disk_info_path, external=False, >+ lock_path=self.lock_path) >+ def write_to_disk_info_file(): >+ with open(self.disk_info_path, "w") as disk_info_file: >+ disk_info_file.write('%s\n' % >+ jsonutils.dumps((self.path, driver_format))) >+ # Ensure the file is always owned by root so qemu can't write it. >+ utils.execute('chown', 'root:root', self.disk_info_path, >+ run_as_root=True) >+ >+ if (self.disk_info_path is not None and >+ os.path.exists(self.disk_info_path)): >+ with open(self.disk_info_path) as disk_info_file: >+ line = disk_info_file.read().rstrip() >+ try: >+ parts = jsonutils.loads(line) >+ except (TypeError, ValueError): >+ parts = [] >+ if len(parts) == 2: >+ (path, driver_format) = parts >+ if path == self.path: >+ return driver_format >+ driver_format = self._get_driver_format() >+ if self.disk_info_path is not None: >+ fileutils.ensure_tree(os.path.dirname(self.disk_info_path)) >+ write_to_disk_info_file() >+ return driver_format >+ > > class Raw(Image): > def __init__(self, instance=None, disk_name=None, path=None, >@@ -243,12 +288,17 @@ class Raw(Image): > disk_name)) > self.snapshot_name = snapshot_name > self.preallocate = CONF.preallocate_images != 'none' >+ self.disk_info_path = os.path.join(os.path.dirname(self.path), >+ 'disk.info') > self.correct_format() > >+ def _get_driver_format(self): >+ data = images.qemu_img_info(self.path) >+ return data.file_format or 'raw' >+ > def correct_format(self): > if os.path.exists(self.path): >- data = images.qemu_img_info(self.path) >- self.driver_format = data.file_format or 'raw' >+ self.driver_format = self.resolve_driver_format() > > def create_image(self, prepare_template, base, size, *args, **kwargs): > @utils.synchronized(base, external=True, lock_path=self.lock_path) >@@ -291,6 +341,9 @@ class Qcow2(Image): > disk_name)) > self.snapshot_name = snapshot_name > self.preallocate = CONF.preallocate_images != 'none' >+ self.disk_info_path = os.path.join(os.path.dirname(self.path), >+ 'disk.info') >+ self.resolve_driver_format() > > def create_image(self, prepare_template, base, size, *args, **kwargs): > @utils.synchronized(base, external=True, lock_path=self.lock_path) >-- >1.8.5.3 > > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1078002
:
876204
|
876205