<div dir="ltr">Hi John,<div><br></div><div>Thanks for pointing that out. A fix was proposed in here <a href="https://www.redhat.com/archives/libvir-list/2014-September/msg01000.html">https://www.redhat.com/archives/libvir-list/2014-September/msg01000.html</a>.</div><div><br></div><div>Best regards,</div><div>Hongbin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 15, 2014 at 11:46 AM, John Ferlan <span dir="ltr"><<a href="mailto:jferlan@redhat.com" target="_blank">jferlan@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
<br>
On 09/04/2014 10:25 PM, Hongbin Lu wrote:<br>
> This patch adds initial migration support to the OpenVZ driver,<br>
> using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration<br>
> functions.<br>
> ---<br>
>  src/openvz/openvz_conf.h   |    5 +-<br>
>  src/openvz/openvz_driver.c |  348 ++++++++++++++++++++++++++++++++++++++++++++<br>
>  src/openvz/openvz_driver.h |   10 ++<br>
>  3 files changed, 361 insertions(+), 2 deletions(-)<br>
><br>
> diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h<br>
> index a7de7d2..33998d6 100644<br>
> --- a/src/openvz/openvz_conf.h<br>
> +++ b/src/openvz/openvz_conf.h<br>
> @@ -35,8 +35,9 @@<br>
><br>
><br>
>  /* OpenVZ commands - Replace with wrapper scripts later? */<br>
> -# define VZLIST  "/usr/sbin/vzlist"<br>
> -# define VZCTL   "/usr/sbin/vzctl"<br>
> +# define VZLIST     "/usr/sbin/vzlist"<br>
> +# define VZCTL      "/usr/sbin/vzctl"<br>
> +# define VZMIGRATE  "/usr/sbin/vzmigrate"<br>
>  # define VZ_CONF_FILE "/etc/vz/vz.conf"<br>
><br>
>  # define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)<br>
> diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c<br>
> index 851ed30..57b3c22 100644<br>
> --- a/src/openvz/openvz_driver.c<br>
> +++ b/src/openvz/openvz_driver.c<br>
> @@ -2207,6 +2207,348 @@ openvzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,<br>
>  }<br>
><br>
><br>
> +static int<br>
> +openvzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)<br>
> +{<br>
> +    switch (feature) {<br>
> +    case VIR_DRV_FEATURE_MIGRATION_PARAMS:<br>
> +    case VIR_DRV_FEATURE_MIGRATION_V3:<br>
> +        return 1;<br>
> +    default:<br>
> +        return 0;<br>
> +    }<br>
> +}<br>
> +<br>
> +<br>
> +static char *<br>
> +openvzDomainMigrateBegin3Params(virDomainPtr domain,<br>
> +                                virTypedParameterPtr params,<br>
> +                                int nparams,<br>
> +                                char **cookieout ATTRIBUTE_UNUSED,<br>
> +                                int *cookieoutlen ATTRIBUTE_UNUSED,<br>
> +                                unsigned int flags)<br>
> +{<br>
> +    virDomainObjPtr vm = NULL;<br>
> +    struct openvz_driver *driver = domain->conn->privateData;<br>
> +    char *xml = NULL;<br>
> +    int status;<br>
> +<br>
> +    virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);<br>
> +    if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
> +        return NULL;<br>
> +<br>
> +    openvzDriverLock(driver);<br>
> +    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
> +    openvzDriverUnlock(driver);<br>
> +<br>
> +    if (!vm) {<br>
> +        virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
> +                       _("no domain with matching uuid"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    if (!virDomainObjIsActive(vm)) {<br>
> +        virReportError(VIR_ERR_OPERATION_INVALID,<br>
> +                       "%s", _("domain is not running"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (status != VIR_DOMAIN_RUNNING) {<br>
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> +                       _("domain is not in running state"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);<br>
> +<br>
> + cleanup:<br>
> +    if (vm)<br>
> +        virObjectUnlock(vm);<br>
> +    return xml;<br>
> +}<br>
> +<br>
> +static int<br>
> +openvzDomainMigratePrepare3Params(virConnectPtr dconn,<br>
> +                                  virTypedParameterPtr params,<br>
> +                                  int nparams,<br>
> +                                  const char *cookiein ATTRIBUTE_UNUSED,<br>
> +                                  int cookieinlen ATTRIBUTE_UNUSED,<br>
> +                                  char **cookieout ATTRIBUTE_UNUSED,<br>
> +                                  int *cookieoutlen ATTRIBUTE_UNUSED,<br>
> +                                  char **uri_out,<br>
> +                                  unsigned int fflags ATTRIBUTE_UNUSED)<br>
> +{<br>
> +    struct openvz_driver *driver = dconn->privateData;<br>
> +    const char *dom_xml = NULL;<br>
> +    const char *uri_in = NULL;<br>
> +    virDomainDefPtr def = NULL;<br>
> +    virDomainObjPtr vm = NULL;<br>
> +    char *hostname = NULL;<br>
> +    virURIPtr uri = NULL;<br>
> +    int ret = -1;<br>
> +<br>
> +    if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
> +        goto error;<br>
> +<br>
> +    if (virTypedParamsGetString(params, nparams,<br>
> +                                VIR_MIGRATE_PARAM_DEST_XML,<br>
> +                                &dom_xml) < 0 ||<br>
> +        virTypedParamsGetString(params, nparams,<br>
> +                                VIR_MIGRATE_PARAM_URI,<br>
> +                                &uri_in) < 0)<br>
> +        goto error;<br>
> +<br>
> +    if (!dom_xml) {<br>
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> +                       _("no domain XML passed"));<br>
> +        goto error;<br>
> +    }<br>
> +<br>
> +    if (!(def = virDomainDefParseString(dom_xml, driver->caps, driver->xmlopt,<br>
> +                                        1 << VIR_DOMAIN_VIRT_OPENVZ,<br>
> +                                        VIR_DOMAIN_XML_INACTIVE)))<br>
> +        goto error;<br>
> +<br>
> +    if (!(vm = virDomainObjListAdd(driver->domains, def,<br>
> +                                   driver->xmlopt,<br>
> +                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |<br>
> +                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,<br>
> +                                   NULL)))<br>
> +        goto error;<br>
> +    def = NULL;<br>
> +<br>
> +    if (!uri_in) {<br>
> +        if ((hostname = virGetHostname()) == NULL)<br>
> +            goto error;<br>
> +<br>
<br>
</div></div>hostname is leaked  (Coverity finds this)<br>
<div><div class="h5"><br>
<br>
> +        if (STRPREFIX(hostname, "localhost")) {<br>
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> +                           _("hostname on destination resolved to localhost,"<br>
> +                             " but migration requires an FQDN"));<br>
> +            goto error;<br>
> +        }<br>
> +    } else {<br>
> +        uri = virURIParse(uri_in);<br>
> +<br>
> +        if (uri == NULL) {<br>
> +            virReportError(VIR_ERR_INVALID_ARG,<br>
> +                           _("unable to parse URI: %s"),<br>
> +                           uri_in);<br>
> +            goto error;<br>
> +        }<br>
> +<br>
> +        if (uri->server == NULL) {<br>
> +            virReportError(VIR_ERR_INVALID_ARG,<br>
> +                           _("missing host in migration URI: %s"),<br>
> +                           uri_in);<br>
> +            goto error;<br>
> +        } else {<br>
> +            hostname = uri->server;<br>
> +        }<br>
> +    }<br>
> +<br>
> +    if (virAsprintf(uri_out, "ssh://%s", hostname) < 0)<br>
> +        goto error;<br>
> +<br>
> +    ret = 0;<br>
> +    goto done;<br>
> +<br>
> + error:<br>
> +    virDomainDefFree(def);<br>
> +    if (vm) {<br>
> +        virDomainObjListRemove(driver->domains, vm);<br>
> +        vm = NULL;<br>
> +    }<br>
> +<br>
> + done:<br>
> +    virURIFree(uri);<br>
> +    if (vm)<br>
> +        virObjectUnlock(vm);<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +static int<br>
> +openvzDomainMigratePerform3Params(virDomainPtr domain,<br>
> +                                  const char *dconnuri ATTRIBUTE_UNUSED,<br>
> +                                  virTypedParameterPtr params,<br>
> +                                  int nparams,<br>
> +                                  const char *cookiein ATTRIBUTE_UNUSED,<br>
> +                                  int cookieinlen ATTRIBUTE_UNUSED,<br>
> +                                  char **cookieout ATTRIBUTE_UNUSED,<br>
> +                                  int *cookieoutlen ATTRIBUTE_UNUSED,<br>
> +                                  unsigned int flags)<br>
> +{<br>
> +    struct openvz_driver *driver = domain->conn->privateData;<br>
> +    virDomainObjPtr vm = NULL;<br>
> +    const char *uri_str = NULL;<br>
> +    virURIPtr uri = NULL;<br>
> +    virCommandPtr cmd = virCommandNew(VZMIGRATE);<br>
> +    int ret = -1;<br>
> +<br>
<br>
</div></div>And 'cmd' is leaked (Coverity finds this) because virCheckFlags is a<br>
macro which causes a return of -1<br>
<span class="HOEnZb"><font color="#888888"><br>
John<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
> +    virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);<br>
> +    if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (virTypedParamsGetString(params, nparams,<br>
> +                                VIR_MIGRATE_PARAM_URI,<br>
> +                                &uri_str) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    openvzDriverLock(driver);<br>
> +    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
> +    openvzDriverUnlock(driver);<br>
> +<br>
> +    if (!vm) {<br>
> +        virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
> +                       _("no domain with matching uuid"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    /* parse dst host:port from uri */<br>
> +    uri = virURIParse(uri_str);<br>
> +    if (uri == NULL || uri->server == NULL)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (flags & VIR_MIGRATE_LIVE)<br>
> +        virCommandAddArg(cmd, "--live");<br>
> +    virCommandAddArg(cmd, uri->server);<br>
> +    virCommandAddArg(cmd, vm->def->name);<br>
> +<br>
> +    if (virCommandRun(cmd, NULL) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    ret = 0;<br>
> +<br>
> + cleanup:<br>
> +    virCommandFree(cmd);<br>
> +    virURIFree(uri);<br>
> +    if (vm)<br>
> +        virObjectUnlock(vm);<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +static virDomainPtr<br>
> +openvzDomainMigrateFinish3Params(virConnectPtr dconn,<br>
> +                                 virTypedParameterPtr params,<br>
> +                                 int nparams,<br>
> +                                 const char *cookiein ATTRIBUTE_UNUSED,<br>
> +                                 int cookieinlen ATTRIBUTE_UNUSED,<br>
> +                                 char **cookieout ATTRIBUTE_UNUSED,<br>
> +                                 int *cookieoutlen ATTRIBUTE_UNUSED,<br>
> +                                 unsigned int flags,<br>
> +                                 int cancelled)<br>
> +{<br>
> +    struct openvz_driver *driver = dconn->privateData;<br>
> +    virDomainObjPtr vm = NULL;<br>
> +    const char *dname = NULL;<br>
> +    virDomainPtr dom = NULL;<br>
> +    int status;<br>
> +<br>
> +    if (cancelled)<br>
> +        goto cleanup;<br>
> +<br>
> +    virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);<br>
> +    if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (virTypedParamsGetString(params, nparams,<br>
> +                                VIR_MIGRATE_PARAM_DEST_NAME,<br>
> +                                &dname) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (!dname ||<br>
> +        !(vm = virDomainObjListFindByName(driver->domains, dname))) {<br>
> +        /* Migration obviously failed if the domain doesn't exist */<br>
> +        virReportError(VIR_ERR_OPERATION_FAILED,<br>
> +                       _("Migration failed. No domain on destination host "<br>
> +                         "with matching name '%s'"),<br>
> +                       NULLSTR(dname));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
> +        goto cleanup;<br>
> +<br>
> +    if (status != VIR_DOMAIN_RUNNING) {<br>
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
> +                       _("domain is not running on destination host"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    vm->def->id = strtoI(vm->def->name);<br>
> +    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_MIGRATED);<br>
> +<br>
> +    dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);<br>
> +    if (dom)<br>
> +        dom->id = vm->def->id;<br>
> +<br>
> + cleanup:<br>
> +    if (vm)<br>
> +        virObjectUnlock(vm);<br>
> +    return dom;<br>
> +}<br>
> +<br>
> +static int<br>
> +openvzDomainMigrateConfirm3Params(virDomainPtr domain,<br>
> +                                  virTypedParameterPtr params,<br>
> +                                  int nparams,<br>
> +                                  const char *cookiein ATTRIBUTE_UNUSED,<br>
> +                                  int cookieinlen ATTRIBUTE_UNUSED,<br>
> +                                  unsigned int flags,<br>
> +                                  int cancelled)<br>
> +{<br>
> +    struct openvz_driver *driver = domain->conn->privateData;<br>
> +    virDomainObjPtr vm = NULL;<br>
> +    int status;<br>
> +    int ret = -1;<br>
> +<br>
> +    virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);<br>
> +    if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
> +        goto cleanup;<br>
> +<br>
> +    openvzDriverLock(driver);<br>
> +    vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
> +    openvzDriverUnlock(driver);<br>
> +<br>
> +    if (!vm) {<br>
> +        virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
> +                       _("no domain with matching uuid"));<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    if (cancelled) {<br>
> +        if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
> +            goto cleanup;<br>
> +<br>
> +        if (status == VIR_DOMAIN_RUNNING) {<br>
> +            ret = 0;<br>
> +        } else {<br>
> +            VIR_DEBUG("Domain '%s' does not recover after failed migration",<br>
> +                      vm->def->name);<br>
> +        }<br>
> +<br>
> +        goto cleanup;<br>
> +    }<br>
> +<br>
> +    vm->def->id = -1;<br>
> +<br>
> +    VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);<br>
> +<br>
> +    virDomainObjListRemove(driver->domains, vm);<br>
> +    vm = NULL;<br>
> +<br>
> +    ret = 0;<br>
> +<br>
> + cleanup:<br>
> +    if (vm)<br>
> +        virObjectUnlock(vm);<br>
> +    return ret;<br>
> +}<br>
> +<br>
> +<br>
>  static virDriver openvzDriver = {<br>
>      .no = VIR_DRV_OPENVZ,<br>
>      .name = "OPENVZ",<br>
> @@ -2265,6 +2607,12 @@ static virDriver openvzDriver = {<br>
>      .connectIsAlive = openvzConnectIsAlive, /* 0.9.8 */<br>
>      .domainUpdateDeviceFlags = openvzDomainUpdateDeviceFlags, /* 0.9.13 */<br>
>      .domainGetHostname = openvzDomainGetHostname, /* 0.10.0 */<br>
> +    .connectSupportsFeature = openvzConnectSupportsFeature, /* 1.2.8 */<br>
> +    .domainMigrateBegin3Params = openvzDomainMigrateBegin3Params, /* 1.2.8 */<br>
> +    .domainMigratePrepare3Params = openvzDomainMigratePrepare3Params, /* 1.2.8 */<br>
> +    .domainMigratePerform3Params = openvzDomainMigratePerform3Params, /* 1.2.8 */<br>
> +    .domainMigrateFinish3Params = openvzDomainMigrateFinish3Params, /* 1.2.8 */<br>
> +    .domainMigrateConfirm3Params = openvzDomainMigrateConfirm3Params, /* 1.2.8 */<br>
>  };<br>
><br>
>  int openvzRegister(void)<br>
> diff --git a/src/openvz/openvz_driver.h b/src/openvz/openvz_driver.h<br>
> index b39e81c..0c7a070 100644<br>
> --- a/src/openvz/openvz_driver.h<br>
> +++ b/src/openvz/openvz_driver.h<br>
> @@ -31,6 +31,16 @@<br>
><br>
>  # include "internal.h"<br>
><br>
> +# define OPENVZ_MIGRATION_FLAGS                 \<br>
> +    (VIR_MIGRATE_LIVE)<br>
> +<br>
> +/* All supported migration parameters and their types. */<br>
> +# define OPENVZ_MIGRATION_PARAMETERS                            \<br>
> +    VIR_MIGRATE_PARAM_URI,              VIR_TYPED_PARAM_STRING, \<br>
> +    VIR_MIGRATE_PARAM_DEST_NAME,        VIR_TYPED_PARAM_STRING, \<br>
> +    VIR_MIGRATE_PARAM_DEST_XML,         VIR_TYPED_PARAM_STRING, \<br>
> +    NULL<br>
> +<br>
>  int openvzRegister(void);<br>
><br>
>  #endif<br>
><br>
</div></div></blockquote></div><br></div>