Преглед изворни кода

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.
3hhh пре 3 година
родитељ
комит
e5838dbd97
1 измењених фајлова са 72 додато и 8 уклоњено
  1. 72 8
      qubes/storage/callback.py

+ 72 - 8
qubes/storage/callback.py

@@ -189,9 +189,6 @@ class CallbackPool(qubes.storage.Pool):
     ```
     '''
 
-    driver = 'callback'
-    config_path = '/etc/qubes_callback.json'
-
     def __init__(self, *, name, conf_id):
         '''Constructor.
         :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?!')
         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)
         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:
             self._cb_conf = conf_all[self._cb_conf_id] #: Dictionary holding all configuration for the given _cb_conf_id.
         except KeyError:
             #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:
             bdriver = self._cb_conf['bdriver']
         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().
 
@@ -344,7 +342,7 @@ class CallbackPool(qubes.storage.Pool):
     def config(self):
         return {
             'name': self.name,
-            'driver': CallbackPool.driver,
+            'driver': 'callback',
             'conf_id': self._cb_conf_id,
         }
 
@@ -395,6 +393,30 @@ class CallbackPool(qubes.storage.Pool):
             return None
         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")
     #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_'.
@@ -552,6 +574,48 @@ class CallbackVolume(qubes.storage.Volume):
         yield from self._assert_initialized()
         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
     def __getattr__(self, name):
         return getattr(self._cb_impl, name)