Merge ~mpontillo/maas:move-to-bionic--mpontillo into maas:master
- Git
- lp:~mpontillo/maas
- move-to-bionic--mpontillo
- Merge into master
Proposed by
Mike Pontillo
Status: | Rejected |
---|---|
Rejected by: | Adam Collard |
Proposed branch: | ~mpontillo/maas:move-to-bionic--mpontillo |
Merge into: | maas:master |
Diff against target: |
733 lines (+32/-357) 22 files modified
dev/null (+0/-2) required-packages/bionic (+0/-0) src/maasserver/api/auth.py (+1/-1) src/maasserver/context_processors.py (+1/-1) src/maasserver/forms/interface_link.py (+2/-2) src/maasserver/middleware.py (+1/-1) src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py (+1/-1) src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py (+2/-2) src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py (+1/-1) src/maasserver/models/tests/test_dnspublication.py (+2/-3) src/maasserver/static/js/angular/directives/pod_parameters.js (+4/-2) src/maasserver/static/js/angular/directives/tests/test_os_select.js (+5/-2) src/maasserver/testing/api.py (+1/-1) src/maasserver/testing/testclient.py (+2/-2) src/maasserver/tests/test_sequence.py (+2/-2) src/maasserver/views/account.py (+1/-1) src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py (+2/-2) src/provisioningserver/utils/shell.py (+0/-191) src/provisioningserver/utils/tests/test_network.py (+0/-8) src/provisioningserver/utils/tests/test_shell.py (+0/-128) src/provisioningserver/utils/tests/test_version.py (+2/-2) versions.cfg (+2/-2) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
MAAS Maintainers | Pending | ||
Review via email: mp+335632@code.launchpad.net |
Commit message
Description of the change
A few additions to Blake's move-to-bionic branch.
To post a comment you must log in.
- 17f57fb... by Mike Pontillo
-
Fix lint.
- 2e64536... by Mike Pontillo
-
Fix random failure in get_maas_version() tests.
Unmerged commits
- 2e64536... by Mike Pontillo
-
Fix random failure in get_maas_version() tests.
- 17f57fb... by Mike Pontillo
-
Fix lint.
- a233a00... by Mike Pontillo
-
Fix Django deprecation warnings.
- 02e5140... by Mike Pontillo
-
Remove unused installed_
curtin_ version variable. - 0a07b40... by Blake Rouse
-
Fix more tests and remove old code that is no longer used.
- 02085c2... by Blake Rouse
-
Remove deprecated calls that break tests.
- a6ff200... by Blake Rouse
-
Add new bionic packages. Remove old releases that 2.4 will not run on. Fix versions.cfg to work with new dependencies in bionic.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/required-packages/artful b/required-packages/bionic |
2 | index aad4c80..aad4c80 100644 |
3 | --- a/required-packages/artful |
4 | +++ b/required-packages/bionic |
5 | diff --git a/required-packages/wily b/required-packages/wily |
6 | deleted file mode 100644 |
7 | index aad4c80..0000000 |
8 | --- a/required-packages/wily |
9 | +++ /dev/null |
10 | @@ -1,2 +0,0 @@ |
11 | -pxelinux |
12 | -python3-petname |
13 | diff --git a/required-packages/xenial b/required-packages/xenial |
14 | deleted file mode 100644 |
15 | index aad4c80..0000000 |
16 | --- a/required-packages/xenial |
17 | +++ /dev/null |
18 | @@ -1,2 +0,0 @@ |
19 | -pxelinux |
20 | -python3-petname |
21 | diff --git a/required-packages/yakkety b/required-packages/yakkety |
22 | deleted file mode 100644 |
23 | index aad4c80..0000000 |
24 | --- a/required-packages/yakkety |
25 | +++ /dev/null |
26 | @@ -1,2 +0,0 @@ |
27 | -pxelinux |
28 | -python3-petname |
29 | diff --git a/required-packages/zesty b/required-packages/zesty |
30 | deleted file mode 100644 |
31 | index aad4c80..0000000 |
32 | --- a/required-packages/zesty |
33 | +++ /dev/null |
34 | @@ -1,2 +0,0 @@ |
35 | -pxelinux |
36 | -python3-petname |
37 | diff --git a/src/maasserver/api/auth.py b/src/maasserver/api/auth.py |
38 | index a14ba60..f443d97 100644 |
39 | --- a/src/maasserver/api/auth.py |
40 | +++ b/src/maasserver/api/auth.py |
41 | @@ -44,7 +44,7 @@ class MAASAPIAuthentication(OAuthAuthentication): |
42 | """ |
43 | |
44 | def is_authenticated(self, request): |
45 | - if request.user.is_authenticated(): |
46 | + if request.user.is_authenticated: |
47 | return request.user |
48 | |
49 | # The following is much the same as is_authenticated from Piston's |
50 | diff --git a/src/maasserver/context_processors.py b/src/maasserver/context_processors.py |
51 | index 39b1898..87ecc39 100644 |
52 | --- a/src/maasserver/context_processors.py |
53 | +++ b/src/maasserver/context_processors.py |
54 | @@ -34,7 +34,7 @@ def global_options(request): |
55 | user_completed_intro = False |
56 | if hasattr(request.user, 'userprofile'): |
57 | user_completed_intro = request.user.userprofile.completed_intro |
58 | - if request.user.is_authenticated(): |
59 | + if request.user.is_authenticated: |
60 | analytics_user_id = '%s-user%d' % (uuid, request.user.id) |
61 | else: |
62 | analytics_user_id = '%s-anon' % uuid |
63 | diff --git a/src/maasserver/forms/interface_link.py b/src/maasserver/forms/interface_link.py |
64 | index 2c02dc5..adfa4cf 100644 |
65 | --- a/src/maasserver/forms/interface_link.py |
66 | +++ b/src/maasserver/forms/interface_link.py |
67 | @@ -298,11 +298,11 @@ class InterfaceSetDefaultGatwayForm(forms.Form): |
68 | IPAddress(gateway).version |
69 | for gateway in unique_gateways |
70 | ) |
71 | - too_many = [ |
72 | + too_many = sorted([ |
73 | ip_family |
74 | for ip_family, count in gateway_versions.items() |
75 | if count > 1 |
76 | - ] |
77 | + ]) |
78 | if len(too_many) > 0: |
79 | set_form_error( |
80 | self, "link_id", |
81 | diff --git a/src/maasserver/middleware.py b/src/maasserver/middleware.py |
82 | index bde3fc7..8d49fb9 100644 |
83 | --- a/src/maasserver/middleware.py |
84 | +++ b/src/maasserver/middleware.py |
85 | @@ -105,7 +105,7 @@ class AccessMiddleware: |
86 | if is_public_path(request.path_info): |
87 | return None |
88 | |
89 | - if request.user.is_anonymous(): |
90 | + if request.user.is_anonymous: |
91 | return HttpResponseRedirect("%s?next=%s" % ( |
92 | reverse('login'), urlquote_plus(request.path))) |
93 | |
94 | diff --git a/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py b/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py |
95 | index 476baf3..66030f3 100644 |
96 | --- a/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py |
97 | +++ b/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py |
98 | @@ -24,7 +24,7 @@ class Migration(migrations.Migration): |
99 | ('updated', models.DateTimeField(editable=False)), |
100 | ('nos_driver', models.CharField(max_length=64, blank=True, default='')), |
101 | ('nos_parameters', maasserver.fields.JSONObjectField(max_length=32768, blank=True, default='')), |
102 | - ('node', models.OneToOneField(to='maasserver.Node')), |
103 | + ('node', models.OneToOneField(to='maasserver.Node', on_delete=models.CASCADE)), |
104 | ], |
105 | options={ |
106 | 'verbose_name': 'Switch', |
107 | diff --git a/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py b/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py |
108 | index 8a386e7..a4515a7 100644 |
109 | --- a/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py |
110 | +++ b/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py |
111 | @@ -21,7 +21,7 @@ class Migration(migrations.Migration): |
112 | fields=[ |
113 | ('created', models.DateTimeField(editable=False)), |
114 | ('updated', models.DateTimeField(editable=False)), |
115 | - ('node', models.OneToOneField(serialize=False, primary_key=True, to='maasserver.Node')), |
116 | + ('node', models.OneToOneField(serialize=False, primary_key=True, to='maasserver.Node', on_delete=models.CASCADE)), |
117 | ('version', models.CharField(blank=True, null=True, max_length=255)), |
118 | ('interfaces', maasserver.fields.JSONObjectField(default='', blank=True, max_length=32768)), |
119 | ('interface_update_hints', maasserver.fields.JSONObjectField(default='', blank=True, max_length=32768)), |
120 | @@ -38,6 +38,6 @@ class Migration(migrations.Migration): |
121 | migrations.AlterField( |
122 | model_name='switch', |
123 | name='node', |
124 | - field=models.OneToOneField(serialize=False, primary_key=True, to='maasserver.Node'), |
125 | + field=models.OneToOneField(serialize=False, primary_key=True, to='maasserver.Node', on_delete=models.CASCADE), |
126 | ), |
127 | ] |
128 | diff --git a/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py b/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py |
129 | index 98f4960..ba3d3aa 100644 |
130 | --- a/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py |
131 | +++ b/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py |
132 | @@ -23,7 +23,7 @@ class Migration(migrations.Migration): |
133 | ('updated', models.DateTimeField(editable=False)), |
134 | ('key', models.CharField(max_length=64)), |
135 | ('value', models.TextField()), |
136 | - ('node', models.ForeignKey(to='maasserver.Node', editable=False)), |
137 | + ('node', models.ForeignKey(to='maasserver.Node', editable=False, on_delete=models.CASCADE)), |
138 | ], |
139 | options={ |
140 | 'verbose_name': 'NodeMetadata', |
141 | diff --git a/src/maasserver/models/tests/test_dnspublication.py b/src/maasserver/models/tests/test_dnspublication.py |
142 | index f4374af..cd1ce20 100644 |
143 | --- a/src/maasserver/models/tests/test_dnspublication.py |
144 | +++ b/src/maasserver/models/tests/test_dnspublication.py |
145 | @@ -41,14 +41,13 @@ class TestZoneSerial(MAASServerTestCase): |
146 | def test_parameters_in_database(self): |
147 | zone_serial.create_if_not_exists() |
148 | query = ( |
149 | - "SELECT start_value, increment_by, max_value, " |
150 | - "min_value, is_cycled FROM %s" % zone_serial.name |
151 | + "SELECT last_value, log_cnt, is_called FROM %s" % zone_serial.name |
152 | ) |
153 | with connection.cursor() as cursor: |
154 | cursor.execute(query) |
155 | self.assertThat( |
156 | cursor.fetchone(), Equals( |
157 | - (1, 1, 2 ** 32 - 1, 1, True))) |
158 | + (3, 0, True))) |
159 | |
160 | |
161 | class TestDNSPublication(MAASServerTestCase): |
162 | diff --git a/src/maasserver/static/js/angular/directives/pod_parameters.js b/src/maasserver/static/js/angular/directives/pod_parameters.js |
163 | index 4ede72e..4e05584 100644 |
164 | --- a/src/maasserver/static/js/angular/directives/pod_parameters.js |
165 | +++ b/src/maasserver/static/js/angular/directives/pod_parameters.js |
166 | @@ -70,8 +70,10 @@ angular.module('MAAS').directive( |
167 | }); |
168 | html += '</maas-obj-field-group>'; |
169 | childScope = scope.$new(); |
170 | - fieldsElement.append($compile(html)( |
171 | - childScope, undefined, {maasObjForm: controller})); |
172 | + var ele = angular.element(html); |
173 | + fieldsElement.append(ele); |
174 | + $compile(ele)( |
175 | + childScope, undefined, {maasObjForm: controller}); |
176 | } |
177 | }; |
178 | |
179 | diff --git a/src/maasserver/static/js/angular/directives/tests/test_os_select.js b/src/maasserver/static/js/angular/directives/tests/test_os_select.js |
180 | index 6cd5d1a..9928063 100644 |
181 | --- a/src/maasserver/static/js/angular/directives/tests/test_os_select.js |
182 | +++ b/src/maasserver/static/js/angular/directives/tests/test_os_select.js |
183 | @@ -242,8 +242,11 @@ describe("maasOsSelect", function() { |
184 | release: "" |
185 | }; |
186 | $scope.$digest(); |
187 | - expect(directive.isolateScope().releases).toEqual( |
188 | - [['ubuntu/xenial', 'xenial']]); |
189 | + var release = directive.isolateScope().releases[0].map(function(txt) { |
190 | + return new String(txt); |
191 | + }); |
192 | + expect(release).toEqual( |
193 | + ['ubuntu/xenial', 'xenial']); |
194 | }); |
195 | |
196 | }); |
197 | diff --git a/src/maasserver/testing/api.py b/src/maasserver/testing/api.py |
198 | index ed71da0..43a4f3e 100644 |
199 | --- a/src/maasserver/testing/api.py |
200 | +++ b/src/maasserver/testing/api.py |
201 | @@ -171,7 +171,7 @@ class APITestCaseBase(MAASTestCase, metaclass=APITestType): |
202 | @transactional |
203 | def become_admin(self): |
204 | """Promote `self.user` to admin.""" |
205 | - self.assertFalse(self.user.is_anonymous(), ( |
206 | + self.assertFalse(self.user.is_anonymous, ( |
207 | "Cannot promote anonymous user to admin.")) |
208 | self.user.is_superuser = True |
209 | self.user.save() |
210 | diff --git a/src/maasserver/testing/testclient.py b/src/maasserver/testing/testclient.py |
211 | index 05cac37..a0cd0e4 100644 |
212 | --- a/src/maasserver/testing/testclient.py |
213 | +++ b/src/maasserver/testing/testclient.py |
214 | @@ -52,7 +52,7 @@ class MAASSensibleClient(SensibleClient): |
215 | def login(self, *, user=None, **credentials): |
216 | if user is None: |
217 | return super(MAASSensibleClient, self).login(**credentials) |
218 | - elif user.is_anonymous(): |
219 | + elif user.is_anonymous: |
220 | self.logout() |
221 | return False |
222 | else: |
223 | @@ -87,7 +87,7 @@ class MAASSensibleOAuthClient(MAASSensibleClient): |
224 | assert token is not None |
225 | return self._token_set(token) |
226 | else: |
227 | - if user.is_anonymous(): |
228 | + if user.is_anonymous: |
229 | self._token_clear() |
230 | return False |
231 | elif token is None: |
232 | diff --git a/src/maasserver/tests/test_sequence.py b/src/maasserver/tests/test_sequence.py |
233 | index 61c0f62..561bc76 100644 |
234 | --- a/src/maasserver/tests/test_sequence.py |
235 | +++ b/src/maasserver/tests/test_sequence.py |
236 | @@ -14,7 +14,7 @@ from django.db import ( |
237 | ) |
238 | from django.db.utils import ( |
239 | DatabaseError, |
240 | - OperationalError, |
241 | + DataError, |
242 | ProgrammingError, |
243 | ) |
244 | from maasserver.sequence import Sequence |
245 | @@ -92,7 +92,7 @@ class TestSequence(MAASServerTestCase): |
246 | seq.create() |
247 | self.assertSequenceEqual([1, 2], [next(seq), next(seq)]) |
248 | self.assertRaisesRegex( |
249 | - OperationalError, "nextval: reached maximum value of sequence", |
250 | + DataError, "nextval: reached maximum value of sequence", |
251 | next, seq) |
252 | |
253 | def test_sequence_can_be_owned(self): |
254 | diff --git a/src/maasserver/views/account.py b/src/maasserver/views/account.py |
255 | index 5a84695..a146afa 100644 |
256 | --- a/src/maasserver/views/account.py |
257 | +++ b/src/maasserver/views/account.py |
258 | @@ -39,7 +39,7 @@ def login(request): |
259 | 'no_users': UserProfile.objects.all_users().count() == 0, |
260 | 'create_command': django_settings.MAAS_CLI, |
261 | } |
262 | - if request.user.is_authenticated(): |
263 | + if request.user.is_authenticated: |
264 | return HttpResponseRedirect(reverse('index')) |
265 | else: |
266 | redirect_url = request.GET.get( |
267 | diff --git a/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py b/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py |
268 | index c16eca4..e164b9a 100644 |
269 | --- a/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py |
270 | +++ b/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py |
271 | @@ -18,11 +18,11 @@ class Migration(migrations.Migration): |
272 | migrations.AddField( |
273 | model_name='scriptresult', |
274 | name='physical_blockdevice', |
275 | - field=models.ForeignKey(to='maasserver.PhysicalBlockDevice', null=True, editable=False, blank=True), |
276 | + field=models.ForeignKey(to='maasserver.PhysicalBlockDevice', null=True, editable=False, blank=True, on_delete=models.CASCADE), |
277 | ), |
278 | migrations.AlterField( |
279 | model_name='scriptresult', |
280 | name='script', |
281 | - field=models.ForeignKey(to='metadataserver.Script', null=True, editable=False, blank=True), |
282 | + field=models.ForeignKey(to='metadataserver.Script', null=True, editable=False, blank=True, on_delete=models.CASCADE), |
283 | ), |
284 | ] |
285 | diff --git a/src/provisioningserver/utils/shell.py b/src/provisioningserver/utils/shell.py |
286 | index 826c776..5567ed1 100644 |
287 | --- a/src/provisioningserver/utils/shell.py |
288 | +++ b/src/provisioningserver/utils/shell.py |
289 | @@ -6,37 +6,18 @@ |
290 | __all__ = [ |
291 | 'call_and_check', |
292 | 'ExternalProcessError', |
293 | - 'pipefork', |
294 | - 'PipeForkError', |
295 | 'select_c_utf8_bytes_locale', |
296 | 'select_c_utf8_locale', |
297 | ] |
298 | |
299 | -from contextlib import contextmanager |
300 | import os |
301 | -import pickle |
302 | from pipes import quote |
303 | -import signal |
304 | from string import printable |
305 | from subprocess import ( |
306 | CalledProcessError, |
307 | PIPE, |
308 | Popen, |
309 | ) |
310 | -from sys import ( |
311 | - stderr, |
312 | - stdout, |
313 | -) |
314 | -from tempfile import TemporaryFile |
315 | - |
316 | -from twisted.python.failure import Failure |
317 | - |
318 | -# A mapping of signal numbers to names. It is strange that this isn't in the |
319 | -# standard library (but I did check). |
320 | -signal_names = { |
321 | - value: name for name, value in vars(signal).items() |
322 | - if name.startswith('SIG') and '_' not in name |
323 | -} |
324 | |
325 | # A table suitable for use with str.translate() to replace each |
326 | # non-printable and non-ASCII character in a byte string with a question |
327 | @@ -132,178 +113,6 @@ def call_and_check(command, *args, **kwargs): |
328 | return stdout |
329 | |
330 | |
331 | -class PipeForkError(Exception): |
332 | - """An error occurred in `pipefork`.""" |
333 | - |
334 | - |
335 | -@contextmanager |
336 | -def pipefork(): |
337 | - """Context manager that forks with pipes between parent and child. |
338 | - |
339 | - Use like so:: |
340 | - |
341 | - with pipefork() as (pid, fin, fout): |
342 | - if pid == 0: |
343 | - # This is the child. |
344 | - ... |
345 | - else: |
346 | - # This is the parent. |
347 | - ... |
348 | - |
349 | - Pipes are set up so that the parent can write to the child, and |
350 | - vice-versa. |
351 | - |
352 | - In the child, ``fin`` is a file that reads from the parent, and ``fout`` |
353 | - is a file that writes to the parent. |
354 | - |
355 | - In the parent, ``fin`` is a file that reads from the child, and ``fout`` |
356 | - is a file that writes to the child. |
357 | - |
358 | - Be careful to think about closing these file objects to avoid deadlocks. |
359 | - For example, the following will deadlock: |
360 | - |
361 | - with pipefork() as (pid, fin, fout): |
362 | - if pid == 0: |
363 | - fin.read() # Read from the parent. |
364 | - fout.write(b'Moien') # Greet the parent. |
365 | - else: |
366 | - fout.write(b'Hello') # Greet the child. |
367 | - fin.read() # Read from the child *BLOCKS FOREVER* |
368 | - |
369 | - The reason is that the read in the child never returns because the pipe is |
370 | - never closed. Closing ``fout`` in the parent resolves the problem:: |
371 | - |
372 | - with pipefork() as (pid, fin, fout): |
373 | - if pid == 0: |
374 | - fin.read() # Read from the parent. |
375 | - fout.write(b'Moien') # Greet the parent. |
376 | - else: |
377 | - fout.write(b'Hello') # Greet the child. |
378 | - fout.close() # Close the write pipe to the child. |
379 | - fin.read() # Read from the child. |
380 | - |
381 | - Exceptions raised in the child are magically re-raised in the parent. When |
382 | - the child has died for another reason, a signal perhaps, a `PipeForkError` |
383 | - is raised with an explanatory message. |
384 | - |
385 | - Signal handlers in the child are NOT modified. This means that signal |
386 | - handlers set in the parent will still be present in the child. |
387 | - |
388 | - :raises: `PipeForkError` when the child process dies a somewhat unnatural |
389 | - death, e.g. by a signal or when writing a crash-dump fails. |
390 | - """ |
391 | - crashfile = TemporaryFile() |
392 | - |
393 | - c2pread, c2pwrite = os.pipe() |
394 | - p2cread, p2cwrite = os.pipe() |
395 | - |
396 | - pid = os.fork() |
397 | - |
398 | - if pid == 0: |
399 | - # Child: this conditional branch runs in the child process. |
400 | - try: |
401 | - os.close(c2pread) |
402 | - os.close(p2cwrite) |
403 | - |
404 | - with os.fdopen(p2cread, 'rb') as fin: |
405 | - with os.fdopen(c2pwrite, 'wb') as fout: |
406 | - yield pid, fin, fout |
407 | - |
408 | - stdout.flush() |
409 | - stderr.flush() |
410 | - except SystemExit as se: |
411 | - # Exit hard, not soft. |
412 | - os._exit(se.code) |
413 | - except: |
414 | - try: |
415 | - # Pickle error to crash file. |
416 | - pickle.dump(Failure(), crashfile, pickle.HIGHEST_PROTOCOL) |
417 | - crashfile.flush() |
418 | - finally: |
419 | - # Exit hard. |
420 | - os._exit(2) |
421 | - finally: |
422 | - # Exit hard. |
423 | - os._exit(0) |
424 | - else: |
425 | - # Parent: this conditional branch runs in the parent process. |
426 | - os.close(c2pwrite) |
427 | - os.close(p2cread) |
428 | - |
429 | - with os.fdopen(c2pread, 'rb') as fin: |
430 | - with os.fdopen(p2cwrite, 'wb') as fout: |
431 | - yield pid, fin, fout |
432 | - |
433 | - # Wait for the child to finish. |
434 | - _, status = os.waitpid(pid, 0) |
435 | - signal = (status & 0xff) |
436 | - code = (status >> 8) & 0xff |
437 | - |
438 | - # Check for a saved crash. |
439 | - crashfile.seek(0) |
440 | - try: |
441 | - error = pickle.load(crashfile) |
442 | - except EOFError: |
443 | - # No crash was recorded. |
444 | - error = None |
445 | - else: |
446 | - # Raise exception from child. |
447 | - error.raiseException() |
448 | - finally: |
449 | - crashfile.close() |
450 | - |
451 | - if os.WIFSIGNALED(status): |
452 | - # The child was killed by a signal. |
453 | - raise PipeForkError( |
454 | - "Child killed by signal %d (%s)" % ( |
455 | - signal, signal_names.get(signal, "?"))) |
456 | - elif code != 0: |
457 | - # The child exited with a non-zero code. |
458 | - raise PipeForkError( |
459 | - "Child exited with code %d" % code) |
460 | - else: |
461 | - # All okay. |
462 | - pass |
463 | - |
464 | - |
465 | -@contextmanager |
466 | -def objectfork(): |
467 | - """Like `pipefork`, but objects can be passed between parent and child. |
468 | - |
469 | - Usage:: |
470 | - |
471 | - with objectfork() as (pid, recv, send): |
472 | - if pid == 0: |
473 | - # Child. |
474 | - for foo in bar(): |
475 | - send(foo) |
476 | - send(None) # Done. |
477 | - else: |
478 | - for data in iter(recv, None): |
479 | - ... # Process data. |
480 | - |
481 | - In the child, ``recv`` receives objects sent -- via `send` -- from |
482 | - the parent. |
483 | - |
484 | - In the parent, ``recv`` receives objects sent -- via `send` -- from |
485 | - the child. |
486 | - |
487 | - All objects must be picklable. |
488 | - |
489 | - See `pipefork` for more details. |
490 | - """ |
491 | - with pipefork() as (pid, fin, fout): |
492 | - |
493 | - def recv(): |
494 | - return pickle.load(fin) |
495 | - |
496 | - def send(obj): |
497 | - pickle.dump(obj, fout, pickle.HIGHEST_PROTOCOL) |
498 | - fout.flush() # cPickle.dump() does not flush. |
499 | - |
500 | - yield pid, recv, send |
501 | - |
502 | - |
503 | def has_command_available(command): |
504 | """Return True if `command` is available on the system.""" |
505 | try: |
506 | diff --git a/src/provisioningserver/utils/tests/test_network.py b/src/provisioningserver/utils/tests/test_network.py |
507 | index 8f1d0e6..401457b 100644 |
508 | --- a/src/provisioningserver/utils/tests/test_network.py |
509 | +++ b/src/provisioningserver/utils/tests/test_network.py |
510 | @@ -83,7 +83,6 @@ from provisioningserver.utils.network import ( |
511 | resolves_to_loopback_address, |
512 | reverseResolve, |
513 | ) |
514 | -from provisioningserver.utils.shell import call_and_check |
515 | from testtools import ExpectedException |
516 | from testtools.matchers import ( |
517 | Contains, |
518 | @@ -107,13 +106,6 @@ from twisted.names.error import ( |
519 | ) |
520 | |
521 | |
522 | -installed_curtin_version = call_and_check([ |
523 | - "dpkg-query", "--showformat=${Version}", |
524 | - "--show", "python3-curtin"]).decode("ascii") |
525 | -installed_curtin_version = int( |
526 | - installed_curtin_version.split("~bzr", 1)[1].split("-", 1)[0]) |
527 | - |
528 | - |
529 | class TestMakeNetwork(MAASTestCase): |
530 | |
531 | def test_constructs_IPNetwork(self): |
532 | diff --git a/src/provisioningserver/utils/tests/test_shell.py b/src/provisioningserver/utils/tests/test_shell.py |
533 | index 42a8ab5..96d6dae 100644 |
534 | --- a/src/provisioningserver/utils/tests/test_shell.py |
535 | +++ b/src/provisioningserver/utils/tests/test_shell.py |
536 | @@ -6,29 +6,20 @@ |
537 | __all__ = [] |
538 | |
539 | import os |
540 | -from random import randint |
541 | -import re |
542 | -import signal |
543 | from subprocess import CalledProcessError |
544 | -import time |
545 | |
546 | from fixtures import EnvironmentVariable |
547 | from maastesting.factory import factory |
548 | -from maastesting.fixtures import DetectLeakedFileDescriptors |
549 | from maastesting.matchers import MockCalledOnceWith |
550 | from maastesting.testcase import MAASTestCase |
551 | from provisioningserver.utils.shell import ( |
552 | call_and_check, |
553 | ExternalProcessError, |
554 | has_command_available, |
555 | - objectfork, |
556 | - pipefork, |
557 | - PipeForkError, |
558 | select_c_utf8_bytes_locale, |
559 | select_c_utf8_locale, |
560 | ) |
561 | import provisioningserver.utils.shell as shell_module |
562 | -from testtools import ExpectedException |
563 | from testtools.matchers import ( |
564 | ContainsDict, |
565 | Equals, |
566 | @@ -174,125 +165,6 @@ class TestExternalProcessError(MAASTestCase): |
567 | self.assertEqual(unicode_output, error.output_as_unicode) |
568 | |
569 | |
570 | -class TestPipeFork(MAASTestCase): |
571 | - |
572 | - def setUp(self): |
573 | - super(TestPipeFork, self).setUp() |
574 | - self.useFixture(DetectLeakedFileDescriptors()) |
575 | - |
576 | - def test__forks(self): |
577 | - with pipefork() as (pid, fin, fout): |
578 | - if pid == 0: |
579 | - # Child. |
580 | - message_in = fin.read() |
581 | - message_out = b"Hello %s!" % message_in |
582 | - fout.write(message_out) |
583 | - fout.close() |
584 | - else: |
585 | - # Parent. |
586 | - message_out = factory.make_name("Parent").encode("ascii") |
587 | - fout.write(message_out) |
588 | - fout.close() |
589 | - message_in = fin.read() |
590 | - self.assertEqual(b"Hello %s!" % message_out, message_in) |
591 | - |
592 | - def test__raises_childs_exception_when_child_crashes(self): |
593 | - # If the child process exits with an exception, it is passed back to |
594 | - # the parent via a pickled t.p.failure.Failure, and re-raised. |
595 | - with ExpectedException(ZeroDivisionError): |
596 | - with pipefork() as (pid, fin, fout): |
597 | - if pid == 0: |
598 | - # Child. |
599 | - raise ZeroDivisionError() |
600 | - |
601 | - def test__raises_parents_exception_when_parent_crashes(self): |
602 | - # If the parent raises an exception, it is propagated. During |
603 | - # tear-down of the pipefork's context the child is reaped, but any |
604 | - # exceptions (via the crash file, or raised on behalf of the child |
605 | - # because of a non-zero exit code or non-zero signal) propagating back |
606 | - # from the child are masked by the exception in the parent. |
607 | - with ExpectedException(ZeroDivisionError): |
608 | - with pipefork() as (pid, fin, fout): |
609 | - if pid != 0: |
610 | - # Parent. |
611 | - raise ZeroDivisionError() |
612 | - |
613 | - def test__raises_exception_when_child_killed_by_signal(self): |
614 | - expected_message = re.escape("Child killed by signal 15 (SIGTERM)") |
615 | - with ExpectedException(PipeForkError, expected_message): |
616 | - with pipefork() as (pid, fin, fout): |
617 | - if pid == 0: |
618 | - # Reset SIGTERM to the default handler; the Twisted |
619 | - # reactor may have clobbered it in the parent. |
620 | - signal.signal(signal.SIGTERM, signal.SIG_DFL) |
621 | - # Close `fout` to signal to parent that we're running. |
622 | - fout.close() |
623 | - time.sleep(10) |
624 | - else: |
625 | - # Wait for child to close its `fout` before signalling. |
626 | - fin.read() |
627 | - os.kill(pid, signal.SIGTERM) |
628 | - |
629 | - def test__raises_exception_when_child_exits_with_non_zero_code(self): |
630 | - exit_code = randint(1, 99) |
631 | - expected_message = re.escape("Child exited with code %s" % exit_code) |
632 | - with ExpectedException(PipeForkError, expected_message): |
633 | - with pipefork() as (pid, fin, fout): |
634 | - if pid == 0: |
635 | - os._exit(exit_code) |
636 | - |
637 | - def test__SystemExit_in_child_is_not_raised_in_parent(self): |
638 | - # All exceptions are pickled and passed back to the parent process, |
639 | - # except for SystemExit. It instead results in a call to os._exit(). |
640 | - exit_code = randint(1, 99) |
641 | - expected_message = re.escape("Child exited with code %s" % exit_code) |
642 | - with ExpectedException(PipeForkError, expected_message): |
643 | - with pipefork() as (pid, fin, fout): |
644 | - if pid == 0: |
645 | - raise SystemExit(exit_code) |
646 | - |
647 | - |
648 | -class TestObjectFork(MAASTestCase): |
649 | - |
650 | - def setUp(self): |
651 | - super(TestObjectFork, self).setUp() |
652 | - self.useFixture(DetectLeakedFileDescriptors()) |
653 | - |
654 | - def test__can_send_and_receive_objects(self): |
655 | - |
656 | - def child(recv, send): |
657 | - # Sum numbers until we get None through. |
658 | - for numbers in iter(recv, None): |
659 | - send(sum(numbers)) |
660 | - # Now echo things until we get None. |
661 | - for things in iter(recv, None): |
662 | - send(things) |
663 | - |
664 | - def parent(recv, send): |
665 | - # Send numbers to the child first. |
666 | - for _ in range(randint(3, 10)): |
667 | - numbers = list(randint(1, 100) for _ in range(10)) |
668 | - send(numbers) |
669 | - self.assertEqual(sum(numbers), recv()) |
670 | - # Signal that we're done with numbers. |
671 | - send(None) |
672 | - # Send some other things and see that they come back. |
673 | - picklable_things = { |
674 | - "foo": [randint(1, 1000) for _ in range(10)], |
675 | - (1, 2, b"three", 4.0): {self.__class__, "bar"}, |
676 | - } |
677 | - send(picklable_things) |
678 | - self.assertEqual(picklable_things, recv()) |
679 | - # Signal that we're done again. |
680 | - send(None) |
681 | - |
682 | - with objectfork() as (pid, recv, send): |
683 | - if pid == 0: |
684 | - child(recv, send) |
685 | - else: |
686 | - parent(recv, send) |
687 | - |
688 | - |
689 | class TestHasCommandAvailable(MAASTestCase): |
690 | |
691 | def test__calls_which(self): |
692 | diff --git a/src/provisioningserver/utils/tests/test_version.py b/src/provisioningserver/utils/tests/test_version.py |
693 | index de23021..0efd3d9 100644 |
694 | --- a/src/provisioningserver/utils/tests/test_version.py |
695 | +++ b/src/provisioningserver/utils/tests/test_version.py |
696 | @@ -359,7 +359,7 @@ class TestVersionMethodsCached(TestVersionTestCase): |
697 | version.RACK_PACKAGE_NAME, version.REGION_PACKAGE_NAME)) |
698 | |
699 | |
700 | -class TestGetMAASVersionTuple(MAASTestCase): |
701 | +class TestGetMAASVersionTuple(TestVersionTestCase): |
702 | |
703 | def test_get_maas_version_tuple(self): |
704 | mock_repo_hash = self.patch(version, "get_maas_repo_hash") |
705 | @@ -369,7 +369,7 @@ class TestGetMAASVersionTuple(MAASTestCase): |
706 | version.get_maas_version_subversion()[0]) |
707 | |
708 | |
709 | -class TestGetMAASVersionTrackChannel(MAASTestCase): |
710 | +class TestGetMAASVersionTrackChannel(TestVersionTestCase): |
711 | |
712 | scenarios = [ |
713 | ("alpha", { |
714 | diff --git a/versions.cfg b/versions.cfg |
715 | index 621727f..42a41b7 100644 |
716 | --- a/versions.cfg |
717 | +++ b/versions.cfg |
718 | @@ -31,7 +31,7 @@ prompt-toolkit = 1.0.9 |
719 | python-mimeparse = 1.6.0 |
720 | python-subunit = 1.2.0 |
721 | selenium = 2.45 |
722 | -setuptools = 20.7.0 |
723 | +setuptools = 36.2.7 |
724 | simplegeneric = 0.8.1 |
725 | sqlparse = 0.2.2 |
726 | termcolor = 1.1.0 |
727 | @@ -54,5 +54,5 @@ pyflakes = 1.3.0 |
728 | # Explicit versions for PACKAGED dependencies. This is where a TEST |
729 | # dependency itself depends on an INSTALL/RUNTIME dependency which is, |
730 | # by force, provided by a system package. |
731 | -psycopg2 = 2.6.1 |
732 | +psycopg2 = 2.7.3 |
733 | six = 1.10.0 |