From a138fe87467ca96a6314889fe0dd17dcdccded62 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jan 2010 15:51:04 +0100 Subject: SOSreport: make it avoid double runs; add forced regeneration; upd PLUGINS-HOWTO Signed-off-by: Denys Vlasenko --- doc/PLUGINS-HOWTO | 90 ++++++++++++++++++++++----------------- lib/Plugins/FileTransfer.cpp | 2 +- lib/Plugins/FileTransfer.h | 2 +- lib/Plugins/KerneloopsScanner.cpp | 2 +- lib/Plugins/KerneloopsScanner.h | 2 +- lib/Plugins/RunApp.cpp | 2 +- lib/Plugins/RunApp.h | 2 +- lib/Plugins/SOSreport.cpp | 38 +++++++++++------ lib/Plugins/SOSreport.h | 2 +- lib/Plugins/TicketUploader.cpp | 13 +++--- lib/Utils/Action.h | 2 +- src/Daemon/MiddleWare.cpp | 14 +++--- 12 files changed, 98 insertions(+), 73 deletions(-) diff --git a/doc/PLUGINS-HOWTO b/doc/PLUGINS-HOWTO index a7c08088..81090f33 100644 --- a/doc/PLUGINS-HOWTO +++ b/doc/PLUGINS-HOWTO @@ -21,49 +21,64 @@ their output files there, if any. Plugin types in detail: -Action Plugin -------------- -This type of plugin is useful when you need some action to be performed -immediately when a crash is encountered (using ActionsAndReporters = ... -directive in abrt.conf), or if you need some action to be performed -periodically ([Cron] section in the same file). - -You have to override one method: +Analyzer Plugin +--------------- +Crashes differ, depending on where they occur, for example crashes +in the kernel differ from crashes in userspace binaries, which differ +from crashes in python scripts. Therefore, there is a plugin +for each type of application that you want abrt to handle. -virtual void Run(const char *dir, const char *args); +You have to override these methods: -The first argument is a directory that contains the current debug -dump, or all debug dumps for periodic actions. -The second argument is a string with arguments (specified in config file). +virtual std::string GetLocalUUID(const char *pDebugDumpPath); +- This method is invoked immediately after crash is detected + and its data is saved by the corresponding hook. + It needs to compute an unique hash (UUID) of the crash. + When a crash occurs and abrt finds an earlier crash with the same + UUID, new crash is discarded as a duplicate, it doesn't show up + in abrt's crash list, but instead a crash count for the earlier + crash is incremented. + +virtual void CreateReport(const char *pDebugDumpDir, int force) +- This method is called when user wants to report a crash + ([Reoprt] button in GUI, etc). Analyzer can perform additional, + more CPU/disk intensive, or interactive processing at this point. + For example, CCpp plugin's CreateReport() processes coredump file, + produces a textual backtrace, and saves it to crash dump directory. + +virtual std::string GetGlobalUUID(const char *pDebugDumpPath); +- This method computes a "duplicate hash" which is used search for + duplicates in remote bug databases such as Bugzilla. They are + "less unique" than LocalUUIDs: ideally, the same crash + on different architecture or with slightly different backtrace + will still have the same GlobalUUID. + [TODO: renaming it to DUPHASH] -Analyzer Plugin ---------------- -This plugin has to compute the UUID of the crash. Crashes differ, depending on -where they occur, for example crashes in the kernel differ from crashes in -userspace binaries, which differ from crashes in python scripts. Therefore, -you need a plugin for each type of application that you want abrt to handle. +Action Plugin +------------- +This type of plugin is useful when you need some action to be performed. +Action plugins can be invoked in three ways: -You have to override these methods: +* Immediately when a crash is encountered (using ActionsAndReporters = ... + directive in abrt.conf). These action plugins are run on every crash + (regardless of crash type). -virtual std::string GetLocalUUID(const std::string& pDebugDumpPath); -- This method computes the local UUID of the crash. +* After Analyzer plugin processed a crash (by specifying plugin in + [AnalyzerActionsAndReporters] section, for example: "CCpp = AnActionPlugin"). + In this case, action plugin's Run() method will be run after analyzer + plugin's CreateReport() and GetGlobalUUID() methods have finished. -virtual std::string GetGlobalUUID(const std::string& pDebugDumpPath); -- This method computes the global UUID of the crash. +* If you need some action to be performed periodically ([Cron] section + in the same file). -{something is fishy here} +You have to override one method: -NOTE: The difference between local and global UUID is that the local UUID -is specific for the machine architecture on which the crash is encountered. -When the crash is reported, abrt has to use the "-debuginfo" packages -to render a global UUID, which should be independent of the specific -system (the same crash on different architectures/configurations can -yield different local UUIDs but has to have the same global UUID). +virtual void Run(const char *dir, const char *args); -virtual void CreateReport(const std::string& pDebugDumpPath); -- This method creates the report about the crash and stores it - in the crash's directory. +The first argument is a directory that contains the current debug +dump, or all debug dumps for periodic actions. +The second argument is a string with arguments (specified in config file). Reporter Plugin @@ -76,19 +91,18 @@ You have to override this method: virtual void Report(const map_crash_data_t& pCrashData, const char *pArgs); --It is self-explanatory, that this method takes the report - and presents it somewhere to the world. - The second argument is a string with arguments specified for the reporter. +- This method takes the report and presents it somewhere to the world. + The second argument is a string with arguments specified for the reporter. Database Plugin --------------- -You use this plugin to store the metadata about the crash. The metadata +This plugin is used to store the metadata about the crash. The metadata has to be in a database, to distinguish whether the current crash is or is not the same as some crash before. The database can be local, or in some centralized location on the network. -you have to override these methods: +You have to override these methods: virtual void Connect(); virtual void DisConnect(); - connect and disconnect from the database diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp index 4d317c8d..5479f9fb 100644 --- a/lib/Plugins/FileTransfer.cpp +++ b/lib/Plugins/FileTransfer.cpp @@ -284,7 +284,7 @@ static string DirBase(const char *pStr) return string(pStr + beg, end - beg); } -void CFileTransfer::Run(const char *pActionDir, const char *pArgs) +void CFileTransfer::Run(const char *pActionDir, const char *pArgs, int force) { update_client(_("File Transfer: Creating a report...")); diff --git a/lib/Plugins/FileTransfer.h b/lib/Plugins/FileTransfer.h index 91207f49..2548c506 100644 --- a/lib/Plugins/FileTransfer.h +++ b/lib/Plugins/FileTransfer.h @@ -43,7 +43,7 @@ class CFileTransfer : public CAction virtual void SetSettings(const map_plugin_settings_t& pSettings); //ok to delete? // virtual const map_plugin_settings_t& GetSettings(); - virtual void Run(const char *pActionDir, const char *pArgs); + virtual void Run(const char *pActionDir, const char *pArgs, int force); }; #endif /* FILETRANSFER_H_ */ diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp index 42ffd409..fb9bac60 100644 --- a/lib/Plugins/KerneloopsScanner.cpp +++ b/lib/Plugins/KerneloopsScanner.cpp @@ -46,7 +46,7 @@ CKerneloopsScanner::CKerneloopsScanner() SaveOopsToDebugDump(); } -void CKerneloopsScanner::Run(const char *pActionDir, const char *pArgs) +void CKerneloopsScanner::Run(const char *pActionDir, const char *pArgs, int force) { const char *syslog_file = "/var/log/messages"; map_plugin_settings_t::const_iterator it = m_pSettings.find("SysLogFile"); diff --git a/lib/Plugins/KerneloopsScanner.h b/lib/Plugins/KerneloopsScanner.h index 9f00df21..dfcb8b5e 100644 --- a/lib/Plugins/KerneloopsScanner.h +++ b/lib/Plugins/KerneloopsScanner.h @@ -46,7 +46,7 @@ class CKerneloopsScanner : public CAction /* Plugin interface */ public: CKerneloopsScanner(); - virtual void Run(const char *pActionDir, const char *pArgs); + virtual void Run(const char *pActionDir, const char *pArgs, int force); }; #endif diff --git a/lib/Plugins/RunApp.cpp b/lib/Plugins/RunApp.cpp index 77f5d3c8..ecbecf20 100644 --- a/lib/Plugins/RunApp.cpp +++ b/lib/Plugins/RunApp.cpp @@ -31,7 +31,7 @@ using namespace std; -void CActionRunApp::Run(const char *pActionDir, const char *pArgs) +void CActionRunApp::Run(const char *pActionDir, const char *pArgs, int force) { /* Don't update_client() - actions run at crash time, there is no client * to talk to at that point */ diff --git a/lib/Plugins/RunApp.h b/lib/Plugins/RunApp.h index 939feaa5..da465f89 100644 --- a/lib/Plugins/RunApp.h +++ b/lib/Plugins/RunApp.h @@ -29,7 +29,7 @@ class CActionRunApp : public CAction { public: - virtual void Run(const char *pActionDir, const char *pArgs); + virtual void Run(const char *pActionDir, const char *pArgs, int force); }; #endif diff --git a/lib/Plugins/SOSreport.cpp b/lib/Plugins/SOSreport.cpp index 25769105..90611b5d 100644 --- a/lib/Plugins/SOSreport.cpp +++ b/lib/Plugins/SOSreport.cpp @@ -16,10 +16,9 @@ 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. - */ - -#include -#include +*/ +//#include +//#include #include "abrtlib.h" #include "abrt_types.h" #include "ABRTException.h" @@ -28,6 +27,8 @@ #include "ABRTException.h" #include "CommLayerInner.h" +using namespace std; + static void ErrorCheck(int pos) { if (pos < 0) @@ -36,7 +37,7 @@ static void ErrorCheck(int pos) } } -static std::string ParseFilename(const std::string& pOutput) +static string ParseFilename(const string& pOutput) { /* the sosreport's filename is embedded in sosreport's output. @@ -64,9 +65,19 @@ static std::string ParseFilename(const std::string& pOutput) return pOutput.substr(filename_start, filename_end - filename_start + 1); } -void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) +void CActionSOSreport::Run(const char *pActionDir, const char *pArgs, int force) { - update_client(_("Executing SOSreport plugin...")); + if (!force) + { + CDebugDump dd; + dd.Open(pActionDir); + bool bt_exists = dd.Exist("sosreport.tar.bz2"); + if (bt_exists) + { + VERB3 log("%s already exists, not regenerating", "sosreport.tar.bz2"); + return; + } + } static const char command_default[] = "sosreport --batch --no-progressbar --only=anaconda --only=bootloader" " --only=devicemapper --only=filesys --only=hardware --only=kernel" @@ -74,7 +85,7 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) " --only=pam --only=process --only=rpm -k rpm.rpmva=off --only=ssh" " --only=startup --only=yum 2>&1"; static const char command_prefix[] = "sosreport --batch --no-progressbar"; - std::string command; + string command; vector_string_t args; parse_args(pArgs, args, '"'); @@ -88,16 +99,17 @@ void CActionSOSreport::Run(const char *pActionDir, const char *pArgs) command = ssprintf("%s %s 2>&1", command_prefix, args[0].c_str()); } - update_client(_("running sosreport: %s"), command.c_str()); - std::string output = command; + update_client(_("Running sosreport: %s"), command.c_str()); + string output = command; output += '\n'; char *command_out = run_in_shell_and_save_output(/*flags:*/ 0, command.c_str(), /*dir:*/ NULL, /*size_p:*/ NULL); output += command_out; free(command_out); - update_client(_("done running sosreport")); + update_client(_("Done running sosreport")); + VERB3 log("sosreport output:'%s'", output.c_str()); - std::string sosreport_filename = ParseFilename(output); - std::string sosreport_dd_filename = concat_path_file(pActionDir, "sosreport.tar.bz2"); + string sosreport_filename = ParseFilename(output); + string sosreport_dd_filename = concat_path_file(pActionDir, "sosreport.tar.bz2"); CDebugDump dd; dd.Open(pActionDir); diff --git a/lib/Plugins/SOSreport.h b/lib/Plugins/SOSreport.h index d4e0d733..bd08eee1 100644 --- a/lib/Plugins/SOSreport.h +++ b/lib/Plugins/SOSreport.h @@ -26,7 +26,7 @@ class CActionSOSreport : public CAction { public: - virtual void Run(const char *pActionDir, const char *pArgs); + virtual void Run(const char *pActionDir, const char *pArgs, int force); }; #endif diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp index 38590f34..0ea2d5b2 100644 --- a/lib/Plugins/TicketUploader.cpp +++ b/lib/Plugins/TicketUploader.cpp @@ -166,7 +166,7 @@ string CTicketUploader::Report(const map_crash_data_t& pCrashData, bool do_upload; int retry_count; int retry_delay; - + /* if parse_settings fails it returns an empty map so we need to use defaults */ map_plugin_settings_t settings = parse_settings(pSettings); // Get ticket name, customer name, and do_encrypt from config settings @@ -275,7 +275,7 @@ string CTicketUploader::Report(const map_crash_data_t& pCrashData, } // generate md5sum - cmd = ssprintf("cd %s; md5sum %s", tmpdir_name, outfile_basename.c_str()); + cmd = ssprintf("cd %s; md5sum <%s", tmpdir_name, outfile_basename.c_str()); string md5sum = ReadCommand(cmd.c_str()); // upload or cp to /tmp @@ -298,13 +298,12 @@ string CTicketUploader::Report(const map_crash_data_t& pCrashData, msg += "Please copy this into ticket: "; msg += ticket_name; msg += '\n'; - msg += "========cut here========="; - msg += '\n'; + msg += "========cut here========\n"; } else { msg += "Please send this to your technical support:\n"; - msg += "========cut here========="; + msg += "========cut here========\n"; } if (do_upload) { @@ -324,7 +323,7 @@ string CTicketUploader::Report(const map_crash_data_t& pCrashData, } msg += "FILE: "; msg += outfile_basename; - msg += "\nMD5SUM:"; + msg += "\nMD5SUM: "; msg += md5sum; msg += '\n'; if (do_encrypt) @@ -337,7 +336,7 @@ string CTicketUploader::Report(const map_crash_data_t& pCrashData, // warn the client (why _warn_? it's not an error, maybe update_client?): //error_msg("%s", msg.c_str()); - + // delete the temporary directory cmd = ssprintf("rm -rf %s", tmpdir_name); RunCommand(cmd.c_str()); diff --git a/lib/Utils/Action.h b/lib/Utils/Action.h index 5992cbff..d9a68b79 100644 --- a/lib/Utils/Action.h +++ b/lib/Utils/Action.h @@ -39,7 +39,7 @@ class CAction : public CPlugin * @param pActionDir An actual directory. * @param pArgs Plugin's arguments. */ - virtual void Run(const char *pActionDir, const char *pArgs) = 0; + virtual void Run(const char *pActionDir, const char *pArgs, int force) = 0; }; #endif diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index a89070e9..c56b7b1c 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -61,7 +61,7 @@ static map_analyzer_actions_and_reporters_t s_mapAnalyzerActionsAndReporters; static vector_pair_string_string_t s_vectorActionsAndReporters; -static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir); +static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir, int force); static char* is_text_file(const char *name, ssize_t *sz) @@ -278,8 +278,8 @@ mw_result_t CreateCrashReport(const char *pUUID, std::string dup_hash = GetGlobalUUID(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); VERB3 log(" DUPHASH:'%s'", dup_hash.c_str()); - VERB3 log(" RunAnalyzerActions('%s','%s')", analyzer.c_str(), row.m_sDebugDumpDir.c_str()); - RunAnalyzerActions(analyzer.c_str(), row.m_sDebugDumpDir.c_str()); + VERB3 log(" RunAnalyzerActions('%s','%s',force=%d)", analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force); + RunAnalyzerActions(analyzer.c_str(), row.m_sDebugDumpDir.c_str(), force); DebugDumpToCrashReport(row.m_sDebugDumpDir.c_str(), pCrashData); @@ -320,7 +320,7 @@ void RunAction(const char *pActionDir, } try { - action->Run(pActionDir, pPluginArgs); + action->Run(pActionDir, pPluginArgs, /*force:*/ 0); } catch (CABRTException& e) { @@ -351,7 +351,7 @@ void RunActionsAndReporters(const char *pDebugDumpDir) { CAction* action = g_pPluginManager->GetAction(plugin_name); /* can't be NULL */ VERB2 log("%s.Run('%s','%s')", plugin_name, pDebugDumpDir, it_ar->second.c_str()); - action->Run(pDebugDumpDir, it_ar->second.c_str()); + action->Run(pDebugDumpDir, it_ar->second.c_str(), /*force:*/ 0); } } catch (CABRTException& e) @@ -747,7 +747,7 @@ void autoreport(const pair_string_string_t& reporter_options, const map_crash_da * @param pAnalyzer A name of an analyzer plugin. * @param pDebugDumpPath A debugdump dir containing all necessary data. */ -static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir) +static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir, int force) { map_analyzer_actions_and_reporters_t::iterator analyzer = s_mapAnalyzerActionsAndReporters.find(pAnalyzer); if (analyzer != s_mapAnalyzerActionsAndReporters.end()) @@ -766,7 +766,7 @@ static void RunAnalyzerActions(const char *pAnalyzer, const char *pDebugDumpDir) } try { - action->Run(pDebugDumpDir, it_a->second.c_str()); + action->Run(pDebugDumpDir, it_a->second.c_str(), force); } catch (CABRTException& e) { -- cgit