From 86062536d4a314c0d628791640127238a2952be4 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Tue, 22 Oct 2013 15:45:34 +0200 Subject: [ABRT PATCH 59/76] factor out D-Bus notification to a python script This patch is a part of our effort to move application logic from configuration files to executables. Related to #684 Signed-off-by: Jakub Filak --- doc/Makefile.am | 1 + doc/abrt-action-notify.txt | 38 ++++++++++ src/dbus/dbus_event.conf | 19 +---- src/plugins/Makefile.am | 6 +- src/plugins/abrt-action-notify | 164 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 doc/abrt-action-notify.txt create mode 100644 src/plugins/abrt-action-notify diff --git a/doc/Makefile.am b/doc/Makefile.am index 1ca52b5..8b14517 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -16,6 +16,7 @@ MAN1_TXT += abrt-action-analyze-vulnerability.txt MAN1_TXT += abrt-action-install-debuginfo.txt MAN1_TXT += abrt-action-list-dsos.txt MAN1_TXT += abrt-action-perform-ccpp-analysis.txt +MAN1_TXT += abrt-action-notify.txt MAN1_TXT += abrt-applet.txt MAN1_TXT += abrt-dump-oops.txt MAN1_TXT += abrt-dump-xorg.txt diff --git a/doc/abrt-action-notify.txt b/doc/abrt-action-notify.txt new file mode 100644 index 0000000..c5bd7b0 --- /dev/null +++ b/doc/abrt-action-notify.txt @@ -0,0 +1,38 @@ +abrt-action-notify(1) +=================== + +NAME +---- +abrt-action-notify - Announces a new occurrence of problem via all accessible channels + +SYNOPSIS +-------- +'abrt-action-notify' [-h] [-d PROBLEM_DIR] + +DESCRIPTION +----------- +The current implementation emits a D-Bus signal on System bus in path +/org/freedesktop/problems of org.freedesktop.problems interface for Crash +member. + +Integration with ABRT events +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +'abrt-action-notify' is used to notify new problems and consecutive occurrences +of a single problem for all crash types. + +------------ +EVENT=notify package!= + abrt-action-notify +------------ + +OPTIONS +------- +-d, --problem-dir PROBLEM_DIR:: + Problem directory [Default: current directory] + +-h, --help:: + Show help message + +AUTHORS +------- +* ABRT team diff --git a/src/dbus/dbus_event.conf b/src/dbus/dbus_event.conf index 4d24fef..499e484 100644 --- a/src/dbus/dbus_event.conf +++ b/src/dbus/dbus_event.conf @@ -1,16 +1,5 @@ -EVENT=notify package!= uid!= - dbus-send --system --type=signal /org/freedesktop/problems org.freedesktop.problems.Crash \ - string:"`cat package`" string:"$DUMP_DIR" string:"`cat uid`" - -EVENT=notify package!= uid= - dbus-send --system --type=signal /org/freedesktop/problems org.freedesktop.problems.Crash \ - string:"`cat package`" string:"$DUMP_DIR" - -EVENT=notify-dup package!= uid!= - dbus-send --system --type=signal /org/freedesktop/problems org.freedesktop.problems.Crash \ - string:"`cat package`" string:"$DUMP_DIR" string:"`cat uid`" - -EVENT=notify-dup package!= uid= - dbus-send --system --type=signal /org/freedesktop/problems org.freedesktop.problems.Crash \ - string:"`cat package`" string:"$DUMP_DIR" +EVENT=notify package!= + abrt-action-notify -d $DUMP_DIR +EVENT=notify-dup package!= + abrt-action-notify -d $DUMP_DIR diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index fbda305..370d5fd 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -8,7 +8,8 @@ bin_SCRIPTS = \ abrt-action-list-dsos \ abrt-action-perform-ccpp-analysis \ abrt-action-save-kernel-data \ - abrt-action-analyze-ccpp-local + abrt-action-analyze-ccpp-local \ + abrt-action-notify bin_PROGRAMS = \ abrt-watch-log \ @@ -73,7 +74,8 @@ PYTHON_FILES = \ abrt-action-analyze-core \ abrt-action-analyze-vulnerability \ abrt-action-analyze-vmcore.in \ - abrt-action-perform-ccpp-analysis.in + abrt-action-perform-ccpp-analysis.in \ + abrt-action-notify EXTRA_DIST = \ $(PYTHON_FILES) \ diff --git a/src/plugins/abrt-action-notify b/src/plugins/abrt-action-notify new file mode 100644 index 0000000..722d7f6 --- /dev/null +++ b/src/plugins/abrt-action-notify @@ -0,0 +1,164 @@ +#!/usr/bin/python +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import sys +from argparse import ArgumentParser + +import dbus +import dbus.lowlevel + +import report +from reportclient import (RETURN_OK, + RETURN_FAILURE) + +CD_DUMPDIR = "Directory" +FILENAME_PACKAGE = "package" +FILENAME_UID = "uid" +FILENAME_UUID = "uuid" +FILENAME_DUPHASH = "duphash" + +def emit_crash_dbus_signal(problem_data): + """Emits a Crash signal on D-Bus Problem bus + + Emits a signal with 5 members: + package -- value of 'package' element in problem_data + problem_id -- value of 'Directory' element in problem_data + uid -- empty string if 'uid' element is not present in problem_data + + + + Keyword arguments: + problem_data -- problem data of notified problems + + Returns None as it raises an exception on error + + Raises: + RuntimeError -- for all D-Bus related errors + KeyError -- if any of required elements is missing + """ + + try: + bus = dbus.SystemBus() + msg = dbus.lowlevel.SignalMessage("/org/freedesktop/problems", + "org.freedesktop.problems", "Crash") + + # List of tuples where the first member is element name and the second + # member is a Boolean flag which is True if the element is required + arguments = ((FILENAME_PACKAGE, True), (CD_DUMPDIR, True), + (FILENAME_UID, False) + ) + + for elem in arguments: + itm = problem_data.get(elem[0]) + + if itm is None: + if elem[1]: + raise KeyError(elem[0]) + + msg.append("", signature="s") + else: + msg.append(itm[0], signature="s") + + + bus.send_message(msg) + except dbus.exceptions.DBusException as ex: + raise RuntimeError("Failed to emit D-Bus Crash signal: {0}" + .format(ex.message)) + finally: + if bus is not None: + bus.close() + +def build_notification_problem_data(problem_dir): + """Loads all necessary problem elements + + Problem dump directory must contain 'package' element. + + Keyword arguments: + problem_dir -- an absolute file system path problem directory + + Returns an instance of report.problem_data + + Raises: + ValueError -- if problem_dir is not an absolute path, if problem_dir cannot + be opened and if any required problem element is missing. + """ + + if not os.path.isabs(problem_dir): + raise ValueError("problem directory must be absolute path") + + prblm_dt = report.problem_data() + + try: + dump_dir = report.dd_opendir(problem_dir, report.DD_OPEN_READONLY) + if not dump_dir: + raise ValueError("cannot open problem directory") + + dd_load_flag = (report.DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE + | report.DD_FAIL_QUIETLY_ENOENT) + + package = dump_dir.load_text(FILENAME_PACKAGE, dd_load_flag) + if not package: + raise ValueError("problem directory misses '{0}'" + .format(FILENAME_PACKAGE)) + + pd_add_flag = report.CD_FLAG_TXT | report.CD_FLAG_ISNOTEDITABLE + + prblm_dt.add(FILENAME_PACKAGE, package, pd_add_flag) + prblm_dt.add(CD_DUMPDIR, problem_dir, pd_add_flag) + + for element in (FILENAME_UID, FILENAME_UUID, FILENAME_DUPHASH): + val = dump_dir.load_text(element, dd_load_flag) + if val is not None: + prblm_dt.add(element, val, pd_add_flag) + finally: + dump_dir.close() + + return prblm_dt + + +if __name__ == "__main__": + CMDARGS = ArgumentParser( + description=("Announce a new or duplicated problem via" + " all accessible channels")) + CMDARGS.add_argument("-d", "--problem-dir", + type=str, required=True, + help="An absolute path to a new or duplicated problem directory") + + OPTIONS = CMDARGS.parse_args() + + DIR_PATH = OPTIONS.problem_dir + + try: + PD = build_notification_problem_data(DIR_PATH) + except ValueError as ex: + sys.stderr.write("Cannot notify '{0}': {1}\n". + format(DIR_PATH, ex.message)) + sys.exit(RETURN_FAILURE) + + try: + emit_crash_dbus_signal(PD) + except RuntimeError as ex: + sys.stderr.write("Cannot notify '{0}': {1}\n". + format(DIR_PATH, ex.message)) + sys.exit(RETURN_FAILURE) + except KeyError as ex: + # this is a bug in build_notification_problem_data() + sys.stderr.write("BUG: problem data misses required element '{0}'" + .format(ex.message)) + sys.exit(RETURN_FAILURE) + + sys.exit(RETURN_OK) + -- 1.8.3.1