|
|
0d20ef |
From 770be29b68b151964aff988de606963eaf04dbe3 Mon Sep 17 00:00:00 2001
|
|
|
0d20ef |
From: John Eckersberg <jeckersb@redhat.com>
|
|
|
0d20ef |
Date: Fri, 5 Dec 2014 16:58:13 -0500
|
|
|
0d20ef |
Subject: [PATCH] p2v: wait for qemu-nbd before starting conversion
|
|
|
0d20ef |
(RHBZ#1167774)
|
|
|
0d20ef |
|
|
|
0d20ef |
Wait up to 10 seconds for qemu-nbd to start up and respond to clients.
|
|
|
0d20ef |
Otherwise the conversion server may attempt to connect before qemu-nbd
|
|
|
0d20ef |
is ready to serve it.
|
|
|
0d20ef |
|
|
|
0d20ef |
(cherry picked from commit 33098d23020bd3824a2954823a0dbaff751c814d)
|
|
|
0d20ef |
---
|
|
|
0d20ef |
p2v/conversion.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
0d20ef |
1 file changed, 76 insertions(+)
|
|
|
0d20ef |
|
|
|
0d20ef |
diff --git a/p2v/conversion.c b/p2v/conversion.c
|
|
|
0d20ef |
index cb2deed..9f5a3ad 100644
|
|
|
0d20ef |
--- a/p2v/conversion.c
|
|
|
0d20ef |
+++ b/p2v/conversion.c
|
|
|
0d20ef |
@@ -31,6 +31,8 @@
|
|
|
0d20ef |
#include <libintl.h>
|
|
|
0d20ef |
#include <sys/types.h>
|
|
|
0d20ef |
#include <sys/wait.h>
|
|
|
0d20ef |
+#include <arpa/inet.h>
|
|
|
0d20ef |
+#include <netinet/in.h>
|
|
|
0d20ef |
|
|
|
0d20ef |
#include <glib.h>
|
|
|
0d20ef |
|
|
|
0d20ef |
@@ -39,6 +41,9 @@
|
|
|
0d20ef |
#include "miniexpect.h"
|
|
|
0d20ef |
#include "p2v.h"
|
|
|
0d20ef |
|
|
|
0d20ef |
+/* How long to wait for qemu-nbd to start (seconds). */
|
|
|
0d20ef |
+#define WAIT_QEMU_NBD_TIMEOUT 10
|
|
|
0d20ef |
+
|
|
|
0d20ef |
/* Data per NBD connection / physical disk. */
|
|
|
0d20ef |
struct data_conn {
|
|
|
0d20ef |
mexp_h *h; /* miniexpect handle to ssh */
|
|
|
0d20ef |
@@ -49,6 +54,7 @@ struct data_conn {
|
|
|
0d20ef |
|
|
|
0d20ef |
static int send_quoted (mexp_h *, const char *s);
|
|
|
0d20ef |
static pid_t start_qemu_nbd (int nbd_local_port, const char *device);
|
|
|
0d20ef |
+static int wait_qemu_nbd (int nbd_local_port, int timeout_seconds);
|
|
|
0d20ef |
static void cleanup_data_conns (struct data_conn *data_conns, size_t nr);
|
|
|
0d20ef |
static char *generate_libvirt_xml (struct config *, struct data_conn *);
|
|
|
0d20ef |
static const char *map_interface_to_network (struct config *, const char *interface);
|
|
|
0d20ef |
@@ -156,6 +162,11 @@ start_conversion (struct config *config,
|
|
|
0d20ef |
if (data_conns[i].nbd_pid == 0)
|
|
|
0d20ef |
goto out;
|
|
|
0d20ef |
|
|
|
0d20ef |
+ /* Wait for qemu-nbd to listen */
|
|
|
0d20ef |
+ if (wait_qemu_nbd (data_conns[i].nbd_local_port,
|
|
|
0d20ef |
+ WAIT_QEMU_NBD_TIMEOUT) == -1)
|
|
|
0d20ef |
+ goto out;
|
|
|
0d20ef |
+
|
|
|
0d20ef |
#if DEBUG_STDERR
|
|
|
0d20ef |
fprintf (stderr,
|
|
|
0d20ef |
"%s: data connection for %s: SSH remote port %d, local port %d\n",
|
|
|
0d20ef |
@@ -371,6 +382,71 @@ start_qemu_nbd (int port, const char *device)
|
|
|
0d20ef |
return pid;
|
|
|
0d20ef |
}
|
|
|
0d20ef |
|
|
|
0d20ef |
+static int
|
|
|
0d20ef |
+wait_qemu_nbd (int nbd_local_port, int timeout_seconds)
|
|
|
0d20ef |
+{
|
|
|
0d20ef |
+ int sockfd;
|
|
|
0d20ef |
+ int result = -1;
|
|
|
0d20ef |
+ struct sockaddr_in addr;
|
|
|
0d20ef |
+ time_t start_t, now_t;
|
|
|
0d20ef |
+ struct timeval timeout = { .tv_usec = 0 };
|
|
|
0d20ef |
+ char magic[8]; /* NBDMAGIC */
|
|
|
0d20ef |
+ size_t bytes_read = 0;
|
|
|
0d20ef |
+ ssize_t recvd;
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ time (&start_t);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ sockfd = socket (AF_INET, SOCK_STREAM, 0);
|
|
|
0d20ef |
+ if (sockfd == -1) {
|
|
|
0d20ef |
+ perror ("socket");
|
|
|
0d20ef |
+ return -1;
|
|
|
0d20ef |
+ }
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ memset (&addr, 0, sizeof addr);
|
|
|
0d20ef |
+ addr.sin_family = AF_INET;
|
|
|
0d20ef |
+ addr.sin_port = htons (nbd_local_port);
|
|
|
0d20ef |
+ inet_pton (AF_INET, "localhost", &addr.sin_addr);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ for (;;) {
|
|
|
0d20ef |
+ time (&now_t);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ if (now_t - start_t >= timeout_seconds) {
|
|
|
0d20ef |
+ set_conversion_error ("waiting for qemu-nbd to start: connect: %m");
|
|
|
0d20ef |
+ goto cleanup;
|
|
|
0d20ef |
+ }
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ if (connect (sockfd, (struct sockaddr *) &addr, sizeof addr) == 0)
|
|
|
0d20ef |
+ break;
|
|
|
0d20ef |
+ }
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ time (&now_t);
|
|
|
0d20ef |
+ timeout.tv_sec = (start_t + timeout_seconds) - now_t;
|
|
|
0d20ef |
+ setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ do {
|
|
|
0d20ef |
+ recvd = recv (sockfd, magic, sizeof magic - bytes_read, 0);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ if (recvd == -1) {
|
|
|
0d20ef |
+ set_conversion_error ("waiting for qemu-nbd to start: recv: %m");
|
|
|
0d20ef |
+ goto cleanup;
|
|
|
0d20ef |
+ }
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ bytes_read += recvd;
|
|
|
0d20ef |
+ } while (bytes_read < sizeof magic);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ if (memcmp (magic, "NBDMAGIC", sizeof magic) != 0) {
|
|
|
0d20ef |
+ set_conversion_error ("waiting for qemu-nbd to start: "
|
|
|
0d20ef |
+ "'NBDMAGIC' was not received from qemu-nbd");
|
|
|
0d20ef |
+ goto cleanup;
|
|
|
0d20ef |
+ }
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ result = 0;
|
|
|
0d20ef |
+cleanup:
|
|
|
0d20ef |
+ close (sockfd);
|
|
|
0d20ef |
+
|
|
|
0d20ef |
+ return result;
|
|
|
0d20ef |
+}
|
|
|
0d20ef |
+
|
|
|
0d20ef |
static void
|
|
|
0d20ef |
cleanup_data_conns (struct data_conn *data_conns, size_t nr)
|
|
|
0d20ef |
{
|
|
|
0d20ef |
--
|
|
|
0d20ef |
1.8.3.1
|
|
|
0d20ef |
|