Completely exclude mpoints when running rsync
authorNikos Skalkotos <skalkoto@grnet.gr>
Fri, 18 Jan 2013 18:45:32 +0000 (20:45 +0200)
committerNikos Skalkotos <skalkoto@grnet.gr>
Fri, 18 Jan 2013 19:20:12 +0000 (21:20 +0200)
We used to exclude mount point from rsync with options like this:

 --exclude mount/point/*

This will copy the directory and leave out all files under it. In
some cases, this causes problems because rsync will fail if it
cannot stat the directory and some mount point will only return
stat info to their owner and not root. Even if this wasn't the
case, we cannot determine the real directory attributes. The stat
syscall will return the attributes associated with the mount
options. It's better to completely exclude those mpoints in rsync
and create them explicitly after the command runs. We make them
inherit the mode and the ownership of their parent directory.

image_creator/bundle_volume.py

index c099daa..4b15acd 100644 (file)
@@ -312,7 +312,7 @@ class BundleVolume(object):
             if not found_ancestor:
                 excluded.append(mpoint)
 
-        return map(lambda d: d + "/*", excluded)
+        return excluded
 
     def _replace_uuids(self, target, new_uuid):
 
@@ -380,17 +380,28 @@ class BundleVolume(object):
                 absmpoints = self._mount(target,
                                          [(mapped[i], filesystem[i].mpoint)
                                          for i in mapped.keys()])
-                exclude = self._to_exclude() + [image]
+                excluded = self._to_exclude()
 
                 rsync = Rsync(self.out)
 
                 # Excluded paths need to be relative to the source
-                for excl in map(lambda p: os.path.relpath(p, '/'), exclude):
+                for excl in map(lambda p: os.path.relpath(p, '/'),
+                                excluded + [image]):
                     rsync.exclude(excl)
 
                 rsync.archive().hard_links().xattrs().sparse().acls()
                 rsync.run('/', target, 'host', 'temporary image')
 
+                # Create missing mountpoints. Since they are mountpoints, we
+                # cannot determine the ownership and the mode of the real
+                # directory. Make them inherit those properties from their
+                # parent dir
+                for excl in excluded:
+                   dirname = os.path.dirname(excl)
+                   stat = os.stat(dirname)
+                   os.mkdir(target + excl, stat.st_mode)
+                   os.chown(target + excl, stat.st_uid, stat.st_gid)
+
                 # We need to replace the old UUID referencies with the new
                 # ones in grub configuration files and /etc/fstab for file
                 # systems that have been recreated.