Skip to content
This repository has been archived by the owner on Apr 26, 2020. It is now read-only.

Commit

Permalink
Refactor the qubesdbus model objects
Browse files Browse the repository at this point in the history
- Remove a lot of initialization logic from `DbusServiceObject`
- The `ObjectManager` class is now responsible for managing the `dbus.Session`
  and `dbus.service.BusName`
  • Loading branch information
kalkin committed Jun 27, 2017
2 parents f1a0dbd + 99f8fb3 commit e61410f
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 58 deletions.
43 changes: 32 additions & 11 deletions qubesdbus/domain_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import qubesadmin
import qubesdbus.serialize
from qubesdbus.models import Domain
from qubesdbus.service import ObjectManager, PropertiesObject
from qubesdbus.service import PropertiesObject

import gi # isort:skip
gi.require_version('Gtk', '3.0') # isort:skip
Expand All @@ -45,9 +45,12 @@
DBusString = Union[str, dbus.String]
DBusProperties = Dict[DBusString, Any]

SERVICE_NAME = 'org.qubes.DomainManager1'
SERVICE_PATH = '/org/qubes/DomainManager1'
INTERFACE = 'org.qubes.DomainManager1'

class DomainManager(PropertiesObject, ObjectManager):

class DomainManager(PropertiesObject):
''' The `DomainManager` is the equivalent to the `qubes.Qubes` object for
managing domains. Implements:
* `org.freedesktop.DBus.ObjectManager` interface for acquiring all the
Expand All @@ -57,22 +60,40 @@ class DomainManager(PropertiesObject, ObjectManager):
'''

def __init__(self, qubes_data: DBusProperties, domains: List[DBusProperties]) -> None:
super(DomainManager, self).__init__('DomainManager1', INTERFACE, qubes_data)
bus = dbus.SessionBus()
bus_name = dbus.service.BusName(SERVICE_NAME, bus=bus,
allow_replacement=True,
replace_existing=True)
super().__init__(bus_name, SERVICE_PATH, INTERFACE, qubes_data)
self.bus_name = bus_name
self.bus = bus
self.managed_objects = [self._proxify_domain(vm) for vm in domains]
self.state_signals = {
'Starting': self.Starting,
'Started' : self.Started,
'Failed' : self.Failed,
'Halting' : self.Halting,
'Halted' : self.Halted,
'Unknown' : lambda _, __: None,
'Started': self.Started,
'Failed': self.Failed,
'Halting': self.Halting,
'Halted': self.Halted,
'Unknown': lambda _, __: None,
}
self.signal_matches = {} # type: Dict[dbus.ObjectPath, List[DBusSignalMatch]]
self.signal_matches = {
} # type: Dict[dbus.ObjectPath, List[DBusSignalMatch]]

for domain in self.managed_objects:
obj_path = domain._object_path # pylint: disable=protected-access
obj_path = domain._object_path # pylint: disable=protected-access
self._setup_signals(obj_path)

@dbus.service.method(dbus_interface="org.freedesktop.DBus.ObjectManager",
out_signature="a{oa{sa{sv}}}")
def GetManagedObjects(self):
''' Returns the domain objects paths and their supported interfaces and
properties.
''' # pylint: disable=protected-access
return {
o._object_path: o.properties_iface()
for o in self.managed_objects
}

def _setup_signals(self, obj_path: dbus.ObjectPath):
def emit_state_signal(dbus_interface,
changed_properties: DBusProperties,
Expand Down Expand Up @@ -186,7 +207,7 @@ def RemoveDomain(self, vm_dbus_path, execute=False):

def _proxify_domain(self, vm):
# type: (Dict[Union[str,DBusString], Any]) -> Domain
return Domain(self.bus, self.bus_name, self.bus_path, vm)
return Domain(self.bus_name, SERVICE_PATH, vm)


def main(args=None): # pylint: disable=unused-argument
Expand Down
11 changes: 7 additions & 4 deletions qubesdbus/labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@

import qubesadmin
import qubesdbus.serialize
from qubesdbus.service import ObjectManager, PropertiesObject
from qubesdbus.service import ObjectManager
from qubesdbus.models import Label

import gi # isort:skip
gi.require_version('Gtk', '3.0') # isort:skip
from gi.repository import GLib # isort:skip pylint:disable=wrong-import-position

log = logging.getLogger('org.qubes.Labels1')
SERVICE_NAME = "org.qubes.Labels1"
SERVICE_PATH = "/org/qubes/Labels1"

log = logging.getLogger(SERVICE_NAME)
log.addHandler(JournalHandler(SYSLOG_IDENTIFIER='qubesdbus.labels'))
log.setLevel(logging.INFO)

Expand All @@ -44,11 +47,11 @@ class Labels(ObjectManager):
'''

def __init__(self, labels_data):
super(Labels, self).__init__()
super().__init__(SERVICE_NAME, SERVICE_PATH)
self.managed_objects = [self._new_label(d) for d in labels_data]

def _new_label(self, label_data):
return Label(self.bus, self.bus_name, self.bus_path, label_data)
return Label(self.bus_name, SERVICE_PATH, label_data)



Expand Down
28 changes: 15 additions & 13 deletions qubesdbus/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,33 @@
* *org.qubes.Label*
'''

import os.path
from typing import Any, Dict, Union

import dbus
from dbus.exceptions import ValidationException
import dbus.service
from dbus._dbus import SessionBus
from dbus.exceptions import ValidationException
from dbus.service import BusName

import qubesadmin
import qubesdbus.service

DBusString = Union[str, dbus.String]

INTERFACE = 'org.qubes.Domain'


class Domain(qubesdbus.service.PropertiesObject):
''' `Domain` is managed by `DomainManager1` and represents a domain. Its D-Bus
object path is `/org/qubes/DomainManager1/domains/QID`
'''
INTERFACE = 'org.qubes.Domain'

def __init__(self, bus: SessionBus, bus_name: BusName, bus_path: str,
def __init__(self, bus_name: BusName, path_prefix: str,
data: Dict[Union[str, dbus.String], Any]) -> None:
self.properties = data
bus_path = '/'.join([bus_path, 'domains', str(data['qid'])])
obj_path = os.path.join(path_prefix, 'domains', str(data['qid']))

super().__init__(bus_name, obj_path, Domain.INTERFACE, data)

self.name = data['name']
super(Domain, self).__init__(self.name, INTERFACE, data, bus=bus,
bus_name=bus_name, bus_path=bus_path)

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Set(self, interface, name,
Expand Down Expand Up @@ -124,13 +123,16 @@ def valid_state_change(cur_state: DBusString, state: DBusString) -> bool:

return False


class Label(qubesdbus.service.PropertiesObject):
''' Represents a qubes label. Its D-Bus object path is
`org/qubes/Labels1/labels/COLORNAME`
'''

def __init__(self, bus, bus_name, bus_path, data):
bus_path = '/'.join([bus_path, 'labels', data['name']])
INTERFACE = 'org.qubes.Label1'

def __init__(self, bus_name, prefix_path, data):
name = data['name']
super(Label, self).__init__(name, 'org.qubes.Label1', data, bus=bus,
bus_name=bus_name, bus_path=bus_path)
obj_path = os.path.join(prefix_path, 'labels', name)
super(Label, self).__init__(bus_name, obj_path, Label.INTERFACE, data)

49 changes: 19 additions & 30 deletions qubesdbus/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,9 @@ class DbusServiceObject(dbus.service.Object):
''' A class implementing a useful shortcut for writing own D-Bus Services
'''

def __init__(self, bus=None, bus_name=None, bus_path=None):
# type: (SessionBus, BusName, str) -> None
if bus is not None:
self.bus = bus
else:
self.bus = dbus.SessionBus()

if bus_path is not None:
self.bus_path = bus_path
else:
self.bus_path = ''.join([PATH_PREFIX, '/', self.__class__.__name__,
str(VERSION)])

if bus_name is not None:
self.bus_name = bus_name
else:
_name = ''.join([NAME_PREFIX, '.', self.__class__.__name__,
str(VERSION)])
self.bus_name = dbus.service.BusName(_name, self.bus)
super(DbusServiceObject, self).__init__(self.bus_name, self.bus_path)
def __init__(self, bus_name: dbus.service.BusName, obj_path: str):
super(DbusServiceObject, self).__init__(bus_name=bus_name,
object_path=obj_path)


class ObjectManager(DbusServiceObject):
Expand All @@ -75,9 +58,13 @@ class ObjectManager(DbusServiceObject):
'''

# pylint: disable=too-few-public-methods
def __init__(self, bus=None, bus_name=None, bus_path=None):
super(ObjectManager, self).__init__(bus=bus, bus_name=bus_name,
bus_path=bus_path)
def __init__(self, name: str, obj_path: str):
bus = dbus.SessionBus()
bus_name = dbus.service.BusName(name, bus=bus, allow_replacement=True,
replace_existing=True)
super().__init__(bus_name=bus_name, obj_path=obj_path)
self.bus_name = bus_name
self.bus = bus
self.managed_objects = [] # type: PropertiesObject

@dbus.service.method(dbus_interface="org.freedesktop.DBus.ObjectManager",
Expand All @@ -94,16 +81,18 @@ class PropertiesObject(DbusServiceObject):
# pylint: disable=invalid-name
''' Implements `org.freedesktop.DBus.Properties` interface. '''

def __init__(self, name, iface, data, *args, **kwargs):
def __init__(self, bus_name: dbus.service.BusName, obj_path: str,
iface: str, data: dict):
assert iface, "No interface provided for PropertiesObject"

super().__init__(bus_name, obj_path)

self.properties = data
self.id = name
self.id = obj_path
self.iface = iface
self.log = logging.getLogger(name)
self.log = logging.getLogger(obj_path)
self.log.addHandler(
JournalHandler(level=logging.DEBUG, SYSLOG_IDENTIFIER='qubesdbus.'
+ name))

super(PropertiesObject, self).__init__(*args, **kwargs)
JournalHandler(level=logging.DEBUG, SYSLOG_IDENTIFIER=obj_path))

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Get(self, interface, property_name):
Expand Down

0 comments on commit e61410f

Please sign in to comment.