133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
|
#
|
||
|
# DBus connections
|
||
|
#
|
||
|
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
|
||
|
#
|
||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||
|
#
|
||
|
import os
|
||
|
|
||
|
from dasbus.connection import SystemMessageBus, MessageBus, SessionMessageBus
|
||
|
from dasbus.constants import DBUS_STARTER_ADDRESS
|
||
|
from dasbus.error import ErrorMapper, get_error_decorator, AbstractErrorRule
|
||
|
from pyanaconda.anaconda_loggers import get_module_logger
|
||
|
from pyanaconda.core.constants import DBUS_ANACONDA_SESSION_ADDRESS, ANACONDA_BUS_ADDR_FILE
|
||
|
from pyanaconda.modules.common.errors import register_errors
|
||
|
|
||
|
log = get_module_logger(__name__)
|
||
|
|
||
|
__all__ = ["DBus", "SystemBus", "SessionBus", "error_mapper", "dbus_error"]
|
||
|
|
||
|
|
||
|
class AnacondaMessageBus(MessageBus):
|
||
|
"""Representation of an Anaconda bus connection."""
|
||
|
|
||
|
@property
|
||
|
def address(self):
|
||
|
"""The bus address."""
|
||
|
return self._find_bus_address()
|
||
|
|
||
|
def _get_connection(self):
|
||
|
"""Get a connection to a bus at the specified address."""
|
||
|
bus_address = self._find_bus_address()
|
||
|
|
||
|
log.info("Connecting to the Anaconda bus at %s.", bus_address)
|
||
|
return self._provider.get_addressed_bus_connection(bus_address)
|
||
|
|
||
|
def _find_bus_address(self):
|
||
|
"""Get the address of the Anaconda bus."""
|
||
|
if DBUS_ANACONDA_SESSION_ADDRESS in os.environ:
|
||
|
return os.environ.get(DBUS_ANACONDA_SESSION_ADDRESS)
|
||
|
|
||
|
if os.path.exists(ANACONDA_BUS_ADDR_FILE):
|
||
|
with open(ANACONDA_BUS_ADDR_FILE, 'rt') as f:
|
||
|
return f.read().strip()
|
||
|
|
||
|
raise ConnectionError("Can't find Anaconda bus address!")
|
||
|
|
||
|
|
||
|
class DefaultMessageBus(AnacondaMessageBus):
|
||
|
"""Representation of a default bus connection."""
|
||
|
|
||
|
def _find_bus_address(self):
|
||
|
"""Get the address of the default bus.
|
||
|
|
||
|
Connect to the bus specified by the environmental variable
|
||
|
DBUS_STARTER_ADDRESS. If it is not specified, connect to
|
||
|
the Anaconda bus.
|
||
|
"""
|
||
|
if DBUS_STARTER_ADDRESS in os.environ:
|
||
|
return os.environ.get(DBUS_STARTER_ADDRESS)
|
||
|
|
||
|
return super()._find_bus_address()
|
||
|
|
||
|
|
||
|
class AnacondaErrorMapper(ErrorMapper):
|
||
|
"""Map Anaconda exceptions to DBus errors."""
|
||
|
|
||
|
def reset_rules(self):
|
||
|
"""Reset rules in the error mapper."""
|
||
|
super().reset_rules()
|
||
|
self.add_rule(DefaultNameErrorRule(
|
||
|
"org.fedoraproject.Anaconda.Error"
|
||
|
))
|
||
|
|
||
|
|
||
|
class DefaultNameErrorRule(AbstractErrorRule):
|
||
|
"""Default rule for mapping an unknown exception to a DBus error name."""
|
||
|
|
||
|
def __init__(self, default_name):
|
||
|
"""Create a new rule.
|
||
|
|
||
|
:param default_name: a default name of a DBus error
|
||
|
"""
|
||
|
self._default_name = default_name
|
||
|
|
||
|
def match_type(self, exception_type):
|
||
|
"""Match every Python exception raised on the server side."""
|
||
|
return True
|
||
|
|
||
|
def get_name(self, exception_type):
|
||
|
"""Return a default error name for every matched exception."""
|
||
|
return self._default_name
|
||
|
|
||
|
def match_name(self, error_name):
|
||
|
"""Don't apply this rule on the client side."""
|
||
|
return False
|
||
|
|
||
|
def get_type(self, error_name):
|
||
|
"""There is no default error type in this rule."""
|
||
|
return None
|
||
|
|
||
|
|
||
|
# System bus.
|
||
|
SystemBus = SystemMessageBus()
|
||
|
|
||
|
# Session bus.
|
||
|
SessionBus = SessionMessageBus()
|
||
|
|
||
|
# The mapper of DBus errors.
|
||
|
error_mapper = AnacondaErrorMapper()
|
||
|
|
||
|
# The decorator for DBus errors.
|
||
|
dbus_error = get_error_decorator(error_mapper)
|
||
|
|
||
|
# Register all DBus errors.
|
||
|
register_errors()
|
||
|
|
||
|
# Default bus. Anaconda uses this connection.
|
||
|
DBus = DefaultMessageBus(
|
||
|
error_mapper=error_mapper
|
||
|
)
|