Create a new cloud wizard page
[snf-image-creator] / image_creator / rsync.py
index 9ae22b6..833d0be 100644 (file)
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+#
 # Copyright 2012 GRNET S.A. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or
@@ -31,6 +33,8 @@
 # interpreted as representing official policies, either expressed
 # or implied, of GRNET S.A.
 
+"""This module provides an interface for the rsync utility"""
+
 import subprocess
 import time
 import signal
@@ -82,7 +86,7 @@ class Rsync:
         self._exclude = []
         self._options = ['-v']
 
-    def run(self, src, dest):
+    def run(self, src, dest, slabel='source', dlabel='destination'):
         """Run the actual command"""
         cmd = []
         cmd.append('rsync')
@@ -90,14 +94,15 @@ class Rsync:
         for i in self._exclude:
             cmd.extend(['--exclude', i])
 
-        self._out.output("Calculating total number of host files ...", False)
+        self._out.output("Calculating total number of %s files ..." % slabel,
+                         False)
 
         # If you don't specify a destination, rsync will list the source files.
         dry_run = subprocess.Popen(cmd + [src], shell=False,
                                    stdout=subprocess.PIPE, bufsize=0)
         try:
             total = 0
-            for line in iter(dry_run.stdout.readline, b''):
+            for _ in iter(dry_run.stdout.readline, b''):
                 total += 1
         finally:
             dry_run.communicate()
@@ -106,14 +111,13 @@ class Rsync:
 
         self._out.success("%d" % total)
 
-        progress = self._out.Progress(total,
-                                      "Copying host files into the image")
+        progress = self._out.Progress(total, "Copying files to %s" % dlabel)
         run = subprocess.Popen(cmd + [src, dest], shell=False,
                                stdout=subprocess.PIPE, bufsize=0)
         try:
             t = time.time()
             i = 0
-            for line in iter(run.stdout.readline, b''):
+            for _ in iter(run.stdout.readline, b''):
                 i += 1
                 current = time.time()
                 if current - t > 0.1:
@@ -123,12 +127,19 @@ class Rsync:
             progress.success('done')
 
         finally:
-            run.poll()
-            if run.returncode is None:
-                run.send_signal(signal.SIGHUP)
+            def handler(signum, frame):
+                run.terminate()
+                time.sleep(1)
+                run.poll()
+                if run.returncode is None:
+                    run.kill()
+                run.wait()
+
+            signal.signal(signal.SIGALRM, handler)
+            signal.alarm(2)
             run.communicate()
+            signal.alarm(0)
             if run.returncode != 0:
                 raise FatalError("rsync failed")
 
-
 # vim: set sta sts=4 shiftwidth=4 sw=4 et ai :