diff --git a/fs-storage-driver.patch b/fs-storage-driver.patch index 2429882..9e6fef6 100644 --- a/fs-storage-driver.patch +++ b/fs-storage-driver.patch @@ -1,8 +1,8 @@ -Index: libvirt-0.4.4/src/storage_backend_fs.c +Index: libvirt-0.4.5/src/storage_backend_fs.c =================================================================== ---- libvirt-0.4.4.orig/src/storage_backend_fs.c -+++ libvirt-0.4.4/src/storage_backend_fs.c -@@ -455,7 +455,9 @@ virStorageBackendFileSystemIsMounted(vir +--- libvirt-0.4.5.orig/src/storage_backend_fs.c ++++ libvirt-0.4.5/src/storage_backend_fs.c +@@ -583,7 +583,9 @@ virStorageBackendFileSystemIsMounted(vir virStoragePoolObjPtr pool) { FILE *mtab; struct mntent *ent; @@ -13,7 +13,7 @@ Index: libvirt-0.4.4/src/storage_backend_fs.c if ((mtab = fopen(_PATH_MOUNTED, "r")) == NULL) { virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot read %s: %s"), -@@ -463,14 +465,27 @@ virStorageBackendFileSystemIsMounted(vir +@@ -591,14 +593,27 @@ virStorageBackendFileSystemIsMounted(vir return -1; } @@ -42,7 +42,7 @@ Index: libvirt-0.4.4/src/storage_backend_fs.c return 0; } -@@ -797,12 +812,16 @@ virStorageBackendFileSystemDelete(virCon +@@ -951,12 +966,16 @@ virStorageBackendFileSystemDelete(virCon { /* XXX delete all vols first ? */ diff --git a/libvirt-0.4.4.tar.bz2 b/libvirt-0.4.4.tar.bz2 deleted file mode 100644 index d791bfb..0000000 --- a/libvirt-0.4.4.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2f04d72f036b077c29f8af811e0e3ede9d44fe61a7e7ac4bdc35f14d297d6941 -size 2944387 diff --git a/libvirt-0.4.6.tar.bz2 b/libvirt-0.4.6.tar.bz2 new file mode 100644 index 0000000..c42f407 --- /dev/null +++ b/libvirt-0.4.6.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:135ab72ebfba0359972e0fa0b4e643c4b744a0ebc9d60b3fb5e5518b5e575355 +size 3136828 diff --git a/libvirt.changes b/libvirt.changes index 466ba88..61b5ba8 100644 --- a/libvirt.changes +++ b/libvirt.changes @@ -1,3 +1,58 @@ +------------------------------------------------------------------- +Mon Oct 6 15:36:17 MDT 2008 - jfehlig@novell.com + +- Use xend vs hypercall interface to change max mem setting + bnc#431766 + +------------------------------------------------------------------- +Wed Oct 1 16:04:21 MDT 2008 - jfehlig@novell.com + +- Enabled libvirtd listen mode in libvirtd init script. + +------------------------------------------------------------------- +Tue Sep 30 19:07:45 MDT 2008 - jfehlig@novell.com + +- Updated to version 0.4.6 + - avoid a segfault if missing qemu emulator + - reading vncdisplay from xend domain + - segfault in OpenVZ + - fix parsing of pool without a source +- Fixed bug in network interface parsing + - vif-parsing.patch submitted upstream + +------------------------------------------------------------------- +Tue Sep 16 13:02:40 MDT 2008 - jfehlig@novell.com + +- open-iscsi package required for iscsi storage backend + +------------------------------------------------------------------- +Mon Sep 15 15:59:28 MDT 2008 - jfehlig@novell.com + +- Updated to version 0.4.5 + - NETNS support for Linux containers + - unified XML domain and network parsing for all drivers + - OpenVZ features improvements + - OpenVZ and Linux containers support now default + - USB device passthrough for QEmu/KVM + - storage pool source discovery + - other bug fixes and improvements + +------------------------------------------------------------------- +Thu Sep 4 15:49:55 CEST 2008 - kwolf@suse.de + +- Added Python bindings for the snapshot functions + +------------------------------------------------------------------- +Wed Sep 3 21:09:27 CEST 2008 - kwolf@suse.de + +- Implemented listing of snapshots for Xen and in virsh + +------------------------------------------------------------------- +Tue Sep 2 13:23:22 CEST 2008 - kwolf@suse.de + +- Added snapshot support. Implemented snapshot_create/apply/delete + for Xen. + ------------------------------------------------------------------- Fri Aug 29 17:37:53 MDT 2008 - jfehlig@novell.com diff --git a/libvirt.spec b/libvirt.spec index cf2b347..4b21c53 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -1,5 +1,5 @@ # -# spec file for package libvirt (Version 0.4.4) +# spec file for package libvirt (Version 0.4.6) # # Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -48,8 +48,8 @@ Url: http://libvirt.org/ License: LGPL v2.1 or later Group: Development/Libraries/C and C++ AutoReqProv: yes -Version: 0.4.4 -Release: 28 +Version: 0.4.6 +Release: 1 Summary: A C toolkit to interract with the virtualization capabilities of Linux Requires: readline Requires: ncurses @@ -58,17 +58,20 @@ Requires: iptables Requires: cyrus-sasl Requires: lvm2 Requires: parted +#Requires: /usr/bin/qemu-img Recommends: cyrus-sasl-digestmd5 Requires: dnsmasq Requires: PolicyKit >= 0.6 Requires: socat +Requires: open-iscsi Source0: %{name}-%{version}.tar.bz2 Source1: libvirtd.init -Patch0: libvirtd-polkit.patch -Patch1: socat.patch -Patch2: libvirtd-defaults.patch -Patch3: logical-storage-driver.patch -Patch4: fs-storage-driver.patch +Patch0: socat.patch +Patch1: libvirtd-defaults.patch +Patch2: fs-storage-driver.patch +Patch3: snapshots.patch +Patch4: vif-parsing.patch +Patch5: xen-maxmem.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -164,14 +167,15 @@ Authors: %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 rm po/no.* %build %if ! %{with_xen} %define _without_xen --without-xen %endif -%if %{with_lxc} -%define _with_lxc --with-lxc +%if ! %{with_lxc} +%define _without_lxc --without-lxc %endif %if %{with_selinux} %define _with_selinux --with-selinux @@ -179,14 +183,14 @@ rm po/no.* autoreconf -f -i export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %configure %{?_without_xen} \ - %{?_with_lxc} \ + %{?_without_lxc} \ %{?_with_selinux} \ --libexecdir=%{_libdir}/%{name} \ --with-init-script=none \ --with-remote-pid-file=%{_localstatedir}/run/libvirtd.pid \ --with-xen-proxy=no \ ac_cv_path_DNSMASQ=/usr/sbin/dnsmasq \ - ac_cv_path_QEMU_IMG=/usr/bin/qemu-img \ + ac_cv_path_QEMU_IMG=/usr/bin/qemu-img-xen \ ac_cv_path_ISCSIADM=/sbin/iscsiadm make DOCS_DIR=%{_docdir}/%{name}-python EXAMPLE_DIR=%{_docdir}/%{name}-python/examples HTML_DIR=%{_docdir}/%{name} cd docs/examples ; make index.html ; cd ../.. @@ -199,6 +203,11 @@ rm -rf $RPM_BUILD_ROOT/usr/share/locale/sr@latin # for now, do not install the default network definition rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/default.xml rm -f $RPM_BUILD_ROOT%{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml +# do not package augeas config files for now +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd.aug +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/libvirtd_qemu.aug +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd.aug +rm -f $RPM_BUILD_ROOT%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/libvirt mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/libvirt rm $RPM_BUILD_ROOT%{_docdir}/%{name}/{*.c,examples.x*} @@ -253,6 +262,9 @@ rm -rf $RPM_BUILD_ROOT %if 0%{?suse_version} > 1030 %{_libdir}/%{name}/libvirt_parthelper %endif +%if %{with_lxc} +%attr(0755, root, root) %{_libdir}/%{name}/libvirt_lxc +%endif %dir %attr(0700, root, root) %{_sysconfdir}/libvirt/ %dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/ %dir %attr(0700, root, root) %{_sysconfdir}/libvirt/qemu/networks/ @@ -265,7 +277,7 @@ rm -rf $RPM_BUILD_ROOT %config %{_sysconfdir}/libvirt/qemu.conf %config %{_sysconfdir}/sasl2/libvirt.conf %if 0%{?suse_version} > 1030 -%{_datadir}/PolicyKit/policy/libvirtd.policy +%{_datadir}/PolicyKit/policy/org.libvirt.unix.policy %endif %files devel @@ -288,6 +300,37 @@ rm -rf $RPM_BUILD_ROOT %{py_sitedir}/libvirtmod* %changelog +* Mon Oct 06 2008 jfehlig@novell.com +- Use xend vs hypercall interface to change max mem setting + bnc#431766 +* Wed Oct 01 2008 jfehlig@novell.com +- Enabled libvirtd listen mode in libvirtd init script. +* Tue Sep 30 2008 jfehlig@novell.com +- Updated to version 0.4.6 + - avoid a segfault if missing qemu emulator + - reading vncdisplay from xend domain + - segfault in OpenVZ + - fix parsing of pool without a source +- Fixed bug in network interface parsing + - vif-parsing.patch submitted upstream +* Tue Sep 16 2008 jfehlig@novell.com +- open-iscsi package required for iscsi storage backend +* Mon Sep 15 2008 jfehlig@novell.com +- Updated to version 0.4.5 + - NETNS support for Linux containers + - unified XML domain and network parsing for all drivers + - OpenVZ features improvements + - OpenVZ and Linux containers support now default + - USB device passthrough for QEmu/KVM + - storage pool source discovery + - other bug fixes and improvements +* Thu Sep 04 2008 kwolf@suse.de +- Added Python bindings for the snapshot functions +* Wed Sep 03 2008 kwolf@suse.de +- Implemented listing of snapshots for Xen and in virsh +* Tue Sep 02 2008 kwolf@suse.de +- Added snapshot support. Implemented snapshot_create/apply/delete + for Xen. * Fri Aug 29 2008 jfehlig@novell.com - Fixed bugs in nfs storage pool creation/deletion * Thu Aug 28 2008 jfehlig@novell.com diff --git a/libvirtd-polkit.patch b/libvirtd-polkit.patch deleted file mode 100644 index 1baf0c3..0000000 --- a/libvirtd-polkit.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -ru a/qemud/libvirtd.policy b/qemud/libvirtd.policy ---- a/qemud/libvirtd.policy 2007-12-05 11:21:27.000000000 -0700 -+++ b/qemud/libvirtd.policy 2008-05-09 09:28:26.000000000 -0600 -@@ -36,7 +36,7 @@ - read-write mode for management, and we require user password --> - no - no -- auth_self_keep_session -+ auth_admin_keep_session - - - -\ No newline at end of file -Only in b/qemud: libvirtd.policy~ diff --git a/libvirtd.init b/libvirtd.init index 76b98c2..5af6963 100644 --- a/libvirtd.init +++ b/libvirtd.init @@ -31,7 +31,7 @@ rc_reset case "$1" in start) echo -n "Starting libvirtd " - startproc $LIBVIRTD_BIN -d + startproc $LIBVIRTD_BIN -d -l rc_status -v ;; stop) diff --git a/logical-storage-driver.patch b/logical-storage-driver.patch deleted file mode 100644 index 625d05e..0000000 --- a/logical-storage-driver.patch +++ /dev/null @@ -1,21 +0,0 @@ -Index: libvirt-0.4.4/src/storage_backend_logical.c -=================================================================== ---- libvirt-0.4.4.orig/src/storage_backend_logical.c -+++ libvirt-0.4.4/src/storage_backend_logical.c -@@ -280,7 +280,7 @@ virStorageBackendLogicalBuildPool(virCon - memset(zeros, 0, sizeof(zeros)); - - /* XXX multiple pvs */ -- if (VIR_ALLOC_N(vgargv, 1) < 0) { -+ if (VIR_ALLOC_N(vgargv, 3 + pool->def->source.ndevice) < 0) { - virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("command line")); - return -1; - } -@@ -531,6 +531,7 @@ virStorageBackend virStorageBackendLogic - .deleteVol = virStorageBackendLogicalDeleteVol, - - .poolOptions = { -+ .flags = (VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE), - .formatFromString = virStorageBackendLogicalPoolFormatFromString, - .formatToString = virStorageBackendLogicalPoolFormatToString, - }, diff --git a/snapshots.patch b/snapshots.patch new file mode 100644 index 0000000..291e80e --- /dev/null +++ b/snapshots.patch @@ -0,0 +1,1215 @@ +Index: libvirt-0.4.6/include/libvirt/libvirt.h.in +=================================================================== +--- libvirt-0.4.6.orig/include/libvirt/libvirt.h.in ++++ libvirt-0.4.6/include/libvirt/libvirt.h.in +@@ -470,6 +470,21 @@ int virDomainRestore + const char *from); + + /* ++ * Snapshots ++ */ ++int virDomainSnapshotCreate (virDomainPtr domain, ++ const char* name); ++int virDomainSnapshotApply (virDomainPtr domain, ++ const char* name); ++int virDomainSnapshotDelete (virDomainPtr domain, ++ const char* name); ++int virDomainNumOfSnapshots (virDomainPtr domain); ++int virDomainListSnapshots (virDomainPtr domain, ++ char **const names, ++ int maxnames); ++ ++ ++/* + * Domain core dump + */ + int virDomainCoreDump (virDomainPtr domain, +Index: libvirt-0.4.6/src/libvirt.c +=================================================================== +--- libvirt-0.4.6.orig/src/libvirt.c ++++ libvirt-0.4.6/src/libvirt.c +@@ -1659,6 +1659,168 @@ virDomainRestore(virConnectPtr conn, con + return -1; + } + ++ ++/** ++ * virDomainSnapshotCreate: ++ * @domain: a domain object ++ * @name: name for the new snapshot ++ * ++ * Creates a snapshot from a running domain ++ * ++ * Returns 0 in case of success and -1 in case of failure. ++ */ ++int ++virDomainSnapshotCreate(virDomainPtr domain, const char* name) ++{ ++ virConnectPtr conn; ++ ++ DEBUG("domain=%p", domain); ++ ++ if (!VIR_IS_CONNECTED_DOMAIN(domain)) { ++ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); ++ return (-1); ++ } ++ ++ conn = domain->conn; ++ if (conn->flags & VIR_CONNECT_RO) { ++ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); ++ return (-1); ++ } ++ ++ if (conn->driver->domainSnapshotCreate) ++ return conn->driver->domainSnapshotCreate(domain, name); ++ ++ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); ++ return -1; ++} ++ ++/** ++ * virDomainSnapshotApply: ++ * @domain: a domain object ++ * @name: name of the snapshot to apply ++ * ++ * Starts a domain using a given snapshot. The domain needs to be shut down ++ * before calling thsi function. ++ * ++ * Returns 0 in case of success and -1 in case of failure. ++ */ ++int ++virDomainSnapshotApply(virDomainPtr domain, const char* name) ++{ ++ virConnectPtr conn; ++ ++ DEBUG("domain=%p", domain); ++ ++ if (!VIR_IS_CONNECTED_DOMAIN(domain)) { ++ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); ++ return (-1); ++ } ++ ++ conn = domain->conn; ++ if (conn->flags & VIR_CONNECT_RO) { ++ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); ++ return (-1); ++ } ++ ++ if (conn->driver->domainSnapshotApply) ++ return conn->driver->domainSnapshotApply(domain, name); ++ ++ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); ++ return -1; ++} ++ ++/** ++ * virDomainSnapshotDelete: ++ * @domain: a domain object ++ * @name: name of the snapshot to delete ++ * ++ * Deletes a snapshot from the given domain ++ * ++ * Returns 0 in case of success and -1 in case of failure. ++ */ ++int ++virDomainSnapshotDelete(virDomainPtr domain, const char* name) ++{ ++ virConnectPtr conn; ++ ++ DEBUG("domain=%p", domain); ++ ++ if (!VIR_IS_CONNECTED_DOMAIN(domain)) { ++ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); ++ return (-1); ++ } ++ ++ conn = domain->conn; ++ if (conn->flags & VIR_CONNECT_RO) { ++ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); ++ return (-1); ++ } ++ ++ if (conn->driver->domainSnapshotDelete) ++ return conn->driver->domainSnapshotDelete(domain, name); ++ ++ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); ++ return -1; ++} ++ ++/** ++ * virDomainNumOfSnapshots: ++ * @domain: a domain object ++ * ++ * Returns the number of snapshots of the given domain or -1 in case of failure ++ */ ++int ++virDomainNumOfSnapshots(virDomainPtr domain) ++{ ++ virConnectPtr conn; ++ ++ DEBUG("domain=%p", domain); ++ ++ if (!VIR_IS_CONNECTED_DOMAIN(domain)) { ++ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); ++ return (-1); ++ } ++ ++ conn = domain->conn; ++ if (conn->driver->domainNumOfSnapshots) ++ return conn->driver->domainNumOfSnapshots(domain); ++ ++ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); ++ return -1; ++} ++ ++/** ++ * virDomainListSnapshots: ++ * @domain: a domain object ++ * @names: pointer to an array to store the snapshot names ++ * @maxnames: size of the array ++ * ++ * List the names of all snapshots of the given domain. The names are ++ * stored in the @names array. Unused array entries are set to NULL. ++ * ++ * Returns 0 in case of success and -1 in case of failure. ++ */ ++int ++virDomainListSnapshots(virDomainPtr domain, char **const names, int maxnames) ++{ ++ virConnectPtr conn; ++ ++ DEBUG("domain=%p", domain); ++ ++ if (!VIR_IS_CONNECTED_DOMAIN(domain)) { ++ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); ++ return (-1); ++ } ++ ++ conn = domain->conn; ++ if (conn->driver->domainListSnapshots) ++ return conn->driver->domainListSnapshots(domain, names, maxnames); ++ ++ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); ++ return -1; ++} ++ ++ + /** + * virDomainCoreDump: + * @domain: a domain object +Index: libvirt-0.4.6/src/driver.h +=================================================================== +--- libvirt-0.4.6.orig/src/driver.h ++++ libvirt-0.4.6/src/driver.h +@@ -146,6 +146,21 @@ typedef int + (*virDrvDomainRestore) (virConnectPtr conn, + const char *from); + typedef int ++ (*virDrvDomainSnapshotCreate) (virDomainPtr domain, ++ const char* name); ++typedef int ++ (*virDrvDomainSnapshotApply) (virDomainPtr domain, ++ const char* name); ++typedef int ++ (*virDrvDomainSnapshotDelete) (virDomainPtr domain, ++ const char* name); ++typedef int ++ (*virDrvDomainNumOfSnapshots) (virDomainPtr domain); ++typedef int ++ (*virDrvDomainListSnapshots) (virDomainPtr domain, ++ char **const names, ++ int maxnames); ++typedef int + (*virDrvDomainCoreDump) (virDomainPtr domain, + const char *to, + int flags); +@@ -352,6 +367,12 @@ struct _virDriver { + virDrvDomainMemoryPeek domainMemoryPeek; + virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; + virDrvNodeGetFreeMemory getFreeMemory; ++ ++ virDrvDomainSnapshotCreate domainSnapshotCreate; ++ virDrvDomainSnapshotApply domainSnapshotApply; ++ virDrvDomainSnapshotDelete domainSnapshotDelete; ++ virDrvDomainNumOfSnapshots domainNumOfSnapshots; ++ virDrvDomainListSnapshots domainListSnapshots; + }; + + typedef int +Index: libvirt-0.4.6/src/xen_unified.c +=================================================================== +--- libvirt-0.4.6.orig/src/xen_unified.c ++++ libvirt-0.4.6/src/xen_unified.c +@@ -869,6 +869,81 @@ xenUnifiedDomainRestore (virConnectPtr c + } + + static int ++xenUnifiedDomainSnapshotCreate(virDomainPtr domain, const char* name) ++{ ++ GET_PRIVATE(domain->conn); ++ int i; ++ ++ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) ++ if (priv->opened[i] && ++ drivers[i]->domainSnapshotCreate && ++ drivers[i]->domainSnapshotCreate(domain, name) == 0) ++ return 0; ++ ++ return -1; ++} ++ ++static int ++xenUnifiedDomainSnapshotApply(virDomainPtr domain, const char* name) ++{ ++ GET_PRIVATE(domain->conn); ++ int i; ++ ++ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) ++ if (priv->opened[i] && ++ drivers[i]->domainSnapshotApply && ++ drivers[i]->domainSnapshotApply(domain, name) == 0) ++ return 0; ++ ++ return -1; ++} ++ ++static int ++xenUnifiedDomainSnapshotDelete(virDomainPtr domain, const char* name) ++{ ++ GET_PRIVATE(domain->conn); ++ int i; ++ ++ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) ++ if (priv->opened[i] && ++ drivers[i]->domainSnapshotDelete && ++ drivers[i]->domainSnapshotDelete(domain, name) == 0) ++ return 0; ++ ++ return -1; ++} ++ ++static int ++xenUnifiedDomainNumOfSnapshots(virDomainPtr domain) ++{ ++ GET_PRIVATE(domain->conn); ++ int i; ++ ++ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) ++ if (priv->opened[i] && ++ drivers[i]->domainNumOfSnapshots) ++ return drivers[i]->domainNumOfSnapshots(domain); ++ ++ return -1; ++} ++ ++static int ++xenUnifiedDomainListSnapshots(virDomainPtr domain, char **const names, ++ int maxnames) ++{ ++ GET_PRIVATE(domain->conn); ++ int i; ++ ++ for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) ++ if (priv->opened[i] && ++ drivers[i]->domainListSnapshots && ++ drivers[i]->domainListSnapshots(domain, names, maxnames) == 0) ++ return 0; ++ ++ return -1; ++} ++ ++static int + xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags) + { + GET_PRIVATE(dom->conn); +@@ -1336,6 +1411,11 @@ static virDriver xenUnifiedDriver = { + .domainGetInfo = xenUnifiedDomainGetInfo, + .domainSave = xenUnifiedDomainSave, + .domainRestore = xenUnifiedDomainRestore, ++ .domainSnapshotCreate = xenUnifiedDomainSnapshotCreate, ++ .domainSnapshotApply = xenUnifiedDomainSnapshotApply, ++ .domainSnapshotDelete = xenUnifiedDomainSnapshotDelete, ++ .domainNumOfSnapshots = xenUnifiedDomainNumOfSnapshots, ++ .domainListSnapshots = xenUnifiedDomainListSnapshots, + .domainCoreDump = xenUnifiedDomainCoreDump, + .domainSetVcpus = xenUnifiedDomainSetVcpus, + .domainPinVcpu = xenUnifiedDomainPinVcpu, +Index: libvirt-0.4.6/src/xen_unified.h +=================================================================== +--- libvirt-0.4.6.orig/src/xen_unified.h ++++ libvirt-0.4.6/src/xen_unified.h +@@ -63,6 +63,11 @@ struct xenUnifiedDriver { + virDrvDomainGetInfo domainGetInfo; + virDrvDomainSave domainSave; + virDrvDomainRestore domainRestore; ++ virDrvDomainSnapshotCreate domainSnapshotCreate; ++ virDrvDomainSnapshotApply domainSnapshotApply; ++ virDrvDomainSnapshotDelete domainSnapshotDelete; ++ virDrvDomainNumOfSnapshots domainNumOfSnapshots; ++ virDrvDomainListSnapshots domainListSnapshots; + virDrvDomainCoreDump domainCoreDump; + virDrvDomainSetVcpus domainSetVcpus; + virDrvDomainPinVcpu domainPinVcpu; +Index: libvirt-0.4.6/src/xend_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xend_internal.c ++++ libvirt-0.4.6/src/xend_internal.c +@@ -51,6 +51,12 @@ + + #ifndef PROXY + ++static int xenDaemonDomainSnapshotCreate(virDomainPtr domain, const char* name); ++static int xenDaemonDomainSnapshotApply(virDomainPtr domain, const char* name); ++static int xenDaemonDomainSnapshotDelete(virDomainPtr domain, const char* name); ++static int xenDaemonDomainNumOfSnapshots(virDomainPtr domain); ++static int xenDaemonDomainListSnapshots(virDomainPtr domain, char **const names, int maxnames); ++ + /* + * The number of Xen scheduler parameters + */ +@@ -3070,6 +3076,87 @@ xenDaemonDomainRestore(virConnectPtr con + } + return xend_op(conn, "", "op", "restore", "file", filename, NULL); + } ++ ++static int ++xenDaemonDomainSnapshotCreate(virDomainPtr domain, const char* name) ++{ ++ if ((domain == NULL) || (name == NULL)) { ++ virXendError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); ++ return (-1); ++ } ++ return xend_op(domain->conn, domain->name, "op", ++ "snapshot_create", "name", name, NULL); ++} ++ ++static int ++xenDaemonDomainSnapshotApply(virDomainPtr domain, const char* name) ++{ ++ if ((domain == NULL) || (name == NULL)) { ++ virXendError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); ++ return (-1); ++ } ++ return xend_op(domain->conn, domain->name, "op", ++ "snapshot_apply", "name", name, NULL); ++} ++ ++static int ++xenDaemonDomainSnapshotDelete(virDomainPtr domain, const char* name) ++{ ++ if ((domain == NULL) || (name == NULL)) { ++ virXendError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); ++ return (-1); ++ } ++ return xend_op(domain->conn, domain->name, "op", ++ "snapshot_delete", "name", name, NULL); ++} ++ ++static int ++xenDaemonDomainNumOfSnapshots(virDomainPtr domain) ++{ ++ struct sexpr *root, *node, *value; ++ int i; ++ ++ root = sexpr_get(domain->conn, ++ "/xend/domain/%s?op=snapshot_list", domain->name); ++ if (root == NULL) ++ return -1; ++ ++ for (node = root, i = 0; node->kind == SEXPR_CONS; node = node->u.s.cdr) { ++ value = node->u.s.car; ++ ++ if (value->kind == SEXPR_VALUE) ++ i++; ++ } ++ ++ return i; ++} ++ ++static int ++xenDaemonDomainListSnapshots(virDomainPtr domain, char **const names, ++ int maxnames) ++{ ++ struct sexpr *root, *node, *value; ++ int i; ++ root = sexpr_get(domain->conn, ++ "/xend/domain/%s?op=snapshot_list", domain->name); ++ if (root == NULL) ++ return -1; ++ ++ for (node = root, i = 0; node->kind == SEXPR_CONS; node = node->u.s.cdr) { ++ value = node->u.s.car; ++ ++ if (value->kind == SEXPR_VALUE) { ++ names[i] = strdup(value->u.value); ++ if (++i > maxnames) ++ return 0; ++ } ++ } ++ ++ for (; i < maxnames; i++) ++ names[i] = NULL; ++ ++ return 0; ++} + #endif /* !PROXY */ + + /** +@@ -4824,6 +4911,11 @@ struct xenUnifiedDriver xenDaemonDriver + xenDaemonDomainGetInfo, /* domainGetInfo */ + xenDaemonDomainSave, /* domainSave */ + xenDaemonDomainRestore, /* domainRestore */ ++ xenDaemonDomainSnapshotCreate, /* domainSnapshotCreate */ ++ xenDaemonDomainSnapshotApply, /* domainSnapshotApply */ ++ xenDaemonDomainSnapshotDelete, /* domainSnapshotDelete */ ++ xenDaemonDomainNumOfSnapshots, /* domainNumOfSnapshots */ ++ xenDaemonDomainListSnapshots, /* domainListSnapshots */ + xenDaemonDomainCoreDump, /* domainCoreDump */ + xenDaemonDomainSetVcpus, /* domainSetVcpus */ + xenDaemonDomainPinVcpu, /* domainPinVcpu */ +Index: libvirt-0.4.6/src/proxy_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/proxy_internal.c ++++ libvirt-0.4.6/src/proxy_internal.c +@@ -66,6 +66,11 @@ struct xenUnifiedDriver xenProxyDriver = + xenProxyDomainGetInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + NULL, /* domainCoreDump */ + NULL, /* domainSetVcpus */ + NULL, /* domainPinVcpu */ +Index: libvirt-0.4.6/src/xen_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xen_internal.c ++++ libvirt-0.4.6/src/xen_internal.c +@@ -700,6 +700,11 @@ struct xenUnifiedDriver xenHypervisorDri + xenHypervisorGetDomainInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + NULL, /* domainCoreDump */ + xenHypervisorSetVcpus, /* domainSetVcpus */ + xenHypervisorPinVcpu, /* domainPinVcpu */ +Index: libvirt-0.4.6/src/xm_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xm_internal.c ++++ libvirt-0.4.6/src/xm_internal.c +@@ -105,6 +105,11 @@ struct xenUnifiedDriver xenXMDriver = { + xenXMDomainGetInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + NULL, /* domainCoreDump */ + xenXMDomainSetVcpus, /* domainSetVcpus */ + xenXMDomainPinVcpu, /* domainPinVcpu */ +Index: libvirt-0.4.6/src/xs_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xs_internal.c ++++ libvirt-0.4.6/src/xs_internal.c +@@ -66,6 +66,11 @@ struct xenUnifiedDriver xenStoreDriver = + xenStoreGetDomainInfo, /* domainGetInfo */ + NULL, /* domainSave */ + NULL, /* domainRestore */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + NULL, /* domainCoreDump */ + NULL, /* domainSetVcpus */ + NULL, /* domainPinVcpu */ +Index: libvirt-0.4.6/src/virsh.c +=================================================================== +--- libvirt-0.4.6.orig/src/virsh.c ++++ libvirt-0.4.6/src/virsh.c +@@ -1100,6 +1100,189 @@ cmdSave(vshControl *ctl, const vshCmd *c + return ret; + } + ++ ++/* ++ * "snapshot-create" command ++ */ ++static vshCmdInfo info_snapshot_create[] = { ++ {"syntax", "snapshot-create "}, ++ {"help", gettext_noop("Create a snapshot of the domain")}, ++ {"desc", gettext_noop("Create a snapshot of the domain")}, ++ {NULL, NULL} ++}; ++ ++static vshCmdOptDef opts_snapshot_create[] = { ++ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Domain name, id or uuid")}, ++ {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Name of the snapshot")}, ++ {NULL, 0, 0, NULL} ++}; ++ ++static int ++cmdSnapshotCreate(vshControl * ctl, vshCmd * cmd) ++{ ++ virDomainPtr dom; ++ char *name; ++ char *domain; ++ int ret = TRUE; ++ ++ if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) ++ return FALSE; ++ ++ if (!(name = vshCommandOptString(cmd, "name", NULL))) ++ return FALSE; ++ ++ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &domain))) ++ return FALSE; ++ ++ if (virDomainSnapshotCreate(dom, name) == 0) { ++ vshPrint(ctl, _("Snapshot %s created for domain %s\n"), name, domain); ++ } else { ++ vshError(ctl, FALSE, _("Failed to create snapshot %s for domain %s"), ++ name, domain); ++ ret = FALSE; ++ } ++ ++ virDomainFree(dom); ++ return ret; ++} ++ ++/* ++ * "snapshot-apply" command ++ */ ++static vshCmdInfo info_snapshot_apply[] = { ++ {"syntax", "snapshot-apply "}, ++ {"help", gettext_noop("Start the domain using a snapshot")}, ++ {"desc", gettext_noop("Start the domain using a snapshot")}, ++ {NULL, NULL} ++}; ++ ++static vshCmdOptDef opts_snapshot_apply[] = { ++ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Domain name, id or uuid")}, ++ {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Name of the snapshot")}, ++ {NULL, 0, 0, NULL} ++}; ++ ++static int ++cmdSnapshotApply(vshControl * ctl, vshCmd * cmd) ++{ ++ virDomainPtr dom; ++ char *name; ++ char *domain; ++ int ret = TRUE; ++ ++ if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) ++ return FALSE; ++ ++ if (!(name = vshCommandOptString(cmd, "name", NULL))) ++ return FALSE; ++ ++ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &domain))) ++ return FALSE; ++ ++ if (virDomainSnapshotApply(dom, name) == 0) { ++ vshPrint(ctl, _("Domain %s started using snapshot %s\n"), ++ domain, name); ++ } else { ++ vshError(ctl, FALSE, _("Failed to start domain %s using snapshot %s"), ++ domain, name); ++ ret = FALSE; ++ } ++ ++ virDomainFree(dom); ++ return ret; ++} ++ ++/* ++ * "snapshot-delete" command ++ */ ++static vshCmdInfo info_snapshot_delete[] = { ++ {"syntax", "snapshot-delete "}, ++ {"help", gettext_noop("Delete a snapshot from a domain")}, ++ {"desc", gettext_noop("Delete a snapshot from a domain")}, ++ {NULL, NULL} ++}; ++ ++static vshCmdOptDef opts_snapshot_delete[] = { ++ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Domain name, id or uuid")}, ++ {"name", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Name of the snapshot")}, ++ {NULL, 0, 0, NULL} ++}; ++ ++static int ++cmdSnapshotDelete(vshControl * ctl, vshCmd * cmd) ++{ ++ virDomainPtr dom; ++ char *name; ++ char *domain; ++ int ret = TRUE; ++ ++ if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) ++ return FALSE; ++ ++ if (!(name = vshCommandOptString(cmd, "name", NULL))) ++ return FALSE; ++ ++ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &domain))) ++ return FALSE; ++ ++ if (virDomainSnapshotDelete(dom, name) == 0) { ++ vshPrint(ctl, _("Snapshot %s deleted from domain %s\n"), name, domain); ++ } else { ++ vshError(ctl, FALSE, _("Failed to delete snapshot %s from domain %s"), ++ name, domain); ++ ret = FALSE; ++ } ++ ++ virDomainFree(dom); ++ return ret; ++} ++ ++/* ++ * "snapshot-list" command ++ */ ++static vshCmdInfo info_snapshot_list[] = { ++ {"syntax", "snapshot-list "}, ++ {"help", gettext_noop("List all snapshots of a domain")}, ++ {"desc", gettext_noop("List all snapshots of a domain")}, ++ {NULL, NULL} ++}; ++ ++static vshCmdOptDef opts_snapshot_list[] = { ++ {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("Domain name, id or uuid")}, ++ {NULL, 0, 0, NULL} ++}; ++ ++static int ++cmdSnapshotList(vshControl * ctl, vshCmd * cmd) ++{ ++ virDomainPtr dom; ++ char *domain; ++ char** names; ++ int num; ++ int i; ++ int ret = TRUE; ++ ++ if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) ++ return FALSE; ++ ++ if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", &domain))) ++ return FALSE; ++ ++ // TODO Display snapshot details ++ num = virDomainNumOfSnapshots(dom); ++ names = malloc(num * sizeof(*names)); ++ virDomainListSnapshots(dom, names, num); ++ ++ for (i = 0; i < num; i++) { ++ printf("%s\n", names[i]); ++ free(names[i]); ++ } ++ ++ free(names); ++ virDomainFree(dom); ++ return ret; ++} ++ + /* + * "schedinfo" command + */ +@@ -5568,6 +5751,12 @@ static const vshCmdDef commands[] = { + {"undefine", cmdUndefine, opts_undefine, info_undefine}, + {"uri", cmdURI, NULL, info_uri}, + ++ {"snapshot-create", cmdSnapshotCreate, opts_snapshot_create, info_snapshot_create}, ++ {"snapshot-apply", cmdSnapshotApply, opts_snapshot_apply, info_snapshot_apply}, ++ {"snapshot-delete", cmdSnapshotDelete, opts_snapshot_delete, info_snapshot_delete}, ++ {"snapshot-list", cmdSnapshotList, opts_snapshot_list, info_snapshot_list}, ++ ++ + {"vol-create", cmdVolCreate, opts_vol_create, info_vol_create}, + {"vol-create-as", cmdVolCreateAs, opts_vol_create_as, info_vol_create_as}, + {"vol-delete", cmdVolDelete, opts_vol_delete, info_vol_delete}, +Index: libvirt-0.4.6/src/lxc_driver.c +=================================================================== +--- libvirt-0.4.6.orig/src/lxc_driver.c ++++ libvirt-0.4.6/src/lxc_driver.c +@@ -1203,6 +1203,11 @@ static virDriver lxcDriver = { + NULL, /* domainMemoryPeek */ + NULL, /* nodeGetCellsFreeMemory */ + NULL, /* getFreeMemory */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + }; + + +Index: libvirt-0.4.6/src/openvz_driver.c +=================================================================== +--- libvirt-0.4.6.orig/src/openvz_driver.c ++++ libvirt-0.4.6/src/openvz_driver.c +@@ -1014,6 +1014,11 @@ static virDriver openvzDriver = { + NULL, /* domainMemoryPeek */ + NULL, /* nodeGetCellsFreeMemory */ + NULL, /* nodeGetFreeMemory */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + }; + + int openvzRegister(void) { +Index: libvirt-0.4.6/src/qemu_driver.c +=================================================================== +--- libvirt-0.4.6.orig/src/qemu_driver.c ++++ libvirt-0.4.6/src/qemu_driver.c +@@ -4079,6 +4079,11 @@ static virDriver qemuDriver = { + NULL, /* nodeGetCellsFreeMemory */ + NULL, /* getFreeMemory */ + #endif ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + }; + + static virNetworkDriver qemuNetworkDriver = { +Index: libvirt-0.4.6/src/remote_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/remote_internal.c ++++ libvirt-0.4.6/src/remote_internal.c +@@ -4888,6 +4888,11 @@ static virDriver driver = { + .domainMemoryPeek = remoteDomainMemoryPeek, + .nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory, + .getFreeMemory = remoteNodeGetFreeMemory, ++ .domainSnapshotCreate = NULL, ++ .domainSnapshotApply = NULL, ++ .domainSnapshotDelete = NULL, ++ .domainNumOfSnapshots = NULL, ++ .domainListSnapshots = NULL, + }; + + static virNetworkDriver network_driver = { +Index: libvirt-0.4.6/src/test.c +=================================================================== +--- libvirt-0.4.6.orig/src/test.c ++++ libvirt-0.4.6/src/test.c +@@ -1595,6 +1595,11 @@ static virDriver testDriver = { + NULL, /* domainMemoryPeek */ + testNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */ + NULL, /* getFreeMemory */ ++ NULL, /* domainSnapshotCreate */ ++ NULL, /* domainSnapshotApply */ ++ NULL, /* domainSnapshotDelete */ ++ NULL, /* domainNumOfSnapshots */ ++ NULL, /* domainListSnapshots */ + }; + + static virNetworkDriver testNetworkDriver = { +Index: libvirt-0.4.6/src/libvirt_sym.version +=================================================================== +--- libvirt-0.4.6.orig/src/libvirt_sym.version ++++ libvirt-0.4.6/src/libvirt_sym.version +@@ -35,6 +35,11 @@ + virDomainRestore; + virDomainResume; + virDomainSave; ++ virDomainSnapshotCreate; ++ virDomainSnapshotApply; ++ virDomainSnapshotDelete; ++ virDomainNumOfSnapshots; ++ virDomainListSnapshots; + virDomainCoreDump; + virDomainSetMemory; + virDomainSetMaxMemory; +Index: libvirt-0.4.6/docs/libvirt-api.xml +=================================================================== +--- libvirt-0.4.6.orig/docs/libvirt-api.xml ++++ libvirt-0.4.6/docs/libvirt-api.xml +@@ -143,6 +143,11 @@ + + + ++ ++ ++ ++ ++ + + + +@@ -1096,6 +1101,36 @@ see note above'/> + + + ++ ++ Start a shut off domain based on a previously taken snapshot ++ ++ ++ ++ ++ ++ Create a snapshot from a running domain ++ ++ ++ ++ ++ ++ Delete a snapshot from a domain ++ ++ ++ ++ ++ ++ Returns the number of snapshot a given domain has ++ ++ ++ ++ ++ Returns the names of the snapshots of a domain ++ ++ ++ ++ ++ + + Undefine a domain but does not stop it if it is running + +Index: libvirt-0.4.6/python/libvirt-py.c +=================================================================== +--- libvirt-0.4.6.orig/python/libvirt-py.c ++++ libvirt-0.4.6/python/libvirt-py.c +@@ -25,6 +25,25 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * ++libvirt_virDomainSnapshotDelete(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ int c_retval; ++ virDomainPtr domain; ++ PyObject *pyobj_domain; ++ char * name; ++ ++ if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainSnapshotDelete", &pyobj_domain, &name)) ++ return(NULL); ++ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ ++ c_retval = virDomainSnapshotDelete(domain, name); ++LIBVIRT_END_ALLOW_THREADS; ++ py_retval = libvirt_intWrap((int) c_retval); ++ return(py_retval); ++} ++ ++PyObject * + libvirt_virStorageVolGetKey(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + const char * c_retval; +@@ -520,24 +539,6 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * +-libvirt_virNetworkGetName(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { +- PyObject *py_retval; +- const char * c_retval; +- virNetworkPtr network; +- PyObject *pyobj_network; +- +- if (!PyArg_ParseTuple(args, (char *)"O:virNetworkGetName", &pyobj_network)) +- return(NULL); +- network = (virNetworkPtr) PyvirNetwork_Get(pyobj_network); +-LIBVIRT_BEGIN_ALLOW_THREADS; +- +- c_retval = virNetworkGetName(network); +-LIBVIRT_END_ALLOW_THREADS; +- py_retval = libvirt_charPtrConstWrap((const char *) c_retval); +- return(py_retval); +-} +- +-PyObject * + libvirt_virNetworkDestroy(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + int c_retval; +@@ -771,6 +772,25 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * ++libvirt_virDomainSnapshotCreate(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ int c_retval; ++ virDomainPtr domain; ++ PyObject *pyobj_domain; ++ char * name; ++ ++ if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainSnapshotCreate", &pyobj_domain, &name)) ++ return(NULL); ++ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ ++ c_retval = virDomainSnapshotCreate(domain, name); ++LIBVIRT_END_ALLOW_THREADS; ++ py_retval = libvirt_intWrap((int) c_retval); ++ return(py_retval); ++} ++ ++PyObject * + libvirt_virNetworkDefineXML(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + virNetworkPtr c_retval; +@@ -806,6 +826,24 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * ++libvirt_virDomainNumOfSnapshots(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ int c_retval; ++ virDomainPtr domain; ++ PyObject *pyobj_domain; ++ ++ if (!PyArg_ParseTuple(args, (char *)"O:virDomainNumOfSnapshots", &pyobj_domain)) ++ return(NULL); ++ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ ++ c_retval = virDomainNumOfSnapshots(domain); ++LIBVIRT_END_ALLOW_THREADS; ++ py_retval = libvirt_intWrap((int) c_retval); ++ return(py_retval); ++} ++ ++PyObject * + libvirt_virDomainResume(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + int c_retval; +@@ -824,6 +862,25 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * ++libvirt_virDomainSnapshotApply(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ int c_retval; ++ virDomainPtr domain; ++ PyObject *pyobj_domain; ++ char * name; ++ ++ if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainSnapshotApply", &pyobj_domain, &name)) ++ return(NULL); ++ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ ++ c_retval = virDomainSnapshotApply(domain, name); ++LIBVIRT_END_ALLOW_THREADS; ++ py_retval = libvirt_intWrap((int) c_retval); ++ return(py_retval); ++} ++ ++PyObject * + libvirt_virConnectGetHostname(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + char * c_retval; +@@ -897,6 +954,24 @@ LIBVIRT_END_ALLOW_THREADS; + } + + PyObject * ++libvirt_virNetworkGetName(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ const char * c_retval; ++ virNetworkPtr network; ++ PyObject *pyobj_network; ++ ++ if (!PyArg_ParseTuple(args, (char *)"O:virNetworkGetName", &pyobj_network)) ++ return(NULL); ++ network = (virNetworkPtr) PyvirNetwork_Get(pyobj_network); ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ ++ c_retval = virNetworkGetName(network); ++LIBVIRT_END_ALLOW_THREADS; ++ py_retval = libvirt_charPtrConstWrap((const char *) c_retval); ++ return(py_retval); ++} ++ ++PyObject * + libvirt_virConnectGetCapabilities(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + char * c_retval; +Index: libvirt-0.4.6/python/libvirt-py.h +=================================================================== +--- libvirt-0.4.6.orig/python/libvirt-py.h ++++ libvirt-0.4.6/python/libvirt-py.h +@@ -1,6 +1,7 @@ + /* Generated */ + + PyObject * libvirt_virStoragePoolGetXMLDesc(PyObject *self, PyObject *args); ++PyObject * libvirt_virDomainSnapshotDelete(PyObject *self, PyObject *args); + PyObject * libvirt_virStorageVolGetKey(PyObject *self, PyObject *args); + PyObject * libvirt_virConnectClose(PyObject *self, PyObject *args); + PyObject * libvirt_virDomainDefineXML(PyObject *self, PyObject *args); +@@ -28,7 +29,6 @@ PyObject * libvirt_virConnectNumOfNetwor + PyObject * libvirt_virStorageVolGetName(PyObject *self, PyObject *args); + PyObject * libvirt_virStoragePoolLookupByUUIDString(PyObject *self, PyObject *args); + PyObject * libvirt_virDomainGetXMLDesc(PyObject *self, PyObject *args); +-PyObject * libvirt_virNetworkGetName(PyObject *self, PyObject *args); + PyObject * libvirt_virNetworkDestroy(PyObject *self, PyObject *args); + PyObject * libvirt_virStoragePoolLookupByName(PyObject *self, PyObject *args); + PyObject * libvirt_virNetworkGetBridgeName(PyObject *self, PyObject *args); +@@ -42,13 +42,17 @@ PyObject * libvirt_virNetworkSetAutostar + PyObject * libvirt_virDomainGetMaxMemory(PyObject *self, PyObject *args); + PyObject * libvirt_virResetLastError(PyObject *self, PyObject *args); + PyObject * libvirt_virStoragePoolFree(PyObject *self, PyObject *args); ++PyObject * libvirt_virDomainSnapshotCreate(PyObject *self, PyObject *args); + PyObject * libvirt_virNetworkDefineXML(PyObject *self, PyObject *args); + PyObject * libvirt_virConnResetLastError(PyObject *self, PyObject *args); ++PyObject * libvirt_virDomainNumOfSnapshots(PyObject *self, PyObject *args); + PyObject * libvirt_virDomainResume(PyObject *self, PyObject *args); ++PyObject * libvirt_virDomainSnapshotApply(PyObject *self, PyObject *args); + PyObject * libvirt_virConnectGetHostname(PyObject *self, PyObject *args); + PyObject * libvirt_virDomainGetName(PyObject *self, PyObject *args); + PyObject * libvirt_virNetworkGetXMLDesc(PyObject *self, PyObject *args); + PyObject * libvirt_virConnectNumOfStoragePools(PyObject *self, PyObject *args); ++PyObject * libvirt_virNetworkGetName(PyObject *self, PyObject *args); + PyObject * libvirt_virConnectGetCapabilities(PyObject *self, PyObject *args); + PyObject * libvirt_virDomainLookupByName(PyObject *self, PyObject *args); + PyObject * libvirt_virConnectFindStoragePoolSources(PyObject *self, PyObject *args); +Index: libvirt-0.4.6/python/libvirt.py +=================================================================== +--- libvirt-0.4.6.orig/python/libvirt.py ++++ libvirt-0.4.6/python/libvirt.py +@@ -359,6 +359,12 @@ class virDomain: + ret = libvirtmod.virDomainGetName(self._o) + return ret + ++ def numOfSnapshots(self): ++ """Returns the number of snapshot a given domain has """ ++ ret = libvirtmod.virDomainNumOfSnapshots(self._o) ++ if ret == -1: raise libvirtError ('virDomainNumOfSnapshots() failed', dom=self) ++ return ret ++ + def reboot(self, flags): + """Reboot a domain, the domain object is still usable there + after but the domain OS is being stopped for a restart. +@@ -433,6 +439,24 @@ class virDomain: + if ret == -1: raise libvirtError ('virDomainShutdown() failed', dom=self) + return ret + ++ def snapshotApply(self, name): ++ """Start a shut off domain based on a previously taken snapshot """ ++ ret = libvirtmod.virDomainSnapshotApply(self._o, name) ++ if ret == -1: raise libvirtError ('virDomainSnapshotApply() failed', dom=self) ++ return ret ++ ++ def snapshotCreate(self, name): ++ """Create a snapshot from a running domain """ ++ ret = libvirtmod.virDomainSnapshotCreate(self._o, name) ++ if ret == -1: raise libvirtError ('virDomainSnapshotCreate() failed', dom=self) ++ return ret ++ ++ def snapshotDelete(self, name): ++ """Delete a snapshot from a domain """ ++ ret = libvirtmod.virDomainSnapshotDelete(self._o, name) ++ if ret == -1: raise libvirtError ('virDomainSnapshotDelete() failed', dom=self) ++ return ret ++ + def suspend(self): + """Suspends an active domain, the process is frozen without + further access to CPU resources and I/O but the memory used +@@ -489,6 +513,12 @@ class virDomain: + ret = libvirtmod.virDomainInterfaceStats(self._o, path) + return ret + ++ def listSnapshots(self): ++ """Returns the names of the snapshots of a domain """ ++ ret = libvirtmod.virDomainListSnapshots(self._o) ++ if ret is None: raise libvirtError ('virDomainListSnapshots() failed', dom=self) ++ return ret ++ + def pinVcpu(self, vcpu, cpumap): + """Dynamically change the real CPUs which can be allocated to + a virtual CPU. This function requires privileged access to +Index: libvirt-0.4.6/python/libvir.c +=================================================================== +--- libvirt-0.4.6.orig/python/libvir.c ++++ libvirt-0.4.6/python/libvir.c +@@ -1466,6 +1466,35 @@ libvirt_virStoragePoolLookupByUUID(PyObj + return(py_retval); + } + ++static PyObject * ++libvirt_virDomainListSnapshots(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { ++ PyObject *py_retval; ++ int i, num; ++ char** names; ++ virDomainPtr domain; ++ PyObject *pyobj_domain; ++ ++ if (!PyArg_ParseTuple(args, (char *)"O:virDomainListSnapshots", ++ &pyobj_domain)) ++ return(NULL); ++ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ++ ++LIBVIRT_BEGIN_ALLOW_THREADS; ++ num = virDomainNumOfSnapshots(domain); ++ names = malloc(num * sizeof(*names)); ++ virDomainListSnapshots(domain, names, num); ++LIBVIRT_END_ALLOW_THREADS; ++ ++ py_retval = PyList_New(num); ++ for (i = 0; i < num; i++) { ++ PyList_SetItem(py_retval, i, Py_BuildValue("s", names[i])); ++ free(names[i]); ++ } ++ free(names); ++ ++ return(py_retval); ++} ++ + + + /************************************************************************ +@@ -1502,6 +1531,7 @@ static PyMethodDef libvirtMethods[] = { + {(char *) "virDomainSetSchedulerParameters", libvirt_virDomainSetSchedulerParameters, METH_VARARGS, NULL}, + {(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS, NULL}, + {(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL}, ++ {(char *) "virDomainListSnapshots", libvirt_virDomainListSnapshots, METH_VARARGS, NULL}, + {(char *) "virConnectListStoragePools", libvirt_virConnectListStoragePools, METH_VARARGS, NULL}, + {(char *) "virConnectListDefinedStoragePools", libvirt_virConnectListDefinedStoragePools, METH_VARARGS, NULL}, + {(char *) "virStoragePoolGetAutostart", libvirt_virStoragePoolGetAutostart, METH_VARARGS, NULL}, +Index: libvirt-0.4.6/python/libvirt-python-api.xml +=================================================================== +--- libvirt-0.4.6.orig/python/libvirt-python-api.xml ++++ libvirt-0.4.6/python/libvirt-python-api.xml +@@ -135,6 +135,11 @@ + + + ++ ++ Returns the names of the snapshots of a domain ++ ++ ++ + + list the storage pools, stores the pointers to the names in @names + +Index: libvirt-0.4.6/python/generator.py +=================================================================== +--- libvirt-0.4.6.orig/python/generator.py ++++ libvirt-0.4.6/python/generator.py +@@ -306,6 +306,7 @@ skip_impl = ( + 'virDomainSetSchedulerParameters', + 'virDomainGetVcpus', + 'virDomainPinVcpu', ++ 'virDomainListSnapshots', + 'virStoragePoolGetUUID', + 'virStoragePoolGetUUIDString', + 'virStoragePoolLookupByUUID', diff --git a/socat.patch b/socat.patch index 6c01965..0d19d61 100644 --- a/socat.patch +++ b/socat.patch @@ -1,8 +1,8 @@ -Index: libvirt-0.4.4/src/remote_internal.c +Index: libvirt-0.4.5/src/remote_internal.c =================================================================== ---- libvirt-0.4.4.orig/src/remote_internal.c -+++ libvirt-0.4.4/src/remote_internal.c -@@ -660,9 +660,22 @@ doRemoteOpen (virConnectPtr conn, +--- libvirt-0.4.5.orig/src/remote_internal.c ++++ libvirt-0.4.5/src/remote_internal.c +@@ -623,9 +623,22 @@ doRemoteOpen (virConnectPtr conn, cmd_argv[j++] = strdup ("none"); } cmd_argv[j++] = strdup (priv->hostname); @@ -27,4 +27,4 @@ Index: libvirt-0.4.4/src/remote_internal.c + } cmd_argv[j++] = 0; assert (j == nr_args); - for (j = 0; j < (nr_args-1); j++) { + for (j = 0; j < (nr_args-1); j++) diff --git a/vif-parsing.patch b/vif-parsing.patch new file mode 100644 index 0000000..a392340 --- /dev/null +++ b/vif-parsing.patch @@ -0,0 +1,13 @@ +Index: libvirt-0.4.6/src/xend_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xend_internal.c ++++ libvirt-0.4.6/src/xend_internal.c +@@ -1890,6 +1890,8 @@ xenDaemonParseSxprNets(virConnectPtr con + prev->next = net; + else + def->nets = net; ++ ++ prev = net; + vif_index++; + } + } diff --git a/xen-maxmem.patch b/xen-maxmem.patch new file mode 100644 index 0000000..cb9244e --- /dev/null +++ b/xen-maxmem.patch @@ -0,0 +1,13 @@ +Index: libvirt-0.4.6/src/xen_internal.c +=================================================================== +--- libvirt-0.4.6.orig/src/xen_internal.c ++++ libvirt-0.4.6/src/xen_internal.c +@@ -695,7 +695,7 @@ struct xenUnifiedDriver xenHypervisorDri + xenHypervisorDestroyDomain, /* domainDestroy */ + xenHypervisorDomainGetOSType, /* domainGetOSType */ + xenHypervisorGetMaxMemory, /* domainGetMaxMemory */ +- xenHypervisorSetMaxMemory, /* domainSetMaxMemory */ ++ NULL, /* domainSetMaxMemory */ + NULL, /* domainSetMemory */ + xenHypervisorGetDomainInfo, /* domainGetInfo */ + NULL, /* domainSave */