[libvirt] [PATCH] Add migration APIs for libxl driver

Daniel P. Berrange berrange at redhat.com
Mon Mar 19 10:18:40 UTC 2012


On Fri, Mar 09, 2012 at 06:55:55PM +0800, Chunyan Liu wrote:
> diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
> index d5fa64a..5dc29a0 100644
> --- a/src/libxl/libxl_driver.c
> +++ b/src/libxl/libxl_driver.c
> +static int doParseURI(const char *uri, char **p_hostname, int *p_port)
> +{
> +    char *p, *hostname;
> +    int port_nr = 0;
> +
> +    if (uri == NULL)
> +        return -1;
> +
> +    /* URI passed is a string "hostname[:port]" */
> +    if ((p = strrchr(uri, ':')) != NULL) { /* "hostname:port" */
> +        int n;
> +
> +        if (virStrToLong_i(p+1, NULL, 10, &port_nr) < 0) {
> +            libxlError(VIR_ERR_INVALID_ARG,
> +                        _("Invalid port number"));
> +            return -1;
> +        }
> +
> +        /* Get the hostname. */
> +        n = p - uri; /* n = Length of hostname in bytes. */
> +        if (n <= 0) {
> +            libxlError(VIR_ERR_INVALID_ARG,
> +                       _("Hostname must be specified in the URI"));
> +            return -1;
> +        }
> +
> +        if (virAsprintf(&hostname, "%s", uri) < 0) {
> +            virReportOOMError();
> +            return -1;
> +        }
> +
> +        hostname[n] = '\0';
> +    }
> +    else {/* "hostname" (or IP address) */
> +        if (virAsprintf(&hostname, "%s", uri) < 0) {
> +            virReportOOMError();
> +            return -1;
> +        }
> +    }
> +    *p_hostname = hostname;
> +    *p_port = port_nr;
> +    return 0;
> +}

Lets not re-invent URI parsing code with wierd special cases for
base hostnames. Please just use virURIParse, since there is no
compatibility issue here.

> +static void doMigrateReceive(void *opaque)
> +{
> +    migrate_receive_args *data = opaque;
> +    virConnectPtr conn = data->conn;
> +    int sockfd = data->sockfd;
> +    virDomainObjPtr vm = data->vm;
> +    libxlDriverPrivatePtr driver = conn->privateData;
> +    int recv_fd;
> +    struct sockaddr_in new_addr;
> +    socklen_t socklen = sizeof(new_addr);
> +    int len;
> +
> +    do {
> +        recv_fd = accept(sockfd, (struct sockaddr *)&new_addr, &socklen);
> +    } while(recv_fd < 0 && errno == EINTR);

[snip]

> +    sockfd = socket(AF_INET, SOCK_STREAM, 0);
> +    if (sockfd == -1) {
> +        libxlError(VIR_ERR_OPERATION_FAILED,
> +                   _("Failed to create socket for incoming migration"));
> +        goto cleanup;
> +    }
> +
> +    memset(&addr, 0, sizeof(addr));
> +    addr.sin_family = AF_INET;
> +    addr.sin_port = htons(port);
> +    addr.sin_addr.s_addr = htonl(INADDR_ANY);
> +
> +    if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
> +        libxlError(VIR_ERR_OPERATION_FAILED,
> +                   _("Fail to bind port for incoming migration"));
> +        goto cleanup;
> +    }
> +
> +    if (listen(sockfd, MAXCONN_NUM) < 0){
> +        libxlError(VIR_ERR_OPERATION_FAILED,
> +                   _("Fail to listen to incoming migration"));
> +        goto cleanup;
> +    }
> +
> +    if (VIR_ALLOC(args) < 0) {
> +        virReportOOMError();
> +        goto cleanup;
> +    }

[snip]

> +    memset(&hints, 0, sizeof(hints));
> +    hints.ai_family = AF_INET;
> +    hints.ai_socktype = SOCK_STREAM;
> +    if (getaddrinfo(hostname, servname, &hints, &res) || res == NULL) {
> +        libxlError(VIR_ERR_OPERATION_FAILED,
> +                   _("IP address lookup failed"));
> +        goto cleanup;
> +    }
> +
> +    if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
> +        libxlError(VIR_ERR_OPERATION_FAILED,
> +                   _("Connect error"));
> +        goto cleanup;
> +    }

I know the QEMU code doesn't follow what I'm about to say, but I would
prefer it if all this socket code was re-written to use the internal
virNetSocketPtr APIs.  In particular this would result in correct
usage of getaddrinfo() which is lacking here.



> diff --git a/src/libxl/libxl_driver.h b/src/libxl/libxl_driver.h
> index 4632d33..ad8df1f 100644
> --- a/src/libxl/libxl_driver.h
> +++ b/src/libxl/libxl_driver.h
> @@ -21,9 +21,25 @@
>  /*---------------------------------------------------------------------------*/
> 
>  #ifndef LIBXL_DRIVER_H
> -# define LIBXL_DRIVER_H
> +#define LIBXL_DRIVER_H
> 
> -# include <config.h>
> +#include <config.h>
> +
> +#define LIBXL_MIGRATION_FLAGS                   \
> +    (VIR_MIGRATE_LIVE |                         \
> +     VIR_MIGRATE_UNDEFINE_SOURCE |              \
> +     VIR_MIGRATE_PAUSED)
> +
> +#define MAXCONN_NUM 10
> +#define LIBXL_MIGRATION_MIN_PORT 49512
> +#define LIBXL_MIGRATION_NUM_PORTS 64
> +#define LIBXL_MIGRATION_MAX_PORT                \
> +    (LIBXL_MIGRATION_MIN_PORT + LIBXL_MIGRATION_NUM_PORTS)
> +
> +static const char migrate_receiver_banner[]=
> +    "xl migration receiver ready, send binary domain data";
> +static const char migrate_receiver_ready[]=
> +    "domain received, ready to unpause";

It is better if these were in the .c file, or if they need to be
shared across multiple driver files, use the libxl_conf.h

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list