Add protection against daemons that may already be listening
authorHrvoje Ribicic <riba@google.com>
Mon, 8 Jun 2015 16:35:27 +0000 (16:35 +0000)
committerHrvoje Ribicic <riba@google.com>
Thu, 11 Jun 2015 14:23:19 +0000 (16:23 +0200)
Should the migration port already be taken, Ganeti will try and start a
socat daemon that will immediately die, leaving Ganeti to pipe the
migration data into whatever process that happens to be listening. This
patch prevents that from happening by checking if the socat daemon
started by Ganeti is ready to accept the migration data.

Signed-off-by: Hrvoje Ribicic <riba@google.com>
Reviewed-by: Klaus Aehlig <aehlig@google.com>

lib/hypervisor/hv_xen.py

index 271ecaa..a4ec4ca 100644 (file)
@@ -36,6 +36,7 @@ import logging
 import errno
 import string # pylint: disable=W0402
 import shutil
+import time
 from cStringIO import StringIO
 
 from ganeti import constants
@@ -1150,8 +1151,18 @@ class XenHypervisor(hv_base.BaseHypervisor):
       # And try and kill a previous daemon
       XenHypervisor._KillMigrationDaemon(instance)
 
-      utils.StartDaemon(["socat", "TCP-LISTEN:%d,bind=%s" % (port, target),
-                         "SYSTEM:'xl migrate-receive'"], pidfile=pidfile)
+      listening_arg = "TCP-LISTEN:%d,bind=%s" % (port, target)
+      socat_pid = utils.StartDaemon(["socat", listening_arg,
+                                     "SYSTEM:'xl migrate-receive'"],
+                                     pidfile=pidfile)
+
+      # Wait for a while to make sure the socat process has successfully started
+      # listening
+      time.sleep(1)
+      if not utils.IsProcessAlive(socat_pid):
+        raise errors.HypervisorError("Could not start receiving socat process"
+                                     " on port %d: check if port is available" %
+                                     port)
 
   def FinalizeMigrationDst(self, instance, info, success):
     """Finalize an instance migration.