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

2012-03-13 Thread Jean-Baptiste Rouault
On Friday 03 February 2012 09:42:29 Matthias Bolte wrote: 
> You changed all lifecycle functions not to rely on possible stale
> information, but you missed to update the cached state information in
> the virDomainObj list resulting in virsh list giving wrong output and
> possibly listing VMs as active that aren't active anymore.
> 
> Maybe you should replace vmwareGetVMStatus with vmwareUpdateVMStatus
> that updates the cached information in a virDomainObj and call it in
> all places that read information from a virDomainObj.
> 
> A more general question: is this driver supposed to work properly when
> someone uses vmrun to alter a VMs behind libvirt's back? If that's the
> case then maybe this driver should not cache anything at all and work
> like the vSphere, Hyper-V or VirtualBox driver. They always query the
> hypervisor for information and cache nothing.
> 
> I'm not sure what's the best approach here.

Hi,

The problem here is that contrary to vSphere, Hyper-V or VirtualBox, I have no 
way to get a list of defined domains as vmrun only lists running domains.
So I think I'll do as you suggested and go for a vmwareUpdateVMStatus
function.

Regards,
Jean-Baptiste

-- 
Jean-Baptiste ROUAULT
Ingénieur R&D - diateam : Architectes de l'information
Phone : +33 (0)9 53 16 02 70 Fax : +33 (0)2 98 050 051

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

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

2012-02-03 Thread Matthias Bolte
2012/2/1 Jean-Baptiste Rouault :
> 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.

> @@ -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;

vmxAbsolutePath needs to be initialized to NULL and outbuf should be
initialized to NULL too.

> +    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;

Because this goto cleanup can skip the initialization of
vmxAbsolutePath and the VIR_FREE call later on will free a random
pointer.

> +    state = virDomainObjGetState(vm, reason);
> +
> +    if (virFileResolveAllLinks(((vmwareDomainPtr) vm->privateData)->vmxPath,
> +                               &vmxAbsolutePath) == -1)

Check for < 0 instead of == -1.

> +        goto cleanup;
> +
> +    if (strstr(outbuf, vmxAbsolutePath)) {

This isn't robust, simple substring match doesn't work properly here.
For example, when vmxAbsolutePath is /random/path/file.vmx and you
have two VMs, /random/path/file.vmx and
/something/random/path/file.vmx. Now just the second one is currently
active, vmrun outputs just /something/random/path/file.vmx and you get
a match for /random/path/file.vmx from strstr making you think this
one is active but it isn't.

I think this needs more complex parsing to get it robust.

> +        /* 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)

> @@ -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;

Prefer < 0 over == -1, as this is the common style in libvirt.

You changed all lifecycle functions not to rely on possible stale
information, but you missed to update the cached state information in
the virDomainObj list resulting in virsh list giving wrong output and
possibly listing VMs as active that aren't active anymore.

Maybe you should replace vmwareGetVMStatus with vmwareUpdateVMStatus
that updates the cached information in a virDomainObj and call it in
all places that read information from a virDomainObj.

A more general question: is this driver supposed to work properly when
someone uses vmrun to alter a VMs behind libvirt's back? If that's the
case then maybe this driver should not cache anything at all and work
like the vSphere, Hyper-V or VirtualBox driver. They always query the
hypervisor for information and cache nothing.

I'm not sure what's the best approach here.

-- 
Matthias Bolte
http://photron.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

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

2012-02-02 Thread Daniel Veillard
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 runnin

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

2012-02-01 Thread Jean-Baptiste Rouault
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 (virDomainObjIs