summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Thode <prometheanfire@gentoo.org>2014-03-27 23:08:50 +0000
committerMatt Thode <prometheanfire@gentoo.org>2014-03-27 23:08:50 +0000
commite196d50df2c3f71b880e28411212b11942ea63da (patch)
tree72b30e443c14991b37ded738947667a66be0ed76
parentInstall multilib libgudev, bug #506002 (diff)
downloadhistorical-e196d50df2c3f71b880e28411212b11942ea63da.tar.gz
historical-e196d50df2c3f71b880e28411212b11942ea63da.tar.bz2
historical-e196d50df2c3f71b880e28411212b11942ea63da.zip
better patch
Package-Manager: portage-2.2.8-r1/cvs/Linux x86_64 Manifest-Sign-Key: 0x2471EB3E40AC5AC3
-rw-r--r--sys-cluster/nova/ChangeLog6
-rw-r--r--sys-cluster/nova/Manifest30
-rw-r--r--sys-cluster/nova/files/2013.2.2-CVE-2014-0134.patch272
3 files changed, 234 insertions, 74 deletions
diff --git a/sys-cluster/nova/ChangeLog b/sys-cluster/nova/ChangeLog
index c9fe51c0e0dd..b6922480dc40 100644
--- a/sys-cluster/nova/ChangeLog
+++ b/sys-cluster/nova/ChangeLog
@@ -1,6 +1,10 @@
# ChangeLog for sys-cluster/nova
# Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/ChangeLog,v 1.53 2014/03/25 20:51:33 prometheanfire Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/nova/ChangeLog,v 1.54 2014/03/27 23:08:43 prometheanfire Exp $
+
+ 27 Mar 2014; Matthew Thode <prometheanfire@gentoo.org>
+ files/2013.2.2-CVE-2014-0134.patch:
+ better patch
*nova-2013.2.2-r1 (25 Mar 2014)
diff --git a/sys-cluster/nova/Manifest b/sys-cluster/nova/Manifest
index 25c852c94801..a6c0cc1cf8cb 100644
--- a/sys-cluster/nova/Manifest
+++ b/sys-cluster/nova/Manifest
@@ -1,7 +1,7 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
-AUX 2013.2.2-CVE-2014-0134.patch 23445 SHA256 b5358a78c7ef3452a1f11708a5ce8a72d4a174b68dbef1ea7e99bc90df7782e9 SHA512 fd93a7e14627cccaef82c260e2568b4c73ce771ee39f1fa13c2e692534eaf9aa0a953b3e4ed3630e819dbb3d34f126bcfbd1f8cef1624fdce232ce675523d3f6 WHIRLPOOL 1e9d0bb56aaf907a9c1ace61b1ececab657255e057253761a860c1d2fb8d5c82fe8738e28d5dfb318597ba5b4835e72136016f71194968a439537daecb7127ae
+AUX 2013.2.2-CVE-2014-0134.patch 29323 SHA256 dd751e26c0d179603282cbfa8234d60756349db563b1b076db09d3f08fe92788 SHA512 74cfe95d4c35fc2456c55f38feb4481e18fef9141f1b1f4cf67958ba7505d068e3f4e36ad5b52a76d4a1b63d27e9a618d3721ea60d5d99a8fe3df89abaa93128 WHIRLPOOL 322a928c1be361904c3c30da13dc2885ff438fd16b9257292d800450e7e5d524cf7f8de68066b8683150c3ac97ecdfb81ff6b7bc7562b2a39f179b6674f298e0
AUX nova-confd 101 SHA256 d9013141618d1e8b8ba85297155747d9c8fc362238de7bba3108b9a2539c8c73 SHA512 4c7ec1d123f2cdaf394d1f4824df861bbe309b0b329db44080160d81746cd0fc9d4cc1b35da0f66ab075f1d4e835ababfb7bccaf4a2e931e60f2c0ac572a552e WHIRLPOOL 6a237357a3905d29a96b32c37f6d189e4f5cefc0986bb091e24a79295191332143741c604c2a9fd44484c75b3be89742a5570862cf0cd4ba225425f7f32b5348
AUX nova-initd 1496 SHA256 5b5f928335ac345103492555c3bc57407f547915b099762d0087aef172e5edf8 SHA512 cca06baba484d505f3a96643d836204a08e9dde50197531cdab2d95188b992a95a375a386b9c54fcc8e0a4f6167babba975db7510db1087f044afa39effe4eec WHIRLPOOL 4c667a5cc469826063a65879c1beddc98371edf295a273c9b8f679627cabfe2260d8b3bbdf9550d3894fc1525d63b9f98d6e939406f90ac5f2f745daa59311c2
AUX nova-sudoers 78 SHA256 9e88c2843fb74cc46802c0b103067ad12915ec50335d05e546a5dba76acb4a76 SHA512 22c0606c6335b2d1a03bd18a319a54f16f76f091b2e8416dbba05ce7c15890beff7f32f0322eb5ba3f2a5c750436cacbe0cee189b390b878e3f0c0df219ef984 WHIRLPOOL bc42ae1d12e9f900b263fd5c3d0f59062f46fbec1ff97c0bceb234082bea5943eb64795b4f5e102b8e2749c6868163e5924467088cad42df09345e3406e5f83c
@@ -12,22 +12,22 @@ EBUILD nova-2013.1.9999.ebuild 5070 SHA256 1dd4815b62e7290b24f0a6ebed20b388546d1
EBUILD nova-2013.2.2-r1.ebuild 5133 SHA256 88a89a8476c994654563f862d3257e08802c398628c9fa45734524f93c678294 SHA512 130e6a2232255f470054b73b01f09903a329a1bbe9db61e118fa1a77058a3b0bab0e1b5e794831d4be58ccad8d904b8627758a6290fb9c56fa8b48b57054c85e WHIRLPOOL c66627ee4db02a3d1aed1025f427c3e1dd90d4684d03e2a585f5a9886251e414ebb57226202e811652d57edefd8e9fdb26c725aec290cc82356c5386b7446127
EBUILD nova-2013.2.9999.ebuild 5086 SHA256 9a7a79415aa6c5597a7eaac6967c9a69e917c183dc6424f5eaaed42753c996ab SHA512 b964c5fe5caf221fd00c94444470b3c638b504352fdaf48985784a157cbb1b71379af34e10bb9977da99dede7e6eb67e3ceb8d40bcd5b570639d609cb710a724 WHIRLPOOL 2088fe0677075c2efdaebdd9a5295146daba5a2f1bf0d3bd85c24ca891564176523a324445325e7b7f2019c7dfcdbc2cede820b89fa417746fadb2a0796a0f89
EBUILD nova-9999.ebuild 5225 SHA256 8336956c0a15fd17e15f748c6445c3b144f2a9047dd8257ba3dda7a7b7f1ad01 SHA512 6d961e646096eb4df5814d31b06352f999291becefa5e8fdd88afd14e6ede54e583ba224e474e1122e90b114da4136782cd8336afb467c61fc5400a7dd3a05e8 WHIRLPOOL c4bad3d35be8adb4af48562507ef213185e6d722541226e7d8bedd02578265c035874b371f432db4d1db222fc2776cc74374a508ca562a30dae622a86e0bab10
-MISC ChangeLog 13045 SHA256 7acb8c8fb1634e5fdbf90e254267d4b54e5e6e1449e6e0af424bc771da14acad SHA512 0c5c9910c36db750c8f7b49fb961371dbce677f7162c3fb602fcdd372798ae9acf9df17c06b17c0b477171d601d19c3130b3e44865d4245a72f6de01c05181e1 WHIRLPOOL 30b2fa645b30dc6f8a2954e40404a100b69786d9541ccaceefe24f6b0ca77b7ea32010235e54474941c9cfa2d347455615a151cb3c41774e49415ba6cc85ff9d
+MISC ChangeLog 13156 SHA256 dfc44e7f762957c2110dc861f920d16508f23e7ebd9da6c13a357d9e7502d71d SHA512 41d3dfce8708fec544ef723b8565ff230d6dd0d9cf257c7e7ba8573e2c70642f429e1ecb5719033dd83dba838e8f3178d509efb36ea93ac1e9fa81462f3f69f7 WHIRLPOOL e6f3f16aa221935050f22b3d152f6e5bc0f76e6a38b1c22a702fa8c8a93c487b373a2e7d49082bb9ffa08e52e9ca0c7d4195f4ef2caad9ccd5e9522958bfa87a
MISC metadata.xml 1452 SHA256 29bf3efaab7a4e45f5e442b26a7606edaed3f47e4ffec3e8990f95aea6bf2450 SHA512 537664b6ff29f4afe09eb4635c2cb06d87a6c3c3101e8ef89d1ab9b5b802c79024e94a0cce5a44ec2fd5b1cc37a251dd42156a015b6a294f219b90daff17c9c1 WHIRLPOOL c6e44f9a48fea6ae2a323e9e03d8805301fb0d94bb5634b1946909715f6c05d45c49180204d00221aae1e6dc6748347b4273fae838216b5d5d07932bc473a851
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
-iQIcBAEBCAAGBQJTMeyDAAoJECRx6z5ArFrDQVkP/3TxWE5PjLuN5dYupA2fsPYG
-jCB7GT2LWcorFWadkbjgW89aTd7gj5R3MY5xrt5nNQkYDMS80EjNHdcqmnL8TblY
-ZiEGFOEZavcb9e5+jaNb5HnPFN5YmzJyCu5ndw7kuroZOGvMSNFkaxYqvcWij0l6
-yIq6ebvbBBrbzzoKfNk8MFa08zHQtsT/HZcUBa7QeF6TxQuXdfWYLwNlX6t8YAWN
-xUpOlcI9H37z7unlScHhZ7IJfaYe08gPDkot+LFnezUdmcUS74MOtib3sPCg2MdI
-t/2jbz+nhOZYYBtj39KyHIf7Xh5UpqrzXEmSfGUF2UF2MXV/kWS8rEgDONpXH3BB
-FxlbQlkrLv90lRgyqiAZ6FV2XxdFGr4zA9+6LUE430SKG/3a7913kYamKb+cwtbT
-8KnDOsiD4B3j0yIK5RCxdx3j/cAYKSmz4ofxOcddk8856N2Rje4CUSis82M7P54t
-2LDntvtCYaMS31L08KRA5srIJg+67txHayDziV1eYwjYNOqMKQHoxvd9xfM8Pr51
-IroxS8Ugcm5SnoL38FKgL1iFLKeVaXzIe+ZX6HRZWpZYfoA7lFZ1DcK0h5yp8cDf
-dk632D8hshWSdhl6wmnxE/uWkJqV1ERD37owt5Tq6f8RpY6AFZSoIFHYc5UY2x1p
-eIdjmwkBsY0nR+TzBan8
-=T4lx
+iQIcBAEBCAAGBQJTNK+qAAoJECRx6z5ArFrDkq8QALiHXnx5H066FLCk84f4Bs2z
+bUsytUs0vYCu5Pj0wk6qfWKH/top9AWFqWCSqJ9mpV6MAjh7yeb3uV1n7gTE4Scq
+hk6FWglNjc7w0fB4cu7NzNurfFVqYaPMC4w3IB6qhRH9ZXEN5TDfWGPtVqv41QeL
+Lr0Ec571kwjXTuLUhZSv/OGjvgnOEw6PJdzOPz4VGRaJv2HwYbTcdogOC76DDy8x
+EW0XqjAgOSbusOFC7bzIjmZ0nalZlxPGYD5IKxFnPBcU5r0gIo7ZKyGs+DxYWr5T
+U3lz4PHyn1KadEZY6Hi5LDsz1yaL/k0VJuu0JuLmNxDbkVlJ9hGCt+IWylAsEaGL
+qM8gpVW9ur4FMBXGtQM3NrvbeSjCvLcneAgwjJ34uOh1khmTepkxSKUhajInmVp2
+4LP6mae1gE45tKS32rXMyBBMlRks3XeMgJ9znSyenJ588vV526EsuJvDy0RU4idE
+8NetDzcaO2axx39obNuBBcExG8ydD7B+IMPrvfbfw5NmZEvm6t2PZK9uIzwhznqd
+VBekyQ0z8hXgGDrTSw/TXIkZUiy5gZmbiO+f/lSABTEp5zENsGwhC/AwICfvXKLn
+bnrlJiKML2weVOLnNAIvAVgBkkhraWi7ZcIqrQvkyTNcBqW672dXS937fW/B93T+
+asNtbfHWwzQ55Eiw7xSk
+=EwvS
-----END PGP SIGNATURE-----
diff --git a/sys-cluster/nova/files/2013.2.2-CVE-2014-0134.patch b/sys-cluster/nova/files/2013.2.2-CVE-2014-0134.patch
index 4aab09443087..04d14cae392a 100644
--- a/sys-cluster/nova/files/2013.2.2-CVE-2014-0134.patch
+++ b/sys-cluster/nova/files/2013.2.2-CVE-2014-0134.patch
@@ -1,6 +1,6 @@
-From e2527e64f77ca0211c744908031cf056cb144f07 Mon Sep 17 00:00:00 2001
+From 25e761acd56d4c820273fc0245ada06c500c1637 Mon Sep 17 00:00:00 2001
From: David Ripton <dripton@redhat.com>
-Date: Mon, 17 Mar 2014 22:18:05 -0400
+Date: Tue, 28 Jan 2014 16:38:51 -0500
Subject: [PATCH] Persist image format to a file, to prevent attacks based on
changing it
@@ -10,21 +10,48 @@ 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.
+that file.
-Manually resolved one conflict in nova/virt/libvirt/imagebackend.py:
-snapshot_delete was removed in icehouse, but is still there in havana
+SecurityImpact
+
+Conflicts:
+ nova/virt/libvirt/imagebackend.py
+
+Manual tweaks to some mocking in test_imagebackend.py
Change-Id: I2016efdb3f49a44ec4d677ac596eacc97871f30a
+Co-authored-by: Nikola Dipanov <ndipanov@redhat.com>
Closes-bug: #1221190
---
- nova/tests/virt/libvirt/test_imagebackend.py | 331 ++++++++++++++++++++++-----
- nova/virt/libvirt/imagebackend.py | 57 ++++-
- 2 files changed, 324 insertions(+), 64 deletions(-)
+ nova/exception.py | 8 +
+ nova/tests/virt/libvirt/test_imagebackend.py | 359 ++++++++++++++++++++++-----
+ nova/tests/virt/libvirt/test_libvirt.py | 3 +
+ nova/tests/virt/test_virt_drivers.py | 7 +
+ nova/utils.py | 14 ++
+ nova/virt/libvirt/imagebackend.py | 76 +++++-
+ 6 files changed, 403 insertions(+), 64 deletions(-)
+diff --git a/nova/exception.py b/nova/exception.py
+index 7c17803..770a700 100644
+--- a/nova/exception.py
++++ b/nova/exception.py
+@@ -449,6 +449,14 @@ class InvalidDiskFormat(Invalid):
+ msg_fmt = _("Disk format %(disk_format)s is not acceptable")
+
+
++class InvalidDiskInfo(Invalid):
++ msg_fmt = _("Disk info file is invalid: %(reason)s")
++
++
++class DiskInfoReadWriteFail(Invalid):
++ msg_fmt = _("Failed to read or write disk info file: %(reason)s")
++
++
+ class ImageUnacceptable(Invalid):
+ msg_fmt = _("Image %(image_id)s is unacceptable: %(reason)s")
+
diff --git a/nova/tests/virt/libvirt/test_imagebackend.py b/nova/tests/virt/libvirt/test_imagebackend.py
-index 2455ec8..3df22fa 100644
+index 5bfa94d..5424f7b 100644
--- a/nova/tests/virt/libvirt/test_imagebackend.py
+++ b/nova/tests/virt/libvirt/test_imagebackend.py
@@ -16,6 +16,8 @@
@@ -36,7 +63,14 @@ index 2455ec8..3df22fa 100644
import fixtures
from oslo.config import cfg
-@@ -31,7 +33,6 @@ CONF = cfg.CONF
+@@ -27,13 +29,13 @@
+ from nova import test
+ from nova.tests import fake_processutils
+ from nova.tests.virt.libvirt import fake_libvirt_utils
++from nova import utils
+ from nova.virt.libvirt import imagebackend
+
+ CONF = cfg.CONF
class _ImageTestCase(object):
@@ -44,7 +78,7 @@ index 2455ec8..3df22fa 100644
def mock_create_image(self, image):
def create_image(fn, base, size, *args, **kwargs):
-@@ -40,10 +41,13 @@ class _ImageTestCase(object):
+@@ -42,10 +44,13 @@ def create_image(fn, base, size, *args, **kwargs):
def setUp(self):
super(_ImageTestCase, self).setUp()
@@ -58,10 +92,14 @@ index 2455ec8..3df22fa 100644
self.NAME = 'fake.vm'
self.TEMPLATE = 'template'
-@@ -61,6 +65,70 @@ class _ImageTestCase(object):
+@@ -63,6 +68,78 @@ def setUp(self):
'nova.virt.libvirt.imagebackend.libvirt_utils',
fake_libvirt_utils))
++ def fake_chown(path, owner_uid=None):
++ return None
++ self.stubs.Set(utils, 'chown', fake_chown)
++
+ def tearDown(self):
+ super(_ImageTestCase, self).tearDown()
+ shutil.rmtree(self.INSTANCES_PATH)
@@ -118,6 +156,10 @@ index 2455ec8..3df22fa 100644
+ super(RawTestCase, self).setUp()
+ self.stubs.Set(imagebackend.Raw, 'correct_format', lambda _: None)
+
++ def fake_chown(path, owner_uid=None):
++ return None
++ self.stubs.Set(utils, 'chown', fake_chown)
++
+ def prepare_mocks(self):
+ fn = self.mox.CreateMockAnything()
+ self.mox.StubOutWithMock(imagebackend.utils.synchronized,
@@ -129,7 +171,7 @@ index 2455ec8..3df22fa 100644
def test_cache(self):
self.mox.StubOutWithMock(os.path, 'exists')
if self.OLD_STYLE_INSTANCE_PATH:
-@@ -128,66 +196,6 @@ class _ImageTestCase(object):
+@@ -130,66 +207,6 @@ def test_cache_template_exists(self):
self.mox.VerifyAll()
@@ -196,7 +238,7 @@ index 2455ec8..3df22fa 100644
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):
+@@ -224,16 +241,21 @@ def test_create_image_extend(self):
self.mox.VerifyAll()
def test_correct_format(self):
@@ -206,6 +248,10 @@ index 2455ec8..3df22fa 100644
self.mox.StubOutWithMock(os.path, 'exists')
self.mox.StubOutWithMock(imagebackend.images, 'qemu_img_info')
++ def fake_chown(path, owner_uid=None):
++ return None
++ self.stubs.Set(utils, 'chown', fake_chown)
++
os.path.exists(self.PATH).AndReturn(True)
+ os.path.exists(self.DISK_INFO_PATH).AndReturn(False)
info = self.mox.CreateMockAnything()
@@ -215,7 +261,7 @@ index 2455ec8..3df22fa 100644
self.mox.ReplayAll()
image = self.image_class(self.INSTANCE, self.NAME, path=self.PATH)
-@@ -239,6 +248,11 @@ class RawTestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -241,6 +263,11 @@ def test_correct_format(self):
self.mox.VerifyAll()
@@ -227,7 +273,18 @@ index 2455ec8..3df22fa 100644
class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
SIZE = 1024 * 1024 * 1024
-@@ -259,6 +273,77 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -251,6 +278,10 @@ def setUp(self):
+ self.QCOW2_BASE = (self.TEMPLATE_PATH +
+ '_%d' % (self.SIZE / (1024 * 1024 * 1024)))
+
++ def fake_chown(path, owner_uid=None):
++ return None
++ self.stubs.Set(utils, 'chown', fake_chown)
++
+ def prepare_mocks(self):
+ fn = self.mox.CreateMockAnything()
+ self.mox.StubOutWithMock(imagebackend.utils.synchronized,
+@@ -261,6 +292,80 @@ def prepare_mocks(self):
self.mox.StubOutWithMock(imagebackend.disk, 'extend')
return fn
@@ -240,6 +297,7 @@ index 2455ec8..3df22fa 100644
+ os.path.exists(self.TEMPLATE_DIR).AndReturn(False)
+ os.path.exists(self.INSTANCES_PATH).AndReturn(True)
+ os.path.exists(self.PATH).AndReturn(False)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.ReplayAll()
@@ -274,6 +332,7 @@ index 2455ec8..3df22fa 100644
+ os.path.exists(self.INSTANCES_PATH).AndReturn(True)
+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
+ os.path.exists(self.PATH).AndReturn(False)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.ReplayAll()
@@ -292,6 +351,7 @@ index 2455ec8..3df22fa 100644
+ os.path.exists(self.INSTANCES_PATH).AndReturn(True)
+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
+ os.path.exists(self.PATH).AndReturn(False)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.ReplayAll()
@@ -305,7 +365,7 @@ index 2455ec8..3df22fa 100644
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):
+@@ -279,6 +384,8 @@ def test_create_image_with_size(self):
self.mox.StubOutWithMock(os.path, 'exists')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
@@ -314,7 +374,7 @@ index 2455ec8..3df22fa 100644
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):
+@@ -298,6 +405,8 @@ def test_create_image_too_small(self):
self.mox.StubOutWithMock(imagebackend.disk, 'get_disk_size')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
@@ -323,7 +383,7 @@ index 2455ec8..3df22fa 100644
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):
+@@ -316,6 +425,8 @@ def test_generate_resized_backing_files(self):
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
@@ -332,7 +392,7 @@ index 2455ec8..3df22fa 100644
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
os.path.exists(self.PATH).AndReturn(True)
-@@ -340,6 +431,9 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -342,6 +453,9 @@ def test_qcow2_exists_and_has_no_backing_file(self):
'get_disk_backing_file')
if self.OLD_STYLE_INSTANCE_PATH:
os.path.exists(self.OLD_STYLE_INSTANCE_PATH).AndReturn(False)
@@ -342,7 +402,7 @@ index 2455ec8..3df22fa 100644
os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
os.path.exists(self.PATH).AndReturn(True)
-@@ -353,6 +447,55 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -355,6 +469,53 @@ def test_qcow2_exists_and_has_no_backing_file(self):
self.mox.VerifyAll()
@@ -369,8 +429,7 @@ index 2455ec8..3df22fa 100644
+ 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 1 %s.fallocate_test' % self.PATH,
+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH),
+ 'fallocate -n -l %s %s' % (self.SIZE, self.PATH)])
+
@@ -392,13 +451,12 @@ index 2455ec8..3df22fa 100644
+ # 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])
++ self.assertEqual(fake_processutils.fake_execute_get_log(), [])
+
class LvmTestCase(_ImageTestCase, test.NoDBTestCase):
VG = 'FakeVG'
-@@ -429,6 +572,56 @@ class LvmTestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -431,6 +592,58 @@ def _create_image_resize(self, sparse):
self.mox.VerifyAll()
@@ -408,6 +466,7 @@ index 2455ec8..3df22fa 100644
+ 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)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
@@ -441,6 +500,7 @@ index 2455ec8..3df22fa 100644
+ 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)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree')
@@ -455,13 +515,14 @@ index 2455ec8..3df22fa 100644
def test_create_image(self):
self._create_image(False)
-@@ -594,6 +787,20 @@ class RbdTestCase(_ImageTestCase, test.NoDBTestCase):
+@@ -596,6 +809,21 @@ def test_cache_template_exists(self):
self.mox.VerifyAll()
+ def test_cache_base_dir_exists(self):
+ self.mox.StubOutWithMock(os.path, 'exists')
+ os.path.exists(self.TEMPLATE_DIR).AndReturn(True)
++ os.path.exists(self.TEMPLATE_PATH).AndReturn(False)
+ fn = self.mox.CreateMockAnything()
+ fn(target=self.TEMPLATE_PATH)
+ self.mox.StubOutWithMock(imagebackend.fileutils, 'ensure_tree')
@@ -476,11 +537,89 @@ index 2455ec8..3df22fa 100644
def test_create_image(self):
fn = self.prepare_mocks()
fn(max_size=None, rbd=self.rbd, target=self.TEMPLATE_PATH)
+@@ -642,6 +870,13 @@ class BackendTestCase(test.NoDBTestCase):
+ 'uuid': uuidutils.generate_uuid()}
+ NAME = 'fake-name.suffix'
+
++ def setUp(self):
++ super(BackendTestCase, self).setUp()
++
++ def fake_chown(path, owner_uid=None):
++ return None
++ self.stubs.Set(utils, 'chown', fake_chown)
++
+ def get_image(self, use_cow, image_type):
+ return imagebackend.Backend(use_cow).image(self.INSTANCE,
+ self.NAME,
+diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
+index ba842ad..ea8ac13 100644
+--- a/nova/tests/virt/libvirt/test_libvirt.py
++++ b/nova/tests/virt/libvirt/test_libvirt.py
+@@ -390,6 +390,9 @@ def fake_extend(image, size, use_cow=False):
+
+ self.stubs.Set(libvirt_driver.disk, 'extend', fake_extend)
+
++ self.stubs.Set(imagebackend.Image, 'resolve_driver_format',
++ imagebackend.Image._get_driver_format)
++
+ class FakeConn():
+ def getCapabilities(self):
+ """Ensure standard capabilities being returned."""
+diff --git a/nova/tests/virt/test_virt_drivers.py b/nova/tests/virt/test_virt_drivers.py
+index 832d9d6..8f1bd23 100644
+--- a/nova/tests/virt/test_virt_drivers.py
++++ b/nova/tests/virt/test_virt_drivers.py
+@@ -30,6 +30,7 @@
+ from nova.tests.virt.libvirt import fake_libvirt_utils
+ from nova.virt import event as virtevent
+ from nova.virt import fake
++from nova.virt.libvirt import imagebackend
+
+ LOG = logging.getLogger(__name__)
+
+@@ -201,6 +202,12 @@ def setUp(self):
+ fake.FakeVirtAPI())
+ self.ctxt = test_utils.get_test_admin_context()
+ self.image_service = fake_image.FakeImageService()
++ # NOTE(dripton): resolve_driver_format does some file reading and
++ # writing and chowning that complicate testing too much by requiring
++ # using real directories with proper permissions. Just stub it out
++ # here; we test it in test_imagebackend.py
++ self.stubs.Set(imagebackend.Image, 'resolve_driver_format',
++ imagebackend.Image._get_driver_format)
+
+ def _get_running_instance(self):
+ instance_ref = test_utils.get_test_instance()
+diff --git a/nova/utils.py b/nova/utils.py
+index 599cb64..4757f3a 100755
+--- a/nova/utils.py
++++ b/nova/utils.py
+@@ -924,6 +924,20 @@ def temporary_chown(path, owner_uid=None):
+ execute('chown', orig_uid, path, run_as_root=True)
+
+
++def chown(path, owner_uid=None):
++ """chown a path.
++
++ :param owner_uid: UID of owner (defaults to current user)
++ """
++ if owner_uid is None:
++ owner_uid = os.getuid()
++
++ orig_uid = os.stat(path).st_uid
++
++ if orig_uid != owner_uid:
++ execute('chown', owner_uid, path, run_as_root=True)
++
++
+ @contextlib.contextmanager
+ def tempdir(**kwargs):
+ argdict = kwargs.copy()
diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
-index e900789..21c7641 100644
+index 51872cf..ed11c90 100644
--- a/nova/virt/libvirt/imagebackend.py
+++ b/nova/virt/libvirt/imagebackend.py
-@@ -88,6 +88,11 @@ class Image(object):
+@@ -88,6 +88,11 @@ def __init__(self, source_type, driver_format, is_block_dev=False):
self.is_block_dev = is_block_dev
self.preallocate = False
@@ -492,7 +631,7 @@ index e900789..21c7641 100644
# 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):
+@@ -232,6 +237,65 @@ def snapshot_extract(self, target, out_format):
def snapshot_delete(self):
raise NotImplementedError()
@@ -508,38 +647,57 @@ index e900789..21c7641 100644
+
+ See https://bugs.launchpad.net/nova/+bug/1221190
+ """
++ def _dict_from_line(line):
++ if not line:
++ return {}
++ try:
++ return jsonutils.loads(line)
++ except (TypeError, ValueError) as e:
++ msg = (_("Could not load line %(line)s, got error "
++ "%(error)s") %
++ {'line': line, 'error': unicode(e)})
++ raise exception.InvalidDiskInfo(reason=msg)
++
+ @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:
++ # Use os.open to create it without group or world write permission.
++ fd = os.open(self.disk_info_path, os.O_RDWR | os.O_CREAT, 0o644)
++ with os.fdopen(fd, "r+") 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()
++ dct = _dict_from_line(line)
++ if self.path in dct:
++ msg = _("Attempted overwrite of an existing value.")
++ raise exception.InvalidDiskInfo(reason=msg)
++ dct.update({self.path: driver_format})
++ disk_info_file.seek(0)
++ disk_info_file.truncate()
++ disk_info_file.write('%s\n' % jsonutils.dumps(dct))
++ # Ensure the file is always owned by the nova user so qemu can't
++ # write it.
++ utils.chown(self.disk_info_path, owner_uid=os.getuid())
++
++ try:
++ 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()
++ dct = _dict_from_line(line)
++ for path, driver_format in dct.iteritems():
++ 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()
++ except OSError as e:
++ raise exception.DiskInfoReadWriteFail(reason=unicode(e))
+ return driver_format
+
class Raw(Image):
def __init__(self, instance=None, disk_name=None, path=None,
-@@ -243,12 +288,17 @@ class Raw(Image):
+@@ -243,12 +307,17 @@ def __init__(self, instance=None, disk_name=None, path=None,
disk_name))
self.snapshot_name = snapshot_name
self.preallocate = CONF.preallocate_images != 'none'
@@ -559,7 +717,7 @@ index e900789..21c7641 100644
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):
+@@ -291,6 +360,9 @@ def __init__(self, instance=None, disk_name=None, path=None,
disk_name))
self.snapshot_name = snapshot_name
self.preallocate = CONF.preallocate_images != 'none'
@@ -570,7 +728,5 @@ index e900789..21c7641 100644
def create_image(self, prepare_template, base, size, *args, **kwargs):
@utils.synchronized(base, external=True, lock_path=self.lock_path)
--
-1.8.5.3
-
-
+1.8.5.5