[libvirt] [PATCH] vmware: detect when a domain was shut down from the inside

Daniel Veillard veillard at redhat.com
Thu Feb 2 13:46:40 UTC 2012


On Wed, Feb 01, 2012 at 02:29:37PM +0100, Jean-Baptiste Rouault wrote:
> This patch adds an internal function vmwareGetVMStatus to
> get the real state of the domain. This function is used in
> various places in the driver, in particular to detect when
> the domain has been shut down by the user with the "halt"
> command.
> ---
>  src/vmware/vmware_driver.c |   83 +++++++++++++++++++++++++++++++++++++-------
>  1 files changed, 70 insertions(+), 13 deletions(-)
> 
> diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
> index 56e9d2d..6f75f86 100644
> --- a/src/vmware/vmware_driver.c
> +++ b/src/vmware/vmware_driver.c
> @@ -28,6 +28,7 @@
>  #include "datatypes.h"
>  #include "virfile.h"
>  #include "memory.h"
> +#include "util.h"
>  #include "uuid.h"
>  #include "command.h"
>  #include "vmx.h"
> @@ -181,6 +182,50 @@ vmwareGetVersion(virConnectPtr conn, unsigned long *version)
>  }
>  
>  static int
> +vmwareGetVMStatus(struct vmware_driver *driver,
> +                  virDomainObjPtr vm,
> +                  int *status,
> +                  int *reason)
> +{
> +    virCommandPtr cmd;
> +    char *outbuf;
> +    char *vmxAbsolutePath;
> +    int state;
> +    int ret = -1;
> +
> +    cmd = virCommandNewArgList(VMRUN, "-T", vmw_types[driver->type],
> +                               "list", NULL);
> +    virCommandSetOutputBuffer(cmd, &outbuf);
> +    if (virCommandRun(cmd, NULL) < 0)
> +        goto cleanup;
> +
> +    state = virDomainObjGetState(vm, reason);
> +
> +    if (virFileResolveAllLinks(((vmwareDomainPtr) vm->privateData)->vmxPath,
> +                               &vmxAbsolutePath) == -1)
> +        goto cleanup;
> +
> +    if (strstr(outbuf, vmxAbsolutePath)) {
> +        /* If the vmx path is in the output, the domain is running or
> +         * is paused but we have no way to detect if it is paused or not. */
> +        if (state == VIR_DOMAIN_PAUSED)
> +            *status = state;
> +        else
> +            *status = VIR_DOMAIN_RUNNING;
> +    } else {
> +        *status = VIR_DOMAIN_SHUTOFF;
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    virCommandFree(cmd);
> +    VIR_FREE(outbuf);
> +    VIR_FREE(vmxAbsolutePath);
> +    return ret;
> +}
> +
> +static int
>  vmwareStopVM(struct vmware_driver *driver,
>               virDomainObjPtr vm,
>               virDomainShutoffReason reason)
> @@ -212,12 +257,6 @@ vmwareStartVM(struct vmware_driver *driver, virDomainObjPtr vm)
>      };
>      const char *vmxPath = ((vmwareDomainPtr) vm->privateData)->vmxPath;
>  
> -    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
> -        vmwareError(VIR_ERR_OPERATION_INVALID, "%s",
> -                    _("domain is not in shutoff state"));
> -        return -1;
> -    }
> -
>      vmwareSetSentinal(cmd, vmw_types[driver->type]);
>      vmwareSetSentinal(cmd, vmxPath);
>      if (!((vmwareDomainPtr) vm->privateData)->gui)
> @@ -317,6 +356,7 @@ vmwareDomainShutdownFlags(virDomainPtr dom,
>  {
>      struct vmware_driver *driver = dom->conn->privateData;
>      virDomainObjPtr vm;
> +    int status;
>      int ret = -1;
>  
>      virCheckFlags(0, -1);
> @@ -331,7 +371,10 @@ vmwareDomainShutdownFlags(virDomainPtr dom,
>          goto cleanup;
>      }
>  
> -    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
> +    if (vmwareGetVMStatus(driver, vm, &status, NULL) == -1)
> +        goto cleanup;
> +
> +    if (status != VIR_DOMAIN_RUNNING) {
>          vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
>                      _("domain is not in running state"));
>          goto cleanup;
> @@ -467,6 +510,7 @@ vmwareDomainReboot(virDomainPtr dom, unsigned int flags)
>          VMRUN, "-T", PROGRAM_SENTINAL,
>          "reset", PROGRAM_SENTINAL, "soft", NULL
>      };
> +    int status;
>      int ret = -1;
>  
>      virCheckFlags(0, -1);
> @@ -485,8 +529,10 @@ vmwareDomainReboot(virDomainPtr dom, unsigned int flags)
>      vmwareSetSentinal(cmd, vmw_types[driver->type]);
>      vmwareSetSentinal(cmd, vmxPath);
>  
> +    if (vmwareGetVMStatus(driver, vm, &status, NULL) == -1)
> +        goto cleanup;
>  
> -    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
> +    if (status != VIR_DOMAIN_RUNNING) {
>          vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
>                      _("domain is not in running state"));
>          goto cleanup;
> @@ -582,6 +628,7 @@ vmwareDomainCreateWithFlags(virDomainPtr dom,
>  {
>      struct vmware_driver *driver = dom->conn->privateData;
>      virDomainObjPtr vm;
> +    int status;
>      int ret = -1;
>  
>      virCheckFlags(0, -1);
> @@ -596,7 +643,10 @@ vmwareDomainCreateWithFlags(virDomainPtr dom,
>          goto cleanup;
>      }
>  
> -    if (virDomainObjIsActive(vm)) {
> +    if (vmwareGetVMStatus(driver, vm, &status, NULL) == -1)
> +        goto cleanup;
> +
> +    if (status != VIR_DOMAIN_SHUTOFF) {
>          vmwareError(VIR_ERR_OPERATION_INVALID,
>                      "%s", _("Domain is already running"));
>          goto cleanup;
> @@ -623,6 +673,7 @@ vmwareDomainUndefineFlags(virDomainPtr dom,
>  {
>      struct vmware_driver *driver = dom->conn->privateData;
>      virDomainObjPtr vm;
> +    int status;
>      int ret = -1;
>  
>      virCheckFlags(0, -1);
> @@ -645,7 +696,10 @@ vmwareDomainUndefineFlags(virDomainPtr dom,
>          goto cleanup;
>      }
>  
> -    if (virDomainObjIsActive(vm)) {
> +    if (vmwareGetVMStatus(driver, vm, &status, NULL) == -1)
> +        goto cleanup;
> +
> +    if (status == VIR_DOMAIN_RUNNING) {
>          vm->persistent = 0;
>      } else {
>          virDomainRemoveInactive(&driver->domains, vm);
> @@ -902,6 +956,7 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
>  {
>      struct vmware_driver *driver = dom->conn->privateData;
>      virDomainObjPtr vm;
> +    int state;
>      int ret = -1;
>  
>      vmwareDriverLock(driver);
> @@ -914,7 +969,10 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
>          goto cleanup;
>      }
>  
> -    info->state = virDomainObjGetState(vm, NULL);
> +    if (vmwareGetVMStatus(driver, vm, &state, NULL) == -1)
> +        goto cleanup;
> +
> +    info->state = state;
>      info->cpuTime = 0;
>      info->maxMem = vm->def->mem.max_balloon;
>      info->memory = vm->def->mem.cur_balloon;
> @@ -949,8 +1007,7 @@ vmwareDomainGetState(virDomainPtr dom,
>          goto cleanup;
>      }
>  
> -    *state = virDomainObjGetState(vm, reason);
> -    ret = 0;
> +    ret = vmwareGetVMStatus(driver, vm, state, reason);
>  
>    cleanup:
>      if (vm)

  That looks reasonable to me, there is a small hit due to the
extra round trip to the server, but I would rather have the opinion
of Mathias before pushing this :-)

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list