136 lines
5.1 KiB
Python
136 lines
5.1 KiB
Python
"""Send reports about subiquity to the correct Launchpad project."""
|
|
|
|
import os
|
|
import re
|
|
|
|
from apport import Report, hookutils
|
|
from apport.ui import HookUI
|
|
|
|
|
|
def get_journal(report: Report, log_map: dict[str, str]) -> None:
|
|
"""Get installer environment journal log.
|
|
|
|
Appends the installer specific journal to the log map if it exists,
|
|
otherwise appends the system journal to the report directly.
|
|
"""
|
|
installer_journal = "/var/log/installer/installer-journal.txt"
|
|
if os.path.exists(installer_journal):
|
|
log_map["InstallerJournal"] = installer_journal
|
|
else:
|
|
report["SystemJournal"] = hookutils.recent_syslog(re.compile("."))
|
|
|
|
|
|
def get_revision(debug_log_contents: str) -> str:
|
|
"""Get subiquity revision from debug log contents.
|
|
|
|
Returns revision found (e.g. "1234") or "unknown" if not found.
|
|
"""
|
|
# Revision information is always in the first line of the log file
|
|
first_line = debug_log_contents.splitlines()[0]
|
|
marker = "Starting Subiquity server revision"
|
|
if marker in first_line:
|
|
revision = first_line.split(marker)[1].strip()
|
|
else:
|
|
revision = "unknown"
|
|
|
|
return revision
|
|
|
|
|
|
def add_info(report: Report, unused_ui: HookUI) -> None:
|
|
"""Package hook entry point."""
|
|
# Check if the snap was updated
|
|
# TODO: Add logic to support this outside of the live environment.
|
|
# It may be possible someone wants to report a bug against the
|
|
# installer after first boot.
|
|
report["SnapUpdated"] = str(os.path.exists("/run/subiquity/updating"))
|
|
|
|
# rewrite this section so the report goes to the project in Launchpad
|
|
report[
|
|
"CrashDB"
|
|
] = """\
|
|
{
|
|
"impl": "launchpad",
|
|
"project": "subiquity",
|
|
"bug_pattern_url": "http://people.canonical.com/"
|
|
"~ubuntu-archive/bugpatterns/bugpatterns.xml",
|
|
}
|
|
"""
|
|
|
|
# add in hardware information
|
|
hookutils.attach_hardware(report)
|
|
|
|
# This key is important for checking revision information later
|
|
debug_log_key = "InstallerServerLog"
|
|
|
|
# static subiquity generated logs
|
|
log_map = {
|
|
debug_log_key: "/var/log/installer/subiquity-server-debug.log",
|
|
"InstallerServerLogInfo": "/var/log/installer/subiquity-server-info.log",
|
|
"InstallerClientLog": "/var/log/installer/subiquity-client-debug.log",
|
|
"InstallerClientLogInfo": "/var/log/installer/subiquity-client-info.log",
|
|
"CurtinLog": "/var/log/installer/curtin-install.log",
|
|
"CurtinAptConfig": (
|
|
"/var/log/installer/curtin-install/subiquity-curtin-apt.conf"
|
|
),
|
|
"CurtinCurthooksConfig": (
|
|
"/var/log/installer/curtin-install/subiquity-curthooks.conf"
|
|
),
|
|
"CurtinExtractConfig": (
|
|
"/var/log/installer/curtin-install/subiquity-extract.conf"
|
|
),
|
|
"CurtinInitialConfig": (
|
|
"/var/log/installer/curtin-install/subiquity-initial.conf"
|
|
),
|
|
"CurtinPartitioningConfig": (
|
|
"/var/log/installer/curtin-install/subiquity-partitioning.conf"
|
|
),
|
|
"ProbeData": "/var/log/installer/block/probe-data.json",
|
|
"Traceback": "/var/log/installer/subiquity-traceback.txt",
|
|
"NetplanInstallerConfig": "/etc/netplan/00-installer-config.yaml",
|
|
"NetplanSnapdConfig": "/etc/netplan/00-snapd-config.yaml",
|
|
}
|
|
|
|
# Add journal log
|
|
get_journal(report, log_map)
|
|
|
|
# Add ubuntu-desktop-bootstrap information if available
|
|
udb_log = os.path.realpath("/var/log/installer/ubuntu_bootstrap.log")
|
|
if os.path.exists(udb_log):
|
|
log_map["BootstrapLog"] = udb_log
|
|
report.add_tags(["ubuntu-desktop-bootstrap"])
|
|
# check for udb snap version
|
|
udb_snap = os.path.realpath("/snap/ubuntu-desktop-bootstrap/current")
|
|
if os.path.exists(udb_snap):
|
|
# "current" is a symlink to the current revision and
|
|
# os.path.realpath should have resolved it
|
|
report["DesktopInstallerRev"] = os.path.basename(udb_snap)
|
|
|
|
# Attach logs if they exist
|
|
# The conventional way to attach logs would be to use the
|
|
# hookutils.attach_file_if_exists method, but since subiquity logs
|
|
# are mostly locked down with root r/w only then we will get a permission
|
|
# error if the caller does not have permissions. Ask for elevated
|
|
# permissions instead of requiring users know to run with sudo or similar
|
|
command_mapping = {}
|
|
for name, path in log_map.items():
|
|
if os.path.exists(path):
|
|
real_path = os.path.realpath(path)
|
|
command_mapping[name] = f"cat {real_path}"
|
|
|
|
hookutils.attach_root_command_outputs(report, command_mapping)
|
|
|
|
# Get revision to display in the UI prompt
|
|
# If attach_root_command_outputs fails the log won't be in the report
|
|
revision = "unknown"
|
|
if debug_log_key in report:
|
|
revision = get_revision(report[debug_log_key])
|
|
report["Package"] = f"subiquity ({revision})"
|
|
report["SourcePackage"] = "subiquity"
|
|
|
|
# Package and SourcePackage keys are deleted when the Snap is chosen,
|
|
# so make a separate key to keep track of the revision
|
|
report["SnapVersion"] = revision
|
|
|
|
# Always set reports to private since we might collect sensitive data
|
|
report["LaunchpadPrivate"] = "1"
|