import os import logging import report import problem.config class DBusProxy(object): __instance = None def __init__(self, dbus): self._proxy = None self._iface = None self.dbus = dbus self.connected = False self.connect() def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = super(DBusProxy, cls).__new__(cls) return cls.__instance def connect(self): self.connected = False if self._proxy: self._proxy.close() try: self._proxy = self.dbus.SystemBus().get_object( 'org.freedesktop.problems', '/org/freedesktop/problems') except self.dbus.exceptions.DBusException as e: logging.debug('Unable to get dbus proxy: {0}'.format(e)) return try: self._iface = self.dbus.Interface(self._proxy, 'org.freedesktop.problems') except self.dbus.exceptions.DBusException as e: logging.debug('Unable to get dbus interface: {0}'.format(e)) return self.connected = True def _dbus_call(self, fun_name, *args): try: logging.debug('Calling {0} with {1}'.format(fun_name, args)) return getattr(self._iface, fun_name)(*args) except self.dbus.exceptions.DBusException as e: dbname = e.get_dbus_name() if dbname == "org.freedesktop.DBus.Error.ServiceUnknown": self.connect() return getattr(self._iface, fun_name)(*args) if dbname == 'org.freedesktop.problems.AuthFailure': raise problem.exception.AuthFailure(e) if dbname == 'org.freedesktop.problems.InvalidProblemDir': raise problem.exception.InvalidProblem(e) raise def get_item(self, dump_dir, name): val = self._dbus_call('GetInfo', dump_dir, [name]) if name not in val: return None return str(val[name]) def set_item(self, dump_dir, name, value): return self._dbus_call('SetElement', dump_dir, name, str(value)) def del_item(self, dump_dir, name): return self._dbus_call('DeleteElement', dump_dir, name) def create(self, problem_dict): return self._dbus_call('NewProblem', problem_dict) def delete(self, dump_dir): return self._dbus_call('DeleteProblem', [dump_dir]) def list(self): return map(str, self._dbus_call('GetProblems')) def list_all(self): return map(str, self._dbus_call('GetAllProblems')) class SocketProxy(object): def create(self, problem_dict): import socket sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(5) try: sock.connect('/var/run/abrt/abrt.socket') sock.sendall("PUT / HTTP/1.1\r\n\r\n") for key, value in problem_dict.iteritems(): sock.sendall('{0}={1}\0'.format(key.upper(), value)) sock.shutdown(socket.SHUT_WR) resp = '' while True: buf = sock.recv(256) if not buf: break resp += buf return resp except socket.timeout as exc: logging.error('communication with daemon failed: {0}'.format(exc)) return None def get_item(self, *args): raise NotImplementedError def set_item(self, *args): raise NotImplementedError def del_item(self, *args): raise NotImplementedError def delete(self, *args): raise NotImplementedError def list(self, *args): raise NotImplementedError def list_all(self, *args): return self.list(*args) def get_problem_watcher(self): raise NotImplementedError class FsProxy(object): def __init__(self, directory=problem.config.DEFAULT_DUMP_LOCATION): self.directory = directory def create(self, problem_dict): probd = report.problem_data() for key, value in problem_dict.iteritems(): probd.add(key, value) ddir = probd.create_dump_dir(self.directory) ret = ddir.name ddir.close() return ret def _open_ddir(self, dump_dir, readonly=False): flags = 0 if readonly: flags |= report.DD_OPEN_READONLY ddir = report.dd_opendir(dump_dir, flags) if not ddir: raise problem.exception.InvalidProblem( 'Can\'t open directory: {0}'.format(dump_dir)) return ddir def get_item(self, dump_dir, name): ddir = self._open_ddir(dump_dir, readonly=True) flags = (report.DD_FAIL_QUIETLY_EACCES | report.DD_FAIL_QUIETLY_ENOENT | report.DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE) val = ddir.load_text(name, flags) ddir.close() return val def set_item(self, dump_dir, name, value): ddir = self._open_ddir(dump_dir) ddir.save_text(name, str(value)) ddir.close() def del_item(self, dump_dir, name): ddir = self._open_ddir(dump_dir) ddir.delete_item(name) ddir.close() def delete(self, dump_dir): ddir = report.dd_opendir(dump_dir) if not ddir: return not os.path.isdir(dump_dir) ddir.delete() return True def list(self, _all=False): for dir_entry in os.listdir(self.directory): dump_dir = os.path.join(self.directory, dir_entry) if not os.path.isdir(dump_dir) or not os.access(dump_dir, os.R_OK): continue uid = os.getuid() gid = os.getuid() dir_stat = os.stat(dump_dir) if not _all and (dir_stat.st_uid != uid and dir_stat.st_gid != gid): continue ddir = report.dd_opendir(dump_dir, report.DD_OPEN_READONLY) if ddir: ddir.close() yield dump_dir def list_all(self, *args, **kwargs): kwargs.update(dict(_all=True)) return self.list(*args, **kwargs) def get_proxy(): try: import dbus wrapper = DBusProxy(dbus) if wrapper.connected: return wrapper except ImportError: logging.debug('DBus not found') return FsProxy()