[libvirt] [PATCH v3] qemu: call drive_unplug in DetachPciDiskDevice
by Ryan Harper
Currently libvirt doesn't confirm whether the guest has responded to the
disk removal request. In some cases this can leave the guest with
continued access to the device while the mgmt layer believes that it has
been removed. With a recent qemu monitor command[1] we can
deterministically revoke a guests access to the disk (on the QEMU side)
to ensure no futher access is permitted.
This patch adds support for the drive_unplug() command and introduces it
in the disk removal paths. There is some discussion to be had about how
to handle the case where the guest is running in a QEMU without this
command (and the fact that we currently don't have a way of detecting
what monitor commands are available).
Changes since v2:
- use VIR_ERROR to report when unplug command not found
Changes since v1:
- return > 0 when command isn't present, < 0 on command failure
- detect when drive_unplug command isn't present and log error
instead of failing entire command
Signed-off-by: Ryan Harper <ryanh(a)us.ibm.com>
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index abd8e9d..615427a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8646,6 +8646,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
virCgroupPtr cgroup = NULL;
+ char drivestr[PATH_MAX];
i = qemudFindDisk(vm->def, dev->data.disk->dst);
@@ -8673,13 +8674,36 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
goto cleanup;
}
+ /* build the actual drive id string as the disk->info.alias doesn't
+ * contain the QEMU_DRIVE_HOST_PREFIX that is passed to qemu */
+ if ((ret = snprintf(drivestr, sizeof(drivestr), "%s%s",
+ QEMU_DRIVE_HOST_PREFIX,
+ detach->info.alias))
+ < 0 || ret >= sizeof(drivestr)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) {
+ ret = qemuMonitorDriveUnplug(priv->mon, drivestr);
+ DEBUG("DriveUnplug ret=%d", ret);
+ /* ret > 0 indicates unplug isn't supported, issue will be logged */
+ if (ret < 0) {
+ qemuDomainObjExitMonitor(vm);
+ goto cleanup;
+ }
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(vm);
goto cleanup;
}
} else {
+ ret = qemuMonitorDriveUnplug(priv->mon, drivestr);
+ /* ret > 0 indicates unplug isn't supported, issue will be logged */
+ if (ret < 0) {
+ qemuDomainObjExitMonitor(vm);
+ goto cleanup;
+ }
if (qemuMonitorRemovePCIDevice(priv->mon,
&detach->info.addr.pci) < 0) {
qemuDomainObjExitMonitor(vm);
@@ -8723,6 +8747,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
virCgroupPtr cgroup = NULL;
+ char drivestr[PATH_MAX];
i = qemudFindDisk(vm->def, dev->data.disk->dst);
@@ -8749,7 +8774,22 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
}
}
+ /* build the actual drive id string as the disk->info.alias doesn't
+ * contain the QEMU_DRIVE_HOST_PREFIX that is passed to qemu */
+ if ((ret = snprintf(drivestr, sizeof(drivestr), "%s%s",
+ QEMU_DRIVE_HOST_PREFIX,
+ detach->info.alias))
+ < 0 || ret >= sizeof(drivestr)) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ /* ret > 0 indicates unplug isn't supported, issue will be logged */
+ if (qemuMonitorDriveUnplug(priv->mon, drivestr) < 0) {
+ qemuDomainObjExitMonitor(vm);
+ goto cleanup;
+ }
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(vm);
goto cleanup;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 2366fdb..285381d 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1781,6 +1781,25 @@ int qemuMonitorGetAllPCIAddresses(qemuMonitorPtr mon,
return ret;
}
+int qemuMonitorDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr)
+{
+ DEBUG("mon=%p drivestr=%s", mon, drivestr);
+ int ret;
+
+ if (!mon) {
+ qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (mon->json)
+ ret = qemuMonitorJSONDriveUnplug(mon, drivestr);
+ else
+ ret = qemuMonitorTextDriveUnplug(mon, drivestr);
+ return ret;
+}
+
int qemuMonitorDelDevice(qemuMonitorPtr mon,
const char *devalias)
{
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 48f4c20..bfe3641 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -381,6 +381,9 @@ int qemuMonitorDelDevice(qemuMonitorPtr mon,
int qemuMonitorAddDrive(qemuMonitorPtr mon,
const char *drivestr);
+int qemuMonitorDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr);
+
int qemuMonitorSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
const char *passphrase);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index d3ab25f..b11fd4f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2243,6 +2243,39 @@ int qemuMonitorJSONAddDrive(qemuMonitorPtr mon,
}
+int qemuMonitorJSONDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr)
+{
+ int ret;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+
+ DEBUG("JSONDriveUnplug drivestr=%s", drivestr);
+ cmd = qemuMonitorJSONMakeCommand("drive_unplug",
+ "s:id", drivestr,
+ NULL);
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0) {
+ /* See if drive_unplug isn't supported */
+ if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
+ VIR_ERROR0(_("unplugging disk is not supported. "
+ "This may leak data if disk is reassigned"));
+ ret = 1;
+ goto cleanup;
+ }
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+ }
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
const char *passphrase)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 94806c1..6a8692e 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -188,6 +188,9 @@ int qemuMonitorJSONDelDevice(qemuMonitorPtr mon,
int qemuMonitorJSONAddDrive(qemuMonitorPtr mon,
const char *drivestr);
+int qemuMonitorJSONDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr);
+
int qemuMonitorJSONSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
const char *passphrase);
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 69971a6..6e5bc95 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -2380,6 +2380,52 @@ cleanup:
return ret;
}
+/* Attempts to unplug a drive. Returns 1 if unsupported, 0 if ok, and -1 on
+ * other failure */
+int qemuMonitorTextDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr)
+{
+ char *cmd = NULL;
+ char *reply = NULL;
+ char *safedev;
+ int ret = -1;
+ DEBUG("TextDriveUnplug drivestr=%s", drivestr);
+
+ if (!(safedev = qemuMonitorEscapeArg(drivestr))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&cmd, "drive_unplug %s", safedev) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (qemuMonitorCommand(mon, cmd, &reply) < 0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("cannot unplug %s drive"), drivestr);
+ goto cleanup;
+ }
+
+ if (strstr(reply, "unknown command:")) {
+ VIR_ERROR0(_("unplugging disk is not supported. "
+ "This may leak data if disk is reassigned"));
+ ret = 1;
+ goto cleanup;
+ } else if (STRNEQ(reply, "")) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("unplugging %s drive failed: %s"), drivestr, reply);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(reply);
+ VIR_FREE(safedev);
+ return ret;
+}
int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index c017509..8355ce8 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -186,6 +186,9 @@ int qemuMonitorTextDelDevice(qemuMonitorPtr mon,
int qemuMonitorTextAddDrive(qemuMonitorPtr mon,
const char *drivestr);
+int qemuMonitorTextDriveUnplug(qemuMonitorPtr mon,
+ const char *drivestr);
+
int qemuMonitorTextSetDrivePassphrase(qemuMonitorPtr mon,
const char *alias,
const char *passphrase);
--
Ryan Harper
Software Engineer; Linux Technology Center
IBM Corp., Austin, Tx
ryanh(a)us.ibm.com
13 years, 11 months
[libvirt] Valid characters in domain names?
by Richard W.M. Jones
Does libvirt enforce any sort of validity of characters in guest names?
Someone tried to create a domain called '#' (the single hash
character) and noted that this caused failures in virt-tools:
https://bugzilla.redhat.com/show_bug.cgi?id=639601
https://bugzilla.redhat.com/show_bug.cgi?id=639602
Had a look at the code but couldn't see anything obvious: It seems
like libvirt delegates this entirely to the drivers, the drivers
(probably) all call virDomainDefParseXML, and this function does no
checking that I could see.
If my analysis is correct, this could be dangerous. What if the name
contains a character that is special to the qemu command line (','),
to XML ('>'), or to C (�)?
As an example, the code already does:
char *virDomainDefFormat(virDomainDefPtr def,
int flags)
{
...
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
...
}
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://et.redhat.com/~rjones/virt-df/
14 years
[libvirt] ruby-libvirt issue
by Jaromír Červenka
Good evening,
could anybody explain me this, please?
divinus:~ # virsh
error: cannot recv data: : Connection reset by peer
error: failed to connect to the hypervisor
divinus:~ #
I am trying to imlement Chris's ruby-libvirt to my Ruby on Rails
application. First few connection to libvirt daemon (thru ruby-libvirt API)
from my app are ok, but then somethings happend and it's not possible to
connect anymore until I restart libvirt daemon manually by init.d script or
until I restart apache (or WEBrick). And it's not possible connect to virsh
from shell also! See messages above.
When I try ruby-libvirt from bare Ruby script, everythig is fine - doesn't
matter how many times I connect. It's strange.
Does anybody have experience with ruby-libvirt in RoR application?
Thank you.
Jaromir.
14 years
[libvirt] VMware Workstation/Player support
by Jean-Baptiste Rouault
Hi all,
I'm working on the hynesim project (http://www.hynesim.org
http://blog.hynesim.org).
We are going to add VMware Workstation support to hynesim,
so we would like to contribute to the development of a libvirt driver.
There probably are multiple ways of doing this, one of them could
be to use the VIX C API provided by VMware :
http://www.vmware.com/support/developer/vix-api/
However, the VIX license seems to be quite restrictive :
http://www.vmware.com/download/eula/vixapi_eula.html
I'm not a license expert so I don't know if this license forbids
using the API in software like libvirt.
Another possibility could be to run VMware command line tools
from libvirt to control guests.
As Daniel P. Berrange stated on IRC yesterday, the vmx <-> XML
conversion code can be reused from the ESX driver.
I'd like to have your opinion about the "best" to implement this
VMware Workstation driver.
Regards,
Jean-Baptiste Rouault
14 years
[libvirt] process= support for 'qemu-kvm -name' [Bug 576950]
by John Morrissey
I wrote (attached here, and to the bug) a quick patch that sets the process
name to the same value as the window title.
I'm unsure where to go from here. Should I add support for converting
"native" QEMU command lines to libvirt XML? What would that look like, since
I'm not modifying the libvirt format? Should it just drop any ,process= from
the QEMU command line it's parsing? I also imagine the test cases will need
updating.
If someone could give me some high-level guidance, I'd be happy to keep
going on this.
john
--
John Morrissey _o /\ ---- __o
jwm(a)horde.net _-< \_ / \ ---- < \,
www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__
14 years
[libvirt] [PATCH] RFC: Remove all object hashtable caches from virConnectPtr
by Daniel P. Berrange
The virConnectPtr struct will cache instances of all other
objects. APIs like virDomainLookupByUUID will return a
cached object, so if you do virDomainLookupByUUID twice in
a row, you'll get the same exact virDomainPtr instance.
This does not have any performance benefit, since the actual
logic in virDomainLookupByUUID (and other APIs returning
virDomainPtr, etc instances) is not short-circuited. All
it does is to ensure there is only one single virDomainPtr
in existance for any given UUID.
The caching has a number of downsides though, all relating
to stale data. If APIs aren't careful to always overwrite
the 'id' field in virDomainPtr it may become out of data.
Likewise for the name field, if a guest is renamed, or if
a guest is deleted, and then a new one created with the
same UUID but different name.
This has been an ongoing, endless source of bugs for all
applications using libvirt from languages with garbage
collection, causing them to get virDomainPtr instances
from long ago with stale data.
The caching is also a waste of memory resources, since
both applications, and language bindings often maintain
their own hashtable caches of object instances.
This patch removes all the hash table caching, so all
APIs return brand new virDomainPtr (etc) object instances.
Other options include
- Explicitly overrite the 'name' field in the cached
objects every time they are looked up, to ensure
fully up2date objects
- Add a flag to virConnectOpen to allow apps to
turn off caching themselves.
* src/datatypes.h: Delete all hash tables.
* src/datatypes.c: Remove all object caching code
---
src/datatypes.c | 657 +++++++++++++------------------------------------------
src/datatypes.h | 10 -
2 files changed, 149 insertions(+), 518 deletions(-)
diff --git a/src/datatypes.c b/src/datatypes.c
index 46009ae..66dbc99 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -41,120 +41,6 @@
* *
************************************************************************/
-/**
- * virDomainFreeName:
- * @domain: a domain object
- *
- * Destroy the domain object, this is just used by the domain hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefDomain(domain));
-}
-
-/**
- * virNetworkFreeName:
- * @network: a network object
- *
- * Destroy the network object, this is just used by the network hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefNetwork(network));
-}
-
-/**
- * virInterfaceFreeName:
- * @interface: an interface object
- *
- * Destroy the interface object, this is just used by the interface hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virInterfaceFreeName(virInterfacePtr iface, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefInterface(iface));
-}
-
-/**
- * virStoragePoolFreeName:
- * @pool: a pool object
- *
- * Destroy the pool object, this is just used by the pool hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virStoragePoolFreeName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefStoragePool(pool));
-}
-
-/**
- * virStorageVolFreeName:
- * @vol: a vol object
- *
- * Destroy the vol object, this is just used by the vol hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefStorageVol(vol));
-}
-
-/**
- * virSecretFreeName:
- * @secret_: a secret object
- *
- * Destroy the secret object, this is just used by the secret hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static void
-virSecretFreeName(void *secret_, const char *name ATTRIBUTE_UNUSED)
-{
- virSecretPtr secret;
-
- secret = secret_;
- virUnrefSecret(secret);
-}
-
-/**
- * virNWFilterPoolFreeName:
- * @pool: a nwfilter pool object
- *
- * Destroy the nwfilter pool object, this is just used by the nwfilter pool hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virNWFilterPoolFreeName(virNWFilterPtr pool, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefNWFilter(pool));
-}
-
-/**
- * virDomainSnapshotFreeName:
- * @snapshot: a domain snapshotobject
- *
- * Destroy the domain snapshot object, this is just used by the domain hash callback.
- *
- * Returns 0 in case of success and -1 in case of failure.
- */
-static int
-virDomainSnapshotFreeName(virDomainSnapshotPtr snapshot, const char *name ATTRIBUTE_UNUSED)
-{
- return (virUnrefDomainSnapshot(snapshot));
-}
/**
* virGetConnect:
@@ -182,53 +68,12 @@ virGetConnect(void) {
ret->privateData = NULL;
ret->networkPrivateData = NULL;
ret->interfacePrivateData = NULL;
- ret->domains = virHashCreate(20);
- if (ret->domains == NULL)
- goto failed;
- ret->networks = virHashCreate(20);
- if (ret->networks == NULL)
- goto failed;
- ret->interfaces = virHashCreate(20);
- if (ret->interfaces == NULL)
- goto failed;
- ret->storagePools = virHashCreate(20);
- if (ret->storagePools == NULL)
- goto failed;
- ret->storageVols = virHashCreate(20);
- if (ret->storageVols == NULL)
- goto failed;
- ret->nodeDevices = virHashCreate(256);
- if (ret->nodeDevices == NULL)
- goto failed;
- ret->secrets = virHashCreate(20);
- if (ret->secrets == NULL)
- goto failed;
- ret->nwfilterPools = virHashCreate(20);
- if (ret->nwfilterPools == NULL)
- goto failed;
ret->refs = 1;
return(ret);
failed:
if (ret != NULL) {
- if (ret->domains != NULL)
- virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName);
- if (ret->networks != NULL)
- virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName);
- if (ret->interfaces != NULL)
- virHashFree(ret->interfaces, (virHashDeallocator) virInterfaceFreeName);
- if (ret->storagePools != NULL)
- virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName);
- if (ret->storageVols != NULL)
- virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName);
- if (ret->nodeDevices != NULL)
- virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
- if (ret->secrets != NULL)
- virHashFree(ret->secrets, virSecretFreeName);
- if (ret->nwfilterPools != NULL)
- virHashFree(ret->nwfilterPools, (virHashDeallocator) virNWFilterPoolFreeName);
-
virMutexDestroy(&ret->lock);
VIR_FREE(ret);
}
@@ -247,22 +92,6 @@ failed:
static void
virReleaseConnect(virConnectPtr conn) {
DEBUG("release connection %p", conn);
- if (conn->domains != NULL)
- virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
- if (conn->networks != NULL)
- virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName);
- if (conn->interfaces != NULL)
- virHashFree(conn->interfaces, (virHashDeallocator) virInterfaceFreeName);
- if (conn->storagePools != NULL)
- virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName);
- if (conn->storageVols != NULL)
- virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName);
- if (conn->nodeDevices != NULL)
- virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
- if (conn->secrets != NULL)
- virHashFree(conn->secrets, virSecretFreeName);
- if (conn->nwfilterPools != NULL)
- virHashFree(conn->nwfilterPools, (virHashDeallocator) virNWFilterPoolFreeName);
virResetError(&conn->err);
@@ -353,36 +182,23 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virUUIDFormat(uuid, uuidstr);
- ret = (virDomainPtr) virHashLookup(conn->domains, uuidstr);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_DOMAIN_MAGIC;
- ret->conn = conn;
- ret->id = -1;
- memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
- ret->snapshots = virHashCreate(20);
-
- if (virHashAddEntry(conn->domains, uuidstr, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add domain to connection hash table"));
- goto error;
- }
- conn->refs++;
- DEBUG("New hash entry %p", ret);
- } else {
- DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1);
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->magic = VIR_DOMAIN_MAGIC;
+ ret->conn = conn;
+ ret->id = -1;
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -415,18 +231,9 @@ virReleaseDomain(virDomainPtr domain) {
virUUIDFormat(domain->uuid, uuidstr);
DEBUG("release domain %p %s %s", domain, domain->name, uuidstr);
- if (virHashRemoveEntry(conn->domains, uuidstr, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("domain missing from connection hash table"));
- conn = NULL;
- }
-
domain->magic = -1;
domain->id = -1;
VIR_FREE(domain->name);
- if (domain->snapshots != NULL)
- virHashFree(domain->snapshots, (virHashDeallocator) virDomainSnapshotFreeName);
VIR_FREE(domain);
if (conn) {
@@ -499,31 +306,22 @@ virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) {
virUUIDFormat(uuid, uuidstr);
- ret = (virNetworkPtr) virHashLookup(conn->networks, uuidstr);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_NETWORK_MAGIC;
- ret->conn = conn;
- memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
-
- if (virHashAddEntry(conn->networks, uuidstr, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add network to connection hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->magic = VIR_NETWORK_MAGIC;
+ ret->conn = conn;
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -556,13 +354,6 @@ virReleaseNetwork(virNetworkPtr network) {
virUUIDFormat(network->uuid, uuidstr);
DEBUG("release network %p %s %s", network, network->name, uuidstr);
- if (virHashRemoveEntry(conn->networks, uuidstr, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("network missing from connection hash table"));
- conn = NULL;
- }
-
network->magic = -1;
VIR_FREE(network->name);
VIR_FREE(network);
@@ -641,70 +432,28 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac) {
virMutexLock(&conn->lock);
- ret = (virInterfacePtr) virHashLookup(conn->interfaces, name);
-
- if (ret != NULL) {
- if (STRCASENEQ(ret->mac, mac)) {
- /*
- * If the mac address has changed, try to modify it in
- * place, which will only work if the new mac is the
- * same length as, or shorter than, the old mac.
- */
- size_t newmaclen = strlen(mac);
- size_t oldmaclen = strlen(ret->mac);
- if (newmaclen <= oldmaclen) {
- strcpy(ret->mac, mac);
- } else {
- /*
- * If it's longer, we're kind of screwed, because we
- * can't add a new hashtable entry (it would clash
- * with the existing entry of same name), and we can't
- * free/re-alloc the existing entry's mac, as some
- * other thread may already be using the existing mac
- * pointer. Fortunately, this should never happen,
- * since the length of the mac address for any
- * interface is determined by the type of the
- * interface, and that is unlikely to change.
- */
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to change interface mac address "
- "from %s to %s due to differing lengths."),
- ret->mac, mac);
- ret = NULL;
- goto error;
- }
- }
- } else {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->mac = strdup(mac);
- if (ret->mac == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->mac = strdup(mac);
+ if (ret->mac == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
- ret->magic = VIR_INTERFACE_MAGIC;
- ret->conn = conn;
+ ret->magic = VIR_INTERFACE_MAGIC;
+ ret->conn = conn;
- if (virHashAddEntry(conn->interfaces, name, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add interface to connection hash table"));
- goto error;
- }
- conn->refs++;
- }
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -735,15 +484,6 @@ virReleaseInterface(virInterfacePtr iface) {
virConnectPtr conn = iface->conn;
DEBUG("release interface %p %s", iface, iface->name);
- if (virHashRemoveEntry(conn->interfaces, iface->name, NULL) < 0) {
- /* unlock before reporting error because error report grabs lock */
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("interface missing from connection hash table"));
- /* don't decr the conn refct if we weren't connected to it */
- conn = NULL;
- }
-
iface->magic = -1;
VIR_FREE(iface->name);
VIR_FREE(iface->mac);
@@ -820,31 +560,22 @@ virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uui
virUUIDFormat(uuid, uuidstr);
- ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, uuidstr);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_STORAGE_POOL_MAGIC;
- ret->conn = conn;
- memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
-
- if (virHashAddEntry(conn->storagePools, uuidstr, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to add storage pool to connection hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->magic = VIR_STORAGE_POOL_MAGIC;
+ ret->conn = conn;
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -878,13 +609,6 @@ virReleaseStoragePool(virStoragePoolPtr pool) {
virUUIDFormat(pool->uuid, uuidstr);
DEBUG("release pool %p %s %s", pool, pool->name, uuidstr);
- if (virHashRemoveEntry(conn->storagePools, uuidstr, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pool missing from connection hash table"));
- conn = NULL;
- }
-
pool->magic = -1;
VIR_FREE(pool->name);
VIR_FREE(pool);
@@ -958,42 +682,33 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const c
}
virMutexLock(&conn->lock);
- ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->pool = strdup(pool);
- if (ret->pool == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- if (virStrcpyStatic(ret->key, key) == NULL) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- _("Volume key %s too large for destination"), key);
- goto error;
- }
- ret->magic = VIR_STORAGE_VOL_MAGIC;
- ret->conn = conn;
-
- if (virHashAddEntry(conn->storageVols, key, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add storage vol to connection hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->pool = strdup(pool);
+ if (ret->pool == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ if (virStrcpyStatic(ret->key, key) == NULL) {
+ virMutexUnlock(&conn->lock);
+ virLibConnError(VIR_ERR_INTERNAL_ERROR,
+ _("Volume key %s too large for destination"), key);
+ goto error;
}
+ ret->magic = VIR_STORAGE_VOL_MAGIC;
+ ret->conn = conn;
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -1025,13 +740,6 @@ virReleaseStorageVol(virStorageVolPtr vol) {
virConnectPtr conn = vol->conn;
DEBUG("release vol %p %s", vol, vol->name);
- if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("vol missing from connection hash table"));
- conn = NULL;
- }
-
vol->magic = -1;
VIR_FREE(vol->name);
VIR_FREE(vol->pool);
@@ -1105,30 +813,21 @@ virGetNodeDevice(virConnectPtr conn, const char *name)
}
virMutexLock(&conn->lock);
- ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_NODE_DEVICE_MAGIC;
- ret->conn = conn;
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
-
- if (virHashAddEntry(conn->nodeDevices, name, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to add node dev to conn hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->magic = VIR_NODE_DEVICE_MAGIC;
+ ret->conn = conn;
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -1159,13 +858,6 @@ virReleaseNodeDevice(virNodeDevicePtr dev) {
virConnectPtr conn = dev->conn;
DEBUG("release dev %p %s", dev, dev->name);
- if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("dev missing from connection hash table"));
- conn = NULL;
- }
-
dev->magic = -1;
VIR_FREE(dev->name);
VIR_FREE(dev->parent);
@@ -1239,30 +931,21 @@ virGetSecret(virConnectPtr conn, const unsigned char *uuid,
virUUIDFormat(uuid, uuidstr);
- ret = virHashLookup(conn->secrets, uuidstr);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_SECRET_MAGIC;
- ret->conn = conn;
- memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
- ret->usageType = usageType;
- if (!(ret->usageID = strdup(usageID))) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- if (virHashAddEntry(conn->secrets, uuidstr, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add secret to conn hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->magic = VIR_SECRET_MAGIC;
+ ret->conn = conn;
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+ ret->usageType = usageType;
+ if (!(ret->usageID = strdup(usageID))) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return ret;
@@ -1294,13 +977,6 @@ virReleaseSecret(virSecretPtr secret) {
virUUIDFormat(secret->uuid, uuidstr);
DEBUG("release secret %p %s", secret, uuidstr);
- if (virHashRemoveEntry(conn->secrets, uuidstr, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("secret missing from connection hash table"));
- conn = NULL;
- }
-
VIR_FREE(secret->usageID);
secret->magic = -1;
VIR_FREE(secret);
@@ -1433,31 +1109,22 @@ virGetNWFilter(virConnectPtr conn, const char *name, const unsigned char *uuid)
virUUIDFormat(uuid, uuidstr);
- ret = (virNWFilterPtr) virHashLookup(conn->nwfilterPools, uuidstr);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_NWFILTER_MAGIC;
- ret->conn = conn;
- memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
-
- if (virHashAddEntry(conn->nwfilterPools, uuidstr, ret) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to add network filter pool to connection hash table"));
- goto error;
- }
- conn->refs++;
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->magic = VIR_NWFILTER_MAGIC;
+ ret->conn = conn;
+ memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+
+ conn->refs++;
ret->refs++;
virMutexUnlock(&conn->lock);
return(ret);
@@ -1491,13 +1158,6 @@ virReleaseNWFilterPool(virNWFilterPtr pool) {
virUUIDFormat(pool->uuid, uuidstr);
DEBUG("release pool %p %s %s", pool, pool->name, uuidstr);
- if (virHashRemoveEntry(conn->nwfilterPools, uuidstr, NULL) < 0) {
- virMutexUnlock(&conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("pool missing from connection hash table"));
- conn = NULL;
- }
-
pool->magic = -1;
VIR_FREE(pool->name);
VIR_FREE(pool);
@@ -1558,33 +1218,21 @@ virGetDomainSnapshot(virDomainPtr domain, const char *name)
}
virMutexLock(&domain->conn->lock);
- ret = (virDomainSnapshotPtr) virHashLookup(domain->snapshots, name);
- if (ret == NULL) {
- if (VIR_ALLOC(ret) < 0) {
- virMutexUnlock(&domain->conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->name = strdup(name);
- if (ret->name == NULL) {
- virMutexUnlock(&domain->conn->lock);
- virReportOOMError();
- goto error;
- }
- ret->magic = VIR_SNAPSHOT_MAGIC;
- ret->domain = domain;
-
- if (virHashAddEntry(domain->snapshots, name, ret) < 0) {
- virMutexUnlock(&domain->conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to add snapshot to domain hash table"));
- goto error;
- }
- domain->refs++;
- DEBUG("New hash entry %p", ret);
- } else {
- DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1);
+ if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&domain->conn->lock);
+ virReportOOMError();
+ goto error;
+ }
+ ret->name = strdup(name);
+ if (ret->name == NULL) {
+ virMutexUnlock(&domain->conn->lock);
+ virReportOOMError();
+ goto error;
}
+ ret->magic = VIR_SNAPSHOT_MAGIC;
+ ret->domain = domain;
+
+ domain->refs++;
ret->refs++;
virMutexUnlock(&domain->conn->lock);
return(ret);
@@ -1604,13 +1252,6 @@ virReleaseDomainSnapshot(virDomainSnapshotPtr snapshot)
virDomainPtr domain = snapshot->domain;
DEBUG("release snapshot %p %s", snapshot, snapshot->name);
- if (virHashRemoveEntry(domain->snapshots, snapshot->name, NULL) < 0) {
- virMutexUnlock(&domain->conn->lock);
- virLibConnError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("snapshot missing from domain hash table"));
- domain = NULL;
- }
-
snapshot->magic = -1;
VIR_FREE(snapshot->name);
VIR_FREE(snapshot);
diff --git a/src/datatypes.h b/src/datatypes.h
index bbeb7cf..0409ab1 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -24,7 +24,6 @@
# include "internal.h"
-# include "hash.h"
# include "driver.h"
# include "threads.h"
@@ -188,14 +187,6 @@ struct _virConnect {
virErrorFunc handler; /* associated handlet */
void *userData; /* the user data */
- virHashTablePtr domains; /* hash table for known domains */
- virHashTablePtr networks; /* hash table for known domains */
- virHashTablePtr interfaces; /* hash table for known interfaces */
- virHashTablePtr storagePools;/* hash table for known storage pools */
- virHashTablePtr storageVols;/* hash table for known storage vols */
- virHashTablePtr nodeDevices; /* hash table for known node devices */
- virHashTablePtr secrets; /* hash taboe for known secrets */
- virHashTablePtr nwfilterPools; /* hash tables ofr known nw filter pools */
int refs; /* reference count */
};
@@ -211,7 +202,6 @@ struct _virDomain {
char *name; /* the domain external name */
int id; /* the domain ID */
unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */
- virHashTablePtr snapshots; /* hash table for known snapshots */
};
/**
--
1.7.2.3
14 years
[libvirt] New save/restore api proposal
by Jean-Baptiste Rouault
Hello all,
I'd like to add support for save and restore to the OpenVZ and VirtualBox
drivers because I have to support these operations in the application I'm
working on.
However, the save/restore API in its current state doesn't fit well to our
needs. The main problem is that the domain definition is included inside the
save file. This is problematic because between the save and the restore
operations, the names of the network interfaces on the host side are likely to
have changed and we can't modify them before restoring the domain.
To summarize, what we would like to be able to do is:
- save a domain and undefine it
- update the domain definition to use the new names of host side interfaces
- restore the domain
This is why I would like to add two new functions with the following
signatures (better names are probably needed):
int virDomainSaveState(virDomainPtr domain, const char *to);
int virDomainRestoreState(virDomainPtr domain, const char *from);
The first one would do the same as virDomainSave but without prepending the
domain's definition to the save file.
The other function would be able to restore a domain saved by the first one.
What do you think ?
Regards,
Jean-Baptiste
14 years
[libvirt] Release of libvirt-0.8.5
by Daniel Veillard
So the release it out ! And hopefully we are back on our 'end of month'
release cycle. The libvirt-0.8.5 release is available from
ftp://libvirt.org/libvirt/
So we have a number of features in this new release, I will also note
the rather large mount of documentation fixes (thanks Justin and others!)
and portability. Hopefully this will help people to use libvirt in a
veriety of context !
Features:
- Enable JSON and netdev features in QEMU >= 0.13 (Daniel P. Berrange)
- framework for auditing integration (Daniel P. Berrange)
- framework for DTrace/SystemTap integration (Daniel P. Berrange)
- Setting the number of vcpu at boot (Eric Blake)
- Enable support for nested SVM (Daniel P. Berrange)
- Virtio plan9fs filesystem QEMU (Daniel P. Berrange)
- Memory parameter controls (Nikunj A. Dadhania)
- portability to OS-X (Justin Clift)
Documentation:
- virsh: improve the help description for managedsave and start (Justin Clift)
- docs: updated the C# bindings page with arnauds latest changes (Justin Clift)
- docs: update ruby bindings maintainer to chris lalancette (Justin Clift)
- docs: reworded and reordered the bindings page, plus minor tweaks (Justin Clift)
- Fix xen API documentation (Philipp Hahn)
- docs: added a table of contents to the first 11 docs files (Justin Clift)
- docs: reformated the bindings page html markup to match other pages (Justin Clift)
- docs: revamp api_extension example, using vcpu patch series (Eric Blake)
- docs: install the generated html files when make install is run (Justin Clift)
- Fix documentation for virEventAddTimeout() (Philipp Hahn)
- esx: Add documentation about certificates and connection problems (Matthias Bolte)
- docs: added a table of contents to the new c sharp bindings page (Justin Clift)
- docs: removed old changelog file, as it is no longer relevant (Justin Clift)
- Update comments for the memory tunables macros (Nikunj A. Dadhania)
- docs: added initial page for c# binding, with links to it (Justin Clift)
- virsh: consolidate memtune docs (Eric Blake)
- Update docs for memory parameters and memtune command (Nikunj A. Dadhania)
- docs: document how to disable memballoon (Eric Blake)
- Update todo list file to point at bugzilla/website (Daniel P. Berrange)
- virsh: update comment about parsing (Eric Blake)
- virsh: document options in man page (Eric Blake)
- Fixes for documentation extraction (Daniel Veillard)
- Add automatic generation of a todo item page (Daniel P. Berrange)
- nwfilter: Add 2nd example to the html docs (Stefan Berger)
- nwfilter: Extend docs with info about the state attribute (Stefan Berger)
- vcpu: improve cpuset attribute (Eric Blake)
- nwfilter: Extend docs with information about comment attr. (Stefan Berger)
- docs: grammar cleanups on logging examples (Eric Blake)
- Fix spelling of Xen in comments (Philipp Hahn)
- docs: reworked the policykit patch submitted by Patrick Dignan (Justin Clift)
- docs: fix the xml validity errors regarding name and id (Justin Clift)
- docs: improve wording for the dev guide (Justin Clift)
- docs: add the app dev guide (Justin Clift)
Portability:
- mingw: Add body for virFork and remove double virDriverLoadModule export (Matthias Bolte)
- daemon: exclude requirement for probes.h on systems without systemtap (Justin Clift)
- build: skip xenapi driver when building for RHEL (Eric Blake)
- build: fix mingw build (Eric Blake)
- build: require pkg-config for bootstrap (Eric Blake)
- configure: disable network and storage-fs drivers on mac os x (Justin Clift)
- build: fix example build on MacOS X (Eric Blake)
- mpath: disable devmapper-multipath checking on non-linux (Justin Clift)
- mac os x: use awk selected by build system rather than first in path (Justin Clift)
- virtualbox: fix a typo in the expected location on mac os x (Justin Clift)
- nwfilter: Don't compile nwfilter driver on other systems than Linux (Stefan Berger)
- nwfilter: add a missing define, so libvirtd builds on macos x (Justin Clift)
- build: avoid non-portable IPv6 struct member, for MacOS X (Eric Blake)
- virsh: change wexitstatus order to allow compilation on mac osx (Justin Clift)
- build: use portable sed expressions (Eric Blake)
Bug Fixes:
- eliminate possibility of a double-closed file descriptor (Stefan Berger)
- qemu: check for vm after starting a job (Eric Blake)
- Only attempt removal of the rule allowing tftp if it was added (Laine Stump)
- qemu: don't use %.3d format for bus/addr of USB devices (Diego Elio Pettenò)
- virsh: fix range of memtune command (Eric Blake)
- qemu: work around dash 0.5.5 bug in managed save (Eric Blake)
- Avoid squashing errors during network startup cleanup path (Daniel P. Berrange)
- xen: Fix domain dump (Jiri Denemark)
- dnsmasq: avoid potential crash (Eric Blake)
- Fix netmask checks for IPv6 in virSocketCheckNetmask (Daniel P. Berrange)
- Don't fail lxc domain start when memory controller support is missing (Guido Günther)
- root_squash: virFileOperation may fail with EPERM too (Dan Kenigsberg)
- qemu: let qemu group look below /var/lib/libvirt/qemu/ (Dan Kenigsberg)
- qemu: Prohibit migration of guests with host devices (Jiri Denemark)
- cpu: Use vendor in baseline CPU only if all hosts use it (Jiri Denemark)
- cpu: Fix vendor for recent CPU models (Jiri Denemark)
- Fix Xen SEXPR generation to properly quote strings containing () (Daniel P. Berrange)
- nwfilter: resolve deadlock between VM ops and filter update (Stefan Berger)
- Don't fail on missing D-Bus (Guido Günther)
- cpu: Remove redundant features (Jiri Denemark)
- xen: Fix virDomain{At,De}tachDevice (Jiri Denemark)
- xen: xenXMDomain*DeviceFlags should obey all flags (Jiri Denemark)
- nwfilter: fix memory leaks (Stefan Berger)
- phyp: Checking for NULL values when building new guest (Eduardo Otubo)
- libvirt-guests: start late and stop early (Jiri Denemark)
- nwfilter bug appearing on big endian machines (Stefan Berger)
- Rebuild network filter for UML guests on updates (Soren Hansen)
Improvements:
- vbox: Stop hardcoding a single path for VBoxXPCOMC.so (Matthias Bolte)
- Add disk/net resource auditing to QEMU driver (Daniel P. Berrange)
- Add auditing of security label in QEMU driver (Daniel P. Berrange)
- Add auditing of start/stop events to the QEMU driver (Daniel P. Berrange)
- Add printf format attribute annotation to virAuditSend method (Daniel P. Berrange)
- Add audit helper for escaping log message strings (Daniel P. Berrange)
- virsh: use - not _ in memtune option names (Eric Blake)
- build: fix shell detection bug (Eric Blake)
- virsh: improve help text where integers are expected (Eric Blake)
- docs: make the location of the xml catalog file a configure option (Justin Clift)
- Fix build for SystemTap 1.0 (Matthias Bolte)
- Fix formatting of network address in iptables helpers (Daniel P. Berrange)
- virsh: Add option 'model' for attach-interface (Osier Yang)
- qemu: Fix detection of drive readonly option (Jiri Denemark)
- vbox: Fix compile errors due to the virSocketAddr series (Matthias Bolte)
- Don't try to parse a NULL ip address for boot server (Daniel P. Berrange)
- Convert virNetwork to use virSocketAddr everywhere (Daniel P. Berrange)
- Include socket address in client probe data (Daniel P. Berrange)
- Add dtrace static probes in libvirtd (Daniel P. Berrange)
- Add test suite for virSocket APIs (Daniel P. Berrange)
- Ban use of all inet_* functions (Daniel P. Berrange)
- Fix error reporting for virSocketParse (Daniel P. Berrange)
- Expand virSocketFormat to be more flexible (Daniel P. Berrange)
- Fix passing of address family to virSocketParseAddr (Daniel P. Berrange)
- Include length with virSocketAddr data (Daniel P. Berrange)
- audit: simplify declaration (Eric Blake)
- qemu: Exit on first error in qemuDomainGetMemoryParameters (Matthias Bolte)
- virsh: Don't read nparams when virDomainGetMemoryParameters fails (Matthias Bolte)
- Fix formatting of the memtune XML element (Matthias Bolte)
- Add process= support for 'qemu-kvm -name' (John Morrissey)
- nwfilter: avoid dir. enforcement for certain types of rules (Stefan Berger)
- Audit SELinux label assignment. (Miloslav Trmač)
- Audit VM start/stop/suspend/resume (Miloslav Trmač)
- vcpu: remove dead xen code (Eric Blake)
- vcpu: improve support for setting xen vcpu counts (Eric Blake)
- vcpu: improve support for getting xen vcpu counts (Eric Blake)
- vcpu: improve vcpu support in xen command line (Eric Blake)
- vcpu: complete vcpu support in qemu driver (Eric Blake)
- vcpu: improve vcpu support in qemu command line (Eric Blake)
- vcpu: support all flags in test driver (Eric Blake)
- vcpu: add virsh support (Eric Blake)
- vcpu: support maxvcpu in domain_conf (Eric Blake)
- vcpu: make old API trivially wrap to new API (Eric Blake)
- vcpu: implement the remote protocol (Eric Blake)
- vcpu: implement the public APIs (Eric Blake)
- vcpu: define internal driver API (Eric Blake)
- vcpu: add new public API (Eric Blake)
- nwfilter: changes to rules in VM->host table (Stefan Berger)
- esx: Handle non-UTF-8 encoded VMX files (Matthias Bolte)
- Run initgroups() in qemudOpenAsUID() (Dan Kenigsberg)
- memtune: Add min_guarantee to the virsh memtune command (Nikunj A. Dadhania)
- esx: Fix check in esxDomainGetInfo's perf metric handling (Matthias Bolte)
- virsh: add tests for recent cli improvements (Eric Blake)
- virsh: new echo command (Eric Blake)
- virsh: add support for accepting arbitrary argv (Eric Blake)
- esx: Explictly declare VMX file content as UTF-8 (Matthias Bolte)
- esx: Handle name escaping properly (Matthias Bolte)
- nwfilter: prevent filters with different name but same UUID (Stefan Berger)
- new attribute accessmode to filesystem element (Harsh Prateek Bora)
- nwfilter: cut off connections after changing filters (Stefan Berger)
- build: provide URL in 'configure --help' (Eric Blake)
- tests: Honor LIBVIRT_{DEBUG,LOG_*} variables (Jiri Denemark)
- tests: Do not override LIBVIRT_DEBUG variable (Jiri Denemark)
- Improve error reporting in test suites (Daniel P. Berrange)
- virsh: move code into topological order (Eric Blake)
- virsh: simplify top-level option parsing (Eric Blake)
- virsh: add -- support (Lai Jiangshan)
- virsh: support single quote (Lai Jiangshan)
- virsh: add escaper \ for command string parsing (Lai Jiangshan)
- virsh: rework command parsing (Lai Jiangshan)
- virsh: add vshCommandParser abstraction (Lai Jiangshan)
- virsh: better handling the boolean option (Lai Jiangshan)
- virsh: allow zero length arguments (Lai Jiangshan)
- virsh: better support double quote (Lai Jiangshan)
- Add todo.pl and config example to EXTRA_DIST (Daniel P. Berrange)
- Fix several minor problems introduced by the memtune series (Matthias Bolte)
- Remote protocol implementation of virDomainSet/GetMemoryParameters (Nikunj A. Dadhania)
- Adding memtune command to virsh tool (Nikunj A. Dadhania)
- Implement domainGetMemoryParamters for LXC (Nikunj A. Dadhania)
- Implement domainSetMemoryParamters for LXC (Nikunj A. Dadhania)
- Adding memtunables to libvirt-lxc command (Nikunj A. Dadhania)
- Adding memtunables to qemuSetupCgroup (Nikunj A. Dadhania)
- Implement domainGetMemoryParamters for QEmu (Nikunj A. Dadhania)
- Implement domainSetMemoryParamters for QEmu (Nikunj A. Dadhania)
- Implement cgroup memory controller tunables (Nikunj A. Dadhania)
- XML parsing for memory tunables (Nikunj A. Dadhania)
- Adds xml entries for memory tunables in domain schema (Nikunj A. Dadhania)
- Adding structure and defines for virDomainSet/GetMemoryParameters (Nikunj A. Dadhania)
- Set sensible defaults for cpu match and feature policy (Daniel P. Berrange)
- xen: Fix logic bug in xenDaemon*DeviceFlags (Jiri Denemark)
- xen: Make xenDaemon*DeviceFlags errors less confusing (Jiri Denemark)
- Return a suitable error message if we can't find a matching emulator (Guido Günther)
- Pass -n to ip(6)tables (Guido Günther)
- nwfilter: Extend schema to accept state attribute (Stefan Berger)
- nwfilter: Add test case for testing the state attribute (Stefan Berger)
- nwfilter: Instantiate state match in ip(6)tables rules (Stefan Berger)
- nwfilter: Extend XML parser and gen. to support state attr. (Stefan Berger)
- xen: Fix bogus error when attaching a device (Jiri Denemark)
- esx: Add support for virtual serial device network backing (Matthias Bolte)
- phyp: Verify that domain XML contains at least one disk element (Matthias Bolte)
- implement usb and pci hot attach in AppArmor driver (Jamie Strandboge)
- nwfilter: Add a test case for testing the comment attribute (Stefan Berger)
- nwfilter: Extend nwfilter schema to accept comment attrib. (Stefan Berger)
- nwfilter: Instantiate comments in ip(6)tables rules (Stefan Berger)
- nwfilter: Extend XML parser and generator w/ comment attribute (Stefan Berger)
- configure: tweak logic flow of virtport check (Justin Clift)
- Rework configure logic for virtualport support (Stefan Berger)
- nwfilter: report if ip(6)tables rules would not be active (Stefan Berger)
- app-armor: add 'rw' for appropriate devices (Jamie Strandboge)
- add extra tests to virt-aa-helper-test for new '-p' option (Jamie Strandboge)
- esx: Allow '-' in VMX entry names (Matthias Bolte)
- Make SASL work over UNIX domain sockets (Daniel P. Berrange)
- Refactor some daemon code to facilitate introduction of static probes (Daniel P. Berrange)
- nodeinfo: work when hot-plugging is disabled (Eric Blake)
- libvirtd: improve the error message displayed on tls client auth failure (Justin Clift)
- virsh: Use virBuffer for generating XML (Jiri Denemark)
Cleanups:
- audit: printf warning fix (KAMEZAWA Hiroyuki)
- build: use shorter file names for 'make dist' (Eric Blake)
- maint: fix syntax-check failure of previous patch (Eric Blake)
- maint: ignore new test executable (Eric Blake)
- tests: Silence qemuxml2argv test (Jiri Denemark)
- Remove all use of inet_pton and inet_ntop (Daniel P. Berrange)
- Remove both addrToString methods (Daniel P. Berrange)
- Remove pointless nwIPAddress struct & void *casts (Daniel P. Berrange)
- Remove useless code in error path of getnameinfo() (Daniel P. Berrange)
- maint: sort private sym lists (Eric Blake)
- Rename VIR_DOMAIN_SWAP_HARD_LIMIT to VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT (Matthias Bolte)
- Fix make check on RHEL-5 (Jiri Denemark)
- Don't let daemon-conf test fail when auditing is disabled (Matthias Bolte)
- Fix compile errors in remote.c and newly added audit code (Matthias Bolte)
- Fix symbol exports & remove duplicated libvirt_util.la linkage (Daniel P. Berrange)
- Fix statstest when driver modules are enabled (Daniel P. Berrange)
- build: avoid false positive syntax-check failure (Eric Blake)
- proxy: Fix undefined reference to virClose (Matthias Bolte)
- Introduce VIR_CLOSE to be used rather than close() (Stefan Berger)
- Fix warning about a non-literal format string in qemu_driver.c (Laine Stump)
- test: silence nwfilter test (Stefan Berger)
- tests: fix spurious test failure (Eric Blake)
- memory: fix remote protocol compilation (Eric Blake)
- virsh: poison raw allocation routines (Eric Blake)
- Avoid checking against strncpy in virsh.c (Daniel Veillard)
- Cleanup some tabs issues (Daniel Veillard)
- util: add missing export (Eric Blake)
- virt-aa-helper-test cleanups (Jamie Strandboge)
- python: drop unnecessary conn assignment (Dan Kenigsberg)
- pciFindStubDriver should return NULL on error (Chris Wright)
- tests: silence qemuargv2xmltest noise (Eric Blake)
- tests: clean up qemuargv2xmltest (Eric Blake)
- maint: silence warning from libtool (Eric Blake)
- tests: Fix preprocessor indentation (Jiri Denemark)
Thanks everybody who helped for this release !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
14 years
[libvirt] RFC [0/3]: A proposal for lock manager plugins
by Daniel P. Berrange
A few weeks back David introduce sync-manager as a means for protecting
against the same VM being started on multiple hosts:
https://www.redhat.com/archives/libvir-list/2010-August/msg00179.html
This is obviously a desirable feature for libvirt, but we don't want to
have a hardcoded dependancy on a particular implementation. We can
achieve isolation between libvirt & sync-manager, allowing for alternative
implementations by specifying a formal plugin for supervisor processes.
What follows is my mockup of what a plugin API would look like, its
internal libvirt API and an outline of the usage scenarios in psuedo
code.
At the minimum level of compliance, the plugin implementation provides
for per-VM level exclusion. Optionally a plugin can declare that it
- supports locks against individual resources (disks)
- supports hotplug of individual resources
- supports migration of the supervised process
Migration/hotplug will be forbid if those capabilities aren't declared
by the plugin.
In parallel with David's work on sync-manager, I intend to write a simple
plugin implementation based solely on fcntl() locking. It is important
that we have 2 independant implementations to prove the validity of the
plugin API. The fcntl() impl should provide a zero-config impl we can
deploy out of the box that will provide protection against 2 vms using
the same disk image on a host, and limited protection in multi-host
scenarios with shared filesystems (no protection for shared block devs).
Perhaps we should have a 3rd impl based on libdlm too, for Red Hat
ClusterSuite scenarios, though sync-manager may well be general &
simple enough to easily cope with this already.
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
14 years