2012/2/1 Jean-Baptiste Rouault <jean-baptiste.rouault(a)diateam.net>:
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