From 91948ede727a83855279bcd3a369b252fbe0e89c Mon Sep 17 00:00:00 2001 From: kos Date: Thu, 15 Dec 2011 16:18:46 +0900 Subject: [PATCH] [crashreport] import plugin. --- configure.ac | 2 + .../Plugins/SystemPlugins/CrashReport/Makefile.am | 7 + .../Plugins/SystemPlugins/CrashReport/__init__.py | 0 .../SystemPlugins/CrashReport/meta/Makefile.am | 3 + .../CrashReport/meta/plugin_crashreport.xml | 16 ++ .../Plugins/SystemPlugins/CrashReport/plugin.py | 320 +++++++++++++++++++++ .../Plugins/SystemPlugins/CrashReport/sender.py | 100 +++++++ lib/python/Plugins/SystemPlugins/Makefile.am | 3 +- 8 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/Makefile.am create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/__init__.py create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile.am create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/meta/plugin_crashreport.xml create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/plugin.py create mode 100644 lib/python/Plugins/SystemPlugins/CrashReport/sender.py diff --git a/configure.ac b/configure.ac index 242f2d8..9044359 100644 --- a/configure.ac +++ b/configure.ac @@ -246,6 +246,8 @@ lib/python/Plugins/SystemPlugins/LEDBrightnessSetup/Makefile lib/python/Plugins/SystemPlugins/LEDBrightnessSetup/meta/Makefile lib/python/Plugins/SystemPlugins/FirmwareUpgrade/Makefile lib/python/Plugins/SystemPlugins/FirmwareUpgrade/meta/Makefile +lib/python/Plugins/SystemPlugins/CrashReport/Makefile +lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile lib/python/Tools/Makefile lib/service/Makefile lib/components/Makefile diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/Makefile.am b/lib/python/Plugins/SystemPlugins/CrashReport/Makefile.am new file mode 100644 index 0000000..26ff78c --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/CrashReport/Makefile.am @@ -0,0 +1,7 @@ +installdir = $(pkglibdir)/python/Plugins/SystemPlugins/CrashReport + +SUBDIRS = meta + +install_PYTHON = __init__.py \ + plugin.py \ + sender.py diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/__init__.py b/lib/python/Plugins/SystemPlugins/CrashReport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile.am new file mode 100644 index 0000000..090d41c --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile.am @@ -0,0 +1,3 @@ +installdir = $(datadir)/meta + +dist_install_DATA = plugin_crashreport.xml diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/meta/plugin_crashreport.xml b/lib/python/Plugins/SystemPlugins/CrashReport/meta/plugin_crashreport.xml new file mode 100644 index 0000000..49fe46a --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/CrashReport/meta/plugin_crashreport.xml @@ -0,0 +1,16 @@ + + + + + + oskwon + CrashReport + enigma2-plugin-systemplugins-crashreport + Automatically report crashlogs to Vu+ + With the CrashReport plugin it is possible to automatically mail crashlogs found on your hard drive to Vu+. + + + + + + diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/plugin.py b/lib/python/Plugins/SystemPlugins/CrashReport/plugin.py new file mode 100644 index 0000000..1850ba1 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/CrashReport/plugin.py @@ -0,0 +1,320 @@ +# twisted-mail twisted-names python-compression python-mime python-email +import os + +from Plugins.Plugin import PluginDescriptor + +from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigText, ConfigSelection, ConfigYesNo,ConfigText +from Components.ConfigList import ConfigListScreen +from Components.ActionMap import ActionMap +from Components.Sources.StaticText import StaticText +from Components.Pixmap import Pixmap +from Components.Label import Label + +from Screens.Screen import Screen +from Screens.VirtualKeyBoard import VirtualKeyBoard +from Screens.ChoiceBox import ChoiceBox +from Screens.MessageBox import MessageBox + +from enigma import ePoint, eConsoleAppContainer + +from Tools.Directories import resolveFilename, SCOPE_PLUGINS + +g_configfile=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/CrashReport/settings") +g_senderfile=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/CrashReport/sender.py") + +g_default_activation = "" +g_default_aftersummit = "" +g_default_optionalinfo = False +g_default_username = "" +g_default_useremail = "" +g_default_machineinfo = True + +def getValue(str): + idx = str.find("=") + #print "---->>[%s][%d][%d]" % (str, len(str), idx) + if idx == len(str): + return "" + elif idx == -1: + return str + return str[idx+1:] + +def saveConfig(activation, aftersummit, machineinfo, optionalinfo, username="", useremail=""): + global g_configfile + configs = [] + configs.append("activation=%s\n" % (activation)) + configs.append("aftersummit=%s\n" % (aftersummit)) + configs.append("optionalinfo=%s\n" % (str(optionalinfo))) + configs.append("username=%s\n" % (username)) + configs.append("useremail=%s\n" % (useremail)) + configs.append("machineinfo=%s\n" % (str(machineinfo))) + + f = open(g_configfile, 'w') + f.writelines(configs) + f.close() + loadConfig() + +def loadConfig(): + global g_configfile + if os.path.exists(g_configfile) == False: + return + global g_default_activation + global g_default_aftersummit + global g_default_optionalinfo + global g_default_username + global g_default_useremail + global g_default_machineinfo + f = open(g_configfile) + conf_list = f.readlines() + f.close() + print "load config : ", conf_list + if len(conf_list) < 6: + return + g_default_activation = getValue(conf_list[0].strip()) + g_default_aftersummit = getValue(conf_list[1].strip()) + if getValue(conf_list[2].strip()) == "True": + g_default_optionalinfo = True + g_default_username = getValue(conf_list[3].strip()) + g_default_useremail = getValue(conf_list[4].strip()) + if getValue(conf_list[5].strip()) == "False": + g_default_machineinfo = False + +class CrashlogReportConfiguration(Screen, ConfigListScreen): + skin = """ + + + + + + + Format:%H:%M + + + + + + + + + + + + + """ + def __init__(self, session): + Screen.__init__(self, session) + self.session = session + + self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ], + { + "ok": self.keyOK, + "cancel": self.keyCancel, + "red": self.keyCancel, + "green": self.keyOK, + }, -2) + self["VirtualKB"] = ActionMap(["VirtualKeyboardActions" ], + { + "showVirtualKeyboard": self.cbSetTitle, + }, -1) + + self.list = [] + ConfigListScreen.__init__(self, self.list, session=self.session) + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Save")) + self["status"] = StaticText(" ") + self["VKeyIcon"] = Pixmap() + self["HelpWindow"] = Pixmap() + + self["VKeyIcon"].hide() + self["VirtualKB"].setEnabled(False) + + self.initGlobal() + self.setupUI() + + def initGlobal(self): + global g_default_activation + global g_default_aftersummit + global g_default_optionalinfo + global g_default_username + global g_default_useremail + global g_default_machineinfo + if g_default_activation == "": + g_default_activation = "send_summit" + if g_default_aftersummit == "": + g_default_aftersummit = "rename" + g_default_optionalinfo + if g_default_username == "": + g_default_username = "Vuplus User" + if g_default_useremail == "": + g_default_useremail = "yourmail@here.is" + self.g_activation = ConfigSelection(default=g_default_activation, choices=[("send_summit", _("Enable")), ("send_disable", _("Disable"))]) + self.g_aftersummit = ConfigSelection(default=g_default_aftersummit, choices=[("rename", _("Rename")), ("delete", _("Delete"))]) + self.g_optionalinfo = ConfigYesNo(default = g_default_optionalinfo) + self.g_username = ConfigText(default = g_default_username, fixed_size = False) + self.g_useremail = ConfigText(default = g_default_useremail, fixed_size = False) + self.g_machineinfo = ConfigYesNo(default = g_default_machineinfo) + + self._activation = getConfigListEntry(_("Activation mode"), self.g_activation) + self._after_action = getConfigListEntry(_("Action after summit"), self.g_aftersummit) + self._add_user_info = getConfigListEntry(_("Include optional infomation"), self.g_optionalinfo) + self._user_info_name = getConfigListEntry(_("User name"), self.g_username) + self._user_info_mail = getConfigListEntry(_("User Email"), self.g_useremail) + self._machineinfo = getConfigListEntry(_("Include settop information"), self.g_machineinfo) + + if not self.cbSelectionChanged in self["config"].onSelectionChanged: + self["config"].onSelectionChanged.append(self.cbSelectionChanged) + + def setupUI(self): + self.list = [] + self.list.append(self._activation) + if self.g_activation.value == "send_summit": + self.list.append(self._after_action) + self.list.append(self._add_user_info) + if self.g_optionalinfo.value: + self.list.append(self._user_info_name) + self.list.append(self._user_info_mail) + self.list.append(self._machineinfo) + self["config"].list = self.list + self["config"].l.setList(self.list) + + def resetUI(self): + if self["config"].getCurrent() == self._activation or self["config"].getCurrent() == self._add_user_info: + self.setupUI() + + def cbSelectionChanged(self): + current = self["config"].getCurrent() + if current == self._activation: + self.enableVKIcon(False) + elif current == self._after_action: + self.enableVKIcon(False) + elif current == self._add_user_info: + self.enableVKIcon(False) + elif current == self._user_info_name: + self.enableVKIcon(True) + elif current == self._user_info_mail: + self.enableVKIcon(True) + elif current == self._machineinfo: + self.enableVKIcon(False) + + def cbSetTitle(self): + t = " " + if self["config"].getCurrent() == self._user_info_mail: + t = "Please enter user email:" + if self["config"].getCurrent() == self._user_info_name: + t = "Please enter user name:" + self.session.openWithCallback(self.NameCallback, VirtualKeyBoard, title = (t), text = self._user_info_name.value) + + def enableVKIcon(self, mode): + if mode: + self["VKeyIcon"].show() + else: + self["VKeyIcon"].hide() + self["VirtualKB"].setEnabled(True) + + def saveConfig(self): + if self.g_optionalinfo.value: + saveConfig(self.g_activation.value, self.g_aftersummit.value, self.g_machineinfo.value, self.g_optionalinfo.value, self.g_username.value, self.g_useremail.value) + else: + saveConfig(self.g_activation.value, self.g_aftersummit.value, self.g_machineinfo.value, self.g_optionalinfo.value) + + def keyLeft(self): + ConfigListScreen.keyLeft(self) + self.resetUI() + + def keyRight(self): + ConfigListScreen.keyRight(self) + self.resetUI() + + def keyOK(self): + self.saveConfig() + self.close() + + def keyCancel(self): + global g_configfile + if os.path.exists(g_configfile) == False: + self.saveConfig() + self.close() + +def main(session, **kwargs): + loadConfig() + session.open(CrashlogReportConfiguration) + +def opensetting(menuid, **kwargs): + if menuid != "system": + return [] + return [(_("Crashlog Reporting"), main, "crashlog_configure", 70)] + +def generateInformation(): + from os import popen + from Tools.DreamboxHardware import getFPVersion + from Components.Harddisk import harddiskmanager + from Components.NimManager import nimmanager + from Components.About import about + def command(cmd): + try: + result = popen(cmd, "r").read().strip() + return str(result) + except: + pass + information = [ + "kernel : %s\n"%(command("uname -a")) + ,"version : %s (%s)\n"%(str(about.getImageVersionString()), str(about.getEnigmaVersionString())) + ,"frontprocessor : %s\n"%(str(getFPVersion())) + ,"frontend : %s\n"%(str(nimmanager.nimList())) + ,"hdd info : %s\n"%(str(harddiskmanager.HDDList())) + ,"network information : \n%s\n"%(command("ifconfig -a")) + ] + f = open("/tmp/machine.info", 'w') + f.writelines(information) + f.close() + +sender = None +def autosubmit(reason, **kwargs): + global g_default_activation + global g_default_aftersummit + global g_default_username + global g_default_useremail + + print "[CrashReport] auto submit" + loadConfig() + import os + def isExistCrashlog(d='/media/hdd'): + for f in os.listdir(d): + if f.startswith("enigma2_crash_") and f.endswith(".log"): + return True + return False + + def cbDataAvail(ret_data): + print ret_data + def cbAppClosed(retval): + if os.path.exists("/tmp/machine.info"): + os.system("rm -f /tmp/machine.info") + + if "session" in kwargs: + if isExistCrashlog() == False: + print "[CrashReport] no crash-log" + return + session = kwargs["session"] + if g_default_activation == "send_summit": + global sender + global g_senderfile + sender = eConsoleAppContainer() + sender.dataAvail.append(cbDataAvail) + sender.appClosed.append(cbAppClosed) + + if g_default_username == "": + un = "Vuplus User" + else: + un = g_default_username + if g_default_useremail == "": + um = "yourmail@here.is" + else: + um = g_default_useremail + if g_default_machineinfo: + generateInformation() + + sender.execute(_("python %s %s %s %s" % (g_senderfile, um, un.replace(" ", "_"), g_default_aftersummit))) + +def Plugins(**kwargs): + return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART], needsRestart = False, fnc = autosubmit), + PluginDescriptor(name=_("CrashlogReportSetting"), description=_("CrashlogReport setting"),where=PluginDescriptor.WHERE_MENU, needsRestart = False, fnc=opensetting)] + diff --git a/lib/python/Plugins/SystemPlugins/CrashReport/sender.py b/lib/python/Plugins/SystemPlugins/CrashReport/sender.py new file mode 100644 index 0000000..d983752 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/CrashReport/sender.py @@ -0,0 +1,100 @@ +import os, mimetypes + +from twisted.internet import reactor +from twisted.mail import smtp, relaymanager + +from email import Encoders +from email.MIMEBase import MIMEBase +from email.MIMEText import MIMEText +from email.MIMEMultipart import MIMEMultipart + +g_config_after_file_status = "" + +def getMailExchange(H): + def cbMX(mxRecord): + return str(mxRecord.name) + return relaymanager.MXCalculator().getMX(H).addCallback(cbMX) + +def getLogList(d): + l = [] + if d is None or d == "": + return l + for f in os.listdir(d): + if f.startswith("enigma2_crash_") and f.endswith(".log"): + print "[CrashReport] found : ", os.path.basename(f) + l.append(d + '/' + f) + return l + +def sendEmail(F, T, M, S="", FL=[]): + def cbError(e): + print "[CrashReport] Error >> \n", e.getErrorMessage() + reactor.stop() + + def cbSuccess(r): + print "[CrashReport] Success >> after action : [%s], success message : [%s]" % (g_config_after_file_status, r) + global g_config_after_file_status + for f in FL: + if f.startswith("/tmp/"): + continue + if g_config_after_file_status == "rename": + n = "%s/%s.summited" % (os.path.dirname(f), os.path.basename(f)) + print "[CrashReport] rename : [%s] to [%s]" % (f,n) + os.rename(f, n) + elif g_config_after_file_status == "delete": + print "[CrashReport] remove : [%s]" % (f) + os.remove(f) + reactor.stop() + + def cbSend(H): + context = MIMEMultipart('alternative') + context['From'] = F + context['To'] = T + context['Subject'] = S + #context['Date'] = smtp.rfc822date() + context['MIME-Version'] = '1.0' + context.attach(MIMEText(M, 'plain')) + + for f in FL: + ctype, encoding = mimetypes.guess_type(f) + if ctype is None or encoding is not None: + ctype = 'application/octet-stream' + maintype, subtype = ctype.split('/', 1) + + tmp = MIMEBase(maintype, subtype) + tmp.set_payload(file(f).read()) + Encoders.encode_base64(tmp) + + tmp.add_header("Content-Transfer-Encoding", 'base64') + tmp.add_header('Content-Disposition', 'attachment', filename=os.path.basename(f)) + tmp.add_header('Content-Description', 'vuplus crashlog') + context.attach(tmp) + + print "[CrashReport] host:[%s], from:[%s], to:[%s]" % (H, F, T) + sending = smtp.sendmail(str(H), F, T, context.as_string()) + sending.addCallback(cbSuccess).addErrback(cbError) + return getMailExchange(T.split("@")[1]).addCallback(cbSend) + +def doSummit(summitTo, summitFrom, summitName, afterFileStatus="rename"): + fileList = getLogList('/media/hdd') + if len(fileList) == 0: + return + + fileListLen = len(fileList) + if os.path.exists("/tmp/machine.info"): + fileList.append("/tmp/machine.info") + + global g_config_after_file_status + g_config_after_file_status = afterFileStatus + summitText = "There are %d crash logs found for you.\n" % (fileListLen) + if summitName is not None or summitName != "": + summitText += "\nSubmitter : %s (%s)\n" % (summitName, summitFrom) + summitText += "\nThis is an automatically generated email from the CrashlogReport-Plugin.\nGood luck.\n" + summitSubject = "Submit automatically generated crashlog." + sendEmail(summitFrom, summitTo, summitText, summitSubject, fileList) + reactor.run() + +import sys +print "[CrashReport] argvs : ", sys.argv +if len(sys.argv) == 4: + doSummit(summitTo='vuplus@code.vuplus.com', summitFrom=sys.argv[1], summitName=sys.argv[2], afterFileStatus=sys.argv[3]) + diff --git a/lib/python/Plugins/SystemPlugins/Makefile.am b/lib/python/Plugins/SystemPlugins/Makefile.am index 802e6cc..0faf422 100755 --- a/lib/python/Plugins/SystemPlugins/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/Makefile.am @@ -5,7 +5,8 @@ SUBDIRS = SoftwareManager FrontprocessorUpgrade PositionerSetup Satfinder \ DefaultServicesScanner NFIFlash DiseqcTester CommonInterfaceAssignment \ CrashlogAutoSubmit CleanupWizard VideoEnhancement WirelessLan NetworkWizard \ TempFanControl FactoryTest Fancontrol FPGAUpgrade WirelessLanSetup ManualFancontrol \ - Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup FirmwareUpgrade + Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup \ + FirmwareUpgrade CrashReport install_PYTHON = \ __init__.py -- 2.7.4