Merge ~ltrager/maas:lp1701694_2.2 into maas:2.2

Proposed by Lee Trager on 2017-07-19
Status: Merged
Approved by: Lee Trager on 2017-07-27
Approved revision: c262efce2849c532e1373662b12354f5d5e0eea5
Merge reported by: Lee Trager
Merged at revision: c262efce2849c532e1373662b12354f5d5e0eea5
Proposed branch: ~ltrager/maas:lp1701694_2.2
Merge into: maas:2.2
Diff against target: 727 lines (+186/-138)
22 files modified
src/maasserver/bootresources.py (+3/-3)
src/maasserver/forms/__init__.py (+11/-13)
src/maasserver/forms/tests/test_bootresource.py (+45/-2)
src/maasserver/models/bootresource.py (+12/-3)
src/maasserver/models/tests/test_bootresource.py (+21/-0)
src/maasserver/tests/test_bootresources.py (+3/-3)
src/maasserver/utils/osystems.py (+4/-5)
src/maasserver/utils/tests/test_osystems.py (+25/-0)
src/provisioningserver/drivers/osystem/__init__.py (+6/-5)
src/provisioningserver/drivers/osystem/bootloader.py (+0/-4)
src/provisioningserver/drivers/osystem/centos.py (+28/-24)
src/provisioningserver/drivers/osystem/custom.py (+0/-5)
src/provisioningserver/drivers/osystem/tests/test_base.py (+10/-1)
src/provisioningserver/drivers/osystem/tests/test_bootloader.py (+0/-5)
src/provisioningserver/drivers/osystem/tests/test_centos.py (+5/-19)
src/provisioningserver/drivers/osystem/tests/test_custom.py (+0/-9)
src/provisioningserver/drivers/osystem/tests/test_ubuntu.py (+11/-6)
src/provisioningserver/drivers/osystem/tests/test_ubuntucore.py (+0/-9)
src/provisioningserver/drivers/osystem/ubuntu.py (+1/-9)
src/provisioningserver/drivers/osystem/ubuntucore.py (+0/-5)
src/provisioningserver/drivers/osystem/windows.py (+1/-5)
src/provisioningserver/testing/os.py (+0/-3)
Reviewer Review Type Date Requested Status
Blake Rouse (community) 2017-07-19 Approve on 2017-07-21
Review via email: mp+327753@code.launchpad.net

Commit message

Allow uploading images with the format osystem/release.

All images uploaded are now of rtype UPLOADED. Users can upload using the format osystem/release where osystem is a supported OS.

Fixes: LP: #1701694, #1361370

Description of the change

This is a backport of https://code.launchpad.net/~ltrager/maas/+git/maas/+merge/327482 however I also had to backport the CentOS customization from https://code.launchpad.net/~ltrager/maas/rhel_driver/+merge/324909 as well.

To post a comment you must log in.
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/bootresources.py b/src/maasserver/bootresources.py
2index 996a6a0..f3c3824 100644
3--- a/src/maasserver/bootresources.py
4+++ b/src/maasserver/bootresources.py
5@@ -224,11 +224,11 @@ class SimpleStreamsHandler:
6 def get_boot_resource_identifiers(self, resource):
7 """Return tuple (os, arch, subarch, series) for the given resource."""
8 arch, subarch = resource.split_arch()
9- if resource.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
10+ if '/' in resource.name:
11+ os, series = resource.name.split('/')
12+ else:
13 os = 'custom'
14 series = resource.name
15- else:
16- os, series = resource.name.split('/')
17 return (os, arch, subarch, series)
18
19 def get_product_name(self, resource):
20diff --git a/src/maasserver/forms/__init__.py b/src/maasserver/forms/__init__.py
21index c03cc54..e6384c8 100644
22--- a/src/maasserver/forms/__init__.py
23+++ b/src/maasserver/forms/__init__.py
24@@ -2237,11 +2237,19 @@ class BootResourceForm(MAASModelForm):
25 If the passed resource already has a match in the database then that
26 resource is returned. If not then the passed resource is returned.
27 """
28+ if resource.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
29+ # Uploaded BootResources were previously generated, now they're
30+ # uploaded. Search for both to convert.
31+ rtypes = [
32+ BOOT_RESOURCE_TYPE.UPLOADED, BOOT_RESOURCE_TYPE.GENERATED]
33+ else:
34+ rtypes = [resource.type]
35 existing_resource = get_one(
36 BootResource.objects.filter(
37- rtype=resource.rtype,
38+ rtype__in=rtypes,
39 name=resource.name, architecture=resource.architecture))
40 if existing_resource is not None:
41+ existing_resource.rtype = resource.rtype
42 return existing_resource
43 return resource
44
45@@ -2289,24 +2297,14 @@ class BootResourceForm(MAASModelForm):
46 This implementation of `save` does not support the `commit` argument.
47 """
48 resource = super(BootResourceForm, self).save(commit=False)
49-
50- # XXX blake_r 2014-09-22 bug=1361370: Temporarily support the ability
51- # to upload a generated image. This should only exist while CentOS and
52- # Windows images need to be uploaded, rather than synced or generated.
53- if '/' not in resource.name:
54- label = 'uploaded'
55- resource.rtype = BOOT_RESOURCE_TYPE.UPLOADED
56- else:
57- label = 'generated'
58- resource.rtype = BOOT_RESOURCE_TYPE.GENERATED
59-
60+ resource.rtype = BOOT_RESOURCE_TYPE.UPLOADED
61 resource = self.get_existing_resource(resource)
62 resource.extra = {'subarches': resource.architecture.split('/')[1]}
63 if 'title' in self.cleaned_data:
64 resource.extra['title'] = self.cleaned_data['title']
65
66 resource.save()
67- resource_set = self.create_resource_set(resource, label)
68+ resource_set = self.create_resource_set(resource, 'uploaded')
69 self.create_resource_file(
70 resource_set, self.cleaned_data)
71 return resource
72diff --git a/src/maasserver/forms/tests/test_bootresource.py b/src/maasserver/forms/tests/test_bootresource.py
73index be7845a..5fb843f 100644
74--- a/src/maasserver/forms/tests/test_bootresource.py
75+++ b/src/maasserver/forms/tests/test_bootresource.py
76@@ -8,6 +8,7 @@ __all__ = []
77 import random
78
79 from django.core.files.uploadedfile import SimpleUploadedFile
80+from maasserver.clusterrpc import osystems
81 from maasserver.enum import (
82 BOOT_RESOURCE_FILE_TYPE,
83 BOOT_RESOURCE_TYPE,
84@@ -99,8 +100,11 @@ class TestBootResourceForm(MAASServerTestCase):
85 written_content = stream.read()
86 self.assertEqual(content, written_content)
87
88- def test_creates_boot_resoures_with_generated_rtype(self):
89+ def test_creates_boot_resoures_with_uploaded_rtype(self):
90 os = factory.make_name('os')
91+ self.patch(
92+ osystems, 'gen_all_known_operating_systems').return_value = [
93+ {'name': os}]
94 series = factory.make_name('series')
95 name = '%s/%s' % (os, series)
96 architecture = make_usable_architecture(self)
97@@ -118,7 +122,7 @@ class TestBootResourceForm(MAASServerTestCase):
98 self.assertTrue(form.is_valid(), form._errors)
99 form.save()
100 resource = BootResource.objects.get(
101- rtype=BOOT_RESOURCE_TYPE.GENERATED,
102+ rtype=BOOT_RESOURCE_TYPE.UPLOADED,
103 name=name, architecture=architecture)
104 resource_set = resource.sets.first()
105 rfile = resource_set.files.first()
106@@ -131,6 +135,9 @@ class TestBootResourceForm(MAASServerTestCase):
107
108 def test_adds_boot_resource_set_to_existing_generated_boot_resource(self):
109 os = factory.make_name('os')
110+ self.patch(
111+ osystems, 'gen_all_known_operating_systems').return_value = [
112+ {'name': os}]
113 series = factory.make_name('series')
114 name = '%s/%s' % (os, series)
115 architecture = make_usable_architecture(self)
116@@ -159,6 +166,42 @@ class TestBootResourceForm(MAASServerTestCase):
117 with rfile.largefile.content.open('rb') as stream:
118 written_content = stream.read()
119 self.assertEqual(content, written_content)
120+ self.assertEqual(resource.rtype, BOOT_RESOURCE_TYPE.UPLOADED)
121+
122+ def test_adds_boot_resource_set_to_existing_uploaded_boot_resource(self):
123+ os = factory.make_name('os')
124+ self.patch(
125+ osystems, 'gen_all_known_operating_systems').return_value = [
126+ {'name': os}]
127+ series = factory.make_name('series')
128+ name = '%s/%s' % (os, series)
129+ architecture = make_usable_architecture(self)
130+ resource = factory.make_usable_boot_resource(
131+ rtype=BOOT_RESOURCE_TYPE.UPLOADED,
132+ name=name, architecture=architecture)
133+ upload_type, filetype = self.pick_filetype()
134+ size = random.randint(1024, 2048)
135+ content = factory.make_string(size).encode('utf-8')
136+ upload_name = factory.make_name('filename')
137+ uploaded_file = SimpleUploadedFile(content=content, name=upload_name)
138+ data = {
139+ 'name': name,
140+ 'architecture': architecture,
141+ 'filetype': upload_type,
142+ }
143+ form = BootResourceForm(data=data, files={'content': uploaded_file})
144+ self.assertTrue(form.is_valid(), form._errors)
145+ form.save()
146+ resource = reload_object(resource)
147+ resource_set = resource.sets.order_by('id').last()
148+ rfile = resource_set.files.first()
149+ self.assertTrue(filetype, rfile.filetype)
150+ self.assertTrue(filetype, rfile.filename)
151+ self.assertTrue(size, rfile.largefile.total_size)
152+ with rfile.largefile.content.open('rb') as stream:
153+ written_content = stream.read()
154+ self.assertEqual(content, written_content)
155+ self.assertEqual(resource.rtype, BOOT_RESOURCE_TYPE.UPLOADED)
156
157 def test_requires_fields(self):
158 form = BootResourceForm(data={})
159diff --git a/src/maasserver/models/bootresource.py b/src/maasserver/models/bootresource.py
160index 905e675..5af3eee 100644
161--- a/src/maasserver/models/bootresource.py
162+++ b/src/maasserver/models/bootresource.py
163@@ -187,6 +187,7 @@ class BootResourceManager(Manager):
164 rtypes = [
165 BOOT_RESOURCE_TYPE.SYNCED,
166 BOOT_RESOURCE_TYPE.GENERATED,
167+ BOOT_RESOURCE_TYPE.UPLOADED,
168 ]
169 name = '%s/%s' % (image['osystem'], image['release'])
170 else:
171@@ -442,9 +443,17 @@ class BootResource(CleanSave, TimestampedModel):
172 """
173 if self.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
174 if '/' in self.name:
175- raise ValidationError(
176- "%s boot resource cannot contain a '/' in it's name." % (
177- self.display_rtype))
178+ # Avoid circular dependency
179+ from maasserver.clusterrpc.osystems import (
180+ gen_all_known_operating_systems,
181+ )
182+ osystem = self.name.split('/')[0]
183+ if osystem not in {
184+ i['name'] for i in gen_all_known_operating_systems()}:
185+ raise ValidationError(
186+ "%s boot resource cannot contain a '/' in it's name "
187+ "unless it starts with a supported operating system."
188+ % (self.display_rtype))
189 elif self.rtype in RTYPE_REQUIRING_OS_SERIES_NAME:
190 if '/' not in self.name:
191 raise ValidationError(
192diff --git a/src/maasserver/models/tests/test_bootresource.py b/src/maasserver/models/tests/test_bootresource.py
193index 2efb4fc..59c3ac2 100644
194--- a/src/maasserver/models/tests/test_bootresource.py
195+++ b/src/maasserver/models/tests/test_bootresource.py
196@@ -10,6 +10,7 @@ from datetime import datetime
197 import random
198
199 from django.core.exceptions import ValidationError
200+from maasserver.clusterrpc import osystems
201 from maasserver.clusterrpc.testing.boot_images import make_rpc_boot_image
202 from maasserver.enum import (
203 BOOT_RESOURCE_FILE_TYPE,
204@@ -771,6 +772,26 @@ class TestBootResource(MAASServerTestCase):
205 self.assertRaises(
206 ValidationError, resource.save)
207
208+ def test_validation_allows_any_uploaded_name_slash_with_supported_os(self):
209+ osystem = factory.make_name('osystem')
210+ self.patch(
211+ osystems, 'gen_all_known_operating_systems').return_value = [
212+ {'name': osystem}]
213+ name = '%s/%s' % (osystem, factory.make_name('release'))
214+ arch = '%s/%s' % (
215+ factory.make_name('arch'), factory.make_name('subarch'))
216+ resource = BootResource(
217+ rtype=BOOT_RESOURCE_TYPE.UPLOADED, name=name, architecture=arch)
218+ resource.save()
219+
220+ def test_validation_allows_any_uploaded_name_without_slash(self):
221+ name = factory.make_name('name')
222+ arch = '%s/%s' % (
223+ factory.make_name('arch'), factory.make_name('subarch'))
224+ resource = BootResource(
225+ rtype=BOOT_RESOURCE_TYPE.UPLOADED, name=name, architecture=arch)
226+ resource.save()
227+
228 def test_create_raises_error_on_not_unique(self):
229 name = '%s/%s' % (
230 factory.make_name('os'), factory.make_name('series'))
231diff --git a/src/maasserver/tests/test_bootresources.py b/src/maasserver/tests/test_bootresources.py
232index 135715b..3c860e8 100644
233--- a/src/maasserver/tests/test_bootresources.py
234+++ b/src/maasserver/tests/test_bootresources.py
235@@ -200,11 +200,11 @@ class TestSimpleStreamsHandler(MAASServerTestCase):
236
237 def get_product_name_for_resource(self, resource):
238 arch, subarch = resource.architecture.split('/')
239- if resource.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
240+ if '/' in resource.name:
241+ os, series = resource.name.split('/')
242+ else:
243 os = 'custom'
244 series = resource.name
245- else:
246- os, series = resource.name.split('/')
247 return 'maas:boot:%s:%s:%s:%s' % (os, arch, subarch, series)
248
249 def make_usable_product_boot_resource(
250diff --git a/src/maasserver/utils/osystems.py b/src/maasserver/utils/osystems.py
251index d7ad380..2746d46 100644
252--- a/src/maasserver/utils/osystems.py
253+++ b/src/maasserver/utils/osystems.py
254@@ -25,7 +25,6 @@ from distro_info import UbuntuDistroInfo
255 from django.core.exceptions import ValidationError
256 from django.db.models import Q
257 from maasserver.clusterrpc.osystems import gen_all_known_operating_systems
258-from maasserver.enum import BOOT_RESOURCE_TYPE
259 from maasserver.models import (
260 BootResource,
261 BootSourceCache,
262@@ -57,7 +56,7 @@ def list_osystem_choices(osystems, include_default=True):
263 (osystem['name'], osystem['title'])
264 for osystem in osystems
265 ]
266- return choices
267+ return sorted(list(set(choices)))
268
269
270 def list_all_usable_releases(osystems):
271@@ -75,11 +74,11 @@ def list_all_usable_releases(osystems):
272 # When custom images are returned by list_all_usable_osystems
273 # the osystem name is 'custom' and the release name to whatever
274 # the user specified.
275- if resource.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
276+ if '/' in resource.name:
277+ osystem, release = resource.name.split('/')
278+ else:
279 osystem = 'custom'
280 release = resource.name
281- else:
282- osystem, release = resource.name.split('/')
283 if osystem not in titles:
284 titles[osystem] = {}
285 titles[osystem][release] = resource.extra['title']
286diff --git a/src/maasserver/utils/tests/test_osystems.py b/src/maasserver/utils/tests/test_osystems.py
287index e0d92a8..8ee6b92 100644
288--- a/src/maasserver/utils/tests/test_osystems.py
289+++ b/src/maasserver/utils/tests/test_osystems.py
290@@ -10,6 +10,7 @@ import random
291
292 from distro_info import UbuntuDistroInfo
293 from django.core.exceptions import ValidationError
294+from maasserver.clusterrpc import osystems
295 from maasserver.clusterrpc.testing.osystems import (
296 make_rpc_osystem,
297 make_rpc_release,
298@@ -95,6 +96,15 @@ class TestOsystems(MAASServerTestCase):
299 [(osystem['name'], osystem['title'])],
300 list_osystem_choices([osystem], include_default=False))
301
302+ def test_list_osystem_choices_doesnt_duplicate(self):
303+ self.assertEqual(
304+ [('custom', 'Custom')],
305+ list_osystem_choices(
306+ [
307+ {'name': 'custom', 'title': 'Custom'},
308+ {'name': 'custom', 'title': 'Custom'},
309+ ], include_default=False))
310+
311
312 class TestReleases(MAASServerTestCase):
313
314@@ -145,6 +155,21 @@ class TestReleases(MAASServerTestCase):
315 title,
316 list_all_usable_releases([osystem])[osystem['name']][0]['title'])
317
318+ def test_list_all_usable_releases_finds_uploaded_with_osystem(self):
319+ release = make_rpc_release()
320+ osystem = make_rpc_osystem(releases=[release])
321+ title = factory.make_name('title')
322+ self.patch(
323+ osystems, 'gen_all_known_operating_systems').return_value = [
324+ {'name': osystem['name']}]
325+ factory.make_BootResource(
326+ rtype=BOOT_RESOURCE_TYPE.UPLOADED,
327+ name='%s/%s' % (osystem['name'], release['name']),
328+ extra={'title': title})
329+ self.assertEquals(
330+ title,
331+ list_all_usable_releases([osystem])[osystem['name']][0]['title'])
332+
333 def test_list_all_releases_requiring_keys(self):
334 releases = [
335 make_rpc_release(requires_license_key=True) for _ in range(3)]
336diff --git a/src/provisioningserver/drivers/osystem/__init__.py b/src/provisioningserver/drivers/osystem/__init__.py
337index bdf6ff8..93a9f4b 100644
338--- a/src/provisioningserver/drivers/osystem/__init__.py
339+++ b/src/provisioningserver/drivers/osystem/__init__.py
340@@ -1,4 +1,4 @@
341-# Copyright 2014-2016 Canonical Ltd. This software is licensed under the
342+# Copyright 2014-2017 Canonical Ltd. This software is licensed under the
343 # GNU Affero General Public License version 3 (see the file LICENSE).
344
345 """Osystem Drivers."""
346@@ -67,10 +67,6 @@ class OperatingSystem(metaclass=ABCMeta):
347 """Title of the operating system."""
348
349 @abstractmethod
350- def is_release_supported(self, release):
351- """Return True when the release is supported, False otherwise."""
352-
353- @abstractmethod
354 def get_default_release(self):
355 """Return the default release to use when none is specified.
356
357@@ -96,6 +92,11 @@ class OperatingSystem(metaclass=ABCMeta):
358 :return: list of supported purposes
359 """
360
361+ def is_release_supported(self, release):
362+ """Return True when the release is supported, False otherwise."""
363+ # If the osystem matches assume all releases are supported.
364+ return True
365+
366 def format_release_choices(self, releases):
367 """Format the release choices that are presented to the user.
368
369diff --git a/src/provisioningserver/drivers/osystem/bootloader.py b/src/provisioningserver/drivers/osystem/bootloader.py
370index 6ada008..2811a82 100644
371--- a/src/provisioningserver/drivers/osystem/bootloader.py
372+++ b/src/provisioningserver/drivers/osystem/bootloader.py
373@@ -18,10 +18,6 @@ class BootLoaderOS(OperatingSystem):
374 name = 'bootloader'
375 title = 'Bootloader'
376
377- def is_release_supported(self, release):
378- # All releases are supported, they're pulled from the Ubuntu archive.
379- return True
380-
381 def get_default_release(self):
382 # No Default bootloader as it depends on the arch.
383 return ''
384diff --git a/src/provisioningserver/drivers/osystem/centos.py b/src/provisioningserver/drivers/osystem/centos.py
385index aee813b..b9f2290 100644
386--- a/src/provisioningserver/drivers/osystem/centos.py
387+++ b/src/provisioningserver/drivers/osystem/centos.py
388@@ -1,4 +1,4 @@
389-# Copyright 2014-2015 Canonical Ltd. This software is licensed under the
390+# Copyright 2014-2017 Canonical Ltd. This software is licensed under the
391 # GNU Affero General Public License version 3 (see the file LICENSE).
392
393 """CentOS Operating System."""
394@@ -14,20 +14,20 @@ from provisioningserver.drivers.osystem import (
395 OperatingSystem,
396 )
397
398-
399-DISTRO_SERIES_DEFAULT = 'centos65'
400-
401-# Regex matcher that is used to check if the release is supported.
402-# It needs to match the name "centosXY". Where "X" is the major version
403-# and "Y" is the minor version.
404-DISTRO_MATCHER = re.compile("centos(?P<major>[0-9])(?P<minor>[0-9])?\Z")
405+# Regex matcher that is used to check if the release is supported. The release
406+# name just has to start with 'centos' to be supported but the major, minor,
407+# and title are found if available to help format the title.
408+DISTRO_MATCHER = re.compile(
409+ '^centos((?P<major>[0-9])(?P<minor>[0-9])?)?([\-\.]?(?P<title>.+))?$',
410+ re.I)
411+DISTRO_SERIES_DEFAULT = 'centos70'
412
413
414 class CentOS(OperatingSystem):
415 """CentOS operating system."""
416
417- name = "centos"
418- title = "CentOS"
419+ name = 'centos'
420+ title = 'CentOS'
421
422 def get_boot_image_purposes(self, arch, subarch, release, label):
423 """Gets the purpose of each boot image."""
424@@ -35,11 +35,6 @@ class CentOS(OperatingSystem):
425 BOOT_IMAGE_PURPOSE.XINSTALL
426 ]
427
428- def is_release_supported(self, release):
429- """Return True when the release is supported, False otherwise."""
430- matched = DISTRO_MATCHER.match(release)
431- return matched is not None
432-
433 def get_default_release(self):
434 """Gets the default release to use when a release is not
435 explicit."""
436@@ -49,10 +44,14 @@ class CentOS(OperatingSystem):
437 """Return the title for the given release."""
438 matched = DISTRO_MATCHER.match(release)
439 if matched is None:
440- return None
441- matched_dict = matched.groupdict()
442- major = matched_dict['major']
443- minor = matched_dict['minor']
444+ # This should never happen as is_release_supported will return
445+ # false but just in case it does...
446+ return "%s %s" % (self.title, release)
447+
448+ ret = self.title
449+ major = matched.group('major')
450+ minor = matched.group('minor')
451+ title = matched.group('title')
452 # MAAS provided images via streams are not bound to a minor
453 # release version, which means we always provide the latest
454 # available release from CentOS 6 and CentOS 7. To address
455@@ -65,9 +64,14 @@ class CentOS(OperatingSystem):
456 # from the stream and the minor version doesn't match to what
457 # we publish. As such, we ensure that we only return minor
458 # if we have any other version other that X.0, 7.0 and 6.6.
459- if minor is None or minor == '0':
460- return "CentOS %s" % major
461+ if major is not None and minor is None or minor == '0':
462+ ret = "%s %s" % (ret, major)
463 elif major == '6' and minor == '6':
464- return "CentOS %s" % major
465- else:
466- return "CentOS %s.%s" % (major, minor)
467+ ret = "%s %s" % (ret, major)
468+ elif None not in (major, minor):
469+ ret = "%s %s.%s" % (ret, major, minor)
470+
471+ if title is not None:
472+ ret = "%s %s" % (ret, title)
473+
474+ return ret
475diff --git a/src/provisioningserver/drivers/osystem/custom.py b/src/provisioningserver/drivers/osystem/custom.py
476index 6e817e1..845c132 100644
477--- a/src/provisioningserver/drivers/osystem/custom.py
478+++ b/src/provisioningserver/drivers/osystem/custom.py
479@@ -27,11 +27,6 @@ class CustomOS(OperatingSystem):
480 # Custom images can only be used with XINSTALL.
481 return [BOOT_IMAGE_PURPOSE.XINSTALL]
482
483- def is_release_supported(self, release):
484- """Return True when the release is supported, False otherwise."""
485- # All release are supported, since the user uploaded it.
486- return True
487-
488 def get_default_release(self):
489 """Gets the default release to use when a release is not
490 explicit."""
491diff --git a/src/provisioningserver/drivers/osystem/tests/test_base.py b/src/provisioningserver/drivers/osystem/tests/test_base.py
492index 9c41dc4..1fa9ca1 100644
493--- a/src/provisioningserver/drivers/osystem/tests/test_base.py
494+++ b/src/provisioningserver/drivers/osystem/tests/test_base.py
495@@ -1,4 +1,4 @@
496-# Copyright 2014-2016 Canonical Ltd. This software is licensed under the
497+# Copyright 2014-2017 Canonical Ltd. This software is licensed under the
498 # GNU Affero General Public License version 3 (see the file LICENSE).
499
500 """Tests for `provisioningserver.drivers.osystem`."""
501@@ -42,6 +42,15 @@ class TestOperatingSystem(MAASTestCase):
502 osystem_module, 'list_boot_images_for').return_value = images
503 return images
504
505+ def test_is_release_supported(self):
506+ osystem = self.make_usable_osystem()
507+ releases = [factory.make_name('release') for _ in range(3)]
508+ supported = [
509+ osystem.is_release_supported(release)
510+ for release in releases
511+ ]
512+ self.assertEqual([True, True, True], supported)
513+
514 def test_format_release_choices(self):
515 osystem = self.make_usable_osystem()
516 releases = osystem.get_supported_releases()
517diff --git a/src/provisioningserver/drivers/osystem/tests/test_bootloader.py b/src/provisioningserver/drivers/osystem/tests/test_bootloader.py
518index da0766e..9d89480 100644
519--- a/src/provisioningserver/drivers/osystem/tests/test_bootloader.py
520+++ b/src/provisioningserver/drivers/osystem/tests/test_bootloader.py
521@@ -13,11 +13,6 @@ from provisioningserver.drivers.osystem.bootloader import BootLoaderOS
522
523 class TestCustomOS(MAASTestCase):
524
525- def test_is_release_supported(self):
526- osystem = BootLoaderOS()
527- self.assertTrue(
528- osystem.is_release_supported(factory.make_name('release')))
529-
530 def test_get_default_release(self):
531 osystem = BootLoaderOS()
532 self.assertEquals("", osystem.get_default_release())
533diff --git a/src/provisioningserver/drivers/osystem/tests/test_centos.py b/src/provisioningserver/drivers/osystem/tests/test_centos.py
534index 8b3dbb6..92f8be7 100644
535--- a/src/provisioningserver/drivers/osystem/tests/test_centos.py
536+++ b/src/provisioningserver/drivers/osystem/tests/test_centos.py
537@@ -1,4 +1,4 @@
538-# Copyright 2014-2015 Canonical Ltd. This software is licensed under the
539+# Copyright 2014-2017 Canonical Ltd. This software is licensed under the
540 # GNU Affero General Public License version 3 (see the file LICENSE).
541
542 """Tests for the CentOS module."""
543@@ -34,21 +34,6 @@ class TestCentOS(MAASTestCase):
544 BOOT_IMAGE_PURPOSE.XINSTALL,
545 ])
546
547- def test_is_release_supported(self):
548- name_supported = {
549- "centos6": True,
550- "centos65": True,
551- "centos7": True,
552- "centos71": True,
553- "cent65": False,
554- "cent": False,
555- "centos711": False,
556- }
557- osystem = CentOS()
558- for name, supported in name_supported.items():
559- self.expectThat(
560- osystem.is_release_supported(name), Equals(supported))
561-
562 def test_get_default_release(self):
563 osystem = CentOS()
564 expected = osystem.get_default_release()
565@@ -62,9 +47,10 @@ class TestCentOS(MAASTestCase):
566 "centos7": "CentOS 7",
567 "centos70": "CentOS 7", # See LP: #1654063
568 "centos71": "CentOS 7.1",
569- "cent65": None,
570- "cent": None,
571- "centos711": None,
572+ "centos65": "CentOS 6.5",
573+ "cent": "CentOS cent",
574+ "centos711": "CentOS 7.1 1",
575+ "centos71-custom": "CentOS 7.1 custom",
576 }
577 osystem = CentOS()
578 for name, title in name_titles.items():
579diff --git a/src/provisioningserver/drivers/osystem/tests/test_custom.py b/src/provisioningserver/drivers/osystem/tests/test_custom.py
580index 1b7ff8e..80a6cce 100644
581--- a/src/provisioningserver/drivers/osystem/tests/test_custom.py
582+++ b/src/provisioningserver/drivers/osystem/tests/test_custom.py
583@@ -51,15 +51,6 @@ class TestCustomOS(MAASTestCase):
584 BOOT_IMAGE_PURPOSE.XINSTALL,
585 ])
586
587- def test_is_release_supported(self):
588- osystem = CustomOS()
589- releases = [factory.make_name('release') for _ in range(3)]
590- supported = [
591- osystem.is_release_supported(release)
592- for release in releases
593- ]
594- self.assertEqual([True, True, True], supported)
595-
596 def test_get_default_release(self):
597 osystem = CustomOS()
598 self.assertEqual("", osystem.get_default_release())
599diff --git a/src/provisioningserver/drivers/osystem/tests/test_ubuntu.py b/src/provisioningserver/drivers/osystem/tests/test_ubuntu.py
600index d64faa9..f68f493 100644
601--- a/src/provisioningserver/drivers/osystem/tests/test_ubuntu.py
602+++ b/src/provisioningserver/drivers/osystem/tests/test_ubuntu.py
603@@ -19,12 +19,7 @@ from provisioningserver.drivers.osystem.ubuntu import UbuntuOS
604 class TestUbuntuOS(MAASTestCase):
605
606 def get_lts_release(self):
607- # XXX ltrager 2016-04-06 - python3-distro-info won't set the latest lts
608- # to Xenial until its been released. So we can start testing MAAS 2.0
609- # with Xenial by default override it here. Once Xenial is released this
610- # can be removed
611- # return UbuntuDistroInfo().lts()
612- return "xenial"
613+ return UbuntuDistroInfo().lts()
614
615 def get_release_title(self, release):
616 info = UbuntuDistroInfo()
617@@ -51,6 +46,16 @@ class TestUbuntuOS(MAASTestCase):
618 BOOT_IMAGE_PURPOSE.DISKLESS,
619 ])
620
621+ def test_is_release_supported(self):
622+ osystem = UbuntuOS()
623+ info = UbuntuDistroInfo()
624+ self.assertTrue(osystem.is_release_supported(random.choice(info.all)))
625+
626+ def test_get_lts_release(self):
627+ # Canary so we know when the lts changes
628+ osystem = UbuntuOS()
629+ self.assertEquals('xenial', osystem.get_lts_release())
630+
631 def test_get_default_release(self):
632 osystem = UbuntuOS()
633 expected = osystem.get_default_release()
634diff --git a/src/provisioningserver/drivers/osystem/tests/test_ubuntucore.py b/src/provisioningserver/drivers/osystem/tests/test_ubuntucore.py
635index 591a7bf..c01ee28 100644
636--- a/src/provisioningserver/drivers/osystem/tests/test_ubuntucore.py
637+++ b/src/provisioningserver/drivers/osystem/tests/test_ubuntucore.py
638@@ -51,15 +51,6 @@ class TestUbuntuCoreOS(MAASTestCase):
639 BOOT_IMAGE_PURPOSE.XINSTALL,
640 ])
641
642- def test_is_release_supported(self):
643- osystem = UbuntuCoreOS()
644- releases = [factory.make_name('release') for _ in range(3)]
645- supported = [
646- osystem.is_release_supported(release)
647- for release in releases
648- ]
649- self.assertEqual([True, True, True], supported)
650-
651 def test_get_default_release(self):
652 osystem = UbuntuCoreOS()
653 self.assertEqual("16", osystem.get_default_release())
654diff --git a/src/provisioningserver/drivers/osystem/ubuntu.py b/src/provisioningserver/drivers/osystem/ubuntu.py
655index 7490465..dd8d243 100644
656--- a/src/provisioningserver/drivers/osystem/ubuntu.py
657+++ b/src/provisioningserver/drivers/osystem/ubuntu.py
658@@ -42,15 +42,7 @@ class UbuntuOS(OperatingSystem):
659
660 def get_lts_release(self):
661 """Return the latest Ubuntu LTS release."""
662- lts_release = self.ubuntu_distro_info.lts()
663- # XXX ltrager 2016-04-06 - python3-distro-info won't set the latest lts
664- # to Xenial until its been released. So we can start testing MAAS 2.0
665- # with Xenial by default override it here. Once Xenial is released this
666- # can be removed
667- if lts_release == "trusty":
668- return "xenial"
669- else:
670- return lts_release
671+ return self.ubuntu_distro_info.lts()
672
673 def get_default_release(self):
674 """Gets the default release to use when a release is not
675diff --git a/src/provisioningserver/drivers/osystem/ubuntucore.py b/src/provisioningserver/drivers/osystem/ubuntucore.py
676index 0a1ea45..1830da6 100644
677--- a/src/provisioningserver/drivers/osystem/ubuntucore.py
678+++ b/src/provisioningserver/drivers/osystem/ubuntucore.py
679@@ -27,11 +27,6 @@ class UbuntuCoreOS(OperatingSystem):
680 # Custom images can only be used with XINSTALL.
681 return [BOOT_IMAGE_PURPOSE.XINSTALL]
682
683- def is_release_supported(self, release):
684- """Return True when the release is supported, False otherwise."""
685- # All release are supported, since the user uploaded it.
686- return True
687-
688 def get_default_release(self):
689 """Gets the default release to use when a release is not
690 explicit."""
691diff --git a/src/provisioningserver/drivers/osystem/windows.py b/src/provisioningserver/drivers/osystem/windows.py
692index a3bc514..ad7391d 100644
693--- a/src/provisioningserver/drivers/osystem/windows.py
694+++ b/src/provisioningserver/drivers/osystem/windows.py
695@@ -55,10 +55,6 @@ class WindowsOS(OperatingSystem):
696 purposes.append(BOOT_IMAGE_PURPOSE.INSTALL)
697 return purposes
698
699- def is_release_supported(self, release):
700- """Return True when the release is supported, False otherwise."""
701- return release in WINDOWS_CHOICES
702-
703 def get_default_release(self):
704 """Gets the default release to use when a release is not
705 explicit."""
706@@ -66,7 +62,7 @@ class WindowsOS(OperatingSystem):
707
708 def get_release_title(self, release):
709 """Return the title for the given release."""
710- return WINDOWS_CHOICES.get(release)
711+ return WINDOWS_CHOICES.get(release, release)
712
713 def requires_license_key(self, release):
714 return release in REQUIRE_LICENSE_KEY
715diff --git a/src/provisioningserver/testing/os.py b/src/provisioningserver/testing/os.py
716index 5dd7538..9bc5626 100644
717--- a/src/provisioningserver/testing/os.py
718+++ b/src/provisioningserver/testing/os.py
719@@ -34,9 +34,6 @@ class FakeOS(OperatingSystem):
720 def get_boot_image_purposes(self, *args):
721 return self.purpose
722
723- def is_release_supported(self, release):
724- return release in self.fake_list
725-
726 def get_supported_releases(self):
727 return self.fake_list
728

Subscribers

People subscribed via source and target branches

to all changes: