[libvirt] [PATCH] Tunnelled migration.

Daniel P. Berrange berrange at redhat.com
Wed Sep 30 12:11:04 UTC 2009


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 :|




More information about the libvir-list mailing list