Fix bugs in rsync module
authorNikos Skalkotos <skalkoto@grnet.gr>
Mon, 31 Dec 2012 01:05:32 +0000 (03:05 +0200)
committerNikos Skalkotos <skalkoto@grnet.gr>
Mon, 31 Dec 2012 01:05:32 +0000 (03:05 +0200)
 * Fix a bug where the parent process did not wait on the child
   processes.
 * Make sure that when updating the copy progress bar, at least
   0.1 seconds have passed. This guarantees that we do not experience
   any flickering in the progress bar.

image_creator/bundle_volume.py
image_creator/rsync.py

index bd418ce..919a08b 100644 (file)
@@ -378,8 +378,7 @@ class BundleVolume(object):
                 exclude = self._to_exclude() + [image]
                 rsync = Rsync('/', target,
                               map(lambda p: os.path.relpath(p, '/'), exclude))
-                msg = "Copying host files into the image"
-                rsync.archive().run(self.out, msg)
+                rsync.archive().run(self.out)
 
                 self._replace_uuids(target, new_uuid)
 
index 7c869c2..0c6b639 100644 (file)
 # or implied, of GRNET S.A.
 
 import subprocess
+import time
+import signal
+
+from image_creator.util import FatalError
 
 
 class Rsync:
+    """Wrapper class for the rsync command"""
+
     def __init__(self, src, dest, exclude=[]):
+        """Create an instance by defining a source, a destinationa and a number
+        of exclude patterns.
+        """
         self.src = src
         self.dest = dest
         self.exclude = exclude
         self.options = ['-v']
 
     def archive(self):
+        """Enable the archive option"""
         self.options.append('-a')
         return self
 
-    def run(self, out, msg):
+    def run(self, out):
+        """Run the actual command"""
         cmd = []
         cmd.append('rsync')
         cmd.extend(self.options)
         for i in self.exclude:
             cmd.extend(['--exclude', i])
 
+        out.output("Calculating total number of host files ...", False)
         dry_run = subprocess.Popen(cmd + ['-n', self.src, self.dest],
                                    shell=False, stdout=subprocess.PIPE,
                                    bufsize=0)
-        total = 0
-        for line in iter(dry_run.stdout.readline, b''):
-            total += 1
+        try:
+            total = 0
+            for line in iter(dry_run.stdout.readline, b''):
+                total += 1
+        finally:
+            dry_run.communicate()
+            if dry_run.returncode != 0:
+                raise FatalError("rsync failed")
+
+        out.success("%d" % total)
 
-        progress = out.Progress(total, msg)
+        progress = out.Progress(total, "Copying files into the image ... ")
         run = subprocess.Popen(cmd + [self.src, self.dest], shell=False,
                                stdout=subprocess.PIPE, bufsize=0)
-        for line in iter(run.stdout.readline, b''):
-            progress.next()
+        try:
+            t = time.time()
+            i = 0
+            for line in iter(run.stdout.readline, b''):
+                i += 1
+                current = time.time()
+                if current - t > 0.1:
+                    t = current
+                    progress.goto(i)
+
+            progress.success('done')
+
+        finally:
+            run.poll()
+            if run.returncode is None:
+                run.send_signal(signal.SIGHUP)
+            run.communicate()
+            if run.returncode != 0:
+                raise FatalError("rsync failed")
 
-        progress.success('done')
 
 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :