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

Commit

Permalink
Refactor Domain & DomainManager
Browse files Browse the repository at this point in the history
  • Loading branch information
kalkin committed Sep 27, 2016
1 parent a6610ba commit 7138049
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 141 deletions.
110 changes: 15 additions & 95 deletions qubesdbus/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,87 +18,28 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import logging

import dbus.service
from qubesdbus import serialize
from systemd.journal import JournalHandler

import qubesdbus.service

try:
# Check for mypy dependencies pylint: disable=ungrouped-imports
from typing import Any # pylint: disable=unused-import
# Check mypy types. pylint: disable=ungrouped-imports, unused-import
from typing import Any, Union
import dbus
from dbus._dbus import SessionBus
from dbus.service import BusName
except ImportError:
pass

DOMAIN_PROPERTIES = ['attached_volumes',
'autostart',
'backup_timestamp',
# 'block_devices',
'conf_file',
# 'connected_vms',
'default_dispvm',
'default_user',
# 'devices',
'dir_path',
'dir_path_prefix',
'dns',
'features',
'firewall_conf',
'hvm',
'icon_path',
'include_in_backups',
'installed_by_rpm',
'internal',
'ip',
'is_networked',
'is_halted',
'is_paused',
'is_running',
'is_qrexec_running',
'is_outdated',
'kernel',
'kernelopts',
'label',
'mac',
'maxmem',
'memory',
'name',
'netmask',
'netvm',
'qid',
'qrexec_timeout',
# 'storage',
# 'tags',
'template',
'updateable',
'uuid',
'vcpus',
# 'volumes',
'xid', ]

DOMAIN_STATE_PROPERTIES = ['is_halted',
'is_paused',
'is_running',
'is_qrexec_running', ]


class Domain(dbus.service.Object):
def __init__(self, domain, bus, bus_name, path_prefix):
self.bus_path = '/'.join([path_prefix, 'domains', str(domain.qid)])
self.bus_name = bus_name
self.bus = bus
self.properties = serialize.domain(domain)
self.qid = str(domain.qid)
logger_name = 'qubesdbus.domain.' + self.qid
self.log = logging.getLogger(logger_name)
self.log.addHandler(
JournalHandler(level=logging.DEBUG, SYSLOG_IDENTIFIER=logger_name))

dbus.service.Object.__init__(self, self.bus_name, self.bus_path)

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Get(self, _, property_name):
return self.properties[property_name]
class Domain(qubesdbus.service.PropertiesObject):
def __init__(self, bus, bus_name, bus_path, data):
# type: (SessionBus, BusName , str, Dict[Union[str,dbus.String], Any]) -> None
self.properties = data
bus_path = '/'.join([bus_path, 'domains', str(data['qid'])])
name = data['name']
super(Domain, self).__init__(name, data, bus=bus, bus_name=bus_name,
bus_path=bus_path)

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def GetAll(self, _):
Expand All @@ -108,27 +49,6 @@ def GetAll(self, _):
return dbus.Dictionary({k: dbus.String(v)
for k, v in self.properties.items()})

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Set(self, _, name, value): # type: (str, dbus.String, Any) -> None
new_value = value
old_value = self.properties[name]
if new_value == old_value:
self.log.info('%s: Property %s not changed (%s)', self.qid, name,
old_value)
else:
self.properties[name] = value
self.PropertiesChanged("org.freedesktop.DBus.Properties",
{name: value}, [])

@dbus.service.signal(dbus_interface='org.freedesktop.DBus.Properties',
signature="sa{sv}as")
def PropertiesChanged(self, iface_name, changed_properties,
invalidated_properties=None):
# type: (str, Dict[dbus.String, Any], List[dbus.String]) -> None
for name, value in changed_properties.items():
self.log.debug('%s: Property %s changed %s', self.qid, name, value)
pass

@dbus.service.signal(
dbus_interface="org.qubes.DomainManager1.domains.Signals",
signature='s')
Expand Down
60 changes: 15 additions & 45 deletions qubesdbus/domain_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
from gi.repository import GLib
from systemd.journal import JournalHandler

from qubesdbus.interface import _QubesDbusInterface
from qubesdbus.service import _DbusServiceObject
from qubesdbus.service import PropertiesObject
from qubesdbus.domain import Domain
import qubesdbus.serialize

try:
# Check for mypy dependencies pylint: disable=ungrouped-imports
from typing import Any # pylint: disable=unused-import
# Check mypy types. pylint: disable=ungrouped-imports, unused-import
from typing import Any, Union
except ImportError:
pass

Expand All @@ -44,21 +44,11 @@
SYSLOG_IDENTIFIER='qubesdbus.domain_manager'))
log.propagate = True

INTERESTING_PROPERTIES = ['clockvm', 'default_dispvm', 'default_fw_netvm',
'default_kernel', 'default_netvm',
'default_template', 'updatevm']

class DomainManager(_DbusServiceObject, _QubesDbusInterface):
def __init__(self, app):
super(DomainManager, self).__init__()
self.properties = {} # type: Dict[str, Any]
self.identifier = str(app)
self.domains = self.proxify_domains(app.domains)
for p_name in INTERESTING_PROPERTIES:
try:
self.properties[p_name] = str(getattr(app, p_name))
except AttributeError:
self.properties[p_name] = ''
class DomainManager(PropertiesObject):
def __init__(self, data, domains):
# type: (Dict[dbus.String, Any], List[Dict[Union[str,dbus.String], Any]]) -> None
super(DomainManager, self).__init__('DomainManager1', data)
self.domains = [self._proxify_domain(vm) for vm in domains]

@dbus.service.method(dbus_interface="org.freedesktop.DBus.ObjectManager")
def GetManagedObjects(self):
Expand All @@ -70,38 +60,18 @@ def GetManagedObjects(self):
"%s.domains.%s" % (self.bus_name._name, d.qid)
for d in self.domains}

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Get(self, _, property_name):
return self.properties[property_name]

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def GetAll(self, _):
return self.properties

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Set(self, _, property_name, value):
log.info('%s: Property changed %s = %s', self.identifier,
property_name, value)
self.properties[property_name] = value

def proxify_domains(self, domains):
result = []
for vm in domains:
vm_proxy = Domain(vm, self.bus, self.bus_name, self.bus_path)
result.append(vm_proxy)
return result

@dbus.service.method(dbus_interface="org.qubes.Signals1",
in_signature='sava{sv}')
def ForwardSignal(self, event_name, args=None, kwargs=None):
log.warn('Unknown signal %s received %s', event_name, self.identifier)
def _proxify_domain(self, vm):
# type: (Dict[Union[str,dbus.String], Any]) -> Domain
return Domain(self.bus, self.bus_name, self.bus_path, vm)


def main(args=None):
''' Main function ''' # pylint: disable=unused-argument
loop = GLib.MainLoop()
app = qubes.Qubes()
_ = DomainManager(app)
data = qubesdbus.serialize.qubes(app)
domains = [qubesdbus.serialize.domain(vm) for vm in app.domains]
_ = DomainManager(data, domains)
print("Service running...")
loop.run()
print("Service stopped")
Expand Down
74 changes: 73 additions & 1 deletion qubesdbus/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,49 @@

from __future__ import absolute_import

import logging

import dbus
import dbus.mainloop.glib
import dbus.service
from systemd.journal import JournalHandler

from .constants import NAME_PREFIX, PATH_PREFIX, VERSION

dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

try:
# Check mypy types. pylint: disable=ungrouped-imports, unused-import
from typing import Any
from dbus._dbus import SessionBus
from dbus.service import BusName
except ImportError:
pass


class DbusServiceObject(dbus.service.Object):
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)
# avoid pylint super-on-old-class error
dbus.service.Object.__init__(self, self.bus_name, self.bus_path)


class _DbusServiceObject(dbus.service.Object):
def __init__(self):
Expand All @@ -38,5 +74,41 @@ def __init__(self):
str(VERSION)])
self.bus = dbus.SessionBus()
self.bus_name = dbus.service.BusName(bus_name, self.bus)
# avoid pylint super-on-old-class error
dbus.service.Object.__init__(self, self.bus_name, self.bus_path)


class PropertiesObject(DbusServiceObject):
# pylint: disable=invalid-name

def __init__(self, name, data, *args, **kwargs):
self.properties = data
self.id = name
self.log = logging.getLogger(name)
self.log.addHandler(
JournalHandler(level=logging.DEBUG, SYSLOG_IDENTIFIER='qubesdbus.'
+ name))

super(PropertiesObject, self).__init__(*args, **kwargs)

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Get(self, _, property_name):
return self.properties[property_name]

@dbus.service.method(dbus_interface="org.freedesktop.DBus.Properties")
def Set(self, _, name, value): # type: (str, dbus.String, Any) -> None
new_value = value
old_value = self.properties[name]
if new_value == old_value:
self.log.info('%s: Property %s not changed (%s)', self.id, name,
old_value)
else:
self.properties[name] = value
self.PropertiesChanged("org.freedesktop.DBus.Properties",
{name: value}, [])

@dbus.service.signal(dbus_interface='org.freedesktop.DBus.Properties',
signature="sa{sv}as")
def PropertiesChanged(self, _, changed_properties, __=None):
# type: (str, Dict[dbus.String, Any], List[dbus.String]) -> None
for name, value in changed_properties.items():
self.log.debug('%s: Property %s changed %s', self.id, name, value)

0 comments on commit 7138049

Please sign in to comment.