[libvirt] [Patch v2] Add VMware Workstation and Player driver

Jean-Baptiste Rouault jean-baptiste.rouault at diateam.net
Thu Dec 2 13:51:43 UTC 2010


---
 configure.ac                |    7 +
 include/libvirt/virterror.h |    1 +
 po/POTFILES.in              |    2 +
 src/Makefile.am             |   24 +-
 src/driver.h                |    3 +-
 src/libvirt.c               |   15 +
 src/util/virterror.c        |    3 +
 src/vmware/vmware_conf.c    |  480 +++++++++++++++
 src/vmware/vmware_conf.h    |   82 +++
 src/vmware/vmware_driver.c  | 1372 +++++++++++++++++++++++++++++++++++++++++++
 src/vmware/vmware_driver.h  |   25 +
 11 files changed, 2010 insertions(+), 4 deletions(-)
 create mode 100644 src/vmware/vmware_conf.c
 create mode 100644 src/vmware/vmware_conf.h
 create mode 100644 src/vmware/vmware_driver.c
 create mode 100644 src/vmware/vmware_driver.h

diff --git a/configure.ac b/configure.ac
index d26bc68..f96a326 100644
--- a/configure.ac
+++ b/configure.ac
@@ -227,6 +227,8 @@ AC_ARG_WITH([uml],
   AC_HELP_STRING([--with-uml], [add UML support @<:@default=check@:>@]),[],[with_uml=check])
 AC_ARG_WITH([openvz],
   AC_HELP_STRING([--with-openvz], [add OpenVZ support @<:@default=yes@:>@]),[],[with_openvz=yes])
+AC_ARG_WITH([vmware],
+  AC_HELP_STRING([--with-vmware], [add VMware support @<:@default=yes@:>@]),[],[with_vmware=yes])
 AC_ARG_WITH([libssh2],
   AC_HELP_STRING([--with-libssh2=@<:@PFX@:>@], [libssh2 location @<:@default=/usr/local/lib@:>@]),[],[with_libssh2=yes])
 AC_ARG_WITH([phyp],
@@ -316,6 +318,10 @@ if test "$with_openvz" = "yes"; then
 fi
 AM_CONDITIONAL([WITH_OPENVZ], [test "$with_openvz" = "yes"])
 
+if test "$with_vmware" = "yes"; then
+    AC_DEFINE_UNQUOTED([WITH_VMWARE], 1, [whether VMware driver is enabled])
+fi
+AM_CONDITIONAL([WITH_VMWARE], [test "$with_vmware" = "yes"])
 
 dnl
 dnl check for XDR
@@ -2274,6 +2280,7 @@ AC_MSG_NOTICE([     Xen: $with_xen])
 AC_MSG_NOTICE([    QEMU: $with_qemu])
 AC_MSG_NOTICE([     UML: $with_uml])
 AC_MSG_NOTICE([  OpenVZ: $with_openvz])
+AC_MSG_NOTICE([  VMware: $with_vmware])
 AC_MSG_NOTICE([    VBox: $with_vbox])
 AC_MSG_NOTICE([  XenAPI: $with_xenapi])
 AC_MSG_NOTICE([     LXC: $with_lxc])
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index eaeb477..a1f88f4 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -52,6 +52,7 @@ typedef enum {
     VIR_FROM_TEST,	/* Error from test driver */
     VIR_FROM_REMOTE,	/* Error from remote driver */
     VIR_FROM_OPENVZ,    /* Error from OpenVZ driver */
+    VIR_FROM_VMWARE,    /* Error from VMware driver */
     VIR_FROM_XENXM,	/* Error at Xen XM layer */
     VIR_FROM_STATS_LINUX,/* Error in the Linux Stats code */
     VIR_FROM_LXC,       /* Error from Linux Container driver */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2820ac1..71c7608 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -99,6 +99,8 @@ src/util/xml.c
 src/vbox/vbox_XPCOMCGlue.c
 src/vbox/vbox_driver.c
 src/vbox/vbox_tmpl.c
+src/vmware/vmware_conf.c
+src/vmware/vmware_driver.c
 src/xen/xen_driver.c
 src/xen/xen_hypervisor.c
 src/xen/xen_inotify.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a9a1986..78eaa0b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -217,8 +217,6 @@ check-local: remote_protocol-structs
 TEST_DRIVER_SOURCES =						\
 		test/test_driver.c test/test_driver.h
 
-
-
 # Now the Hypervisor specific drivers
 XEN_DRIVER_SOURCES =						\
 		xen/sexpr.c xen/sexpr.h				\
@@ -254,6 +252,10 @@ OPENVZ_DRIVER_SOURCES =						\
 		openvz/openvz_conf.c openvz/openvz_conf.h	\
 		openvz/openvz_driver.c openvz/openvz_driver.h
 
+VMWARE_DRIVER_SOURCES = 					\
+		vmware/vmware_driver.c vmware/vmware.h		\
+		vmware/vmware_conf.c vmware/vmware_conf.h
+
 VBOX_DRIVER_SOURCES =						\
         vbox/vbox_XPCOMCGlue.c vbox/vbox_XPCOMCGlue.h		\
         vbox/vbox_driver.c vbox/vbox_driver.h			\
@@ -599,6 +601,21 @@ endif
 libvirt_driver_openvz_la_SOURCES = $(OPENVZ_DRIVER_SOURCES)
 endif
 
+if WITH_VMWARE
+if WITH_DRIVER_MODULES
+mod_LTLIBRARIES += libvirt_driver_vmware.la
+else
+noinst_LTLIBRARIES += libvirt_driver_vmware.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_vmware.la
+endif
+libvirt_driver_vmware_la_CFLAGS = \
+		-I at top_srcdir@/src/conf
+if WITH_DRIVER_MODULES
+libvirt_driver_vmware_la_LDFLAGS = -module -avoid-version
+endif
+libvirt_driver_vmware_la_SOURCES = $(VMWARE_DRIVER_SOURCES)
+endif
+
 if WITH_VBOX
 if WITH_DRIVER_MODULES
 mod_LTLIBRARIES += libvirt_driver_vbox.la
@@ -951,7 +968,8 @@ EXTRA_DIST +=							\
 		$(SECURITY_DRIVER_SELINUX_SOURCES)		\
 		$(SECURITY_DRIVER_APPARMOR_SOURCES)		\
 		$(SECRET_DRIVER_SOURCES)			\
-		$(VBOX_DRIVER_EXTRA_DIST)
+		$(VBOX_DRIVER_EXTRA_DIST)			\
+		$(VMWARE_DRIVER_SOURCES)
 
 check-local: augeas-check
 
diff --git a/src/driver.h b/src/driver.h
index b770e5e..a03ea25 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -27,7 +27,8 @@ typedef enum {
     VIR_DRV_ONE = 9,
     VIR_DRV_ESX = 10,
     VIR_DRV_PHYP = 11,
-    VIR_DRV_XENAPI = 12
+    VIR_DRV_XENAPI = 12,
+    VIR_DRV_VMWARE = 13
 } virDrvNo;
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index b4951c2..8243c5e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -54,6 +54,9 @@
 # ifdef WITH_OPENVZ
 #  include "openvz/openvz_driver.h"
 # endif
+# ifdef WITH_VMWARE
+#  include "vmware/vmware_driver.h"
+# endif
 # ifdef WITH_PHYP
 #  include "phyp/phyp_driver.h"
 # endif
@@ -365,6 +368,9 @@ virInitialize(void)
 # ifdef WITH_OPENVZ
     virDriverLoadModule("openvz");
 # endif
+# ifdef WITH_VMWARE
+    virDriverLoadModule("vmware");
+# endif
 # ifdef WITH_VBOX
     virDriverLoadModule("vbox");
 # endif
@@ -387,6 +393,9 @@ virInitialize(void)
 # ifdef WITH_OPENVZ
     if (openvzRegister() == -1) return -1;
 # endif
+# ifdef WITH_VMWARE
+    if (vmwareRegister() == -1) return -1;
+# endif
 # ifdef WITH_PHYP
     if (phypRegister() == -1) return -1;
 # endif
@@ -1120,6 +1129,12 @@ virGetVersion(unsigned long *libVer, const char *type,
         if (STRCASEEQ(type, "OpenVZ"))
             *typeVer = LIBVIR_VERSION_NUMBER;
 # endif
+# if WITH_VMWARE
+        if (STRCASEEQ(type, "vmware player"))
+            *typeVer = LIBVIR_VERSION_NUMBER;
+        if (STRCASEEQ(type, "vmware workstation"))
+            *typeVer = LIBVIR_VERSION_NUMBER;
+# endif
 # if WITH_VBOX
         if (STRCASEEQ(type, "VBox"))
             *typeVer = LIBVIR_VERSION_NUMBER;
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 6e49fa2..6b9653e 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -134,6 +134,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
         case VIR_FROM_OPENVZ:
             dom = "OpenVZ ";
             break;
+        case VIR_FROM_VMWARE:
+            dom = "VMware ";
+            break;
         case VIR_FROM_XENXM:
             dom = "Xen XM ";
             break;
diff --git a/src/vmware/vmware_conf.c b/src/vmware/vmware_conf.c
new file mode 100644
index 0000000..5e873e1
--- /dev/null
+++ b/src/vmware/vmware_conf.c
@@ -0,0 +1,480 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright 2010, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+/*---------------------------------------------------------------------------*/
+
+#include <config.h>
+
+#include <sys/utsname.h>
+
+#include "cpu/cpu.h"
+#include "memory.h"
+#include "nodeinfo.h"
+#include "util/files.h"
+#include "uuid.h"
+#include "virterror_internal.h"
+#include "../esx/esx_vmx.h"
+
+#include "vmware_conf.h"
+
+#define VMWARE_MAX_ARG 20
+
+/* Free all memory associated with a vmware_driver structure */
+void
+vmwareFreeDriver(struct vmware_driver *driver)
+{
+    if (!driver)
+        return;
+
+    virDomainObjListDeinit(&driver->domains);
+    virCapabilitiesFree(driver->caps);
+    VIR_FREE(driver);
+}
+
+virCapsPtr
+vmwareCapsInit(void)
+{
+    struct utsname utsname;
+    virCapsPtr caps = NULL;
+    virCapsGuestPtr guest = NULL;
+    virCPUDefPtr cpu = NULL;
+    union cpuData *data = NULL;
+
+    uname(&utsname);
+
+    if ((caps = virCapabilitiesNew(utsname.machine, 0, 0)) == NULL)
+        goto error;
+
+    if (nodeCapsInitNUMA(caps) < 0)
+        goto error;
+
+    virCapabilitiesSetMacPrefix(caps, (unsigned char[]) {0x52, 0x54, 0x00});
+
+    /* i686 guests are always supported */
+    if ((guest = virCapabilitiesAddGuest(caps,
+                                         "hvm",
+                                         "i686",
+                                         32,
+                                         NULL, NULL, 0, NULL)) == NULL)
+        goto error;
+
+    if (virCapabilitiesAddGuestDomain(guest,
+                                      "vmware",
+                                      NULL, NULL, 0, NULL) == NULL)
+        goto error;
+
+    /* check if x86_64 guests are supported */
+    if (VIR_ALLOC(cpu) < 0
+        || !(cpu->arch = strdup(utsname.machine))) {
+        virReportOOMError();
+        goto error;
+    }
+
+    cpu->type = VIR_CPU_TYPE_HOST;
+
+    if (!(data = cpuNodeData(cpu->arch))
+        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
+        goto error;
+    }
+
+    if (cpuHasFeature(utsname.machine, data, "vmx")
+        || cpuHasFeature(utsname.machine, data, "svm")) {
+
+        if ((guest = virCapabilitiesAddGuest(caps,
+                                             "hvm",
+                                             "x86_64",
+                                             64,
+                                             NULL, NULL, 0, NULL)) == NULL)
+            goto error;
+
+        if (virCapabilitiesAddGuestDomain(guest,
+                                          "vmware",
+                                          NULL, NULL, 0, NULL) == NULL)
+            goto error;
+    }
+
+cleanup:
+    virCPUDefFree(cpu);
+    cpuDataFree(utsname.machine, data);
+
+    return caps;
+
+error:
+    virCapabilitiesFree(caps);
+    goto cleanup;
+}
+
+int
+vmwareLoadDomains(struct vmware_driver *driver)
+{
+    FILE *fp;
+    virDomainDefPtr vmdef = NULL;
+    virDomainObjPtr vm = NULL;
+    char vmxPath[1024];
+    char * vmx = NULL;
+    vmwareDomainPtr pDomain;
+    char *directoryName = NULL;
+    char *fileName = NULL;
+    int ret = -1;
+    esxVMX_Context ctx;
+
+    ctx.parseFileName = esxCopyVMXFileName;
+
+    fp = driver->type ==
+        TYPE_PLAYER ? popen(VMRUN " -T " "player" " list 2>/dev/null",
+                            "r") : popen(VMRUN " -T " "ws"
+                                         " list 2>/dev/null", "r");
+    if (fp == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s", _("popen failed"));
+        return -1;
+    }
+
+    while (!feof(fp)) {
+        if (fgets(vmxPath, 1024, fp) == NULL) {
+            if (feof(fp))
+                break;
+
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Failed to parse vmrun list output"));
+            goto cleanup;
+        }
+        if (vmxPath[0] != '/')
+            continue;
+
+        /* remove trailing newline */
+        int len = strlen(vmxPath);
+        if (len && vmxPath[len-1] == '\n')
+            vmxPath[len-1] = '\0';
+
+        if (virFileReadAll(vmxPath, 10000, &vmx) == -1) {
+            perror("error reading vmx file");
+            vmwareError(VIR_ERR_INTERNAL_ERROR,
+                        _("failed to read vmx file %s"), vmxPath);
+            goto cleanup;
+        }
+
+        if ((vmdef =
+             esxVMX_ParseConfig(&ctx, driver->caps, vmx,
+                                esxVI_ProductVersion_ESX4x)) == NULL) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR,
+                        _("failed to parse config file"));
+            goto cleanup;
+        }
+
+        if (!(vm = virDomainAssignDef(driver->caps,
+                                      &driver->domains, vmdef, false)))
+            goto cleanup;
+
+        pDomain = vm->privateData;
+
+        pDomain->vmxPath = strdup(vmxPath);
+        if (pDomain->vmxPath == NULL) {
+            virReportOOMError();
+            goto no_memory;
+        }
+
+        vmwareDomainConfigDisplay(pDomain, vmdef);
+
+        //vmrun list only reports running vms
+        vm->state = VIR_DOMAIN_RUNNING;
+        vm->def->id = driver->nextvmid++;
+        vm->persistent = 1;
+
+        virDomainObjUnlock(vm);
+
+        vmdef = NULL;
+        vm = NULL;
+    }
+
+    ret = 0;
+
+cleanup:
+    virDomainDefFree(vmdef);
+    VIR_FORCE_FCLOSE(fp);
+    VIR_FREE(directoryName);
+    VIR_FREE(fileName);
+    VIR_FREE(vmx);
+    if (vm)
+        virDomainObjUnref(vm);
+    return ret;
+
+no_memory:
+    virReportOOMError();
+    goto cleanup;
+}
+
+void
+vmwareSetSentinal(const char **prog, const char *key)
+{
+    const char **tmp = prog;
+
+    while (tmp && *tmp) {
+        if (*tmp == PROGRAM_SENTINAL) {
+            *tmp = key;
+            break;
+        }
+        tmp++;
+    }
+}
+
+int
+vmwareExtractVersion(struct vmware_driver *driver)
+{
+    unsigned long version = 0;
+    FILE *fp = NULL;
+    char str[50];
+    char *tmp;
+    int ret = -1;
+
+    if (driver->type == TYPE_PLAYER) {
+        if ((fp = popen("vmplayer -v 2>/dev/null", "r")) == NULL) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s", _("popen failed"));
+            goto cleanup;
+        }
+        if (!feof(fp) && fgets(str, 49, fp)) {
+            if ((tmp = STRSKIP(str, "VMware Player ")) == NULL) {
+                vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("vmplayer -v parsing error"));
+                goto cleanup;
+            }
+            if (virParseVersionString(tmp, &version) < 0) {
+                vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("version parsing error"));
+                goto cleanup;
+            }
+            driver->version = version;
+            ret = 0;
+        } else {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("vmplayer -v reading error"));
+        }
+    } else if (driver->type == TYPE_WORKSTATION) {
+        if ((fp = popen("vmware -v 2>/dev/null", "r")) == NULL) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s", _("popen failed"));
+            goto cleanup;
+        }
+        if (!feof(fp) && fgets(str, 49, fp)) {
+            if ((tmp = STRSKIP(str, "VMware Workstation ")) == NULL) {
+                vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("vmware -v parsing error"));
+                goto cleanup;
+            }
+            if (virParseVersionString(tmp, &version) < 0) {
+                vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("version parsing error"));
+                goto cleanup;
+            }
+            driver->version = version;
+            ret = 0;
+        } else {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("vmware -v reading error"));
+        }
+    }
+
+cleanup:
+    VIR_FORCE_FCLOSE(fp);
+    return ret;
+}
+
+int
+vmwareDomainConfigDisplay(vmwareDomainPtr pDomain, virDomainDefPtr def)
+{
+    int i = 0;
+
+    if (def->ngraphics == 0) {
+        pDomain->gui = true;
+        return 0;
+    } else {
+        pDomain->gui = false;
+        for (i = 0; i < def->ngraphics; i++) {
+            if (def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) {
+                pDomain->gui = true;
+                return 0;
+            }
+        }
+        return 0;
+    }
+}
+
+int
+vmwareParsePath(char *path, char **directory, char **filename)
+{
+    char *separator;
+
+    separator = strrchr(path, '/');
+
+    if (separator != NULL) {
+        *separator++ = '\0';
+
+        if (*separator == '\0') {
+            vmwareError(VIR_ERR_INTERNAL_ERROR,
+                        _("path '%s' doesn't reference a file"), path);
+            return -1;
+        }
+
+        if ((*directory = strdup(path)) == NULL)
+            goto no_memory;
+        if ((*filename = strdup(separator)) == NULL)
+            goto no_memory;
+
+    } else {
+        if ((*filename = strdup(separator)) == NULL)
+            goto no_memory;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+    return -1;
+}
+
+int
+vmwareConstructVmxPath(char *directoryName, char *name, char **vmxPath)
+{
+    if (directoryName != NULL) {
+        if (virAsprintf(vmxPath, "%s/%s.vmx", directoryName, name) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+    } else {
+        if (virAsprintf(vmxPath, "%s.vmx", name) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int
+vmwareVmxPath(virDomainDefPtr vmdef, char **vmxPath)
+{
+    virDomainDiskDefPtr disk = NULL;
+    char *directoryName = NULL;
+    char *fileName = NULL;
+    int ret = -1;
+    int i = 0;
+
+    /*
+     * Build VMX URL. Use the source of the first file-based harddisk
+     * to deduce the path for the VMX file. Don't just use the
+     * first disk, because it may be CDROM disk and ISO images are normaly not
+     * located in the virtual machine's directory. This approach
+     * isn't perfect but should work in the majority of cases.
+     */
+    if (vmdef->ndisks < 1) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("Domain XML doesn't contain any disks, "
+                      "cannot deduce datastore and path for VMX file"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < vmdef->ndisks; ++i) {
+        if (vmdef->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
+            vmdef->disks[i]->type == VIR_DOMAIN_DISK_TYPE_FILE) {
+            disk = vmdef->disks[i];
+            break;
+        }
+    }
+
+    if (disk == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("Domain XML doesn't contain any file-based harddisks, "
+                      "cannot deduce datastore and path for VMX file"));
+        goto cleanup;
+    }
+
+    if (disk->src == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("First file-based harddisk has no source, cannot "
+                      "deduce datastore and path for VMX file"));
+        goto cleanup;
+    }
+
+    if (vmwareParsePath(disk->src, &directoryName, &fileName) < 0) {
+        goto cleanup;
+    }
+
+    if (!virFileHasSuffix(fileName, ".vmdk")) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("Expecting source '%s' of first file-based harddisk "
+                      "to be a VMDK image"), disk->src);
+        goto cleanup;
+    }
+
+    if (vmwareConstructVmxPath(directoryName, vmdef->name, vmxPath) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    ret = 0;
+
+  cleanup:
+    VIR_FREE(directoryName);
+    VIR_FREE(fileName);
+    return ret;
+}
+
+int
+vmwareMoveFile(char *srcFile, char *dstFile)
+{
+    const char *cmdmv[] =
+        { "mv", PROGRAM_SENTINAL, PROGRAM_SENTINAL, NULL };
+
+    if (!virFileExists(srcFile)) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, _("file %s does not exist"),
+                    srcFile);
+        return -1;
+    }
+
+    if (STREQ(srcFile, dstFile))
+        return 0;
+
+    vmwareSetSentinal(cmdmv, srcFile);
+    vmwareSetSentinal(cmdmv, dstFile);
+    if (virRun(cmdmv, NULL) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("failed to move file to %s "), dstFile);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+vmwareMakePath(char *srcDir, char *srcName, char *srcExt, char **outpath)
+{
+    if (virAsprintf(outpath, "%s/%s.%s", srcDir, srcName, srcExt) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+    return 0;
+}
+
+char *
+esxCopyVMXFileName(const char *datastorePath, void *opaque ATTRIBUTE_UNUSED)
+{
+    char *path = strdup(datastorePath);
+
+    if (path == NULL) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return path;
+}
diff --git a/src/vmware/vmware_conf.h b/src/vmware/vmware_conf.h
new file mode 100644
index 0000000..a41c846
--- /dev/null
+++ b/src/vmware/vmware_conf.h
@@ -0,0 +1,82 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright 2010, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+/*---------------------------------------------------------------------------*/
+
+#ifndef VMWARE_CONF_H
+# define VMWARE_CONF_H
+
+# define VMRUN "vmrun"
+# define NOGUI "nogui"
+
+# include "internal.h"
+# include "domain_conf.h"
+# include "threads.h"
+
+# define VIR_FROM_THIS VIR_FROM_VMWARE
+# define PROGRAM_SENTINAL ((char *)0x1)
+
+# define vmwareError(code, ...) \
+         virReportErrorHelper(NULL, VIR_FROM_VMWARE, code, __FILE__, \
+                              __FUNCTION__, __LINE__, __VA_ARGS__)
+
+# define TYPE_PLAYER        0
+# define TYPE_WORKSTATION   1
+
+struct vmware_driver {
+    virMutex lock;
+    virCapsPtr caps;
+
+    virDomainObjList domains;
+    int version;
+    int type;
+    int nextvmid;
+};
+
+typedef struct _vmwareDomain {
+    char *vmxPath;
+    bool gui;
+
+} vmwareDomain, *vmwareDomainPtr;
+
+void vmwareFreeDriver(struct vmware_driver *driver);
+
+virCapsPtr vmwareCapsInit(void);
+
+int vmwareLoadDomains(struct vmware_driver *driver);
+
+void vmwareSetSentinal(const char **prog, const char *key);
+
+int vmwareExtractVersion(struct vmware_driver *driver);
+
+int vmwareDomainConfigDisplay(vmwareDomainPtr domain, virDomainDefPtr vmdef);
+
+int vmwareParsePath(char *path, char **directory, char **filename);
+
+int vmwareConstructVmxPath(char *directoryName, char *name,
+                           char **vmxPath);
+
+int vmwareVmxPath(virDomainDefPtr vmdef, char **vmxPath);
+
+int vmwareMoveFile(char *srcFile, char *dstFile);
+
+int vmwareMakePath(char *srcDir, char *srcName, char *srcExt,
+                   char **outpath);
+
+char * esxCopyVMXFileName(const char *datastorePath, void *opaque);
+
+#endif
diff --git a/src/vmware/vmware_driver.c b/src/vmware/vmware_driver.c
new file mode 100644
index 0000000..5615bef
--- /dev/null
+++ b/src/vmware/vmware_driver.c
@@ -0,0 +1,1372 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright 2010, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+/*---------------------------------------------------------------------------*/
+
+#include <config.h>
+
+#include <fcntl.h>
+
+#include "memory.h"
+#include "uuid.h"
+
+#include "../esx/esx_vmx.h"
+#include "vmware_conf.h"
+#include "vmware_driver.h"
+
+const char *vmw_types[] = { "player", "ws" };
+
+static void
+vmwareDriverLock(struct vmware_driver *driver)
+{
+    virMutexLock(&driver->lock);
+}
+
+static void
+vmwareDriverUnlock(struct vmware_driver *driver)
+{
+    virMutexUnlock(&driver->lock);
+}
+
+static void *
+vmwareDataAllocFunc(void)
+{
+    vmwareDomainPtr dom;
+
+    if (VIR_ALLOC(dom) < 0)
+        return NULL;
+
+    dom->vmxPath = NULL;
+    dom->gui = true;
+
+    return dom;
+}
+
+static void
+vmwareDataFreeFunc(void *data)
+{
+    vmwareDomainPtr dom = data;
+
+    VIR_FREE(dom->vmxPath);
+    VIR_FREE(dom);
+}
+
+static virDrvOpenStatus
+vmwareOpen(virConnectPtr conn,
+           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+           int flags ATTRIBUTE_UNUSED)
+{
+    struct vmware_driver *driver;
+
+    if (conn->uri == NULL) {
+        /* @TODO accept */
+        return VIR_DRV_OPEN_DECLINED;
+    } else {
+        if (conn->uri->scheme == NULL ||
+            (STRNEQ(conn->uri->scheme, "vmwareplayer") &&
+             STRNEQ(conn->uri->scheme, "vmwarews")))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* If server name is given, its for remote driver */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* If path isn't /session, then they typoed, so tell them correct path */
+        if (conn->uri->path == NULL || STRNEQ(conn->uri->path, "/session")) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR,
+                        ("unexpected VMware URI path '%s', try vmwareplayer:///session or vmwarews:///session"),
+                        conn->uri->path);
+            return VIR_DRV_OPEN_ERROR;
+        }
+    }
+
+    /* We now know the URI is definitely for this driver, so beyond
+     * here, don't return DECLINED, always use ERROR */
+
+    if (VIR_ALLOC(driver) < 0) {
+        virReportOOMError();
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    if (virMutexInit(&driver->lock) < 0)
+        goto cleanup;
+
+    driver->type = STRNEQ(conn->uri->scheme, "vmwareplayer") ?
+      TYPE_WORKSTATION : TYPE_PLAYER;
+
+    if (virDomainObjListInit(&driver->domains) < 0)
+        goto cleanup;
+
+    if (!(driver->caps = vmwareCapsInit()))
+        goto cleanup;
+
+    driver->caps->privateDataAllocFunc = vmwareDataAllocFunc;
+    driver->caps->privateDataFreeFunc = vmwareDataFreeFunc;
+
+    driver->nextvmid = 1;
+    if (vmwareLoadDomains(driver) < 0)
+        goto cleanup;
+
+    if (vmwareExtractVersion(driver) < 0)
+        goto cleanup;
+
+    conn->privateData = driver;
+
+    return VIR_DRV_OPEN_SUCCESS;
+
+  cleanup:
+    vmwareFreeDriver(driver);
+    return VIR_DRV_OPEN_ERROR;
+};
+
+static int
+vmwareClose(virConnectPtr conn)
+{
+    struct vmware_driver *driver = conn->privateData;
+
+    vmwareFreeDriver(driver);
+
+    conn->privateData = NULL;
+
+    return 0;
+}
+
+static const char *
+vmwareGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    struct vmware_driver *driver = conn->privateData;
+    int type;
+
+    vmwareDriverLock(driver);
+    type = driver->type;
+    vmwareDriverUnlock(driver);
+    return type == TYPE_PLAYER ? "vmware player" : "vmware workstation";
+}
+
+static int
+vmwareGetVersion(virConnectPtr conn, unsigned long *version)
+{
+    struct vmware_driver *driver = conn->privateData;
+
+    vmwareDriverLock(driver);
+    *version = driver->version;
+    vmwareDriverUnlock(driver);
+    return 0;
+}
+
+static int
+vmwareStartVM(struct vmware_driver *driver, virDomainObjPtr vm)
+{
+    const char *cmd[] = {
+        VMRUN, "-T", PROGRAM_SENTINAL, "start",
+        PROGRAM_SENTINAL, PROGRAM_SENTINAL, NULL
+    };
+
+    if (vm->state != VIR_DOMAIN_SHUTOFF) {
+        vmwareError(VIR_ERR_OPERATION_DENIED, "%s",
+                    _("domain is not in shutoff state"));
+        return -1;
+    }
+
+    vmwareSetSentinal(cmd, vmw_types[driver->type]);
+    vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
+    if (!((vmwareDomainPtr) vm->privateData)->gui)
+        vmwareSetSentinal(cmd, NOGUI);
+    else
+        vmwareSetSentinal(cmd, NULL);
+
+    if (virRun(cmd, NULL) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VMRUN);
+        return -1;
+    }
+
+    vm->def->id = driver->nextvmid++;
+    vm->state = VIR_DOMAIN_RUNNING;
+
+    return 0;
+}
+
+static int
+vmwareStopVM(struct vmware_driver *driver, virDomainObjPtr vm)
+{
+    const char *cmd[] = {
+        VMRUN, "-T", PROGRAM_SENTINAL, "stop",
+        PROGRAM_SENTINAL, "soft", NULL
+    };
+
+    if (vm->state != VIR_DOMAIN_RUNNING) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("domain is not in running state"));
+        return -1;
+    }
+
+    vmwareSetSentinal(cmd, vmw_types[driver->type]);
+    vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
+
+    if (virRun(cmd, NULL) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VMRUN);
+        return -1;
+    }
+
+    vm->def->id = -1;
+    vm->state = VIR_DOMAIN_SHUTOFF;
+
+    return 0;
+}
+
+static virDomainPtr
+vmwareDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainDefPtr vmdef = NULL;
+    virDomainObjPtr vm = NULL;
+    virDomainPtr dom = NULL;
+    char *vmx = NULL;
+    char *directoryName = NULL;
+    char *fileName = NULL;
+    char *vmxPath = NULL;
+    vmwareDomainPtr pDomain = NULL;
+    esxVMX_Context ctx;
+
+    ctx.formatFileName = esxCopyVMXFileName;
+
+    vmwareDriverLock(driver);
+    if ((vmdef = virDomainDefParseString(driver->caps, xml,
+                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
+        goto cleanup;
+
+    vm = virDomainFindByName(&driver->domains, vmdef->name);
+    if (vm) {
+        vmwareError(VIR_ERR_OPERATION_FAILED,
+                    _("Already an VMWARE VM active with the id '%s'"),
+                    vmdef->name);
+        goto cleanup;
+    }
+    
+    /* generate vmx file */
+    vmx = esxVMX_FormatConfig(&ctx, driver->caps, vmdef,
+                              esxVI_ProductVersion_ESX4x);
+    if (vmx == NULL) {
+        vmwareError(VIR_ERR_OPERATION_FAILED, _("cannot create xml"));
+        goto cleanup;
+    }
+
+    if (vmwareVmxPath(vmdef, &vmxPath) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("retrieve vmx path.. failed"));
+        goto cleanup;
+    }
+
+    /* create vmx file */
+    if (virFileWriteStr(vmxPath, vmx) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to write vmx file '%s'"), vmxPath);
+        goto cleanup;
+    }
+
+    /* assign def */
+    if (!(vm = virDomainAssignDef(driver->caps,
+                                  &driver->domains, vmdef, false)))
+        goto cleanup;
+
+    pDomain = vm->privateData;
+    if ((pDomain->vmxPath = strdup(vmxPath)) == NULL) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    vmwareDomainConfigDisplay(pDomain, vmdef);
+
+    vmdef = NULL;
+    vm->persistent = 1;
+
+    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+    if (dom)
+        dom->id = -1;
+
+  cleanup:
+    virDomainDefFree(vmdef);
+    VIR_FREE(vmx);
+    VIR_FREE(directoryName);
+    VIR_FREE(fileName);
+    VIR_FREE(vmxPath);
+    if (vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return dom;
+}
+
+static int
+vmwareDomainShutdown(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    if (vmwareStopVM(driver, vm) < 0)
+        goto cleanup;
+
+    if (!vm->persistent) {
+        virDomainRemoveInactive(&driver->domains, vm);
+        vm = NULL;
+    }
+
+    ret = 0;
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return ret;
+}
+
+static int
+vmwareDomainSuspend(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+
+    virDomainObjPtr vm;
+    const char *cmd[] = {
+      VMRUN, "-T", PROGRAM_SENTINAL, "pause",
+      PROGRAM_SENTINAL, NULL
+    };
+    int ret = -1;
+
+    if (driver->type == TYPE_PLAYER) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("vmplayer does not support libvirt suspend/resume"
+                      " (vmware pause/unpause) operation "));
+        return ret;
+    }
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    vmwareSetSentinal(cmd, vmw_types[driver->type]);
+    vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
+    if (vm->state != VIR_DOMAIN_RUNNING) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("domain is not in running state"));
+        goto cleanup;
+    }
+
+    if (virRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    vm->state = VIR_DOMAIN_PAUSED;
+    ret = 0;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
+vmwareDomainResume(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+
+    virDomainObjPtr vm;
+    const char *cmd[] = {
+        VMRUN, "-T", PROGRAM_SENTINAL, "unpause", PROGRAM_SENTINAL,
+        NULL
+    };
+    int ret = -1;
+
+    if (driver->type == TYPE_PLAYER) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("vmplayer does not support libvirt suspend/resume"
+                      "(vmware pause/unpause) operation "));
+        return ret;
+    }
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    vmwareDriverLock(driver);
+    vmwareSetSentinal(cmd, vmw_types[driver->type]);
+    vmwareDriverUnlock(driver);
+    vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
+    if (vm->state != VIR_DOMAIN_PAUSED) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("domain is not in suspend state"));
+        goto cleanup;
+    }
+
+    if (virRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    vm->state = VIR_DOMAIN_RUNNING;
+    ret = 0;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
+vmwareDomainReboot(virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+
+    virDomainObjPtr vm;
+    const char *cmd[] = {
+        VMRUN, "-T", PROGRAM_SENTINAL,
+        "reset", PROGRAM_SENTINAL, NULL
+    };
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    vmwareDriverLock(driver);
+    vmwareSetSentinal(cmd, vmw_types[driver->type]);
+    vmwareDriverUnlock(driver);
+    vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath);
+
+
+    if (vm->state != VIR_DOMAIN_RUNNING) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("domain is not in running state"));
+        goto cleanup;
+    }
+
+    if (virRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    vmwareDriverLock(driver);
+    vm->def->id = driver->nextvmid++;
+    vmwareDriverUnlock(driver);
+    vm->state = VIR_DOMAIN_RUNNING;
+    ret = 0;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
+vmwareDomainSave(virDomainPtr dom, const char *path)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    const char *cmdsuspend[] = {
+        VMRUN, "-T", PROGRAM_SENTINAL,
+        "suspend", PROGRAM_SENTINAL, NULL
+    };
+    int ret = -1;
+    char *fDirectoryName = NULL;
+    char *fFileName = NULL;
+    char *tDirectoryName = NULL;
+    char *tFileName = NULL;
+    char *copyPath = NULL;
+    char *copyvmxPath = NULL;
+    char *fvmss = NULL;
+    char *tvmss = NULL;
+    char *fvmem = NULL;
+    char *tvmem = NULL;
+    char *fvmx = NULL;
+    char *tvmx = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    /* vmware suspend */
+    vmwareSetSentinal(cmdsuspend, vmw_types[driver->type]);
+    vmwareSetSentinal(cmdsuspend,
+                      ((vmwareDomainPtr) vm->privateData)->vmxPath);
+
+    if (vm->state != VIR_DOMAIN_RUNNING) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("domain is not in running state"));
+        goto cleanup;
+    }
+
+    if (virRun(cmdsuspend, NULL) < 0)
+        goto cleanup;
+
+    /* create files path */
+    copyvmxPath = strdup(((vmwareDomainPtr) vm->privateData)->vmxPath);
+    if(copyvmxPath == NULL) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if((copyPath = strdup(path)) == NULL) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (vmwareParsePath(copyvmxPath, &fDirectoryName, &fFileName) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to parse vmxPath"));
+        goto cleanup;
+    }
+    if (vmwareParsePath(copyPath, &tDirectoryName, &tFileName) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to parse path"));
+        goto cleanup;
+    }
+
+    /* dir */
+    if (virFileMakePath(tDirectoryName) != 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s", _("make path error"));
+        goto cleanup;
+    }
+
+    vmwareMakePath(fDirectoryName, vm->def->name, (char *) "vmss", &fvmss);
+    vmwareMakePath(tDirectoryName, vm->def->name, (char *) "vmss", &tvmss);
+    vmwareMakePath(fDirectoryName, vm->def->name, (char *) "vmem", &fvmem);
+    vmwareMakePath(tDirectoryName, vm->def->name, (char *) "vmem", &tvmem);
+    vmwareMakePath(fDirectoryName, vm->def->name, (char *) "vmx", &fvmx);
+    vmwareMakePath(tDirectoryName, vm->def->name, (char *) "vmx", &tvmx);
+
+    /* create linker file */
+    int fd;
+
+    if ((fd =
+         open(path, O_CREAT | O_WRONLY | O_TRUNC,
+              S_IRUSR | S_IWUSR)) == -1) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to open linker file '%s'"), path);
+        goto cleanup;
+    }
+    if (safewrite
+        (fd, ((vmwareDomainPtr) vm->privateData)->vmxPath,
+         strlen(((vmwareDomainPtr) vm->privateData)->vmxPath)) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to create linker file"));
+        goto cleanup;
+    }
+
+    /* we want to let saved VM inside default directory */
+    if (STREQ(fDirectoryName, tDirectoryName))
+        goto end;
+
+    /* move {vmx,vmss,vmem} files */
+    if ((vmwareMoveFile(fvmss, tvmss) < 0)
+        || (vmwareMoveFile(fvmem, tvmem) < 0)
+        || (vmwareMoveFile(fvmx, tvmx) < 0)
+        ) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to move file"));
+        goto cleanup;
+    }
+
+  end:
+    vm->def->id = -1;
+    vm->state = VIR_DOMAIN_SHUTOFF;
+    ret = 0;
+
+  cleanup:
+    VIR_FREE(fDirectoryName);
+    VIR_FREE(fFileName);
+    VIR_FREE(tDirectoryName);
+    VIR_FREE(tFileName);
+    VIR_FREE(copyPath);
+    VIR_FREE(copyvmxPath);
+
+    VIR_FREE(fvmss);
+    VIR_FREE(tvmss);
+    VIR_FREE(fvmem);
+    VIR_FREE(tvmem);
+    VIR_FREE(fvmx);
+    VIR_FREE(tvmx);
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
+vmwareDomainRestore(virConnectPtr conn, const char *path)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainDefPtr vmdef = NULL;
+    virDomainPtr dom = NULL;
+    virDomainObjPtr vm = NULL;
+    int ret = -1;
+    char *vmxPath = NULL;
+    char *copypath = NULL;
+    char *copyvmxPath = NULL;
+    char *tDirectoryName = NULL;
+    char *tFileName = NULL;
+    char *fDirectoryName = NULL;
+    char *fFileName = NULL;
+    char *vmx = NULL;
+    char *xml = NULL;
+    char *sep = NULL;
+    char *baseVmss;
+    char *fvmss = NULL;
+    char *tvmss = NULL;
+    char *fvmem = NULL;
+    char *tvmem = NULL;
+    char *fvmx = NULL;
+    char *tvmx = NULL;
+    esxVMX_Context ctx;
+
+    ctx.parseFileName = esxCopyVMXFileName;
+
+    if (!virFileExists(path)) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("file %s does not exist"), path);
+        goto cleanup;
+    }
+    if (virFileHasSuffix(path, ".vmx")) {       //we want to restore a vm saved in its default directory
+        if((tvmx = strdup(path)) == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if((copypath = strdup(path)) == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (vmwareParsePath(copypath, &fDirectoryName, &fFileName) < 0) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("failed to parse path"));
+            goto cleanup;
+        }
+        sep = strrchr(fFileName, '.');
+        if (sep != NULL)
+            *sep = '\0';
+        vmwareMakePath(fFileName, fFileName, (char *) "vmss", &fvmss);
+        baseVmss = basename(fvmss);
+    } else {                    //we want to restore a vm saved elsewhere
+        if (virFileReadAll(path, 1024, &vmxPath) < 0) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("failed to read vmxPath"));
+            goto cleanup;
+        }
+
+        if (!virFileHasSuffix(vmxPath, ".vmx")) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR,
+                        _("%s is not a .vmx file"), vmxPath);
+            goto cleanup;
+        }
+
+        /* move files */
+        if((copyvmxPath = strdup(vmxPath)) == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if((copypath = strdup(path)) == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (vmwareParsePath(copypath, &fDirectoryName, &fFileName) < 0) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("failed to parse path"));
+            goto cleanup;
+        }
+        if (vmwareParsePath(copyvmxPath, &tDirectoryName, &tFileName) < 0) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("failed to parse vmxPath"));
+            goto cleanup;
+        }
+
+        sep = strrchr(tFileName, '.');
+        if (sep != NULL)
+            *sep = '\0';
+
+        if (virFileMakePath(tDirectoryName) != 0) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("make path error"));
+            goto cleanup;
+        }
+
+        vmwareMakePath(fDirectoryName, tFileName, (char *) "vmss", &fvmss);
+        vmwareMakePath(tDirectoryName, tFileName, (char *) "vmss", &tvmss);
+        vmwareMakePath(fDirectoryName, tFileName, (char *) "vmem", &fvmem);
+        vmwareMakePath(tDirectoryName, tFileName, (char *) "vmem", &tvmem);
+        vmwareMakePath(fDirectoryName, tFileName, (char *) "vmx", &fvmx);
+        vmwareMakePath(tDirectoryName, tFileName, (char *) "vmx", &tvmx);
+
+        if ((vmwareMoveFile(fvmss, tvmss) < 0)
+            || (vmwareMoveFile(fvmem, tvmem) < 0)
+            || (vmwareMoveFile(fvmx, tvmx) < 0)
+            ) {
+            vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("failed to move files"));
+            goto cleanup;
+        }
+
+        baseVmss = basename(tvmss);
+    }
+
+    if (virFileReadAll(tvmx, 10000, &vmx) == -1) {
+        perror("error reading vmx file");
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("failed to read vmx file %s"), tvmx);
+        goto cleanup;
+    }
+
+    vmwareDriverLock(driver);
+    if ((vmdef =
+         esxVMX_ParseConfig(&ctx, driver->caps, vmx,
+                            esxVI_ProductVersion_ESX4x)) == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("failed to parse config file"));
+        goto cleanup;
+    }
+    vmwareDriverUnlock(driver);
+
+    xml = virDomainDefFormat(vmdef, VIR_DOMAIN_XML_SECURE);
+
+    if ((dom = vmwareDomainDefineXML(conn, xml)) == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to define domain"));
+        goto cleanup;
+    }
+
+    /* esxVMX_ParseConfig don't care about vmx checkpoint property for now, so we add it here
+     * TODO
+     */
+    FILE *pFile = NULL;
+
+    if ((pFile = fopen(tvmx, "a+")) == NULL) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to reopen vmx file"));
+        goto cleanup;
+    }
+
+    fputs("checkpoint.vmState = \"", pFile);
+    fputs(baseVmss, pFile);
+    fputs("\"", pFile);
+    fclose(pFile);
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByName(&driver->domains, dom->name);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching id"));
+        goto cleanup;
+    }
+
+    /* start */
+    if (vmwareStartVM(driver, vm) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR, "%s",
+                    _("failed to create domain"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+  cleanup:
+    VIR_FREE(vmxPath);
+    VIR_FREE(copypath);
+    VIR_FREE(copyvmxPath);
+    VIR_FREE(tDirectoryName);
+    VIR_FREE(tFileName);
+    VIR_FREE(fDirectoryName);
+    VIR_FREE(fFileName);
+    VIR_FREE(vmx);
+    VIR_FREE(xml);
+
+    VIR_FREE(fvmss);
+    VIR_FREE(tvmss);
+    VIR_FREE(fvmem);
+    VIR_FREE(tvmem);
+    VIR_FREE(fvmx);
+    VIR_FREE(tvmx);
+
+    if (dom)
+        virUnrefDomain(dom);
+    if (vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return ret;
+}
+
+static virDomainPtr
+vmwareDomainCreateXML(virConnectPtr conn, const char *xml,
+                      unsigned int flags ATTRIBUTE_UNUSED)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainDefPtr vmdef = NULL;
+    virDomainObjPtr vm = NULL;
+    virDomainPtr dom = NULL;
+    char *vmx = NULL;
+    char *vmxPath = NULL;
+    vmwareDomainPtr pDomain = NULL;
+    esxVMX_Context ctx;
+
+    ctx.formatFileName = esxCopyVMXFileName;
+
+    vmwareDriverLock(driver);
+
+    if ((vmdef = virDomainDefParseString(driver->caps, xml,
+                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
+        goto cleanup;
+
+    vm = virDomainFindByName(&driver->domains, vmdef->name);
+    if (vm) {
+        vmwareError(VIR_ERR_OPERATION_FAILED,
+                    _("Already an VMWARE VM active with the id '%s'"),
+                    vmdef->name);
+        goto cleanup;
+    }
+
+    /* generate vmx file */
+    vmx = esxVMX_FormatConfig(&ctx, driver->caps, vmdef,
+                              esxVI_ProductVersion_ESX4x);
+    if (vmx == NULL) {
+        vmwareError(VIR_ERR_OPERATION_FAILED, _("cannot create xml"));
+        goto cleanup;
+    }
+
+    if (vmwareVmxPath(vmdef, &vmxPath) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("retrieve vmx path.. failed"));
+        goto cleanup;
+    }
+
+    /* create vmx file */
+    if (virFileWriteStr(vmxPath, vmx) < 0) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    _("Failed to write vmx file '%s'"), vmxPath);
+        goto cleanup;
+    }
+
+    /* assign def */
+    if (!(vm = virDomainAssignDef(driver->caps,
+                                  &driver->domains, vmdef, false)))
+        goto cleanup;
+
+    pDomain = vm->privateData;
+    pDomain->vmxPath = strdup(vmxPath);
+
+    vmwareDomainConfigDisplay(pDomain, vmdef);
+    vmdef = NULL;
+
+    if (vmwareStartVM(driver, vm) < 0) {
+        virDomainRemoveInactive(&driver->domains, vm);
+        vm = NULL;
+        goto cleanup;
+    }
+
+    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+    if (dom)
+        dom->id = vm->def->id;
+
+cleanup:
+    virDomainDefFree(vmdef);
+    VIR_FREE(vmx);
+    VIR_FREE(vmxPath);
+    if(vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return dom;
+}
+
+static int
+vmwareDomainCreateWithFlags(virDomainPtr dom,
+                            unsigned int flags ATTRIBUTE_UNUSED)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        vmwareError(VIR_ERR_NO_DOMAIN,
+                    _("No domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (virDomainObjIsActive(vm)) {
+        vmwareError(VIR_ERR_OPERATION_INVALID,
+                    "%s", _("Domain is already running"));
+        goto cleanup;
+    }
+
+    ret = vmwareStartVM(driver, vm);
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return ret;
+}
+
+static int
+vmwareDomainCreate(virDomainPtr dom)
+{
+    return vmwareDomainCreateWithFlags(dom, 0);
+}
+
+static int
+vmwareDomainUndefine(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+        virUUIDFormat(dom->uuid, uuidstr);
+        vmwareError(VIR_ERR_NO_DOMAIN,
+                    _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (virDomainObjIsActive(vm)) {
+        vmwareError(VIR_ERR_OPERATION_INVALID,
+                    "%s", _("cannot delete active domain"));
+        goto cleanup;
+    }
+
+    if (!vm->persistent) {
+        vmwareError(VIR_ERR_INTERNAL_ERROR,
+                    "%s", _("cannot undefine transient domain"));
+        goto cleanup;
+    }
+
+    virDomainRemoveInactive(&driver->domains, vm);
+    vm = NULL;
+    ret = 0;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    vmwareDriverUnlock(driver);
+    return ret;
+}
+
+static virDomainPtr
+vmwareDomainLookupByID(virConnectPtr conn, int id)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainObjPtr vm;
+    virDomainPtr dom = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByID(&driver->domains, id);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+
+    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+    if (dom)
+        dom->id = vm->def->id;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return dom;
+}
+
+static char *
+vmwareGetOSType(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    char *ret = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+
+    if (!(ret = strdup(vm->def->os.type)))
+        virReportOOMError();
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+
+static virDomainPtr
+vmwareDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainObjPtr vm;
+    virDomainPtr dom = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+
+    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+    if (dom)
+        dom->id = vm->def->id;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return dom;
+}
+
+static virDomainPtr
+vmwareDomainLookupByName(virConnectPtr conn, const char *name)
+{
+    struct vmware_driver *driver = conn->privateData;
+    virDomainObjPtr vm;
+    virDomainPtr dom = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByName(&driver->domains, name);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+
+    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+    if (dom)
+        dom->id = vm->def->id;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return dom;
+}
+
+static int
+vmwareDomainIsActive(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr obj;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+    if (!obj) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+    ret = virDomainObjIsActive(obj);
+
+  cleanup:
+    if (obj)
+        virDomainObjUnlock(obj);
+    return ret;
+}
+
+
+static int
+vmwareDomainIsPersistent(virDomainPtr dom)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr obj;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+    if (!obj) {
+        vmwareError(VIR_ERR_NO_DOMAIN, NULL);
+        goto cleanup;
+    }
+    ret = obj->persistent;
+
+  cleanup:
+    if (obj)
+        virDomainObjUnlock(obj);
+    return ret;
+}
+
+
+static char *
+vmwareDomainDumpXML(virDomainPtr dom, int flags)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    char *ret = NULL;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virDomainDefFormat(vm->def, flags);
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
+vmwareNumDefinedDomains(virConnectPtr conn)
+{
+    struct vmware_driver *driver = conn->privateData;
+    int n;
+
+    vmwareDriverLock(driver);
+    n = virDomainObjListNumOfDomains(&driver->domains, 0);
+    vmwareDriverUnlock(driver);
+
+    return n;
+}
+
+static int
+vmwareNumDomains(virConnectPtr conn)
+{
+    struct vmware_driver *driver = conn->privateData;
+    int n;
+
+    vmwareDriverLock(driver);
+    n = virDomainObjListNumOfDomains(&driver->domains, 1);
+    vmwareDriverUnlock(driver);
+
+    return n;
+}
+
+
+static int
+vmwareListDomains(virConnectPtr conn, int *ids, int nids)
+{
+    struct vmware_driver *driver = conn->privateData;
+    int n;
+
+    vmwareDriverLock(driver);
+    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
+    vmwareDriverUnlock(driver);
+
+    return n;
+}
+
+static int
+vmwareListDefinedDomains(virConnectPtr conn,
+                         char **const names, int nnames)
+{
+    struct vmware_driver *driver = conn->privateData;
+    int n;
+
+    vmwareDriverLock(driver);
+    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
+    vmwareDriverUnlock(driver);
+    return n;
+}
+
+static int
+vmwareDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
+{
+    struct vmware_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    vmwareDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    vmwareDriverUnlock(driver);
+
+    if (!vm) {
+        vmwareError(VIR_ERR_INVALID_DOMAIN, "%s",
+                    _("no domain with matching uuid"));
+        goto cleanup;
+    }
+
+    info->state = vm->state;
+    info->cpuTime = 0;
+    info->maxMem = vm->def->mem.max_balloon;
+    info->memory = vm->def->mem.cur_balloon;
+    info->nrVirtCpu = vm->def->vcpus;
+    ret = 0;
+
+  cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static virDriver vmwareDriver = {
+    VIR_DRV_VMWARE,
+    "VMWARE",
+    vmwareOpen,                 /* open */
+    vmwareClose,                /* close */
+    NULL,                       /* supports_feature */
+    vmwareGetType,              /* type */
+    vmwareGetVersion,           /* version */
+    NULL,                       /* libvirtVersion (impl. in libvirt.c) */
+    NULL,                       /* getHostname */
+    NULL,                       /* getMaxVcpus */
+    NULL,                       /* nodeGetInfo */
+    NULL,                       /* getCapabilities */
+    vmwareListDomains,          /* listDomains */
+    vmwareNumDomains,           /* numOfDomains */
+    vmwareDomainCreateXML,      /* domainCreateXML */
+    vmwareDomainLookupByID,     /* domainLookupByID */
+    vmwareDomainLookupByUUID,   /* domainLookupByUUID */
+    vmwareDomainLookupByName,   /* domainLookupByName */
+    vmwareDomainSuspend,        /* domainSuspend */
+    vmwareDomainResume,         /* domainResume */
+    vmwareDomainShutdown,       /* domainShutdown */
+    vmwareDomainReboot,         /* domainReboot */
+    vmwareDomainShutdown,        /* domainDestroy */
+    vmwareGetOSType,            /* domainGetOSType */
+    NULL,                       /* domainGetMaxMemory */
+    NULL,                       /* domainSetMaxMemory */
+    NULL,                       /* domainSetMemory */
+    vmwareDomainGetInfo,        /* domainGetInfo */
+    vmwareDomainSave,           /* domainSave */
+    vmwareDomainRestore,        /* domainRestore */
+    NULL,                       /* domainCoreDump */
+    NULL,                       /* domainSetVcpus */
+    NULL,                       /* domainSetVcpusFlags */
+    NULL,                       /* domainGetVcpusFlags */
+    NULL,                       /* domainPinVcpu */
+    NULL,                       /* domainGetVcpus */
+    NULL,                       /* domainGetMaxVcpus */
+    NULL,                       /* domainGetSecurityLabel */
+    NULL,                       /* nodeGetSecurityModel */
+    vmwareDomainDumpXML,        /* domainDumpXML */
+    NULL,                       /* domainXmlFromNative */
+    NULL,                       /* domainXmlToNative */
+    vmwareListDefinedDomains,   /* listDefinedDomains */
+    vmwareNumDefinedDomains,    /* numOfDefinedDomains */
+    vmwareDomainCreate,         /* domainCreate */
+    vmwareDomainCreateWithFlags,/* domainCreateWithFlags */
+    vmwareDomainDefineXML,      /* domainDefineXML */
+    vmwareDomainUndefine,       /* domainUndefine */
+    NULL,                       /* domainAttachDevice */
+    NULL,                       /* domainAttachDeviceFlags */
+    NULL,                       /* domainDetachDevice */
+    NULL,                       /* domainDetachDeviceFlags */
+    NULL,                       /* domainUpdateDeviceFlags */
+    NULL,                       /* domainGetAutostart */
+    NULL,                       /* domainSetAutostart */
+    NULL,                       /* domainGetSchedulerType */
+    NULL,                       /* domainGetSchedulerParameters */
+    NULL,                       /* domainSetSchedulerParameters */
+    NULL,                       /* domainMigratePrepare */
+    NULL,                       /* domainMigratePerform */
+    NULL,                       /* domainMigrateFinish */
+    NULL,                       /* domainBlockStats */
+    NULL,                       /* domainInterfaceStats */
+    NULL,                       /* domainMemoryStats */
+    NULL,                       /* domainBlockPeek */
+    NULL,                       /* domainMemoryPeek */
+    NULL,                       /* domainGetBlockInfo */
+    NULL,                       /* nodeGetCellsFreeMemory */
+    NULL,                       /* getFreeMemory */
+    NULL,                       /* domainEventRegister */
+    NULL,                       /* domainEventDeregister */
+    NULL,                       /* domainMigratePrepare2 */
+    NULL,                       /* domainMigrateFinish2 */
+    NULL,                       /* nodeDeviceDettach */
+    NULL,                       /* nodeDeviceReAttach */
+    NULL,                       /* nodeDeviceReset */
+    NULL,                       /* domainMigratePrepareTunnel */
+    NULL,                       /* IsEncrypted */
+    NULL,                       /* IsSecure */
+    vmwareDomainIsActive,       /* DomainIsActive */
+    vmwareDomainIsPersistent,   /* DomainIsPersistent */
+    NULL,                       /* domainIsUpdated */
+    NULL,                       /* cpuCompare */
+    NULL,                       /* cpuBaseline */
+    NULL,                       /* domainGetJobInfo */
+    NULL,                       /* domainAbortJob */
+    NULL,                       /* domainMigrateSetMaxDowntime */
+    NULL,                       /* domainEventRegisterAny */
+    NULL,                       /* domainEventDeregisterAny */
+    NULL,                       /* domainManagedSave */
+    NULL,                       /* domainHasManagedSaveImage */
+    NULL,                       /* domainManagedSaveRemove */
+    NULL,                       /* domainSnapshotCreateXML */
+    NULL,                       /* domainSnapshotDumpXML */
+    NULL,                       /* domainSnapshotNum */
+    NULL,                       /* domainSnapshotListNames */
+    NULL,                       /* domainSnapshotLookupByName */
+    NULL,                       /* domainHasCurrentSnapshot */
+    NULL,                       /* domainSnapshotCurrent */
+    NULL,                       /* domainRevertToSnapshot */
+    NULL,                       /* domainSnapshotDelete */
+    NULL,                       /* qemuDomainMonitorCommand */
+    NULL,                       /* domainSetMemoryParameters */
+    NULL,                       /* domainGetMemoryParameters */
+    NULL,                       /* domainOpenConsole */
+};
+
+int
+vmwareRegister(void)
+{
+    if (virRegisterDriver(&vmwareDriver) < 0)
+        return -1;
+    return 0;
+}
diff --git a/src/vmware/vmware_driver.h b/src/vmware/vmware_driver.h
new file mode 100644
index 0000000..71186de
--- /dev/null
+++ b/src/vmware/vmware_driver.h
@@ -0,0 +1,25 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright 2010, diateam (www.diateam.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ */
+/*---------------------------------------------------------------------------*/
+
+#ifndef VMWARE_DRIVER_H
+# define VMWARE_DRIVER_H
+
+int vmwareRegister(void);
+
+#endif
-- 
1.7.0.4




More information about the libvir-list mailing list