diff options
author | Chad Smith <chad.smith@canonical.com> | 2017-09-12 10:27:07 -0600 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2017-09-15 15:46:02 -0400 |
commit | e626966ee7d339b53d2c8b14a8f2ff8e3fe892ee (patch) | |
tree | bba6a1a7d8d31b1fc790b7bff1ca94183c278b78 /cloudinit/apport.py | |
parent | da1db792b2721d94ef85df8c136e78012c49c6e5 (diff) | |
download | vyos-cloud-init-e626966ee7d339b53d2c8b14a8f2ff8e3fe892ee.tar.gz vyos-cloud-init-e626966ee7d339b53d2c8b14a8f2ff8e3fe892ee.zip |
cmdline: add collect-logs subcommand.
Add a new collect-logs sub command to the cloud-init CLI. This script
will collect all logs pertinent to a cloud-init run and store them in a
compressed tar-gzipped file. This tarfile can be attached to any
cloud-init bug filed in order to aid in bug triage and resolution.
A cloudinit.apport module is also added that allows apport interaction.
Here is an example bug filed via ubuntu-bug cloud-init: LP: #1716975.
Once the apport launcher is packaged in cloud-init, bugs can be filed
against cloud-init with the following command:
ubuntu-bug cloud-init
LP: #1607345
Diffstat (limited to 'cloudinit/apport.py')
-rw-r--r-- | cloudinit/apport.py | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/cloudinit/apport.py b/cloudinit/apport.py new file mode 100644 index 00000000..221f341c --- /dev/null +++ b/cloudinit/apport.py @@ -0,0 +1,105 @@ +# Copyright (C) 2017 Canonical Ltd. +# +# This file is part of cloud-init. See LICENSE file for license information. + +'''Cloud-init apport interface''' + +try: + from apport.hookutils import ( + attach_file, attach_root_command_outputs, root_command_output) + has_apport = True +except ImportError: + has_apport = False + + +KNOWN_CLOUD_NAMES = [ + 'Amazon - Ec2', 'AliYun', 'AltCloud', 'Azure', 'Bigstep', 'CloudSigma', + 'CloudStack', 'DigitalOcean', 'GCE - Google Compute Engine', 'MAAS', + 'NoCloud', 'OpenNebula', 'OpenStack', 'OVF', 'Scaleway', 'SmartOS', + 'VMware', 'Other'] + +# Potentially clear text collected logs +CLOUDINIT_LOG = '/var/log/cloud-init.log' +CLOUDINIT_OUTPUT_LOG = '/var/log/cloud-init-output.log' +USER_DATA_FILE = '/var/lib/cloud/instance/user-data.txt' # Optional + + +def attach_cloud_init_logs(report, ui=None): + '''Attach cloud-init logs and tarfile from 'cloud-init collect-logs'.''' + attach_root_command_outputs(report, { + 'cloud-init-log-warnings': + 'egrep -i "warn|error" /var/log/cloud-init.log', + 'cloud-init-output.log.txt': 'cat /var/log/cloud-init-output.log'}) + root_command_output( + ['cloud-init', 'collect-logs', '-t', '/tmp/cloud-init-logs.tgz']) + attach_file(report, '/tmp/cloud-init-logs.tgz', 'logs.tgz') + + +def attach_hwinfo(report, ui=None): + '''Optionally attach hardware info from lshw.''' + prompt = ( + 'Your device details (lshw) may be useful to developers when' + ' addressing this bug, but gathering it requires admin privileges.' + ' Would you like to include this info?') + if ui and ui.yesno(prompt): + attach_root_command_outputs(report, {'lshw.txt': 'lshw'}) + + +def attach_cloud_info(report, ui=None): + '''Prompt for cloud details if available.''' + if ui: + prompt = 'Is this machine running in a cloud environment?' + response = ui.yesno(prompt) + if response is None: + raise StopIteration # User cancelled + if response: + prompt = ('Please select the cloud vendor or environment in which' + ' this instance is running') + response = ui.choice(prompt, KNOWN_CLOUD_NAMES) + if response: + report['CloudName'] = KNOWN_CLOUD_NAMES[response[0]] + else: + report['CloudName'] = 'None' + + +def attach_user_data(report, ui=None): + '''Optionally provide user-data if desired.''' + if ui: + prompt = ( + 'Your user-data or cloud-config file can optionally be provided' + ' from {0} and could be useful to developers when addressing this' + ' bug. Do you wish to attach user-data to this bug?'.format( + USER_DATA_FILE)) + response = ui.yesno(prompt) + if response is None: + raise StopIteration # User cancelled + if response: + attach_file(report, USER_DATA_FILE, 'user_data.txt') + + +def add_bug_tags(report): + '''Add any appropriate tags to the bug.''' + if 'JournalErrors' in report.keys(): + errors = report['JournalErrors'] + if 'Breaking ordering cycle' in errors: + report['Tags'] = 'systemd-ordering' + + +def add_info(report, ui): + '''This is an entry point to run cloud-init's apport functionality. + + Distros which want apport support will have a cloud-init package-hook at + /usr/share/apport/package-hooks/cloud-init.py which defines an add_info + function and returns the result of cloudinit.apport.add_info(report, ui). + ''' + if not has_apport: + raise RuntimeError( + 'No apport imports discovered. Apport functionality disabled') + attach_cloud_init_logs(report, ui) + attach_hwinfo(report, ui) + attach_cloud_info(report, ui) + attach_user_data(report, ui) + add_bug_tags(report) + return True + +# vi: ts=4 expandtab |