Blame src/python-problem/problem/proxies.py

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