Merge lp:~rbanffy/maas/qa-lab-tests into lp:~rbanffy/maas/qa-lab-tests-fast
- qa-lab-tests
- Merge into qa-lab-tests-fast
Status: | Work in progress |
---|---|
Proposed branch: | lp:~rbanffy/maas/qa-lab-tests |
Merge into: | lp:~rbanffy/maas/qa-lab-tests-fast |
Diff against target: |
854 lines (+242/-78) 6 files modified
.bzrignore (+1/-0) HACKING.md (+25/-0) config.py (+4/-4) maas-integration.py (+190/-68) maas-package-test (+1/-1) utils.py (+21/-5) |
To merge this branch: | bzr merge lp:~rbanffy/maas/qa-lab-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ricardo Bánffy | Pending | ||
Review via email: mp+282094@code.launchpad.net |
Commit message
Description of the change
- 331. By Ricardo Bánffy
-
Merge, test Juju
- 332. By Ricardo Bánffy
-
Re-enable proxy for Juju tests
- 333. By Ricardo Bánffy
-
Reordering tests
- 334. By Ricardo Bánffy
-
Make it run under Python3
- 335. By Ricardo Bánffy
-
Try using nosetests3
- 336. By Ricardo Bánffy
-
Fixing imports
- 337. By Ricardo Bánffy
-
Fixing typo
- 338. By Ricardo Bánffy
-
adding Python3 compatibility preamble to utils.py, fixed byte-string magic in run_command
- 339. By Ricardo Bánffy
-
Added .bzrignore
- 340. By Ricardo Bánffy
-
Some more Python3 work
- 341. By Ricardo Bánffy
-
Cheating - the error makes no sense
- 342. By Ricardo Bánffy
-
Deal with AppRegistryNotReady situations
- 343. By Ricardo Bánffy
-
Indentation fix
- 344. By Ricardo Bánffy
-
Insufficient coffee error
- 345. By Ricardo Bánffy
-
Manually initialize Django
- 346. By Ricardo Bánffy
-
Properly convert bytestrings
- 347. By Ricardo Bánffy
-
NeedMoreCoffee error
- 348. By Ricardo Bánffy
-
It was already a string
- 349. By Ricardo Bánffy
-
Revert changes to test_create_admin
- 350. By Ricardo Bánffy
-
Avoid using floats for version numbers
- 351. By Ricardo Bánffy
-
Removing edit leftovers
- 352. By Ricardo Bánffy
-
We use systemctl from 16.04 and on
- 353. By Ricardo Bánffy
-
Typo
- 354. By Ricardo Bánffy
-
Typo #2
- 355. By Ricardo Bánffy
-
Typos
- 356. By Ricardo Bánffy
-
Addind missing parameter
- 357. By Ricardo Bánffy
-
Adding test_restart_
provisioning_ server_ systemctl to test order list - 358. By Ricardo Bánffy
-
Adding pause to a test that should not run, but is
- 359. By Ricardo Bánffy
-
Forgotten parameter
- 360. By Ricardo Bánffy
-
open is neater
- 361. By Ricardo Bánffy
-
Inverting conditional tests
- 362. By Ricardo Bánffy
-
No longer needs a pause
- 363. By Ricardo Bánffy
-
more bytes → string stuff
- 364. By Ricardo Bánffy
-
Investigating
- 365. By Ricardo Bánffy
-
systemct is not verbose
- 366. By Ricardo Bánffy
-
added test_check_
initial_ services_ systemctl - 367. By Ricardo Bánffy
-
systemctl is verbose when it wants to
- 368. By Ricardo Bánffy
-
removing pause
- 369. By Ricardo Bánffy
-
decoding varios bytestrings into strings
- 370. By Ricardo Bánffy
-
missed some incompatibilities
- 371. By Ricardo Bánffy
-
more str issues
- 372. By Ricardo Bánffy
-
upstart and systemd paths for test_update_
dns_config_ systemctl - 373. By Ricardo Bánffy
-
Adding new tests to test order list
- 374. By Ricardo Bánffy
-
LAB_DNS_CONFIG was already a string
- 375. By Ricardo Bánffy
-
One more unextected str
- 376. By Ricardo Bánffy
-
pausing to investigate ehy _wait_nodes in test_check_
nodes_declared timed out - 377. By Ricardo Bánffy
-
Removing timeout
- 378. By Ricardo Bánffy
-
Better pause strategy
- 379. By Ricardo Bánffy
-
Better pause strategy
- 380. By Ricardo Bánffy
-
Improved test
- 381. By Ricardo Bánffy
-
Added a friendlier pause
- 382. By Ricardo Bánffy
-
run_command does not assumt it's a MAAS CLI command
- 383. By Ricardo Bánffy
-
Moving the pause around
- 384. By Ricardo Bánffy
-
Move new function around, add a pause
- 385. By Ricardo Bánffy
-
Add a new pause when we can't decode the dhcp setup return message
- 386. By Ricardo Bánffy
-
Removing timeout from test_set_
up_dhcp_ region - 387. By Ricardo Bánffy
-
Remove pause with dhcp to check isc-dhcp-server fix
- 388. By Ricardo Bánffy
-
One less Python 2 ism
- 389. By Ricardo Bánffy
-
Remove pauses
- 390. By Ricardo Bánffy
-
DHCP is still acting up. Checking why
- 391. By Ricardo Bánffy
-
DHCP is still acting up. Checking why
- 392. By Ricardo Bánffy
-
Typo!
- 393. By Ricardo Bánffy
-
addind pause to investigate MAAS login issue
- 394. By Ricardo Bánffy
-
repositioning pause
- 395. By Ricardo Bánffy
-
Fix typo
- 396. By Ricardo Bánffy
-
Saner test_login_api, waits for MAAS to come up
- 397. By Ricardo Bánffy
-
/me bangs head on the desk
- 398. By Ricardo Bánffy
-
Wait for up to 30 minutes, be more selective
Unmerged revisions
- 398. By Ricardo Bánffy
-
Wait for up to 30 minutes, be more selective
- 397. By Ricardo Bánffy
-
/me bangs head on the desk
- 396. By Ricardo Bánffy
-
Saner test_login_api, waits for MAAS to come up
- 395. By Ricardo Bánffy
-
Fix typo
- 394. By Ricardo Bánffy
-
repositioning pause
- 393. By Ricardo Bánffy
-
addind pause to investigate MAAS login issue
- 392. By Ricardo Bánffy
-
Typo!
- 391. By Ricardo Bánffy
-
DHCP is still acting up. Checking why
- 390. By Ricardo Bánffy
-
DHCP is still acting up. Checking why
- 389. By Ricardo Bánffy
-
Remove pauses
Preview Diff
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2016-01-26 22:17:32 +0000 |
4 | @@ -0,0 +1,1 @@ |
5 | +.env |
6 | |
7 | === added file 'HACKING.md' |
8 | --- HACKING.md 1970-01-01 00:00:00 +0000 |
9 | +++ HACKING.md 2016-01-26 22:17:32 +0000 |
10 | @@ -0,0 +1,25 @@ |
11 | +Some tips for the developer |
12 | +=========================== |
13 | + |
14 | +This document exists so developers can write tips for other developers |
15 | +who need to add or fix tests to this environment. |
16 | + |
17 | +In a nutshell |
18 | +------------- |
19 | + |
20 | +The script `maas-package-test` calls nosetest3, which, in turn, runs |
21 | +`maas-integration.py`. |
22 | + |
23 | + |
24 | +Pausing the test |
25 | +---------------- |
26 | + |
27 | +The `utils.py` file contains a handy function, `pause_until_released`, |
28 | +that writes a message to `/tmp/paused` and waits until the file is |
29 | +deleted. It can be used to pause the test program at any given time so |
30 | +you can ssh into the machine and inspect it. Another neat trick you can |
31 | +do is to stop the program before any test runs. You can then run the |
32 | +tests (and change the test-integration.py file to suit your needs). From |
33 | +a folder named like `/tmp/adt-run.Ezz1tN/build.mM6/real-tree`, run |
34 | +`nosetests3 --verbose --stop debian/tests/maas-integration.py` to start |
35 | +it. |
36 | |
37 | === modified file 'config.py' |
38 | --- config.py 2016-01-11 11:26:55 +0000 |
39 | +++ config.py 2016-01-26 22:17:32 +0000 |
40 | @@ -17,7 +17,7 @@ |
41 | |
42 | CLUSTER_CONTROLLER_IP = '10.245.136.6' |
43 | |
44 | -SQUID_DEB_PROXY_URL = 'http://162.213.35.104:8000' |
45 | +SQUID_DEB_PROXY_URL = 'http://10.55.32.185:8000' |
46 | # HTTP proxy used to access the external world. |
47 | HTTP_PROXY = "http://162.213.35.104:3128" |
48 | |
49 | @@ -53,7 +53,7 @@ |
50 | "00:E0:81:DD:D4:11": "10.245.143.105", |
51 | # lenovo-RD230-06, MAAS-06 |
52 | "00:E0:81:D1:B1:47": "10.245.143.106", |
53 | - } |
54 | +} |
55 | |
56 | CLUSTER_CONTROLLER_NODES = { |
57 | # lenovo-RD230-07, MAAS-07 |
58 | @@ -68,7 +68,7 @@ |
59 | "00:E0:81:DD:D0:FF": "10.245.143.111", |
60 | # lenovo-RD230-12, MAAS-12 |
61 | "00:E0:81:DD:D4:F9": "10.245.143.112" |
62 | - } |
63 | +} |
64 | |
65 | |
66 | LENOVO_LAB = REGION_CONTROLLER_NODES |
67 | @@ -81,7 +81,7 @@ |
68 | 'fc:2f:40:fa:2f:9a': '192.168.21.51', |
69 | 'fc:2f:40:ec:73:42': '192.168.21.52', |
70 | 'fc:2f:40:d5:87:ce': '192.168.21.53' |
71 | - } |
72 | +} |
73 | |
74 | # dnssec is now enabled by default, so disable it to avoid errors from the |
75 | # forwarder server. |
76 | |
77 | === modified file 'maas-integration.py' |
78 | --- maas-integration.py 2016-01-11 11:26:55 +0000 |
79 | +++ maas-integration.py 2016-01-26 22:17:32 +0000 |
80 | @@ -1,21 +1,45 @@ |
81 | -from contextlib import closing |
82 | +from __future__ import ( |
83 | + absolute_import, |
84 | + print_function, |
85 | + unicode_literals, |
86 | + ) |
87 | + |
88 | +str = None |
89 | + |
90 | +__metaclass__ = type |
91 | +__all__ = [] |
92 | + |
93 | import errno |
94 | -from itertools import count |
95 | import os |
96 | import pipes |
97 | import platform |
98 | import re |
99 | +import sys |
100 | +from contextlib import closing |
101 | +from distutils.version import StrictVersion |
102 | +from itertools import count |
103 | from shutil import copytree |
104 | -import sys |
105 | from textwrap import dedent |
106 | from time import sleep |
107 | -import unittest |
108 | from unittest import ( |
109 | skipIf, |
110 | + skipUnless, |
111 | SkipTest, |
112 | + TestLoader, |
113 | ) |
114 | -import urllib2 |
115 | -from urlparse import urlparse |
116 | +try: |
117 | + from urllib2 import ( |
118 | + urlopen, |
119 | + HTTPError, |
120 | + ) |
121 | +except ImportError: |
122 | + from urllib.request import urlopen |
123 | + from urllib.error import HTTPError |
124 | + |
125 | +try: |
126 | + from urllib.parse import urlparse |
127 | +except ImportError: |
128 | + from urlparse import urlparse |
129 | |
130 | from netaddr import ( |
131 | IPAddress, |
132 | @@ -42,17 +66,24 @@ |
133 | filter_dict, |
134 | get_maas_revision, |
135 | get_maas_version, |
136 | + get_ubuntu_version, |
137 | is_juju_core, |
138 | retries, |
139 | run_command, |
140 | + pause_until_released # If this is not used below, linters will complain. |
141 | ) |
142 | import yaml |
143 | import zmq |
144 | |
145 | |
146 | +# Needed by the imports below - linters will complain. |
147 | sys.path.insert(0, "/usr/share/maas") |
148 | os.environ['DJANGO_SETTINGS_MODULE'] = 'maas.settings' |
149 | |
150 | +import django |
151 | +django.setup() |
152 | + |
153 | +from django.core.exceptions import AppRegistryNotReady |
154 | from django.core.management import call_command |
155 | from django.contrib.auth.models import User |
156 | |
157 | @@ -99,7 +130,7 @@ |
158 | config_content = make_juju_config() % (server, oauth, series) |
159 | juju_configfile = os.path.join(juju_dir, 'environments.yaml') |
160 | juju_configfile_fd = open(juju_configfile, 'w') |
161 | - juju_configfile_fd.write(config_content) |
162 | + juju_configfile_fd.write(config_content.encode('utf-8')) |
163 | |
164 | |
165 | def get_token_str(): |
166 | @@ -126,10 +157,10 @@ |
167 | |
168 | |
169 | def setup_local_dns(): |
170 | - content = open('/etc/resolv.conf').read() |
171 | + content = open('/etc/resolv.conf').read().decode('ascii') |
172 | content = 'nameserver 127.0.0.1\n' + content |
173 | with open('/etc/resolv.conf', 'w') as f: |
174 | - f.write(content) |
175 | + f.write(content.encode('utf-8')) |
176 | |
177 | |
178 | DEB_PROXY_CONFIG = """ |
179 | @@ -142,10 +173,10 @@ |
180 | # Configure the region proxy to use the proxy. |
181 | def setup_deb_proxy(): |
182 | config = '/usr/share/maas/maas-proxy.conf' |
183 | - content = open(config).read() |
184 | + content = open(config).read().decode('ascii') |
185 | content = content + DEB_PROXY_CONFIG |
186 | with open(config, 'w') as f: |
187 | - f.write(content) |
188 | + f.write(content.encode('utf-8')) |
189 | run_command(['sudo', 'service', 'maas-proxy', 'restart']) |
190 | |
191 | tests_order = [ |
192 | @@ -154,10 +185,13 @@ |
193 | "test_update_maas_url_old", |
194 | "test_update_maas_url", |
195 | "test_restart_provisioning_server", |
196 | + "test_restart_provisioning_server_systemctl", |
197 | "test_check_initial_services", |
198 | + "test_check_initial_services_systemctl", |
199 | "test_check_rpc_info", |
200 | "test_update_preseed_arm", |
201 | "test_login_api", |
202 | + "test_maas_logged_in", |
203 | "test_set_http_proxy", |
204 | # From this point on, we can connect to the external world. |
205 | "test_import_boot_resources", |
206 | @@ -165,8 +199,10 @@ |
207 | "test_cluster_connected", |
208 | "test_set_up_dhcp_region", |
209 | "test_check_dhcp_service", |
210 | + "test_check_dhcp_service_systemctl", |
211 | "test_set_up_dhcp_cluster", |
212 | "test_update_dns_config", |
213 | + "test_update_dns_config_systemctl", |
214 | "test_add_new_zones", |
215 | "test_list_zones", |
216 | "test_delete_zone", |
217 | @@ -196,19 +232,18 @@ |
218 | "test_configure_juju", |
219 | "test_juju_bootstrap", |
220 | "test_apply_tag_to_all_nodes", |
221 | + "test_juju_bootstrapped", |
222 | "test_check_tag_applied_to_all_nodes", |
223 | - "test_juju_bootstrapped", |
224 | "test_juju_deploy_mysql", |
225 | "test_machines_deployed", |
226 | "test_static_ip_addresses", |
227 | ] |
228 | |
229 | - |
230 | def sorting_method(ignored, first_test, second_test): |
231 | return tests_order.index(first_test) - tests_order.index(second_test) |
232 | |
233 | |
234 | -unittest.TestLoader.sortTestMethodsUsing = sorting_method |
235 | +TestLoader.sortTestMethodsUsing = sorting_method |
236 | |
237 | # The 'maas-cli' has been renamed to 'maas' in version 1931. |
238 | maascli = 'maas' if get_maas_revision() >= 1931 else 'maas-cli' |
239 | @@ -252,25 +287,25 @@ |
240 | break |
241 | |
242 | self.addDetail( |
243 | - 'retcode for %s maas %s' % (maascli, str(args)), |
244 | - text_content(str(retcode))) |
245 | - self.addDetail( |
246 | - 'stdout for %s maas %s' % (maascli, str(args)), |
247 | - text_content(str(output))) |
248 | - self.addDetail( |
249 | - 'stderr for %s maas %s' % (maascli, str(args)), |
250 | - text_content(str(err))) |
251 | + 'retcode for %s maas %s' % (maascli, args), |
252 | + text_content('%d' % retcode)) |
253 | + self.addDetail( |
254 | + 'stdout for %s maas %s' % (maascli, args), |
255 | + text_content(output)) |
256 | + self.addDetail( |
257 | + 'stderr for %s maas %s' % (maascli, args), |
258 | + text_content(err)) |
259 | return (output, err) |
260 | |
261 | def _update_dhcpd_apparmor_profile(self): |
262 | """Workaround for raring due to bug 1107686.""" |
263 | with open("/etc/apparmor.d/usr.sbin.dhcpd", "r+") as dhcpd_fd: |
264 | - dhcpd_file = dhcpd_fd.read() |
265 | + dhcpd_file = dhcpd_fd.read().decode('ascii') |
266 | dhcpd_file = dhcpd_file.replace( |
267 | 'network packet packet,', |
268 | 'network packet packet,\n network packet raw,') |
269 | dhcpd_fd.seek(0) |
270 | - dhcpd_fd.write(dhcpd_file) |
271 | + dhcpd_fd.write(dhcpd_file.encode('utf-8')) |
272 | cmd = ["service", "apparmor", "reload"] |
273 | expected_output = '* Reloading AppArmor profiles' |
274 | assertCommandReturnCode(self, cmd, expected_output) |
275 | @@ -293,7 +328,12 @@ |
276 | maas_dhcp_cmd = [ |
277 | "node-group-interfaces", "new", uuid] + dhcp_cli_args |
278 | output, err = self._run_maas_cli(maas_dhcp_cmd) |
279 | - node_group = loads(output) |
280 | + try: |
281 | + node_group = loads(output) |
282 | + except: |
283 | + # pass |
284 | + #from maas.provisioningserver.service_monitor import get_service_state |
285 | + pause_until_released(ng_list.__repr__()) |
286 | # The JSON object returned by MAAS doesn't include the router_ip |
287 | # address, so let's remove it from the dhcp_config before comparing. |
288 | dhcp_config = dhcp_config.copy() |
289 | @@ -416,12 +456,11 @@ |
290 | cmd_output = call_command( |
291 | "createadmin", username=ADMIN_USER, password=PASSWORD, |
292 | email="example@canonical.com", noinput=True) |
293 | - # No output, means admin user was created successfully. |
294 | self.assertEqual(cmd_output, None) |
295 | |
296 | # Since revision 1828, MAAS doesn't use avahi/dbus anymore so |
297 | # we do not need to restart these daemons. |
298 | - @unittest.skipIf( |
299 | + @skipIf( |
300 | get_maas_revision() >= 1828, "Avahi/DBUS are not used anymore") |
301 | def test_restart_dbus_avahi(self): |
302 | cmd = ["service", "dbus", "restart"] |
303 | @@ -431,21 +470,21 @@ |
304 | expected_output = 'avahi-daemon start/running' |
305 | assertCommandReturnCode(self, cmd, expected_output) |
306 | |
307 | - @unittest.skipUnless( |
308 | + @skipUnless( |
309 | os.path.exists("/etc/maas/maas_local_settings.py"), |
310 | "maas_local_settings.py is not used anymore") |
311 | def test_update_maas_url_old(self): |
312 | # XXX: matsubara For some reason using a debconf file to set the |
313 | # initial value of DEFAULT_MAAS_URL is not working. |
314 | maas_fd = open("/etc/maas/maas_local_settings.py", "r+") |
315 | - maas_file = maas_fd.read() |
316 | + maas_file = maas_fd.read().decode('ascii') |
317 | maas_file = re.sub( |
318 | 'DEFAULT_MAAS_URL = ".*"', |
319 | 'DEFAULT_MAAS_URL = "http://10.245.136.6/MAAS"', |
320 | maas_file, |
321 | ) |
322 | maas_fd.seek(0) |
323 | - maas_fd.write(maas_file) |
324 | + maas_fd.write(maas_file.encode('utf-8')) |
325 | maas_fd.close() |
326 | # Restart apache2. |
327 | cmd = ["service", "apache2", "restart"] |
328 | @@ -456,7 +495,7 @@ |
329 | else: |
330 | self.fail("apache2 cannot be restarted") |
331 | |
332 | - @unittest.skipIf( |
333 | + @skipIf( |
334 | os.path.exists("/etc/maas/maas_local_settings.py"), |
335 | "local_config_set is not available") |
336 | def test_update_maas_url(self): |
337 | @@ -477,6 +516,9 @@ |
338 | else: |
339 | self.fail("apache2 cannot be restarted") |
340 | |
341 | + @skipIf( |
342 | + StrictVersion(get_ubuntu_version()) >= StrictVersion('15.10'), |
343 | + 'We used upstart prior to 15.10') |
344 | def test_restart_provisioning_server(self): |
345 | # Restart the provisioning server as MAAS is installed before the |
346 | # network is properly configured, which makes clusterd listen only in |
347 | @@ -485,10 +527,36 @@ |
348 | expected_output = 'maas-clusterd start/running' |
349 | assertCommandReturnCode(self, cmd, expected_output) |
350 | |
351 | + @skipIf( |
352 | + StrictVersion(get_ubuntu_version()) < StrictVersion('15.10'), |
353 | + 'From 15.10 onwards, we use systemd') |
354 | + def test_restart_provisioning_server_systemctl(self): |
355 | + # Restart the provisioning server as MAAS is installed before the |
356 | + # network is properly configured, which makes clusterd listen only in |
357 | + # the 10.0.2.15 interface. |
358 | + cmd = ["systemctl", "restart", "maas-clusterd"] |
359 | + retcode, output, err = run_command(cmd) |
360 | + self.assertEqual(0, retcode) |
361 | + self.assertEqual('', output) # No news is good news |
362 | + self.assertEqual('', err) |
363 | + |
364 | + @skipIf( |
365 | + StrictVersion(get_ubuntu_version()) >= StrictVersion('15.10'), |
366 | + 'We used upstart prior to 15.10') |
367 | def test_check_initial_services(self): |
368 | assertStartedUpstartService( |
369 | self, 'maas-clusterd', '/var/log/maas/clusterd.log') |
370 | |
371 | + @skipIf( |
372 | + StrictVersion(get_ubuntu_version()) < StrictVersion('15.10'), |
373 | + 'From 15.10 onwards, we use systemd') |
374 | + def test_check_initial_services_systemctl(self): |
375 | + cmd = ["systemctl", "status", "maas-clusterd"] |
376 | + retcode, output, err = run_command(cmd) |
377 | + self.assertEqual(0, retcode) |
378 | + self.assertIn('Active: active (running)', output) |
379 | + self.assertEqual('', err) |
380 | + |
381 | def test_check_rpc_info(self): |
382 | # Ensure that the region is publishing RPC info to the clusters. This |
383 | # is a reasonable indication that the region is running correctly. |
384 | @@ -499,21 +567,21 @@ |
385 | for elapsed, remaining in retries(timeout=300, delay=10): |
386 | attempt = next(attempts) |
387 | try: |
388 | - with closing(urllib2.urlopen(url)) as response: |
389 | + with closing(urlopen(url)) as response: |
390 | details = content_from_stream(response, buffer_now=True) |
391 | - except urllib2.HTTPError as error: |
392 | + except HTTPError as error: |
393 | errors.append(error) |
394 | else: |
395 | self.addDetail('info', details) |
396 | break |
397 | else: |
398 | self.addDetail('errors', text_content( |
399 | - u"\n--\n".join(unicode(error) for error in errors))) |
400 | + "\n--\n".join([error for error in errors]))) |
401 | self.fail( |
402 | "RPC info not published after %d attempts over %d seconds." |
403 | % (attempt, elapsed)) |
404 | |
405 | - @unittest.skipIf(DO_NOT_USE_ARM_NODES, "Don't test ARM nodes") |
406 | + @skipIf(DO_NOT_USE_ARM_NODES, "Don't test ARM nodes") |
407 | def test_update_preseed_arm(self): |
408 | # XXX: matsubara add workaround to boot arm nodes. |
409 | try: |
410 | @@ -523,14 +591,14 @@ |
411 | "/usr/share/maas/preseeds/enlist_userdata", "rb+") |
412 | except IOError: |
413 | userdata_fd = open("/etc/maas/preseeds/enlist_userdata", "rb+") |
414 | - userdata = userdata_fd.read() |
415 | + userdata = userdata_fd.read().decode('utf-8') |
416 | url = 'http://ports.ubuntu.com/ubuntu-ports' |
417 | userdata += '\n' + dedent("""\ |
418 | apt_sources: |
419 | - source: "deb %s precise-proposed main" |
420 | """) % url |
421 | userdata_fd.seek(0) |
422 | - userdata_fd.write(userdata) |
423 | + userdata_fd.write(userdata.encode('utf-8')) |
424 | userdata_fd.close() |
425 | |
426 | def test_login_api(self): |
427 | @@ -538,7 +606,25 @@ |
428 | api_url = MAAS_URL + "/api/1.0/" |
429 | cmd = [maascli, "login", "maas", api_url, token_str] |
430 | expected_output = "\nYou are now logged in to the MAAS server" |
431 | - assertCommandReturnCode(self, cmd, expected_output) |
432 | + for _ in range(30): |
433 | + retcode, output, err = run_command(cmd, env=os.environ.copy()) |
434 | + if retcode == 0: |
435 | + break |
436 | + elif retcode == 1 and 'Expected application/json' in err: |
437 | + # The cli may error with 'Expected application/json, got: |
438 | + # text/html; charset=utf-8\n' with retcode 1 before all pieces |
439 | + # are up and running. |
440 | + sleep(10) # We need to give MAAS some time. |
441 | + self.assertIn(expected_output, output) |
442 | + |
443 | + def test_maas_logged_in(self): |
444 | + """Make sure MAAS is successfully logged in. Also, it signals a handy |
445 | + place to put a pause.""" |
446 | + # pause_until_released('test_maas_logged_in') |
447 | + cmd = ["maas", "list"] |
448 | + retcode, output, err = run_command(cmd) |
449 | + self.assertEqual(0, retcode) |
450 | + self.assertEqual('', err) |
451 | |
452 | def test_set_http_proxy(self): |
453 | output, err = self._run_maas_cli([ |
454 | @@ -550,7 +636,7 @@ |
455 | self.assertThat(output, Contains(HTTP_PROXY)) |
456 | |
457 | # Check that the user-data passed on to nodes have the proxy address. |
458 | - output = urllib2.urlopen(USER_DATA_URL).read() |
459 | + output = urlopen(USER_DATA_URL).read().decode('utf-8') |
460 | self.assertThat(output, Contains( |
461 | "apt_proxy: %s" % HTTP_PROXY)) |
462 | |
463 | @@ -569,7 +655,7 @@ |
464 | sleep(10) |
465 | name = self.get_master_ng()['uuid'] |
466 | |
467 | - @timeout(10 * 60) |
468 | + # @timeout(10 * 60) |
469 | def test_set_up_dhcp_region(self): |
470 | release = platform.linux_distribution()[2] |
471 | if release in ('quantal', 'raring'): |
472 | @@ -597,11 +683,25 @@ |
473 | content_from_file("/var/log/maas/maas.log")) |
474 | sleep(2) |
475 | |
476 | + @skipIf( |
477 | + StrictVersion(get_ubuntu_version()) >= StrictVersion('15.10'), |
478 | + 'We used upstart prior to 15.10') |
479 | def test_check_dhcp_service(self): |
480 | assertStartedUpstartService( |
481 | self, 'maas-dhcpd', |
482 | '/var/log/upstart/maas-dhcpd.log') |
483 | |
484 | + @skipIf( |
485 | + StrictVersion(get_ubuntu_version()) < StrictVersion('15.10'), |
486 | + 'From 15.10 onwards, we use systemd') |
487 | + def test_check_dhcp_service_systemctl(self): |
488 | + cmd = ["systemctl", "status", "maas-dhcpd"] |
489 | + retcode, output, err = run_command(cmd) |
490 | + pause_until_released((retcode, output, err).__repr__()) |
491 | + self.assertEqual(0, retcode) |
492 | + self.assertIn('Active: active (running)', output) |
493 | + self.assertEqual('', err) |
494 | + |
495 | @skipIf(not USE_CC_NODES, "Not testing cluster controller") |
496 | @timeout(5 * 60) |
497 | def test_set_up_dhcp_cluster(self): |
498 | @@ -638,6 +738,9 @@ |
499 | self.assertThat( |
500 | output, Contains("Nodegroup(s) accepted.")) |
501 | |
502 | + @skipIf( |
503 | + StrictVersion(get_ubuntu_version()) >= StrictVersion('15.10'), |
504 | + 'We used upstart prior to 15.10') |
505 | def test_update_dns_config(self): |
506 | # XXX: matsubara Could be asked by maas-dns package and configurable |
507 | # through debconf seed file. |
508 | @@ -648,9 +751,22 @@ |
509 | expected_output = '* Starting domain name service... bind9' |
510 | assertCommandReturnCode(self, cmd, expected_output) |
511 | |
512 | + @skipIf( |
513 | + StrictVersion(get_ubuntu_version()) < StrictVersion('15.10'), |
514 | + 'From 15.10 onwards, we use systemd') |
515 | + def test_update_dns_config_systemctl(self): |
516 | + dns_config = open("/etc/bind/named.conf.options", 'w') |
517 | + dns_config.write(LAB_DNS_CONFIG) |
518 | + dns_config.close() |
519 | + cmd = ["systemctl", "restart", "bind9"] |
520 | + retcode, output, err = run_command(cmd) |
521 | + self.assertEqual(0, retcode) |
522 | + self.assertEqual('', output) # No news is good news |
523 | + self.assertEqual('', err) |
524 | + |
525 | # Zones |
526 | @skipIf( |
527 | - float(get_maas_version()[:3]) < 1.5, |
528 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.5'), |
529 | "Zone feature only available after 1.5") |
530 | def test_add_new_zones(self): |
531 | # Create 2 new zones. |
532 | @@ -665,7 +781,7 @@ |
533 | self.assertEqual('delete-zone', zone['name']) |
534 | |
535 | @skipIf( |
536 | - float(get_maas_version()[:3]) < 1.5, |
537 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.5'), |
538 | "Zone feature only available after 1.5") |
539 | def test_list_zones(self): |
540 | output, err = self._run_maas_cli(["zones", "read"]) |
541 | @@ -674,7 +790,7 @@ |
542 | self.assertEqual(expected, sorted([zone['name'] for zone in zones])) |
543 | |
544 | @skipIf( |
545 | - float(get_maas_version()[:3]) < 1.5, |
546 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.5'), |
547 | "Zone feature only available after 1.5") |
548 | def test_delete_zone(self): |
549 | _, err = self._run_maas_cli(["zone", "delete", "delete-zone"]) |
550 | @@ -686,7 +802,7 @@ |
551 | |
552 | # Spaces and subnets |
553 | @skipIf( |
554 | - float(get_maas_version()[:3]) < 1.9, |
555 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
556 | 'Space feature only available after 1.9') |
557 | def test_add_new_spaces(self): |
558 | # Create 2 new spaces. |
559 | @@ -700,7 +816,7 @@ |
560 | self.assertEqual('delete-space', out_dict['name']) |
561 | |
562 | @skipIf( |
563 | - float(get_maas_version()[:3]) < 1.9, |
564 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
565 | 'Subnet feature only available after 1.9') |
566 | def test_add_subnet_to_space(self): |
567 | output, err = self._run_maas_cli( |
568 | @@ -712,7 +828,7 @@ |
569 | self.assertEqual('space-0', out_dict['space']) |
570 | |
571 | @skipIf( |
572 | - float(get_maas_version()[:3]) < 1.9, |
573 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
574 | 'Space feature only available after 1.9') |
575 | def test_list_spaces(self): |
576 | output, err = self._run_maas_cli(['spaces', 'read']) |
577 | @@ -722,7 +838,7 @@ |
578 | expected, [item['name'] for item in out_dict]) |
579 | |
580 | @skipIf( |
581 | - float(get_maas_version()[:3]) < 1.9, |
582 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
583 | 'Subnet feature only available after 1.9') |
584 | def test_list_subnets(self): |
585 | output, err = self._run_maas_cli(['subnets', 'read']) |
586 | @@ -730,7 +846,7 @@ |
587 | self.assertEqual(2, len(out_dict), 'space-0 should now have 2 subnets') |
588 | |
589 | @skipIf( |
590 | - float(get_maas_version()[:3]) < 1.9, |
591 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
592 | 'Subnet feature only available after 1.9') |
593 | def test_delete_subnet(self): |
594 | _, err = self._run_maas_cli(['subnet', 'delete', 'test-subnet']) |
595 | @@ -743,7 +859,7 @@ |
596 | 'Name and CIDR should be equal for the default subnet.') |
597 | |
598 | @skipIf( |
599 | - float(get_maas_version()[:3]) < 1.9, |
600 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
601 | 'Space feature only available after 1.9') |
602 | def test_delete_space(self): |
603 | _, err = self._run_maas_cli(['space', 'delete', 'delete-space']) |
604 | @@ -755,7 +871,7 @@ |
605 | |
606 | # Fabrics and VLANs |
607 | @skipIf( |
608 | - float(get_maas_version()[:3]) < 1.9, |
609 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
610 | 'Fabric feature only available after 1.9') |
611 | def test_add_new_fabrics(self): |
612 | # Create 2 new fabrics. |
613 | @@ -769,7 +885,7 @@ |
614 | self.assertEqual('delete-fabric', out_dict['name']) |
615 | |
616 | @skipIf( |
617 | - float(get_maas_version()[:3]) < 1.9, |
618 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
619 | 'VLAN feature only available after 1.9') |
620 | def test_add_vlan_to_fabric(self): |
621 | output, err = self._run_maas_cli( |
622 | @@ -780,7 +896,7 @@ |
623 | self.assertEqual(2, out_dict['vid']) |
624 | |
625 | @skipIf( |
626 | - float(get_maas_version()[:3]) < 1.9, |
627 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
628 | 'Fabric feature only available after 1.9') |
629 | def test_list_fabrics(self): |
630 | output, err = self._run_maas_cli(['fabrics', 'read']) |
631 | @@ -794,7 +910,7 @@ |
632 | for f in out_dict if f['name'] == 'test-fabric'][0]) |
633 | |
634 | @skipIf( |
635 | - float(get_maas_version()[:3]) < 1.9, |
636 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
637 | 'VLAN feature only available after 1.9') |
638 | def test_list_vlans(self): |
639 | output, err = self._run_maas_cli(['vlans', 'read', 'test-fabric']) |
640 | @@ -803,7 +919,7 @@ |
641 | self.assertItemsEqual(expected, [v['name'] for v in out_dict]) |
642 | |
643 | @skipIf( |
644 | - float(get_maas_version()[:3]) < 1.9, |
645 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
646 | 'VLAN feature only available after 1.9') |
647 | def test_delete_vlan(self): |
648 | _, err = self._run_maas_cli( |
649 | @@ -814,7 +930,7 @@ |
650 | self.assertEqual(1, len(out), 'Fabric should have only one VLAN now.') |
651 | |
652 | @skipIf( |
653 | - float(get_maas_version()[:3]) < 1.9, |
654 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.9'), |
655 | "Fabric feature only available after 1.9") |
656 | def test_delete_fabric(self): |
657 | _, err = self._run_maas_cli(["fabric", "delete", "delete-fabric"]) |
658 | @@ -826,8 +942,8 @@ |
659 | |
660 | # On older releases the boot images were only held at the cluster level. |
661 | @skipIf( |
662 | - float(get_maas_version()[:3]) < 1.7, |
663 | - "Don't import boot resources on older releases.") |
664 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.7'), |
665 | + "Don't import boot resources on pre 1.7 releases.") |
666 | def test_import_boot_resources(self): |
667 | output, err = self._run_maas_cli( |
668 | ["boot-resources", "import"]) |
669 | @@ -837,7 +953,7 @@ |
670 | |
671 | # On older releases the boot images were only held at the cluster level. |
672 | @skipIf( |
673 | - float(get_maas_version()[:3]) < 1.7, |
674 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.7'), |
675 | "Don't check imported boot resources on older releases.") |
676 | @timeout(60 * 60) # Allow for up to one hour |
677 | def test_imported_boot_resources(self): |
678 | @@ -868,11 +984,11 @@ |
679 | # On 1.7 and higher this is not needed as the clusters will import boot |
680 | # images once importing on the region has completed. |
681 | @skipIf( |
682 | - float(get_maas_version()[:3]) > 1.6, |
683 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.6'), |
684 | "Don't call import boot images on 1.7 and higher.") |
685 | def test_import_boot_images(self): |
686 | # On 1.5 and later use maas-cli to import boot images. |
687 | - if float(get_maas_version()[:3]) >= 1.5: |
688 | + if StrictVersion(get_maas_version()[:3]) > StrictVersion('1.4'): |
689 | region_uuid = get_local_cluster_UUID() |
690 | output, err = self._run_maas_cli( |
691 | ["node-group", "import-boot-images", region_uuid]) |
692 | @@ -892,7 +1008,7 @@ |
693 | # through the CLI and we check if the expected images were imported before |
694 | # proceeding. |
695 | @skipIf( |
696 | - float(get_maas_version()[:3]) < 1.5, |
697 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.5'), |
698 | "Don't check imported images on older releases.") |
699 | @timeout(15 * 60) |
700 | def test_imported_boot_images(self): |
701 | @@ -933,7 +1049,8 @@ |
702 | setup_ssh() |
703 | home_dir = os.path.expanduser('~/') |
704 | ssh_dir = os.path.join(home_dir, '.ssh') |
705 | - ssh_key = file(os.path.join(ssh_dir, 'id_rsa.pub')).read() |
706 | + ssh_key = open( |
707 | + os.path.join(ssh_dir, 'id_rsa.pub')).read() |
708 | out, err = self._run_maas_cli(["sshkeys", "new", "key=%s" % ssh_key]) |
709 | out, err = self._run_maas_cli(["sshkeys", "list"]) |
710 | keys = loads(out) |
711 | @@ -942,12 +1059,12 @@ |
712 | def test_boot_nodes_enlist(self): |
713 | self._boot_nodes() |
714 | |
715 | - @timeout(7 * 60) |
716 | + # @timeout(7 * 60) |
717 | def test_check_nodes_declared(self): |
718 | self._wait_nodes(NODE_STATUS.NEW) # 0 |
719 | |
720 | @skipIf( |
721 | - float(get_maas_version()[:3]) < 1.5, |
722 | + StrictVersion(get_maas_version()[:3]) < StrictVersion('1.5'), |
723 | "Zone feature only available after 1.5") |
724 | def test_assign_nodes_to_test_zone(self): |
725 | # Set two of the declared nodes to the test-zone created earlier. |
726 | @@ -1016,7 +1133,7 @@ |
727 | def test_configure_juju(self): |
728 | # Proxy is currently broken: disable using the lab's proxy |
729 | # as parent for now. |
730 | - setup_deb_proxy() # Maybe it's not broken |
731 | + setup_deb_proxy() # Maybe it's not broken anymore |
732 | token_str = get_token_str() |
733 | # Workaround bug 972829 (in juju precise). |
734 | server_url = MAAS_URL.replace('/MAAS', ':80/MAAS') |
735 | @@ -1034,6 +1151,11 @@ |
736 | else: |
737 | command = ['bootstrap'] |
738 | self._run_juju_command(command) |
739 | + |
740 | + @skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
741 | + @timeout(60 * 60) |
742 | + def test_juju_bootstrapped(self): |
743 | + """Wait for one machine with the Juju agent up.""" |
744 | self._wait_machines_running(1) |
745 | |
746 | @skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
747 | @@ -1093,10 +1215,10 @@ |
748 | log_dir = "/var/log/maas" |
749 | stdout_path = os.path.join(log_dir, 'dumpdata.stdout') |
750 | with open(stdout_path, 'wb') as w_file: |
751 | - w_file.write(stdout) |
752 | + w_file.write(stdout.encode('utf-8')) |
753 | stderr_path = os.path.join(log_dir, 'dumpdata.stderr') |
754 | with open(stderr_path, 'wb') as w_file: |
755 | - w_file.write(stderr) |
756 | + w_file.write(stderr.encode('utf-8')) |
757 | |
758 | @classmethod |
759 | def _collect_logs(cls, log_dirs, log_dest): |
760 | @@ -1143,7 +1265,7 @@ |
761 | log_dir = "/var/log/maas" |
762 | stdout_path = os.path.join(log_dir, 'juju-log-replay.stdout') |
763 | with open(stdout_path, 'wb') as w_file: |
764 | - w_file.write(stdout) |
765 | + w_file.write(stdout.encode('utf-8')) |
766 | ret, stdout, stderr = run_command([ |
767 | "juju", "scp", "0:/var/log/juju/*", log_dir]) |
768 | |
769 | |
770 | === modified file 'maas-package-test' |
771 | --- maas-package-test 2015-11-12 23:58:19 +0000 |
772 | +++ maas-package-test 2016-01-26 22:17:32 +0000 |
773 | @@ -5,4 +5,4 @@ |
774 | # If any post-install changes are needed, this is where they should go. |
775 | |
776 | # Run tests. |
777 | -nosetests --verbose --stop debian/tests/maas-integration.py |
778 | +nosetests3 --verbose --stop debian/tests/maas-integration.py |
779 | |
780 | === modified file 'utils.py' |
781 | --- utils.py 2015-11-08 13:15:53 +0000 |
782 | +++ utils.py 2016-01-26 22:17:32 +0000 |
783 | @@ -1,3 +1,14 @@ |
784 | +from __future__ import ( |
785 | + absolute_import, |
786 | + print_function, |
787 | + unicode_literals, |
788 | + ) |
789 | + |
790 | +str = None |
791 | + |
792 | +__metaclass__ = type |
793 | +__all__ = [] |
794 | + |
795 | from datetime import datetime |
796 | import os |
797 | import platform |
798 | @@ -33,6 +44,7 @@ |
799 | retcode, out, err = run_command(['juju', '--version']) |
800 | # pyjuju 0.6 has no --version option. pyjuju 0.7 returns "juju |
801 | # <version>". gojuju returns "<version>". |
802 | + # At this point, out should be a string (it's decoded at run_command). |
803 | if out == '' or 'juju ' in out: |
804 | return False |
805 | return True |
806 | @@ -43,6 +55,10 @@ |
807 | return distid == distname |
808 | |
809 | |
810 | +def get_ubuntu_version(): |
811 | + return platform.linux_distribution()[1] |
812 | + |
813 | + |
814 | def is_precise(): |
815 | return is_dist('precise') |
816 | |
817 | @@ -55,7 +71,7 @@ |
818 | """A wrapper to Popen to run commands in the command-line.""" |
819 | process = Popen(args, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env) |
820 | stdout, stderr = process.communicate() |
821 | - return process.returncode, stdout, stderr |
822 | + return process.returncode, stdout.decode('utf-8'), stderr.decode('utf-8') |
823 | |
824 | |
825 | def retries(timeout=30, delay=1): |
826 | @@ -79,7 +95,7 @@ |
827 | def add_log_content(runner, log_file): |
828 | """Add content of log_file as detail to the test runner.""" |
829 | try: |
830 | - log_file_content = open(log_file, 'rb').read() |
831 | + log_file_content = open(log_file, 'rb').read().decode('utf-8') |
832 | runner.addDetail( |
833 | "[%s] File %s content" % (datetime.now(), log_file), |
834 | text_content(log_file_content)) |
835 | @@ -112,8 +128,8 @@ |
836 | if env is None: |
837 | env = os.environ.copy() |
838 | retcode, output, err = run_command(cmd, env=env) |
839 | - runner.addDetail('%s stdout' % cmd, text_content(str(output))) |
840 | - runner.addDetail('%s stderr' % cmd, text_content(str(err))) |
841 | + runner.addDetail('%s stdout' % cmd, text_content(output)) |
842 | + runner.addDetail('%s stderr' % cmd, text_content(err)) |
843 | runner.assertThat(output, Contains(expected_output)) |
844 | runner.assertIs(retcode, expected_retcode) |
845 | |
846 | @@ -176,7 +192,7 @@ |
847 | to continue. The `message` parameter is written to the file. |
848 | """ |
849 | pause_file = '/tmp/paused' |
850 | - with file(pause_file, 'w') as f: |
851 | + with open(pause_file, 'w') as f: |
852 | f.write("The CI test suite is now PAUSED.\n") |
853 | f.write("To resume, please delete this file.\n") |
854 | f.write("---\n") |