Merge lp:~blake-rouse/maas/fix-1445942-1.8 into lp:maas/1.8

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4039
Proposed branch: lp:~blake-rouse/maas/fix-1445942-1.8
Merge into: lp:maas/1.8
Diff against target: 254 lines (+129/-16)
5 files modified
src/maasserver/node_action.py (+8/-4)
src/maasserver/tests/test_node_action.py (+51/-10)
src/maasserver/utils/osystems.py (+25/-0)
src/maasserver/utils/tests/test_osystems.py (+43/-0)
src/maasserver/websockets/handlers/tests/test_node.py (+2/-2)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-1445942-1.8
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+268550@code.launchpad.net

Commit message

Validate the osystem and distro_series when using the deploy action. Strip the ending '*' on releases that accept a license key.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Self-approving backport.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/node_action.py'
2--- src/maasserver/node_action.py 2015-05-28 15:32:21 +0000
3+++ src/maasserver/node_action.py 2015-08-19 20:52:03 +0000
4@@ -33,6 +33,7 @@
5 from collections import OrderedDict
6
7 from crochet import TimeoutError
8+from django.core.exceptions import ValidationError
9 from maasserver import locks
10 from maasserver.enum import (
11 NODE_PERMISSION,
12@@ -49,6 +50,7 @@
13 is_failed_status,
14 NON_MONITORED_STATUSES,
15 )
16+from maasserver.utils.osystems import validate_osystem_and_distro_series
17 from metadataserver.enum import RESULT_TYPE
18 from metadataserver.models.noderesult import NodeResult
19 from provisioningserver.rpc.exceptions import (
20@@ -296,11 +298,13 @@
21 with locks.node_acquire:
22 self.node.acquire(self.user, token=None)
23
24- # Set the osystem in distro_series if provided and not empty.
25 if osystem and distro_series:
26- self.node.osystem = osystem
27- self.node.distro_series = distro_series
28- self.node.save()
29+ try:
30+ self.node.osystem, self.node.distro_series = (
31+ validate_osystem_and_distro_series(osystem, distro_series))
32+ self.node.save()
33+ except ValidationError as e:
34+ raise NodeActionError(e.message)
35
36 try:
37 self.node.start(self.user)
38
39=== modified file 'src/maasserver/tests/test_node_action.py'
40--- src/maasserver/tests/test_node_action.py 2015-05-27 20:44:21 +0000
41+++ src/maasserver/tests/test_node_action.py 2015-08-19 20:52:03 +0000
42@@ -48,7 +48,10 @@
43 )
44 from maasserver.testing.factory import factory
45 from maasserver.testing.orm import reload_object
46-from maasserver.testing.osystems import make_osystem_with_releases
47+from maasserver.testing.osystems import (
48+ make_osystem_with_releases,
49+ make_usable_osystem,
50+)
51 from maasserver.testing.testcase import (
52 MAASServerTestCase,
53 MAASTransactionServerTestCase,
54@@ -422,21 +425,59 @@
55 self.assertThat(
56 node_start, MockCalledOnceWith(user))
57
58+ def test_Deploy_raises_NodeActionError_for_invalid_os(self):
59+ user = factory.make_User()
60+ node = factory.make_Node(
61+ mac=True, status=NODE_STATUS.ALLOCATED,
62+ power_type='ether_wake', owner=user)
63+ self.patch(node, 'start')
64+ os_name = factory.make_name("os")
65+ release_name = factory.make_name("release")
66+ extra = {
67+ "osystem": os_name,
68+ "distro_series": release_name,
69+ }
70+ error = self.assertRaises(
71+ NodeActionError, Deploy(node, user).execute, **extra)
72+ self.assertEquals(
73+ "%s is not a support operating system." % os_name,
74+ error.message)
75+
76 def test_Deploy_sets_osystem_and_series(self):
77 user = factory.make_User()
78 node = factory.make_Node(
79 mac=True, status=NODE_STATUS.ALLOCATED,
80 power_type='ether_wake', owner=user)
81 self.patch(node, 'start')
82- osystem = make_osystem_with_releases(self)
83- extra = {
84- "osystem": osystem["name"],
85- "distro_series": osystem["releases"][0]["name"],
86- }
87- Deploy(node, user).execute(**extra)
88- self.expectThat(node.osystem, Equals(osystem["name"]))
89- self.expectThat(
90- node.distro_series, Equals(osystem["releases"][0]["name"]))
91+ osystem = make_usable_osystem(self)
92+ os_name = osystem["name"]
93+ release_name = osystem["releases"][0]["name"]
94+ extra = {
95+ "osystem": os_name,
96+ "distro_series": release_name
97+ }
98+ Deploy(node, user).execute(**extra)
99+ self.expectThat(node.osystem, Equals(os_name))
100+ self.expectThat(
101+ node.distro_series, Equals(release_name))
102+
103+ def test_Deploy_sets_osystem_and_series_strips_license_key_token(self):
104+ user = factory.make_User()
105+ node = factory.make_Node(
106+ mac=True, status=NODE_STATUS.ALLOCATED,
107+ power_type='ether_wake', owner=user)
108+ self.patch(node, 'start')
109+ osystem = make_usable_osystem(self)
110+ os_name = osystem["name"]
111+ release_name = osystem["releases"][0]["name"]
112+ extra = {
113+ "osystem": os_name,
114+ "distro_series": release_name + '*'
115+ }
116+ Deploy(node, user).execute(**extra)
117+ self.expectThat(node.osystem, Equals(os_name))
118+ self.expectThat(
119+ node.distro_series, Equals(release_name))
120
121 def test_Deploy_doesnt_set_osystem_and_series_if_os_missing(self):
122 user = factory.make_User()
123
124=== modified file 'src/maasserver/utils/osystems.py'
125--- src/maasserver/utils/osystems.py 2015-06-10 11:35:04 +0000
126+++ src/maasserver/utils/osystems.py 2015-08-19 20:52:03 +0000
127@@ -25,6 +25,7 @@
128
129 from operator import itemgetter
130
131+from django.core.exceptions import ValidationError
132 from maasserver.clusterrpc.osystems import gen_all_known_operating_systems
133
134
135@@ -176,3 +177,27 @@
136 for release in releases
137 if release['can_commission']
138 ]
139+
140+
141+def validate_osystem_and_distro_series(osystem, distro_series):
142+ """Validate `osystem` and `distro_series` are valid choices."""
143+ if '/' in distro_series:
144+ series_os, release = distro_series.split('/', 1)
145+ if series_os != osystem:
146+ raise ValidationError(
147+ "%s in distro_series does not match with "
148+ "operating system %s." % (distro_series, osystem))
149+ else:
150+ release = distro_series
151+ release = release.replace('*', '')
152+ usable_osystems = list_all_usable_osystems()
153+ found_osystem = get_osystem_from_osystems(usable_osystems, osystem)
154+ if found_osystem is None:
155+ raise ValidationError(
156+ "%s is not a support operating system." % osystem)
157+ found_release = get_release_from_osystem(found_osystem, release)
158+ if found_release is None:
159+ raise ValidationError(
160+ "%s/%s is not a support operating system and release "
161+ "combination." % (osystem, release))
162+ return osystem, release
163
164=== modified file 'src/maasserver/utils/tests/test_osystems.py'
165--- src/maasserver/utils/tests/test_osystems.py 2015-05-21 09:41:57 +0000
166+++ src/maasserver/utils/tests/test_osystems.py 2015-08-19 20:52:03 +0000
167@@ -17,11 +17,13 @@
168 from operator import itemgetter
169 import random
170
171+from django.core.exceptions import ValidationError
172 from maasserver.clusterrpc.testing.osystems import (
173 make_rpc_osystem,
174 make_rpc_release,
175 )
176 from maasserver.testing.factory import factory
177+from maasserver.testing.osystems import make_usable_osystem
178 from maasserver.testing.testcase import MAASServerTestCase
179 from maasserver.utils import osystems as osystems_module
180 from maasserver.utils.osystems import (
181@@ -33,6 +35,7 @@
182 list_commissioning_choices,
183 list_osystem_choices,
184 list_release_choices,
185+ validate_osystem_and_distro_series,
186 )
187
188
189@@ -253,3 +256,43 @@
190 for release in comm_releases
191 ]
192 self.assertEqual(choices, list_commissioning_choices([osystem]))
193+
194+
195+class TestValidateOsystemAndDistroSeries(MAASServerTestCase):
196+
197+ def test__raises_error_of_osystem_and_distro_series_dont_match(self):
198+ os = factory.make_name("os")
199+ release = "%s/%s" % (
200+ factory.make_name("os"), factory.make_name("release"))
201+ error = self.assertRaises(
202+ ValidationError, validate_osystem_and_distro_series, os, release)
203+ self.assertEquals(
204+ "%s in distro_series does not match with "
205+ "operating system %s." % (release, os), error.message)
206+
207+ def test__raises_error_if_not_supported_osystem(self):
208+ os = factory.make_name("os")
209+ release = factory.make_name("release")
210+ error = self.assertRaises(
211+ ValidationError, validate_osystem_and_distro_series, os, release)
212+ self.assertEquals(
213+ "%s is not a support operating system." % os,
214+ error.message)
215+
216+ def test__raises_error_if_not_supported_release(self):
217+ osystem = make_usable_osystem(self)
218+ release = factory.make_name("release")
219+ error = self.assertRaises(
220+ ValidationError, validate_osystem_and_distro_series,
221+ osystem['name'], release)
222+ self.assertEquals(
223+ "%s/%s is not a support operating system and release "
224+ "combination." % (osystem['name'], release),
225+ error.message)
226+
227+ def test__returns_osystem_and_release_with_license_key_stripped(self):
228+ osystem = make_usable_osystem(self)
229+ release = osystem['default_release']
230+ self.assertEquals(
231+ (osystem['name'], release),
232+ validate_osystem_and_distro_series(osystem['name'], release + '*'))
233
234=== modified file 'src/maasserver/websockets/handlers/tests/test_node.py'
235--- src/maasserver/websockets/handlers/tests/test_node.py 2015-05-28 15:07:01 +0000
236+++ src/maasserver/websockets/handlers/tests/test_node.py 2015-08-19 20:52:03 +0000
237@@ -37,7 +37,7 @@
238 )
239 from maasserver.testing.factory import factory
240 from maasserver.testing.orm import reload_object
241-from maasserver.testing.osystems import make_osystem_with_releases
242+from maasserver.testing.osystems import make_usable_osystem
243 from maasserver.testing.testcase import (
244 MAASServerTestCase,
245 MAASTransactionServerTestCase,
246@@ -719,7 +719,7 @@
247 user = factory.make_User()
248 factory.make_SSHKey(user)
249 node = factory.make_Node(status=NODE_STATUS.ALLOCATED, owner=user)
250- osystem = make_osystem_with_releases(self)
251+ osystem = make_usable_osystem(self)
252 handler = NodeHandler(user, {})
253 handler.action({
254 "system_id": node.system_id,

Subscribers

People subscribed via source and target branches

to all changes: