Merge lp:~ericsnowcurrently/landscape-charm/fix-1610413-collect-inner-model into lp:~landscape/landscape-charm/tools

Proposed by Eric Snow
Status: Rejected
Rejected by: Eric Snow
Proposed branch: lp:~ericsnowcurrently/landscape-charm/fix-1610413-collect-inner-model
Merge into: lp:~landscape/landscape-charm/tools
Prerequisite: lp:~ericsnowcurrently/landscape-charm/tools-unit-tests-for-script
Diff against target: 818 lines (+351/-140) (has conflicts)
2 files modified
collect-logs (+108/-53)
test_collect-logs.py (+243/-87)
Text conflict in collect-logs
To merge this branch: bzr merge lp:~ericsnowcurrently/landscape-charm/fix-1610413-collect-inner-model
Reviewer Review Type Date Requested Status
Landscape Pending
Review via email: mp+303086@code.launchpad.net

This proposal supersedes a proposal from 2016-08-17.

Description of the change

Make collect-logs work with Juju 2.

Testing instructions:

1. Deploy landscape
2. install juju-2.0 on the landscape-server/0 unit
3. enable the "juju-2.0" feature flag
4. autopilot
5. run collect-logs

To post a comment you must log in.
28. By Eric Snow

Revert revision #27.

29. By Eric Snow

Revert revision #26.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'collect-logs'
2--- collect-logs 2016-08-17 14:14:30 +0000
3+++ collect-logs 2016-08-17 14:14:30 +0000
4@@ -2,6 +2,7 @@
5
6 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
7 import errno
8+import functools
9 import logging
10 import multiprocessing
11 import os
12@@ -25,16 +26,24 @@
13 "/var/lib/juju/containers/juju-*-lxc-template"]
14 LANDSCAPE_JUJU_HOME = "/var/lib/landscape/juju-homes"
15
16-
17-def juju_status():
18+JUJU1 = "juju"
19+# XXX This is going to break once juju-2.1 happens.
20+# See https://bugs.launchpad.net/juju-core/+bug/1613864.
21+JUJU2 = "juju-2.0"
22+JUJU = JUJU1
23+
24+
25+def juju_status(juju):
26 """Return a juju status structure."""
27- cmd = ["juju", "status", "--format=yaml"]
28+ cmd = [juju, "status", "--format=yaml"]
29 output = check_output(cmd).decode("utf-8").strip()
30 return yaml.load(output)
31
32
33-def get_units(status=juju_status()):
34+def get_units(juju, status=None):
35 """Return a list with all units."""
36+ if status is None:
37+ status = juju_status(juju)
38 units = []
39 if "services" in status:
40 applications = status["services"]
41@@ -52,12 +61,12 @@
42 return units
43
44
45-def _create_ps_output_file(unit):
46+def _create_ps_output_file(juju, unit):
47 """List running processes and redirect them to a file."""
48 ps_cmd = "ps fauxww | sudo tee /var/log/ps-fauxww.txt"
49 try:
50 log.info("Collecting ps output on unit {}".format(unit))
51- check_output(["juju", "ssh", unit, ps_cmd], stderr=STDOUT)
52+ check_output([juju, "ssh", unit, ps_cmd], stderr=STDOUT)
53 except CalledProcessError as e:
54 log.warning(
55 "Failed to collect running processes on unit {}".format(unit))
56@@ -65,7 +74,7 @@
57 log.warning(e.returncode)
58
59
60-def _create_log_tarball(unit):
61+def _create_log_tarball(juju, unit):
62 exclude = " ".join(["--exclude=%s" % x for x in EXCLUDED])
63 logs = "$(sudo sh -c \"ls -1d %s 2>/dev/null\")" % " ".join(LOGS)
64 # note, tar commands can fail since we are backing up log files
65@@ -80,7 +89,7 @@
66 tar_cmd, exclude, logsuffix, logs)
67 try:
68 log.info("Creating tarball on unit {}".format(unit))
69- check_output(["juju", "ssh", unit, cmd], stderr=STDOUT)
70+ check_output([juju, "ssh", unit, cmd], stderr=STDOUT)
71 except CalledProcessError as e:
72 log.warning(
73 "Failed to create remote log tarball on unit {}".format(unit))
74@@ -88,7 +97,7 @@
75 log.warning(e.returncode)
76
77
78-def collect_logs():
79+def collect_logs(juju=JUJU):
80 """
81 Remotely, on each unit, create a tarball with the requested log files
82 or directories, if they exist. If a requested log does not exist on a
83@@ -96,19 +105,19 @@
84 After each tarball is created, it's downloaded to the current directory
85 and expanded, and the tarball is then deleted.
86 """
87- units = get_units()
88+ units = get_units(juju)
89 # include bootstrap
90 units.append("0")
91
92 log.info("Collecting running processes for all units including bootstrap")
93- map(_create_ps_output_file, units)
94+ map((lambda u: _create_ps_output_file(juju, u)), units)
95
96 log.info("Creating remote tarball in parallel for units %s" % (
97 ",".join(units)))
98- map(_create_log_tarball, units)
99+ map((lambda u: _create_log_tarball(juju, u)), units)
100 log.info("Downloading logs from units")
101
102- _mp_map(download_log_from_unit, units)
103+ _mp_map(functools.partial(download_log_from_unit, juju), units)
104
105
106 def _mp_map(func, args):
107@@ -129,6 +138,7 @@
108 return units[0]
109
110
111+<<<<<<< TREE
112 def disable_ssh_proxy(landscape_unit):
113 """
114 Workaround for #1607076: disable the proxy-ssh juju environment setting
115@@ -148,77 +158,117 @@
116 log.warning("Error was:\n{}".format(e.output))
117
118 def collect_inner_logs():
119+=======
120+def find_inner_juju(juju, landscape_unit):
121+ """Return the juju dir and binary path, if any."""
122+ # Identify the most recent juju "home" that landscape is using.
123+ cmd = "sudo ls -rt {}/".format(LANDSCAPE_JUJU_HOME)
124+ try:
125+ output = check_output(["juju", "ssh", landscape_unit, cmd]).strip()
126+ except CalledProcessError:
127+ return None, None
128+ if output.startswith("sudo: "):
129+ _, _, output = output.partition("\r\n")
130+ models = [m for m in output.split() if m and m.isdigit()]
131+ if not models:
132+ return None, None
133+ model = models[-1]
134+ juju_dir = os.path.join(LANDSCAPE_JUJU_HOME, model)
135+
136+ # Try Juju 2.
137+ juju_env = "JUJU_DATA={}".format(juju_dir)
138+ cmd = "sudo {} {} status".format(juju_env, JUJU2)
139+ if call([juju, "ssh", landscape_unit, cmd]) == 0:
140+ log.info("using Juju 2 for inner model")
141+ return juju_env, JUJU2
142+
143+ # Try Juju 1.
144+ juju_env = "JUJU_HOME={}".format(juju_dir)
145+ cmd = "sudo {} {} status".format(juju_env, JUJU1)
146+ if call([juju, "ssh", landscape_unit, cmd]) == 0:
147+ log.info("using Juju 1 for inner model")
148+ return juju_env, JUJU1
149+
150+ # We didn't find an inner model.
151+ return None, None
152+
153+
154+def collect_inner_logs(juju=JUJU):
155+>>>>>>> MERGE-SOURCE
156 """Collect logs from an inner landscape[-server]/0 unit."""
157- units = get_units()
158+ units = get_units(juju)
159 landscape_unit = get_landscape_unit(units)
160 if not landscape_unit:
161 log.info("No landscape[-server]/N found, skipping")
162 return
163- log.info("Found landscape unit %s" % landscape_unit)
164+ log.info("Found landscape unit {}".format(landscape_unit))
165
166- # Make sure that there *is* an inner model.
167- poke_inner_env = (
168- "sudo JUJU_HOME=%s/`sudo ls -rt %s/ | tail -1` juju status" %
169- (LANDSCAPE_JUJU_HOME, LANDSCAPE_JUJU_HOME))
170- try:
171- check_output(["juju", "ssh", landscape_unit, poke_inner_env])
172- except CalledProcessError:
173- log.info("No active inner environment found on %s, skipping" %
174- landscape_unit)
175+ # Look up the inner model.
176+ juju_env, inner_juju = find_inner_juju(juju, landscape_unit)
177+ if inner_juju is None:
178+ log.info(("No active inner environment found on {}, skipping"
179+ ).format(landscape_unit))
180 return
181 <<<<<<< TREE
182 disable_ssh_proxy(landscape_unit)
183+ call(["juju", "scp", PRG, "%s:%s" % (landscape_unit, collect_logs)])
184+ call(["juju", "ssh", landscape_unit, "sudo rm -rf /tmp/inner-logs.tar.*"])
185+ log.info("Collecting Logs on inner environment")
186+ check_call(
187+ ["juju", "ssh", landscape_unit, "sudo -u landscape %s" % collect_run])
188 =======
189
190 # Prepare to get the logs from the inner model.
191 collect_logs = "/tmp/collect-logs"
192->>>>>>> MERGE-SOURCE
193- call(["juju", "scp", PRG, "%s:%s" % (landscape_unit, collect_logs)])
194- call(["juju", "ssh", landscape_unit, "sudo rm -rf /tmp/inner-logs.tar.*"])
195+ tarball = "/tmp/inner-logs.tar.gz"
196+ check_call([juju, "scp",
197+ PRG,
198+ "{}:{}".format(landscape_unit, collect_logs)])
199+ check_call([juju, "ssh", landscape_unit,
200+ "sudo rm -rf /tmp/inner-logs.tar.*"])
201
202 # Collect the logs for the inner model.
203- log.info("Collecting Logs on inner environment")
204- collect_run = (
205- "JUJU_HOME=%s/`sudo ls -rt %s/ | tail -1`"
206- " %s /tmp/inner-logs.tar.gz" % (
207- LANDSCAPE_JUJU_HOME, LANDSCAPE_JUJU_HOME, collect_logs))
208- check_call(["juju", "ssh",
209+ log.info("Collecting logs on inner environment")
210+ cmd = ("{} {} --inner --juju {} {}"
211+ ).format(juju_env, collect_logs, inner_juju, tarball)
212+ check_call([juju, "ssh",
213 landscape_unit,
214- "sudo -u landscape %s" % collect_run,
215+ "sudo -u landscape {}".format(cmd),
216 ])
217
218 # Copy the inner logs into a local directory.
219+>>>>>>> MERGE-SOURCE
220 log.info("Copying inner environment back")
221+ source = "{}:{}".format(landscape_unit, tarball)
222+ cwd = os.getcwd()
223+ target = os.path.join(cwd, os.path.basename(tarball))
224 try:
225- check_call(["juju", "scp",
226- "%s:/tmp/inner-logs.tar.gz" % landscape_unit,
227- ".",
228- ])
229- cwd = os.getcwd()
230+ check_call([juju, "scp", source, target])
231+
232 inner_dir = "landscape-0-inner-logs"
233 os.mkdir(inner_dir)
234 os.chdir(inner_dir)
235 try:
236- check_call(["tar", "-zxf", "%s/inner-logs.tar.gz" % cwd])
237+ check_call(["tar", "-zxf", target])
238 finally:
239 os.chdir(cwd)
240 finally:
241 try:
242- os.remove("inner-logs.tar.gz")
243+ os.remove(target)
244 except OSError as e:
245 if e.errno != errno.ENOENT:
246 log.warning(
247- "failed to remove inner logs tarball: {}".format(err))
248-
249-
250-def download_log_from_unit(unit):
251+ "failed to remove inner logs tarball: {}".format(e))
252+
253+
254+def download_log_from_unit(juju, unit):
255 log.info("Downloading tarball from unit %s" % unit)
256 unit_filename = unit.replace("/", "-")
257 if unit == "0":
258 unit_filename = "bootstrap"
259 try:
260 remote_filename = "logs_%s.tar.gz" % unit_filename
261- call(["juju", "scp", "%s:/tmp/%s" % (unit, remote_filename), "."])
262+ call([juju, "scp", "%s:/tmp/%s" % (unit, remote_filename), "."])
263 os.mkdir(unit_filename)
264 call(["tar", "-C", unit_filename, "-xzf", remote_filename])
265 os.unlink(remote_filename)
266@@ -267,13 +317,17 @@
267 "inner autopilot cloud is detected, include that.")
268 parser = ArgumentParser(description=description,
269 formatter_class=ArgumentDefaultsHelpFormatter)
270+ parser.add_argument("--inner", action="store_true", default=False,
271+ help="Collect logs for an inner model.")
272+ parser.add_argument("--juju", default=JUJU,
273+ help="The Juju binary to use.")
274 parser.add_argument("tarfile", help="Full path to tarfile to create.")
275 parser.add_argument("extrafiles", help="Optional full path to extra "
276 "logfiles to include, space separated", nargs="*")
277 return parser
278
279
280-def main(tarfile, extrafiles):
281+def main(tarfile, extrafiles, juju=JUJU, inner=False):
282 # we need the absolute path because we will be changing
283 # the cwd
284 tmpdir = mkdtemp()
285@@ -281,11 +335,12 @@
286 # logs are collected inside a temporary directory
287 os.chdir(tmpdir)
288 try:
289- collect_logs()
290- try:
291- collect_inner_logs()
292- except:
293- log.warning("Collecting inner logs failed, continuing")
294+ collect_logs(juju)
295+ if not inner:
296+ try:
297+ collect_inner_logs(juju)
298+ except:
299+ log.warning("Collecting inner logs failed, continuing")
300 # we create the final tarball outside of tmpdir to we can
301 # add the extrafiles to the tarball root
302 os.chdir(cwd)
303@@ -302,4 +357,4 @@
304 parser = get_option_parser()
305 args = parser.parse_args(sys.argv[1:])
306 tarfile = os.path.abspath(args.tarfile)
307- main(tarfile, args.extrafiles)
308+ main(tarfile, args.extrafiles, args.juju, args.inner)
309
310=== modified file 'test_collect-logs.py'
311--- test_collect-logs.py 2016-08-17 14:14:30 +0000
312+++ test_collect-logs.py 2016-08-17 14:14:30 +0000
313@@ -92,22 +92,35 @@
314
315 script.main(tarfile, extrafiles)
316
317- script.collect_logs.assert_called_once_with()
318- script.collect_inner_logs.assert_called_once_with()
319+ script.collect_logs.assert_called_once_with("juju")
320+ script.collect_inner_logs.assert_called_once_with("juju")
321 script.bundle_logs.assert_called_once_with(
322 self.tempdir, tarfile, extrafiles)
323 self.assertFalse(os.path.exists(self.tempdir))
324
325 def test_in_correct_directories(self):
326- script.collect_logs.side_effect = lambda: self.assert_cwd(self.tempdir)
327+ script.collect_logs.side_effect = (
328+ lambda _: self.assert_cwd(self.tempdir))
329 script.collect_inner_logs.side_effect = (
330- lambda: self.assert_cwd(self.tempdir))
331+ lambda _: self.assert_cwd(self.tempdir))
332 script.bundle_logs.side_effect = lambda *a: self.assert_cwd(self.cwd)
333 tarfile = "/tmp/logs.tgz"
334 extrafiles = ["spam.py"]
335
336 script.main(tarfile, extrafiles)
337
338+ def test_inner(self):
339+ tarfile = "/tmp/logs.tgz"
340+ extrafiles = ["spam.py"]
341+
342+ script.main(tarfile, extrafiles, inner=True)
343+
344+ script.collect_logs.assert_called_once_with("juju")
345+ script.collect_inner_logs.assert_not_called()
346+ script.bundle_logs.assert_called_once_with(
347+ self.tempdir, tarfile, extrafiles)
348+ self.assertFalse(os.path.exists(self.tempdir))
349+
350 def test_cleanup(self):
351 tarfile = "/tmp/logs.tgz"
352 extrafiles = ["spam.py"]
353@@ -124,7 +137,7 @@
354 with self.assertRaises(FakeError):
355 script.main(tarfile, extrafiles)
356
357- script.collect_logs.assert_called_once_with()
358+ script.collect_logs.assert_called_once_with("juju")
359 script.collect_inner_logs.assert_not_called()
360 script.bundle_logs.assert_not_called()
361 self.assertFalse(os.path.exists(self.tempdir))
362@@ -136,8 +149,8 @@
363
364 script.main(tarfile, extrafiles)
365
366- script.collect_logs.assert_called_once_with()
367- script.collect_inner_logs.assert_called_once_with()
368+ script.collect_logs.assert_called_once_with("juju")
369+ script.collect_inner_logs.assert_called_once_with("juju")
370 script.bundle_logs.assert_called_once_with(
371 self.tempdir, tarfile, extrafiles)
372 self.assertFalse(os.path.exists(self.tempdir))
373@@ -150,8 +163,8 @@
374 with self.assertRaises(FakeError):
375 script.main(tarfile, extrafiles)
376
377- script.collect_logs.assert_called_once_with()
378- script.collect_inner_logs.assert_called_once_with()
379+ script.collect_logs.assert_called_once_with("juju")
380+ script.collect_inner_logs.assert_called_once_with("juju")
381 script.bundle_logs.assert_called_once_with(
382 self.tempdir, tarfile, extrafiles)
383 self.assertFalse(os.path.exists(self.tempdir))
384@@ -192,9 +205,9 @@
385 def test_success(self):
386 script.call.side_effect = self._call_side_effect
387
388- script.collect_logs()
389+ script.collect_logs("juju")
390
391- script.get_units.assert_called_once_with()
392+ script.get_units.assert_called_once_with("juju")
393 expected = []
394 units = self.units + ["0"]
395 # for _create_ps_output_file()
396@@ -246,9 +259,9 @@
397 script.get_units.side_effect = FakeError()
398
399 with self.assertRaises(FakeError):
400- script.collect_logs()
401+ script.collect_logs("juju")
402
403- script.get_units.assert_called_once_with()
404+ script.get_units.assert_called_once_with("juju")
405 script.check_output.assert_not_called()
406 script.call.assert_not_called()
407
408@@ -258,9 +271,9 @@
409 ]
410
411 with self.assertRaises(FakeError):
412- script.collect_logs()
413+ script.collect_logs("juju")
414
415- script.get_units.assert_called_once_with()
416+ script.get_units.assert_called_once_with("juju")
417 self.assertEqual(script.check_output.call_count, 2)
418 script.call.assert_not_called()
419
420@@ -276,9 +289,9 @@
421 return self._call_side_effect(cmd)
422 script.call.side_effect = call_side_effect
423
424- script.collect_logs()
425+ script.collect_logs("juju")
426
427- script.get_units.assert_called_once_with()
428+ script.get_units.assert_called_once_with("juju")
429 units = self.units + ["0"]
430 self.assertEqual(script.check_output.call_count, len(units) * 2)
431 self.assertEqual(script.call.call_count, len(units) * 2 - 1)
432@@ -306,6 +319,8 @@
433 "haproxy/0",
434 ]
435 script.get_units.return_value = self.units[:]
436+ script.check_output.return_value = "0\n"
437+ script.call.return_value = 0
438
439 os.chdir(self.tempdir)
440
441@@ -313,50 +328,110 @@
442 self.assert_cwd(self.tempdir)
443 self.assertFalse(os.path.exists("inner-logs.tar.gz"))
444
445- def test_success(self):
446- def check_call_side_effect(cmd):
447- if script.check_call.call_count == 2:
448- self.assert_cwd(self.tempdir)
449- self._touch_tempfile("inner-logs.tar.gz")
450- elif script.check_call.call_count == 3:
451- cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")
452- self.assert_cwd(cwd)
453- return None
454- script.check_call.side_effect = check_call_side_effect
455-
456- script.collect_inner_logs()
457-
458- # get_units()
459- script.get_units.assert_called_once_with()
460- # check_output()
461- cmd = ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/"
462- "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"
463- " juju status")
464- script.check_output.assert_called_once_with(
465- ["juju", "ssh", "landscape-server/0", cmd])
466- # call()
467- expected = [
468- mock.call(["juju", "scp",
469- os.path.join(os.path.dirname(__file__), "collect-logs"),
470- "landscape-server/0:/tmp/collect-logs",
471- ]),
472- mock.call(["juju", "ssh",
473- "landscape-server/0",
474- "sudo rm -rf /tmp/inner-logs.tar.*",
475- ]),
476- ]
477- self.assertEqual(script.call.call_count, len(expected))
478- script.call.assert_has_calls(expected, any_order=True)
479- # check_call()
480- cmd = ("sudo -u landscape"
481- " JUJU_HOME=/var/lib/landscape/juju-homes/"
482- "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"
483- " /tmp/collect-logs /tmp/inner-logs.tar.gz")
484- expected = [
485- mock.call(["juju", "ssh", "landscape-server/0", cmd]),
486- mock.call(["juju", "scp",
487- "landscape-server/0:/tmp/inner-logs.tar.gz",
488- ".",
489+ def test_juju_2(self):
490+ def check_call_side_effect(cmd):
491+ if script.check_call.call_count == 4:
492+ self.assert_cwd(self.tempdir)
493+ self._touch_tempfile("inner-logs.tar.gz")
494+ elif script.check_call.call_count == 5:
495+ cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")
496+ self.assert_cwd(cwd)
497+ return None
498+ script.check_call.side_effect = check_call_side_effect
499+
500+ script.collect_inner_logs("juju")
501+
502+ # get_units()
503+ script.get_units.assert_called_once_with("juju")
504+ # check_output()
505+ script.check_output.assert_called_once_with(
506+ ["juju", "ssh", "landscape-server/0",
507+ "sudo ls -rt /var/lib/landscape/juju-homes/"])
508+ # call()
509+ expected = [
510+ mock.call(["juju", "ssh", "landscape-server/0",
511+ ("sudo JUJU_DATA=/var/lib/landscape/juju-homes/0 "
512+ "juju-2.0 status"),
513+ ]),
514+ ]
515+ self.assertEqual(script.call.call_count, len(expected))
516+ script.call.assert_has_calls(expected, any_order=True)
517+ # check_call()
518+ cmd = ("sudo -u landscape"
519+ " JUJU_DATA=/var/lib/landscape/juju-homes/0"
520+ " /tmp/collect-logs --inner --juju juju-2.0"
521+ " /tmp/inner-logs.tar.gz")
522+ expected = [
523+ mock.call(["juju", "scp",
524+ os.path.join(os.path.dirname(__file__), "collect-logs"),
525+ "landscape-server/0:/tmp/collect-logs",
526+ ]),
527+ mock.call(["juju", "ssh",
528+ "landscape-server/0",
529+ "sudo rm -rf /tmp/inner-logs.tar.*",
530+ ]),
531+ mock.call(["juju", "ssh", "landscape-server/0", cmd]),
532+ mock.call(["juju", "scp",
533+ "landscape-server/0:/tmp/inner-logs.tar.gz",
534+ os.path.join(self.tempdir, "inner-logs.tar.gz"),
535+ ]),
536+ mock.call(["tar", "-zxf", self.tempdir + "/inner-logs.tar.gz"]),
537+ ]
538+ self.assertEqual(script.check_call.call_count, len(expected))
539+ script.check_call.assert_has_calls(expected, any_order=True)
540+ self.assert_clean()
541+
542+ def test_juju_1(self):
543+ def check_call_side_effect(cmd):
544+ if script.check_call.call_count == 4:
545+ self.assert_cwd(self.tempdir)
546+ self._touch_tempfile("inner-logs.tar.gz")
547+ elif script.check_call.call_count == 5:
548+ cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")
549+ self.assert_cwd(cwd)
550+ return None
551+ script.check_call.side_effect = check_call_side_effect
552+ script.call.side_effect = [1, 0]
553+
554+ script.collect_inner_logs("juju")
555+
556+ # get_units()
557+ script.get_units.assert_called_once_with("juju")
558+ # check_output()
559+ script.check_output.assert_called_once_with(
560+ ["juju", "ssh", "landscape-server/0",
561+ "sudo ls -rt /var/lib/landscape/juju-homes/"])
562+ # call()
563+ expected = [
564+ mock.call(["juju", "ssh", "landscape-server/0",
565+ ("sudo JUJU_DATA=/var/lib/landscape/juju-homes/0 "
566+ "juju-2.0 status"),
567+ ]),
568+ mock.call(["juju", "ssh", "landscape-server/0",
569+ ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/0 "
570+ "juju status"),
571+ ]),
572+ ]
573+ self.assertEqual(script.call.call_count, len(expected))
574+ script.call.assert_has_calls(expected, any_order=True)
575+ # check_call()
576+ cmd = ("sudo -u landscape"
577+ " JUJU_HOME=/var/lib/landscape/juju-homes/0"
578+ " /tmp/collect-logs --inner --juju juju"
579+ " /tmp/inner-logs.tar.gz")
580+ expected = [
581+ mock.call(["juju", "scp",
582+ os.path.join(os.path.dirname(__file__), "collect-logs"),
583+ "landscape-server/0:/tmp/collect-logs",
584+ ]),
585+ mock.call(["juju", "ssh",
586+ "landscape-server/0",
587+ "sudo rm -rf /tmp/inner-logs.tar.*",
588+ ]),
589+ mock.call(["juju", "ssh", "landscape-server/0", cmd]),
590+ mock.call(["juju", "scp",
591+ "landscape-server/0:/tmp/inner-logs.tar.gz",
592+ os.path.join(self.tempdir, "inner-logs.tar.gz"),
593 ]),
594 mock.call(["tar", "-zxf", self.tempdir + "/inner-logs.tar.gz"]),
595 ]
596@@ -368,21 +443,19 @@
597 self.units[0] = "landscape/0"
598 script.get_units.return_value = self.units[:]
599
600- script.collect_inner_logs()
601+ script.collect_inner_logs("juju")
602
603- cmd = ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/"
604- "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"
605- " juju status")
606 script.check_output.assert_called_once_with(
607- ["juju", "ssh", "landscape/0", cmd])
608+ ["juju", "ssh", "landscape/0",
609+ "sudo ls -rt /var/lib/landscape/juju-homes/"])
610 self.assert_clean()
611
612 def test_no_units(self):
613 script.get_units.return_value = []
614
615- script.collect_inner_logs()
616+ script.collect_inner_logs("juju")
617
618- script.get_units.assert_called_once_with()
619+ script.get_units.assert_called_once_with("juju")
620 script.check_output.assert_not_called()
621 script.call.assert_not_called()
622 script.check_call.assert_not_called()
623@@ -392,9 +465,23 @@
624 del self.units[0]
625 script.get_units.return_value = self.units[:]
626
627- script.collect_inner_logs()
628-
629- script.get_units.assert_called_once_with()
630+ script.collect_inner_logs("juju")
631+
632+ script.get_units.assert_called_once_with("juju")
633+ script.check_output.assert_not_called()
634+ script.call.assert_not_called()
635+ script.check_call.assert_not_called()
636+ self.assert_clean()
637+
638+ def test_no_juju_homes(self):
639+ script.get_units.return_value = []
640+ script.check_output.return_value = ""
641+
642+ script.collect_inner_logs("juju")
643+
644+ script.get_units.assert_called_once_with("juju")
645+
646+ script.get_units.assert_called_once_with("juju")
647 script.check_output.assert_not_called()
648 script.call.assert_not_called()
649 script.check_call.assert_not_called()
650@@ -404,7 +491,7 @@
651 script.get_units.side_effect = FakeError()
652
653 with self.assertRaises(FakeError):
654- script.collect_inner_logs()
655+ script.collect_inner_logs("juju")
656
657 self.assertEqual(script.get_units.call_count, 1)
658 script.check_output.assert_not_called()
659@@ -417,7 +504,7 @@
660 script.check_output.side_effect = FakeError()
661
662 with self.assertRaises(FakeError):
663- script.collect_inner_logs()
664+ script.collect_inner_logs("juju")
665
666 self.assertEqual(script.get_units.call_count, 1)
667 self.assertEqual(script.check_output.call_count, 1)
668@@ -426,11 +513,11 @@
669 self.assert_cwd(self.tempdir)
670 self.assert_clean()
671
672- def test_call_failure_1(self):
673+ def test_call_juju2_failure(self):
674 script.call.side_effect = FakeError()
675
676 with self.assertRaises(FakeError):
677- script.collect_inner_logs()
678+ script.collect_inner_logs("juju")
679
680 self.assertEqual(script.get_units.call_count, 1)
681 self.assertEqual(script.check_output.call_count, 1)
682@@ -439,13 +526,51 @@
683 self.assert_cwd(self.tempdir)
684 self.assert_clean()
685
686- def test_call_failure_2(self):
687- script.call.side_effect = [None,
688+ def test_call_juju1_failure(self):
689+ script.call.side_effect = [1,
690 FakeError(),
691 ]
692
693 with self.assertRaises(FakeError):
694- script.collect_inner_logs()
695+ script.collect_inner_logs("juju")
696+
697+ self.assertEqual(script.get_units.call_count, 1)
698+ self.assertEqual(script.check_output.call_count, 1)
699+ self.assertEqual(script.call.call_count, 2)
700+ script.check_call.assert_not_called()
701+ self.assert_cwd(self.tempdir)
702+ self.assert_clean()
703+
704+ def test_call_juju2_nonzero_return(self):
705+ script.call.side_effect = [1,
706+ mock.DEFAULT,
707+ ]
708+
709+ script.collect_inner_logs("juju")
710+
711+ self.assertEqual(script.get_units.call_count, 1)
712+ self.assertEqual(script.check_output.call_count, 1)
713+ self.assertEqual(script.call.call_count, 2)
714+ self.assertEqual(script.check_call.call_count, 5)
715+ self.assert_clean()
716+
717+ def test_call_juju1_nonzero_return(self):
718+ script.call.side_effect = [mock.DEFAULT,
719+ 1,
720+ ]
721+
722+ script.collect_inner_logs("juju")
723+
724+ self.assertEqual(script.get_units.call_count, 1)
725+ self.assertEqual(script.check_output.call_count, 1)
726+ self.assertEqual(script.call.call_count, 1)
727+ self.assertEqual(script.check_call.call_count, 5)
728+ self.assert_clean()
729+
730+ def test_call_all_nonzero_return(self):
731+ script.call.return_value = 1
732+
733+ script.collect_inner_logs("juju")
734
735 self.assertEqual(script.get_units.call_count, 1)
736 self.assertEqual(script.check_output.call_count, 1)
737@@ -457,11 +582,11 @@
738 script.check_call.side_effect = FakeError()
739
740 with self.assertRaises(FakeError):
741- script.collect_inner_logs()
742+ script.collect_inner_logs("juju")
743
744 self.assertEqual(script.get_units.call_count, 1)
745 self.assertEqual(script.check_output.call_count, 1)
746- self.assertEqual(script.call.call_count, 2)
747+ self.assertEqual(script.call.call_count, 1)
748 self.assertEqual(script.check_call.call_count, 1)
749 self.assert_clean()
750
751@@ -471,31 +596,62 @@
752 ]
753
754 with self.assertRaises(FakeError):
755- script.collect_inner_logs()
756+ script.collect_inner_logs("juju")
757
758 self.assertEqual(script.get_units.call_count, 1)
759 self.assertEqual(script.check_output.call_count, 1)
760- self.assertEqual(script.call.call_count, 2)
761+ self.assertEqual(script.call.call_count, 1)
762 self.assertEqual(script.check_call.call_count, 2)
763 self.assert_clean()
764
765 def test_check_call_failure_3(self):
766+ script.check_call.side_effect = [None,
767+ None,
768+ FakeError(),
769+ ]
770+
771+ with self.assertRaises(FakeError):
772+ script.collect_inner_logs("juju")
773+
774+ self.assertEqual(script.get_units.call_count, 1)
775+ self.assertEqual(script.check_output.call_count, 1)
776+ self.assertEqual(script.call.call_count, 1)
777+ self.assertEqual(script.check_call.call_count, 3)
778+ self.assert_clean()
779+
780+ def test_check_call_failure_4(self):
781+ script.check_call.side_effect = [None,
782+ None,
783+ None,
784+ FakeError(),
785+ ]
786+
787+ with self.assertRaises(FakeError):
788+ script.collect_inner_logs("juju")
789+
790+ self.assertEqual(script.get_units.call_count, 1)
791+ self.assertEqual(script.check_output.call_count, 1)
792+ self.assertEqual(script.call.call_count, 1)
793+ self.assertEqual(script.check_call.call_count, 4)
794+ self.assert_clean()
795+
796+ def test_check_call_failure_5(self):
797 def check_call_side_effect(cmd):
798- if script.check_call.call_count == 1:
799+ if script.check_call.call_count in (1, 2, 3):
800 return None
801- if script.check_call.call_count == 2:
802+ if script.check_call.call_count == 4:
803 self._touch_tempfile("inner-logs.tar.gz")
804 return None
805 raise FakeError()
806 script.check_call.side_effect = check_call_side_effect
807
808 with self.assertRaises(FakeError):
809- script.collect_inner_logs()
810+ script.collect_inner_logs("juju")
811
812 self.assertEqual(script.get_units.call_count, 1)
813 self.assertEqual(script.check_output.call_count, 1)
814- self.assertEqual(script.call.call_count, 2)
815- self.assertEqual(script.check_call.call_count, 3)
816+ self.assertEqual(script.call.call_count, 1)
817+ self.assertEqual(script.check_call.call_count, 5)
818 self.assert_clean()
819
820

Subscribers

People subscribed via source and target branches

to all changes: