implement Entropy Error reporting through UGC

This commit is contained in:
Fabio Erculiani
2009-05-31 16:14:07 +02:00
parent 8267090196
commit dee3e35f4f
5 changed files with 175 additions and 4 deletions
+86
View File
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
'''
# DESCRIPTION:
# Entropy Object Oriented Interface
Copyright (C) 2007-2009 Fabio Erculiani
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'''
from entropy.qa import ErrorReportInterface
from entropy.client.interfaces import Client
from entropy.core import SystemSettings
from entropy.exceptions import IncorrectParameter, OnlineMirrorError, \
PermissionDenied
from entropy.i18n import _
class UGCErrorReportInterface(ErrorReportInterface):
"""
Entropy Errors Reporting Interface that works over User Generated
Content (UGC) infrastructure. This version is bound to a specific
repository which MUST provide UGC services, otherwise, the error
submission will fail.
This class will allow Entropy repository maintainers to know about
critical errors happened during normal operation.
Here is an example on how to use this:
error_interface = UGCErrorReportInterface('sabayonlinux.org')
error_interface.prepare()
reported = error_interface.submit()
if reported:
print("error reported succesfully")
else:
print("cannot report error")
"""
def __init__(self, repository_id):
"""
object constructor, repository_id must be a valid repository
identifier.
@param repository_id -- valid repository identifier
@type basestring
"""
ErrorReportInterface.__init__(self)
self.entropy = Client()
self.__repository_id = repository_id
if self.entropy.UGC == None:
# enable UGC
from entropy.client.services.ugc.interfaces import Client as ugc
self.entropy.UGC = ugc(self.entropy)
self.__system_settings = SystemSettings()
if repository_id not in self.__system_settings['repositories']['order']:
raise IncorrectParameter('invalid repository_id provided')
if not self.entropy.UGC.is_repository_eapi3_aware(repository_id):
raise OnlineMirrorError('UGC not supported by the provided repo')
def submit(self):
"""
Overloaded method from ErrorReportInterface.
Does the actual error submission. You must call it after prepare().
@return submission status -- bool
"""
if self.generated:
done, err_msg = self.entropy.UGC.report_error(self.__repository_id,
self.params)
if done:
return True
return False
else:
mytxt = _("Not prepared yet")
raise PermissionDenied("PermissionDenied: %s" % (mytxt,))
+1 -1
View File
@@ -286,4 +286,4 @@ class FileUpdates:
mydict['automerge'] = True
except:
pass
return mydict
return mydict
@@ -703,4 +703,15 @@ class Client(Base):
pkgkey,
xml_string,
)
return self.do_generic_handler(cmd, session_id)
return self.do_generic_handler(cmd, session_id)
def report_error(self, session_id, error_data):
xml_string = self.entropyTools.xml_from_dict(error_data)
cmd = "%s %s %s" % (
session_id,
'ugc:report_error',
xml_string,
)
return self.do_generic_handler(cmd, session_id)
@@ -340,6 +340,9 @@ class Client:
return self.remove_comment(repository, iddoc)
return None,'type not supported locally'
def report_error(self, repository, error_data):
return self.do_cmd(repository, False, "report_error", [error_data], {})
class AuthStore(Singleton):
+73 -2
View File
@@ -26,6 +26,7 @@ import shutil
from entropy.services.skel import SocketCommands
from entropy.const import etpConst
from entropy.services.ugc.interfaces import Server
from entropy.misc import EmailSender
class UGC(SocketCommands):
@@ -45,7 +46,8 @@ class UGC(SocketCommands):
]
self.raw_commands = [
'ugc:add_comment', 'ugc:edit_comment',
'ugc:register_stream','ugc:do_download_stats'
'ugc:register_stream','ugc:do_download_stats',
'ugc:report_error'
]
self.valid_commands = {
@@ -249,6 +251,16 @@ class UGC(SocketCommands):
'syntax': "<SESSION_ID> ugc:do_download_stats <valid xml formatted data>",
'from': unicode(self), # from what class
},
'ugc:report_error': {
'auth': False,
'built_in': False,
'cb': self.docmd_do_report_error,
'args': ["authenticator","myargs"],
'as_user': False,
'desc': "submit an Entropy Error Report",
'syntax': "<SESSION_ID> ugc:report_error <valid xml formatted data>",
'from': unicode(self), # from what class
},
}
def _load_ugc_interface(self):
@@ -765,4 +777,63 @@ class UGC(SocketCommands):
if metadata == None:
return None,'no metadata available'
return metadata,'ok'
return metadata,'ok'
def docmd_do_report_error(self, authenticator, myargs):
if not myargs:
return None, 'wrong arguments'
xml_string = ' '.join(myargs)
try:
mydict = self.entropyTools.dict_from_xml(xml_string)
except Exception, e:
return None, "error: %s" % (e,)
subject = 'Entropy Error Reporting Handler'
destination_email = 'entropy.errors@sabayon.org'
sender_email = mydict.get('email', 'anonymous@sabayon.org')
keys_to_file = ['errordata', 'processes', 'lspci', 'dmesg', 'locale']
# call it over
mail_txt = ''
for key in sorted(mydict):
if key in keys_to_file:
continue
mail_txt += u'%s: %s\n' % (key, mydict.get(key),)
from datetime import datetime
import time
import tempfile
date = datetime.fromtimestamp(time.time())
# add ip address
ip_addr = self._get_session_ip_address(authenticator)
mail_txt += u'ip_address: %s\n' % (ip_addr,)
mail_txt += u'date: %s\n' % (date,)
files = []
rm_paths = []
for key in keys_to_file:
if key not in mydict:
continue
fd, path = tempfile.mkstemp(suffix = "__%s.txt" % (key,))
try:
f_path = open(path, "w")
f_path.write(mydict.get(key,''))
f_path.flush()
f_path.close()
except IOError:
continue
files.append(path)
rm_paths.append(path)
sender = EmailSender()
sender.send_mime_email(sender_email, [destination_email], subject,
mail_txt, files)
del sender
for rm_path in rm_paths:
os.remove(rm_path)
return True,'ok'