implement Entropy Error reporting through UGC
This commit is contained in:
@@ -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,))
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user