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
=== modified file 'collect-logs'
--- collect-logs 2016-08-17 14:14:30 +0000
+++ collect-logs 2016-08-17 14:14:30 +0000
@@ -2,6 +2,7 @@
22
3from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter3from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
4import errno4import errno
5import functools
5import logging6import logging
6import multiprocessing7import multiprocessing
7import os8import os
@@ -25,16 +26,24 @@
25 "/var/lib/juju/containers/juju-*-lxc-template"]26 "/var/lib/juju/containers/juju-*-lxc-template"]
26LANDSCAPE_JUJU_HOME = "/var/lib/landscape/juju-homes"27LANDSCAPE_JUJU_HOME = "/var/lib/landscape/juju-homes"
2728
2829JUJU1 = "juju"
29def juju_status():30# XXX This is going to break once juju-2.1 happens.
31# See https://bugs.launchpad.net/juju-core/+bug/1613864.
32JUJU2 = "juju-2.0"
33JUJU = JUJU1
34
35
36def juju_status(juju):
30 """Return a juju status structure."""37 """Return a juju status structure."""
31 cmd = ["juju", "status", "--format=yaml"]38 cmd = [juju, "status", "--format=yaml"]
32 output = check_output(cmd).decode("utf-8").strip()39 output = check_output(cmd).decode("utf-8").strip()
33 return yaml.load(output)40 return yaml.load(output)
3441
3542
36def get_units(status=juju_status()):43def get_units(juju, status=None):
37 """Return a list with all units."""44 """Return a list with all units."""
45 if status is None:
46 status = juju_status(juju)
38 units = []47 units = []
39 if "services" in status:48 if "services" in status:
40 applications = status["services"]49 applications = status["services"]
@@ -52,12 +61,12 @@
52 return units61 return units
5362
5463
55def _create_ps_output_file(unit):64def _create_ps_output_file(juju, unit):
56 """List running processes and redirect them to a file."""65 """List running processes and redirect them to a file."""
57 ps_cmd = "ps fauxww | sudo tee /var/log/ps-fauxww.txt"66 ps_cmd = "ps fauxww | sudo tee /var/log/ps-fauxww.txt"
58 try:67 try:
59 log.info("Collecting ps output on unit {}".format(unit))68 log.info("Collecting ps output on unit {}".format(unit))
60 check_output(["juju", "ssh", unit, ps_cmd], stderr=STDOUT)69 check_output([juju, "ssh", unit, ps_cmd], stderr=STDOUT)
61 except CalledProcessError as e:70 except CalledProcessError as e:
62 log.warning(71 log.warning(
63 "Failed to collect running processes on unit {}".format(unit))72 "Failed to collect running processes on unit {}".format(unit))
@@ -65,7 +74,7 @@
65 log.warning(e.returncode)74 log.warning(e.returncode)
6675
6776
68def _create_log_tarball(unit):77def _create_log_tarball(juju, unit):
69 exclude = " ".join(["--exclude=%s" % x for x in EXCLUDED])78 exclude = " ".join(["--exclude=%s" % x for x in EXCLUDED])
70 logs = "$(sudo sh -c \"ls -1d %s 2>/dev/null\")" % " ".join(LOGS)79 logs = "$(sudo sh -c \"ls -1d %s 2>/dev/null\")" % " ".join(LOGS)
71 # note, tar commands can fail since we are backing up log files80 # note, tar commands can fail since we are backing up log files
@@ -80,7 +89,7 @@
80 tar_cmd, exclude, logsuffix, logs)89 tar_cmd, exclude, logsuffix, logs)
81 try:90 try:
82 log.info("Creating tarball on unit {}".format(unit))91 log.info("Creating tarball on unit {}".format(unit))
83 check_output(["juju", "ssh", unit, cmd], stderr=STDOUT)92 check_output([juju, "ssh", unit, cmd], stderr=STDOUT)
84 except CalledProcessError as e:93 except CalledProcessError as e:
85 log.warning(94 log.warning(
86 "Failed to create remote log tarball on unit {}".format(unit))95 "Failed to create remote log tarball on unit {}".format(unit))
@@ -88,7 +97,7 @@
88 log.warning(e.returncode)97 log.warning(e.returncode)
8998
9099
91def collect_logs():100def collect_logs(juju=JUJU):
92 """101 """
93 Remotely, on each unit, create a tarball with the requested log files102 Remotely, on each unit, create a tarball with the requested log files
94 or directories, if they exist. If a requested log does not exist on a103 or directories, if they exist. If a requested log does not exist on a
@@ -96,19 +105,19 @@
96 After each tarball is created, it's downloaded to the current directory105 After each tarball is created, it's downloaded to the current directory
97 and expanded, and the tarball is then deleted.106 and expanded, and the tarball is then deleted.
98 """107 """
99 units = get_units()108 units = get_units(juju)
100 # include bootstrap109 # include bootstrap
101 units.append("0")110 units.append("0")
102111
103 log.info("Collecting running processes for all units including bootstrap")112 log.info("Collecting running processes for all units including bootstrap")
104 map(_create_ps_output_file, units)113 map((lambda u: _create_ps_output_file(juju, u)), units)
105114
106 log.info("Creating remote tarball in parallel for units %s" % (115 log.info("Creating remote tarball in parallel for units %s" % (
107 ",".join(units)))116 ",".join(units)))
108 map(_create_log_tarball, units)117 map((lambda u: _create_log_tarball(juju, u)), units)
109 log.info("Downloading logs from units")118 log.info("Downloading logs from units")
110119
111 _mp_map(download_log_from_unit, units)120 _mp_map(functools.partial(download_log_from_unit, juju), units)
112121
113122
114def _mp_map(func, args):123def _mp_map(func, args):
@@ -129,6 +138,7 @@
129 return units[0]138 return units[0]
130139
131140
141<<<<<<< TREE
132def disable_ssh_proxy(landscape_unit):142def disable_ssh_proxy(landscape_unit):
133 """143 """
134 Workaround for #1607076: disable the proxy-ssh juju environment setting144 Workaround for #1607076: disable the proxy-ssh juju environment setting
@@ -148,77 +158,117 @@
148 log.warning("Error was:\n{}".format(e.output))158 log.warning("Error was:\n{}".format(e.output))
149159
150def collect_inner_logs():160def collect_inner_logs():
161=======
162def find_inner_juju(juju, landscape_unit):
163 """Return the juju dir and binary path, if any."""
164 # Identify the most recent juju "home" that landscape is using.
165 cmd = "sudo ls -rt {}/".format(LANDSCAPE_JUJU_HOME)
166 try:
167 output = check_output(["juju", "ssh", landscape_unit, cmd]).strip()
168 except CalledProcessError:
169 return None, None
170 if output.startswith("sudo: "):
171 _, _, output = output.partition("\r\n")
172 models = [m for m in output.split() if m and m.isdigit()]
173 if not models:
174 return None, None
175 model = models[-1]
176 juju_dir = os.path.join(LANDSCAPE_JUJU_HOME, model)
177
178 # Try Juju 2.
179 juju_env = "JUJU_DATA={}".format(juju_dir)
180 cmd = "sudo {} {} status".format(juju_env, JUJU2)
181 if call([juju, "ssh", landscape_unit, cmd]) == 0:
182 log.info("using Juju 2 for inner model")
183 return juju_env, JUJU2
184
185 # Try Juju 1.
186 juju_env = "JUJU_HOME={}".format(juju_dir)
187 cmd = "sudo {} {} status".format(juju_env, JUJU1)
188 if call([juju, "ssh", landscape_unit, cmd]) == 0:
189 log.info("using Juju 1 for inner model")
190 return juju_env, JUJU1
191
192 # We didn't find an inner model.
193 return None, None
194
195
196def collect_inner_logs(juju=JUJU):
197>>>>>>> MERGE-SOURCE
151 """Collect logs from an inner landscape[-server]/0 unit."""198 """Collect logs from an inner landscape[-server]/0 unit."""
152 units = get_units()199 units = get_units(juju)
153 landscape_unit = get_landscape_unit(units)200 landscape_unit = get_landscape_unit(units)
154 if not landscape_unit:201 if not landscape_unit:
155 log.info("No landscape[-server]/N found, skipping")202 log.info("No landscape[-server]/N found, skipping")
156 return203 return
157 log.info("Found landscape unit %s" % landscape_unit)204 log.info("Found landscape unit {}".format(landscape_unit))
158205
159 # Make sure that there *is* an inner model.206 # Look up the inner model.
160 poke_inner_env = (207 juju_env, inner_juju = find_inner_juju(juju, landscape_unit)
161 "sudo JUJU_HOME=%s/`sudo ls -rt %s/ | tail -1` juju status" %208 if inner_juju is None:
162 (LANDSCAPE_JUJU_HOME, LANDSCAPE_JUJU_HOME))209 log.info(("No active inner environment found on {}, skipping"
163 try:210 ).format(landscape_unit))
164 check_output(["juju", "ssh", landscape_unit, poke_inner_env])
165 except CalledProcessError:
166 log.info("No active inner environment found on %s, skipping" %
167 landscape_unit)
168 return211 return
169<<<<<<< TREE212<<<<<<< TREE
170 disable_ssh_proxy(landscape_unit)213 disable_ssh_proxy(landscape_unit)
214 call(["juju", "scp", PRG, "%s:%s" % (landscape_unit, collect_logs)])
215 call(["juju", "ssh", landscape_unit, "sudo rm -rf /tmp/inner-logs.tar.*"])
216 log.info("Collecting Logs on inner environment")
217 check_call(
218 ["juju", "ssh", landscape_unit, "sudo -u landscape %s" % collect_run])
171=======219=======
172220
173 # Prepare to get the logs from the inner model.221 # Prepare to get the logs from the inner model.
174 collect_logs = "/tmp/collect-logs"222 collect_logs = "/tmp/collect-logs"
175>>>>>>> MERGE-SOURCE223 tarball = "/tmp/inner-logs.tar.gz"
176 call(["juju", "scp", PRG, "%s:%s" % (landscape_unit, collect_logs)])224 check_call([juju, "scp",
177 call(["juju", "ssh", landscape_unit, "sudo rm -rf /tmp/inner-logs.tar.*"])225 PRG,
226 "{}:{}".format(landscape_unit, collect_logs)])
227 check_call([juju, "ssh", landscape_unit,
228 "sudo rm -rf /tmp/inner-logs.tar.*"])
178229
179 # Collect the logs for the inner model.230 # Collect the logs for the inner model.
180 log.info("Collecting Logs on inner environment")231 log.info("Collecting logs on inner environment")
181 collect_run = (232 cmd = ("{} {} --inner --juju {} {}"
182 "JUJU_HOME=%s/`sudo ls -rt %s/ | tail -1`"233 ).format(juju_env, collect_logs, inner_juju, tarball)
183 " %s /tmp/inner-logs.tar.gz" % (234 check_call([juju, "ssh",
184 LANDSCAPE_JUJU_HOME, LANDSCAPE_JUJU_HOME, collect_logs))
185 check_call(["juju", "ssh",
186 landscape_unit,235 landscape_unit,
187 "sudo -u landscape %s" % collect_run,236 "sudo -u landscape {}".format(cmd),
188 ])237 ])
189238
190 # Copy the inner logs into a local directory.239 # Copy the inner logs into a local directory.
240>>>>>>> MERGE-SOURCE
191 log.info("Copying inner environment back")241 log.info("Copying inner environment back")
242 source = "{}:{}".format(landscape_unit, tarball)
243 cwd = os.getcwd()
244 target = os.path.join(cwd, os.path.basename(tarball))
192 try:245 try:
193 check_call(["juju", "scp",246 check_call([juju, "scp", source, target])
194 "%s:/tmp/inner-logs.tar.gz" % landscape_unit,247
195 ".",
196 ])
197 cwd = os.getcwd()
198 inner_dir = "landscape-0-inner-logs"248 inner_dir = "landscape-0-inner-logs"
199 os.mkdir(inner_dir)249 os.mkdir(inner_dir)
200 os.chdir(inner_dir)250 os.chdir(inner_dir)
201 try:251 try:
202 check_call(["tar", "-zxf", "%s/inner-logs.tar.gz" % cwd])252 check_call(["tar", "-zxf", target])
203 finally:253 finally:
204 os.chdir(cwd)254 os.chdir(cwd)
205 finally:255 finally:
206 try:256 try:
207 os.remove("inner-logs.tar.gz")257 os.remove(target)
208 except OSError as e:258 except OSError as e:
209 if e.errno != errno.ENOENT:259 if e.errno != errno.ENOENT:
210 log.warning(260 log.warning(
211 "failed to remove inner logs tarball: {}".format(err))261 "failed to remove inner logs tarball: {}".format(e))
212262
213263
214def download_log_from_unit(unit):264def download_log_from_unit(juju, unit):
215 log.info("Downloading tarball from unit %s" % unit)265 log.info("Downloading tarball from unit %s" % unit)
216 unit_filename = unit.replace("/", "-")266 unit_filename = unit.replace("/", "-")
217 if unit == "0":267 if unit == "0":
218 unit_filename = "bootstrap"268 unit_filename = "bootstrap"
219 try:269 try:
220 remote_filename = "logs_%s.tar.gz" % unit_filename270 remote_filename = "logs_%s.tar.gz" % unit_filename
221 call(["juju", "scp", "%s:/tmp/%s" % (unit, remote_filename), "."])271 call([juju, "scp", "%s:/tmp/%s" % (unit, remote_filename), "."])
222 os.mkdir(unit_filename)272 os.mkdir(unit_filename)
223 call(["tar", "-C", unit_filename, "-xzf", remote_filename])273 call(["tar", "-C", unit_filename, "-xzf", remote_filename])
224 os.unlink(remote_filename)274 os.unlink(remote_filename)
@@ -267,13 +317,17 @@
267 "inner autopilot cloud is detected, include that.")317 "inner autopilot cloud is detected, include that.")
268 parser = ArgumentParser(description=description,318 parser = ArgumentParser(description=description,
269 formatter_class=ArgumentDefaultsHelpFormatter)319 formatter_class=ArgumentDefaultsHelpFormatter)
320 parser.add_argument("--inner", action="store_true", default=False,
321 help="Collect logs for an inner model.")
322 parser.add_argument("--juju", default=JUJU,
323 help="The Juju binary to use.")
270 parser.add_argument("tarfile", help="Full path to tarfile to create.")324 parser.add_argument("tarfile", help="Full path to tarfile to create.")
271 parser.add_argument("extrafiles", help="Optional full path to extra "325 parser.add_argument("extrafiles", help="Optional full path to extra "
272 "logfiles to include, space separated", nargs="*")326 "logfiles to include, space separated", nargs="*")
273 return parser327 return parser
274328
275329
276def main(tarfile, extrafiles):330def main(tarfile, extrafiles, juju=JUJU, inner=False):
277 # we need the absolute path because we will be changing331 # we need the absolute path because we will be changing
278 # the cwd332 # the cwd
279 tmpdir = mkdtemp()333 tmpdir = mkdtemp()
@@ -281,11 +335,12 @@
281 # logs are collected inside a temporary directory335 # logs are collected inside a temporary directory
282 os.chdir(tmpdir)336 os.chdir(tmpdir)
283 try:337 try:
284 collect_logs()338 collect_logs(juju)
285 try:339 if not inner:
286 collect_inner_logs()340 try:
287 except:341 collect_inner_logs(juju)
288 log.warning("Collecting inner logs failed, continuing")342 except:
343 log.warning("Collecting inner logs failed, continuing")
289 # we create the final tarball outside of tmpdir to we can344 # we create the final tarball outside of tmpdir to we can
290 # add the extrafiles to the tarball root345 # add the extrafiles to the tarball root
291 os.chdir(cwd)346 os.chdir(cwd)
@@ -302,4 +357,4 @@
302 parser = get_option_parser()357 parser = get_option_parser()
303 args = parser.parse_args(sys.argv[1:])358 args = parser.parse_args(sys.argv[1:])
304 tarfile = os.path.abspath(args.tarfile)359 tarfile = os.path.abspath(args.tarfile)
305 main(tarfile, args.extrafiles)360 main(tarfile, args.extrafiles, args.juju, args.inner)
306361
=== modified file 'test_collect-logs.py'
--- test_collect-logs.py 2016-08-17 14:14:30 +0000
+++ test_collect-logs.py 2016-08-17 14:14:30 +0000
@@ -92,22 +92,35 @@
9292
93 script.main(tarfile, extrafiles)93 script.main(tarfile, extrafiles)
9494
95 script.collect_logs.assert_called_once_with()95 script.collect_logs.assert_called_once_with("juju")
96 script.collect_inner_logs.assert_called_once_with()96 script.collect_inner_logs.assert_called_once_with("juju")
97 script.bundle_logs.assert_called_once_with(97 script.bundle_logs.assert_called_once_with(
98 self.tempdir, tarfile, extrafiles)98 self.tempdir, tarfile, extrafiles)
99 self.assertFalse(os.path.exists(self.tempdir))99 self.assertFalse(os.path.exists(self.tempdir))
100100
101 def test_in_correct_directories(self):101 def test_in_correct_directories(self):
102 script.collect_logs.side_effect = lambda: self.assert_cwd(self.tempdir)102 script.collect_logs.side_effect = (
103 lambda _: self.assert_cwd(self.tempdir))
103 script.collect_inner_logs.side_effect = (104 script.collect_inner_logs.side_effect = (
104 lambda: self.assert_cwd(self.tempdir))105 lambda _: self.assert_cwd(self.tempdir))
105 script.bundle_logs.side_effect = lambda *a: self.assert_cwd(self.cwd)106 script.bundle_logs.side_effect = lambda *a: self.assert_cwd(self.cwd)
106 tarfile = "/tmp/logs.tgz"107 tarfile = "/tmp/logs.tgz"
107 extrafiles = ["spam.py"]108 extrafiles = ["spam.py"]
108109
109 script.main(tarfile, extrafiles)110 script.main(tarfile, extrafiles)
110111
112 def test_inner(self):
113 tarfile = "/tmp/logs.tgz"
114 extrafiles = ["spam.py"]
115
116 script.main(tarfile, extrafiles, inner=True)
117
118 script.collect_logs.assert_called_once_with("juju")
119 script.collect_inner_logs.assert_not_called()
120 script.bundle_logs.assert_called_once_with(
121 self.tempdir, tarfile, extrafiles)
122 self.assertFalse(os.path.exists(self.tempdir))
123
111 def test_cleanup(self):124 def test_cleanup(self):
112 tarfile = "/tmp/logs.tgz"125 tarfile = "/tmp/logs.tgz"
113 extrafiles = ["spam.py"]126 extrafiles = ["spam.py"]
@@ -124,7 +137,7 @@
124 with self.assertRaises(FakeError):137 with self.assertRaises(FakeError):
125 script.main(tarfile, extrafiles)138 script.main(tarfile, extrafiles)
126139
127 script.collect_logs.assert_called_once_with()140 script.collect_logs.assert_called_once_with("juju")
128 script.collect_inner_logs.assert_not_called()141 script.collect_inner_logs.assert_not_called()
129 script.bundle_logs.assert_not_called()142 script.bundle_logs.assert_not_called()
130 self.assertFalse(os.path.exists(self.tempdir))143 self.assertFalse(os.path.exists(self.tempdir))
@@ -136,8 +149,8 @@
136149
137 script.main(tarfile, extrafiles)150 script.main(tarfile, extrafiles)
138151
139 script.collect_logs.assert_called_once_with()152 script.collect_logs.assert_called_once_with("juju")
140 script.collect_inner_logs.assert_called_once_with()153 script.collect_inner_logs.assert_called_once_with("juju")
141 script.bundle_logs.assert_called_once_with(154 script.bundle_logs.assert_called_once_with(
142 self.tempdir, tarfile, extrafiles)155 self.tempdir, tarfile, extrafiles)
143 self.assertFalse(os.path.exists(self.tempdir))156 self.assertFalse(os.path.exists(self.tempdir))
@@ -150,8 +163,8 @@
150 with self.assertRaises(FakeError):163 with self.assertRaises(FakeError):
151 script.main(tarfile, extrafiles)164 script.main(tarfile, extrafiles)
152165
153 script.collect_logs.assert_called_once_with()166 script.collect_logs.assert_called_once_with("juju")
154 script.collect_inner_logs.assert_called_once_with()167 script.collect_inner_logs.assert_called_once_with("juju")
155 script.bundle_logs.assert_called_once_with(168 script.bundle_logs.assert_called_once_with(
156 self.tempdir, tarfile, extrafiles)169 self.tempdir, tarfile, extrafiles)
157 self.assertFalse(os.path.exists(self.tempdir))170 self.assertFalse(os.path.exists(self.tempdir))
@@ -192,9 +205,9 @@
192 def test_success(self):205 def test_success(self):
193 script.call.side_effect = self._call_side_effect206 script.call.side_effect = self._call_side_effect
194207
195 script.collect_logs()208 script.collect_logs("juju")
196209
197 script.get_units.assert_called_once_with()210 script.get_units.assert_called_once_with("juju")
198 expected = []211 expected = []
199 units = self.units + ["0"]212 units = self.units + ["0"]
200 # for _create_ps_output_file()213 # for _create_ps_output_file()
@@ -246,9 +259,9 @@
246 script.get_units.side_effect = FakeError()259 script.get_units.side_effect = FakeError()
247260
248 with self.assertRaises(FakeError):261 with self.assertRaises(FakeError):
249 script.collect_logs()262 script.collect_logs("juju")
250263
251 script.get_units.assert_called_once_with()264 script.get_units.assert_called_once_with("juju")
252 script.check_output.assert_not_called()265 script.check_output.assert_not_called()
253 script.call.assert_not_called()266 script.call.assert_not_called()
254267
@@ -258,9 +271,9 @@
258 ]271 ]
259272
260 with self.assertRaises(FakeError):273 with self.assertRaises(FakeError):
261 script.collect_logs()274 script.collect_logs("juju")
262275
263 script.get_units.assert_called_once_with()276 script.get_units.assert_called_once_with("juju")
264 self.assertEqual(script.check_output.call_count, 2)277 self.assertEqual(script.check_output.call_count, 2)
265 script.call.assert_not_called()278 script.call.assert_not_called()
266279
@@ -276,9 +289,9 @@
276 return self._call_side_effect(cmd)289 return self._call_side_effect(cmd)
277 script.call.side_effect = call_side_effect290 script.call.side_effect = call_side_effect
278291
279 script.collect_logs()292 script.collect_logs("juju")
280293
281 script.get_units.assert_called_once_with()294 script.get_units.assert_called_once_with("juju")
282 units = self.units + ["0"]295 units = self.units + ["0"]
283 self.assertEqual(script.check_output.call_count, len(units) * 2)296 self.assertEqual(script.check_output.call_count, len(units) * 2)
284 self.assertEqual(script.call.call_count, len(units) * 2 - 1)297 self.assertEqual(script.call.call_count, len(units) * 2 - 1)
@@ -306,6 +319,8 @@
306 "haproxy/0",319 "haproxy/0",
307 ]320 ]
308 script.get_units.return_value = self.units[:]321 script.get_units.return_value = self.units[:]
322 script.check_output.return_value = "0\n"
323 script.call.return_value = 0
309324
310 os.chdir(self.tempdir)325 os.chdir(self.tempdir)
311326
@@ -313,50 +328,110 @@
313 self.assert_cwd(self.tempdir)328 self.assert_cwd(self.tempdir)
314 self.assertFalse(os.path.exists("inner-logs.tar.gz"))329 self.assertFalse(os.path.exists("inner-logs.tar.gz"))
315330
316 def test_success(self):331 def test_juju_2(self):
317 def check_call_side_effect(cmd):332 def check_call_side_effect(cmd):
318 if script.check_call.call_count == 2:333 if script.check_call.call_count == 4:
319 self.assert_cwd(self.tempdir)334 self.assert_cwd(self.tempdir)
320 self._touch_tempfile("inner-logs.tar.gz")335 self._touch_tempfile("inner-logs.tar.gz")
321 elif script.check_call.call_count == 3:336 elif script.check_call.call_count == 5:
322 cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")337 cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")
323 self.assert_cwd(cwd)338 self.assert_cwd(cwd)
324 return None339 return None
325 script.check_call.side_effect = check_call_side_effect340 script.check_call.side_effect = check_call_side_effect
326341
327 script.collect_inner_logs()342 script.collect_inner_logs("juju")
328343
329 # get_units()344 # get_units()
330 script.get_units.assert_called_once_with()345 script.get_units.assert_called_once_with("juju")
331 # check_output()346 # check_output()
332 cmd = ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/"347 script.check_output.assert_called_once_with(
333 "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"348 ["juju", "ssh", "landscape-server/0",
334 " juju status")349 "sudo ls -rt /var/lib/landscape/juju-homes/"])
335 script.check_output.assert_called_once_with(350 # call()
336 ["juju", "ssh", "landscape-server/0", cmd])351 expected = [
337 # call()352 mock.call(["juju", "ssh", "landscape-server/0",
338 expected = [353 ("sudo JUJU_DATA=/var/lib/landscape/juju-homes/0 "
339 mock.call(["juju", "scp",354 "juju-2.0 status"),
340 os.path.join(os.path.dirname(__file__), "collect-logs"),355 ]),
341 "landscape-server/0:/tmp/collect-logs",356 ]
342 ]),357 self.assertEqual(script.call.call_count, len(expected))
343 mock.call(["juju", "ssh",358 script.call.assert_has_calls(expected, any_order=True)
344 "landscape-server/0",359 # check_call()
345 "sudo rm -rf /tmp/inner-logs.tar.*",360 cmd = ("sudo -u landscape"
346 ]),361 " JUJU_DATA=/var/lib/landscape/juju-homes/0"
347 ]362 " /tmp/collect-logs --inner --juju juju-2.0"
348 self.assertEqual(script.call.call_count, len(expected))363 " /tmp/inner-logs.tar.gz")
349 script.call.assert_has_calls(expected, any_order=True)364 expected = [
350 # check_call()365 mock.call(["juju", "scp",
351 cmd = ("sudo -u landscape"366 os.path.join(os.path.dirname(__file__), "collect-logs"),
352 " JUJU_HOME=/var/lib/landscape/juju-homes/"367 "landscape-server/0:/tmp/collect-logs",
353 "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"368 ]),
354 " /tmp/collect-logs /tmp/inner-logs.tar.gz")369 mock.call(["juju", "ssh",
355 expected = [370 "landscape-server/0",
356 mock.call(["juju", "ssh", "landscape-server/0", cmd]),371 "sudo rm -rf /tmp/inner-logs.tar.*",
357 mock.call(["juju", "scp",372 ]),
358 "landscape-server/0:/tmp/inner-logs.tar.gz",373 mock.call(["juju", "ssh", "landscape-server/0", cmd]),
359 ".",374 mock.call(["juju", "scp",
375 "landscape-server/0:/tmp/inner-logs.tar.gz",
376 os.path.join(self.tempdir, "inner-logs.tar.gz"),
377 ]),
378 mock.call(["tar", "-zxf", self.tempdir + "/inner-logs.tar.gz"]),
379 ]
380 self.assertEqual(script.check_call.call_count, len(expected))
381 script.check_call.assert_has_calls(expected, any_order=True)
382 self.assert_clean()
383
384 def test_juju_1(self):
385 def check_call_side_effect(cmd):
386 if script.check_call.call_count == 4:
387 self.assert_cwd(self.tempdir)
388 self._touch_tempfile("inner-logs.tar.gz")
389 elif script.check_call.call_count == 5:
390 cwd = os.path.join(self.tempdir, "landscape-0-inner-logs")
391 self.assert_cwd(cwd)
392 return None
393 script.check_call.side_effect = check_call_side_effect
394 script.call.side_effect = [1, 0]
395
396 script.collect_inner_logs("juju")
397
398 # get_units()
399 script.get_units.assert_called_once_with("juju")
400 # check_output()
401 script.check_output.assert_called_once_with(
402 ["juju", "ssh", "landscape-server/0",
403 "sudo ls -rt /var/lib/landscape/juju-homes/"])
404 # call()
405 expected = [
406 mock.call(["juju", "ssh", "landscape-server/0",
407 ("sudo JUJU_DATA=/var/lib/landscape/juju-homes/0 "
408 "juju-2.0 status"),
409 ]),
410 mock.call(["juju", "ssh", "landscape-server/0",
411 ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/0 "
412 "juju status"),
413 ]),
414 ]
415 self.assertEqual(script.call.call_count, len(expected))
416 script.call.assert_has_calls(expected, any_order=True)
417 # check_call()
418 cmd = ("sudo -u landscape"
419 " JUJU_HOME=/var/lib/landscape/juju-homes/0"
420 " /tmp/collect-logs --inner --juju juju"
421 " /tmp/inner-logs.tar.gz")
422 expected = [
423 mock.call(["juju", "scp",
424 os.path.join(os.path.dirname(__file__), "collect-logs"),
425 "landscape-server/0:/tmp/collect-logs",
426 ]),
427 mock.call(["juju", "ssh",
428 "landscape-server/0",
429 "sudo rm -rf /tmp/inner-logs.tar.*",
430 ]),
431 mock.call(["juju", "ssh", "landscape-server/0", cmd]),
432 mock.call(["juju", "scp",
433 "landscape-server/0:/tmp/inner-logs.tar.gz",
434 os.path.join(self.tempdir, "inner-logs.tar.gz"),
360 ]),435 ]),
361 mock.call(["tar", "-zxf", self.tempdir + "/inner-logs.tar.gz"]),436 mock.call(["tar", "-zxf", self.tempdir + "/inner-logs.tar.gz"]),
362 ]437 ]
@@ -368,21 +443,19 @@
368 self.units[0] = "landscape/0"443 self.units[0] = "landscape/0"
369 script.get_units.return_value = self.units[:]444 script.get_units.return_value = self.units[:]
370445
371 script.collect_inner_logs()446 script.collect_inner_logs("juju")
372447
373 cmd = ("sudo JUJU_HOME=/var/lib/landscape/juju-homes/"
374 "`sudo ls -rt /var/lib/landscape/juju-homes/ | tail -1`"
375 " juju status")
376 script.check_output.assert_called_once_with(448 script.check_output.assert_called_once_with(
377 ["juju", "ssh", "landscape/0", cmd])449 ["juju", "ssh", "landscape/0",
450 "sudo ls -rt /var/lib/landscape/juju-homes/"])
378 self.assert_clean()451 self.assert_clean()
379452
380 def test_no_units(self):453 def test_no_units(self):
381 script.get_units.return_value = []454 script.get_units.return_value = []
382455
383 script.collect_inner_logs()456 script.collect_inner_logs("juju")
384457
385 script.get_units.assert_called_once_with()458 script.get_units.assert_called_once_with("juju")
386 script.check_output.assert_not_called()459 script.check_output.assert_not_called()
387 script.call.assert_not_called()460 script.call.assert_not_called()
388 script.check_call.assert_not_called()461 script.check_call.assert_not_called()
@@ -392,9 +465,23 @@
392 del self.units[0]465 del self.units[0]
393 script.get_units.return_value = self.units[:]466 script.get_units.return_value = self.units[:]
394467
395 script.collect_inner_logs()468 script.collect_inner_logs("juju")
396469
397 script.get_units.assert_called_once_with()470 script.get_units.assert_called_once_with("juju")
471 script.check_output.assert_not_called()
472 script.call.assert_not_called()
473 script.check_call.assert_not_called()
474 self.assert_clean()
475
476 def test_no_juju_homes(self):
477 script.get_units.return_value = []
478 script.check_output.return_value = ""
479
480 script.collect_inner_logs("juju")
481
482 script.get_units.assert_called_once_with("juju")
483
484 script.get_units.assert_called_once_with("juju")
398 script.check_output.assert_not_called()485 script.check_output.assert_not_called()
399 script.call.assert_not_called()486 script.call.assert_not_called()
400 script.check_call.assert_not_called()487 script.check_call.assert_not_called()
@@ -404,7 +491,7 @@
404 script.get_units.side_effect = FakeError()491 script.get_units.side_effect = FakeError()
405492
406 with self.assertRaises(FakeError):493 with self.assertRaises(FakeError):
407 script.collect_inner_logs()494 script.collect_inner_logs("juju")
408495
409 self.assertEqual(script.get_units.call_count, 1)496 self.assertEqual(script.get_units.call_count, 1)
410 script.check_output.assert_not_called()497 script.check_output.assert_not_called()
@@ -417,7 +504,7 @@
417 script.check_output.side_effect = FakeError()504 script.check_output.side_effect = FakeError()
418505
419 with self.assertRaises(FakeError):506 with self.assertRaises(FakeError):
420 script.collect_inner_logs()507 script.collect_inner_logs("juju")
421508
422 self.assertEqual(script.get_units.call_count, 1)509 self.assertEqual(script.get_units.call_count, 1)
423 self.assertEqual(script.check_output.call_count, 1)510 self.assertEqual(script.check_output.call_count, 1)
@@ -426,11 +513,11 @@
426 self.assert_cwd(self.tempdir)513 self.assert_cwd(self.tempdir)
427 self.assert_clean()514 self.assert_clean()
428515
429 def test_call_failure_1(self):516 def test_call_juju2_failure(self):
430 script.call.side_effect = FakeError()517 script.call.side_effect = FakeError()
431518
432 with self.assertRaises(FakeError):519 with self.assertRaises(FakeError):
433 script.collect_inner_logs()520 script.collect_inner_logs("juju")
434521
435 self.assertEqual(script.get_units.call_count, 1)522 self.assertEqual(script.get_units.call_count, 1)
436 self.assertEqual(script.check_output.call_count, 1)523 self.assertEqual(script.check_output.call_count, 1)
@@ -439,13 +526,51 @@
439 self.assert_cwd(self.tempdir)526 self.assert_cwd(self.tempdir)
440 self.assert_clean()527 self.assert_clean()
441528
442 def test_call_failure_2(self):529 def test_call_juju1_failure(self):
443 script.call.side_effect = [None,530 script.call.side_effect = [1,
444 FakeError(),531 FakeError(),
445 ]532 ]
446533
447 with self.assertRaises(FakeError):534 with self.assertRaises(FakeError):
448 script.collect_inner_logs()535 script.collect_inner_logs("juju")
536
537 self.assertEqual(script.get_units.call_count, 1)
538 self.assertEqual(script.check_output.call_count, 1)
539 self.assertEqual(script.call.call_count, 2)
540 script.check_call.assert_not_called()
541 self.assert_cwd(self.tempdir)
542 self.assert_clean()
543
544 def test_call_juju2_nonzero_return(self):
545 script.call.side_effect = [1,
546 mock.DEFAULT,
547 ]
548
549 script.collect_inner_logs("juju")
550
551 self.assertEqual(script.get_units.call_count, 1)
552 self.assertEqual(script.check_output.call_count, 1)
553 self.assertEqual(script.call.call_count, 2)
554 self.assertEqual(script.check_call.call_count, 5)
555 self.assert_clean()
556
557 def test_call_juju1_nonzero_return(self):
558 script.call.side_effect = [mock.DEFAULT,
559 1,
560 ]
561
562 script.collect_inner_logs("juju")
563
564 self.assertEqual(script.get_units.call_count, 1)
565 self.assertEqual(script.check_output.call_count, 1)
566 self.assertEqual(script.call.call_count, 1)
567 self.assertEqual(script.check_call.call_count, 5)
568 self.assert_clean()
569
570 def test_call_all_nonzero_return(self):
571 script.call.return_value = 1
572
573 script.collect_inner_logs("juju")
449574
450 self.assertEqual(script.get_units.call_count, 1)575 self.assertEqual(script.get_units.call_count, 1)
451 self.assertEqual(script.check_output.call_count, 1)576 self.assertEqual(script.check_output.call_count, 1)
@@ -457,11 +582,11 @@
457 script.check_call.side_effect = FakeError()582 script.check_call.side_effect = FakeError()
458583
459 with self.assertRaises(FakeError):584 with self.assertRaises(FakeError):
460 script.collect_inner_logs()585 script.collect_inner_logs("juju")
461586
462 self.assertEqual(script.get_units.call_count, 1)587 self.assertEqual(script.get_units.call_count, 1)
463 self.assertEqual(script.check_output.call_count, 1)588 self.assertEqual(script.check_output.call_count, 1)
464 self.assertEqual(script.call.call_count, 2)589 self.assertEqual(script.call.call_count, 1)
465 self.assertEqual(script.check_call.call_count, 1)590 self.assertEqual(script.check_call.call_count, 1)
466 self.assert_clean()591 self.assert_clean()
467592
@@ -471,31 +596,62 @@
471 ]596 ]
472597
473 with self.assertRaises(FakeError):598 with self.assertRaises(FakeError):
474 script.collect_inner_logs()599 script.collect_inner_logs("juju")
475600
476 self.assertEqual(script.get_units.call_count, 1)601 self.assertEqual(script.get_units.call_count, 1)
477 self.assertEqual(script.check_output.call_count, 1)602 self.assertEqual(script.check_output.call_count, 1)
478 self.assertEqual(script.call.call_count, 2)603 self.assertEqual(script.call.call_count, 1)
479 self.assertEqual(script.check_call.call_count, 2)604 self.assertEqual(script.check_call.call_count, 2)
480 self.assert_clean()605 self.assert_clean()
481606
482 def test_check_call_failure_3(self):607 def test_check_call_failure_3(self):
608 script.check_call.side_effect = [None,
609 None,
610 FakeError(),
611 ]
612
613 with self.assertRaises(FakeError):
614 script.collect_inner_logs("juju")
615
616 self.assertEqual(script.get_units.call_count, 1)
617 self.assertEqual(script.check_output.call_count, 1)
618 self.assertEqual(script.call.call_count, 1)
619 self.assertEqual(script.check_call.call_count, 3)
620 self.assert_clean()
621
622 def test_check_call_failure_4(self):
623 script.check_call.side_effect = [None,
624 None,
625 None,
626 FakeError(),
627 ]
628
629 with self.assertRaises(FakeError):
630 script.collect_inner_logs("juju")
631
632 self.assertEqual(script.get_units.call_count, 1)
633 self.assertEqual(script.check_output.call_count, 1)
634 self.assertEqual(script.call.call_count, 1)
635 self.assertEqual(script.check_call.call_count, 4)
636 self.assert_clean()
637
638 def test_check_call_failure_5(self):
483 def check_call_side_effect(cmd):639 def check_call_side_effect(cmd):
484 if script.check_call.call_count == 1:640 if script.check_call.call_count in (1, 2, 3):
485 return None641 return None
486 if script.check_call.call_count == 2:642 if script.check_call.call_count == 4:
487 self._touch_tempfile("inner-logs.tar.gz")643 self._touch_tempfile("inner-logs.tar.gz")
488 return None644 return None
489 raise FakeError()645 raise FakeError()
490 script.check_call.side_effect = check_call_side_effect646 script.check_call.side_effect = check_call_side_effect
491647
492 with self.assertRaises(FakeError):648 with self.assertRaises(FakeError):
493 script.collect_inner_logs()649 script.collect_inner_logs("juju")
494650
495 self.assertEqual(script.get_units.call_count, 1)651 self.assertEqual(script.get_units.call_count, 1)
496 self.assertEqual(script.check_output.call_count, 1)652 self.assertEqual(script.check_output.call_count, 1)
497 self.assertEqual(script.call.call_count, 2)653 self.assertEqual(script.call.call_count, 1)
498 self.assertEqual(script.check_call.call_count, 3)654 self.assertEqual(script.check_call.call_count, 5)
499 self.assert_clean()655 self.assert_clean()
500656
501657

Subscribers

People subscribed via source and target branches

to all changes: