On Wed, Sep 30, 2009 at 01:27:21PM +0200, Chris Lalancette wrote:
+static int doTunnelMigrate(virDomainPtr dom,
+ virDomainObjPtr vm,
+ const char *uri,
+ unsigned long flags,
+ const char *dname,
+ unsigned long resource)
+{
+ struct qemud_driver *driver = dom->conn->privateData;
+ int client_sock, qemu_sock;
+ struct sockaddr_un sa_qemu, sa_client;
+ socklen_t addrlen;
+ virConnectPtr dconn;
+ virDomainPtr ddomain;
+ char *dest;
+ int retval = -1;
+ ssize_t bytes;
+ char buffer[65536];
+ char *safe_uri;
+ virStreamPtr st;
+ char *dom_xml = NULL;
+ char *unixfile;
+ int internalret;
+ unsigned int qemuCmdFlags;
+ int status;
+ unsigned long long transferred, remaining, total;
+
+ /* the order of operations is important here; we make sure the
+ * destination side is completely setup before we touch the source
+ */
+
+ safe_uri = qemuMonitorEscapeArg(uri);
+ if (!safe_uri) {
+ virReportOOMError(dom->conn);
+ return -1;
+ }
+
+ dconn = virConnectOpen(safe_uri);
+ VIR_FREE (safe_uri);
virConnectOpen() doesn't want a URI that's been escaped for QEMU monitor
syntax - it should just take the original 'uri' surely ?
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
+ internalret = virAsprintf(&dest, "unix:%s", unixfile);
+ else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)
+ internalret = virAsprintf(&dest, "exec:nc -U %s", unixfile);
+
+ internalret = qemuMonitorMigrate(vm, 1, dest);
This is the bit that should be done via strongly typed monitor APIs, eg
something like
if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX)
internalret = qemuMonitorMigrateToUNIX(vm, unixfile);
else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
const char *args[] = { "nc", "-U", unixfile, NULL};
internalret = qemuMonitorMigrateToCommand(vm, args, "/dev/null");
} else {
....error
}
+ for (;;) {
+ bytes = saferead(client_sock, buffer, sizeof(buffer));
+ if (bytes < 0) {
+ virReportSystemError(dconn, errno, "%s",
+ _("tunnelled migration failed to read from
qemu"));
+ goto close_client_sock;
+ }
+ else if (bytes == 0)
+ /* EOF; get out of here */
+ break;
+
+ if (virStreamSend(st, buffer, bytes) < 0) {
+ qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
+ _("Failed to write migration data to remote
libvirtd"));
+ virStreamAbort(st);
+ goto close_client_sock;
+ }
+ }
The virStreamSend() API isn't guaranteed to have sent all the bytes you
passed in, so its neccessary to check the return value to see how much
has actually been sent, and loop until its all gone even in blocking mode.
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|