Merge lp:~ltrager/maas/stress_ng_tests into lp:~maas-committers/maas/trunk
- stress_ng_tests
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Lee Trager |
Approved revision: | no longer in the source branch. |
Merged at revision: | 5878 |
Proposed branch: | lp:~ltrager/maas/stress_ng_tests |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
617 lines (+217/-51) 20 files modified
src/maasserver/api/scripts.py (+4/-1) src/maasserver/api/tests/test_scripts.py (+14/-0) src/maasserver/forms/script.py (+5/-0) src/maasserver/forms/tests/test_script.py (+24/-0) src/metadataserver/builtin_scripts/__init__.py (+32/-10) src/metadataserver/builtin_scripts/internet_connectivity.sh (+5/-4) src/metadataserver/builtin_scripts/memtester.sh (+4/-3) src/metadataserver/builtin_scripts/ntp.sh (+4/-4) src/metadataserver/builtin_scripts/stress-ng-cpu-long.sh (+6/-6) src/metadataserver/builtin_scripts/stress-ng-cpu-short.sh (+32/-0) src/metadataserver/builtin_scripts/stress-ng-memory-long.sh (+16/-6) src/metadataserver/builtin_scripts/stress-ng-memory-short.sh (+36/-0) src/metadataserver/builtin_scripts/tests/test_builtin_scripts.py (+15/-3) src/metadataserver/user_data/templates/base_user_data.sh (+1/-1) src/metadataserver/user_data/templates/snippets/maas_enlist.sh (+1/-1) src/metadataserver/user_data/templates/snippets/maas_run_remote_scripts.py (+6/-0) src/provisioningserver/refresh/node_info_scripts.py (+6/-6) src/provisioningserver/refresh/tests/test_node_info_scripts.py (+1/-1) src/provisioningserver/refresh/tests/test_refresh.py (+2/-2) src/provisioningserver/rpc/tests/test_clusterservice.py (+3/-3) |
To merge this branch: | bzr merge lp:~ltrager/maas/stress_ng_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mike Pontillo (community) | Approve | ||
Review via email: mp+321027@code.launchpad.net |
Commit message
Add stress-ng short cpu and memory tests and fix stress_
Description of the change
Add stress-ng short cpu and memory tests. These tests run by default during commissioning and testing. This adds 10 minutes to commissioning time.
While testing I discovered the stress_ng_cpu_long fails due to using too much RAM. I've reworked it so while the OOM killer is tripped on a few stress-ng threads it still passes. I also fixed a bug where the script form was resetting any value that wasn't specified on update and new default scripts weren't being added in certain cases.
Gavin Panella (allenap) wrote : | # |
Lee Trager (ltrager) wrote : | # |
Fully agree and implemented. I've been using /bin/sh because only because the existing commissioning script use it.
Gavin Panella (allenap) wrote : | # |
Sorry, I wasn't clear. Despite the similarities between sh and bash a change from one to the other may introduce bugs, and we're close to release. I wanted your feedback on whether you thought a policy like that would be okay with you. I guess that's a yes! You may want to revert r5860 and keep it for another day. And sorry again: rereading my comment makes it clear to me now that it was unclear when I wrote it.
Lee Trager (ltrager) wrote : | # |
I took a look how MAAS is using bash. Its used in simple commissioning and testing scripts, as part of unit tests, or in the user_data scripts. The commissioning and user_data scripts are tested pretty well by CI and bash is a superset of shell so it should be compatible even for more advanced scripts. I think its safe to switch, the riskiest would be the user_data scripts. If we really want to be cautious but move towards a bash world we could switch everywhere but the user data scripts for now.
Mike Pontillo (mpontillo) wrote : | # |
The code looks good. I'll test it out a bit before I approve.
Mike Pontillo (mpontillo) wrote : | # |
Oh, and please change 'sudo' to 'sudo -n' everywhere. I know the risk is small for scripts like these which run in the ephemeral environment, but I'd rather err on the safe side.
Mike Pontillo (mpontillo) wrote : | # |
Saw this on a machine with 64 GB of RAM (4 cores, 8 with hyperthreading, if it matters).
Value 8262470656 is out of range for vm-bytes, allowed: 4096 .. 4294967296
Lee Trager (ltrager) wrote : | # |
Thanks for running the tests! I've added -n to all test scripts which use sudo. The failure you saw was because stress-ng only allows 4GB of testing memory per thread. None of my test systems have more then 4GB total so I never ran into it. I've modified the stress-ng-memory tests to use enough threads so that no thread uses more then 4GB of RAM.
Mike Pontillo (mpontillo) wrote : | # |
Thanks for the fix. Re-tested and it's looking good.
Preview Diff
1 | === modified file 'src/maasserver/api/scripts.py' |
2 | --- src/maasserver/api/scripts.py 2017-03-23 18:20:00 +0000 |
3 | +++ src/maasserver/api/scripts.py 2017-03-29 23:42:47 +0000 |
4 | @@ -259,7 +259,8 @@ |
5 | def download(self, request, name): |
6 | """Download a script. |
7 | |
8 | - :param revision: What revision to download, latest by default. |
9 | + :param revision: What revision to download, latest by default. Can use |
10 | + rev as a shortcut. |
11 | :type revision: integer |
12 | """ |
13 | if name.isdigit(): |
14 | @@ -267,6 +268,8 @@ |
15 | else: |
16 | script = get_object_or_404(Script, name=name) |
17 | revision = get_optional_param(request.GET, 'revision', None, Int) |
18 | + if revision is None: |
19 | + revision = get_optional_param(request.GET, 'rev', None, Int) |
20 | if revision is not None: |
21 | for rev in script.script.previous_versions(): |
22 | if rev.id == revision: |
23 | |
24 | === modified file 'src/maasserver/api/tests/test_scripts.py' |
25 | --- src/maasserver/api/tests/test_scripts.py 2017-03-23 18:20:00 +0000 |
26 | +++ src/maasserver/api/tests/test_scripts.py 2017-03-29 23:42:47 +0000 |
27 | @@ -356,6 +356,20 @@ |
28 | self.assertEquals( |
29 | script.script.previous_version.data, response.content.decode()) |
30 | |
31 | + def test_download_gets_previous_rev(self): |
32 | + script = factory.make_Script() |
33 | + script.script = script.script.update(factory.make_string()) |
34 | + script.save() |
35 | + response = self.client.get( |
36 | + self.get_script_uri(script), |
37 | + { |
38 | + 'op': 'download', |
39 | + 'rev': script.script.previous_version.id, |
40 | + }) |
41 | + self.assertThat(response, HasStatusCode(http.client.OK)) |
42 | + self.assertEquals( |
43 | + script.script.previous_version.data, response.content.decode()) |
44 | + |
45 | def test_download_errors_on_unknown_revision(self): |
46 | script = factory.make_Script() |
47 | response = self.client.get( |
48 | |
49 | === modified file 'src/maasserver/forms/script.py' |
50 | --- src/maasserver/forms/script.py 2017-03-10 09:15:31 +0000 |
51 | +++ src/maasserver/forms/script.py 2017-03-29 23:42:47 +0000 |
52 | @@ -83,6 +83,11 @@ |
53 | self, 'script_type', |
54 | 'Must be %d, test, testing, %d, commission, or commissioning.' |
55 | % (SCRIPT_TYPE.TESTING, SCRIPT_TYPE.COMMISSIONING)) |
56 | + # If a field wasn't passed in keep the old values when updating. |
57 | + if self.instance.id is not None: |
58 | + for field in self._meta.fields: |
59 | + if field not in self.data: |
60 | + cleaned_data[field] = getattr(self.instance, field) |
61 | return cleaned_data |
62 | |
63 | def is_valid(self): |
64 | |
65 | === modified file 'src/maasserver/forms/tests/test_script.py' |
66 | --- src/maasserver/forms/tests/test_script.py 2017-03-10 09:15:31 +0000 |
67 | +++ src/maasserver/forms/tests/test_script.py 2017-03-29 23:42:47 +0000 |
68 | @@ -193,6 +193,30 @@ |
69 | ] |
70 | }, form.errors) |
71 | |
72 | + def test__update_script_doesnt_effect_other_fields(self): |
73 | + script = factory.make_Script() |
74 | + script_content = factory.make_string() |
75 | + name = script.name |
76 | + title = script.title |
77 | + description = script.description |
78 | + tags = script.tags |
79 | + script_type = script.script_type |
80 | + timeout = script.timeout |
81 | + destructive = script.destructive |
82 | + |
83 | + form = ScriptForm(data={'script': script_content}, instance=script) |
84 | + self.assertTrue(form.is_valid(), form.errors) |
85 | + script = form.save() |
86 | + |
87 | + self.assertEquals(name, script.name) |
88 | + self.assertEquals(title, script.title) |
89 | + self.assertEquals(description, script.description) |
90 | + self.assertEquals(tags, script.tags) |
91 | + self.assertEquals(script_type, script.script_type) |
92 | + self.assertEquals(timeout, script.timeout) |
93 | + self.assertEquals(destructive, script.destructive) |
94 | + self.assertFalse(script.default) |
95 | + |
96 | def test__can_use_script_type_name(self): |
97 | script_type_name = random.choice([ |
98 | 'test', 'testing', |
99 | |
100 | === modified file 'src/metadataserver/builtin_scripts/__init__.py' |
101 | --- src/metadataserver/builtin_scripts/__init__.py 2017-03-29 21:13:51 +0000 |
102 | +++ src/metadataserver/builtin_scripts/__init__.py 2017-03-29 23:42:47 +0000 |
103 | @@ -7,6 +7,7 @@ |
104 | 'load_builtin_scripts', |
105 | ] |
106 | |
107 | +from datetime import timedelta |
108 | import os |
109 | |
110 | import attr |
111 | @@ -48,7 +49,8 @@ |
112 | tags = attr.ib(default=None, validator=instance_of(list)) |
113 | script_type = attr.ib( |
114 | default=SCRIPT_TYPE.TESTING, validator=instance_of(int)) |
115 | - timeout = attr.ib(default=0, validator=instance_of(int)) |
116 | + timeout = attr.ib( |
117 | + default=timedelta(seconds=0), validator=instance_of(timedelta)) |
118 | destructive = attr.ib(default=False, validator=instance_of(bool)) |
119 | filename = attr.ib(default=None, validator=instance_of(str)) |
120 | |
121 | @@ -63,7 +65,7 @@ |
122 | title='Storage status', |
123 | description='Validate SMART health for all drives in parallel.', |
124 | tags=['storage', 'commissioning'], |
125 | - timeout=60 * 5, |
126 | + timeout=timedelta(minutes=5), |
127 | filename='smartctl.py', |
128 | ), |
129 | BuiltinScript( |
130 | @@ -73,7 +75,7 @@ |
131 | 'Run the short SMART self-test and validate SMART health on all ' |
132 | 'drives in parallel'), |
133 | tags=['storage'], |
134 | - timeout=60 * 10, |
135 | + timeout=timedelta(minutes=10), |
136 | filename='smartctl.py', |
137 | ), |
138 | BuiltinScript( |
139 | @@ -106,7 +108,7 @@ |
140 | title='Network validation', |
141 | description='Download a file from images.maas.io.', |
142 | tags=['network', 'internet'], |
143 | - timeout=60 * 5, |
144 | + timeout=timedelta(minutes=5), |
145 | filename='internet_connectivity.sh', |
146 | ), |
147 | BuiltinScript( |
148 | @@ -114,23 +116,39 @@ |
149 | title='CPU validation', |
150 | description='Run the stress-ng CPU tests over 12 hours.', |
151 | tags=['cpu'], |
152 | - timeout=60 * 60 * 12, |
153 | - filename='stress_ng_cpu_long.sh', |
154 | + timeout=timedelta(hours=12), |
155 | + filename='stress-ng-cpu-long.sh', |
156 | + ), |
157 | + BuiltinScript( |
158 | + name='stress-ng-cpu-short', |
159 | + title='CPU validation', |
160 | + description='Stress test the CPU for 5 minutes.', |
161 | + tags=['cpu'], |
162 | + timeout=timedelta(minutes=5), |
163 | + filename='stress-ng-cpu-short.sh', |
164 | ), |
165 | BuiltinScript( |
166 | name='stress-ng-memory-long', |
167 | title='Memory integrity', |
168 | description='Run the stress-ng memory tests over 12 hours.', |
169 | tags=['memory'], |
170 | - timeout=60 * 60 * 12, |
171 | - filename='stress_ng_memory_long.sh', |
172 | + timeout=timedelta(hours=12), |
173 | + filename='stress-ng-memory-long.sh', |
174 | + ), |
175 | + BuiltinScript( |
176 | + name='stress-ng-memory-short', |
177 | + title='Memory validation', |
178 | + description='Stress test memory for 5 minutes.', |
179 | + tags=['memory'], |
180 | + timeout=timedelta(minutes=5), |
181 | + filename='stress-ng-memory-short.sh', |
182 | ), |
183 | BuiltinScript( |
184 | name='ntp', |
185 | title='NTP validation', |
186 | description='Run ntp clock set to verify NTP connectivity.', |
187 | tags=['network', 'ntp'], |
188 | - timeout=60, |
189 | + timeout=timedelta(minutes=1), |
190 | filename='ntp.sh', |
191 | ), |
192 | ] |
193 | @@ -161,11 +179,15 @@ |
194 | # Don't add back old versions of a script. This prevents two |
195 | # connected regions with different versions of a script from |
196 | # fighting with eachother. |
197 | + no_update = False |
198 | for vtf in script_in_db.script.previous_versions(): |
199 | if vtf.data == script_content: |
200 | # Don't update anything if we detect we have an old |
201 | # version of the builtin scripts |
202 | - return |
203 | + no_update = True |
204 | + break |
205 | + if no_update: |
206 | + continue |
207 | script_in_db.script = script_in_db.script.update( |
208 | script_content, |
209 | "Updated by maas-%s" % get_maas_package_version()) |
210 | |
211 | === modified file 'src/metadataserver/builtin_scripts/internet_connectivity.sh' |
212 | --- src/metadataserver/builtin_scripts/internet_connectivity.sh 2017-03-10 16:34:33 +0000 |
213 | +++ src/metadataserver/builtin_scripts/internet_connectivity.sh 2017-03-29 23:42:47 +0000 |
214 | @@ -1,4 +1,4 @@ |
215 | -#!/bin/sh -e |
216 | +#!/bin/bash -e |
217 | # |
218 | # internet_connectivity - Check if the system has access to the Internet. |
219 | # |
220 | @@ -20,6 +20,7 @@ |
221 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
222 | |
223 | # Download the index.sjson file used by MAAS to download images to validate |
224 | -# internet connectivity. Close stderr so we don't get the progress from curl. |
225 | -curl -I -A maas_internet_connectivity_test \ |
226 | - https://images.maas.io/ephemeral-v3/daily/streams/v1/index.sjson |
227 | +# internet connectivity. |
228 | +URL="https://images.maas.io/ephemeral-v3/daily/streams/v1/index.sjson" |
229 | +echo "Attempting to retrieve: $URL" |
230 | +curl -ILSsv -A maas_internet_connectivity_test $URL |
231 | |
232 | === modified file 'src/metadataserver/builtin_scripts/memtester.sh' |
233 | --- src/metadataserver/builtin_scripts/memtester.sh 2017-03-23 18:20:00 +0000 |
234 | +++ src/metadataserver/builtin_scripts/memtester.sh 2017-03-29 23:42:47 +0000 |
235 | @@ -1,4 +1,4 @@ |
236 | -#!/bin/sh -e |
237 | +#!/bin/bash -e |
238 | # |
239 | # memtester - Run memtester against all available userspace memory. |
240 | # |
241 | @@ -19,10 +19,11 @@ |
242 | # You should have received a copy of the GNU Affero General Public License |
243 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
244 | |
245 | -sudo apt-get install -q -y memtester |
246 | +sudo -n apt-get install -q -y memtester |
247 | +echo |
248 | |
249 | # Memtester can only test memory available to userspace. Reserve 32M so the |
250 | # test doesn't fail due to the OOM killer. Only run memtester against available |
251 | # RAM once. |
252 | -sudo memtester \ |
253 | +sudo -n memtester \ |
254 | $(awk '/MemAvailable/ { print ($2 - 32768) "K"}' /proc/meminfo) 1 |
255 | |
256 | === modified file 'src/metadataserver/builtin_scripts/ntp.sh' |
257 | --- src/metadataserver/builtin_scripts/ntp.sh 2017-03-23 18:20:00 +0000 |
258 | +++ src/metadataserver/builtin_scripts/ntp.sh 2017-03-29 23:42:47 +0000 |
259 | @@ -1,4 +1,4 @@ |
260 | -#!/bin/sh -e |
261 | +#!/bin/bash -e |
262 | # |
263 | # ntp - Run ntp clock set to verify NTP connectivity. |
264 | # |
265 | @@ -24,7 +24,7 @@ |
266 | # the configured NTP server is accessible. |
267 | e=0 |
268 | ntpq -np |
269 | -sudo systemctl stop ntp.service |
270 | -sudo timeout 10 ntpd -gq || e=$? |
271 | -sudo systemctl start ntp.service |
272 | +sudo -n systemctl stop ntp.service |
273 | +sudo -n timeout 10 ntpd -gq || e=$? |
274 | +sudo -n systemctl start ntp.service |
275 | exit $e |
276 | |
277 | === renamed file 'src/metadataserver/builtin_scripts/stress_ng_cpu_long.sh' => 'src/metadataserver/builtin_scripts/stress-ng-cpu-long.sh' |
278 | --- src/metadataserver/builtin_scripts/stress_ng_cpu_long.sh 2017-03-23 18:20:00 +0000 |
279 | +++ src/metadataserver/builtin_scripts/stress-ng-cpu-long.sh 2017-03-29 23:42:47 +0000 |
280 | @@ -1,6 +1,6 @@ |
281 | -#!/bin/sh -e |
282 | +#!/bin/bash -e |
283 | # |
284 | -# stress_ng_cpu_long - Run stress-ng memory tests over 12 hours. |
285 | +# stress-ng-cpu-long - Run stress-ng memory tests over 12 hours. |
286 | # |
287 | # Author: Lee Trager <lee.trager@canonical.com> |
288 | # |
289 | @@ -19,8 +19,8 @@ |
290 | # You should have received a copy of the GNU Affero General Public License |
291 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
292 | |
293 | -sudo apt-get install -q -y stress-ng |
294 | +sudo -n apt-get install -q -y stress-ng |
295 | +echo |
296 | |
297 | -sudo stress-ng \ |
298 | - --aggressive -a 0 --class cpu,cpu-cache --ignite-cpu --log-brief \ |
299 | - --metrics --times --tz --verify --timeout 12h |
300 | +sudo -n stress-ng --aggressive -a 0 --class cpu,cpu-cache --ignite-cpu \ |
301 | + --log-brief --metrics-brief --times --tz --verify --timeout 12h |
302 | |
303 | === added file 'src/metadataserver/builtin_scripts/stress-ng-cpu-short.sh' |
304 | --- src/metadataserver/builtin_scripts/stress-ng-cpu-short.sh 1970-01-01 00:00:00 +0000 |
305 | +++ src/metadataserver/builtin_scripts/stress-ng-cpu-short.sh 2017-03-29 23:42:47 +0000 |
306 | @@ -0,0 +1,32 @@ |
307 | +#!/bin/bash -e |
308 | +# |
309 | +# stress-ng-cpu-short - Stress test the CPU for 5 minutes. |
310 | +# |
311 | +# Author: Lee Trager <lee.trager@canonical.com> |
312 | +# |
313 | +# Copyright (C) 2017 Canonical |
314 | +# |
315 | +# This program is free software: you can redistribute it and/or modify |
316 | +# it under the terms of the GNU Affero General Public License as |
317 | +# published by the Free Software Foundation, either version 3 of the |
318 | +# License, or (at your option) any later version. |
319 | +# |
320 | +# This program is distributed in the hope that it will be useful, |
321 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
322 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
323 | +# GNU Affero General Public License for more details. |
324 | +# |
325 | +# You should have received a copy of the GNU Affero General Public License |
326 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
327 | + |
328 | +sudo -n apt-get install -q -y stress-ng |
329 | +echo |
330 | + |
331 | +sudo -n stress-ng --matrix 0 --ignite-cpu --log-brief --metrics-brief --times \ |
332 | + --tz --verify --timeout 2m |
333 | +echo |
334 | +sudo -n stress-ng --cache 0 --ignite-cpu --log-brief --metrics-brief --times \ |
335 | + --tz --verify --timeout 1m |
336 | +echo |
337 | +sudo -n stress-ng --cpu 0 --ignite-cpu --log-brief --metrics-brief --times --tz \ |
338 | + --verify --timeout 2m |
339 | |
340 | === renamed file 'src/metadataserver/builtin_scripts/stress_ng_memory_long.sh' => 'src/metadataserver/builtin_scripts/stress-ng-memory-long.sh' |
341 | --- src/metadataserver/builtin_scripts/stress_ng_memory_long.sh 2017-03-23 18:20:00 +0000 |
342 | +++ src/metadataserver/builtin_scripts/stress-ng-memory-long.sh 2017-03-29 23:42:47 +0000 |
343 | @@ -1,4 +1,4 @@ |
344 | -#!/bin/sh -e |
345 | +#!/bin/bash -e |
346 | # |
347 | # stress_ng_memory_long - Run stress-ng memory tests over 12 hours. |
348 | # |
349 | @@ -19,8 +19,18 @@ |
350 | # You should have received a copy of the GNU Affero General Public License |
351 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
352 | |
353 | -sudo apt-get install -q -y stress-ng |
354 | - |
355 | -sudo stress-ng \ |
356 | - --aggressive -a 0 --class memory --ignite-cpu --log-brief --metrics \ |
357 | - --times --tz --verify --timeout 12h |
358 | +sudo -n apt-get install -q -y stress-ng |
359 | +echo |
360 | + |
361 | +# Reserve 64M so the test doesn't fail due to the OOM killer. |
362 | +total_memory=$(awk '/MemAvailable/ { print ($2 - 65536) }' /proc/meminfo) |
363 | +threads=$(lscpu --all --parse | grep -v '#' | wc -l) |
364 | +memory_per_thread=$(($total_memory / $threads)) |
365 | +# stress-ng only allows 4GB of memory per thread. |
366 | +if [ $memory_per_thread -ge 4194304 ]; then |
367 | + threads=$(($total_memory / 4194304 + 1)) |
368 | + memory_per_thread=$(($total_memory / $threads)) |
369 | +fi |
370 | + |
371 | +stress-ng --vm $threads --vm-bytes ${memory_per_thread}k --page-in \ |
372 | + --log-brief --metrics-brief --times --tz --verify --timeout 12h |
373 | |
374 | === added file 'src/metadataserver/builtin_scripts/stress-ng-memory-short.sh' |
375 | --- src/metadataserver/builtin_scripts/stress-ng-memory-short.sh 1970-01-01 00:00:00 +0000 |
376 | +++ src/metadataserver/builtin_scripts/stress-ng-memory-short.sh 2017-03-29 23:42:47 +0000 |
377 | @@ -0,0 +1,36 @@ |
378 | +#!/bin/bash -e |
379 | +# |
380 | +# stress-ng-memory-short - Stress test memory for 5 minutes. |
381 | +# |
382 | +# Author: Lee Trager <lee.trager@canonical.com> |
383 | +# |
384 | +# Copyright (C) 2017 Canonical |
385 | +# |
386 | +# This program is free software: you can redistribute it and/or modify |
387 | +# it under the terms of the GNU Affero General Public License as |
388 | +# published by the Free Software Foundation, either version 3 of the |
389 | +# License, or (at your option) any later version. |
390 | +# |
391 | +# This program is distributed in the hope that it will be useful, |
392 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
393 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
394 | +# GNU Affero General Public License for more details. |
395 | +# |
396 | +# You should have received a copy of the GNU Affero General Public License |
397 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
398 | + |
399 | +sudo -n apt-get install -q -y stress-ng |
400 | +echo |
401 | + |
402 | +# Reserve 64M so the test doesn't fail due to the OOM killer. |
403 | +total_memory=$(awk '/MemAvailable/ { print ($2 - 65536) }' /proc/meminfo) |
404 | +threads=$(lscpu --all --parse | grep -v '#' | wc -l) |
405 | +memory_per_thread=$(($total_memory / $threads)) |
406 | +# stress-ng only allows 4GB of memory per thread. |
407 | +if [ $memory_per_thread -ge 4194304 ]; then |
408 | + threads=$(($total_memory / 4194304 + 1)) |
409 | + memory_per_thread=$(($total_memory / $threads)) |
410 | +fi |
411 | + |
412 | +stress-ng --vm $threads --vm-bytes ${memory_per_thread}k --page-in \ |
413 | + --log-brief --metrics-brief --times --tz --verify --timeout 5m |
414 | |
415 | === modified file 'src/metadataserver/builtin_scripts/tests/test_builtin_scripts.py' |
416 | --- src/metadataserver/builtin_scripts/tests/test_builtin_scripts.py 2017-03-23 18:20:00 +0000 |
417 | +++ src/metadataserver/builtin_scripts/tests/test_builtin_scripts.py 2017-03-29 23:42:47 +0000 |
418 | @@ -34,8 +34,7 @@ |
419 | script_in_db.script.comment) |
420 | self.assertItemsEqual(script.tags, script_in_db.tags) |
421 | self.assertEquals(script.script_type, script_in_db.script_type) |
422 | - self.assertEquals( |
423 | - timedelta(seconds=script.timeout), script_in_db.timeout) |
424 | + self.assertEquals(script.timeout, script_in_db.timeout) |
425 | self.assertEquals(script.destructive, script_in_db.destructive) |
426 | self.assertTrue(script_in_db.default) |
427 | |
428 | @@ -79,7 +78,8 @@ |
429 | |
430 | def test_update_doesnt_revert_script(self): |
431 | load_builtin_scripts() |
432 | - update_script_values = random.choice(BUILTIN_SCRIPTS) |
433 | + update_script_index = random.randint(0, len(BUILTIN_SCRIPTS) - 2) |
434 | + update_script_values = BUILTIN_SCRIPTS[update_script_index] |
435 | script = Script.objects.get(name=update_script_values.name) |
436 | # Put fake new data in to simulate another MAAS region updating |
437 | # to a newer version. |
438 | @@ -99,6 +99,14 @@ |
439 | script.timeout = user_timeout |
440 | script.save() |
441 | |
442 | + # Test that subsequent scripts still get updated |
443 | + second_update_script_values = BUILTIN_SCRIPTS[update_script_index + 1] |
444 | + second_script = Script.objects.get( |
445 | + name=second_update_script_values.name) |
446 | + # Put fake old data in to simulate updating a script. |
447 | + second_script.title = factory.make_string() |
448 | + second_script.save() |
449 | + |
450 | load_builtin_scripts() |
451 | script = reload_object(script) |
452 | |
453 | @@ -111,3 +119,7 @@ |
454 | self.assertEquals(user_tags, script.tags) |
455 | self.assertEquals(user_timeout, script.timeout) |
456 | self.assertTrue(script.default) |
457 | + |
458 | + second_script = reload_object(second_script) |
459 | + self.assertEquals( |
460 | + second_update_script_values.title, second_script.title) |
461 | |
462 | === modified file 'src/metadataserver/user_data/templates/base_user_data.sh' |
463 | --- src/metadataserver/user_data/templates/base_user_data.sh 2017-02-16 00:27:35 +0000 |
464 | +++ src/metadataserver/user_data/templates/base_user_data.sh 2017-03-29 23:42:47 +0000 |
465 | @@ -1,4 +1,4 @@ |
466 | -#!/bin/sh |
467 | +#!/bin/bash |
468 | # |
469 | # This script carries inside it multiple files. When executed, it creates |
470 | # the files into a temporary directory and uses them to execute commands |
471 | |
472 | === modified file 'src/metadataserver/user_data/templates/snippets/maas_enlist.sh' |
473 | --- src/metadataserver/user_data/templates/snippets/maas_enlist.sh 2017-03-08 10:10:12 +0000 |
474 | +++ src/metadataserver/user_data/templates/snippets/maas_enlist.sh 2017-03-29 23:42:47 +0000 |
475 | @@ -1,4 +1,4 @@ |
476 | -#!/bin/sh |
477 | +#!/bin/bash |
478 | # |
479 | # maas-enlist: MAAS Enlistment Tool |
480 | # |
481 | |
482 | === modified file 'src/metadataserver/user_data/templates/snippets/maas_run_remote_scripts.py' |
483 | --- src/metadataserver/user_data/templates/snippets/maas_run_remote_scripts.py 2017-03-03 00:50:43 +0000 |
484 | +++ src/metadataserver/user_data/templates/snippets/maas_run_remote_scripts.py 2017-03-29 23:42:47 +0000 |
485 | @@ -233,6 +233,12 @@ |
486 | fail("URL must be provided either in --url or in config\n") |
487 | url = "%s/%s/" % (url, args.apiver) |
488 | |
489 | + # Disable the OOM killer on the runner process, the OOM killer will still |
490 | + # go after any tests spawned. |
491 | + oom_score_adj_path = os.path.join( |
492 | + '/proc', str(os.getpid()), 'oom_score_adj') |
493 | + open(oom_score_adj_path, 'w').write('-1000') |
494 | + |
495 | heart_beat = HeartBeat(url, creds) |
496 | heart_beat.start() |
497 | |
498 | |
499 | === modified file 'src/provisioningserver/refresh/node_info_scripts.py' |
500 | --- src/provisioningserver/refresh/node_info_scripts.py 2017-03-29 21:13:51 +0000 |
501 | +++ src/provisioningserver/refresh/node_info_scripts.py 2017-03-29 23:42:47 +0000 |
502 | @@ -60,19 +60,19 @@ |
503 | |
504 | # Built-in script to run lshw. |
505 | LSHW_SCRIPT = dedent("""\ |
506 | - #!/bin/sh |
507 | + #!/bin/bash |
508 | sudo -n /usr/bin/lshw -xml |
509 | """) |
510 | |
511 | # Built-in script to run `ip addr` |
512 | IPADDR_SCRIPT = dedent("""\ |
513 | - #!/bin/sh |
514 | + #!/bin/bash |
515 | ip addr |
516 | """) |
517 | |
518 | # Built-in script to detect virtual instances. |
519 | VIRTUALITY_SCRIPT = dedent("""\ |
520 | - #!/bin/sh |
521 | + #!/bin/bash |
522 | # In Bourne Shell `type -p` does not work; `which` is closest. |
523 | if which systemd-detect-virt > /dev/null; then |
524 | # systemd-detect-virt prints "none" and returns nonzero if |
525 | @@ -90,7 +90,7 @@ |
526 | """) |
527 | |
528 | CPUINFO_SCRIPT = dedent("""\ |
529 | - #!/bin/sh |
530 | + #!/bin/bash |
531 | # Gather the standard output as it has some extra info |
532 | lscpu |
533 | # Gather the machine readable output for processing |
534 | @@ -108,7 +108,7 @@ |
535 | """) |
536 | |
537 | SRIOV_SCRIPT = dedent("""\ |
538 | - #!/bin/sh |
539 | + #!/bin/bash |
540 | for file in $(find /sys/devices/ -name sriov_numvfs); do |
541 | dir=$(dirname "$file") |
542 | for eth in $(ls "$dir/net/"); do |
543 | @@ -388,7 +388,7 @@ |
544 | |
545 | LIST_MODALIASES_OUTPUT_NAME = '00-maas-04-list-modaliases' |
546 | LIST_MODALIASES_SCRIPT = dedent("""\ |
547 | - #!/bin/sh |
548 | + #!/bin/bash |
549 | find /sys -name modalias -print0 | xargs -0 cat | sort -u |
550 | """) |
551 | |
552 | |
553 | === modified file 'src/provisioningserver/refresh/tests/test_node_info_scripts.py' |
554 | --- src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-03-23 18:20:00 +0000 |
555 | +++ src/provisioningserver/refresh/tests/test_node_info_scripts.py 2017-03-29 23:42:47 +0000 |
556 | @@ -944,7 +944,7 @@ |
557 | self.sysdv.unlink() |
558 | sysdv_name = factory.make_name("virt") |
559 | with self.sysdv.open("w") as fd: |
560 | - fd.write("#!/bin/sh\n") |
561 | + fd.write("#!/bin/bash\n") |
562 | fd.write("echo %s\n" % sysdv_name) |
563 | fd.write("exit 1\n") |
564 | self.sysdv.chmod(0o700) |
565 | |
566 | === modified file 'src/provisioningserver/refresh/tests/test_refresh.py' |
567 | --- src/provisioningserver/refresh/tests/test_refresh.py 2017-03-03 00:50:43 +0000 |
568 | +++ src/provisioningserver/refresh/tests/test_refresh.py 2017-03-29 23:42:47 +0000 |
569 | @@ -137,7 +137,7 @@ |
570 | if script_name is None: |
571 | script_name = factory.make_name('script_name') |
572 | TEST_SCRIPT = dedent("""\ |
573 | - #!/bin/sh |
574 | + #!/bin/bash |
575 | echo 'test script' |
576 | """) |
577 | refresh.NODE_INFO_SCRIPTS = OrderedDict([ |
578 | @@ -151,7 +151,7 @@ |
579 | if script_name is None: |
580 | script_name = factory.make_name('script_name') |
581 | TEST_SCRIPT = dedent("""\ |
582 | - #!/bin/sh |
583 | + #!/bin/bash |
584 | echo 'test failed' |
585 | exit 1 |
586 | """) |
587 | |
588 | === modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py' |
589 | --- src/provisioningserver/rpc/tests/test_clusterservice.py 2017-03-27 14:35:23 +0000 |
590 | +++ src/provisioningserver/rpc/tests/test_clusterservice.py 2017-03-29 23:42:47 +0000 |
591 | @@ -2479,7 +2479,7 @@ |
592 | @inlineCallbacks |
593 | def test_spawnProcessAndNullifyStdout_nullifies_stdout(self): |
594 | done, protocol = makeDeferredWithProcessProtocol() |
595 | - args = [b"/bin/sh", b'-c', b"echo foo"] |
596 | + args = [b"/bin/bash", b'-c', b"echo foo"] |
597 | outReceived = Mock() |
598 | protocol.outReceived = outReceived |
599 | spawnProcessAndNullifyStdout(protocol, args) |
600 | @@ -2489,7 +2489,7 @@ |
601 | @inlineCallbacks |
602 | def test_spawnProcessAndNullifyStdout_captures_stderr(self): |
603 | done, protocol = makeDeferredWithProcessProtocol() |
604 | - args = [b"/bin/sh", b'-c', b"echo foo >&2"] |
605 | + args = [b"/bin/bash", b'-c', b"echo foo >&2"] |
606 | errReceived = Mock() |
607 | protocol.errReceived = errReceived |
608 | spawnProcessAndNullifyStdout(protocol, args) |
609 | @@ -2500,7 +2500,7 @@ |
610 | def test_executeScanNetworksSubprocess(self): |
611 | mock_scan_args = self.patch( |
612 | clusterservice, 'get_scan_all_networks_args') |
613 | - mock_scan_args.return_value = [b"/bin/sh", b'-c', b"echo -n foo >&2"] |
614 | + mock_scan_args.return_value = [b"/bin/bash", b'-c', b"echo -n foo >&2"] |
615 | mock_log_msg = self.patch(clusterservice.log, 'msg') |
616 | d = executeScanNetworksSubprocess() |
617 | yield d |
I haven't reviewed the rest of this branch, but I'd like to suggest a policy: all shell scripts should be run with bash. Bash is fairly unpleasant for anything non-trivial, but /bin/sh in all its forms is hostile to sanity and happiness. Shell scripts are a blight, but if we must write them then let's at least stick to the least insane of the ubiquitous ones.