[Asterisk-code-review] Adds option to send crash reports via email (testsuite[master])
Joshua Colp
asteriskteam at digium.com
Wed Oct 28 14:40:55 CDT 2015
Joshua Colp has submitted this change and it was merged.
Change subject: Adds option to send crash reports via email
......................................................................
Adds option to send crash reports via email
--email-on-crash enables email on crash behavior. When this
behavior is enabled, the testsuite will attempt to email crash
reports (currently just the path to the test and a backtrace).
Configuration for sending the email (smtp server, who to send as,
who to send to, etc) is handled via crash-mail-config.yaml which
goes in the base folder for the testsuite when in use. There is
a sample configuration for it stored in the sample-yaml folder
(crash-mail-config.yaml.sample)
Change-Id: I17def41f15294a48754269d9c42aa649389840ad
---
M .gitignore
A lib/python/mailer.py
M runtests.py
A sample-yaml/crash-mail-config.yaml.sample
4 files changed, 129 insertions(+), 15 deletions(-)
Approvals:
Anonymous Coward #1000019: Verified
Ashley Sanders: Looks good to me, but someone else must approve
Matt Jordan: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, approved
diff --git a/.gitignore b/.gitignore
index c37e120..fdbbcf0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.pyc
asterisk-test-suite-report.xml
+crash-mail-config.yaml
/astroot
/contrib/valgrind/suppressions.txt
/logs
diff --git a/lib/python/mailer.py b/lib/python/mailer.py
new file mode 100644
index 0000000..9c6d726
--- /dev/null
+++ b/lib/python/mailer.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+"""Simple email via SMTP
+
+Copyright (C) 2015, Digium, Inc.
+Jonathan Rose <jrose at digium.com>
+
+This program is free software, distributed under the terms of
+the GNU General Public License Version 2.
+"""
+
+try:
+ import smtplib
+ SMTP_AVAILABLE = True
+except ImportError:
+ SMTP_AVAILABLE = False
+
+
+def send_email(server, sender, recipients, message, debug=0):
+ """Send an email using SMTP
+
+ Keyword Arguments:
+ server - host address of SMTP server
+ sender - email address to use as the sender
+ recipients - array of email addresses to send the message to
+ message - dictionary containing a body and a subject for the message
+ debug - optional argument sets debug level for smtp interface
+
+ Note: Throws exceptions if SMTP server connection fails in some manner
+ or if smtplib is not available when this function is imported.
+ """
+ if not SMTP_AVAILABLE:
+ raise Exception("smtplib could not be loaded, email functionality "
+ "is unavailable")
+
+ subject = message.get('subject')
+ if subject:
+ email_text = "Subject: {0}\n\n{1}".format(subject,
+ message['body'])
+ else:
+ email_text = message['body']
+
+ smtp_obj = smtplib.SMTP(server)
+ smtp_obj.set_debuglevel(debug)
+ smtp_obj.sendmail(sender, recipients, email_text)
diff --git a/runtests.py b/runtests.py
index 88b0e23..b971004 100755
--- a/runtests.py
+++ b/runtests.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
'''Asterisk external test suite driver.
-Copyright (C) 2010, Digium, Inc.
+Copyright (C) 2015, Digium, Inc.
Russell Bryant <russell at digium.com>
This program is free software, distributed under the terms of
@@ -43,6 +43,7 @@
from asterisk.version import AsteriskVersion
from asterisk.asterisk import Asterisk
from asterisk.test_config import TestConfig
+from mailer import send_email
TESTS_CONFIG = "tests.yaml"
TEST_RESULTS = "asterisk-test-suite-report.xml"
@@ -184,6 +185,37 @@
return core_files
+ def _email_crash_report(self, dest_file_name):
+ email_config = load_yaml_config("crash-mail-config.yaml")
+
+ smtp_server = email_config.get('smtp-server')
+ sender = email_config.get('sender')
+ recipients = email_config.get('recipients')
+ subject = email_config.get('subject', "Testsuite crash detected")
+ max_bt_len = email_config.get('truncate-backtrace', 0)
+ debug_level = email_config.get('debug', 0)
+
+ if not sender or len(recipients) == 0:
+ print "--email-on-crash requires sender and 1+ recipients"
+ return
+
+ with open(dest_file_name, 'r') as bt_file:
+ backtrace_text = bt_file.read()
+
+ if max_bt_len > 0 and backtrace_text > max_bt_len:
+ truncated_text = "\n--truncated to {0} chars--".format(max_bt_len)
+ backtrace_text = backtrace_text[0:max_bt_len] + truncated_text
+
+ email_text = "{0}\n\n{1}".format(dest_file_name, backtrace_text)
+
+ message = {'body': email_text, 'subject': subject}
+
+ try:
+ send_email(smtp_server, sender, recipients, message,
+ debug=debug_level)
+ except Exception as exception:
+ print "Failed to send email\nError: {0}".format(exception)
+
def _archive_core_dumps(self, core_dumps):
for core in core_dumps:
if not os.path.exists(core):
@@ -209,6 +241,10 @@
print "error analyzing core dump; gdb exited with %d" % res
# Copy the backtrace over to the logs
print "Archived backtrace: {0}".format(dest_file_name)
+
+ if self.options.email_on_crash:
+ self._email_crash_report(dest_file_name)
+
except OSError, ose:
print "OSError ([%d]: %s) occurred while executing %r" % \
(ose.errno, ose.strerror, gdb_cmd)
@@ -393,18 +429,10 @@
def _parse_test_yaml(self, test_dir, ast_version):
tests = []
- try:
- f = open("%s/%s" % (test_dir, TESTS_CONFIG), "r")
- except IOError:
- if test_dir != "tests/custom":
- print "Failed to open %s/%s" % (test_dir, TESTS_CONFIG)
- return tests
- except:
- print "Unexpected error: %s" % sys.exc_info()[0]
- return tests
- config = yaml.load(f)
- f.close()
+ config = load_yaml_config("%s/%s" % (test_dir, TESTS_CONFIG))
+ if not config:
+ return tests
for t in config["tests"]:
for val in t:
@@ -616,6 +644,23 @@
tc.appendChild(failure)
+def load_yaml_config(path):
+ """Load contents of a YAML config file to a dictionary"""
+ try:
+ f = open(path, "r")
+ except IOError:
+ print "Failed to open %s" % path
+ return None
+ except:
+ print "Unexpected error: %s" % sys.exc_info()[0]
+ return None
+
+ config = yaml.load(f)
+ f.close()
+
+ return config
+
+
def handle_usr1(sig, stack):
"""Handle the SIGUSR1 signal
@@ -668,14 +713,18 @@
help="List available tags")
parser.add_option("-t", "--test", action="append", default=[],
dest="tests",
- help=("Run a single specified test (directory) instead "
- "of all tests. May be specified more than once."))
+ help="Run a single specified test (directory) instead "
+ "of all tests. May be specified more than once.")
parser.add_option("-v", "--version",
dest="version", default=None,
help="Specify the version of Asterisk rather then detecting it.")
parser.add_option("-V", "--valgrind", action="store_true",
dest="valgrind", default=False,
help="Run Asterisk under Valgrind")
+ parser.add_option("--email-on-crash", action="store_true",
+ dest="email_on_crash", default=False,
+ help="Send email on crash with a backtrace. See "
+ "crash-mail-config.yaml.sample for details.")
parser.add_option("--number", metavar="int", type=int,
dest="number", default=1,
help="Number of times to run the test suite. If a value of "
@@ -686,7 +735,6 @@
parser.add_option("--timeout", metavar='int', type=int,
dest="timeout", default=-1,
help="Abort test after n seconds of no output.")
-
(options, args) = parser.parse_args(argv)
# Install a signal handler for USR1/TERM, and use it to bail out of running
diff --git a/sample-yaml/crash-mail-config.yaml.sample b/sample-yaml/crash-mail-config.yaml.sample
new file mode 100644
index 0000000..9674166
--- /dev/null
+++ b/sample-yaml/crash-mail-config.yaml.sample
@@ -0,0 +1,21 @@
+# Configuration sample for mail on crash functionality. Place this in the
+# testsuite base directory as crash-mail-config.yaml and use the
+# --email-on-crash option for runtests.py to send reports to the recipients
+# using the configured parameters here.
+
+# The smtp server to send the message
+smtp-server: 'example-domain.com'
+# The email address that should act as the sender
+sender: 'bigboss at example-domain.com'
+# Recipients for the email
+recipients:
+ -
+ 'sigint at example-domain.com'
+ -
+ 'paramedic at example-domain.com'
+# (optional) If set, backtrace will be truncated to the first N characters
+truncate-backtrace: 10000
+# (options) Subject line for the email (default: 'Testsuite crash detected')
+subject: 'Testsuite crash detected'
+# (optional) Sets debug level for SMTP interactions (default: 0)
+debug: 0
--
To view, visit https://gerrit.asterisk.org/1539
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I17def41f15294a48754269d9c42aa649389840ad
Gerrit-PatchSet: 6
Gerrit-Project: testsuite
Gerrit-Branch: master
Gerrit-Owner: Jonathan Rose <jrose at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Ashley Sanders <asanders at digium.com>
Gerrit-Reviewer: Corey Farrell <git at cfware.com>
Gerrit-Reviewer: Jonathan Rose <jrose at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>
More information about the asterisk-code-review
mailing list