summaryrefslogtreecommitdiff
path: root/python/vyos/airbag.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/airbag.py')
-rw-r--r--python/vyos/airbag.py181
1 files changed, 181 insertions, 0 deletions
diff --git a/python/vyos/airbag.py b/python/vyos/airbag.py
new file mode 100644
index 000000000..510ab7f46
--- /dev/null
+++ b/python/vyos/airbag.py
@@ -0,0 +1,181 @@
+# Copyright 2019-2020 VyOS maintainers and contributors <maintainers@vyos.io>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+from datetime import datetime
+
+from vyos import debug
+from vyos.logger import syslog
+from vyos.version import get_version
+from vyos.version import get_full_version_data
+
+
+def enable(log=True):
+ if log:
+ _intercepting_logger()
+ _intercepting_exceptions()
+
+
+_noteworthy = []
+
+
+def noteworthy(msg):
+ """
+ noteworthy can be use to take note things which we may not want to
+ report to the user may but be worth including in bug report
+ if something goes wrong later on
+ """
+ _noteworthy.append(msg)
+
+
+# emulate a file object
+class _IO(object):
+ def __init__(self, std, log):
+ self.std = std
+ self.log = log
+
+ def write(self, message):
+ self.std.write(message)
+ for line in message.split('\n'):
+ s = line.rstrip()
+ if s:
+ self.log(s)
+
+ def flush(self):
+ self.std.flush()
+
+ def close(self):
+ pass
+
+
+# The function which will be used to report information
+# to users when an exception is unhandled
+def bug_report(dtype, value, trace):
+ from traceback import format_exception
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ information = get_full_version_data()
+ trace = '\n'.join(format_exception(dtype, value, trace)).replace('\n\n','\n')
+ note = ''
+ if _noteworthy:
+ note = 'noteworthy:\n'
+ note += '\n'.join(_noteworthy)
+
+ information.update({
+ 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ 'trace': trace,
+ 'instructions': COMMUNITY if 'rolling' in get_version() else SUPPORTED,
+ 'note': note,
+ })
+
+ sys.stdout.write(INTRO.format(**information))
+ sys.stdout.flush()
+
+ sys.stderr.write(FAULT.format(**information))
+ sys.stderr.flush()
+
+
+# define an exception handler to be run when an exception
+# reach the end of __main__ and was not intercepted
+def _intercepter(dtype, value, trace):
+ bug_report(dtype, value, trace)
+ if debug.enabled('developer'):
+ import pdb
+ pdb.pm()
+
+
+def _intercepting_logger(_singleton=[False]):
+ skip = _singleton.pop()
+ _singleton.append(True)
+ if skip:
+ return
+
+ # log to syslog any message sent to stderr
+ sys.stderr = _IO(sys.stderr, syslog.critical)
+
+
+# lists as default arguments in function is normally dangerous
+# as they will keep any modification performed, unless this is
+# what you want to do (in that case to only run the code once)
+def _intercepting_exceptions(_singleton=[False]):
+ skip = _singleton.pop()
+ _singleton.append(True)
+ if skip:
+ return
+
+ # install the handler to replace the default behaviour
+ # which just prints the exception trace on screen
+ sys.excepthook = _intercepter
+
+
+# Messages to print
+# if the key before the value has not time, syslog takes that as the source of the message
+
+FAULT = """\
+Report Time: {date}
+Image Version: VyOS {version}
+Release Train: {release_train}
+
+Built by: {built_by}
+Built on: {built_on}
+Build UUID: {build_uuid}
+Build Commit ID: {build_git}
+
+Architecture: {system_arch}
+Boot via: {boot_via}
+System type: {system_type}
+
+Hardware vendor: {hardware_vendor}
+Hardware model: {hardware_model}
+Hardware S/N: {hardware_serial}
+Hardware UUID: {hardware_uuid}
+
+{trace}
+{note}
+"""
+
+INTRO = """\
+VyOS had an issue completing a command.
+
+We are sorry that you encountered a problem while using VyOS.
+There are a few things you can do to help us (and yourself):
+{instructions}
+
+When reporting problems, please include as much information as possible:
+- do not obfuscate any data (feel free to contact us privately if your
+ business policy requires it)
+- and include all the information presented below
+
+"""
+
+COMMUNITY = """\
+- Make sure you are running the latest version of the code available at
+ https://downloads.vyos.io/rolling/current/amd64/vyos-rolling-latest.iso
+- Consult the forum to see how to handle this issue
+ https://forum.vyos.io
+- Join our community on slack where our users exchange help and advice
+ https://vyos.slack.com
+""".strip()
+
+SUPPORTED = """\
+- Make sure you are running the latest stable version of VyOS
+ the code is available at https://downloads.vyos.io/?dir=release/current
+- Contact us using the online help desk
+ https://support.vyos.io/
+- Join our community on slack where our users exchange help and advice
+ https://vyos.slack.com
+""".strip()