faft: Capture logs from servo log-dir, revised
This is a rework of CL:1808442, with several changes:
* Use try/catch to handle rotate_servod_logs control not existing.
This can happen if a labstation is out of date.
* Move the method body, to improve the call stack reported in syslog:
autotest[1234]: from [rotate_servod_logs|rotate_servod_logs|run]...
autotest[1234]: from [initialize|rotate_servod_logs|run] ssh_run...
* Delete the old 'latest' link, to ensure old logs won't be reused
even if log rotation is switched on or off between runs.
BUG=chromium:1011382
BUG=chromium:932820
TEST=Run suite:faft_lv1, check results for files matching servod.*
Change-Id: I0bd35c0b296fc312ba19f5f85bc54088a12884bf
Reviewed-on: https://chromium-review.googlesource.com/1846520
Tested-by: Dana Goyette <dgoyette@chromium.org>
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index f37595f..acf0825 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -314,16 +314,73 @@
"""Returns the serial number of the servo board."""
return self._servo_serial
- def fetch_servod_log(self, filename=None, skip_old=False):
- """Save the servod log into the given local file.
+ def rotate_servod_logs(self, filename=None, directory=None):
+ """Save the latest servod log into a local directory, then rotate logs.
- @param filename: save the contents into a file with the given name.
- @param skip_old: if True, skip past the old data in the log file.
- @type filename: str
- @type skip_old: bool
- @rtype: None
+ The files will be <filename>.DEBUG, <filename>.INFO, <filename>.WARNING,
+ or just <filename>.log if not using split level logging.
+
+ @param filename: local filename prefix (no file extension) to use.
+ If None, rotate log but don't save it.
+ @param directory: local directory to save logs into (if unset, use cwd)
"""
- return self._servo_host.fetch_servod_log(filename, skip_old)
+ if self.is_localhost():
+ # Local servod usually runs without log-dir, so can't be collected.
+ # TODO(crbug.com/1011516): allow localhost when rotation is enabled
+ return
+
+ log_dir = '/var/log/servod_%s' % self._servo_host.servo_port
+
+ if filename:
+ # TODO(crrev.com/c/1793030): remove no-level case once CL is pushed
+ for level_name in ('', 'DEBUG', 'INFO', 'WARNING'):
+
+ remote_path = os.path.join(log_dir, 'latest')
+ if level_name:
+ remote_path += '.%s' % level_name
+
+ local_path = '%s.%s' % (filename, level_name or 'log')
+ if directory:
+ local_path = os.path.join(directory, local_path)
+
+ try:
+ self._servo_host.get_file(
+ remote_path, local_path, try_rsync=False)
+
+ except error.AutoservRunError as e:
+ result = e.result_obj
+ if result.exit_status != 0:
+ stderr = result.stderr.strip()
+
+ # File not existing is okay, but warn for anything else.
+ if 'no such' not in stderr.lower():
+ logging.warn(
+ "Couldn't retrieve servod log: %s",
+ stderr or '\n%s' % result)
+
+ try:
+ if os.stat(local_path).st_size == 0:
+ os.unlink(local_path)
+ except EnvironmentError:
+ pass
+
+ else:
+ # No filename given, so caller wants to discard the log lines.
+ # Remove the symlinks to prevent old log-dir links from being
+ # picked up multiple times when using servod without log-dir.
+ remote_path = os.path.join(log_dir, 'latest*')
+ self._servo_host.run(
+ "rm %s" % remote_path,
+ stderr_tee=None, ignore_status=True)
+
+ # Servod log rotation renames current log, then creates a new file with
+ # the old name: log.<date> -> log.<date>.1.tbz2 -> log.<date>.2.tbz2
+
+ # Must rotate after copying, or the copy would be the new, empty file.
+ try:
+ self.set_nocheck('rotate_servod_logs', 'yes')
+ except ControlUnavailableError as e:
+ logging.warn("Couldn't rotate servod logs: %s", str(e))
def get_power_state_controller(self):
"""Return the power state controller for this Servo.