Merge lp:~billy-olsen/nova/kilo+lp1457517 into lp:~ubuntu-server-dev/nova/kilo
- kilo+lp1457517
- Merge into kilo
Proposed by
Billy Olsen
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 781 | ||||
Proposed branch: | lp:~billy-olsen/nova/kilo+lp1457517 | ||||
Merge into: | lp:~ubuntu-server-dev/nova/kilo | ||||
Diff against target: |
524 lines (+500/-0) 3 files modified
debian/changelog (+5/-0) debian/patches/not-check-disk-size.patch (+494/-0) debian/patches/series (+1/-0) |
||||
To merge this branch: | bzr merge lp:~billy-olsen/nova/kilo+lp1457517 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Server Developers | Pending | ||
Review via email: mp+270466@code.launchpad.net |
Commit message
Description of the change
This is a resubmission of Liang's branch for including the upstream patch for not considering a flavor's volume size when booting from volume. His original branch is located at lp:~cbjchen/nova/kilo-sru-lp1457517 but he's currently unavailable.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2015-08-18 21:07:07 +0000 |
3 | +++ debian/changelog 2015-09-08 23:22:49 +0000 |
4 | @@ -1,7 +1,12 @@ |
5 | nova (1:2015.1.1-0ubuntu2) UNRELEASED; urgency=medium |
6 | |
7 | + [ Corey Bryant ] |
8 | * d/rules: Prevent dh_python2 from guessing dependencies. |
9 | |
10 | + [ Liang Chen ] |
11 | + * d/p/not-check-disk-size.patch: Fix booting from volume error |
12 | + when flavor disk too small (LP: #1457517) |
13 | + |
14 | -- Corey Bryant <corey.bryant@canonical.com> Thu, 13 Aug 2015 15:13:43 -0400 |
15 | |
16 | nova (1:2015.1.1-0ubuntu1) vivid; urgency=medium |
17 | |
18 | === added file 'debian/patches/not-check-disk-size.patch' |
19 | --- debian/patches/not-check-disk-size.patch 1970-01-01 00:00:00 +0000 |
20 | +++ debian/patches/not-check-disk-size.patch 2015-09-08 23:22:49 +0000 |
21 | @@ -0,0 +1,494 @@ |
22 | +From 8794b938dcb983b7c918718807c2396cb255b4ce Mon Sep 17 00:00:00 2001 |
23 | +From: Matthew Booth <mbooth@redhat.com> |
24 | +Date: Wed, 22 Jul 2015 14:56:52 +0100 |
25 | +Subject: [PATCH 1/1] Don't check flavor disk size when booting from volume |
26 | + |
27 | +When creating a volume from an image, cinder copies the image metadata |
28 | +into volume properties. When booting from the volume, we read this |
29 | +metadata from the volume and use it as image metadata once again. |
30 | + |
31 | +While fixing the check against min_ram, |
32 | +change I861a78b5c7efa71e4bf7206d388b8d0d8048c78e introduced a |
33 | +regression which prevents a user from booting a volume which is larger |
34 | +than the flavor's disk. As we are not creating this disk, this check |
35 | +does not make sense. Similarly, it checks the image metadata's |
36 | +min_disk against the flavor disk size, which is not being used. |
37 | + |
38 | +This change leaves the image metadata check unaltered when creating a |
39 | +flavor disk. When booting from a volume, we check min_disk from image |
40 | +metadata against the actual size of the volume. We don't check the |
41 | +volume size at all. The check against min_ram is retained unaltered. |
42 | + |
43 | +Closes-Bug: #1457517 |
44 | +Closes-Bug: #1459491 |
45 | +Closes-Bug: #1466305 |
46 | +Change-Id: I264493172da20b664df571e32876030246c2a87c |
47 | +(cherry picked from commit 642c986f0636d52a9ba279c87e25082b4aa9b3b8) |
48 | +--- |
49 | + nova/compute/api.py | 101 +++++++++++++++----- |
50 | + nova/tests/unit/compute/test_compute.py | 127 +++++++++++++++++++++++--- |
51 | + nova/tests/unit/compute/test_compute_api.py | 11 ++- |
52 | + nova/tests/unit/compute/test_compute_cells.py | 8 +- |
53 | + 4 files changed, 203 insertions(+), 44 deletions(-) |
54 | + |
55 | +diff --git a/nova/compute/api.py b/nova/compute/api.py |
56 | +index 6634918..5937895 100644 |
57 | +--- a/nova/compute/api.py |
58 | ++++ b/nova/compute/api.py |
59 | +@@ -651,7 +651,8 @@ class API(base.Base): |
60 | + # reason, we rely on the DB to cast True to a String. |
61 | + return True if bool_val else '' |
62 | + |
63 | +- def _check_requested_image(self, context, image_id, image, instance_type): |
64 | ++ def _check_requested_image(self, context, image_id, image, |
65 | ++ instance_type, root_bdm): |
66 | + if not image: |
67 | + return |
68 | + |
69 | +@@ -668,15 +669,63 @@ class API(base.Base): |
70 | + if instance_type['memory_mb'] < int(image.get('min_ram') or 0): |
71 | + raise exception.FlavorMemoryTooSmall() |
72 | + |
73 | +- # NOTE(johannes): root_gb is allowed to be 0 for legacy reasons |
74 | +- # since libvirt interpreted the value differently than other |
75 | +- # drivers. A value of 0 means don't check size. |
76 | +- root_gb = instance_type['root_gb'] |
77 | +- if root_gb: |
78 | +- if int(image.get('size') or 0) > root_gb * (1024 ** 3): |
79 | +- raise exception.FlavorDiskTooSmall() |
80 | ++ # Image min_disk is in gb, size is in bytes. For sanity, have them both |
81 | ++ # in bytes. |
82 | ++ image_min_disk = int(image.get('min_disk') or 0) * units.Gi |
83 | ++ image_size = int(image.get('size') or 0) |
84 | ++ |
85 | ++ # Target disk is a volume. Don't check flavor disk size because it |
86 | ++ # doesn't make sense, and check min_disk against the volume size. |
87 | ++ if (root_bdm is not None and root_bdm.is_volume): |
88 | ++ # There are 2 possibilities here: either the target volume already |
89 | ++ # exists, or it doesn't, in which case the bdm will contain the |
90 | ++ # intended volume size. |
91 | ++ # |
92 | ++ # Cinder does its own check against min_disk, so if the target |
93 | ++ # volume already exists this has already been done and we don't |
94 | ++ # need to check it again here. In this case, volume_size may not be |
95 | ++ # set on the bdm. |
96 | ++ # |
97 | ++ # If we're going to create the volume, the bdm will contain |
98 | ++ # volume_size. Therefore we should check it if it exists. This will |
99 | ++ # still be checked again by cinder when the volume is created, but |
100 | ++ # that will not happen until the request reaches a host. By |
101 | ++ # checking it here, the user gets an immediate and useful failure |
102 | ++ # indication. |
103 | ++ # |
104 | ++ # The third possibility is that we have failed to consider |
105 | ++ # something, and there are actually more than 2 possibilities. In |
106 | ++ # this case cinder will still do the check at volume creation time. |
107 | ++ # The behaviour will still be correct, but the user will not get an |
108 | ++ # immediate failure from the api, and will instead have to |
109 | ++ # determine why the instance is in an error state with a task of |
110 | ++ # block_device_mapping. |
111 | ++ # |
112 | ++ # We could reasonably refactor this check into _validate_bdm at |
113 | ++ # some future date, as the various size logic is already split out |
114 | ++ # in there. |
115 | ++ dest_size = root_bdm.volume_size |
116 | ++ if dest_size is not None: |
117 | ++ dest_size *= units.Gi |
118 | ++ |
119 | ++ if image_min_disk > dest_size: |
120 | ++ # TODO(mdbooth) Raise a more descriptive exception here. |
121 | ++ # This is the exception which calling code expects, but |
122 | ++ # it's potentially misleading to the user. |
123 | ++ raise exception.FlavorDiskTooSmall() |
124 | ++ |
125 | ++ # Target disk is a local disk whose size is taken from the flavor |
126 | ++ else: |
127 | ++ dest_size = instance_type['root_gb'] * units.Gi |
128 | ++ |
129 | ++ # NOTE(johannes): root_gb is allowed to be 0 for legacy reasons |
130 | ++ # since libvirt interpreted the value differently than other |
131 | ++ # drivers. A value of 0 means don't check size. |
132 | ++ if dest_size != 0: |
133 | ++ if image_size > dest_size: |
134 | ++ raise exception.FlavorDiskTooSmall() |
135 | + |
136 | +- if int(image.get('min_disk') or 0) > root_gb: |
137 | ++ if image_min_disk > dest_size: |
138 | + raise exception.FlavorDiskTooSmall() |
139 | + |
140 | + def _get_image_defined_bdms(self, base_options, instance_type, image_meta, |
141 | +@@ -767,10 +816,11 @@ class API(base.Base): |
142 | + |
143 | + def _checks_for_create_and_rebuild(self, context, image_id, image, |
144 | + instance_type, metadata, |
145 | +- files_to_inject): |
146 | ++ files_to_inject, root_bdm): |
147 | + self._check_metadata_properties_quota(context, metadata) |
148 | + self._check_injected_file_quota(context, files_to_inject) |
149 | +- self._check_requested_image(context, image_id, image, instance_type) |
150 | ++ self._check_requested_image(context, image_id, image, |
151 | ++ instance_type, root_bdm) |
152 | + |
153 | + def _validate_and_build_base_options(self, context, instance_type, |
154 | + boot_meta, image_href, image_id, |
155 | +@@ -778,7 +828,7 @@ class API(base.Base): |
156 | + display_description, key_name, |
157 | + key_data, security_groups, |
158 | + availability_zone, forced_host, |
159 | +- user_data, metadata, injected_files, |
160 | ++ user_data, metadata, |
161 | + access_ip_v4, access_ip_v6, |
162 | + requested_networks, config_drive, |
163 | + auto_disk_config, reservation_id, |
164 | +@@ -810,9 +860,6 @@ class API(base.Base): |
165 | + except base64.binascii.Error: |
166 | + raise exception.InstanceUserDataMalformed() |
167 | + |
168 | +- self._checks_for_create_and_rebuild(context, image_id, boot_meta, |
169 | +- instance_type, metadata, injected_files) |
170 | +- |
171 | + self._check_requested_secgroups(context, security_groups) |
172 | + |
173 | + # Note: max_count is the number of instances requested by the user, |
174 | +@@ -1095,7 +1142,7 @@ class API(base.Base): |
175 | + instance_type, boot_meta, image_href, image_id, kernel_id, |
176 | + ramdisk_id, display_name, display_description, |
177 | + key_name, key_data, security_groups, availability_zone, |
178 | +- forced_host, user_data, metadata, injected_files, access_ip_v4, |
179 | ++ forced_host, user_data, metadata, access_ip_v4, |
180 | + access_ip_v6, requested_networks, config_drive, |
181 | + auto_disk_config, reservation_id, max_count) |
182 | + |
183 | +@@ -1115,6 +1162,12 @@ class API(base.Base): |
184 | + base_options, instance_type, boot_meta, min_count, max_count, |
185 | + block_device_mapping, legacy_bdm) |
186 | + |
187 | ++ # We can't do this check earlier because we need bdms from all sources |
188 | ++ # to have been merged in order to get the root bdm. |
189 | ++ self._checks_for_create_and_rebuild(context, image_id, boot_meta, |
190 | ++ instance_type, metadata, injected_files, |
191 | ++ block_device_mapping.root_bdm()) |
192 | ++ |
193 | + instance_group = self._get_requested_instance_group(context, |
194 | + scheduler_hints, check_server_group_quota) |
195 | + |
196 | +@@ -2333,8 +2386,9 @@ class API(base.Base): |
197 | + self._check_auto_disk_config(image=image, **kwargs) |
198 | + |
199 | + flavor = instance.get_flavor() |
200 | ++ root_bdm = self._get_root_bdm(context, instance) |
201 | + self._checks_for_create_and_rebuild(context, image_id, image, |
202 | +- flavor, metadata, files_to_inject) |
203 | ++ flavor, metadata, files_to_inject, root_bdm) |
204 | + |
205 | + kernel_id, ramdisk_id = self._handle_kernel_and_ramdisk( |
206 | + context, None, None, image) |
207 | +@@ -3201,15 +3255,18 @@ class API(base.Base): |
208 | + uuids = [instance.uuid for instance in instances] |
209 | + return self.db.instance_fault_get_by_instance_uuids(context, uuids) |
210 | + |
211 | +- def is_volume_backed_instance(self, context, instance, bdms=None): |
212 | +- if not instance.image_ref: |
213 | +- return True |
214 | +- |
215 | ++ def _get_root_bdm(self, context, instance, bdms=None): |
216 | + if bdms is None: |
217 | + bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( |
218 | + context, instance.uuid) |
219 | + |
220 | +- root_bdm = bdms.root_bdm() |
221 | ++ return bdms.root_bdm() |
222 | ++ |
223 | ++ def is_volume_backed_instance(self, context, instance, bdms=None): |
224 | ++ if not instance.image_ref: |
225 | ++ return True |
226 | ++ |
227 | ++ root_bdm = self._get_root_bdm(context, instance, bdms) |
228 | + if not root_bdm: |
229 | + return False |
230 | + return root_bdm.is_volume |
231 | +diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py |
232 | +index bf36960..b18c1e5 100644 |
233 | +--- a/nova/tests/unit/compute/test_compute.py |
234 | ++++ b/nova/tests/unit/compute/test_compute.py |
235 | +@@ -11356,6 +11356,8 @@ class ComputeInactiveImageTestCase(BaseTestCase): |
236 | + return {'id': id, 'min_disk': None, 'min_ram': None, |
237 | + 'name': 'fake_name', |
238 | + 'status': 'deleted', |
239 | ++ 'min_ram': 0, |
240 | ++ 'min_disk': 0, |
241 | + 'properties': {'kernel_id': 'fake_kernel_id', |
242 | + 'ramdisk_id': 'fake_ramdisk_id', |
243 | + 'something_else': 'meow'}} |
244 | +@@ -11708,78 +11710,175 @@ class CheckRequestedImageTestCase(test.TestCase): |
245 | + |
246 | + def test_no_image_specified(self): |
247 | + self.compute_api._check_requested_image(self.context, None, None, |
248 | +- self.instance_type) |
249 | ++ self.instance_type, None) |
250 | + |
251 | + def test_image_status_must_be_active(self): |
252 | + image = dict(id='123', status='foo') |
253 | + |
254 | + self.assertRaises(exception.ImageNotActive, |
255 | + self.compute_api._check_requested_image, self.context, |
256 | +- image['id'], image, self.instance_type) |
257 | ++ image['id'], image, self.instance_type, None) |
258 | + |
259 | + image['status'] = 'active' |
260 | + self.compute_api._check_requested_image(self.context, image['id'], |
261 | +- image, self.instance_type) |
262 | ++ image, self.instance_type, None) |
263 | + |
264 | + def test_image_min_ram_check(self): |
265 | + image = dict(id='123', status='active', min_ram='65') |
266 | + |
267 | + self.assertRaises(exception.FlavorMemoryTooSmall, |
268 | + self.compute_api._check_requested_image, self.context, |
269 | +- image['id'], image, self.instance_type) |
270 | ++ image['id'], image, self.instance_type, None) |
271 | + |
272 | + image['min_ram'] = '64' |
273 | + self.compute_api._check_requested_image(self.context, image['id'], |
274 | +- image, self.instance_type) |
275 | ++ image, self.instance_type, None) |
276 | + |
277 | + def test_image_min_disk_check(self): |
278 | + image = dict(id='123', status='active', min_disk='2') |
279 | + |
280 | + self.assertRaises(exception.FlavorDiskTooSmall, |
281 | + self.compute_api._check_requested_image, self.context, |
282 | +- image['id'], image, self.instance_type) |
283 | ++ image['id'], image, self.instance_type, None) |
284 | + |
285 | + image['min_disk'] = '1' |
286 | + self.compute_api._check_requested_image(self.context, image['id'], |
287 | +- image, self.instance_type) |
288 | ++ image, self.instance_type, None) |
289 | + |
290 | + def test_image_too_large(self): |
291 | + image = dict(id='123', status='active', size='1073741825') |
292 | + |
293 | + self.assertRaises(exception.FlavorDiskTooSmall, |
294 | + self.compute_api._check_requested_image, self.context, |
295 | +- image['id'], image, self.instance_type) |
296 | ++ image['id'], image, self.instance_type, None) |
297 | + |
298 | + image['size'] = '1073741824' |
299 | + self.compute_api._check_requested_image(self.context, image['id'], |
300 | +- image, self.instance_type) |
301 | ++ image, self.instance_type, None) |
302 | + |
303 | + def test_root_gb_zero_disables_size_check(self): |
304 | + self.instance_type['root_gb'] = 0 |
305 | + image = dict(id='123', status='active', size='1073741825') |
306 | + |
307 | + self.compute_api._check_requested_image(self.context, image['id'], |
308 | +- image, self.instance_type) |
309 | ++ image, self.instance_type, None) |
310 | + |
311 | + def test_root_gb_zero_disables_min_disk(self): |
312 | + self.instance_type['root_gb'] = 0 |
313 | + image = dict(id='123', status='active', min_disk='2') |
314 | + |
315 | + self.compute_api._check_requested_image(self.context, image['id'], |
316 | +- image, self.instance_type) |
317 | ++ image, self.instance_type, None) |
318 | + |
319 | + def test_config_drive_option(self): |
320 | + image = {'id': 1, 'status': 'active'} |
321 | + image['properties'] = {'img_config_drive': 'optional'} |
322 | + self.compute_api._check_requested_image(self.context, image['id'], |
323 | +- image, self.instance_type) |
324 | ++ image, self.instance_type, None) |
325 | + image['properties'] = {'img_config_drive': 'mandatory'} |
326 | + self.compute_api._check_requested_image(self.context, image['id'], |
327 | +- image, self.instance_type) |
328 | ++ image, self.instance_type, None) |
329 | + image['properties'] = {'img_config_drive': 'bar'} |
330 | + self.assertRaises(exception.InvalidImageConfigDrive, |
331 | + self.compute_api._check_requested_image, |
332 | +- self.context, image['id'], image, self.instance_type) |
333 | ++ self.context, image['id'], image, self.instance_type, |
334 | ++ None) |
335 | ++ |
336 | ++ def test_volume_blockdevicemapping(self): |
337 | ++ # We should allow a root volume which is larger than the flavor root |
338 | ++ # disk. |
339 | ++ # We should allow a root volume created from an image whose min_disk is |
340 | ++ # larger than the flavor root disk. |
341 | ++ image_uuid = str(uuid.uuid4()) |
342 | ++ image = dict(id=image_uuid, status='active', |
343 | ++ size=self.instance_type.root_gb * units.Gi, |
344 | ++ min_disk=self.instance_type.root_gb + 1) |
345 | ++ |
346 | ++ volume_uuid = str(uuid.uuid4()) |
347 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
348 | ++ source_type='volume', destination_type='volume', |
349 | ++ volume_id=volume_uuid, volume_size=self.instance_type.root_gb + 1) |
350 | ++ |
351 | ++ self.compute_api._check_requested_image(self.context, image['id'], |
352 | ++ image, self.instance_type, root_bdm) |
353 | ++ |
354 | ++ def test_volume_blockdevicemapping_min_disk(self): |
355 | ++ # A bdm object volume smaller than the image's min_disk should not be |
356 | ++ # allowed |
357 | ++ image_uuid = str(uuid.uuid4()) |
358 | ++ image = dict(id=image_uuid, status='active', |
359 | ++ size=self.instance_type.root_gb * units.Gi, |
360 | ++ min_disk=self.instance_type.root_gb + 1) |
361 | ++ |
362 | ++ volume_uuid = str(uuid.uuid4()) |
363 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
364 | ++ source_type='image', destination_type='volume', |
365 | ++ image_id=image_uuid, volume_id=volume_uuid, |
366 | ++ volume_size=self.instance_type.root_gb) |
367 | ++ |
368 | ++ self.assertRaises(exception.FlavorDiskTooSmall, |
369 | ++ self.compute_api._check_requested_image, |
370 | ++ self.context, image_uuid, image, self.instance_type, |
371 | ++ root_bdm) |
372 | ++ |
373 | ++ def test_volume_blockdevicemapping_min_disk_no_size(self): |
374 | ++ # We should allow a root volume whose size is not given |
375 | ++ image_uuid = str(uuid.uuid4()) |
376 | ++ image = dict(id=image_uuid, status='active', |
377 | ++ size=self.instance_type.root_gb * units.Gi, |
378 | ++ min_disk=self.instance_type.root_gb) |
379 | ++ |
380 | ++ volume_uuid = str(uuid.uuid4()) |
381 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
382 | ++ source_type='volume', destination_type='volume', |
383 | ++ volume_id=volume_uuid, volume_size=None) |
384 | ++ |
385 | ++ self.compute_api._check_requested_image(self.context, image['id'], |
386 | ++ image, self.instance_type, root_bdm) |
387 | ++ |
388 | ++ def test_image_blockdevicemapping(self): |
389 | ++ # Test that we can succeed when passing bdms, and the root bdm isn't a |
390 | ++ # volume |
391 | ++ image_uuid = str(uuid.uuid4()) |
392 | ++ image = dict(id=image_uuid, status='active', |
393 | ++ size=self.instance_type.root_gb * units.Gi, min_disk=0) |
394 | ++ |
395 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
396 | ++ source_type='image', destination_type='local', image_id=image_uuid) |
397 | ++ |
398 | ++ self.compute_api._check_requested_image(self.context, image['id'], |
399 | ++ image, self.instance_type, root_bdm) |
400 | ++ |
401 | ++ def test_image_blockdevicemapping_too_big(self): |
402 | ++ # We should do a size check against flavor if we were passed bdms but |
403 | ++ # the root bdm isn't a volume |
404 | ++ image_uuid = str(uuid.uuid4()) |
405 | ++ image = dict(id=image_uuid, status='active', |
406 | ++ size=(self.instance_type.root_gb + 1) * units.Gi, |
407 | ++ min_disk=0) |
408 | ++ |
409 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
410 | ++ source_type='image', destination_type='local', image_id=image_uuid) |
411 | ++ |
412 | ++ self.assertRaises(exception.FlavorDiskTooSmall, |
413 | ++ self.compute_api._check_requested_image, |
414 | ++ self.context, image['id'], |
415 | ++ image, self.instance_type, root_bdm) |
416 | ++ |
417 | ++ def test_image_blockdevicemapping_min_disk(self): |
418 | ++ # We should do a min_disk check against flavor if we were passed bdms |
419 | ++ # but the root bdm isn't a volume |
420 | ++ image_uuid = str(uuid.uuid4()) |
421 | ++ image = dict(id=image_uuid, status='active', |
422 | ++ size=0, min_disk=self.instance_type.root_gb + 1) |
423 | ++ |
424 | ++ root_bdm = block_device_obj.BlockDeviceMapping( |
425 | ++ source_type='image', destination_type='local', image_id=image_uuid) |
426 | ++ |
427 | ++ self.assertRaises(exception.FlavorDiskTooSmall, |
428 | ++ self.compute_api._check_requested_image, |
429 | ++ self.context, image['id'], |
430 | ++ image, self.instance_type, root_bdm) |
431 | + |
432 | + |
433 | + class ComputeHooksTestCase(test.BaseHookTestCase): |
434 | +diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py |
435 | +index 47848a9..5b4c2b3 100644 |
436 | +--- a/nova/tests/unit/compute/test_compute_api.py |
437 | ++++ b/nova/tests/unit/compute/test_compute_api.py |
438 | +@@ -2257,15 +2257,16 @@ class _ComputeAPIUnitTestMixIn(object): |
439 | + vm_state=vm_states.ACTIVE, cell_name='fake-cell', |
440 | + launched_at=timeutils.utcnow(), |
441 | + system_metadata=orig_system_metadata, |
442 | ++ image_ref='foo', |
443 | + expected_attrs=['system_metadata']) |
444 | + get_flavor.return_value = test_flavor.fake_flavor |
445 | + flavor = instance.get_flavor() |
446 | +- image_href = '' |
447 | ++ image_href = 'foo' |
448 | + image = {"min_ram": 10, "min_disk": 1, |
449 | + "properties": {'architecture': arch.X86_64}} |
450 | + admin_pass = '' |
451 | + files_to_inject = [] |
452 | +- bdms = [] |
453 | ++ bdms = objects.BlockDeviceMappingList() |
454 | + |
455 | + _get_image.return_value = (None, image) |
456 | + bdm_get_by_instance_uuid.return_value = bdms |
457 | +@@ -2284,7 +2285,7 @@ class _ComputeAPIUnitTestMixIn(object): |
458 | + |
459 | + _check_auto_disk_config.assert_called_once_with(image=image) |
460 | + _checks_for_create_and_rebuild.assert_called_once_with(self.context, |
461 | +- None, image, flavor, {}, []) |
462 | ++ None, image, flavor, {}, [], None) |
463 | + self.assertNotEqual(orig_system_metadata, instance.system_metadata) |
464 | + |
465 | + @mock.patch.object(objects.Instance, 'save') |
466 | +@@ -2309,7 +2310,7 @@ class _ComputeAPIUnitTestMixIn(object): |
467 | + 'vm_mode': 'xen'}} |
468 | + admin_pass = '' |
469 | + files_to_inject = [] |
470 | +- bdms = [] |
471 | ++ bdms = objects.BlockDeviceMappingList() |
472 | + |
473 | + instance = fake_instance.fake_instance_obj(self.context, |
474 | + vm_state=vm_states.ACTIVE, cell_name='fake-cell', |
475 | +@@ -2342,7 +2343,7 @@ class _ComputeAPIUnitTestMixIn(object): |
476 | + |
477 | + _check_auto_disk_config.assert_called_once_with(image=new_image) |
478 | + _checks_for_create_and_rebuild.assert_called_once_with(self.context, |
479 | +- None, new_image, flavor, {}, []) |
480 | ++ None, new_image, flavor, {}, [], None) |
481 | + self.assertEqual(vm_mode.XEN, instance.vm_mode) |
482 | + |
483 | + def _test_check_injected_file_quota_onset_file_limit_exceeded(self, |
484 | +diff --git a/nova/tests/unit/compute/test_compute_cells.py b/nova/tests/unit/compute/test_compute_cells.py |
485 | +index a769e1d..77d3dd7 100644 |
486 | +--- a/nova/tests/unit/compute/test_compute_cells.py |
487 | ++++ b/nova/tests/unit/compute/test_compute_cells.py |
488 | +@@ -236,11 +236,13 @@ class CellsConductorAPIRPCRedirect(test.NoDBTestCase): |
489 | + @mock.patch.object(compute_api.API, '_check_and_transform_bdm') |
490 | + @mock.patch.object(compute_api.API, '_get_image') |
491 | + @mock.patch.object(compute_api.API, '_validate_and_build_base_options') |
492 | +- def test_build_instances(self, _validate, _get_image, _check_bdm, |
493 | ++ @mock.patch.object(compute_api.API, '_checks_for_create_and_rebuild') |
494 | ++ def test_build_instances(self, _checks_for_create_and_rebuild, |
495 | ++ _validate, _get_image, _check_bdm, |
496 | + _provision, _record_action_start): |
497 | + _get_image.return_value = (None, 'fake-image') |
498 | + _validate.return_value = ({}, 1) |
499 | +- _check_bdm.return_value = 'bdms' |
500 | ++ _check_bdm.return_value = objects.BlockDeviceMappingList() |
501 | + _provision.return_value = 'instances' |
502 | + |
503 | + self.compute_api.create(self.context, 'fake-flavor', 'fake-image') |
504 | +@@ -309,7 +311,7 @@ class CellsConductorAPIRPCRedirect(test.NoDBTestCase): |
505 | + "properties": {'architecture': 'x86_64'}} |
506 | + admin_pass = '' |
507 | + files_to_inject = [] |
508 | +- bdms = [] |
509 | ++ bdms = objects.BlockDeviceMappingList() |
510 | + |
511 | + _get_image.return_value = (None, image) |
512 | + bdm_get_by_instance_uuid.return_value = bdms |
513 | +-- |
514 | +2.1.4 |
515 | + |
516 | |
517 | === modified file 'debian/patches/series' |
518 | --- debian/patches/series 2015-08-03 20:04:14 +0000 |
519 | +++ debian/patches/series 2015-09-08 23:22:49 +0000 |
520 | @@ -7,3 +7,4 @@ |
521 | #rate-limit-power-syncs.patch |
522 | skip-ubuntu-tests.patch |
523 | skip-proxy-test.patch |
524 | +not-check-disk-size.patch |