Add pool config parsing
This commit is contained in:
parent
15d5e6edbb
commit
bfaf37dae5
@ -1,5 +1,6 @@
|
||||
OS ?= Linux
|
||||
|
||||
SYSCONFDIR ?= /etc
|
||||
PYTHON_QUBESPATH = $(PYTHON_SITEPATH)/qubes
|
||||
|
||||
all:
|
||||
@ -13,6 +14,8 @@ endif
|
||||
mkdir -p $(DESTDIR)$(PYTHON_QUBESPATH)/storage
|
||||
cp __init__.py $(DESTDIR)$(PYTHON_QUBESPATH)/storage
|
||||
cp __init__.py[co] $(DESTDIR)$(PYTHON_QUBESPATH)/storage
|
||||
mkdir -p $(DESTDIR)$(SYSCONFDIR)/qubes
|
||||
cp storage.conf $(DESTDIR)$(SYSCONFDIR)/qubes/
|
||||
ifneq ($(BACKEND_VMM),)
|
||||
if [ -r $(BACKEND_VMM).py ]; then \
|
||||
cp $(BACKEND_VMM).py $(DESTDIR)$(PYTHON_QUBESPATH)/storage && \
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import ConfigParser
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
@ -31,6 +32,8 @@ import sys
|
||||
import qubes.qubesutils
|
||||
from qubes.qubes import QubesException, defaults, system_path, vm_files
|
||||
|
||||
CONFIG_FILE = '/etc/qubes/storage.conf'
|
||||
|
||||
|
||||
class QubesVmStorage(object):
|
||||
"""
|
||||
@ -200,5 +203,97 @@ class QubesVmStorage(object):
|
||||
self.create_on_disk_private_img(verbose=False)
|
||||
|
||||
|
||||
def dump(o):
|
||||
""" Returns a string represention of the given object
|
||||
|
||||
Args:
|
||||
o (object): anything that response to `__module__` and `__class__`
|
||||
|
||||
Given the class :class:`qubes.storage.QubesVmStorage` it returns
|
||||
'qubes.storage.QubesVmStorage' as string
|
||||
"""
|
||||
return o.__module__ + '.' + o.__class__.__name__
|
||||
|
||||
|
||||
def load(string):
|
||||
""" Given a dotted full module string representation of a class it loads it
|
||||
|
||||
Args:
|
||||
string (str) i.e. 'qubes.storage.xen.QubesXenVmStorage'
|
||||
|
||||
Returns:
|
||||
type
|
||||
|
||||
See also:
|
||||
:func:`qubes.storage.dump`
|
||||
"""
|
||||
if not type(string) is str:
|
||||
# This is a hack which allows giving a real class to a vm instead of a
|
||||
# string as string_class parameter.
|
||||
return string
|
||||
|
||||
components = string.split(".")
|
||||
module_path = ".".join(components[:-1])
|
||||
klass = components[-1:][0]
|
||||
module = __import__(module_path, fromlist=[klass])
|
||||
return getattr(module, klass)
|
||||
|
||||
|
||||
def get_pool(vm):
|
||||
""" Instantiates the storage for the specified vm """
|
||||
config = _get_storage_config_parser()
|
||||
|
||||
name = vm.storage_pool
|
||||
klass = _get_pool_klass(name, config)
|
||||
|
||||
keys = [k for k in config.options(name) if k != 'type' and k != 'class']
|
||||
values = [config.get(name, o) for o in keys]
|
||||
kwargs = dict(zip(keys, values))
|
||||
return klass(vm, **kwargs)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
if config.has_option(name, 'class'):
|
||||
klass = load(config.get(name, 'class'))
|
||||
elif config.has_option(name, 'type'):
|
||||
pool_type = config.get(name, 'type')
|
||||
klass = defaults['pool_types'][pool_type]
|
||||
|
||||
if klass is None:
|
||||
raise StoragePoolException('Uknown storage pool type ' + name)
|
||||
return klass
|
||||
|
||||
|
||||
class StoragePoolException(QubesException):
|
||||
pass
|
||||
|
||||
class Pool(object):
|
||||
pass
|
||||
|
||||
|
11
core/storage/storage.conf
Normal file
11
core/storage/storage.conf
Normal file
@ -0,0 +1,11 @@
|
||||
[default] ; poolname
|
||||
type=xen ; the default xen storage
|
||||
; class = qubes.storage.xen.XenStorage ; class always overwrites type
|
||||
;
|
||||
; To use our own storage adapter, you need just to specify the module path and
|
||||
; class name
|
||||
; [pool-b]
|
||||
; class = foo.bar.MyStorage
|
||||
;
|
||||
|
||||
|
@ -176,6 +176,7 @@ 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-*
|
||||
%dir %{python_sitearch}/qubes
|
||||
|
@ -27,3 +27,5 @@ endif
|
||||
cp regressions.py[co] $(DESTDIR)$(PYTHON_TESTSPATH)
|
||||
cp run.py $(DESTDIR)$(PYTHON_TESTSPATH)
|
||||
cp run.py[co] $(DESTDIR)$(PYTHON_TESTSPATH)
|
||||
cp storage.py $(DESTDIR)$(PYTHON_TESTSPATH)
|
||||
cp storage.py[co] $(DESTDIR)$(PYTHON_TESTSPATH)
|
||||
|
@ -547,6 +547,7 @@ def load_tests(loader, tests, pattern):
|
||||
'qubes.tests.backup',
|
||||
'qubes.tests.backupcompatibility',
|
||||
'qubes.tests.regressions',
|
||||
'qubes.tests.storage',
|
||||
):
|
||||
tests.addTests(loader.loadTestsFromName(modname))
|
||||
|
||||
|
63
tests/storage.py
Normal file
63
tests/storage.py
Normal file
@ -0,0 +1,63 @@
|
||||
# The Qubes OS Project, https://www.qubes-os.org/
|
||||
#
|
||||
# Copyright (C) 2015 Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
||||
from qubes.tests import QubesTestCase, SystemTestsMixin
|
||||
from qubes.qubes import defaults
|
||||
|
||||
import qubes.storage
|
||||
from qubes.storage.xen import QubesXenVmStorage, XenPool
|
||||
|
||||
|
||||
class TC_00_Storage(SystemTestsMixin, QubesTestCase):
|
||||
|
||||
def test_000_dump(self):
|
||||
""" Dumps storage instance to a storage string """
|
||||
vmname = self.make_vm_name('appvm')
|
||||
template = self.qc.get_default_template()
|
||||
storage = self.qc.add_new_vm('QubesAppVm', name=vmname, pool='default',
|
||||
template=template).storage
|
||||
result = qubes.storage.dump(storage)
|
||||
expected = 'qubes.storage.xen.QubesXenVmStorage'
|
||||
self.assertEquals(result, expected)
|
||||
|
||||
def test_001_load(self):
|
||||
""" Loads storage type from a storage string """
|
||||
result = qubes.storage.load('qubes.storage.xen.QubesXenVmStorage')
|
||||
self.assertTrue(result is QubesXenVmStorage)
|
||||
|
||||
def test_002_default_pool_types(self):
|
||||
""" The only predifined pool type is xen """
|
||||
result = defaults['pool_types'].keys()
|
||||
expected = ["xen"]
|
||||
self.assertEquals(result, expected)
|
||||
|
||||
def test_003_get_pool_klass(self):
|
||||
""" Expect the default pool to be `XenPool` """
|
||||
result = qubes.storage._get_pool_klass('default')
|
||||
self.assertTrue(result is XenPool)
|
||||
|
||||
|
||||
class TC_01_Storage(SystemTestsMixin, QubesTestCase):
|
||||
|
||||
def test_000_vm_use_default_pool(self):
|
||||
vmname = self.make_vm_name('appvm')
|
||||
template = self.qc.get_default_template()
|
||||
vm = self.qc.add_new_vm('QubesAppVm', name=vmname, template=template,
|
||||
pool='default')
|
||||
self.assertIsInstance(vm.storage, QubesXenVmStorage)
|
Loading…
Reference in New Issue
Block a user