]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
vmware: detect when a domain was shut down from the inside
authorJean-Baptiste Rouault <jean-baptiste.rouault@diateam.net>
Mon, 2 Apr 2012 13:59:32 +0000 (15:59 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 4 Jul 2012 09:41:13 +0000 (11:41 +0200)
This patch adds an internal function vmwareUpdateVMStatus to
update 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

index a3356516e6b363bc6b3393bfead30430540595b0..2b9a27531bcc46023d260317cb499713a2fcb100 100644 (file)
@@ -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,64 @@ vmwareGetVersion(virConnectPtr conn, unsigned long *version)
     return 0;
 }
 
+static int
+vmwareUpdateVMStatus(struct vmware_driver *driver, virDomainObjPtr vm)
+{
+    virCommandPtr cmd;
+    char *outbuf = NULL;
+    char *vmxAbsolutePath = NULL;
+    char *parsedVmxPath = NULL;
+    char *str;
+    char *saveptr = NULL;
+    bool found = false;
+    int oldState = virDomainObjGetState(vm, NULL);
+    int newState;
+    int ret = -1;
+
+    cmd = virCommandNewArgList(VMRUN, "-T", vmw_types[driver->type],
+                               "list", NULL);
+    virCommandSetOutputBuffer(cmd, &outbuf);
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    if (virFileResolveAllLinks(((vmwareDomainPtr) vm->privateData)->vmxPath,
+                               &vmxAbsolutePath) < 0)
+        goto cleanup;
+
+    for(str = outbuf ; (parsedVmxPath = strtok_r(str, "\n", &saveptr)) != NULL;
+        str = NULL) {
+
+        if (parsedVmxPath[0] != '/')
+            continue;
+
+        if (STREQ(parsedVmxPath, vmxAbsolutePath)) {
+            found = true;
+            /* 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 (oldState == VIR_DOMAIN_PAUSED)
+                newState = oldState;
+            else
+                newState = VIR_DOMAIN_RUNNING;
+            break;
+        }
+    }
+
+    if (!found) {
+        vm->def->id = -1;
+        newState = VIR_DOMAIN_SHUTOFF;
+    }
+
+    virDomainObjSetState(vm, newState, 0);
+
+    ret = 0;
+
+cleanup:
+    virCommandFree(cmd);
+    VIR_FREE(outbuf);
+    VIR_FREE(vmxAbsolutePath);
+    return ret;
+}
+
 static int
 vmwareStopVM(struct vmware_driver *driver,
              virDomainObjPtr vm,
@@ -332,6 +391,9 @@ vmwareDomainShutdownFlags(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
+
     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("domain is not in running state"));
@@ -486,6 +548,8 @@ vmwareDomainReboot(virDomainPtr dom, unsigned int flags)
     vmwareSetSentinal(cmd, vmw_types[driver->type]);
     vmwareSetSentinal(cmd, vmxPath);
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
 
     if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) {
         vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -597,6 +661,9 @@ vmwareDomainCreateWithFlags(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
+
     if (virDomainObjIsActive(vm)) {
         vmwareError(VIR_ERR_OPERATION_INVALID,
                     "%s", _("Domain is already running"));
@@ -646,6 +713,9 @@ vmwareDomainUndefineFlags(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
+
     if (virDomainObjIsActive(vm)) {
         vm->persistent = 0;
     } else {
@@ -875,6 +945,21 @@ vmwareDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat,
     return xml;
 }
 
+static void vmwareDomainObjListUpdateDomain(void *payload, const void *name ATTRIBUTE_UNUSED, void *data)
+{
+    struct vmware_driver *driver = data;
+    virDomainObjPtr vm = payload;
+    virDomainObjLock(vm);
+    vmwareUpdateVMStatus(driver, vm);
+    virDomainObjUnlock(vm);
+}
+
+static void
+vmwareDomainObjListUpdateAll(virDomainObjListPtr doms, struct vmware_driver *driver)
+{
+    virHashForEach(doms->objs, vmwareDomainObjListUpdateDomain, driver);
+}
+
 static int
 vmwareNumDefinedDomains(virConnectPtr conn)
 {
@@ -882,6 +967,7 @@ vmwareNumDefinedDomains(virConnectPtr conn)
     int n;
 
     vmwareDriverLock(driver);
+    vmwareDomainObjListUpdateAll(&driver->domains, driver);
     n = virDomainObjListNumOfDomains(&driver->domains, 0);
     vmwareDriverUnlock(driver);
 
@@ -895,6 +981,7 @@ vmwareNumDomains(virConnectPtr conn)
     int n;
 
     vmwareDriverLock(driver);
+    vmwareDomainObjListUpdateAll(&driver->domains, driver);
     n = virDomainObjListNumOfDomains(&driver->domains, 1);
     vmwareDriverUnlock(driver);
 
@@ -909,6 +996,7 @@ vmwareListDomains(virConnectPtr conn, int *ids, int nids)
     int n;
 
     vmwareDriverLock(driver);
+    vmwareDomainObjListUpdateAll(&driver->domains, driver);
     n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
     vmwareDriverUnlock(driver);
 
@@ -923,6 +1011,7 @@ vmwareListDefinedDomains(virConnectPtr conn,
     int n;
 
     vmwareDriverLock(driver);
+    vmwareDomainObjListUpdateAll(&driver->domains, driver);
     n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
     vmwareDriverUnlock(driver);
     return n;
@@ -945,6 +1034,9 @@ vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
         goto cleanup;
     }
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
+
     info->state = virDomainObjGetState(vm, NULL);
     info->cpuTime = 0;
     info->maxMem = vm->def->mem.max_balloon;
@@ -980,6 +1072,9 @@ vmwareDomainGetState(virDomainPtr dom,
         goto cleanup;
     }
 
+    if (vmwareUpdateVMStatus(driver, vm) < 0)
+        goto cleanup;
+
     *state = virDomainObjGetState(vm, reason);
     ret = 0;
 
@@ -1006,6 +1101,7 @@ vmwareListAllDomains(virConnectPtr conn,
     virCheckFlags(VIR_CONNECT_LIST_FILTERS_ALL, -1);
 
     vmwareDriverLock(driver);
+    vmwareDomainObjListUpdateAll(&driver->domains, driver);
     ret = virDomainList(conn, driver->domains.objs, domains, flags);
     vmwareDriverUnlock(driver);
     return ret;