141
by Diogo Matsubara
add test |
1 |
import os |
2 |
from simplejson import loads |
|
3 |
import sys |
|
4 |
from subprocess import Popen, PIPE |
|
5 |
from time import sleep |
|
149
by Diogo Matsubara
use TestCase from testools instead of unittest and improve assertions |
6 |
from testtools import TestCase |
154
by Diogo Matsubara
change login api assertion and comment out import pxe files for now |
7 |
from testtools.matchers import Contains, Equals, StartsWith |
182.2.1
by Raphael Badin
Retry to fetch the mediawiki homepage once. |
8 |
from testtools.content import text_content |
188.3.7
by Raphael Badin
Merge trunk. |
9 |
from unittest import skipIf |
174.1.1
by Raphael Badin
Add juju tests. |
10 |
import yaml |
195.1.1
by Raphael Badin
Do not use arch constraint if on precise. |
11 |
import platform |
181.1.1
by Raphael Badin
Add test for mediawiki service. |
12 |
import urllib2 |
141
by Diogo Matsubara
add test |
13 |
|
146
by Diogo Matsubara
add timeout decorator |
14 |
from timeout import timeout |
15 |
||
141
by Diogo Matsubara
add test |
16 |
sys.path.insert(0, "/usr/share/maas") |
17 |
os.environ['DJANGO_SETTINGS_MODULE'] = 'maas.settings' |
|
18 |
from django.core.management import call_command |
|
19 |
from django.contrib.auth.models import User |
|
20 |
||
21 |
from maasserver.models.user import get_creds_tuple |
|
22 |
from apiclient.creds import convert_tuple_to_string |
|
23 |
||
188.3.1
by Raphael Badin
Use env var to configure the test. |
24 |
# Environment variables that can be used to configured
|
25 |
# what is tested.
|
|
26 |
||
27 |
# Series to install on deployed nodes.
|
|
28 |
NODE_SERIES = os.environ.get('NODE_SERIES', 'precise') |
|
29 |
||
30 |
# Whether or not the ARM nodes should be used
|
|
31 |
# in the test.
|
|
188.3.5
by Raphael Badin
Formatting. |
32 |
DO_NOT_USE_ARM_NODES = bool( |
33 |
os.environ.get('DO_NOT_USE_ARM_NODES', False)) |
|
188.3.1
by Raphael Badin
Use env var to configure the test. |
34 |
|
194.1.3
by Raphael Badin
Avoid double negation. |
35 |
|
36 |
USE_ARM_NODES = not DO_NOT_USE_ARM_NODES |
|
37 |
||
38 |
||
188.3.7
by Raphael Badin
Merge trunk. |
39 |
# Whether or not the juju tests should be performed.
|
40 |
DO_NOT_TEST_JUJU = bool( |
|
41 |
os.environ.get('DO_NOT_TEST_JUJU', False)) |
|
42 |
||
188.3.1
by Raphael Badin
Use env var to configure the test. |
43 |
|
185.1.1
by Raphael Badin
Fix MAAS_URL. |
44 |
MAAS_URL = "http://192.168.21.5/MAAS" |
141
by Diogo Matsubara
add test |
45 |
ADMIN_USER = "admin" |
46 |
PASSWORD = "test" |
|
47 |
POWER_USER = "root" |
|
48 |
POWER_PASS = "ubuntu" |
|
49 |
||
50 |
LENOVO_LAB = { |
|
195.1.4
by Raphael Badin
Re-enable lenovo nodes. |
51 |
"00:E0:81:DD:D5:99" : "192.168.22.33", |
52 |
"00:E0:81:DD:D1:0B" : "192.168.22.34", |
|
53 |
"00:E0:81:DD:D4:11" : "192.168.22.35", |
|
54 |
"00:E0:81:D1:B1:47" : "192.168.22.36", |
|
188.2.4
by Raphael Badin
Add option to disable ARM nodes. |
55 |
# There are in a different network, enable them
|
56 |
# when testing with a CC on a different network
|
|
57 |
# is supported.
|
|
58 |
# "00:E0:81:DD:D1:1B" : "192.168.22.37",
|
|
59 |
# "00:E0:81:DD:D1:2B" : "192.168.22.38",
|
|
60 |
# "00:E0:81:DD:D1:A3" : "192.168.22.39",
|
|
61 |
# "00:E0:81:DC:38:6D" : "192.168.22.40",
|
|
62 |
# "00:E0:81:DD:D0:FF" : "192.168.22.41",
|
|
63 |
# "00:E0:81:DD:D4:F9" : "192.168.22.42"
|
|
141
by Diogo Matsubara
add test |
64 |
}
|
65 |
||
66 |
ARM_LAB = { |
|
67 |
'fc:2f:40:d8:fb:1a': '192.168.21.50', |
|
182.1.1
by Diogo Matsubara
Enable the 4 arm nodes again. |
68 |
'fc:2f:40:fa:2f:9a': '192.168.21.51', |
141
by Diogo Matsubara
add test |
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 |
LAB_DNS_CONFIG = """ |
|
74 |
options {
|
|
75 |
directory "/var/cache/bind";
|
|
76 |
forwarders {
|
|
77 |
10.98.0.1;
|
|
78 |
};
|
|
184.1.1
by Raphael Badin
Fix dns config. |
79 |
allow-query-cache {any;};
|
141
by Diogo Matsubara
add test |
80 |
dnssec-validation auto;
|
81 |
auth-nxdomain no; # conform to RFC1035
|
|
82 |
};
|
|
83 |
"""
|
|
84 |
||
174.1.1
by Raphael Badin
Add juju tests. |
85 |
JUJU_CONFIG = """ |
86 |
default: maas
|
|
87 |
environments:
|
|
88 |
maas:
|
|
89 |
type: maas
|
|
90 |
maas-server: '%s' |
|
91 |
maas-oauth: '%s' |
|
92 |
admin-secret: 'nothing'
|
|
93 |
default-series: %s |
|
174.1.5
by Raphael Badin
Fix tests. |
94 |
juju-origin: ppa
|
174.1.1
by Raphael Badin
Add juju tests. |
95 |
"""
|
96 |
||
97 |
||
177.3.1
by Raphael Badin
Improve juju-related code. |
98 |
def setup_juju_config(server, oauth, series): |
174.1.1
by Raphael Badin
Add juju tests. |
99 |
juju_dir = os.path.expanduser('~/.juju') |
174.1.4
by Raphael Badin
Split script. |
100 |
try: |
101 |
os.mkdir(juju_dir) |
|
102 |
except OSError: |
|
103 |
pass
|
|
174.1.1
by Raphael Badin
Add juju tests. |
104 |
config_content = JUJU_CONFIG % (server, oauth, series) |
105 |
juju_configfile = os.path.join(juju_dir, 'environments.yaml') |
|
174.1.3
by Raphael Badin
Fix config writing. |
106 |
juju_configfile_fd = open(juju_configfile, 'w') |
107 |
juju_configfile_fd.write(config_content) |
|
174.1.1
by Raphael Badin
Add juju tests. |
108 |
|
109 |
||
110 |
def get_token_str(): |
|
111 |
admin = User.objects.get(username=ADMIN_USER) |
|
112 |
token = admin.tokens.all()[0] |
|
113 |
return convert_tuple_to_string(get_creds_tuple(token)) |
|
114 |
||
141
by Diogo Matsubara
add test |
115 |
|
174.1.4
by Raphael Badin
Split script. |
116 |
def setup_ssh(): |
117 |
home_dir = os.path.expanduser('~/') |
|
118 |
ssh_dir = os.path.join(home_dir, '.ssh') |
|
119 |
# Setup ssh keys.
|
|
120 |
ssh_key = os.path.join(ssh_dir, 'id_rsa') |
|
121 |
if not os.path.exists(ssh_key): |
|
122 |
try: |
|
123 |
os.mkdir(ssh_dir) |
|
124 |
except OSError: |
|
125 |
pass
|
|
126 |
Popen( |
|
127 |
['ssh-keygen', '-t', 'rsa', '-N', '', '-f', ssh_key], |
|
128 |
stdout=PIPE, stderr=PIPE).communicate() |
|
129 |
# Setup ssh config.
|
|
130 |
ssh_config = os.path.join(ssh_dir, 'config') |
|
131 |
with open(ssh_config, 'w') as f: |
|
132 |
f.write('StrictHostKeyChecking no') |
|
133 |
||
134 |
||
135 |
def setup_local_dns(): |
|
136 |
content = open('/etc/resolv.conf').read() |
|
137 |
content = 'nameserver 127.0.0.1\n' + content |
|
138 |
with open('/etc/resolv.conf', 'w') as f: |
|
139 |
f.write(content) |
|
140 |
||
174.1.8
by Raphael Badin
Fix style. |
141 |
|
142 |
DEB_PROXY_CONFIG = """ |
|
143 |
cache_peer 10.98.0.13 parent 8000 0 no-query no-digest
|
|
144 |
never_direct allow all
|
|
145 |
"""
|
|
146 |
||
147 |
||
148 |
# Configure the region proxy to use the proxy on 10.98.0.13.
|
|
174.1.4
by Raphael Badin
Split script. |
149 |
def setup_deb_proxy(): |
150 |
config = '/etc/squid-deb-proxy/squid-deb-proxy.conf' |
|
151 |
content = open(config).read() |
|
174.1.8
by Raphael Badin
Fix style. |
152 |
content = content + DEB_PROXY_CONFIG |
174.1.4
by Raphael Badin
Split script. |
153 |
with open(config, 'w') as f: |
154 |
f.write(content) |
|
155 |
Popen( |
|
156 |
['sudo', 'service', 'squid-deb-proxy', 'restart'], |
|
157 |
stdout=PIPE, stderr=PIPE).communicate() |
|
174.1.6
by Raphael Badin
Remove classes. |
158 |
|
174.1.4
by Raphael Badin
Split script. |
159 |
|
141
by Diogo Matsubara
add test |
160 |
class TestMAASIntegration(TestCase): |
161 |
||
188.2.4
by Raphael Badin
Add option to disable ARM nodes. |
162 |
def get_node_count(self): |
163 |
"""The number of available nodes."""
|
|
164 |
count = len(LENOVO_LAB) |
|
194.1.3
by Raphael Badin
Avoid double negation. |
165 |
if USE_ARM_NODES: |
188.2.4
by Raphael Badin
Add option to disable ARM nodes. |
166 |
count += len(ARM_LAB) |
167 |
return count |
|
168 |
||
141
by Diogo Matsubara
add test |
169 |
def _run_command(self, args): |
186.1.1
by Raphael Badin
Connect stdin to PIPE. |
170 |
process = Popen(args, stdout=PIPE, stderr=PIPE, stdin=PIPE) |
141
by Diogo Matsubara
add test |
171 |
stdout, stderr = process.communicate() |
172 |
return stdout, stderr |
|
173 |
||
174 |
def _run_maas_cli(self, args): |
|
188.2.2
by Raphael Badin
Move addDetail into _run_maas_cli. |
175 |
result = self._run_command(["maas-cli", "maas"] + args) |
176 |
self.addDetail( |
|
177 |
'maas-cli maas %s' % str(args), text_content(str(result))) |
|
178 |
return result |
|
141
by Diogo Matsubara
add test |
179 |
|
199.1.1
by Raphael Badin
Disable raring. |
180 |
def test_00_disable_raring(self): |
199.1.2
by Raphael Badin
Add bug references. |
181 |
"""Disable raring, the images are not available yet.
|
182 |
# XXX: rvb 2013-02-04 bug=1115178
|
|
183 |
# XXX: rvb 2013-02-04 bug=1115175
|
|
184 |
"""
|
|
199.1.1
by Raphael Badin
Disable raring. |
185 |
maas_fd = open("/etc/maas/import_pxe_files" , "r+") |
186 |
maas_file = maas_fd.read() |
|
187 |
maas_file = maas_file.replace( |
|
188 |
'RELEASES="precise quantal raring"', |
|
189 |
'RELEASES="precise quantal"') |
|
190 |
maas_fd.seek(0) |
|
191 |
maas_fd.write(maas_file) |
|
192 |
maas_fd.close() |
|
193 |
||
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
194 |
def test_01_create_admin(self): |
141
by Diogo Matsubara
add test |
195 |
"""Run maas createsuperuser."""
|
196 |
cmd_output = call_command( |
|
197 |
"createadmin", username=ADMIN_USER, password=PASSWORD, |
|
198 |
email="example@canonical.com", noinput=True) |
|
199 |
# No output, means admin user was created successfully.
|
|
200 |
self.assertEqual(cmd_output, None) |
|
201 |
||
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
202 |
def test_02_update_maas_url(self): |
141
by Diogo Matsubara
add test |
203 |
#XXX: matsubara For some reason using a debconf file to set the
|
204 |
# initial value of DEFAULT_MAAS_URL is not working.
|
|
205 |
maas_fd = open("/etc/maas/maas_local_settings.py" , "r+") |
|
206 |
maas_file = maas_fd.read() |
|
207 |
maas_file = maas_file.replace( |
|
208 |
'DEFAULT_MAAS_URL = "http://10.98.0.90/MAAS"', |
|
209 |
'DEFAULT_MAAS_URL = "http://192.168.21.5/MAAS"') |
|
210 |
maas_fd.seek(0) |
|
211 |
maas_fd.write(maas_file) |
|
212 |
maas_fd.close() |
|
149
by Diogo Matsubara
use TestCase from testools instead of unittest and improve assertions |
213 |
output, err = self._run_command(["service", "apache2", "restart"]) |
150
by Diogo Matsubara
fix apacher restart assertion |
214 |
self.assertThat( |
215 |
output, StartsWith(' * Restarting web server apache2')) |
|
141
by Diogo Matsubara
add test |
216 |
|
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
217 |
def test_03_restart_dbus_avahi(self): |
218 |
"""XXX: matsubara bug=1065775 """
|
|
219 |
output, err = self._run_command(["service", "dbus", "restart"]) |
|
177.1.3
by Raphael Badin
Relax test test_03_restart_dbus_avahi. |
220 |
self.assertThat(output, Contains('dbus start/running')) |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
221 |
output, err = self._run_command(["service", "avahi-daemon", "restart"]) |
177.1.3
by Raphael Badin
Relax test test_03_restart_dbus_avahi. |
222 |
self.assertThat(output, Contains('avahi-daemon start/running')) |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
223 |
|
224 |
def test_04_update_pxe_config(self): |
|
141
by Diogo Matsubara
add test |
225 |
ephemerals_fd = open("/etc/maas/import_ephemerals", "r+") |
226 |
ephemerals = ephemerals_fd.read() |
|
177.1.4
by Raphael Badin
Update ephemerals correctly. |
227 |
# Update mirrors for both trunk and the quantal SRU.
|
228 |
ephemerals_snippet = ( |
|
229 |
'\n' |
|
177.1.5
by Raphael Badin
Fix snippet. |
230 |
'CLOUD_IMAGES_ARCHIVE="http://10.98.0.13/mirrors/maas-ephemeral"\n' |
231 |
'REMOTE_IMAGES_MIRROR="http://10.98.0.13/mirrors/maas-ephemeral"\n' |
|
197.1.1
by Raphael Badin
Do not use the daily images. |
232 |
# XXX: rvb 2013-01-18: Do not use the daily ephemeral images as
|
233 |
# they seem to be broken (more precisely, the image from 20130107 is
|
|
234 |
# and the one from 20121008 isn't); investigation is underway.
|
|
235 |
# 'STREAM=daily\n'
|
|
177.1.4
by Raphael Badin
Update ephemerals correctly. |
236 |
)
|
237 |
ephemerals += ephemerals_snippet |
|
141
by Diogo Matsubara
add test |
238 |
ephemerals_fd.seek(0) |
239 |
ephemerals_fd.write(ephemerals) |
|
240 |
ephemerals_fd.close() |
|
167
by Diogo Matsubara
remove one workaround and add another one |
241 |
# XXX: matsubara Bug=1074167
|
171
by Diogo Matsubara
do not download squashfs images and use proxy |
242 |
# Update import_pxe_files to not download squashfs images
|
243 |
# and use a proxy.
|
|
244 |
pxe_fd = open('/etc/maas/import_pxe_files', "r+") |
|
167
by Diogo Matsubara
remove one workaround and add another one |
245 |
pxe_file = pxe_fd.read() |
177.2.1
by Raphael Badin
Update test_04_update_pxe_config. |
246 |
pxe_snippet = 'export http_proxy="http://10.98.0.13:3128"\n' |
247 |
pxe_file = pxe_snippet + pxe_file |
|
167
by Diogo Matsubara
remove one workaround and add another one |
248 |
pxe_fd.seek(0) |
249 |
pxe_fd.write(pxe_file) |
|
250 |
pxe_fd.close() |
|
141
by Diogo Matsubara
add test |
251 |
|
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
252 |
def test_05_import_pxe_files(self): |
166
by Diogo Matsubara
add assertion for import pxe files, making sure it doesn't output any error |
253 |
output, err = self._run_command(["maas-import-pxe-files"]) |
170
by Diogo Matsubara
add proper assert for import-pxe-files output |
254 |
self.assertThat(output, Contains('Downloading to temporary location')) |
172
by Diogo Matsubara
add reference to bug 1076444 and comment out an assertion |
255 |
# XXX: matsubara Bug=1076444
|
256 |
# maas-import-pxe-files outputs to stderr during normal operation.
|
|
257 |
#self.assertIs(err, '')
|
|
141
by Diogo Matsubara
add test |
258 |
|
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
259 |
def test_06_update_preseed_arm(self): |
141
by Diogo Matsubara
add test |
260 |
#XXX: matsubara add workaround to boot arm nodes.
|
261 |
userdata_fd = open("/usr/share/maas/preseeds/enlist_userdata", "r+") |
|
262 |
userdata = userdata_fd.read() |
|
263 |
userdata += '\napt_sources:\n - source: "deb http://ports.ubuntu.com/ubuntu-ports precise-proposed main"' |
|
264 |
userdata_fd.seek(0) |
|
265 |
userdata_fd.write(userdata) |
|
266 |
userdata_fd.close() |
|
267 |
||
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
268 |
def test_07_login_api(self): |
174.1.1
by Raphael Badin
Add juju tests. |
269 |
token_str = get_token_str() |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
270 |
api_url = MAAS_URL + "/api/1.0/" |
271 |
output, err = self._run_command( |
|
272 |
["maas-cli", "login", "maas", api_url, token_str]) |
|
273 |
self.assertThat( |
|
274 |
output, Contains( |
|
185.1.2
by Raphael Badin
Fix test. |
275 |
"\nYou are now logged in to the MAAS server")) |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
276 |
|
198.1.3
by Raphael Badin
Fix cluster waiting code. |
277 |
def get_master_ng_uuid(self): |
278 |
output, err = self._run_maas_cli(["node-groups", "list"]) |
|
279 |
node_groups = loads(output) |
|
280 |
master_nodegroup = node_groups[0] |
|
198.1.5
by Raphael Badin
Fix typo. |
281 |
return master_nodegroup['uuid'] |
198.1.3
by Raphael Badin
Fix cluster waiting code. |
282 |
|
198.1.4
by Raphael Badin
Improve timeout. |
283 |
@timeout(5*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
284 |
def test_08_cluster_connected(self): |
285 |
# The master cluster is connected and changed the uuid field of the
|
|
286 |
# nodegroup object from 'master' to its UUID.
|
|
198.1.3
by Raphael Badin
Fix cluster waiting code. |
287 |
name = self.get_master_ng_uuid() |
288 |
while name == 'master': |
|
198.1.1
by Raphael Badin
Wait for cluster to connect. |
289 |
sleep(10) |
198.1.3
by Raphael Badin
Fix cluster waiting code. |
290 |
name = self.get_master_ng_uuid() |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
291 |
|
203
by Diogo Matsubara
separate workaround from test code |
292 |
def _update_dhcpd_apparmor_profile(self): |
293 |
"""Workaround for raring due to bug 1107686."""
|
|
294 |
dhcpd_fd = open("/etc/apparmor.d/usr.sbin.dhcpd", "r+") |
|
295 |
dhcpd_file = dhcpd_fd.read() |
|
296 |
dhcpd_file = dhcpd_file.replace( |
|
297 |
'network packet packet,', |
|
298 |
'network packet packet,\n network packet raw,') |
|
299 |
dhcpd_fd.seek(0) |
|
300 |
dhcpd_fd.write(dhcpd_file) |
|
301 |
dhcpd_fd.close() |
|
302 |
output, err = self._run_command(["service", "apparmor", "reload"]) |
|
303 |
self.assertThat(output, Contains('* Reloading AppArmor profiles')) |
|
304 |
||
198.1.1
by Raphael Badin
Wait for cluster to connect. |
305 |
@timeout(60) |
306 |
def test_09_set_up_dhcp(self): |
|
202
by Diogo Matsubara
workaround for raring only |
307 |
if "raring" in platform.linux_distribution(): |
203
by Diogo Matsubara
separate workaround from test code |
308 |
self._update_dhcpd_apparmor_profile() |
201
by Diogo Matsubara
workaround for bug 1107686 |
309 |
|
145
by Diogo Matsubara
update how dhcp is configured and min number of nodes to wait for |
310 |
output, err = self._run_maas_cli(["node-groups", "list"]) |
311 |
node_groups = loads(output) |
|
153
by Diogo Matsubara
fix assertion for dhcp setup |
312 |
output, err = self._run_maas_cli([ |
158
by Diogo Matsubara
proper call to maas-cli |
313 |
"node-group-interface", "update", node_groups[0]['uuid'], |
314 |
"eth1", "ip=192.168.21.5", "interface=eth1", "management=2", |
|
141
by Diogo Matsubara
add test |
315 |
"subnet_mask=255.255.255.0", |
316 |
"broadcast_ip=192.168.21.255", |
|
317 |
"router_ip=192.168.21.1", |
|
318 |
"ip_range_low=192.168.21.10", |
|
319 |
"ip_range_high=192.168.21.30"]) |
|
156
by Diogo Matsubara
change dhcp assertions |
320 |
node_group = loads(output) |
321 |
self.assertThat(node_group['ip'], Equals('192.168.21.5')) |
|
322 |
self.assertThat(node_group['interface'], Equals('eth1')) |
|
323 |
self.assertThat(node_group['subnet_mask'], Equals('255.255.255.0')) |
|
324 |
self.assertThat(node_group['broadcast_ip'], Equals('192.168.21.255')) |
|
325 |
self.assertThat(node_group['ip_range_low'], Equals('192.168.21.10')) |
|
326 |
self.assertThat(node_group['ip_range_high'], Equals('192.168.21.30')) |
|
153
by Diogo Matsubara
fix assertion for dhcp setup |
327 |
# Wait for the task to complete and create the dhcpd.conf file.
|
141
by Diogo Matsubara
add test |
328 |
while os.path.exists("/etc/maas/dhcpd.conf") is False: |
329 |
sleep(2) |
|
330 |
||
198.1.1
by Raphael Badin
Wait for cluster to connect. |
331 |
def test_10_update_dns_config(self): |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
332 |
#XXX: matsubara Could be asked by maas-dns package and configurable
|
333 |
# through debconf seed file.
|
|
334 |
dns_config = open("/etc/bind/named.conf.options", 'w') |
|
335 |
dns_config.write(LAB_DNS_CONFIG) |
|
336 |
dns_config.close() |
|
337 |
output, err = self._run_command(["service", "bind9", "restart"]) |
|
162
by Diogo Matsubara
more assertion fixes |
338 |
self.assertThat(output, Contains( |
339 |
'* Starting domain name service... bind9')) |
|
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
340 |
|
141
by Diogo Matsubara
add test |
341 |
def power_on(self, ip, user, password): |
184.2.1
by Diogo Matsubara
add --stop to nosetests, so test will stop on first failure. Add assertion for ipmi power on and off commands |
342 |
output, err = self._run_command( |
141
by Diogo Matsubara
add test |
343 |
["ipmipower", "-h", ip, "-u", user, "-p", password, "--on"]) |
184.2.8
by Diogo Matsubara
use self.addDetail() to add more debug info when power on and off fail |
344 |
self.addDetail('IPMI power on %s' % ip, text_content(str(output))) |
184.2.4
by Diogo Matsubara
use contains for power on/off assertions |
345 |
self.assertThat(output, Contains("%s: ok" % ip)) |
141
by Diogo Matsubara
add test |
346 |
|
347 |
def power_off(self, ip, user, password): |
|
184.2.2
by Diogo Matsubara
fix power on |
348 |
output, err = self._run_command( |
141
by Diogo Matsubara
add test |
349 |
["ipmipower", "-h", ip, "-u", user, "-p", password, "--off"]) |
184.2.8
by Diogo Matsubara
use self.addDetail() to add more debug info when power on and off fail |
350 |
self.addDetail('IPMI power off %s' % ip, text_content(str(output))) |
184.2.7
by Diogo Matsubara
remove debug code |
351 |
self.assertThat(output, Contains("%s: ok" % ip)) |
141
by Diogo Matsubara
add test |
352 |
|
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
353 |
def _boot_nodes(self): |
141
by Diogo Matsubara
add test |
354 |
# Run ipmipower to boot up nodes.
|
355 |
for ipmi_address in LENOVO_LAB.values(): |
|
356 |
self.power_off(ipmi_address, POWER_USER, POWER_PASS) |
|
357 |
self.power_on(ipmi_address, POWER_USER, POWER_PASS) |
|
194.1.3
by Raphael Badin
Avoid double negation. |
358 |
if USE_ARM_NODES: |
188.2.4
by Raphael Badin
Add option to disable ARM nodes. |
359 |
for ipmi_address in ARM_LAB.values(): |
360 |
self.power_off(ipmi_address, 'admin', 'admin') |
|
361 |
self.power_on(ipmi_address, 'admin', 'admin') |
|
141
by Diogo Matsubara
add test |
362 |
|
198.1.1
by Raphael Badin
Wait for cluster to connect. |
363 |
def test_11_boot_nodes_enlist(self): |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
364 |
self._boot_nodes() |
365 |
||
188.2.4
by Raphael Badin
Add option to disable ARM nodes. |
366 |
def _wait_nodes(self, status, min_node=None): |
367 |
"""Wait for `min_node` nodes with status `status`."""
|
|
368 |
if min_node is None: |
|
369 |
min_node = self.get_node_count() |
|
141
by Diogo Matsubara
add test |
370 |
# XXX: matsubara Can't filter by status.
|
371 |
output, err = self._run_maas_cli(["nodes", "list"]) |
|
372 |
node_list = loads(output) |
|
373 |
filtered_list = [ |
|
374 |
node for node in node_list if node['status'] == status] |
|
375 |
while not len(filtered_list) == min_node: |
|
376 |
sleep(5) |
|
377 |
output, err = self._run_maas_cli(["nodes", "list"]) |
|
378 |
node_list = loads(output) |
|
379 |
filtered_list = [ |
|
380 |
node for node in node_list if node['status'] == status] |
|
381 |
||
182.1.1
by Diogo Matsubara
Enable the 4 arm nodes again. |
382 |
@timeout(5*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
383 |
def test_12_check_nodes_declared(self): |
141
by Diogo Matsubara
add test |
384 |
self._wait_nodes(0) |
385 |
||
198.1.1
by Raphael Badin
Wait for cluster to connect. |
386 |
def test_13_set_nodes_ipmi_config(self): |
141
by Diogo Matsubara
add test |
387 |
"""Set IPMI configuration for each node."""
|
388 |
all_nodes = {} |
|
389 |
all_nodes.update(LENOVO_LAB) |
|
390 |
all_nodes.update(ARM_LAB) |
|
391 |
for mac in all_nodes.keys(): |
|
392 |
# run maas-cli command to search node by mac and return system_id
|
|
393 |
out, err = self._run_maas_cli( |
|
394 |
["nodes", "list", "mac_address=%s" % mac]) |
|
395 |
node_list = loads(out) |
|
396 |
for node in node_list: |
|
397 |
if ARM_LAB.has_key(mac): |
|
398 |
power_user = power_pass = 'admin' |
|
399 |
else: |
|
400 |
power_user = POWER_USER |
|
401 |
power_pass = POWER_PASS |
|
174.1.1
by Raphael Badin
Add juju tests. |
402 |
self._run_maas_cli( |
141
by Diogo Matsubara
add test |
403 |
["node", "update", node['system_id'], "power_type=ipmi", |
404 |
"power_parameters_power_address=%s " % all_nodes[mac], |
|
405 |
"power_parameters_power_user=%s" % power_user, |
|
406 |
"power_parameters_power_pass=%s" % power_pass]) |
|
407 |
||
198.1.1
by Raphael Badin
Wait for cluster to connect. |
408 |
def test_14_commission_nodes(self): |
141
by Diogo Matsubara
add test |
409 |
# Use maas-cli to accept all nodes.
|
148
by Diogo Matsubara
add asserts |
410 |
output, err = self._run_maas_cli(["nodes","accept-all"]) |
411 |
for node in loads(output): |
|
163
by Diogo Matsubara
fix assertion after commission |
412 |
self.assertEqual(node['status'], 1) |
141
by Diogo Matsubara
add test |
413 |
|
174.1.10
by Raphael Badin
Increase timeout. |
414 |
@timeout(10*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
415 |
def test_15_check_nodes_ready(self): |
159
by Diogo Matsubara
change test name scheme so we can get better reporting when they're running |
416 |
self._wait_nodes(4) |
174.1.1
by Raphael Badin
Add juju tests. |
417 |
|
174.1.4
by Raphael Badin
Split script. |
418 |
def setup_juju(self): |
174.1.5
by Raphael Badin
Fix tests. |
419 |
setup_deb_proxy() |
174.1.4
by Raphael Badin
Split script. |
420 |
setup_ssh() |
174.1.1
by Raphael Badin
Add juju tests. |
421 |
token_str = get_token_str() |
188.1.3
by Raphael Badin
Fix comment. |
422 |
# Workaround bug 972829 (in juju precise).
|
188.1.2
by Raphael Badin
Fix url hack. |
423 |
server_url = MAAS_URL.replace('/MAAS', ':80/MAAS') |
188.3.1
by Raphael Badin
Use env var to configure the test. |
424 |
setup_juju_config(server_url, token_str, series=NODE_SERIES) |
174.1.4
by Raphael Badin
Split script. |
425 |
setup_local_dns() |
426 |
||
177.3.1
by Raphael Badin
Improve juju-related code. |
427 |
def _run_juju_command(self, args): |
428 |
output, err = self._run_command(["juju"] + args) |
|
177.3.3
by Raphael Badin
Fix juju output check. |
429 |
# For some reason, in the log, juju replaces '-' by '_'.
|
430 |
command_name = args[0].replace('-', '_') |
|
177.3.1
by Raphael Badin
Improve juju-related code. |
431 |
self.assertIn( |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
432 |
"INFO '%s' command finished successfully" % command_name, err) |
177.3.1
by Raphael Badin
Improve juju-related code. |
433 |
return output |
434 |
||
188.3.10
by Raphael Badin
Fix message. |
435 |
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
195.1.2
by Raphael Badin
Increase timeout. |
436 |
@timeout(50*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
437 |
def test_16_juju_bootstrap(self): |
174.1.4
by Raphael Badin
Split script. |
438 |
self.setup_juju() |
177.3.1
by Raphael Badin
Improve juju-related code. |
439 |
self._run_juju_command(['bootstrap']) |
440 |
self._run_juju_command(['status']) |
|
441 |
||
442 |
def get_juju_status(self): |
|
443 |
status_output = self._run_juju_command(["status"]) |
|
188.2.1
by Raphael Badin
Add details. |
444 |
self.addDetail('juju status', text_content(str(status_output))) |
177.3.1
by Raphael Badin
Improve juju-related code. |
445 |
status = yaml.load(status_output) |
446 |
return status |
|
447 |
||
448 |
def _wait_machines_running(self, nb_machines): |
|
449 |
"""Wait until at least `nb_machines` have their agent running."""
|
|
450 |
while True: |
|
451 |
status = self.get_juju_status() |
|
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
452 |
machines = status['machines'].values() |
177.3.1
by Raphael Badin
Improve juju-related code. |
453 |
running_machines = [ |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
454 |
machine for machine in machines |
182.2.3
by Raphael Badin
Fix juju status parsing. |
455 |
if machine.get('agent-state', '') == 'running'] |
177.3.1
by Raphael Badin
Improve juju-related code. |
456 |
if len(running_machines) >= nb_machines: |
457 |
break
|
|
458 |
sleep(20) |
|
459 |
||
460 |
def _wait_units_started(self, service, nb_units): |
|
461 |
"""Wait until a service has at least `nb_units` units."""
|
|
462 |
while True: |
|
463 |
status = self.get_juju_status() |
|
182.2.3
by Raphael Badin
Fix juju status parsing. |
464 |
try: |
465 |
units = status['services'][service]['units'].values() |
|
466 |
except KeyError: |
|
467 |
units = [] |
|
177.3.1
by Raphael Badin
Improve juju-related code. |
468 |
started_units = [ |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
469 |
unit for unit in units |
182.2.3
by Raphael Badin
Fix juju status parsing. |
470 |
if unit.get('agent-state', '') == 'started'] |
177.3.1
by Raphael Badin
Improve juju-related code. |
471 |
if len(started_units) >= nb_units: |
472 |
break
|
|
473 |
sleep(20) |
|
174.1.1
by Raphael Badin
Add juju tests. |
474 |
|
188.3.10
by Raphael Badin
Fix message. |
475 |
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
476 |
def test_17_juju_setup(self): |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
477 |
# Deploy mediawiki with its mysql db.
|
177.3.1
by Raphael Badin
Improve juju-related code. |
478 |
self._run_juju_command(["deploy", "mysql"]) |
195.1.1
by Raphael Badin
Do not use arch constraint if on precise. |
479 |
is_precise = platform.linux_distribution()[2] == 'precise' |
480 |
if USE_ARM_NODES and not is_precise: |
|
194.1.1
by Raphael Badin
Test. |
481 |
self._run_juju_command( |
194.1.2
by Raphael Badin
Test. |
482 |
["deploy", "mediawiki", "--constraints", "arch=arm"]) |
194.1.3
by Raphael Badin
Avoid double negation. |
483 |
else: |
484 |
self._run_juju_command(["deploy", "mediawiki"]) |
|
177.3.1
by Raphael Badin
Improve juju-related code. |
485 |
self._run_juju_command(["add-relation", "mediawiki:db", "mysql"]) |
486 |
self._run_juju_command(["expose", "mediawiki"]) |
|
177.3.7
by Raphael Badin
Fix comment. |
487 |
# Add new unit for test 18: we run that here to
|
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
488 |
# parallelize the installation of the new machine.
|
489 |
self._run_juju_command(["add-unit", "mediawiki"]) |
|
490 |
||
188.3.10
by Raphael Badin
Fix message. |
491 |
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
191.1.1
by Raphael Badin
Improve timeout to cope with slow ARM nodes. |
492 |
@timeout(30*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
493 |
def test_18_juju_deploy_mediawiki(self): |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
494 |
self._wait_machines_running(3) |
495 |
self._wait_units_started('mediawiki', 1) |
|
496 |
||
188.3.10
by Raphael Badin
Fix message. |
497 |
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
188.3.7
by Raphael Badin
Merge trunk. |
498 |
@timeout(5*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
499 |
def test_19_mediawiki_homepage(self): |
182.2.5
by Raphael Badin
Wait a bit for mediawiki to come up. |
500 |
while True: |
501 |
status = self.get_juju_status() |
|
502 |
mediawiki_address = ( |
|
503 |
status['services']['mediawiki']['units'].values( |
|
504 |
)[0]['public-address']) |
|
505 |
self.addDetail('juju status', text_content(str(status))) |
|
182.2.8
by Raphael Badin
Fix typo. |
506 |
mediawiki_url = 'http://%s/mediawiki/' % mediawiki_address |
182.2.5
by Raphael Badin
Wait a bit for mediawiki to come up. |
507 |
opener = urllib2.build_opener() |
508 |
try: |
|
509 |
homepage = opener.open(mediawiki_url).read() |
|
510 |
except urllib2.URLError: |
|
511 |
pass
|
|
182.2.6
by Raphael Badin
Fix exception handling.. |
512 |
else: |
196.1.1
by Raphael Badin
Improve temporary failures detection code. |
513 |
temporary_failures = ( |
514 |
'database error' in homepage or |
|
515 |
"LocalSettings.php not found" in homepage |
|
516 |
)
|
|
517 |
if not temporary_failures: |
|
182.2.6
by Raphael Badin
Fix exception handling.. |
518 |
break
|
182.2.5
by Raphael Badin
Wait a bit for mediawiki to come up. |
519 |
sleep(15) |
182.2.2
by Raphael Badin
Improve error detection. |
520 |
|
181.1.1
by Raphael Badin
Add test for mediawiki service. |
521 |
self.assertIn("<title>Please set name of wiki</title>", homepage) |
522 |
||
188.3.10
by Raphael Badin
Fix message. |
523 |
@skipIf(DO_NOT_TEST_JUJU, "Not testing juju") |
191.1.1
by Raphael Badin
Improve timeout to cope with slow ARM nodes. |
524 |
@timeout(30*60) |
198.1.1
by Raphael Badin
Wait for cluster to connect. |
525 |
def test_20_juju_add_unit_mediawiki(self): |
177.3.2
by Raphael Badin
Fix juju wrappers. Add test. |
526 |
self._wait_machines_running(4) |
527 |
self._wait_units_started('mediawiki', 2) |