Browse Source

Merge remote-tracking branch 'woju/pull/21/head' into core3-devel

Conflicts:
	qubes/storage/__init__.py
Wojtek Porczyk 8 years ago
parent
commit
1ff1ca37a1
4 changed files with 55 additions and 36 deletions
  1. 1 0
      qubes/app.py
  2. 24 2
      qubes/storage/__init__.py
  3. 29 33
      qubes/storage/file.py
  4. 1 1
      qubes/storage/kernels.py

+ 1 - 0
qubes/app.py

@@ -911,6 +911,7 @@ class Qubes(qubes.PropertyHolder):
         pool = self._get_pool(**kwargs)
         pool.setup()
         self.pools[name] = pool
+        return pool
 
     def remove_pool(self, name):
         """ Remove a storage pool from config file.  """

+ 24 - 2
qubes/storage/__init__.py

@@ -42,6 +42,7 @@ STORAGE_ENTRY_POINT = 'qubes.storage'
 
 
 class StoragePoolException(qubes.exc.QubesException):
+    ''' A general storage exception '''
     pass
 
 
@@ -98,6 +99,9 @@ class Volume(object):
     def __hash__(self):
         return hash('%s:%s %s' % (self.pool, self.vid, self.volume_type))
 
+    def __str__(self):
+        return "{!s}:{!s}".format(self.pool, self.vid)
+
 
 class Storage(object):
     ''' Class for handling VM virtual disks.
@@ -198,7 +202,7 @@ class Storage(object):
         self.get_pool(volume).resize(volume, size)
 
     def create(self, source_template=None):
-
+        ''' Creates volumes on disk '''
         if source_template is None and hasattr(self.vm, 'template'):
             source_template = self.vm.template
 
@@ -213,6 +217,7 @@ class Storage(object):
         os.umask(old_umask)
 
     def clone(self, src_vm):
+        ''' Clone volumes from the specified vm '''
         self.vm.log.info('Creating directory: {0}'.format(self.vm.dir_path))
         if not os.path.exists(self.vm.dir_path):
             self.log.info('Creating directory: {0}'.format(self.vm.dir_path))
@@ -288,6 +293,7 @@ class Storage(object):
         return self.pools[volume.name]
 
     def commit_template_changes(self):
+        ''' Makes changes to an 'origin' volume persistent '''
         for volume in self.vm.volumes.values():
             if volume.volume_type == 'origin':
                 self.get_pool(volume).commit_template_changes(volume)
@@ -318,15 +324,25 @@ class Pool(object):
     private_img_size = qubes.config.defaults['private_img_size']
     root_img_size = qubes.config.defaults['root_img_size']
 
+    def __eq__(self, other):
+        return self.name == other.name
+
+
+    def __neq__(self, other):
+        return not self.__eq__(other)
+
     def __init__(self, name, **kwargs):
         super(Pool, self).__init__(**kwargs)
         self.name = name
         kwargs['name'] = self.name
 
+    def __str__(self):
+        return self.name
+
     def __xml__(self):
         return lxml.etree.Element('pool', **self.config)
 
-    def create(self, volume, source_volume):
+    def create(self, volume, source_volume=None):
         ''' Create the given volume on disk or copy from provided
             `source_volume`.
         '''
@@ -351,6 +367,9 @@ class Pool(object):
                                   self.name)
 
     def destroy(self):
+        ''' Called when removing the pool. Use this for implementation specific
+            clean up.
+        '''
         raise NotImplementedError("Pool %s has destroy() not implemented" %
                                   self.name)
 
@@ -374,6 +393,9 @@ class Pool(object):
                                   self.name)
 
     def setup(self):
+        ''' Called when adding a pool to the system. Use this for implementation
+            specific set up.
+        '''
         raise NotImplementedError("Pool %s has setup() not implemented" %
                                   self.name)
 

+ 29 - 33
qubes/storage/file.py

@@ -91,7 +91,7 @@ class FilePool(Pool):
         ''' Expands volume, throws
             :py:class:`qubst.storage.StoragePoolException` if given size is
             less than current_size
-        '''
+        '''  # pylint: disable=no-self-use
         _type = volume.volume_type
         if _type not in ['origin', 'read-write', 'volatile']:
             raise StoragePoolException('Can not resize a %s volume %s' %
@@ -112,7 +112,18 @@ class FilePool(Pool):
         with open(path, 'a+b') as fd:
             fd.truncate(size)
 
-        self._resize_loop_device(path)
+        p = subprocess.Popen(
+            ['sudo', 'losetup', '--associated', path],
+            stdout=subprocess.PIPE)
+        result = p.communicate()
+
+        m = re.match(r'^(/dev/loop\d+):\s', result[0])
+        if m is not None:
+            loop_dev = m.group(1)
+
+            # resize loop device
+            subprocess.check_call(['sudo', 'losetup', '--set-capacity', loop_dev
+                                   ])
 
     def remove(self, volume):
         if volume.volume_type in ['read-write', 'volatile']:
@@ -133,23 +144,6 @@ class FilePool(Pool):
 
         return volume
 
-    @staticmethod
-    def _resize_loop_device(path):
-        ''' Sets the loop device capacity '''
-        # find loop device if any
-        p = subprocess.Popen(
-            ['sudo', 'losetup', '--associated', path],
-            stdout=subprocess.PIPE)
-        result = p.communicate()
-
-        m = re.match(r'^(/dev/loop\d+):\s', result[0])
-        if m is not None:
-            loop_dev = m.group(1)
-
-            # resize loop device
-            subprocess.check_call(['sudo', 'losetup', '--set-capacity',
-                                   loop_dev])
-
     def commit_template_changes(self, volume):
         if volume.volume_type != 'origin':
             return volume
@@ -175,7 +169,7 @@ class FilePool(Pool):
 
     def start(self, volume):
         if volume.volume_type == 'volatile':
-            self._reset_volume(volume)
+            _reset_volume(volume)
         if volume.volume_type in ['origin', 'snapshot']:
             _check_path(volume.path_origin)
             _check_path(volume.path_cow)
@@ -187,18 +181,6 @@ class FilePool(Pool):
     def stop(self, volume):
         pass
 
-    @staticmethod
-    def _reset_volume(volume):
-        ''' Remove and recreate a volatile volume '''
-        assert volume.volume_type == 'volatile', "Not a volatile volume"
-        assert volume.size
-
-        _remove_if_exists(volume.path)
-
-        with open(volume.path, "w") as f_volatile:
-            f_volatile.truncate(volume.size)
-        return volume
-
     def target_dir(self, vm):
         """ Returns the path to vmdir depending on the type of the VM.
 
@@ -259,6 +241,7 @@ class FilePool(Pool):
                 expected_origin_type
 
             origin_pool = vm.app.get_pool(origin_vm.volume_config[name]['pool'])
+
             assert isinstance(origin_pool,
                               FilePool), 'Origin volume not a file volume'
 
@@ -558,7 +541,7 @@ def copy_file(source, destination):
 
 
 def _remove_if_exists(path):
-    ''' Removes a path if it exist, silently succeeds if file does not exist '''
+    ''' Removes a file if it exist, silently succeeds if file does not exist '''
     if os.path.exists(path):
         os.remove(path)
 
@@ -567,3 +550,16 @@ def _check_path(path):
     ''' Raise an StoragePoolException if ``path`` does not exist'''
     if not os.path.exists(path):
         raise StoragePoolException('Missing image file: %s' % path)
+
+
+def _reset_volume(volume):
+    ''' Remove and recreate a volatile volume '''
+    assert volume.volume_type == 'volatile', "Not a volatile volume"
+
+    assert volume.size
+
+    _remove_if_exists(volume.path)
+
+    with open(volume.path, "w") as f_volatile:
+        f_volatile.truncate(volume.size)
+    return volume

+ 1 - 1
qubes/storage/kernels.py

@@ -63,7 +63,7 @@ class LinuxKernel(Pool):
     def clone(self, source, target):
         return target
 
-    def create(self, volume, source_volume):
+    def create(self, volume, source_volume=None):
         return volume
 
     def commit_template_changes(self, volume):