Merge lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv into lp:~landscape/landscape-client/trunk
- fix-test-race-sys-argv
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Eric Snow | ||||
Approved revision: | 997 | ||||
Merged at revision: | 1002 | ||||
Proposed branch: | lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv | ||||
Merge into: | lp:~landscape/landscape-client/trunk | ||||
Diff against target: |
1291 lines (+304/-257) 20 files modified
landscape/deployment.py (+16/-0) landscape/lib/bpickle.py (+0/-1) landscape/lib/tests/test_process.py (+2/-1) landscape/manager/aptsources.py (+1/-1) landscape/manager/packagemanager.py (+4/-5) landscape/manager/tests/test_aptsources.py (+2/-2) landscape/manager/tests/test_packagemanager.py (+40/-38) landscape/monitor/packagemonitor.py (+4/-1) landscape/monitor/tests/test_packagemonitor.py (+20/-34) landscape/monitor/tests/test_processorinfo.py (+3/-3) landscape/package/changer.py (+12/-10) landscape/package/releaseupgrader.py (+7/-11) landscape/package/reporter.py (+4/-4) landscape/package/tests/test_changer.py (+35/-40) landscape/package/tests/test_releaseupgrader.py (+15/-23) landscape/package/tests/test_reporter.py (+13/-14) landscape/tests/helpers.py (+12/-0) landscape/tests/test_deployment.py (+37/-1) landscape/tests/test_watchdog.py (+73/-66) landscape/watchdog.py (+4/-2) |
||||
To merge this branch: | bzr merge lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
🤖 Landscape Builder | test results | Approve | |
Free Ekanayaka (community) | Approve | ||
Simon Poirier (community) | Approve | ||
Review via email:
|
Commit message
his patch fixes a race condition in tests involving sys.argv.
Under certain load conditions there is a collision on patched-out
sys.argv. To resolve this, we switch to using the config to store the
bindir that should be used (rather than extrapolating from sys.argv[0]).
Description of the change
This patch fixes a race condition in tests involving sys.argv.
Under certain load conditions there is a collision on patched-out
sys.argv. To resolve this, we switch to using the config to store the
bindir that should be used (rather than extrapolating from sys.argv[0]).
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: make ci-check
Result: Success
Revno: 992
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: make ci-check
Result: Success
Revno: 993
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Simon Poirier (simpoir) wrote : | # |
+1 looks good. few nitpicks.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Eric Snow (ericsnowcurrently) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: make ci-check
Result: Success
Revno: 996
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Attempt to merge into lp:landscape-client failed due to conflicts:
text conflict in landscape/
text conflict in landscape/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: make ci-check
Result: Success
Revno: 997
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Landscape Builder (landscape-builder) wrote : | # |
Command: make ci-check
Result: Success
Revno: 997
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/
Preview Diff
1 | === modified file 'landscape/deployment.py' |
2 | --- landscape/deployment.py 2017-01-09 16:38:21 +0000 |
3 | +++ landscape/deployment.py 2017-04-05 14:19:44 +0000 |
4 | @@ -1,4 +1,5 @@ |
5 | import os |
6 | +import os.path |
7 | import sys |
8 | |
9 | from configobj import ConfigObj, ConfigObjError |
10 | @@ -432,3 +433,18 @@ |
11 | upgrade_manager.initialize(persist) |
12 | persist.save(service.persist_filename) |
13 | return persist |
14 | + |
15 | + |
16 | +def get_bindir(config=None): |
17 | + """Return the directory path where the client binaries are. |
18 | + |
19 | + If the config is None, it doesn't have a "bindir" attribute, or its |
20 | + value is None, then sys.argv[0] is returned. |
21 | + """ |
22 | + try: |
23 | + bindir = config.bindir |
24 | + except AttributeError: # ...also the result if config is None. |
25 | + bindir = None |
26 | + if bindir is None: |
27 | + bindir = os.path.dirname(os.path.abspath(sys.argv[0])) |
28 | + return bindir |
29 | |
30 | === modified file 'landscape/lib/bpickle.py' |
31 | --- landscape/lib/bpickle.py 2017-04-03 08:15:02 +0000 |
32 | +++ landscape/lib/bpickle.py 2017-04-05 14:19:44 +0000 |
33 | @@ -210,4 +210,3 @@ |
34 | dumps_table.update({ |
35 | str: dumps_unicode, |
36 | }) |
37 | - |
38 | |
39 | === modified file 'landscape/lib/tests/test_process.py' |
40 | --- landscape/lib/tests/test_process.py 2017-03-29 09:15:01 +0000 |
41 | +++ landscape/lib/tests/test_process.py 2017-04-05 14:19:44 +0000 |
42 | @@ -43,7 +43,8 @@ |
43 | @mock.patch("landscape.lib.process.detect_jiffies", return_value=1) |
44 | @mock.patch("os.listdir") |
45 | @mock.patch("landscape.monitor.computeruptime.get_uptime") |
46 | - def test_missing_process_race(self, get_uptime_mock, list_dir_mock, jiffies_mock): |
47 | + def test_missing_process_race(self, get_uptime_mock, list_dir_mock, |
48 | + jiffies_mock): |
49 | """ |
50 | We use os.listdir("/proc") to get the list of active processes, if a |
51 | process ends before we attempt to read the process' information, then |
52 | |
53 | === modified file 'landscape/manager/aptsources.py' |
54 | --- landscape/manager/aptsources.py 2017-03-28 14:09:52 +0000 |
55 | +++ landscape/manager/aptsources.py 2017-04-05 14:19:44 +0000 |
56 | @@ -135,7 +135,7 @@ |
57 | |
58 | def _run_reporter(self): |
59 | """Once the repositories are modified, trigger a reporter run.""" |
60 | - reporter = find_reporter_command() |
61 | + reporter = find_reporter_command(self.registry.config) |
62 | |
63 | # Force an apt-update run, because the sources.list has changed |
64 | args = ["--force-apt-update"] |
65 | |
66 | === modified file 'landscape/manager/packagemanager.py' |
67 | --- landscape/manager/packagemanager.py 2017-04-04 08:50:05 +0000 |
68 | +++ landscape/manager/packagemanager.py 2017-04-05 14:19:44 +0000 |
69 | @@ -69,13 +69,12 @@ |
70 | if self.config.config: |
71 | args.extend(["-c", self.config.config]) |
72 | if self._package_store.get_next_task(cls.queue_name): |
73 | + command = cls.find_command(self.config) |
74 | + environ = encode_values(os.environ) |
75 | # path is set to None so that getProcessOutput does not |
76 | # chdir to "." see bug #211373 |
77 | - environ = encode_values(os.environ) |
78 | - result = getProcessOutput(cls.find_command(), |
79 | - args=args, env=environ, |
80 | - errortoo=1, |
81 | - path=None) |
82 | + result = getProcessOutput( |
83 | + command, args=args, env=environ, errortoo=1, path=None) |
84 | result.addCallback(self._got_output, cls) |
85 | else: |
86 | result = succeed(None) |
87 | |
88 | === modified file 'landscape/manager/tests/test_aptsources.py' |
89 | --- landscape/manager/tests/test_aptsources.py 2017-04-05 07:25:48 +0000 |
90 | +++ landscape/manager/tests/test_aptsources.py 2017-04-05 14:19:44 +0000 |
91 | @@ -3,7 +3,6 @@ |
92 | import mock |
93 | |
94 | from twisted.internet.defer import Deferred, succeed |
95 | -from twisted.python.compat import _PY3 |
96 | |
97 | from landscape.manager.aptsources import AptSources |
98 | from landscape.manager.plugin import SUCCEEDED, FAILED |
99 | @@ -469,7 +468,8 @@ |
100 | deferred = Deferred() |
101 | |
102 | def _run_process(command, args, env={}, path=None, uid=None, gid=None): |
103 | - self.assertEqual(find_reporter_command(), command) |
104 | + self.assertEqual( |
105 | + find_reporter_command(self.manager.config), command) |
106 | self.assertEqual(["--force-apt-update", "--config=%s" % |
107 | self.manager.config.config], args) |
108 | deferred.callback(("ok", "", 0)) |
109 | |
110 | === modified file 'landscape/manager/tests/test_packagemanager.py' |
111 | --- landscape/manager/tests/test_packagemanager.py 2017-01-09 14:29:54 +0000 |
112 | +++ landscape/manager/tests/test_packagemanager.py 2017-04-05 14:19:44 +0000 |
113 | @@ -1,5 +1,6 @@ |
114 | import mock |
115 | import os |
116 | +import os.path |
117 | |
118 | from twisted.internet.defer import Deferred |
119 | |
120 | @@ -20,6 +21,7 @@ |
121 | def setUp(self): |
122 | """Initialize test helpers and create a sample package store.""" |
123 | super(PackageManagerTest, self).setUp() |
124 | + self.config = self.broker_service.config |
125 | self.package_store = PackageStore(os.path.join(self.data_path, |
126 | "package/database")) |
127 | self.package_manager = PackageManager() |
128 | @@ -29,8 +31,7 @@ |
129 | If the package sqlite database file doesn't exist yet, it is created |
130 | upon message handling. |
131 | """ |
132 | - filename = os.path.join(self.broker_service.config.data_path, |
133 | - "package/database") |
134 | + filename = os.path.join(self.config.data_path, "package/database") |
135 | os.unlink(filename) |
136 | self.assertFalse(os.path.isfile(filename)) |
137 | |
138 | @@ -179,21 +180,21 @@ |
139 | self.package_manager.spawn_handler.assert_called_once_with( |
140 | ReleaseUpgrader) |
141 | |
142 | - @mock.patch("landscape.package.changer.find_changer_command") |
143 | - def test_spawn_changer(self, find_command_mock): |
144 | + def test_spawn_changer(self): |
145 | """ |
146 | The L{PackageManager.spawn_handler} method executes the correct command |
147 | when passed the L{PackageChanger} class as argument. |
148 | """ |
149 | - command = self.makeFile("#!/bin/sh\necho 'I am the changer!' >&2\n") |
150 | - os.chmod(command, 0o755) |
151 | - find_command_mock.return_value = command |
152 | + command = self.write_script( |
153 | + self.config, |
154 | + "landscape-package-changer", |
155 | + "#!/bin/sh\necho 'I am the changer!' >&2\n") |
156 | + self.manager.config = self.config |
157 | |
158 | self.package_store.add_task("changer", "Do something!") |
159 | |
160 | self.manager.add(self.package_manager) |
161 | result = self.package_manager.spawn_handler(PackageChanger) |
162 | - find_command_mock.assert_called_once_with() |
163 | |
164 | def got_result(result): |
165 | log = self.logfile.getvalue() |
166 | @@ -202,21 +203,20 @@ |
167 | |
168 | return result.addCallback(got_result) |
169 | |
170 | - @mock.patch( |
171 | - "landscape.package.releaseupgrader.find_release_upgrader_command") |
172 | - def test_spawn_release_upgrader(self, find_command_mock): |
173 | + def test_spawn_release_upgrader(self): |
174 | """ |
175 | The L{PackageManager.spawn_handler} method executes the correct command |
176 | when passed the L{ReleaseUpgrader} class as argument. |
177 | """ |
178 | - command = self.makeFile("#!/bin/sh\necho 'I am the upgrader!' >&2\n") |
179 | - os.chmod(command, 0o755) |
180 | - find_command_mock.return_value = command |
181 | + command = self.write_script( |
182 | + self.config, |
183 | + "landscape-release-upgrader", |
184 | + "#!/bin/sh\necho 'I am the upgrader!' >&2\n") |
185 | + self.manager.config = self.config |
186 | |
187 | self.package_store.add_task("release-upgrader", "Do something!") |
188 | self.manager.add(self.package_manager) |
189 | result = self.package_manager.spawn_handler(ReleaseUpgrader) |
190 | - find_command_mock.assert_called_once_with() |
191 | |
192 | def got_result(result): |
193 | log = self.logfile.getvalue() |
194 | @@ -225,15 +225,17 @@ |
195 | |
196 | return result.addCallback(got_result) |
197 | |
198 | - @mock.patch("landscape.package.changer.find_changer_command") |
199 | - def test_spawn_handler_without_output(self, find_command_mock): |
200 | - find_command_mock.return_value = "/bin/true" |
201 | + def test_spawn_handler_without_output(self): |
202 | + self.write_script( |
203 | + self.config, |
204 | + "landscape-package-changer", |
205 | + "#!/bin/sh\n/bin/true") |
206 | + self.manager.config = self.config |
207 | |
208 | self.package_store.add_task("changer", "Do something!") |
209 | |
210 | self.manager.add(self.package_manager) |
211 | result = self.package_manager.spawn_handler(PackageChanger) |
212 | - find_command_mock.assert_called_once_with() |
213 | |
214 | def got_result(result): |
215 | log = self.logfile.getvalue() |
216 | @@ -241,18 +243,18 @@ |
217 | |
218 | return result.addCallback(got_result) |
219 | |
220 | - @mock.patch("landscape.package.changer.find_changer_command") |
221 | - def test_spawn_handler_copies_environment(self, find_command_mock): |
222 | - command = self.makeFile("#!/bin/sh\necho VAR: $VAR\n") |
223 | - os.chmod(command, 0o755) |
224 | - find_command_mock.return_value = command |
225 | + def test_spawn_handler_copies_environment(self): |
226 | + command = self.write_script( |
227 | + self.config, |
228 | + "landscape-package-changer", |
229 | + "#!/bin/sh\necho VAR: $VAR\n") |
230 | + self.manager.config = self.config |
231 | |
232 | self.manager.add(self.package_manager) |
233 | self.package_store.add_task("changer", "Do something!") |
234 | |
235 | os.environ["VAR"] = "HI!" |
236 | result = self.package_manager.spawn_handler(PackageChanger) |
237 | - find_command_mock.assert_called_once_with() |
238 | |
239 | def got_result(result): |
240 | log = self.logfile.getvalue() |
241 | @@ -261,16 +263,16 @@ |
242 | |
243 | return result.addCallback(got_result) |
244 | |
245 | - @mock.patch("landscape.package.changer.find_changer_command") |
246 | - def test_spawn_handler_passes_quiet_option(self, find_command_mock): |
247 | - command = self.makeFile("#!/bin/sh\necho OPTIONS: $@\n") |
248 | - os.chmod(command, 0o755) |
249 | - find_command_mock.return_value = command |
250 | + def test_spawn_handler_passes_quiet_option(self): |
251 | + command = self.write_script( |
252 | + self.config, |
253 | + "landscape-package-changer", |
254 | + "#!/bin/sh\necho OPTIONS: $@\n") |
255 | + self.manager.config = self.config |
256 | |
257 | self.manager.add(self.package_manager) |
258 | self.package_store.add_task("changer", "Do something!") |
259 | result = self.package_manager.spawn_handler(PackageChanger) |
260 | - find_command_mock.assert_called_once_with() |
261 | |
262 | def got_result(result): |
263 | log = self.logfile.getvalue() |
264 | @@ -292,22 +294,22 @@ |
265 | |
266 | return result.addCallback(got_result) |
267 | |
268 | - @mock.patch("landscape.package.changer.find_changer_command") |
269 | - def test_spawn_handler_doesnt_chdir(self, find_command_mock): |
270 | - command = self.makeFile("#!/bin/sh\necho RUN\n") |
271 | - os.chmod(command, 0o755) |
272 | + def test_spawn_handler_doesnt_chdir(self): |
273 | + self.write_script( |
274 | + self.config, |
275 | + "landscape-package-changer", |
276 | + "#!/bin/sh\necho RUN\n") |
277 | + self.manager.config = self.config |
278 | + |
279 | cwd = os.getcwd() |
280 | self.addCleanup(os.chdir, cwd) |
281 | dir = self.makeDir() |
282 | os.chdir(dir) |
283 | os.chmod(dir, 0) |
284 | |
285 | - find_command_mock.return_value = command |
286 | - |
287 | self.manager.add(self.package_manager) |
288 | self.package_store.add_task("changer", "Do something!") |
289 | result = self.package_manager.spawn_handler(PackageChanger) |
290 | - find_command_mock.assert_called_once_with() |
291 | |
292 | def got_result(result): |
293 | log = self.logfile.getvalue() |
294 | |
295 | === modified file 'landscape/monitor/packagemonitor.py' |
296 | --- landscape/monitor/packagemonitor.py 2017-04-04 08:50:05 +0000 |
297 | +++ landscape/monitor/packagemonitor.py 2017-04-05 14:19:44 +0000 |
298 | @@ -14,13 +14,14 @@ |
299 | run_interval = 1800 |
300 | scope = "package" |
301 | |
302 | + _reporter_command = None |
303 | + |
304 | def __init__(self, package_store_filename=None): |
305 | super(PackageMonitor, self).__init__() |
306 | if package_store_filename: |
307 | self._package_store = PackageStore(package_store_filename) |
308 | else: |
309 | self._package_store = None |
310 | - self._reporter_command = find_reporter_command() |
311 | |
312 | def register(self, registry): |
313 | self.config = registry.config |
314 | @@ -117,6 +118,8 @@ |
315 | else: |
316 | env["FAKE_GLOBAL_PACKAGE_STORE"] = "1" |
317 | |
318 | + if self._reporter_command is None: |
319 | + self._reporter_command = find_reporter_command(self.config) |
320 | # path is set to None so that getProcessOutput does not |
321 | # chdir to "." see bug #211373 |
322 | env = encode_values(env) |
323 | |
324 | === modified file 'landscape/monitor/tests/test_packagemonitor.py' |
325 | --- landscape/monitor/tests/test_packagemonitor.py 2017-03-30 07:57:04 +0000 |
326 | +++ landscape/monitor/tests/test_packagemonitor.py 2017-04-05 14:19:44 +0000 |
327 | @@ -129,12 +129,10 @@ |
328 | self.assertEqual(task.data, message) |
329 | |
330 | def test_spawn_reporter(self): |
331 | - command = self.makeFile("#!/bin/sh\necho 'I am the reporter!' >&2\n") |
332 | - os.chmod(command, 0o755) |
333 | - find_command_mock_patcher = mock.patch( |
334 | - "landscape.monitor.packagemonitor.find_reporter_command", |
335 | - return_value=command) |
336 | - find_command_mock_patcher.start() |
337 | + command = self.write_script( |
338 | + self.config, |
339 | + "landscape-package-reporter", |
340 | + "#!/bin/sh\necho 'I am the reporter!' >&2\n") |
341 | |
342 | package_monitor = PackageMonitor(self.package_store_filename) |
343 | self.monitor.add(package_monitor) |
344 | @@ -144,15 +142,14 @@ |
345 | log = self.logfile.getvalue() |
346 | self.assertIn("I am the reporter!", log) |
347 | self.assertNotIn(command, log) |
348 | - find_command_mock_patcher.stop() |
349 | |
350 | return result.addCallback(got_result) |
351 | |
352 | def test_spawn_reporter_without_output(self): |
353 | - find_command_mock_patcher = mock.patch( |
354 | - "landscape.monitor.packagemonitor.find_reporter_command", |
355 | - return_value="/bin/true") |
356 | - find_command_mock_patcher.start() |
357 | + self.write_script( |
358 | + self.config, |
359 | + "landscape-package-reporter", |
360 | + "#!/bin/sh\n/bin/true") |
361 | |
362 | package_monitor = PackageMonitor(self.package_store_filename) |
363 | self.monitor.add(package_monitor) |
364 | @@ -161,17 +158,14 @@ |
365 | def got_result(result): |
366 | log = self.logfile.getvalue() |
367 | self.assertNotIn("reporter output", log) |
368 | - find_command_mock_patcher.stop() |
369 | |
370 | return result.addCallback(got_result) |
371 | |
372 | def test_spawn_reporter_copies_environment(self): |
373 | - command = self.makeFile("#!/bin/sh\necho VAR: $VAR\n") |
374 | - os.chmod(command, 0o755) |
375 | - find_command_mock_patcher = mock.patch( |
376 | - "landscape.monitor.packagemonitor.find_reporter_command", |
377 | - return_value=command) |
378 | - find_command_mock_patcher.start() |
379 | + command = self.write_script( |
380 | + self.config, |
381 | + "landscape-package-reporter", |
382 | + "#!/bin/sh\necho VAR: $VAR\n") |
383 | |
384 | package_monitor = PackageMonitor(self.package_store_filename) |
385 | self.monitor.add(package_monitor) |
386 | @@ -184,17 +178,14 @@ |
387 | log = self.logfile.getvalue() |
388 | self.assertIn("VAR: HI!", log) |
389 | self.assertNotIn(command, log) |
390 | - find_command_mock_patcher.stop() |
391 | |
392 | return result.addCallback(got_result) |
393 | |
394 | def test_spawn_reporter_passes_quiet_option(self): |
395 | - command = self.makeFile("#!/bin/sh\necho OPTIONS: $@\n") |
396 | - os.chmod(command, 0o755) |
397 | - find_command_mock_patcher = mock.patch( |
398 | - "landscape.monitor.packagemonitor.find_reporter_command", |
399 | - return_value=command) |
400 | - find_command_mock_patcher.start() |
401 | + command = self.write_script( |
402 | + self.config, |
403 | + "landscape-package-reporter", |
404 | + "#!/bin/sh\necho OPTIONS: $@\n") |
405 | |
406 | package_monitor = PackageMonitor(self.package_store_filename) |
407 | self.monitor.add(package_monitor) |
408 | @@ -205,7 +196,6 @@ |
409 | log = self.logfile.getvalue() |
410 | self.assertIn("OPTIONS: --quiet", log) |
411 | self.assertNotIn(command, log) |
412 | - find_command_mock_patcher.stop() |
413 | |
414 | return result.addCallback(got_result) |
415 | |
416 | @@ -276,19 +266,16 @@ |
417 | self.assertSingleReporterTask(task.data, task.id) |
418 | |
419 | def test_spawn_reporter_doesnt_chdir(self): |
420 | - command = self.makeFile("#!/bin/sh\necho RUN\n") |
421 | - os.chmod(command, 0o755) |
422 | + self.write_script( |
423 | + self.config, |
424 | + "landscape-package-reporter", |
425 | + "#!/bin/sh\necho RUN\n") |
426 | cwd = os.getcwd() |
427 | self.addCleanup(os.chdir, cwd) |
428 | dir = self.makeDir() |
429 | os.chdir(dir) |
430 | os.chmod(dir, 0) |
431 | |
432 | - find_command_mock_patcher = mock.patch( |
433 | - "landscape.monitor.packagemonitor.find_reporter_command", |
434 | - return_value=command) |
435 | - find_command_mock_patcher.start() |
436 | - |
437 | package_monitor = PackageMonitor(self.package_store_filename) |
438 | self.monitor.add(package_monitor) |
439 | |
440 | @@ -299,7 +286,6 @@ |
441 | self.assertIn("RUN", log) |
442 | # restore permissions to the dir so tearDown can clean it up |
443 | os.chmod(dir, 0o766) |
444 | - find_command_mock_patcher.stop() |
445 | |
446 | return result.addCallback(got_result) |
447 | |
448 | |
449 | === modified file 'landscape/monitor/tests/test_processorinfo.py' |
450 | --- landscape/monitor/tests/test_processorinfo.py 2017-03-30 08:53:45 +0000 |
451 | +++ landscape/monitor/tests/test_processorinfo.py 2017-04-05 14:19:44 +0000 |
452 | @@ -389,7 +389,7 @@ |
453 | processor 1: version = FF, identification = 018F67, machine = 2964 |
454 | processor 2: version = FF, identification = 018F67, machine = 2964 |
455 | processor 3: version = FF, identification = 018F67, machine = 2964 |
456 | -""" # noqa |
457 | +""" # noqa |
458 | |
459 | def test_read_sample_s390x_data(self): |
460 | """Ensure the plugin can parse /proc/cpuinfo from an IBM zSeries machine.""" |
461 | @@ -455,7 +455,7 @@ |
462 | address sizes : 40 bits physical, 48 bits virtual |
463 | power management: ts fid vid ttp |
464 | |
465 | -""" |
466 | +""" # noqa |
467 | |
468 | UP_PENTIUM_M = """ |
469 | processor : 0 |
470 | @@ -477,7 +477,7 @@ |
471 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx est tm2 |
472 | bogomips : 1198.25 |
473 | |
474 | -""" |
475 | +""" # noqa |
476 | |
477 | def setUp(self): |
478 | LandscapeTest.setUp(self) |
479 | |
480 | === modified file 'landscape/package/changer.py' |
481 | --- landscape/package/changer.py 2017-03-13 15:15:46 +0000 |
482 | +++ landscape/package/changer.py 2017-04-05 14:19:44 +0000 |
483 | @@ -1,7 +1,6 @@ |
484 | import logging |
485 | import base64 |
486 | import time |
487 | -import sys |
488 | import os |
489 | import pwd |
490 | import grp |
491 | @@ -14,6 +13,7 @@ |
492 | POLICY_STRICT, POLICY_ALLOW_INSTALLS, POLICY_ALLOW_ALL_CHANGES, |
493 | UNKNOWN_PACKAGE_DATA_TIMEOUT) |
494 | |
495 | +from landscape.deployment import get_bindir |
496 | from landscape.lib.fs import create_binary_file |
497 | from landscape.lib.log import log_failure |
498 | from landscape.package.reporter import find_reporter_command |
499 | @@ -101,7 +101,7 @@ |
500 | if os.getuid() == 0: |
501 | os.setgid(grp.getgrnam("landscape").gr_gid) |
502 | os.setuid(pwd.getpwnam("landscape").pw_uid) |
503 | - command = find_reporter_command() |
504 | + command = find_reporter_command(self._config) |
505 | if self._config.config is not None: |
506 | command += " -c %s" % self._config.config |
507 | os.system(command) |
508 | @@ -374,14 +374,16 @@ |
509 | "result-code": 1} |
510 | return self._broker.send_message(response, self._session_id, True) |
511 | |
512 | - @staticmethod |
513 | - def find_command(): |
514 | - return find_changer_command() |
515 | - |
516 | - |
517 | -def find_changer_command(): |
518 | - dirname = os.path.dirname(os.path.abspath(sys.argv[0])) |
519 | - return os.path.join(dirname, "landscape-package-changer") |
520 | + @classmethod |
521 | + def find_command(cls, config=None): |
522 | + """Return the path to the package-changer script. |
523 | + |
524 | + The script's directory is derived from the provided config. |
525 | + If that is None or doesn't have a "bindir" then directory of |
526 | + sys.argv[0] is returned. |
527 | + """ |
528 | + bindir = get_bindir(config) |
529 | + return os.path.join(bindir, "landscape-package-changer") |
530 | |
531 | |
532 | def main(args): |
533 | |
534 | === modified file 'landscape/package/releaseupgrader.py' |
535 | --- landscape/package/releaseupgrader.py 2017-03-22 09:29:17 +0000 |
536 | +++ landscape/package/releaseupgrader.py 2017-04-05 14:19:44 +0000 |
537 | @@ -4,11 +4,11 @@ |
538 | import os |
539 | import pwd |
540 | import shutil |
541 | -import sys |
542 | import tarfile |
543 | |
544 | from twisted.internet.defer import succeed |
545 | |
546 | +from landscape.deployment import get_bindir |
547 | from landscape.lib.fetch import url_to_filename, fetch_to_files |
548 | from landscape.lib.lsb_release import parse_lsb_release, LSB_RELEASE_FILENAME |
549 | from landscape.lib.gpg import gpg_verify |
550 | @@ -252,7 +252,7 @@ |
551 | uid = None |
552 | gid = None |
553 | |
554 | - reporter = find_reporter_command() |
555 | + reporter = find_reporter_command(self._config) |
556 | |
557 | # Force an apt-update run, because the sources.list has changed |
558 | args = ["--force-apt-update"] |
559 | @@ -274,9 +274,11 @@ |
560 | |
561 | return self._send_message(message) |
562 | |
563 | - @staticmethod |
564 | - def find_command(): |
565 | - return find_release_upgrader_command() |
566 | + @classmethod |
567 | + def find_command(cls, config=None): |
568 | + """Return the path to the landscape-release-upgrader script.""" |
569 | + bindir = get_bindir(config) |
570 | + return os.path.join(bindir, "landscape-release-upgrader") |
571 | |
572 | def _send_message(self, message): |
573 | """Acquire a session ID and send the given message.""" |
574 | @@ -289,12 +291,6 @@ |
575 | return deferred |
576 | |
577 | |
578 | -def find_release_upgrader_command(): |
579 | - """Return the path to the landscape-release-upgrader script.""" |
580 | - dirname = os.path.dirname(os.path.abspath(sys.argv[0])) |
581 | - return os.path.join(dirname, "landscape-release-upgrader") |
582 | - |
583 | - |
584 | def main(args): |
585 | if os.getpgrp() != os.getpid(): |
586 | os.setsid() |
587 | |
588 | === modified file 'landscape/package/reporter.py' |
589 | --- landscape/package/reporter.py 2017-03-21 17:00:34 +0000 |
590 | +++ landscape/package/reporter.py 2017-04-05 14:19:44 +0000 |
591 | @@ -5,7 +5,6 @@ |
592 | |
593 | import logging |
594 | import time |
595 | -import sys |
596 | import os |
597 | import glob |
598 | import apt_pkg |
599 | @@ -13,6 +12,7 @@ |
600 | from twisted.internet.defer import ( |
601 | Deferred, succeed, inlineCallbacks, returnValue) |
602 | |
603 | +from landscape.deployment import get_bindir |
604 | from landscape.lib import bpickle |
605 | from landscape.lib.sequenceranges import sequence_to_ranges |
606 | from landscape.lib.twisted_util import gather_results, spawn_process |
607 | @@ -751,6 +751,6 @@ |
608 | return run_task_handler(PackageReporter, args) |
609 | |
610 | |
611 | -def find_reporter_command(): |
612 | - dirname = os.path.dirname(os.path.abspath(sys.argv[0])) |
613 | - return os.path.join(dirname, "landscape-package-reporter") |
614 | +def find_reporter_command(config=None): |
615 | + bindir = get_bindir(config) |
616 | + return os.path.join(bindir, "landscape-package-reporter") |
617 | |
618 | === modified file 'landscape/package/tests/test_changer.py' |
619 | --- landscape/package/tests/test_changer.py 2017-03-21 18:03:57 +0000 |
620 | +++ landscape/package/tests/test_changer.py 2017-04-05 14:19:44 +0000 |
621 | @@ -12,7 +12,7 @@ |
622 | |
623 | from landscape.lib.fs import create_text_file, read_text_file, touch_file |
624 | from landscape.package.changer import ( |
625 | - PackageChanger, main, find_changer_command, UNKNOWN_PACKAGE_DATA_TIMEOUT, |
626 | + PackageChanger, main, UNKNOWN_PACKAGE_DATA_TIMEOUT, |
627 | SUCCESS_RESULT, DEPENDENCY_ERROR_RESULT, POLICY_ALLOW_INSTALLS, |
628 | POLICY_ALLOW_ALL_CHANGES, ERROR_RESULT) |
629 | from landscape.package.store import PackageStore |
630 | @@ -662,15 +662,14 @@ |
631 | |
632 | @patch("os.system") |
633 | def test_spawn_reporter_after_running(self, system_mock): |
634 | - with patch("landscape.package.changer.find_reporter_command", |
635 | - return_value="/fake/bin/landscape-package-reporter"): |
636 | - # Add a task that will do nothing besides producing an |
637 | - # answer. The reporter is only spawned if at least one |
638 | - # task was handled. |
639 | - self.store.add_task("changer", {"type": "change-packages", |
640 | - "operation-id": 123}) |
641 | + self.config.bindir = "/fake/bin" |
642 | + # Add a task that will do nothing besides producing an |
643 | + # answer. The reporter is only spawned if at least one |
644 | + # task was handled. |
645 | + self.store.add_task("changer", {"type": "change-packages", |
646 | + "operation-id": 123}) |
647 | |
648 | - self.successResultOf(self.changer.run()) |
649 | + self.successResultOf(self.changer.run()) |
650 | |
651 | system_mock.assert_called_once_with( |
652 | "/fake/bin/landscape-package-reporter") |
653 | @@ -679,15 +678,14 @@ |
654 | def test_spawn_reporter_after_running_with_config(self, system_mock): |
655 | """The changer passes the config to the reporter when running it.""" |
656 | self.config.config = "test.conf" |
657 | + self.config.bindir = "/fake/bin" |
658 | |
659 | - with patch("landscape.package.changer.find_reporter_command", |
660 | - return_value="/fake/bin/landscape-package-reporter"): |
661 | - # Add a task that will do nothing besides producing an |
662 | - # answer. The reporter is only spawned if at least one |
663 | - # task was handled. |
664 | - self.store.add_task("changer", {"type": "change-packages", |
665 | - "operation-id": 123}) |
666 | - self.successResultOf(self.changer.run()) |
667 | + # Add a task that will do nothing besides producing an |
668 | + # answer. The reporter is only spawned if at least one |
669 | + # task was handled. |
670 | + self.store.add_task("changer", {"type": "change-packages", |
671 | + "operation-id": 123}) |
672 | + self.successResultOf(self.changer.run()) |
673 | |
674 | system_mock.assert_called_once_with( |
675 | "/fake/bin/landscape-package-reporter -c test.conf") |
676 | @@ -703,6 +701,7 @@ |
677 | to report the recent changes. If we're running as root, we want to |
678 | change to the "landscape" user and "landscape" group. |
679 | """ |
680 | + self.config.bindir = "/fake/bin" |
681 | |
682 | class FakeGroup(object): |
683 | gr_gid = 199 |
684 | @@ -713,15 +712,12 @@ |
685 | # We are running as root |
686 | with patch("grp.getgrnam", return_value=FakeGroup()) as grnam_mock: |
687 | with patch("pwd.getpwnam", return_value=FakeUser()) as pwnam_mock: |
688 | - with patch( |
689 | - "landscape.package.changer.find_reporter_command", |
690 | - return_value="/fake/bin/landscape-package-reporter"): |
691 | - # Add a task that will do nothing besides producing an |
692 | - # answer. The reporter is only spawned if at least |
693 | - # one task was handled. |
694 | - self.store.add_task("changer", {"type": "change-packages", |
695 | - "operation-id": 123}) |
696 | - self.successResultOf(self.changer.run()) |
697 | + # Add a task that will do nothing besides producing an |
698 | + # answer. The reporter is only spawned if at least |
699 | + # one task was handled. |
700 | + self.store.add_task("changer", {"type": "change-packages", |
701 | + "operation-id": 123}) |
702 | + self.successResultOf(self.changer.run()) |
703 | |
704 | grnam_mock.assert_called_once_with("landscape") |
705 | setgid_mock.assert_called_once_with(199) |
706 | @@ -778,20 +774,19 @@ |
707 | pgrp.assert_called_once_with() |
708 | task.assert_called_once_with(PackageChanger, ["ARGS"]) |
709 | |
710 | - def test_find_changer_command(self): |
711 | - dirname = self.makeDir() |
712 | - filename = self.makeFile("", dirname=dirname, |
713 | - basename="landscape-package-changer") |
714 | - |
715 | - saved_argv = sys.argv |
716 | - try: |
717 | - sys.argv = [os.path.join(dirname, "landscape-monitor")] |
718 | - |
719 | - command = find_changer_command() |
720 | - |
721 | - self.assertEqual(command, filename) |
722 | - finally: |
723 | - sys.argv = saved_argv |
724 | + def test_find_command_with_bindir(self): |
725 | + self.config.bindir = "/spam/eggs" |
726 | + command = PackageChanger.find_command(self.config) |
727 | + |
728 | + self.assertEqual("/spam/eggs/landscape-package-changer", command) |
729 | + |
730 | + def test_find_command_default(self): |
731 | + expected = os.path.join( |
732 | + os.path.dirname(os.path.abspath(sys.argv[0])), |
733 | + "landscape-package-changer") |
734 | + command = PackageChanger.find_command() |
735 | + |
736 | + self.assertEqual(expected, command) |
737 | |
738 | def test_transaction_error_with_unicode_data(self): |
739 | self.store.set_hash_ids({HASH1: 1}) |
740 | |
741 | === modified file 'landscape/package/tests/test_releaseupgrader.py' |
742 | --- landscape/package/tests/test_releaseupgrader.py 2017-03-23 07:43:57 +0000 |
743 | +++ landscape/package/tests/test_releaseupgrader.py 2017-04-05 14:19:44 +0000 |
744 | @@ -502,20 +502,20 @@ |
745 | packages. |
746 | """ |
747 | upgrade_tool_directory = self.config.upgrade_tool_directory |
748 | - open(os.path.join(upgrade_tool_directory, "somefile"), "w").close() |
749 | + with open(os.path.join(upgrade_tool_directory, "somefile"), "w"): |
750 | + pass |
751 | os.mkdir(os.path.join(upgrade_tool_directory, "somedir")) |
752 | |
753 | - reporter_filename = self.makeFile("#!/bin/sh\n" |
754 | - "echo $@\n" |
755 | - "echo $(pwd)\n") |
756 | - os.chmod(reporter_filename, 0o755) |
757 | + self.write_script( |
758 | + self.config, |
759 | + "landscape-package-reporter", |
760 | + "#!/bin/sh\n" |
761 | + "echo $@\n" |
762 | + "echo $(pwd)\n") |
763 | |
764 | deferred = Deferred() |
765 | |
766 | - @mock.patch("landscape.package.releaseupgrader.find_reporter_command") |
767 | - def do_test(find_reporter_mock): |
768 | - |
769 | - find_reporter_mock.return_value = reporter_filename |
770 | + def do_test(): |
771 | result = self.upgrader.finish() |
772 | |
773 | def check_result(args): |
774 | @@ -526,7 +526,6 @@ |
775 | b"--force-apt-update\n%s\n" % os.getcwd().encode("utf-8")) |
776 | self.assertEqual(err, b"") |
777 | self.assertEqual(code, 0) |
778 | - find_reporter_mock.assert_called_once_with() |
779 | |
780 | result.addCallback(check_result) |
781 | result.chainDeferred(deferred) |
782 | @@ -537,11 +536,7 @@ |
783 | @mock.patch("grp.getgrnam") |
784 | @mock.patch("pwd.getpwnam") |
785 | @mock.patch("os.getuid", return_value=0) |
786 | - @mock.patch("landscape.package.releaseupgrader.find_reporter_command", |
787 | - return_value="reporter") |
788 | - def test_finish_as_root( |
789 | - self, find_reporter_mock, getuid_mock, getpwnam_mock, |
790 | - getgrnam_mock): |
791 | + def test_finish_as_root(self, getuid_mock, getpwnam_mock, getgrnam_mock): |
792 | """ |
793 | If the release-upgrader process is run as root, as it alwyas should, |
794 | the L{ReleaseUpgrader.finish} method spawns the package-reporter with |
795 | @@ -573,7 +568,6 @@ |
796 | reactor.spawnProcess = saved_spawn_process |
797 | self.assertEqual(spawn_process_calls, [True]) |
798 | |
799 | - find_reporter_mock.assert_called_once_with() |
800 | getuid_mock.assert_called_once_with() |
801 | getpwnam_mock.assert_called_once_with("landscape") |
802 | getgrnam_mock.assert_called_once_with("landscape") |
803 | @@ -583,16 +577,15 @@ |
804 | The L{ReleaseUpgrader.finish} method passes over to the reporter the |
805 | configuration file the release-upgrader was called with. |
806 | """ |
807 | - reporter_filename = self.makeFile("#!/bin/sh\necho $@\n") |
808 | - os.chmod(reporter_filename, 0o755) |
809 | + self.write_script( |
810 | + self.config, |
811 | + "landscape-package-reporter", |
812 | + "#!/bin/sh\necho $@\n") |
813 | self.config.config = "/some/config" |
814 | |
815 | deferred = Deferred() |
816 | |
817 | - @mock.patch("landscape.package.releaseupgrader.find_reporter_command") |
818 | - def do_test(find_reporter_mock): |
819 | - |
820 | - find_reporter_mock.return_value = reporter_filename |
821 | + def do_test(): |
822 | result = self.upgrader.finish() |
823 | |
824 | def check_result(args): |
825 | @@ -601,7 +594,6 @@ |
826 | b"--config=/some/config\n") |
827 | self.assertEqual(err, b"") |
828 | self.assertEqual(code, 0) |
829 | - find_reporter_mock.assert_called_once_with() |
830 | |
831 | result.addCallback(check_result) |
832 | result.chainDeferred(deferred) |
833 | |
834 | === modified file 'landscape/package/tests/test_reporter.py' |
835 | --- landscape/package/tests/test_reporter.py 2017-03-21 17:00:34 +0000 |
836 | +++ landscape/package/tests/test_reporter.py 2017-04-05 14:19:44 +0000 |
837 | @@ -1116,20 +1116,19 @@ |
838 | self.assertEqual("RESULT", main(["ARGS"])) |
839 | m.assert_called_once_with(PackageReporter, ["ARGS"]) |
840 | |
841 | - def test_find_reporter_command(self): |
842 | - dirname = self.makeDir() |
843 | - filename = self.makeFile("", dirname=dirname, |
844 | - basename="landscape-package-reporter") |
845 | - |
846 | - saved_argv = sys.argv |
847 | - try: |
848 | - sys.argv = [os.path.join(dirname, "landscape-monitor")] |
849 | - |
850 | - command = find_reporter_command() |
851 | - |
852 | - self.assertEqual(command, filename) |
853 | - finally: |
854 | - sys.argv = saved_argv |
855 | + def test_find_reporter_command_with_bindir(self): |
856 | + self.config.bindir = "/spam/eggs" |
857 | + command = find_reporter_command(self.config) |
858 | + |
859 | + self.assertEqual("/spam/eggs/landscape-package-reporter", command) |
860 | + |
861 | + def test_find_reporter_command_default(self): |
862 | + expected = os.path.join( |
863 | + os.path.dirname(os.path.abspath(sys.argv[0])), |
864 | + "landscape-package-reporter") |
865 | + command = find_reporter_command() |
866 | + |
867 | + self.assertEqual(expected, command) |
868 | |
869 | def test_resynchronize(self): |
870 | """ |
871 | |
872 | === modified file 'landscape/tests/helpers.py' |
873 | --- landscape/tests/helpers.py 2017-03-27 06:26:21 +0000 |
874 | +++ landscape/tests/helpers.py 2017-04-05 14:19:44 +0000 |
875 | @@ -276,6 +276,18 @@ |
876 | self.addCleanup(self._clean_file, path) |
877 | return path |
878 | |
879 | + def write_script(self, config, name, content, bindir=None): |
880 | + """Return the path to the script after writing it to a temp dir.""" |
881 | + if bindir is None: |
882 | + bindir = self.makeDir() |
883 | + config.bindir = bindir |
884 | + filename = self.makeFile( |
885 | + content, |
886 | + dirname=bindir, |
887 | + basename=name) |
888 | + os.chmod(filename, 0o755) |
889 | + return filename |
890 | + |
891 | |
892 | class LandscapeIsolatedTest(LandscapeTest): |
893 | """TestCase that also runs all test methods in a subprocess.""" |
894 | |
895 | === modified file 'landscape/tests/test_deployment.py' |
896 | --- landscape/tests/test_deployment.py 2017-03-13 15:38:09 +0000 |
897 | +++ landscape/tests/test_deployment.py 2017-04-05 14:19:44 +0000 |
898 | @@ -2,12 +2,14 @@ |
899 | from textwrap import dedent |
900 | import mock |
901 | import os |
902 | +import os.path |
903 | +import sys |
904 | |
905 | from landscape.compat import StringIO |
906 | from landscape.lib.fs import read_text_file, create_text_file |
907 | |
908 | from landscape.deployment import ( |
909 | - BaseConfiguration, Configuration, get_versioned_persist) |
910 | + BaseConfiguration, Configuration, get_versioned_persist, get_bindir) |
911 | from landscape.manager.config import ManagerConfiguration |
912 | |
913 | from landscape.tests.helpers import LandscapeTest, LogKeeperHelper |
914 | @@ -711,3 +713,37 @@ |
915 | {"monitor": mock_monitor}): |
916 | persist = get_versioned_persist(FakeService()) |
917 | mock_monitor.apply.assert_called_with(persist) |
918 | + |
919 | + |
920 | +class GetBindirTest(LandscapeTest): |
921 | + |
922 | + BIN_DIR = os.path.dirname(os.path.abspath(sys.argv[0])) |
923 | + |
924 | + def test_config_has_valid_bindir(self): |
925 | + """get_bindir() returns the directory name found in the config.""" |
926 | + cfg = Configuration() |
927 | + cfg.bindir = "/spam/eggs" |
928 | + bindir = get_bindir(cfg) |
929 | + |
930 | + self.assertEqual("/spam/eggs", bindir) |
931 | + |
932 | + def test_config_has_None_bindir(self): |
933 | + """get_bindir() """ |
934 | + cfg = Configuration() |
935 | + cfg.bindir = None |
936 | + bindir = get_bindir(cfg) |
937 | + |
938 | + self.assertEqual(self.BIN_DIR, bindir) |
939 | + |
940 | + def test_config_has_no_bindir(self): |
941 | + """get_bindir() """ |
942 | + cfg = object() |
943 | + bindir = get_bindir(cfg) |
944 | + |
945 | + self.assertEqual(self.BIN_DIR, bindir) |
946 | + |
947 | + def test_config_is_None(self): |
948 | + """get_bindir() """ |
949 | + bindir = get_bindir(None) |
950 | + |
951 | + self.assertEqual(self.BIN_DIR, bindir) |
952 | |
953 | === modified file 'landscape/tests/test_watchdog.py' |
954 | --- landscape/tests/test_watchdog.py 2017-04-04 08:50:05 +0000 |
955 | +++ landscape/tests/test_watchdog.py 2017-04-05 14:19:44 +0000 |
956 | @@ -517,12 +517,10 @@ |
957 | |
958 | connector_factory = RemoteStubBrokerConnector |
959 | |
960 | + EXEC_NAME = "landscape-broker" |
961 | + |
962 | def setUp(self): |
963 | super(DaemonTestBase, self).setUp() |
964 | - self.exec_dir = self.makeDir() |
965 | - self.exec_name = os.path.join(self.exec_dir, "landscape-broker") |
966 | - self.saved_argv = sys.argv |
967 | - sys.argv = [os.path.join(self.exec_dir, "arv0_execname")] |
968 | |
969 | if hasattr(self, "broker_service"): |
970 | # DaemonBrokerTest |
971 | @@ -539,7 +537,6 @@ |
972 | self.daemon = self.get_daemon() |
973 | |
974 | def tearDown(self): |
975 | - sys.argv = self.saved_argv |
976 | if hasattr(self, "broker_service"): |
977 | # DaemonBrokerTest |
978 | self.broker_service.stopService() |
979 | @@ -552,7 +549,7 @@ |
980 | else: |
981 | MyDaemon = Daemon |
982 | daemon = MyDaemon(self.connector, **kwargs) |
983 | - daemon.program = os.path.basename(self.exec_name) |
984 | + daemon.program = self.EXEC_NAME |
985 | daemon.factor = 0.01 |
986 | return daemon |
987 | |
988 | @@ -564,25 +561,39 @@ |
989 | self._mtime = os.path.getmtime(filename) |
990 | self._filename = filename |
991 | |
992 | - def wait(self): |
993 | + def wait(self, timeout=60): |
994 | + if timeout: |
995 | + end = time.time() + timeout |
996 | while self._mtime == os.path.getmtime(self._filename): |
997 | time.sleep(0.1) |
998 | + if timeout and time.time() > end: |
999 | + raise RuntimeError( |
1000 | + "timed out after {} seconds".format(timeout)) |
1001 | |
1002 | |
1003 | class DaemonTest(DaemonTestBase): |
1004 | |
1005 | + def _write_script(self, content): |
1006 | + filename = self.write_script(self.config, self.EXEC_NAME, content) |
1007 | + self.daemon.BIN_DIR = self.config.bindir |
1008 | + return filename |
1009 | + |
1010 | def test_find_executable_works(self): |
1011 | - self.makeFile("I'm the broker.", path=self.exec_name) |
1012 | - self.assertEqual(self.daemon.find_executable(), self.exec_name) |
1013 | + expected = self._write_script("I'm the broker.") |
1014 | + command = self.daemon.find_executable() |
1015 | + |
1016 | + self.assertEqual(expected, command) |
1017 | |
1018 | def test_find_executable_cant_find_file(self): |
1019 | - self.assertRaises(ExecutableNotFoundError, self.daemon.find_executable) |
1020 | + self.daemon.BIN_DIR = "/fake/bin" |
1021 | + |
1022 | + with self.assertRaises(ExecutableNotFoundError): |
1023 | + self.daemon.find_executable() |
1024 | |
1025 | def test_start_process(self): |
1026 | output_filename = self.makeFile("NOT RUN") |
1027 | - self.makeFile('#!/bin/sh\necho "RUN $@" > %s' % output_filename, |
1028 | - path=self.exec_name) |
1029 | - os.chmod(self.exec_name, 0o755) |
1030 | + self._write_script( |
1031 | + '#!/bin/sh\necho "RUN $@" > %s' % output_filename) |
1032 | |
1033 | waiter = FileChangeWaiter(output_filename) |
1034 | |
1035 | @@ -597,16 +608,16 @@ |
1036 | |
1037 | def test_start_process_with_verbose(self): |
1038 | output_filename = self.makeFile("NOT RUN") |
1039 | - self.makeFile('#!/bin/sh\necho "RUN $@" > %s' % output_filename, |
1040 | - path=self.exec_name) |
1041 | - os.chmod(self.exec_name, 0o755) |
1042 | + self._write_script( |
1043 | + '#!/bin/sh\necho "RUN $@" > %s' % output_filename) |
1044 | |
1045 | waiter = FileChangeWaiter(output_filename) |
1046 | |
1047 | daemon = self.get_daemon(verbose=True) |
1048 | + daemon.BIN_DIR = self.config.bindir |
1049 | daemon.start() |
1050 | |
1051 | - waiter.wait() |
1052 | + waiter.wait(timeout=10) |
1053 | |
1054 | self.assertEqual(open(output_filename).read(), |
1055 | "RUN --ignore-sigint\n") |
1056 | @@ -616,15 +627,14 @@ |
1057 | def test_kill_process_with_sigterm(self): |
1058 | """The stop() method sends SIGTERM to the subprocess.""" |
1059 | output_filename = self.makeFile("NOT RUN") |
1060 | - self.makeFile("#!%s\n" |
1061 | - "import time\n" |
1062 | - "file = open(%r, 'w')\n" |
1063 | - "file.write('RUN')\n" |
1064 | - "file.close()\n" |
1065 | - "time.sleep(1000)\n" |
1066 | - % (sys.executable, output_filename), |
1067 | - path=self.exec_name) |
1068 | - os.chmod(self.exec_name, 0o755) |
1069 | + self._write_script( |
1070 | + ("#!%s\n" |
1071 | + "import time\n" |
1072 | + "file = open(%r, 'w')\n" |
1073 | + "file.write('RUN')\n" |
1074 | + "file.close()\n" |
1075 | + "time.sleep(1000)\n" |
1076 | + ) % (sys.executable, output_filename)) |
1077 | |
1078 | waiter = FileChangeWaiter(output_filename) |
1079 | self.daemon.start() |
1080 | @@ -639,16 +649,15 @@ |
1081 | some time after the SIGTERM was issued and didn't work. |
1082 | """ |
1083 | output_filename = self.makeFile("NOT RUN") |
1084 | - self.makeFile("#!%s\n" |
1085 | - "import signal, os\n" |
1086 | - "signal.signal(signal.SIGTERM, signal.SIG_IGN)\n" |
1087 | - "file = open(%r, 'w')\n" |
1088 | - "file.write('RUN')\n" |
1089 | - "file.close()\n" |
1090 | - "os.kill(os.getpid(), signal.SIGSTOP)\n" |
1091 | - % (sys.executable, output_filename), |
1092 | - path=self.exec_name) |
1093 | - os.chmod(self.exec_name, 0o755) |
1094 | + self._write_script( |
1095 | + ("#!%s\n" |
1096 | + "import signal, os\n" |
1097 | + "signal.signal(signal.SIGTERM, signal.SIG_IGN)\n" |
1098 | + "file = open(%r, 'w')\n" |
1099 | + "file.write('RUN')\n" |
1100 | + "file.close()\n" |
1101 | + "os.kill(os.getpid(), signal.SIGSTOP)\n" |
1102 | + ) % (sys.executable, output_filename)) |
1103 | |
1104 | self.addCleanup(setattr, landscape.watchdog, "SIGKILL_DELAY", |
1105 | landscape.watchdog.SIGKILL_DELAY) |
1106 | @@ -666,9 +675,8 @@ |
1107 | died. |
1108 | """ |
1109 | output_filename = self.makeFile("NOT RUN") |
1110 | - self.makeFile('#!/bin/sh\necho "RUN" > %s' % output_filename, |
1111 | - path=self.exec_name) |
1112 | - os.chmod(self.exec_name, 0o755) |
1113 | + self._write_script( |
1114 | + '#!/bin/sh\necho "RUN" > %s' % output_filename) |
1115 | |
1116 | self.daemon.start() |
1117 | |
1118 | @@ -682,9 +690,8 @@ |
1119 | certain amount of time, just like C{wait}. |
1120 | """ |
1121 | output_filename = self.makeFile("NOT RUN") |
1122 | - self.makeFile('#!/bin/sh\necho "RUN" > %s' % output_filename, |
1123 | - path=self.exec_name) |
1124 | - os.chmod(self.exec_name, 0o755) |
1125 | + self._write_script( |
1126 | + '#!/bin/sh\necho "RUN" > %s' % output_filename) |
1127 | |
1128 | self.daemon.start() |
1129 | |
1130 | @@ -695,7 +702,8 @@ |
1131 | def test_wait_or_die_terminates(self): |
1132 | """wait_or_die eventually terminates the process.""" |
1133 | output_filename = self.makeFile("NOT RUN") |
1134 | - self.makeFile("""\ |
1135 | + self._write_script( |
1136 | + """\ |
1137 | #!%(exe)s |
1138 | import time |
1139 | import signal |
1140 | @@ -708,10 +716,7 @@ |
1141 | file.close() |
1142 | signal.signal(signal.SIGTERM, term) |
1143 | time.sleep(999) |
1144 | - """ |
1145 | - % {"exe": sys.executable, "out": output_filename}, |
1146 | - path=self.exec_name) |
1147 | - os.chmod(self.exec_name, 0o755) |
1148 | + """ % {"exe": sys.executable, "out": output_filename}) |
1149 | |
1150 | self.addCleanup(setattr, landscape.watchdog, "GRACEFUL_WAIT_PERIOD", |
1151 | landscape.watchdog.GRACEFUL_WAIT_PERIOD) |
1152 | @@ -728,16 +733,15 @@ |
1153 | and terminating don't work. |
1154 | """ |
1155 | output_filename = self.makeFile("NOT RUN") |
1156 | - self.makeFile("#!%s\n" |
1157 | - "import signal, os\n" |
1158 | - "signal.signal(signal.SIGTERM, signal.SIG_IGN)\n" |
1159 | - "file = open(%r, 'w')\n" |
1160 | - "file.write('RUN')\n" |
1161 | - "file.close()\n" |
1162 | - "os.kill(os.getpid(), signal.SIGSTOP)\n" |
1163 | - % (sys.executable, output_filename), |
1164 | - path=self.exec_name) |
1165 | - os.chmod(self.exec_name, 0o755) |
1166 | + self._write_script( |
1167 | + ("#!%s\n" |
1168 | + "import signal, os\n" |
1169 | + "signal.signal(signal.SIGTERM, signal.SIG_IGN)\n" |
1170 | + "file = open(%r, 'w')\n" |
1171 | + "file.write('RUN')\n" |
1172 | + "file.close()\n" |
1173 | + "os.kill(os.getpid(), signal.SIGSTOP)\n" |
1174 | + ) % (sys.executable, output_filename)) |
1175 | |
1176 | self.addCleanup(setattr, landscape.watchdog, "SIGKILL_DELAY", |
1177 | landscape.watchdog.SIGKILL_DELAY) |
1178 | @@ -789,9 +793,8 @@ |
1179 | |
1180 | output_filename = self.makeFile("NOT RUN") |
1181 | |
1182 | - self.makeFile("#!/bin/sh\necho RUN >> %s" % output_filename, |
1183 | - path=self.exec_name) |
1184 | - os.chmod(self.exec_name, 0o755) |
1185 | + self._write_script( |
1186 | + "#!/bin/sh\necho RUN >> %s" % output_filename) |
1187 | |
1188 | def got_result(result): |
1189 | self.assertEqual(len(list(open(output_filename))), |
1190 | @@ -813,6 +816,7 @@ |
1191 | reactor.callLater(1, result.callback, None) |
1192 | |
1193 | daemon = self.get_daemon(reactor=reactor) |
1194 | + daemon.BIN_DIR = self.config.bindir |
1195 | daemon.start() |
1196 | |
1197 | return result |
1198 | @@ -832,9 +836,8 @@ |
1199 | |
1200 | output_filename = self.makeFile("NOT RUN") |
1201 | |
1202 | - self.makeFile("#!/bin/sh\necho RUN >> %s" % output_filename, |
1203 | - path=self.exec_name) |
1204 | - os.chmod(self.exec_name, 0o755) |
1205 | + self._write_script( |
1206 | + "#!/bin/sh\necho RUN >> %s" % output_filename) |
1207 | |
1208 | def got_result(result): |
1209 | # Pay attention to the +1 bellow. It's the reason for this test. |
1210 | @@ -866,6 +869,7 @@ |
1211 | # It's important to call start() shortly after the mocking above, |
1212 | # as we don't want anyone else getting the fake time. |
1213 | daemon = self.get_daemon(reactor=reactor) |
1214 | + daemon.BIN_DIR = self.config.bindir |
1215 | daemon.start() |
1216 | |
1217 | def mock_reactor_stop(): |
1218 | @@ -891,7 +895,7 @@ |
1219 | the username of the daemon. It also specifies the gid as the primary |
1220 | group of that user. |
1221 | """ |
1222 | - self.makeFile("", path=self.exec_name) |
1223 | + self._write_script("#!/bin/sh") |
1224 | |
1225 | class getpwnam_result: |
1226 | pw_uid = 123 |
1227 | @@ -903,6 +907,7 @@ |
1228 | reactor = mock.Mock() |
1229 | |
1230 | daemon = self.get_daemon(reactor=reactor) |
1231 | + daemon.BIN_DIR = self.config.bindir |
1232 | daemon.start() |
1233 | |
1234 | getuid.assert_called_with() |
1235 | @@ -926,10 +931,11 @@ |
1236 | If the watchdog is not running as root, no uid or gid switching will |
1237 | occur. |
1238 | """ |
1239 | - self.makeFile("", path=self.exec_name) |
1240 | + self._write_script("#!/bin/sh") |
1241 | |
1242 | reactor = mock.Mock() |
1243 | daemon = self.get_daemon(reactor=reactor) |
1244 | + daemon.BIN_DIR = self.config.bindir |
1245 | daemon.start() |
1246 | |
1247 | reactor.spawnProcess.assert_called_with( |
1248 | @@ -943,10 +949,11 @@ |
1249 | If the daemon is specified to run as root, and the watchdog is running |
1250 | as root, no uid or gid switching will occur. |
1251 | """ |
1252 | - self.makeFile("", path=self.exec_name) |
1253 | + self._write_script("#!/bin/sh") |
1254 | reactor = mock.Mock() |
1255 | |
1256 | daemon = self.get_daemon(reactor=reactor, username="root") |
1257 | + daemon.BIN_DIR = self.config.bindir |
1258 | daemon.start() |
1259 | |
1260 | reactor.spawnProcess.assert_called_with( |
1261 | |
1262 | === modified file 'landscape/watchdog.py' |
1263 | --- landscape/watchdog.py 2017-04-05 11:55:26 +0000 |
1264 | +++ landscape/watchdog.py 2017-04-05 14:19:44 +0000 |
1265 | @@ -22,7 +22,7 @@ |
1266 | from twisted.application.service import Service, Application |
1267 | from twisted.application.app import startApplication |
1268 | |
1269 | -from landscape.deployment import init_logging, Configuration |
1270 | +from landscape.deployment import init_logging, Configuration, get_bindir |
1271 | from landscape.lib.encoding import encode_values |
1272 | from landscape.lib.twisted_util import gather_results |
1273 | from landscape.lib.log import log_failure |
1274 | @@ -76,6 +76,8 @@ |
1275 | factor = 1.1 |
1276 | options = None |
1277 | |
1278 | + BIN_DIR = None |
1279 | + |
1280 | def __init__(self, connector, reactor=reactor, verbose=False, |
1281 | config=None): |
1282 | self._connector = connector |
1283 | @@ -115,7 +117,7 @@ |
1284 | If the executable can't be found, L{ExecutableNotFoundError} will be |
1285 | raised. |
1286 | """ |
1287 | - dirname = os.path.dirname(os.path.abspath(sys.argv[0])) |
1288 | + dirname = self.BIN_DIR or get_bindir() |
1289 | executable = os.path.join(dirname, self.program) |
1290 | if not os.path.exists(executable): |
1291 | raise ExecutableNotFoundError("%s doesn't exist" % (executable,)) |
Command: TRIAL_ARGS=-j4 make ci-check /ci.lscape. net/job/ latch-test- xenial/ 3818/
Result: Fail
Revno: 992
Branch: lp:~ericsnowcurrently/landscape-client/fix-test-race-sys-argv
Jenkins: https:/