diff --git a/Makefile b/Makefile index 01edd38a..99d1491d 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,6 @@ endif # $(MAKE) install -C tests $(MAKE) install -C relaxng mkdir -p $(DESTDIR)/etc/qubes - cp etc/storage.conf $(DESTDIR)/etc/qubes/ ifeq ($(BACKEND_VMM),xen) # Currently supported only on xen cp etc/qmemman.conf $(DESTDIR)/etc/qubes/ diff --git a/etc/storage.conf b/etc/storage.conf deleted file mode 100644 index 78fd2a3a..00000000 --- a/etc/storage.conf +++ /dev/null @@ -1,13 +0,0 @@ -[default] ; poolname -driver=xen ; the default xen storage -; class = qubes.storage.xen.XenStorage ; class always overwrites the driver -; -; To use our own pool driver it needs to provide `qubes.storage` entry_point -; see also: https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins -; class name -; [pool-b] -; driver = foo -; -; [test-dummy] -; driver=dummy - diff --git a/qubes/__init__.py b/qubes/__init__.py index bd4ab466..e25b1e1d 100644 --- a/qubes/__init__.py +++ b/qubes/__init__.py @@ -48,8 +48,6 @@ import time import __builtin__ -import docutils.core -import docutils.io import jinja2 import lxml.etree import pkg_resources @@ -1190,8 +1188,8 @@ class Qubes(PropertyHolder): #: collection of all available labels for VMs self.labels = {} - #: collection of all available pool configurations - self.pool_configs = {} + #: collection of all pools + self.pools = {} #: Connection to VMM self.vmm = VMMConnection() @@ -1262,9 +1260,11 @@ class Qubes(PropertyHolder): for node in self.xml.xpath('./pools/pool'): name = node.get('name') - config_data = node.attrib - del(config_data['name']) - self.pool_configs[name] = config_data + assert name, "Pool name '%s' is invalid " % name + try: + self.pools[name] = self._get_pool(**node.attrib) + except qubes.exc.QubesException as e: + self.log.error(e.message) # stage 2: load VMs for node in self.xml.xpath('./domains/domain'): @@ -1400,7 +1400,9 @@ class Qubes(PropertyHolder): 7: Label(7, '0x75507b', 'purple'), 8: Label(8, '0x000000', 'black'), } - self.pool_configs['default'] = qubes.config.defaults['pool_config'] + for name, config in qubes.config.defaults['pool_configs'].items(): + self.pools[name] = self._get_pool(**config) + self.domains.add( qubes.vm.adminvm.AdminVM(self, None, qid=0, name='dom0')) self.save() @@ -1421,12 +1423,12 @@ class Qubes(PropertyHolder): def xml_pool_configs(self): """ Helper for converting pools config to xml """ - pools = lxml.etree.Element('pools') - for config_data in self.pool_configs.values(): - p = lxml.etree.Element('pool', **config_data) - pools.append(p) + pools_xml = lxml.etree.Element('pools') + for pool in self.pools.values(): + p = lxml.etree.Element('pool', **pool.config) + pools_xml.append(p) - return pools + return pools_xml def get_vm_class(self, clsname): '''Find the class for a domain. @@ -1487,6 +1489,48 @@ class Qubes(PropertyHolder): raise KeyError(label) + def add_pool(self, **kwargs): + """ Add a storage pool to config.""" + name = kwargs['name'] + self.pools[name] = self._get_pool(**kwargs) + self.save() + + def remove_pool(self, name): + """ Remove a storage pool from config file. """ + try: + del self.pools[name] + except KeyError: + return + + self.save() + + def get_pool(self, name): + ''' Returns a :py:class:`qubes.storage.Pool` instance ''' + try: + return self.pools[name] + except KeyError: + raise qubes.exc.QubesException('Unknown storage pool ' + name) + + def _get_pool(self, **kwargs): + try: + name = kwargs['name'] + assert name, 'Name needs to be an non empty string' + except KeyError: + raise qubes.exc.QubesException('No pool name for pool') + + try: + driver = kwargs['driver'] + except KeyError: + raise qubes.exc.QubesException('No driver specified for pool ' + + name) + try: + klass = qubes.get_entry_point_one( + qubes.storage.STORAGE_ENTRY_POINT, driver) + del kwargs['driver'] + return klass(**kwargs) + except KeyError: + raise qubes.exc.QubesException('Driver %s for pool %s' % + (driver, name)) @qubes.events.handler('domain-pre-delete') def on_domain_pre_deleted(self, event, vm): diff --git a/qubes/storage/__init__.py b/qubes/storage/__init__.py index bcbdb0d9..c53e68c6 100644 --- a/qubes/storage/__init__.py +++ b/qubes/storage/__init__.py @@ -28,7 +28,6 @@ from __future__ import absolute_import -import ConfigParser import os import os.path import shutil @@ -40,7 +39,6 @@ import qubes.exc import qubes.utils BLKSIZE = 512 -CONFIG_FILE = '/etc/qubes/storage.conf' STORAGE_ENTRY_POINT = 'qubes.storage' @@ -353,89 +351,6 @@ def get_disk_usage(path): return ret - -def get_pool(name, vm): - """ Instantiates the storage for the specified vm """ - config = _get_storage_config_parser() - - klass = _get_pool_klass(name, config) - - keys = [k for k in config.options(name) if k != 'driver' and k != 'class'] - values = [config.get(name, o) for o in keys] - config_kwargs = dict(zip(keys, values)) - - if name == 'default': - kwargs = qubes.config.defaults['pool_config'].copy() - kwargs.update(keys) - else: - kwargs = config_kwargs - - return klass(vm, **kwargs) - - -def pool_exists(name): - """ Check if the specified pool exists """ - try: - _get_pool_klass(name) - return True - except StoragePoolException: - return False - -def add_pool(name, **kwargs): - """ Add a storage pool to config.""" - config = _get_storage_config_parser() - config.add_section(name) - for key, value in kwargs.iteritems(): - config.set(name, key, value) - _write_config(config) - -def remove_pool(name): - """ Remove a storage pool from config file. """ - config = _get_storage_config_parser() - config.remove_section(name) - _write_config(config) - -def _write_config(config): - with open(CONFIG_FILE, 'w') as configfile: - config.write(configfile) - -def _get_storage_config_parser(): - """ Instantiates a `ConfigParaser` for specified storage config file. - - Returns: - RawConfigParser - """ - config = ConfigParser.RawConfigParser() - config.read(CONFIG_FILE) - return config - - -def _get_pool_klass(name, config=None): - """ Returns the storage klass for the specified pool. - - Args: - name: The pool name. - config: If ``config`` is not specified - `_get_storage_config_parser()` is called. - - Returns: - type: A class inheriting from `QubesVmStorage` - """ - if config is None: - config = _get_storage_config_parser() - - if not config.has_section(name): - raise StoragePoolException('Uknown storage pool ' + name) - elif not config.has_option(name, 'driver'): - raise StoragePoolException('No driver specified for pool ' + name) - - - driver = config.get(name, 'driver') - try: - return qubes.get_entry_point_one(STORAGE_ENTRY_POINT, driver) - except KeyError: - raise StoragePoolException('Driver %s for pool %s' % (driver, name)) - class Pool(object): def __init__(self, vm, dir_path): assert vm is not None diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index 942e3f66..d1832259 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -197,7 +197,6 @@ fi %files %defattr(-,root,root,-) %config(noreplace) %attr(0664,root,qubes) %{_sysconfdir}/qubes/qmemman.conf -%config(noreplace) %attr(0664,root,qubes) %{_sysconfdir}/qubes/storage.conf /usr/bin/qvm-* /usr/bin/qubes-* /usr/bin/qmemmand