/*---------------------------------------------------------------------------*/ /* * Copyright (C) 2011-2012 Red Hat, Inc. * 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, see * . */ /*---------------------------------------------------------------------------*/ #include #include #include "internal.h" #include "virerror.h" #include "datatypes.h" #include "virfile.h" #include "viralloc.h" #include "virutil.h" #include "viruuid.h" #include "vircommand.h" #include "vmx.h" #include "vmware_conf.h" #include "vmware_driver.h" static 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, unsigned int flags) { struct vmware_driver *driver; char * vmrun = NULL; virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); 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")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unexpected VMware URI path '%s', try vmwareplayer:///session or vmwarews:///session"), NULLSTR(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 */ vmrun = virFindFileInPath(VMRUN); if (vmrun == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s utility is missing"), VMRUN); return VIR_DRV_OPEN_ERROR; } else { VIR_FREE(vmrun); } 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 (!(driver->domains = virDomainObjListNew())) goto cleanup; if (!(driver->caps = vmwareCapsInit())) goto cleanup; driver->caps->privateDataAllocFunc = vmwareDataAllocFunc; driver->caps->privateDataFreeFunc = vmwareDataFreeFunc; 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) { return "VMware"; } 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 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, virDomainShutoffReason reason) { const char *cmd[] = { VMRUN, "-T", PROGRAM_SENTINAL, "stop", PROGRAM_SENTINAL, "soft", NULL }; vmwareSetSentinal(cmd, vmw_types[driver->type]); vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath); if (virRun(cmd, NULL) < 0) { return -1; } vm->def->id = -1; virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason); return 0; } static int vmwareStartVM(struct vmware_driver *driver, virDomainObjPtr vm) { const char *cmd[] = { VMRUN, "-T", PROGRAM_SENTINAL, "start", PROGRAM_SENTINAL, PROGRAM_SENTINAL, NULL }; const char *vmxPath = ((vmwareDomainPtr) vm->privateData)->vmxPath; if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) { virReportError(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) vmwareSetSentinal(cmd, NOGUI); else vmwareSetSentinal(cmd, NULL); if (virRun(cmd, NULL) < 0) { return -1; } if ((vm->def->id = vmwareExtractPid(vmxPath)) < 0) { vmwareStopVM(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); return -1; } virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED); 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; virVMXContext ctx; ctx.formatFileName = vmwareCopyVMXFileName; vmwareDriverLock(driver); if ((vmdef = virDomainDefParseString(driver->caps, xml, 1 << VIR_DOMAIN_VIRT_VMWARE, VIR_DOMAIN_XML_INACTIVE)) == NULL) goto cleanup; /* generate vmx file */ vmx = virVMXFormatConfig(&ctx, driver->caps, vmdef, 7); if (vmx == NULL) goto cleanup; if (vmwareVmxPath(vmdef, &vmxPath) < 0) goto cleanup; /* create vmx file */ if (virFileWriteStr(vmxPath, vmx, S_IRUSR|S_IWUSR) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to write vmx file '%s'"), vmxPath); goto cleanup; } /* assign def */ if (!(vm = virDomainObjListAdd(driver->domains, driver->caps, vmdef, VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) 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) virObjectUnlock(vm); vmwareDriverUnlock(driver); return dom; } static int vmwareDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; virCheckFlags(0, -1); vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in running state")); goto cleanup; } if (vmwareStopVM(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN) < 0) goto cleanup; if (!vm->persistent) { virDomainObjListRemove(driver->domains, vm); vm = NULL; } ret = 0; cleanup: if (vm) virObjectUnlock(vm); vmwareDriverUnlock(driver); return ret; } static int vmwareDomainShutdown(virDomainPtr dom) { return vmwareDomainShutdownFlags(dom, 0); } 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) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("vmplayer does not support libvirt suspend/resume" " (vmware pause/unpause) operation ")); return ret; } vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } vmwareSetSentinal(cmd, vmw_types[driver->type]); vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath); if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in running state")); goto cleanup; } if (virRun(cmd, NULL) < 0) goto cleanup; virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER); ret = 0; cleanup: if (vm) virObjectUnlock(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) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("vmplayer does not support libvirt suspend/resume " "(vmware pause/unpause) operation ")); return ret; } vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } vmwareSetSentinal(cmd, vmw_types[driver->type]); vmwareSetSentinal(cmd, ((vmwareDomainPtr) vm->privateData)->vmxPath); if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in suspend state")); goto cleanup; } if (virRun(cmd, NULL) < 0) goto cleanup; virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNPAUSED); ret = 0; cleanup: if (vm) virObjectUnlock(vm); return ret; } static int vmwareDomainReboot(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; const char * vmxPath = NULL; virDomainObjPtr vm; const char *cmd[] = { VMRUN, "-T", PROGRAM_SENTINAL, "reset", PROGRAM_SENTINAL, "soft", NULL }; int ret = -1; virCheckFlags(0, -1); vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } vmxPath = ((vmwareDomainPtr) vm->privateData)->vmxPath; vmwareSetSentinal(cmd, vmw_types[driver->type]); vmwareSetSentinal(cmd, vmxPath); if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_RUNNING) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in running state")); goto cleanup; } if (virRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: if (vm) virObjectUnlock(vm); return ret; } static virDomainPtr vmwareDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags) { struct vmware_driver *driver = conn->privateData; virDomainDefPtr vmdef = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; char *vmx = NULL; char *vmxPath = NULL; vmwareDomainPtr pDomain = NULL; virVMXContext ctx; virCheckFlags(0, NULL); ctx.formatFileName = vmwareCopyVMXFileName; vmwareDriverLock(driver); if ((vmdef = virDomainDefParseString(driver->caps, xml, 1 << VIR_DOMAIN_VIRT_VMWARE, VIR_DOMAIN_XML_INACTIVE)) == NULL) goto cleanup; /* generate vmx file */ vmx = virVMXFormatConfig(&ctx, driver->caps, vmdef, 7); if (vmx == NULL) goto cleanup; if (vmwareVmxPath(vmdef, &vmxPath) < 0) goto cleanup; /* create vmx file */ if (virFileWriteStr(vmxPath, vmx, S_IRUSR|S_IWUSR) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to write vmx file '%s'"), vmxPath); goto cleanup; } /* assign def */ if (!(vm = virDomainObjListAdd(driver->domains, driver->caps, vmdef, VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) goto cleanup; pDomain = vm->privateData; pDomain->vmxPath = strdup(vmxPath); vmwareDomainConfigDisplay(pDomain, vmdef); vmdef = NULL; if (vmwareStartVM(driver, vm) < 0) { virDomainObjListRemove(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) virObjectUnlock(vm); vmwareDriverUnlock(driver); return dom; } static int vmwareDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; virCheckFlags(0, -1); vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); virReportError(VIR_ERR_NO_DOMAIN, _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; if (virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is already running")); goto cleanup; } ret = vmwareStartVM(driver, vm); cleanup: if (vm) virObjectUnlock(vm); vmwareDriverUnlock(driver); return ret; } static int vmwareDomainCreate(virDomainPtr dom) { return vmwareDomainCreateWithFlags(dom, 0); } static int vmwareDomainUndefineFlags(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; virCheckFlags(0, -1); vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); virReportError(VIR_ERR_NO_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot undefine transient domain")); goto cleanup; } if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; if (virDomainObjIsActive(vm)) { vm->persistent = 0; } else { virDomainObjListRemove(driver->domains, vm); vm = NULL; } ret = 0; cleanup: if (vm) virObjectUnlock(vm); vmwareDriverUnlock(driver); return ret; } static int vmwareDomainUndefine(virDomainPtr dom) { return vmwareDomainUndefineFlags(dom, 0); } static virDomainPtr vmwareDomainLookupByID(virConnectPtr conn, int id) { struct vmware_driver *driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; vmwareDriverLock(driver); vm = virDomainObjListFindByID(driver->domains, id); vmwareDriverUnlock(driver); if (!vm) { virReportError(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) virObjectUnlock(vm); return dom; } static char * vmwareGetOSType(virDomainPtr dom) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } if (!(ret = strdup(vm->def->os.type))) virReportOOMError(); cleanup: if (vm) virObjectUnlock(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 = virDomainObjListFindByUUID(driver->domains, uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(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) virObjectUnlock(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 = virDomainObjListFindByName(driver->domains, name); vmwareDriverUnlock(driver); if (!vm) { virReportError(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) virObjectUnlock(vm); return dom; } static int vmwareDomainIsActive(virDomainPtr dom) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr obj; int ret = -1; vmwareDriverLock(driver); obj = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!obj) { virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } ret = virDomainObjIsActive(obj); cleanup: if (obj) virObjectUnlock(obj); return ret; } static int vmwareDomainIsPersistent(virDomainPtr dom) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr obj; int ret = -1; vmwareDriverLock(driver); obj = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!obj) { virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } ret = obj->persistent; cleanup: if (obj) virObjectUnlock(obj); return ret; } static char * vmwareDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; char *ret = NULL; /* Flags checked by virDomainDefFormat */ vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } ret = virDomainDefFormat(vm->def, flags); cleanup: if (vm) virObjectUnlock(vm); return ret; } static char * vmwareDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat, const char *nativeConfig, unsigned int flags) { struct vmware_driver *driver = conn->privateData; virVMXContext ctx; virDomainDefPtr def = NULL; char *xml = NULL; virCheckFlags(0, NULL); if (STRNEQ(nativeFormat, "vmware-vmx")) { virReportError(VIR_ERR_INVALID_ARG, _("Unsupported config format '%s'"), nativeFormat); return NULL; } ctx.parseFileName = vmwareCopyVMXFileName; def = virVMXParseConfig(&ctx, driver->caps, nativeConfig); if (def != NULL) xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE); virDomainDefFree(def); return xml; } static int vmwareDomainObjListUpdateDomain(virDomainObjPtr dom, void *data) { struct vmware_driver *driver = data; virObjectLock(dom); ignore_value(vmwareUpdateVMStatus(driver, dom)); virObjectUnlock(dom); return 0; } static void vmwareDomainObjListUpdateAll(virDomainObjListPtr doms, struct vmware_driver *driver) { virDomainObjListForEach(doms, vmwareDomainObjListUpdateDomain, driver); } static int vmwareNumDefinedDomains(virConnectPtr conn) { struct vmware_driver *driver = conn->privateData; int n; vmwareDriverLock(driver); vmwareDomainObjListUpdateAll(driver->domains, 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); vmwareDomainObjListUpdateAll(driver->domains, 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); vmwareDomainObjListUpdateAll(driver->domains, 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); vmwareDomainObjListUpdateAll(driver->domains, 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 = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; info->state = virDomainObjGetState(vm, NULL); 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) virObjectUnlock(vm); return ret; } static int vmwareDomainGetState(virDomainPtr dom, int *state, int *reason, unsigned int flags) { struct vmware_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; virCheckFlags(0, -1); vmwareDriverLock(driver); vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); vmwareDriverUnlock(driver); if (!vm) { virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } if (vmwareUpdateVMStatus(driver, vm) < 0) goto cleanup; *state = virDomainObjGetState(vm, reason); ret = 0; cleanup: if (vm) virObjectUnlock(vm); return ret; } static int vmwareIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) { return 1; } static int vmwareListAllDomains(virConnectPtr conn, virDomainPtr **domains, unsigned int flags) { struct vmware_driver *driver = conn->privateData; int ret = -1; virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); vmwareDriverLock(driver); vmwareDomainObjListUpdateAll(driver->domains, driver); ret = virDomainObjListExport(driver->domains, conn, domains, flags); vmwareDriverUnlock(driver); return ret; } static virDriver vmwareDriver = { .no = VIR_DRV_VMWARE, .name = "VMWARE", .open = vmwareOpen, /* 0.8.7 */ .close = vmwareClose, /* 0.8.7 */ .type = vmwareGetType, /* 0.8.7 */ .version = vmwareGetVersion, /* 0.8.7 */ .listDomains = vmwareListDomains, /* 0.8.7 */ .numOfDomains = vmwareNumDomains, /* 0.8.7 */ .listAllDomains = vmwareListAllDomains, /* 0.9.13 */ .domainCreateXML = vmwareDomainCreateXML, /* 0.8.7 */ .domainLookupByID = vmwareDomainLookupByID, /* 0.8.7 */ .domainLookupByUUID = vmwareDomainLookupByUUID, /* 0.8.7 */ .domainLookupByName = vmwareDomainLookupByName, /* 0.8.7 */ .domainSuspend = vmwareDomainSuspend, /* 0.8.7 */ .domainResume = vmwareDomainResume, /* 0.8.7 */ .domainShutdown = vmwareDomainShutdown, /* 0.8.7 */ .domainShutdownFlags = vmwareDomainShutdownFlags, /* 0.9.10 */ .domainReboot = vmwareDomainReboot, /* 0.8.7 */ .domainDestroy = vmwareDomainShutdown, /* 0.8.7 */ .domainDestroyFlags = vmwareDomainShutdownFlags, /* 0.9.4 */ .domainGetOSType = vmwareGetOSType, /* 0.8.7 */ .domainGetInfo = vmwareDomainGetInfo, /* 0.8.7 */ .domainGetState = vmwareDomainGetState, /* 0.9.2 */ .domainGetXMLDesc = vmwareDomainGetXMLDesc, /* 0.8.7 */ .domainXMLFromNative = vmwareDomainXMLFromNative, /* 0.9.11 */ .listDefinedDomains = vmwareListDefinedDomains, /* 0.8.7 */ .numOfDefinedDomains = vmwareNumDefinedDomains, /* 0.8.7 */ .domainCreate = vmwareDomainCreate, /* 0.8.7 */ .domainCreateWithFlags = vmwareDomainCreateWithFlags, /* 0.8.7 */ .domainDefineXML = vmwareDomainDefineXML, /* 0.8.7 */ .domainUndefine = vmwareDomainUndefine, /* 0.8.7 */ .domainUndefineFlags = vmwareDomainUndefineFlags, /* 0.9.4 */ .domainIsActive = vmwareDomainIsActive, /* 0.8.7 */ .domainIsPersistent = vmwareDomainIsPersistent, /* 0.8.7 */ .isAlive = vmwareIsAlive, /* 0.9.8 */ }; int vmwareRegister(void) { if (virRegisterDriver(&vmwareDriver) < 0) return -1; return 0; }