Skip to content

Commit

Permalink
Merge pull request #3 from mulkieran/master-branch-3
Browse files Browse the repository at this point in the history
Master branch 3
  • Loading branch information
mulkieran authored Nov 18, 2016
2 parents 79e44f6 + 98d9af4 commit 78723bb
Show file tree
Hide file tree
Showing 21 changed files with 395 additions and 238 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def local_file(name):
],
install_requires = [
'dbus-python',
'into-dbus-python'
'into-dbus-python>=0.03'
],
package_dir={"": "src"},
packages=setuptools.find_packages("src"),
Expand Down
2 changes: 1 addition & 1 deletion src/stratisd_client_dbus/_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ def get_object(object_path):
:returns: the proxy object corresponding to the object path
:rtype: ProxyObject
"""
return Bus.get_bus().get_object(SERVICE, object_path)
return Bus.get_bus().get_object(SERVICE, object_path, introspect=False)
152 changes: 117 additions & 35 deletions src/stratisd_client_dbus/_implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,46 @@
"""

import abc
import enum

import dbus

from into_dbus_python import xformer

def _xformers(key_to_sig):
"""
Get a map from keys to functions from a map of names to signatures.
:param key_to_sig: a map from keys to signatures
:type key_to_sig: dict of object * str
:returns: a map from keys to functions
:rtype: dict of object * xformation function
"""
sig_to_xformers = dict((sig, xformer(sig)) for sig in key_to_sig.values())
return dict((method, sig_to_xformers[sig]) for \
(method, sig) in key_to_sig.items())


class Interface(abc.ABC):
"""
Parent class for an interface hierarchy.
"""

_XFORMERS = dict()

_INTERFACE_NAME = abc.abstractproperty(doc="interface name")
_METHODS = abc.abstractproperty(doc="map from method name to data")
_INPUT_SIGS = \
abc.abstractproperty(doc="map from method name to input signatures")
_OUTPUT_SIGS = \
abc.abstractproperty(doc="map from method name to output signatures")
_XFORMERS = abc.abstractproperty(doc="map from method name to xformer")
_PROPERTY_NAMES = abc.abstractproperty(doc="list of property names")

@classmethod
def callMethod(cls, proxy_object, method_name, *args):
def callMethod(cls, proxy_object, method, *args):
"""
Call a dbus method on a proxy object.
:param proxy_object: the proxy object to invoke the method on
:param method_name: a method name
:param method: a method name
:param args: the arguments to pass to the dbus method
:returns: the result of the call
Expand All @@ -46,13 +65,8 @@ def callMethod(cls, proxy_object, method_name, *args):
This method intentionally permits lower-level exceptions to be
propagated.
"""
input_signature = cls._METHODS[method_name]

if input_signature not in cls._XFORMERS:
cls._XFORMERS[input_signature] = xformer(input_signature)
xformed_args = cls._XFORMERS[input_signature](args)

dbus_method = getattr(proxy_object, method_name)
xformed_args = cls._XFORMERS[method](args)
dbus_method = getattr(proxy_object, method.name)
return dbus_method(*xformed_args, dbus_interface=cls._INTERFACE_NAME)

@classmethod
Expand All @@ -68,7 +82,7 @@ def getProperty(cls, proxy_object, name):
"""
return proxy_object.Get(
cls._INTERFACE_NAME,
name,
name.name,
dbus_interface=dbus.PROPERTIES_IFACE
)

Expand All @@ -78,38 +92,106 @@ class Manager(Interface):
Manager interface.
"""

class MethodNames(enum.Enum):
"""
The method names of the manager interface.
"""
ConfigureSimulator = "ConfigureSimulator"
CreatePool = "CreatePool"
DestroyPool = "DestroyPool"
GetCacheObjectPath = "GetCacheObjectPath"
GetDevObjectPath = "GetDevObjectPath"
GetDevTypes = "GetDevTypes"
GetErrorCodes = "GetErrorCodes"
GetFilesystemObjectPath = "GetFilesystemObjectPath"
GetPoolObjectPath = "GetPoolObjectPath"
GetRaidLevels = "GetRaidLevels"
ListPools = "ListPools"

class PropertyNames(enum.Enum):
"""
Names of the properties of the manager interface.
"""
pass

_INTERFACE_NAME = 'org.storage.stratis1.Manager'

_METHODS = {
"ConfigureSimulator" : "u",
"CreatePool" : "sqas",
"DestroyPool" : "s",
"GetCacheObjectPath" : "s",
"GetDevObjectPath" : "s",
"GetDevTypes" : "",
"GetErrorCodes" : "",
"GetFilesystemObjectPath" : "ss",
"GetPoolObjectPath" : "s",
"GetRaidLevels" : "",
"ListPools" : "",
_INPUT_SIGS = {
MethodNames.ConfigureSimulator : "u",
MethodNames.CreatePool : "sqas",
MethodNames.DestroyPool : "s",
MethodNames.GetCacheObjectPath : "s",
MethodNames.GetDevObjectPath : "s",
MethodNames.GetDevTypes : "",
MethodNames.GetErrorCodes : "",
MethodNames.GetFilesystemObjectPath : "ss",
MethodNames.GetPoolObjectPath : "s",
MethodNames.GetRaidLevels : "",
MethodNames.ListPools : "",
}
_OUTPUT_SIGS = {
MethodNames.ConfigureSimulator : "qs",
MethodNames.CreatePool : "oqs",
MethodNames.DestroyPool : "qs",
MethodNames.GetCacheObjectPath : "oqs",
MethodNames.GetDevObjectPath : "oqs",
MethodNames.GetDevTypes : "",
MethodNames.GetErrorCodes : "a(sqs)",
MethodNames.GetFilesystemObjectPath : "oqs",
MethodNames.GetPoolObjectPath : "oqs",
MethodNames.GetRaidLevels : "a(sqs)",
MethodNames.ListPools : "asqs",
}
_XFORMERS = _xformers(_INPUT_SIGS)


class Pool(Interface):
"""
Pool interface.
"""

class MethodNames(enum.Enum):
"""
Names of the methods of the Pool class.
"""
AddCacheDevs = "AddCacheDevs"
AddDevs = "AddDevs"
CreateFilesystems = "CreateFilesystems"
DestroyFilesystems = "DestroyFilesystems"
ListCacheDevs = "ListCacheDevs"
ListDevs = "ListDevs"
ListFilesystems = "ListFilesystems"
RemoveCacheDevs = "RemoveCacheDevs"
RemoveDevs = "RemoveDevs"

class PropertyNames(enum.Enum):
"""
Names of the properties of the manager interface.
"""
pass

_INTERFACE_NAME = 'org.storage.stratis1.pool'

_METHODS = {
"AddCacheDevs": "as",
"AddDevs": "as",
"CreateFilesystems": "a(sst)",
"DestroyFilesystems": "as",
"ListCacheDevs": "",
"ListDevs": "",
"ListFilesystems": "",
"RemoveCacheDevs": "asi",
"RemoveDevs": "asi"
_INPUT_SIGS = {
MethodNames.AddCacheDevs: "as",
MethodNames.AddDevs: "as",
MethodNames.CreateFilesystems: "a(sst)",
MethodNames.DestroyFilesystems: "as",
MethodNames.ListCacheDevs: "",
MethodNames.ListDevs: "",
MethodNames.ListFilesystems: "",
MethodNames.RemoveCacheDevs: "asi",
MethodNames.RemoveDevs: "asi"
}
_OUTPUT_SIGS = {
MethodNames.AddCacheDevs: "a(oqs)qs",
MethodNames.AddDevs: "a(oqs)qs",
MethodNames.CreateFilesystems: "a(oqs)qs",
MethodNames.DestroyFilesystems: "a(qs)qs",
MethodNames.ListCacheDevs: "asqs",
MethodNames.ListDevs: "asqs",
MethodNames.ListFilesystems: "asqs",
MethodNames.RemoveCacheDevs: "a(qs)qs",
MethodNames.RemoveDevs: "a(qs)qs"
}
_XFORMERS = _xformers(_INPUT_SIGS)
4 changes: 2 additions & 2 deletions src/stratisd_client_dbus/_stratisd_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class StratisdErrorsGen(StratisdConstantsGen):
# pylint: disable=too-few-public-methods

_CLASSNAME = 'StratisdErrors'
_METHODNAME = 'GetErrorCodes'
_METHODNAME = Manager.MethodNames.GetErrorCodes

class StratisdRaidGen(StratisdConstantsGen):
"""
Expand All @@ -118,4 +118,4 @@ class StratisdRaidGen(StratisdConstantsGen):
# pylint: disable=too-few-public-methods

_CLASSNAME = 'StratisdRaidLevels'
_METHODNAME = 'GetRaidLevels'
_METHODNAME = Manager.MethodNames.GetRaidLevels
File renamed without changes.
File renamed without changes.
24 changes: 23 additions & 1 deletion tests/_misc.py → tests/dbus/_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,31 @@
import random
import subprocess

from into_dbus_python import signature

from ._constants import _STRATISD
from ._constants import _STRATISD_EXECUTABLE
from ._constants import _STRATISD_RUST


def checked_call(klass, proxy, method, *args):
"""
Call a method and check that the returned value has the expected signature.
:param type klass: the class representing the interface
:param object proxy: the proxy object
:param method: the method to invoke
:param args: the arguments to pass to the method
:returns: the result of the method
:raises ValueError: if the result type is incorrect
"""
result = klass.callMethod(proxy, method, *args)
# pylint: disable=protected-access
if "".join(signature(x) for x in result) != klass._OUTPUT_SIGS[method]:
raise ValueError("result type does not match signature")
return result


def _device_list(devices, minimum):
"""
Get a randomly selected list of devices with at least ``minimum`` elements.
Expand Down Expand Up @@ -54,6 +75,7 @@ def tearDown(self):
"""
Stop the stratisd simulator and daemon.
"""
# pylint: disable=no-member
self._stratisd.terminate()
self._stratisd.wait()

Expand Down Expand Up @@ -82,7 +104,7 @@ class ServiceR(ServiceABC):

def setUp(self):
self._stratisd = subprocess.Popen(
os.path.join(_STRATISD_RUST, 'target/debug/stratisd')
[os.path.join(_STRATISD_RUST, 'target/debug/stratisd'), '--sim']
)


Expand Down
File renamed without changes.
34 changes: 17 additions & 17 deletions tests/manager/test_create.py → tests/dbus/manager/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@

from .._constants import _DEVICES

from .._misc import checked_call
from .._misc import _device_list
from .._misc import Service

_MN = Manager.MethodNames

class Create2TestCase(unittest.TestCase):
"""
Expand All @@ -45,7 +47,7 @@ def setUp(self):
self._service.setUp()
time.sleep(1)
self._proxy = get_object(TOP_OBJECT)
(_, _) = Manager.callMethod(self._proxy, "ConfigureSimulator", 8)
Manager.callMethod(self._proxy, _MN.ConfigureSimulator, 8)

def tearDown(self):
"""
Expand All @@ -59,20 +61,19 @@ def testCreate(self):
If rc is OK, then pool must exist.
"""
(result, rc, message) = Manager.callMethod(
(result, rc, _) = checked_call(
Manager,
self._proxy,
"CreatePool",
_MN.CreatePool,
self._POOLNAME,
0,
[d.device_node for d in _device_list(_DEVICES, 1)]
)
self.assertIsInstance(result, str)
self.assertIsInstance(rc, int)
self.assertIsInstance(message, str)

(pool, rc1, _) = Manager.callMethod(
(pool, rc1, _) = checked_call(
Manager,
self._proxy,
"GetPoolObjectPath",
_MN.GetPoolObjectPath,
self._POOLNAME
)

Expand Down Expand Up @@ -101,12 +102,12 @@ def setUp(self):
self._proxy = get_object(TOP_OBJECT)
Manager.callMethod(
self._proxy,
"CreatePool",
_MN.CreatePool,
self._POOLNAME,
0,
[d.device_node for d in _device_list(_DEVICES, 1)]
)
(_, _) = Manager.callMethod(self._proxy, "ConfigureSimulator", 8)
Manager.callMethod(self._proxy, _MN.ConfigureSimulator, 8)

def tearDown(self):
"""
Expand All @@ -118,22 +119,21 @@ def testCreate(self):
"""
Create should fail trying to create new pool with same name as previous.
"""
(result, rc, message) = Manager.callMethod(
(_, rc, _) = checked_call(
Manager,
self._proxy,
"CreatePool",
_MN.CreatePool,
self._POOLNAME,
0,
[d.device_node for d in _device_list(_DEVICES, 1)]
)
expected_rc = StratisdErrorsGen.get_object().ALREADY_EXISTS
self.assertEqual(rc, expected_rc)
self.assertIsInstance(result, str)
self.assertIsInstance(rc, int)
self.assertIsInstance(message, str)

(_, rc1, _) = Manager.callMethod(
(_, rc1, _) = checked_call(
Manager,
self._proxy,
"GetPoolObjectPath",
_MN.GetPoolObjectPath,
self._POOLNAME
)

Expand Down
Loading

0 comments on commit 78723bb

Please sign in to comment.