Merge ~mpontillo/maas:move-to-bionic--mpontillo into maas: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)
Reviewer Review Type Date Requested Status
MAAS Maintainers Pending
Review via email: mp+335632@code.launchpad.net

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
1diff --git a/required-packages/artful b/required-packages/bionic
2index aad4c80..aad4c80 100644
3--- a/required-packages/artful
4+++ b/required-packages/bionic
5diff --git a/required-packages/wily b/required-packages/wily
6deleted file mode 100644
7index aad4c80..0000000
8--- a/required-packages/wily
9+++ /dev/null
10@@ -1,2 +0,0 @@
11-pxelinux
12-python3-petname
13diff --git a/required-packages/xenial b/required-packages/xenial
14deleted file mode 100644
15index aad4c80..0000000
16--- a/required-packages/xenial
17+++ /dev/null
18@@ -1,2 +0,0 @@
19-pxelinux
20-python3-petname
21diff --git a/required-packages/yakkety b/required-packages/yakkety
22deleted file mode 100644
23index aad4c80..0000000
24--- a/required-packages/yakkety
25+++ /dev/null
26@@ -1,2 +0,0 @@
27-pxelinux
28-python3-petname
29diff --git a/required-packages/zesty b/required-packages/zesty
30deleted file mode 100644
31index aad4c80..0000000
32--- a/required-packages/zesty
33+++ /dev/null
34@@ -1,2 +0,0 @@
35-pxelinux
36-python3-petname
37diff --git a/src/maasserver/api/auth.py b/src/maasserver/api/auth.py
38index 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
50diff --git a/src/maasserver/context_processors.py b/src/maasserver/context_processors.py
51index 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
63diff --git a/src/maasserver/forms/interface_link.py b/src/maasserver/forms/interface_link.py
64index 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",
81diff --git a/src/maasserver/middleware.py b/src/maasserver/middleware.py
82index 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
94diff --git a/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py b/src/maasserver/migrations/builtin/maasserver/0125_add_switch_model.py
95index 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',
107diff --git a/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py b/src/maasserver/migrations/builtin/maasserver/0126_add_controllerinfo_model.py
108index 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 ]
128diff --git a/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py b/src/maasserver/migrations/builtin/maasserver/0127_nodemetadata.py
129index 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',
141diff --git a/src/maasserver/models/tests/test_dnspublication.py b/src/maasserver/models/tests/test_dnspublication.py
142index 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):
162diff --git a/src/maasserver/static/js/angular/directives/pod_parameters.js b/src/maasserver/static/js/angular/directives/pod_parameters.js
163index 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
179diff --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
180index 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 });
197diff --git a/src/maasserver/testing/api.py b/src/maasserver/testing/api.py
198index 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()
210diff --git a/src/maasserver/testing/testclient.py b/src/maasserver/testing/testclient.py
211index 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:
232diff --git a/src/maasserver/tests/test_sequence.py b/src/maasserver/tests/test_sequence.py
233index 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):
254diff --git a/src/maasserver/views/account.py b/src/maasserver/views/account.py
255index 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(
267diff --git a/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py b/src/metadataserver/migrations/builtin/0013_scriptresult_physicalblockdevice.py
268index 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 ]
285diff --git a/src/provisioningserver/utils/shell.py b/src/provisioningserver/utils/shell.py
286index 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:
506diff --git a/src/provisioningserver/utils/tests/test_network.py b/src/provisioningserver/utils/tests/test_network.py
507index 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):
532diff --git a/src/provisioningserver/utils/tests/test_shell.py b/src/provisioningserver/utils/tests/test_shell.py
533index 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):
692diff --git a/src/provisioningserver/utils/tests/test_version.py b/src/provisioningserver/utils/tests/test_version.py
693index 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", {
714diff --git a/versions.cfg b/versions.cfg
715index 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

Subscribers

People subscribed via source and target branches