#!/usr/bin/env python3 # Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions # of the GNU General Public License v.2. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import string import random import functools import xml.etree.ElementTree as Et from collections import OrderedDict import dbus BUSNAME = "com.redhat.lvmdbus1" MANAGER_INT = BUSNAME + '.Manager' MANAGER_OBJ = '/' + BUSNAME.replace('.', '/') + '/Manager' PV_INT = BUSNAME + ".Pv" VG_INT = BUSNAME + ".Vg" LV_INT = BUSNAME + ".Lv" THINPOOL_INT = BUSNAME + ".ThinPool" SNAPSHOT_INT = BUSNAME + ".Snapshot" LV_COMMON_INT = BUSNAME + ".LvCommon" JOB_INT = BUSNAME + ".Job" CACHE_POOL_INT = BUSNAME + ".CachePool" CACHE_LV_INT = BUSNAME + ".CachedLv" THINPOOL_LV_PATH = '/' + THINPOOL_INT.replace('.', '/') def rs(length, suffix, character_set=string.ascii_lowercase): return ''.join(random.choice(character_set) for _ in range(length)) + suffix def mib(s): return 1024 * 1024 * s class DbusIntrospection(object): @staticmethod def introspect(xml_representation): interfaces = {} root = Et.fromstring(xml_representation) for c in root: if c.tag == "interface": in_f = c.attrib['name'] interfaces[in_f] = \ dict(methods=OrderedDict(), properties={}) for nested in c: if nested.tag == "method": mn = nested.attrib['name'] interfaces[in_f]['methods'][mn] = OrderedDict() for arg in nested: if arg.tag == 'arg': arg_dir = arg.attrib['direction'] if arg_dir == 'in': n = arg.attrib['name'] else: n = None arg_type = arg.attrib['type'] if n: v = dict( name=mn, a_dir=arg_dir, a_type=arg_type) interfaces[in_f]['methods'][mn][n] = v elif nested.tag == 'property': pn = nested.attrib['name'] p_access = nested.attrib['access'] p_type = nested.attrib['type'] interfaces[in_f]['properties'][pn] = \ dict(p_access=p_access, p_type=p_type) else: pass # print('Interfaces...') # for k, v in list(interfaces.items()): # print('Interface %s' % k) # if v['methods']: # for m, args in list(v['methods'].items()): # print(' method: %s' % m) # for a, aa in args.items(): # print(' method arg: %s' % (a)) # if v['properties']: # for p, d in list(v['properties'].items()): # print(' Property: %s' % (p)) # print('End interfaces') return interfaces class RemoteObject(object): def _set_props(self, props=None): # print 'Fetching properties' if not props: # prop_fetch = dbus.Interface(self.bus.get_object( # BUSNAME, self.object_path), 'org.freedesktop.DBus.Properties') for i in range(0, 3): try: prop_fetch = dbus.Interface(self.bus.get_object( BUSNAME, self.object_path), 'org.freedesktop.DBus.Properties') props = prop_fetch.GetAll(self.interface) break except dbus.exceptions.DBusException as dbe: if "GetAll" not in str(dbe): raise dbe if props: for kl, vl in list(props.items()): setattr(self, kl, vl) def __init__(self, specified_bus, object_path, interface, properties=None): self.object_path = object_path self.interface = interface self.bus = specified_bus self.dbus_method = dbus.Interface(specified_bus.get_object( BUSNAME, self.object_path), self.interface) self._set_props(properties) def __getattr__(self, item): if hasattr(self.dbus_method, item): return functools.partial(self._wrapper, item) else: return functools.partial(self, item) def _wrapper(self, _method_name, *args, **kwargs): return getattr(self.dbus_method, _method_name)(*args, **kwargs) def update(self): self._set_props() class ClientProxy(object): @staticmethod def _intf_short_name(nm): return nm.split('.')[-1:][0] def __init__(self, specified_bus, object_path, interface=None, props=None): i = dbus.Interface(specified_bus.get_object( BUSNAME, object_path), 'org.freedesktop.DBus.Introspectable') self.intro_spect = DbusIntrospection.introspect(i.Introspect()) for k in self.intro_spect.keys(): sn = ClientProxy._intf_short_name(k) # print('Client proxy has interface: %s %s' % (k, sn)) if interface and interface == k and props is not None: ro = RemoteObject(specified_bus, object_path, k, props) else: ro = RemoteObject(specified_bus, object_path, k) setattr(self, sn, ro) self.object_path = object_path def update(self): # Go through all interfaces and update them for int_f in self.intro_spect.keys(): sn = ClientProxy._intf_short_name(int_f) getattr(self, sn).update()