storage/callback: make pylint happy

This commit is contained in:
3hhh 2020-06-30 11:24:15 +02:00
parent efa0d7c257
commit 5530265b27
No known key found for this signature in database
GPG Key ID: EB03A691DB2F0833

View File

@ -19,7 +19,6 @@
import logging import logging
import subprocess import subprocess
import importlib
import json import json
from shlex import quote from shlex import quote
@ -217,37 +216,41 @@ class CallbackPool(qubes.storage.Pool):
return bool(cmd and cmd != '-') return bool(cmd and cmd != '-')
def _init(self, callback=True): def _init(self, callback=True):
#late initialization on first use for e.g. decryption on first usage request ''' Late storage initialization on first use for e.g. decryption on first usage request.
:param callback: Whether to trigger the `on_sinit` callback or not.
'''
#maybe TODO: if this function is meant to be run in parallel (are Pool operations asynchronous?), a function lock is required! #maybe TODO: if this function is meant to be run in parallel (are Pool operations asynchronous?), a function lock is required!
if callback: if callback:
self._callback('on_sinit') self._callback('on_sinit')
self._cb_requires_init = False self._cb_requires_init = False
def _assertInitialized(self, **kwargs): def _assert_initialized(self, **kwargs):
if self._cb_requires_init: if self._cb_requires_init:
self._init(**kwargs) self._init(**kwargs)
def _callback(self, cb, cb_args=[], log=logging.getLogger('qubes.storage.callback')): def _callback(self, cb, cb_args=None, log=logging.getLogger('qubes.storage.callback')):
'''Run a callback. '''Run a callback.
:param cb: Callback identifier string. :param cb: Callback identifier string.
:param cb_args: Optional arguments to pass to the command as last arguments. :param cb_args: Optional list of arguments to pass to the command as last arguments.
Only passed on for the generic command specified as `cmd`, not for `on_xyz` callbacks. Only passed on for the generic command specified as `cmd`, not for `on_xyz` callbacks.
''' '''
if self._cb_ctor_done: if self._cb_ctor_done:
cmd = self._cb_conf.get(cb) cmd = self._cb_conf.get(cb)
args = [] #on_xyz callbacks should never receive arguments args = [] #on_xyz callbacks should never receive arguments
if not cmd: if not cmd:
if cb_args is None:
cb_args = []
cmd = self._cb_conf.get('cmd') cmd = self._cb_conf.get('cmd')
args = [self.name, self._cb_conf['bdriver'], cb, self._cb_cmd_arg, *cb_args] args = [self.name, self._cb_conf['bdriver'], cb, self._cb_cmd_arg, *cb_args]
if cmd and cmd != '-': if cmd and cmd != '-':
args = filter(None, args) args = filter(None, args)
args = ' '.join(quote(str(a)) for a in args) args = ' '.join(quote(str(a)) for a in args)
cmd = ' '.join(filter(None, [cmd, args])) cmd = ' '.join(filter(None, [cmd, args]))
log.info('callback driver executing (%s, %s %s): %s' % (self._cb_conf_id, cb, cb_args, cmd)) log.info('callback driver executing (%s, %s %s): %s', self._cb_conf_id, cb, cb_args, cmd)
res = subprocess.run(['/bin/bash', '-c', cmd], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) res = subprocess.run(['/bin/bash', '-c', cmd], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
#stdout & stderr are reported if the exit code check fails #stdout & stderr are reported if the exit code check fails
log.debug('callback driver stdout (%s, %s %s): %s' % (self._cb_conf_id, cb, cb_args, res.stdout)) log.debug('callback driver stdout (%s, %s %s): %s', self._cb_conf_id, cb, cb_args, res.stdout)
log.debug('callback driver stderr (%s, %s %s): %s' % (self._cb_conf_id, cb, cb_args, res.stderr)) log.debug('callback driver stderr (%s, %s %s): %s', self._cb_conf_id, cb, cb_args, res.stderr)
if self._cb_conf.get('signal_back', False) is True: if self._cb_conf.get('signal_back', False) is True:
self._process_signals(res.stdout, log) self._process_signals(res.stdout, log)
@ -258,13 +261,8 @@ class CallbackPool(qubes.storage.Pool):
''' '''
for line in out.splitlines(): for line in out.splitlines():
if line == 'SIGNAL_setup': if line == 'SIGNAL_setup':
log.info('callback driver processing SIGNAL_setup for %s' % self._cb_conf_id) log.info('callback driver processing SIGNAL_setup for %s', self._cb_conf_id)
self.setup(callback=False) self._setup_cb(callback=False)
def __del__(self):
s = super()
if hasattr(s, '__del__'):
s.__del__()
@property @property
def config(self): def config(self):
@ -275,7 +273,7 @@ class CallbackPool(qubes.storage.Pool):
} }
def destroy(self): def destroy(self):
self._assertInitialized() self._assert_initialized()
ret = self._cb_impl.destroy() ret = self._cb_impl.destroy()
self._callback('on_destroy') self._callback('on_destroy')
return ret return ret
@ -283,12 +281,15 @@ class CallbackPool(qubes.storage.Pool):
def init_volume(self, vm, volume_config): def init_volume(self, vm, volume_config):
return CallbackVolume(self, self._cb_impl.init_volume(vm, volume_config)) return CallbackVolume(self, self._cb_impl.init_volume(vm, volume_config))
def setup(self, callback=True): def _setup_cb(self, callback=True):
if callback: if callback:
self._callback('on_setup') self._callback('on_setup')
self._assertInitialized(callback=False) #setup is assumed to include initialization self._assert_initialized(callback=False) #setup is assumed to include storage initialization
return self._cb_impl.setup() return self._cb_impl.setup()
def setup(self):
return self._setup_cb()
@property @property
def volumes(self): def volumes(self):
for vol in self._cb_impl.volumes: for vol in self._cb_impl.volumes:
@ -304,21 +305,18 @@ class CallbackPool(qubes.storage.Pool):
def included_in(self, app): def included_in(self, app):
if self._cb_requires_init: if self._cb_requires_init:
return None return None
else:
return self._cb_impl.included_in(app) return self._cb_impl.included_in(app)
@property @property
def size(self): def size(self):
if self._cb_requires_init: if self._cb_requires_init:
return None return None
else:
return self._cb_impl.size return self._cb_impl.size
@property @property
def usage(self): def usage(self):
if self._cb_requires_init: if self._cb_requires_init:
return None return None
else:
return self._cb_impl.usage return self._cb_impl.usage
#remaining method & attribute delegation ("delegation pattern") #remaining method & attribute delegation ("delegation pattern")
@ -361,72 +359,72 @@ class CallbackVolume:
self._cb_pool = pool self._cb_pool = pool
self._cb_impl = impl self._cb_impl = impl
def _assertInitialized(self, **kwargs): def _assert_initialized(self, **kwargs):
return self._cb_pool._assertInitialized(**kwargs) return self._cb_pool._assert_initialized(**kwargs) # pylint: disable=protected-access
def _callback(self, cb, cb_args=[], **kwargs): def _callback(self, cb, cb_args=None, **kwargs):
vol_args = [ *cb_args, self.name, self.vid ] if cb_args is None:
return self._cb_pool._callback(cb, cb_args=vol_args, **kwargs) cb_args = []
vol_args = [self.name, self.vid, *cb_args]
return self._cb_pool._callback(cb, cb_args=vol_args, **kwargs) # pylint: disable=protected-access
def create(self): def create(self):
self._assertInitialized() self._assert_initialized()
self._callback('on_volume_create') self._callback('on_volume_create')
return self._cb_impl.create() return self._cb_impl.create()
def remove(self): def remove(self):
self._assertInitialized() self._assert_initialized()
ret = self._cb_impl.remove() ret = self._cb_impl.remove()
self._callback('on_volume_remove') self._callback('on_volume_remove')
return ret return ret
def resize(self, size): def resize(self, size):
self._assertInitialized() self._assert_initialized()
self._callback('on_volume_resize', cb_args=[size]) self._callback('on_volume_resize', cb_args=[size])
return self._cb_impl.resize(size) return self._cb_impl.resize(size)
def start(self): def start(self):
self._assertInitialized() self._assert_initialized()
self._callback('on_volume_start') self._callback('on_volume_start')
return self._cb_impl.start() return self._cb_impl.start()
def stop(self): def stop(self):
self._assertInitialized() self._assert_initialized()
ret = self._cb_impl.stop() ret = self._cb_impl.stop()
self._callback('on_volume_stop') self._callback('on_volume_stop')
return ret return ret
def import_data(self): def import_data(self):
self._assertInitialized() self._assert_initialized()
self._callback('on_volume_import_data') self._callback('on_volume_import_data')
return self._cb_impl.import_data() return self._cb_impl.import_data()
def import_data_end(self, success): def import_data_end(self, success):
self._assertInitialized() self._assert_initialized()
ret = self._cb_impl.import_data_end(success) ret = self._cb_impl.import_data_end(success)
self._callback('on_volume_import_data_end', cb_args=[success]) self._callback('on_volume_import_data_end', cb_args=[success])
return ret return ret
def import_volume(self, src_volume): def import_volume(self, src_volume):
self._assertInitialized() self._assert_initialized()
self._callback('on_volume_import', cb_args=[src_volume.vid]) self._callback('on_volume_import', cb_args=[src_volume.vid])
return self._cb_impl.import_volume(src_volume) return self._cb_impl.import_volume(src_volume)
def is_dirty(self): def is_dirty(self):
if self._cb_pool._cb_requires_init: if self._cb_pool._cb_requires_init: # pylint: disable=protected-access
return False return False
else:
return self._cb_impl.is_dirty() return self._cb_impl.is_dirty()
def is_outdated(self): def is_outdated(self):
if self._cb_pool._cb_requires_init: if self._cb_pool._cb_requires_init: # pylint: disable=protected-access
return False return False
else:
return self._cb_impl.is_outdated() return self._cb_impl.is_outdated()
#remaining method & attribute delegation #remaining method & attribute delegation
def __getattr__(self, name): def __getattr__(self, name):
if name in ['block_device', 'verify', 'revert', 'export']: if name in ['block_device', 'verify', 'revert', 'export']:
self._assertInitialized() self._assert_initialized()
return getattr(self._cb_impl, name) return getattr(self._cb_impl, name)
def __setattr__(self, name, value): def __setattr__(self, name, value):