Prechádzať zdrojové kódy

Storage move rename() logic to XenPool

- Fix config renaming
Bahtiar `kalkin-` Gadimov 8 rokov pred
rodič
commit
49b4951389
3 zmenil súbory, kde vykonal 86 pridanie a 25 odobranie
  1. 16 18
      qubes/storage/__init__.py
  2. 64 1
      qubes/storage/xen.py
  3. 6 6
      qubes/vm/qubesvm.py

+ 16 - 18
qubes/storage/__init__.py

@@ -56,7 +56,11 @@ class Volume(object):
     script = None
     usage = 0
 
-    def __init__(self, name=None, pool=None, volume_type=None, vid=None,
+    def __init__(self,
+                 name=None,
+                 pool=None,
+                 volume_type=None,
+                 vid=None,
                  size=0):
         assert name and pool and volume_type
         self.name = str(name)
@@ -167,23 +171,12 @@ class Storage(object):
                                                          volume)
             self.vm.volumes[name] = volume
 
-    # TODO migrate this
-    @staticmethod
-    def rename(newpath, oldpath):
-        '''Move storage directory, most likely during domain's rename.
-
-        .. note::
-            The arguments are in different order than in :program:`cp` utility.
-
-        .. versionchange:: 4.0
-            This is now dummy method that just passes everything to
-            :py:func:`os.rename`.
-
-        :param str newpath: New path
-        :param str oldpath: Old path
-        '''
-
-        os.rename(oldpath, newpath)
+    def rename(self, old_name, new_name):
+        ''' Notify the pools that the domain was renamed '''
+        volumes = self.vm.volumes
+        for name, volume in volumes.items():
+            pool = self.get_pool(volume)
+            volumes[name] = pool.rename(volume, old_name, new_name)
 
     def verify_files(self):
         '''Verify that the storage is sane.
@@ -271,6 +264,11 @@ class Pool(object):
         raise NotImplementedError("Pool %s has remove() not implemented" %
                                   self.name)
 
+    def rename(self, volume, old_name, new_name):
+        ''' Called when the domain changes its name '''
+        raise NotImplementedError("Pool %s has rename() not implemented" %
+                                  self.name)
+
     def start(self, volume):
         ''' Do what ever is needed on start '''
         raise NotImplementedError("Pool %s has start() not implemented" %

+ 64 - 1
qubes/storage/xen.py

@@ -114,6 +114,23 @@ class XenPool(Pool):
             _remove_if_exists(volume.vid)
             _remove_if_exists(volume.path_cow)
 
+    def rename(self, volume, old_name, new_name):
+        assert issubclass(volume.__class__, XenVolume)
+        old_dir = os.path.dirname(volume.path)
+        new_dir = os.path.join(os.path.dirname(old_dir), new_name)
+
+        if not os.path.exists(new_dir):
+            os.makedirs(new_dir)
+
+        if volume.volume_type == 'read-write':
+            volume.rename_target_dir(new_name, new_dir)
+        elif volume.volume_type == 'read-only':
+            volume.rename_target_dir(old_name, new_dir)
+        elif volume.volume_type in ['origin', 'volatile']:
+            volume.rename_target_dir(new_dir)
+
+        return volume
+
     def _resize_loop_device(self, path):
         # find loop device if any
         p = subprocess.Popen(
@@ -275,6 +292,17 @@ class ReadWriteFile(SizeMixIn):
         self.path = os.path.join(self.target_dir, self.name + '.img')
         self.vid = self.path
 
+    def rename_target_dir(self, new_name, new_dir):
+        # :pylint: disable=unused-argument
+        old_path = self.path
+        file_name = os.path.basename(self.path)
+        new_path = os.path.join(new_dir, file_name)
+
+        os.rename(old_path, new_path)
+        self.target_dir = new_dir
+        self.path = new_path
+        self.vid = self.path
+
 
 class ReadOnlyFile(XenVolume):
     # :pylint: disable=missing-docstring
@@ -285,6 +313,20 @@ class ReadOnlyFile(XenVolume):
         super(ReadOnlyFile, self).__init__(size=int(size), **kwargs)
         self.path = self.vid
 
+    def rename_target_dir(self, old_name, new_dir):
+        # only copy the read-only volume if it's "owned" by the current vm
+        # "owned" means that it's in a directory named the same as the vm
+        if os.path.basename(self.target_dir) == old_name:
+            file_name = os.path.basename(self.path)
+            new_path = os.path.join(new_dir, file_name)
+            old_path = self.path
+
+            os.rename(old_path, new_path)
+
+            self.target_dir = new_dir
+            self.path = new_path
+            self.vid = self.path
+
 
 class OriginFile(SizeMixIn):
     # :pylint: disable=missing-docstring
@@ -300,6 +342,19 @@ class OriginFile(SizeMixIn):
     def commit(self):
         raise NotImplementedError
 
+    def rename_target_dir(self, new_dir):
+        old_path_origin = self.path_origin
+        old_path_cow = self.path_cow
+        new_path_origin = os.path.join(new_dir, self.name + '.img')
+        new_path_cow = os.path.join(new_dir, self.name + '-cow.img')
+        os.rename(old_path_origin, new_path_origin)
+        os.rename(old_path_cow, new_path_cow)
+        self.target_dir = new_dir
+        self.path_origin = new_path_origin
+        self.path_cow = new_path_cow
+        self.path = '%s:%s' % (self.path_origin, self.path_cow)
+        self.vid = self.path_origin
+
     @property
     def usage(self):
         result = 0
@@ -335,7 +390,15 @@ class VolatileFile(SizeMixIn):
 
     def __init__(self, **kwargs):
         super(VolatileFile, self).__init__(**kwargs)
-        self.path = os.path.join(self.target_dir, 'volatile.img')
+        self.path = os.path.join(self.target_dir, self.name + '.img')
+        self.vid = self.path
+
+    def rename_target_dir(self, new_dir):
+        _remove_if_exists(self)
+        file_name = os.path.basename(self.path)
+        self.target_dir = new_dir
+        new_path = os.path.join(new_dir, file_name)
+        self.path = new_path
         self.vid = self.path
 
 

+ 6 - 6
qubes/vm/qubesvm.py

@@ -566,18 +566,18 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
             self._qdb_connection.close()
             self._qdb_connection = None
 
-        self.storage.rename(
-            os.path.join(qubes.config.system_path['qubes_base_dir'],
-                self.dir_path_prefix, new_name),
-            os.path.join(qubes.config.system_path['qubes_base_dir'],
-                self.dir_path_prefix, old_name))
+        self.storage.rename(old_name, new_name)
+
+        prefix = os.path.join(qubes.config.system_path['qubes_base_dir'], self.dir_path_prefix)
+        old_config = os.path.join(prefix, old_name, old_name + '.conf')
+        new_config = os.path.join(prefix, new_name, new_name + '.conf')
+        os.rename(old_config, new_config)
 
         self._update_libvirt_domain()
 
         if self.autostart:
             self.autostart = self.autostart
 
-
     @qubes.events.handler('property-pre-set:autostart')
     def on_property_pre_set_autostart(self, event, prop, name, value,
             oldvalue=None):