storage/callback: various fixes
- Removed all own class attributes to avoid name clashes with delegated class attributes. - Implemented the previously missing Pool.usage_details property. - Shadowed all class attributes as instance properties. This is required as the parent classes enforce the class attributes upon the CallbackPool & CallbackVolume classes, but they need to be delegated to the class of the _cb_impl object. We also cannot implement them as class attributes in CallbackVolume & CallbackPool as they need to work for arbitrary backend drivers and two backend drivers must not interfere with each other. Possible alternative: One could dynamically create classes.
This commit is contained in:
parent
d9f1bced22
commit
e5838dbd97
@ -189,9 +189,6 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
```
|
```
|
||||||
'''
|
'''
|
||||||
|
|
||||||
driver = 'callback'
|
|
||||||
config_path = '/etc/qubes_callback.json'
|
|
||||||
|
|
||||||
def __init__(self, *, name, conf_id):
|
def __init__(self, *, name, conf_id):
|
||||||
'''Constructor.
|
'''Constructor.
|
||||||
:param conf_id: Identifier as found inside the user-controlled configuration at `/etc/qubes_callback.json`.
|
:param conf_id: Identifier as found inside the user-controlled configuration at `/etc/qubes_callback.json`.
|
||||||
@ -209,21 +206,22 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
raise qubes.storage.StoragePoolException('conf_id is no String. VM attack?!')
|
raise qubes.storage.StoragePoolException('conf_id is no String. VM attack?!')
|
||||||
self._cb_conf_id = conf_id #: Configuration ID as passed to `__init__()`.
|
self._cb_conf_id = conf_id #: Configuration ID as passed to `__init__()`.
|
||||||
|
|
||||||
with open(CallbackPool.config_path) as json_file:
|
config_path = '/etc/qubes_callback.json'
|
||||||
|
with open(config_path) as json_file:
|
||||||
conf_all = json.load(json_file)
|
conf_all = json.load(json_file)
|
||||||
if not isinstance(conf_all, dict):
|
if not isinstance(conf_all, dict):
|
||||||
raise qubes.storage.StoragePoolException('The file %s is supposed to define a dict.' % CallbackPool.config_path)
|
raise qubes.storage.StoragePoolException('The file %s is supposed to define a dict.' % config_path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._cb_conf = conf_all[self._cb_conf_id] #: Dictionary holding all configuration for the given _cb_conf_id.
|
self._cb_conf = conf_all[self._cb_conf_id] #: Dictionary holding all configuration for the given _cb_conf_id.
|
||||||
except KeyError:
|
except KeyError:
|
||||||
#we cannot throw KeyErrors as we'll otherwise generate incorrect error messages @qubes.app._get_pool()
|
#we cannot throw KeyErrors as we'll otherwise generate incorrect error messages @qubes.app._get_pool()
|
||||||
raise qubes.storage.StoragePoolException('The specified conf_id %s could not be found inside %s.' % (self._cb_conf_id, CallbackPool.config_path))
|
raise qubes.storage.StoragePoolException('The specified conf_id %s could not be found inside %s.' % (self._cb_conf_id, config_path))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bdriver = self._cb_conf['bdriver']
|
bdriver = self._cb_conf['bdriver']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise qubes.storage.StoragePoolException('Missing bdriver for the conf_id %s inside %s.' % (self._cb_conf_id, CallbackPool.config_path))
|
raise qubes.storage.StoragePoolException('Missing bdriver for the conf_id %s inside %s.' % (self._cb_conf_id, config_path))
|
||||||
|
|
||||||
self._cb_cmd_arg = json.dumps(self._cb_conf, sort_keys=True, indent=2) #: Full configuration as string in the format required by _callback().
|
self._cb_cmd_arg = json.dumps(self._cb_conf, sort_keys=True, indent=2) #: Full configuration as string in the format required by _callback().
|
||||||
|
|
||||||
@ -344,7 +342,7 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
def config(self):
|
def config(self):
|
||||||
return {
|
return {
|
||||||
'name': self.name,
|
'name': self.name,
|
||||||
'driver': CallbackPool.driver,
|
'driver': 'callback',
|
||||||
'conf_id': self._cb_conf_id,
|
'conf_id': self._cb_conf_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +393,30 @@ class CallbackPool(qubes.storage.Pool):
|
|||||||
return None
|
return None
|
||||||
return self._cb_impl.usage
|
return self._cb_impl.usage
|
||||||
|
|
||||||
|
@property
|
||||||
|
def usage_details(self):
|
||||||
|
if self._cb_requires_init:
|
||||||
|
return {}
|
||||||
|
return self._cb_impl.usage_details
|
||||||
|
|
||||||
|
#shadow all qubes.storage.Pool class attributes as instance properties
|
||||||
|
#NOTE: this will cause a subtle difference to using an actual _cb_impl instance: CallbackPool.private_img_size will return a property object, Pool.private_img_size the actual value
|
||||||
|
@property
|
||||||
|
def private_img_size(self):
|
||||||
|
return self._cb_impl.private_img_size
|
||||||
|
|
||||||
|
@private_img_size.setter
|
||||||
|
def private_img_size(self, private_img_size):
|
||||||
|
self._cb_impl.private_img_size = private_img_size
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root_img_size(self):
|
||||||
|
return self._cb_impl.root_img_size
|
||||||
|
|
||||||
|
@root_img_size.setter
|
||||||
|
def root_img_size(self, root_img_size):
|
||||||
|
self._cb_impl.root_img_size = root_img_size
|
||||||
|
|
||||||
#remaining method & attribute delegation ("delegation pattern")
|
#remaining method & attribute delegation ("delegation pattern")
|
||||||
#Convention: The methods of this object have priority over the delegated object's methods. All attributes are
|
#Convention: The methods of this object have priority over the delegated object's methods. All attributes are
|
||||||
# passed to the delegated object unless their name starts with '_cb_'.
|
# passed to the delegated object unless their name starts with '_cb_'.
|
||||||
@ -552,6 +574,48 @@ class CallbackVolume(qubes.storage.Volume):
|
|||||||
yield from self._assert_initialized()
|
yield from self._assert_initialized()
|
||||||
return (yield from coro_maybe(self._cb_impl.revert(revision=revision)))
|
return (yield from coro_maybe(self._cb_impl.revert(revision=revision)))
|
||||||
|
|
||||||
|
#shadow all qubes.storage.Volume class attributes as instance properties
|
||||||
|
#NOTE: this will cause a subtle difference to using an actual _cb_impl instance: CallbackVolume.devtype will return a property object, Volume.devtype the actual value
|
||||||
|
@property
|
||||||
|
def devtype(self):
|
||||||
|
return self._cb_impl.devtype
|
||||||
|
|
||||||
|
@devtype.setter
|
||||||
|
def devtype(self, devtype):
|
||||||
|
self._cb_impl.devtype = devtype
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain(self):
|
||||||
|
return self._cb_impl.domain
|
||||||
|
|
||||||
|
@domain.setter
|
||||||
|
def domain(self, domain):
|
||||||
|
self._cb_impl.domain = domain
|
||||||
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
return self._cb_impl.path
|
||||||
|
|
||||||
|
@path.setter
|
||||||
|
def path(self, path):
|
||||||
|
self._cb_impl.path = path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def script(self):
|
||||||
|
return self._cb_impl.script
|
||||||
|
|
||||||
|
@script.setter
|
||||||
|
def script(self, script):
|
||||||
|
self._cb_impl.script = script
|
||||||
|
|
||||||
|
@property
|
||||||
|
def usage(self):
|
||||||
|
return self._cb_impl.usage
|
||||||
|
|
||||||
|
@usage.setter
|
||||||
|
def usage(self, usage):
|
||||||
|
self._cb_impl.usage = usage
|
||||||
|
|
||||||
#remaining method & attribute delegation
|
#remaining method & attribute delegation
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._cb_impl, name)
|
return getattr(self._cb_impl, name)
|
||||||
|
Loading…
Reference in New Issue
Block a user