Merge lp:~billy-olsen/nova/kilo+lp1457517 into lp:~ubuntu-server-dev/nova/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
Reviewer Review Type Date Requested Status
Ubuntu Server Developers Pending
Review via email: mp+270466@code.launchpad.net

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

Subscribers

People subscribed via source and target branches