1 Upstream patch fixed in Grizzly 2013.1.5, Havana 2013.2.2, Icehouse |
|
2 |
|
3 commit cbeb5e51886b0296349fc476305bfe3d63c627c3 |
|
4 Author: Nikola Dipanov <[email protected]> |
|
5 Date: Tue Dec 10 17:43:17 2013 +0100 |
|
6 |
|
7 libvirt: Fix root disk leak in live mig |
|
8 |
|
9 This patch makes sure that _create_images_and_backing method of the |
|
10 libvirt driver (called in several places, but most problematic one is |
|
11 the call in the pre_live_migration method) creates all the files the |
|
12 instance needs that are not present. |
|
13 |
|
14 Prioir to this patch - the method would only attempt to download the |
|
15 image, and if it did so with the path of the ephemeral drives, it could |
|
16 expose the image to other users as an ephemeral devices. See the related |
|
17 bug for more detaiis. |
|
18 |
|
19 After this patch - we properly distinguish between image, ephemeral and |
|
20 swap files, and make sure that the imagebackend does the correct thing. |
|
21 |
|
22 Closes-bug: #1251590 |
|
23 |
|
24 Co-authored-by: Loganathan Parthipan <[email protected]> |
|
25 |
|
26 This patch also includes part of commit |
|
27 65386c91910ee03d947c2b8bcc226a53c30e060a, not cherry-picked as a whole |
|
28 due to the fact that it is a trivial change, and to avoud the |
|
29 proliferation of patches needed to fix this bug. |
|
30 |
|
31 (cherry picked from commit c69a619668b5f44e94a8fe1a23f3d887ba2834d7) |
|
32 |
|
33 Conflicts: |
|
34 nova/tests/test_libvirt.py |
|
35 nova/virt/libvirt/driver.py |
|
36 |
|
37 Change-Id: I78aa2f4243899db4f4941e77014a7e18e27fc63e |
|
38 |
|
39 diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py |
|
40 index d2ac73b..d9c7405 100644 |
|
41 --- a/nova/tests/test_libvirt.py |
|
42 +++ b/nova/tests/test_libvirt.py |
|
43 @@ -2346,6 +2346,69 @@ class LibvirtConnTestCase(test.TestCase): |
|
44 |
|
45 db.instance_destroy(self.context, instance_ref['uuid']) |
|
46 |
|
47 + def test_create_images_and_backing(self): |
|
48 + conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) |
|
49 + self.mox.StubOutWithMock(conn, '_fetch_instance_kernel_ramdisk') |
|
50 + self.mox.StubOutWithMock(libvirt_driver.libvirt_utils, 'create_image') |
|
51 + |
|
52 + libvirt_driver.libvirt_utils.create_image(mox.IgnoreArg(), |
|
53 + mox.IgnoreArg(), |
|
54 + mox.IgnoreArg()) |
|
55 + conn._fetch_instance_kernel_ramdisk(self.context, self.test_instance) |
|
56 + self.mox.ReplayAll() |
|
57 + |
|
58 + self.stubs.Set(os.path, 'exists', lambda *args: False) |
|
59 + disk_info_json = jsonutils.dumps([{'path': 'foo', 'type': None, |
|
60 + 'disk_size': 0, |
|
61 + 'backing_file': None}]) |
|
62 + conn._create_images_and_backing(self.context, self.test_instance, |
|
63 + "/fake/instance/dir", disk_info_json) |
|
64 + |
|
65 + def test_create_images_and_backing_ephemeral_gets_created(self): |
|
66 + conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) |
|
67 + disk_info_json = jsonutils.dumps( |
|
68 + [{u'backing_file': u'fake_image_backing_file', |
|
69 + u'disk_size': 10747904, |
|
70 + u'path': u'disk_path', |
|
71 + u'type': u'qcow2', |
|
72 + u'virt_disk_size': 25165824}, |
|
73 + {u'backing_file': u'ephemeral_1_default', |
|
74 + u'disk_size': 393216, |
|
75 + u'over_committed_disk_size': 1073348608, |
|
76 + u'path': u'disk_eph_path', |
|
77 + u'type': u'qcow2', |
|
78 + u'virt_disk_size': 1073741824}]) |
|
79 + |
|
80 + base_dir = os.path.join(CONF.instances_path, '_base') |
|
81 + ephemeral_target = os.path.join(base_dir, 'ephemeral_1_default') |
|
82 + image_target = os.path.join(base_dir, 'fake_image_backing_file') |
|
83 + self.test_instance.update({'name': 'fake_instance', |
|
84 + 'user_id': 'fake-user', |
|
85 + 'os_type': None, |
|
86 + 'project_id': 'fake-project'}) |
|
87 + |
|
88 + self.mox.StubOutWithMock(libvirt_driver.libvirt_utils, 'fetch_image') |
|
89 + self.mox.StubOutWithMock(conn, '_create_ephemeral') |
|
90 + self.mox.StubOutWithMock(conn, '_fetch_instance_kernel_ramdisk') |
|
91 + |
|
92 + conn._create_ephemeral( |
|
93 + target=ephemeral_target, |
|
94 + ephemeral_size=self.test_instance['ephemeral_gb'], |
|
95 + max_size=mox.IgnoreArg(), os_type=mox.IgnoreArg(), |
|
96 + fs_label=mox.IgnoreArg()) |
|
97 + libvirt_driver.libvirt_utils.fetch_image(context=self.context, |
|
98 + image_id=mox.IgnoreArg(), |
|
99 + user_id=mox.IgnoreArg(), project_id=mox.IgnoreArg(), |
|
100 + max_size=mox.IgnoreArg(), target=image_target) |
|
101 + conn._fetch_instance_kernel_ramdisk( |
|
102 + self.context, self.test_instance).AndReturn(None) |
|
103 + |
|
104 + self.mox.ReplayAll() |
|
105 + |
|
106 + conn._create_images_and_backing(self.context, self.test_instance, |
|
107 + "/fake/instance/dir", |
|
108 + disk_info_json) |
|
109 + |
|
110 def test_pre_live_migration_works_correctly_mocked(self): |
|
111 # Creating testdata |
|
112 vol = {'block_device_mapping': [ |
|
113 diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py |
|
114 index 0f0ea46..6c2a22c 100755 |
|
115 --- a/nova/virt/libvirt/driver.py |
|
116 +++ b/nova/virt/libvirt/driver.py |
|
117 @@ -3304,19 +3304,32 @@ class LibvirtDriver(driver.ComputeDriver): |
|
118 elif info['backing_file']: |
|
119 # Creating backing file follows same way as spawning instances. |
|
120 cache_name = os.path.basename(info['backing_file']) |
|
121 - # Remove any size tags which the cache manages |
|
122 - cache_name = cache_name.split('_')[0] |
|
123 |
|
124 image = self.image_backend.image(instance, |
|
125 instance_disk, |
|
126 CONF.libvirt_images_type) |
|
127 - image.cache(fetch_func=libvirt_utils.fetch_image, |
|
128 - context=ctxt, |
|
129 - filename=cache_name, |
|
130 - image_id=instance['image_ref'], |
|
131 - user_id=instance['user_id'], |
|
132 - project_id=instance['project_id'], |
|
133 - size=info['virt_disk_size']) |
|
134 + if cache_name.startswith('ephemeral'): |
|
135 + image.cache(fetch_func=self._create_ephemeral, |
|
136 + fs_label=cache_name, |
|
137 + os_type=instance["os_type"], |
|
138 + filename=cache_name, |
|
139 + size=info['virt_disk_size'], |
|
140 + ephemeral_size=instance['ephemeral_gb']) |
|
141 + elif cache_name.startswith('swap'): |
|
142 + inst_type = instance_types.extract_instance_type(instance) |
|
143 + swap_mb = inst_type['swap'] |
|
144 + image.cache(fetch_func=self._create_swap, |
|
145 + filename="swap_%s" % swap_mb, |
|
146 + size=swap_mb * (1024 ** 2), |
|
147 + swap_mb=swap_mb) |
|
148 + else: |
|
149 + image.cache(fetch_func=libvirt_utils.fetch_image, |
|
150 + context=ctxt, |
|
151 + filename=cache_name, |
|
152 + image_id=instance['image_ref'], |
|
153 + user_id=instance['user_id'], |
|
154 + project_id=instance['project_id'], |
|
155 + size=info['virt_disk_size']) |
|
156 |
|
157 # if image has kernel and ramdisk, just download |
|
158 # following normal way. |
|