[libvirt] [python PATCH] maint: document use of libvirt's run script
by Eric Blake
Ever since libvirt commit 78c09530, it's easier to just use the
run script.
* README: Mention run script.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
README | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/README b/README
index df1de59..96082f0 100644
--- a/README
+++ b/README
@@ -32,10 +32,11 @@ A makefile shim is provided so that you can do
rather than directly invoking setup.py.
As of libvirt 1.2.6, it is possible to develop against an uninstalled
-libvirt.git checkout, by setting some environment variables:
+libvirt.git checkout, by setting PKG_CONFIG_PATH and LD_LIBRARY_PATH
+environment variables to point into that libvirt tree; you can even
+automate this by using libvirt's run script:
- export PKG_CONFIG_PATH=/path/to/libvirt/git/src/
- export LD_LIBRARY_PATH=/path/to/libvirt/git/src/.libs/
+ /path/to/libvirt/run python setup.py build
Patches for this code should be sent to the main libvirt
development mailing list
--
1.9.3
10 years, 4 months
[libvirt] [PATCH v2 00/25] Refactor the xm parser
by David Kiarie
Kiarie Kahurani (25):
src/xenxs:Refactor code parsing memory config
src/xenxs:Refactor code parsing event actions config
src/xenxs:Refactor code parsing virtual time controls config
src/xenxs:Refactor code parsing PCI devices config
src/xenxs:Refactor code parsing CPU features config
src/xenxs:Refactor code parsing disk config
src/xenxs:Refactor code parsing Vfb config
src/xenxs:Refactor code parsing OS related config
src/xenxs:Refactor code parsing Char device related config
src/xenxs:Refactor code parsing Vif
src/xenxs:Refactor code parsing emulated hardware config
src/xenxs:Refactor code parsing general config
src/xenxs:Organise functions to avoid duplication
src/xenxs:Refactor code formating general config
src/xenxs:Refactor code formating memory config
src/xenxs:Reafactor code formating virtual time config
src/xenxs:Refactor code formating event actions config
src/xenxs:Refactor code formating Vif config
src/xenxs:Refactor code formating Vfb config
src/xenxs:Refactor code formating CPU config and features
src/xenxs:Refactor code formating disk list
src/xenxs:Refactor code formating emulated devices config
src/xenxs:Refactor char devices formating code
src/xenxs:Refactor code formating OS config
src/xenxs:Export code to be reused
src/xenxs/xen_xm.c | 2009 ++++++++++++--------
src/xenxs/xen_xm.h | 6 +-
tests/xmconfigdata/test-escape-paths.cfg | 14 +-
tests/xmconfigdata/test-fullvirt-force-hpet.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-force-nohpet.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-localtime.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-net-ioemu.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-net-netfront.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-new-cdrom.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-old-cdrom.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-parallel-tcp.cfg | 12 +-
.../test-fullvirt-serial-dev-2-ports.cfg | 12 +-
.../test-fullvirt-serial-dev-2nd-port.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-file.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-null.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-pipe.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-pty.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-stdio.cfg | 12 +-
.../test-fullvirt-serial-tcp-telnet.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-tcp.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-udp.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-serial-unix.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-sound.cfg | 14 +-
tests/xmconfigdata/test-fullvirt-usbmouse.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-usbtablet.cfg | 12 +-
tests/xmconfigdata/test-fullvirt-utc.cfg | 12 +-
tests/xmconfigdata/test-no-source-cdrom.cfg | 12 +-
tests/xmconfigdata/test-pci-devs.cfg | 12 +-
28 files changed, 1326 insertions(+), 1005 deletions(-)
This patches try to refactor the code for the xen-xm parser since
much of the code can be reused when writing the xen-xl parser.
changes since Prepost
I have finished refactoring all the code
Fixed numerous memory leaks
I have also changed the layout of the tests since they depend
on the layout of the code which I have changed
I would also like to hear some comment on what configs I should
support in the new xen-xl parser.
Regards,
David
--
1.8.4.5
10 years, 4 months
[libvirt] link error on cygwin
by Eric Blake
Even though I pushed a last-minute patch for 1.2.7 to fix the compiler
phase of the build on cygwin, I'm stumped on how to fix this error from
the link phase:
CCLD libvirtd.exe
../src/.libs/libvirt_driver_remote.a(libvirt_net_rpc_server_la-virnetserver.oo):
In function `virNetServerNew':
/home/eblake/libvirt/src/rpc/virnetserver.c:357: multiple definition of
`virNetServerNew'
/home/eblake/libvirt/src/.libs/libvirt.dll.a(d001949.o):(.text+0x0):
first defined here
and several others. Looks like we are including a link library through
two paths, and cygwin is not as tolerant of that as Linux; but I'm not
sure where in the Makefile.am to tweak to try and fix it.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
10 years, 4 months
Re: [libvirt] [Qemu-devel] [PATCH] [RFC] Add machine type pc-1.0-qemu-kvm for live migrate compatibility with qemu-kvm
by Alex Bligh
On 22 Jul 2014, at 19:43, Alex Bligh <alex(a)alex.org.uk> wrote:
> Testing has been light to date (i.e.
> can I migrate it inbound with -S without anything complaining).
I've given this quite a bit more testing today.
It works fine qemu-kvm 1.0 -> qemu-2.0+patch (cirrus vga)
It works fine qemu-2.0+patch -> qemu-2.0+patch (cirrus vga)
It doesn't (yet) work qemu-2.0+patch -> qemu-kvm 1.0 (cirrus vga).
The reason for this is (at least) that I need to emulate the
broken versioning of the mc146818rtc timer section, as writing
it correctly confuses qemu-kvm 1.0. Therefore please don't bother
testing migration back to 1.0 yet.
--
Alex Bligh
10 years, 4 months
[libvirt] [PATCH] Perform disk config validity checking for attach-device config
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1078126
Using 'virsh attach-device --config' (or --persistent) to attach a
file backed lun device will succeed; however, subsequent domain restarts
will result in failure because the configuration of a file backed lun
is not supported.
Although allowing 'illegal configurations' is something that can be
allowed, it may not be practical in this case. Generally, when attaching
a device to a domain means the domain must be running. A way around
this is using the --config (or --persistent) option. When an attach
is done to a running domain, a temporary configuration is modified
first followed by the live update. The live update will make a number
of disk validity checks when building the qemu command to attach the
disk. If any fail, then change is rejected.
Rather than allow a potentially illegal combination, adjust the code
in the configuration path to make the same checks as the running path
will make with respect to disk validity checks. This way we avoid
having the potential for some subsequent start/reboot to fail because
an illegal combination was allowed.
NB: The live checking remains since it is possible to just to --live
configuration modification.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/qemu/qemu_command.c | 138 ++++++++++++++++++++++++++----------------------
src/qemu/qemu_command.h | 3 ++
src/qemu/qemu_driver.c | 2 +
3 files changed, 81 insertions(+), 62 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4e074e5..8e56151 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3234,6 +3234,81 @@ qemuGetDriveSourceString(virStorageSourcePtr src,
}
+int
+qemuBuildCheckDisk(virDomainDiskDefPtr disk,
+ virQEMUCapsPtr qemuCaps)
+{
+ if (virDiskNameToIndex(disk->dst) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unsupported disk type '%s'"), disk->dst);
+ goto error;
+ }
+
+ if (disk->wwn) {
+ if ((disk->bus != VIR_DOMAIN_DISK_BUS_IDE) &&
+ (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only ide and scsi disk support wwn"));
+ goto error;
+ }
+ }
+
+ if ((disk->vendor || disk->product) &&
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only scsi disk supports vendor and product"));
+ goto error;
+ }
+
+ if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
+ /* make sure that both the bus and the qemu binary support
+ * type='lun' (SG_IO).
+ */
+ if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk device='lun' is not supported for bus='%s'"),
+ virDomainDiskQEMUBusTypeToString(disk->bus));
+ goto error;
+ }
+ if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
+ if (disk->src->protocol != VIR_STORAGE_NET_PROTOCOL_ISCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk device='lun' is not supported "
+ "for protocol='%s'"),
+ virStorageNetProtocolTypeToString(disk->src->protocol));
+ goto error;
+ }
+ } else if (!virDomainDiskSourceIsBlockType(disk)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("disk device='lun' is only valid for block "
+ "type disk source"));
+ goto error;
+ }
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SG_IO)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("disk device='lun' is not supported by "
+ "this QEMU"));
+ goto error;
+ }
+ if (disk->wwn) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting wwn is not supported for lun device"));
+ goto error;
+ }
+ if (disk->vendor || disk->product) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting vendor or product is not supported "
+ "for lun device"));
+ goto error;
+ }
+ }
+ return 0;
+ error:
+ return -1;
+}
+
+
char *
qemuBuildDriveStr(virConnectPtr conn,
virDomainDiskDefPtr disk,
@@ -3620,71 +3695,10 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
{
virBuffer opt = VIR_BUFFER_INITIALIZER;
const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus);
- int idx = virDiskNameToIndex(disk->dst);
int controllerModel;
- if (idx < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("unsupported disk type '%s'"), disk->dst);
+ if (qemuBuildCheckDisk(disk, qemuCaps) < 0)
goto error;
- }
-
- if (disk->wwn) {
- if ((disk->bus != VIR_DOMAIN_DISK_BUS_IDE) &&
- (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Only ide and scsi disk support wwn"));
- goto error;
- }
- }
-
- if ((disk->vendor || disk->product) &&
- disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Only scsi disk supports vendor and product"));
- goto error;
- }
-
- if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
- /* make sure that both the bus and the qemu binary support
- * type='lun' (SG_IO).
- */
- if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
- disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("disk device='lun' is not supported for bus='%s'"),
- bus);
- goto error;
- }
- if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
- if (disk->src->protocol != VIR_STORAGE_NET_PROTOCOL_ISCSI) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("disk device='lun' is not supported for protocol='%s'"),
- virStorageNetProtocolTypeToString(disk->src->protocol));
- goto error;
- }
- } else if (!virDomainDiskSourceIsBlockType(disk)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("disk device='lun' is only valid for block type disk source"));
- goto error;
- }
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_SG_IO)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("disk device='lun' is not supported by this QEMU"));
- goto error;
- }
- if (disk->wwn) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting wwn is not supported for lun device"));
- goto error;
- }
- if (disk->vendor || disk->product) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("Setting vendor or product is not supported "
- "for lun device"));
- goto error;
- }
- }
switch (disk->bus) {
case VIR_DOMAIN_DISK_BUS_IDE:
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index b71e964..00097f9 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -271,4 +271,7 @@ qemuParseKeywords(const char *str,
int qemuGetDriveSourceString(virStorageSourcePtr src,
virConnectPtr conn,
char **source);
+
+int qemuBuildCheckDisk(virDomainDiskDefPtr disk,
+ virQEMUCapsPtr qemuCaps);
#endif /* __QEMU_COMMAND_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a3de784..5bc2785 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6744,6 +6744,8 @@ qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
_("target %s already exists"), disk->dst);
return -1;
}
+ if (qemuBuildCheckDisk(disk, qemuCaps) < 0)
+ return -1;
if (virDomainDiskInsert(vmdef, disk))
return -1;
/* vmdef has the pointer. Generic codes for vmdef will do all jobs */
--
1.9.3
10 years, 4 months
[libvirt] [libvirt-glib] [PATCH v6 1/3] libvirt-gobject-domain: Add _fetch_snapshots
by mail@baedert.org
From: Timm Bäder <mail(a)baedert.org>
This function can be used to fetch the snapshots of a domain (according
to the given GVirDomainSnapshotListFlags) and save them in a
domain-internal GHashTable. A function to access them from outside will
be added in a later patch.
---
libvirt-gobject/libvirt-gobject-domain.c | 85 ++++++++++++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-domain.h | 37 ++++++++++++++
libvirt-gobject/libvirt-gobject.sym | 2 +
3 files changed, 124 insertions(+)
diff --git a/libvirt-gobject/libvirt-gobject-domain.c b/libvirt-gobject/libvirt-gobject-domain.c
index c6e30e5..708cb3b 100644
--- a/libvirt-gobject/libvirt-gobject-domain.c
+++ b/libvirt-gobject/libvirt-gobject-domain.c
@@ -38,6 +38,8 @@ struct _GVirDomainPrivate
{
virDomainPtr handle;
gchar uuid[VIR_UUID_STRING_BUFLEN];
+ GHashTable *snapshots;
+ GMutex *lock;
};
G_DEFINE_TYPE(GVirDomain, gvir_domain, G_TYPE_OBJECT);
@@ -121,6 +123,11 @@ static void gvir_domain_finalize(GObject *object)
g_debug("Finalize GVirDomain=%p", domain);
+ if (priv->snapshots) {
+ g_hash_table_unref(priv->snapshots);
+ }
+ g_mutex_free(priv->lock);
+
virDomainFree(priv->handle);
G_OBJECT_CLASS(gvir_domain_parent_class)->finalize(object);
@@ -237,6 +244,7 @@ static void gvir_domain_init(GVirDomain *domain)
g_debug("Init GVirDomain=%p", domain);
domain->priv = GVIR_DOMAIN_GET_PRIVATE(domain);
+ domain->priv->lock = g_mutex_new();
}
typedef struct virDomain GVirDomainHandle;
@@ -1514,3 +1522,80 @@ gvir_domain_create_snapshot(GVirDomain *dom,
g_free(custom_xml);
return dom_snapshot;
}
+
+
+
+/**
+ * gvir_domain_fetch_snapshots:
+ * @dom: The domain
+ * @list_flags: bitwise-OR of #GVirDomainSnapshotListFlags
+ * @cancellable: (allow-none)(transfer-none): cancellation object
+ * @error: (allow-none): Place-holder for error or NULL
+ *
+ * Returns: TRUE on success, FALSE otherwise.
+ */
+gboolean gvir_domain_fetch_snapshots(GVirDomain *dom,
+ guint list_flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVirDomainPrivate *priv;
+ virDomainSnapshotPtr *snapshots = NULL;
+ GVirDomainSnapshot *snap;
+ GHashTable *snap_table;
+ int n_snaps = 0;
+ int i;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail(GVIR_IS_DOMAIN(dom), FALSE);
+ g_return_val_if_fail((error == NULL) || (*error == NULL), FALSE);
+
+ priv = dom->priv;
+
+ snap_table = g_hash_table_new_full(g_str_hash,
+ g_str_equal,
+ NULL,
+ g_object_unref);
+
+
+ n_snaps = virDomainListAllSnapshots(priv->handle, &snapshots, list_flags);
+
+ if (g_cancellable_set_error_if_cancelled(cancellable, error)) {
+ goto cleanup;
+ }
+
+ if (n_snaps < 0) {
+ gvir_set_error(error, GVIR_DOMAIN_ERROR, 0,
+ "Unable to fetch snapshots of %s",
+ gvir_domain_get_name(dom));
+ goto cleanup;
+ }
+
+ for (i = 0; i < n_snaps; i ++) {
+ if (g_cancellable_set_error_if_cancelled(cancellable, error)) {
+ goto cleanup;
+ }
+ snap = GVIR_DOMAIN_SNAPSHOT(g_object_new(GVIR_TYPE_DOMAIN_SNAPSHOT,
+ "handle", snapshots[i],
+ NULL));
+ g_hash_table_insert(snap_table,
+ (gpointer)gvir_domain_snapshot_get_name(snap),
+ snap);
+ }
+
+
+ g_mutex_lock(priv->lock);
+ if (priv->snapshots != NULL)
+ g_hash_table_unref(priv->snapshots);
+ priv->snapshots = snap_table;
+ snap_table = NULL;
+ g_mutex_unlock(priv->lock);
+
+ ret = TRUE;
+
+cleanup:
+ free(snapshots);
+ if (snap_table != NULL)
+ g_hash_table_unref(snap_table);
+ return ret;
+}
diff --git a/libvirt-gobject/libvirt-gobject-domain.h b/libvirt-gobject/libvirt-gobject-domain.h
index 38d3458..8c1a8e5 100644
--- a/libvirt-gobject/libvirt-gobject-domain.h
+++ b/libvirt-gobject/libvirt-gobject-domain.h
@@ -183,6 +183,39 @@ typedef enum {
GVIR_DOMAIN_REBOOT_GUEST_AGENT = VIR_DOMAIN_REBOOT_GUEST_AGENT,
} GVirDomainRebootFlags;
+/**
+ * GVirDomainSnapshotListFlags:
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_ALL: List all snapshots
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS: List all descendants, not just
+ * children, when listing a snapshot.
+ * For historical reasons, groups do not use contiguous bits.
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_ROOTS: Filter by snapshots with no parents, when listing a domain
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_METADATA: Filter by snapshots which have metadata
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_LEAVES: Filter by snapshots with no children
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES: Filter by snapshots that have children
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA: Filter by snapshots with no metadata
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_INACTIVE: Filter by snapshots taken while guest was shut off
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_ACTIVE: Filter by snapshots taken while guest was active, and with memory state
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY: Filter by snapshots taken while guest was active, but without memory state
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_INTERNAL: Filter by snapshots stored internal to disk images
+ * @GVIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL: Filter by snapshots that use files external to disk images
+ */
+typedef enum {
+ GVIR_DOMAIN_SNAPSHOT_LIST_ALL = 0,
+ GVIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS = VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS,
+ GVIR_DOMAIN_SNAPSHOT_LIST_ROOTS = VIR_DOMAIN_SNAPSHOT_LIST_ROOTS,
+ GVIR_DOMAIN_SNAPSHOT_LIST_METADATA = VIR_DOMAIN_SNAPSHOT_LIST_METADATA,
+ GVIR_DOMAIN_SNAPSHOT_LIST_LEAVES = VIR_DOMAIN_SNAPSHOT_LIST_LEAVES,
+ GVIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES = VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES,
+ GVIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA = VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA,
+ GVIR_DOMAIN_SNAPSHOT_LIST_INACTIVE = VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE,
+ GVIR_DOMAIN_SNAPSHOT_LIST_ACTIVE = VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE,
+ GVIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY = VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY,
+ GVIR_DOMAIN_SNAPSHOT_LIST_INTERNAL = VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL,
+ GVIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL = VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL
+} GVirDomainSnapshotListFlags;
+
+
typedef struct _GVirDomainInfo GVirDomainInfo;
struct _GVirDomainInfo
{
@@ -330,6 +363,10 @@ gvir_domain_create_snapshot(GVirDomain *dom,
guint flags,
GError **err);
+gboolean gvir_domain_fetch_snapshots(GVirDomain *dom,
+ guint list_flags,
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
#endif /* __LIBVIRT_GOBJECT_DOMAIN_H__ */
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index b781cc6..781310f 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -236,7 +236,9 @@ LIBVIRT_GOBJECT_0.1.5 {
LIBVIRT_GOBJECT_0.1.9 {
global:
+ gvir_domain_fetch_snapshots;
gvir_domain_snapshot_delete;
+ gvir_domain_snapshot_list_flags_get_type;
} LIBVIRT_GOBJECT_0.1.5;
# .... define new API here using predicted next version number ....
--
2.0.3
10 years, 4 months
[libvirt] [PATCH v2] storage: Refresh storage pool after upload
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1072653
Upon successful upload of a volume, the target volume and storage pool
were not updated to reflect any changes as a result of the upload. Make
use of the existing stream close callback mechanism to force a backend
pool refresh to occur in a separate thread once the stream closes. The
separate thread should avoid potential deadlocks if the refresh needed
to wait on some event from the event loop which is used to perform
the stream callback.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
Update since v1 - as discussed in original posting, use virThreadCreate to
generate a thread to handle the refresh callback:
http://www.redhat.com/archives/libvir-list/2014-July/msg01395.html
Avoid the Free callback function and have the thread do the memory free
as long as thread creation was successful. Thus a couple of changes to
function names were appropriate.
Understood that this can wait for 1.2.8 - figured to get it ready to go
NOTE: Still used pool refresh, since I found that without this patch
applied a pool-dumpxml displayed the same allocation/available before
and after the upload, so that data is not refreshed for each call as
was my concern over using refreshVol vs. refreshPool
# virsh pool-dumpxml default
...
<allocation unit='bytes'>33852141568</allocation>
<available unit='bytes'>110510419968</available>
...
# virsh vol-upload test-qcow2-4g.img test.img default
# virsh pool-dumpxml default
...
<allocation unit='bytes'>33852141568</allocation>
<available unit='bytes'>110510419968</available>
...
#
src/libvirt.c | 8 ++++
src/libvirt_private.syms | 1 +
src/storage/storage_driver.c | 103 +++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 3 ++
4 files changed, 115 insertions(+)
diff --git a/src/libvirt.c b/src/libvirt.c
index 143d319..992e4f2 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -13960,6 +13960,14 @@ virStorageVolDownload(virStorageVolPtr vol,
* detect any errors. The results will be unpredictable if
* another active stream is writing to the storage volume.
*
+ * When the data stream is closed whether the upload is successful
+ * or not the target storage pool will be refreshed to reflect pool
+ * and volume changes as a result of the upload. Depending on
+ * the target volume storage backend and the source stream type
+ * for a successful upload, the target volume may take on the
+ * characteristics from the source stream such as format type,
+ * capacity, and allocation.
+ *
* Returns 0, or -1 upon error.
*/
int
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e792a44..08111d4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -825,6 +825,7 @@ virFDStreamCreateFile;
virFDStreamOpen;
virFDStreamOpenFile;
virFDStreamOpenPTY;
+virFDStreamSetInternalCloseCb;
# libvirt_internal.h
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index efbe5ff..b023281 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -59,6 +59,12 @@ static virStorageDriverStatePtr driverState;
static int storageStateCleanup(void);
+typedef struct _virStorageVolStreamInfo virStorageVolStreamInfo;
+typedef virStorageVolStreamInfo *virStorageVolStreamInfoPtr;
+struct _virStorageVolStreamInfo {
+ char *pool_name;
+};
+
static void storageDriverLock(virStorageDriverStatePtr driver)
{
virMutexLock(&driver->lock);
@@ -1956,6 +1962,78 @@ storageVolDownload(virStorageVolPtr obj,
}
+/**
+ * Frees opaque data.
+ *
+ * @opaque Data to be freed.
+ */
+static void
+virStorageVolPoolRefreshDataFree(void *opaque)
+{
+ virStorageVolStreamInfoPtr cbdata = opaque;
+
+ VIR_FREE(cbdata->pool_name);
+ VIR_FREE(cbdata);
+}
+
+/**
+ * Thread to handle the pool refresh
+ *
+ * @st Pointer to stream being closed.
+ * @opaque Domain's device information structure.
+ */
+static void
+virStorageVolPoolRefreshThread(void *opaque)
+{
+
+ virStorageVolStreamInfoPtr cbdata = opaque;
+ virStoragePoolObjPtr pool = NULL;
+ virStorageBackendPtr backend;
+
+ storageDriverLock(driverState);
+ if (!(pool = virStoragePoolObjFindByName(&driverState->pools,
+ cbdata->pool_name)))
+ goto cleanup;
+
+ if (!(backend = virStorageBackendForType(pool->def->type)))
+ goto cleanup;
+
+ virStoragePoolObjClearVols(pool);
+ if (backend->refreshPool(NULL, pool) < 0)
+ VIR_DEBUG("Failed to refresh storage pool");
+
+ cleanup:
+ if (pool)
+ virStoragePoolObjUnlock(pool);
+ storageDriverUnlock(driverState);
+ virStorageVolPoolRefreshDataFree(cbdata);
+}
+
+/**
+ * Callback being called if a FDstream is closed. Will spin off a thread
+ * to perform a pool refresh.
+ *
+ * @st Pointer to stream being closed.
+ * @opaque Buffer to hold the pool name to be rereshed
+ */
+static void
+virStorageVolFDStreamCloseCb(virStreamPtr st ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virThread thread;
+
+ if (virThreadCreate(&thread, false, virStorageVolPoolRefreshThread,
+ opaque) < 0) {
+ /* Not much else can be done */
+ VIR_ERROR(_("Failed to create thread to handle pool refresh"));
+ goto error;
+ }
+ return; /* Thread will free opaque data */
+
+ error:
+ virStorageVolPoolRefreshDataFree(opaque);
+}
+
static int
storageVolUpload(virStorageVolPtr obj,
virStreamPtr stream,
@@ -1966,6 +2044,7 @@ storageVolUpload(virStorageVolPtr obj,
virStorageBackendPtr backend;
virStoragePoolObjPtr pool = NULL;
virStorageVolDefPtr vol = NULL;
+ virStorageVolStreamInfoPtr cbdata = NULL;
int ret = -1;
virCheckFlags(0, -1);
@@ -1996,11 +2075,35 @@ storageVolUpload(virStorageVolPtr obj,
goto cleanup;
}
+ /* If we have a refreshPool, use the callback routine in order to
+ * refresh the pool after the volume upload stream closes. This way
+ * we make sure the volume and pool data are refreshed without user
+ * interaction and we can just lookup the backend in the callback
+ * routine in order to call the refresh API.
+ */
+ if (backend->refreshPool) {
+ if (VIR_ALLOC(cbdata) < 0 ||
+ VIR_STRDUP(cbdata->pool_name, pool->def->name) < 0)
+ goto cleanup;
+ }
+
ret = backend->uploadVol(obj->conn, pool, vol, stream,
offset, length, flags);
+ /* Add cleanup callback - call after uploadVol since the stream
+ * is then fully set up
+ */
+ if (cbdata) {
+ virFDStreamSetInternalCloseCb(stream,
+ virStorageVolFDStreamCloseCb,
+ cbdata, NULL);
+ cbdata = NULL;
+ }
+
cleanup:
virStoragePoolObjUnlock(pool);
+ if (cbdata)
+ virStorageVolPoolRefreshDataFree(cbdata);
return ret;
}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 849ae31..e377df9 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2981,6 +2981,9 @@ of the amount of data to be uploaded. A negative value is interpreted
as an unsigned long long value to essentially include everything from
the offset to the end of the volume.
An error will occur if the I<local-file> is greater than the specified length.
+See the description for the libvirt virStorageVolUpload API for details
+regarding possible target volume and pool changes as a result of the
+pool refresh when the upload is attempted.
=item B<vol-download> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>]
[I<--length> I<bytes>] I<vol-name-or-key-or-path> I<local-file>
--
1.9.3
10 years, 4 months
[libvirt] [PATCH] Post-release version bump for new dev cycle
by Eric Blake
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the trivial rule.
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index f37c716..9dd07d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU Lesser General Public
dnl License along with this library. If not, see
dnl <http://www.gnu.org/licenses/>.
-AC_INIT([libvirt], [1.2.7], [libvir-list(a)redhat.com], [], [http://libvirt.org])
+AC_INIT([libvirt], [1.2.8], [libvir-list(a)redhat.com], [], [http://libvirt.org])
AC_CONFIG_SRCDIR([src/libvirt.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
--
1.9.3
10 years, 4 months
[libvirt] [PATCH] domtop: Remove unused variable
by Michal Privoznik
The variable 'k' in the print_cpu_usage function is not used anywhere
and can fire a warning on some compilers.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
examples/domtop/domtop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/domtop/domtop.c b/examples/domtop/domtop.c
index 204fdc3..e50988e 100644
--- a/examples/domtop/domtop.c
+++ b/examples/domtop/domtop.c
@@ -199,7 +199,7 @@ print_cpu_usage(const char *dom_name,
virTypedParameterPtr now_params,
size_t now_nparams)
{
- size_t i, j, k;
+ size_t i, j;
size_t nparams = now_nparams;
bool delim = false;
--
1.8.5.5
10 years, 4 months
[libvirt] [PATCH] domtop: Turn parse_argv into void
by Michal Privoznik
Currently, the function follows the usual pattern used in our code:
int ret = -1;
...
ret = 0;
cleanup:
return ret;
However, the function always call exit() on error, so the cleanup
label is never jumped onto. Therefore, it doesn't make any sense to
have the parse_argv function return an integer value, if it
effectively can return only value of zero.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
examples/domtop/domtop.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/examples/domtop/domtop.c b/examples/domtop/domtop.c
index af5da46..204fdc3 100644
--- a/examples/domtop/domtop.c
+++ b/examples/domtop/domtop.c
@@ -94,13 +94,12 @@ print_usage(const char *progname)
unified_progname);
}
-static int
+static void
parse_argv(int argc, char *argv[],
const char **uri,
const char **dom_name,
unsigned int *milliseconds)
{
- int ret = -1;
int arg;
unsigned long val;
char *p;
@@ -155,10 +154,6 @@ parse_argv(int argc, char *argv[],
if (argc > optind)
*dom_name = argv[optind];
-
- ret = 0;
- cleanup:
- return ret;
}
static int
@@ -368,8 +363,7 @@ main(int argc, char *argv[])
unsigned int milliseconds = 500; /* Sleep this long between two API calls */
const int connect_flags = 0; /* No connect flags for now */
- if (parse_argv(argc, argv, &uri, &dom_name, &milliseconds) < 0)
- goto cleanup;
+ parse_argv(argc, argv, &uri, &dom_name, &milliseconds);
DEBUG("Proceeding with uri=%s dom_name=%s milliseconds=%u",
uri, dom_name, milliseconds);
--
1.8.5.5
10 years, 4 months