Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
daemon/remote.c | 311 ++++++++++++++++++++++++
daemon/remote_dispatch_args.h | 9 +
daemon/remote_dispatch_prototypes.h | 72 ++++++
daemon/remote_dispatch_ret.h | 7 +
daemon/remote_dispatch_table.h | 45 ++++
include/libvirt/libvirt.h.in | 62 +++++
include/libvirt/virterror.h | 5 +-
python/generator.py | 3 +
python/typewrappers.c | 15 ++
python/typewrappers.h | 10 +
src/datatypes.c | 122 ++++++++++
src/datatypes.h | 25 ++
src/driver.h | 47 ++++
src/esx/esx_driver.c | 9 +
src/libvirt.c | 456 +++++++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 10 +
src/lxc/lxc_driver.c | 9 +
src/opennebula/one_driver.c | 9 +
src/openvz/openvz_driver.c | 9 +
src/phyp/phyp_driver.c | 9 +
src/qemu/qemu_driver.c | 9 +
src/remote/remote_driver.c | 309 ++++++++++++++++++++++++
src/remote/remote_protocol.c | 181 ++++++++++++++
src/remote/remote_protocol.h | 145 +++++++++++
src/remote/remote_protocol.x | 97 ++++++++-
src/test/test_driver.c | 9 +
src/uml/uml_driver.c | 9 +
src/util/virterror.c | 15 ++
src/vbox/vbox_tmpl.c | 9 +
src/xen/xen_driver.c | 9 +
src/xenapi/xenapi_driver.c | 9 +
32 files changed, 2044 insertions(+), 2 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 67162d5..fd8ac32 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -67,6 +67,7 @@ static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn,
remote_no
static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn,
remote_nonnull_storage_vol vol);
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret
secret);
static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter
nwfilter);
+static virDomainSnapshotPtr get_nonnull_domain_snapshot (virConnectPtr conn,
remote_nonnull_domain_snapshot snapshot);
static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr
net_src);
static void make_nonnull_interface (remote_nonnull_interface *interface_dst,
virInterfacePtr interface_src);
@@ -75,6 +76,7 @@ static void make_nonnull_storage_vol (remote_nonnull_storage_vol
*vol_dst, virSt
static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst,
virNodeDevicePtr dev_src);
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr
secret_src);
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *net_dst, virNWFilterPtr
nwfilter_src);
+static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst,
virDomainSnapshotPtr snapshot_src);
#include "remote_dispatch_prototypes.h"
@@ -5766,6 +5768,298 @@ remoteDispatchDomainMigrateSetMaxDowntime(struct qemud_server
*server ATTRIBUTE_
return 0;
}
+static int
+remoteDispatchDomainSnapshotCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_create_xml_args *args,
+ remote_domain_snapshot_create_xml_ret *ret)
+{
+ virDomainSnapshotPtr snapshot;
+ virDomainPtr domain;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ snapshot = virDomainSnapshotCreateXML(domain, args->xml_desc, args->flags);
+ if (snapshot == NULL) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ make_nonnull_domain_snapshot(&ret->snap, snapshot);
+
+ virDomainSnapshotFree(snapshot);
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_dump_xml_args *args,
+ remote_domain_snapshot_dump_xml_ret *ret)
+{
+ virDomainSnapshotPtr snapshot;
+
+ snapshot = get_nonnull_domain_snapshot(conn, args->snap);
+ if (snapshot == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ /* remoteDispatchClientRequest will free this. */
+ ret->xml = virDomainSnapshotGetXMLDesc(snapshot, args->flags);
+ if (!ret->xml) {
+ virDomainSnapshotFree(snapshot);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainSnapshotFree(snapshot);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotNum (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_num_args *args,
+ remote_domain_snapshot_num_ret *ret)
+{
+ virDomainPtr domain;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ ret->num = virDomainSnapshotNum(domain, args->flags);
+ if (ret->num == -1) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotListNames (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_list_names_args *args,
+ remote_domain_snapshot_list_names_ret *ret)
+{
+ virDomainPtr domain;
+
+ if (args->nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) {
+ remoteDispatchFormatError (rerr, "%s",
+ _("nameslen >
REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX"));
+ return -1;
+ }
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ /* Allocate return buffer. */
+ if (VIR_ALLOC_N(ret->names.names_val, args->nameslen) < 0) {
+ virDomainFree(domain);
+ remoteDispatchOOMError(rerr);
+ return -1;
+ }
+
+ ret->names.names_len = virDomainSnapshotListNames(domain,
+ ret->names.names_val,
+ args->nameslen,
+ args->flags);
+ if (ret->names.names_len == -1) {
+ virDomainFree(domain);
+ VIR_FREE(ret->names.names_val);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_lookup_by_name_args
*args,
+ remote_domain_snapshot_lookup_by_name_ret
*ret)
+{
+ virDomainSnapshotPtr snapshot;
+ virDomainPtr domain;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ snapshot = virDomainSnapshotLookupByName(domain, args->name, args->flags);
+ if (snapshot == NULL) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ make_nonnull_domain_snapshot (&ret->snap, snapshot);
+
+ virDomainSnapshotFree(snapshot);
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainHasCurrentSnapshot(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_has_current_snapshot_args *args,
+ remote_domain_has_current_snapshot_ret *ret)
+{
+ virDomainPtr domain;
+ int result;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ result = virDomainHasCurrentSnapshot(domain, args->flags);
+ if (result < 0) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ ret->result = result;
+
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_current_args *args,
+ remote_domain_snapshot_current_ret *ret)
+{
+ virDomainSnapshotPtr snapshot;
+ virDomainPtr domain;
+
+ domain = get_nonnull_domain(conn, args->domain);
+ if (domain == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ snapshot = virDomainSnapshotCurrent(domain, args->flags);
+ if (snapshot == NULL) {
+ virDomainFree(domain);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ make_nonnull_domain_snapshot(&ret->snap, snapshot);
+
+ virDomainSnapshotFree(snapshot);
+ virDomainFree(domain);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainRevertToSnapshot (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_revert_to_snapshot_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainSnapshotPtr snapshot;
+
+ snapshot = get_nonnull_domain_snapshot(conn, args->snap);
+ if (snapshot == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainRevertToSnapshot(snapshot, args->flags) == -1) {
+ virDomainSnapshotFree(snapshot);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainSnapshotFree(snapshot);
+
+ return 0;
+}
+
+static int
+remoteDispatchDomainSnapshotDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
+ struct qemud_client *client ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_snapshot_delete_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainSnapshotPtr snapshot;
+
+ snapshot = get_nonnull_domain_snapshot(conn, args->snap);
+ if (snapshot == NULL) {
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ if (virDomainSnapshotDelete(snapshot, args->flags) == -1) {
+ virDomainSnapshotFree(snapshot);
+ remoteDispatchConnError(rerr, conn);
+ return -1;
+ }
+
+ virDomainSnapshotFree(snapshot);
+
+ return 0;
+}
+
static int
remoteDispatchDomainEventsRegisterAny (struct qemud_server *server ATTRIBUTE_UNUSED,
@@ -6076,6 +6370,16 @@ get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter
nwfilter)
return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
}
+static virDomainSnapshotPtr
+get_nonnull_domain_snapshot (virConnectPtr conn, remote_nonnull_domain_snapshot
snapshot)
+{
+ virDomainPtr domain;
+ domain = get_nonnull_domain(conn, snapshot.domain);
+ if (domain == NULL)
+ return NULL;
+ return virGetDomainSnapshot(domain, snapshot.name);
+}
+
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
@@ -6135,3 +6439,10 @@ make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst,
virNWFilterPtr nwf
nwfilter_dst->name = strdup (nwfilter_src->name);
memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
}
+
+static void
+make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst,
virDomainSnapshotPtr snapshot_src)
+{
+ snapshot_dst->name = strdup(snapshot_src->name);
+ make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain);
+}
diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h
index b188e6e..cc49c31 100644
--- a/daemon/remote_dispatch_args.h
+++ b/daemon/remote_dispatch_args.h
@@ -151,3 +151,12 @@
remote_list_nwfilters_args val_remote_list_nwfilters_args;
remote_nwfilter_define_xml_args val_remote_nwfilter_define_xml_args;
remote_nwfilter_undefine_args val_remote_nwfilter_undefine_args;
+ remote_domain_snapshot_create_xml_args val_remote_domain_snapshot_create_xml_args;
+ remote_domain_snapshot_dump_xml_args val_remote_domain_snapshot_dump_xml_args;
+ remote_domain_snapshot_num_args val_remote_domain_snapshot_num_args;
+ remote_domain_snapshot_list_names_args val_remote_domain_snapshot_list_names_args;
+ remote_domain_snapshot_lookup_by_name_args
val_remote_domain_snapshot_lookup_by_name_args;
+ remote_domain_has_current_snapshot_args val_remote_domain_has_current_snapshot_args;
+ remote_domain_snapshot_current_args val_remote_domain_snapshot_current_args;
+ remote_domain_revert_to_snapshot_args val_remote_domain_revert_to_snapshot_args;
+ remote_domain_snapshot_delete_args val_remote_domain_snapshot_delete_args;
diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h
index e155c69..54ad5a7 100644
--- a/daemon/remote_dispatch_prototypes.h
+++ b/daemon/remote_dispatch_prototypes.h
@@ -282,6 +282,14 @@ static int remoteDispatchDomainGetVcpus(
remote_error *err,
remote_domain_get_vcpus_args *args,
remote_domain_get_vcpus_ret *ret);
+static int remoteDispatchDomainHasCurrentSnapshot(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_has_current_snapshot_args *args,
+ remote_domain_has_current_snapshot_ret *ret);
static int remoteDispatchDomainInterfaceStats(
struct qemud_server *server,
struct qemud_client *client,
@@ -434,6 +442,14 @@ static int remoteDispatchDomainResume(
remote_error *err,
remote_domain_resume_args *args,
void *ret);
+static int remoteDispatchDomainRevertToSnapshot(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_revert_to_snapshot_args *args,
+ void *ret);
static int remoteDispatchDomainSave(
struct qemud_server *server,
struct qemud_client *client,
@@ -490,6 +506,62 @@ static int remoteDispatchDomainShutdown(
remote_error *err,
remote_domain_shutdown_args *args,
void *ret);
+static int remoteDispatchDomainSnapshotCreateXml(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_create_xml_args *args,
+ remote_domain_snapshot_create_xml_ret *ret);
+static int remoteDispatchDomainSnapshotCurrent(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_current_args *args,
+ remote_domain_snapshot_current_ret *ret);
+static int remoteDispatchDomainSnapshotDelete(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_delete_args *args,
+ void *ret);
+static int remoteDispatchDomainSnapshotDumpXml(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_dump_xml_args *args,
+ remote_domain_snapshot_dump_xml_ret *ret);
+static int remoteDispatchDomainSnapshotListNames(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_list_names_args *args,
+ remote_domain_snapshot_list_names_ret *ret);
+static int remoteDispatchDomainSnapshotLookupByName(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_lookup_by_name_args *args,
+ remote_domain_snapshot_lookup_by_name_ret *ret);
+static int remoteDispatchDomainSnapshotNum(
+ struct qemud_server *server,
+ struct qemud_client *client,
+ virConnectPtr conn,
+ remote_message_header *hdr,
+ remote_error *err,
+ remote_domain_snapshot_num_args *args,
+ remote_domain_snapshot_num_ret *ret);
static int remoteDispatchDomainSuspend(
struct qemud_server *server,
struct qemud_client *client,
diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h
index b134f25..358bc58 100644
--- a/daemon/remote_dispatch_ret.h
+++ b/daemon/remote_dispatch_ret.h
@@ -125,3 +125,10 @@
remote_num_of_nwfilters_ret val_remote_num_of_nwfilters_ret;
remote_list_nwfilters_ret val_remote_list_nwfilters_ret;
remote_nwfilter_define_xml_ret val_remote_nwfilter_define_xml_ret;
+ remote_domain_snapshot_create_xml_ret val_remote_domain_snapshot_create_xml_ret;
+ remote_domain_snapshot_dump_xml_ret val_remote_domain_snapshot_dump_xml_ret;
+ remote_domain_snapshot_num_ret val_remote_domain_snapshot_num_ret;
+ remote_domain_snapshot_list_names_ret val_remote_domain_snapshot_list_names_ret;
+ remote_domain_snapshot_lookup_by_name_ret
val_remote_domain_snapshot_lookup_by_name_ret;
+ remote_domain_has_current_snapshot_ret val_remote_domain_has_current_snapshot_ret;
+ remote_domain_snapshot_current_ret val_remote_domain_snapshot_current_ret;
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index 24756d7..96a30f9 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -912,3 +912,48 @@
.args_filter = (xdrproc_t) xdr_remote_nwfilter_undefine_args,
.ret_filter = (xdrproc_t) xdr_void,
},
+{ /* DomainSnapshotCreateXml => 182 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotCreateXml,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_create_xml_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_create_xml_ret,
+},
+{ /* DomainSnapshotDumpXml => 183 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotDumpXml,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_ret,
+},
+{ /* DomainSnapshotNum => 184 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotNum,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_num_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_num_ret,
+},
+{ /* DomainSnapshotListNames => 185 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotListNames,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_list_names_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_list_names_ret,
+},
+{ /* DomainSnapshotLookupByName => 186 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotLookupByName,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_ret,
+},
+{ /* DomainHasCurrentSnapshot => 187 */
+ .fn = (dispatch_fn) remoteDispatchDomainHasCurrentSnapshot,
+ .args_filter = (xdrproc_t) xdr_remote_domain_has_current_snapshot_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_has_current_snapshot_ret,
+},
+{ /* DomainSnapshotCurrent => 188 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotCurrent,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_current_args,
+ .ret_filter = (xdrproc_t) xdr_remote_domain_snapshot_current_ret,
+},
+{ /* DomainRevertToSnapshot => 189 */
+ .fn = (dispatch_fn) remoteDispatchDomainRevertToSnapshot,
+ .args_filter = (xdrproc_t) xdr_remote_domain_revert_to_snapshot_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
+{ /* DomainSnapshotDelete => 190 */
+ .fn = (dispatch_fn) remoteDispatchDomainSnapshotDelete,
+ .args_filter = (xdrproc_t) xdr_remote_domain_snapshot_delete_args,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 7cb483e..a9f434b 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1374,6 +1374,7 @@ typedef enum {
VIR_DOMAIN_EVENT_STARTED_BOOTED = 0, /* Normal startup from boot */
VIR_DOMAIN_EVENT_STARTED_MIGRATED = 1, /* Incoming migration from another host */
VIR_DOMAIN_EVENT_STARTED_RESTORED = 2, /* Restored from a state file */
+ VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT = 3, /* Restored from snapshot */
} virDomainEventStartedDetailType;
/**
@@ -1410,6 +1411,7 @@ typedef enum {
VIR_DOMAIN_EVENT_STOPPED_MIGRATED = 3, /* Migrated off to another host */
VIR_DOMAIN_EVENT_STOPPED_SAVED = 4, /* Saved to a state file */
VIR_DOMAIN_EVENT_STOPPED_FAILED = 5, /* Host emulator/mgmt failed */
+ VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT = 6, /* offline snapshot loaded */
} virDomainEventStoppedDetailType;
@@ -1861,6 +1863,66 @@ int virDomainGetJobInfo(virDomainPtr dom,
virDomainJobInfoPtr info);
int virDomainAbortJob(virDomainPtr dom);
+/**
+ * virDomainSnapshot:
+ *
+ * a virDomainSnapshot is a private structure representing a snapshot of
+ * a domain.
+ */
+typedef struct _virDomainSnapshot virDomainSnapshot;
+
+/**
+ * virDomainSnapshotPtr:
+ *
+ * a virDomainSnapshotPtr is pointer to a virDomainSnapshot private structure,
+ * and is the type used to reference a domain snapshot in the API.
+ */
+typedef virDomainSnapshot *virDomainSnapshotPtr;
+
+/* Take a snapshot of the current VM state */
+virDomainSnapshotPtr virDomainSnapshotCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags);
+
+/* Dump the XML of a snapshot */
+char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+/* Return the number of snapshots for this domain */
+int virDomainSnapshotNum(virDomainPtr domain, unsigned int flags);
+
+/* Get the names of all snapshots for this domain */
+int virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
+ unsigned int flags);
+
+/* Get a handle to a named snapshot */
+virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
+ const char *name,
+ unsigned int flags);
+
+/* Check whether a domain has a snapshot which is currently used */
+int virDomainHasCurrentSnapshot(virDomainPtr domain, unsigned flags);
+
+/* Get a handle to the current snapshot */
+virDomainSnapshotPtr virDomainSnapshotCurrent(virDomainPtr domain,
+ unsigned int flags);
+
+/* Revert the domain to a point-in-time snapshot. The
+ * state of the guest after this call will be the state
+ * of the guest when the snapshot in question was taken
+ */
+int virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+/* Deactivate a snapshot */
+typedef enum {
+ VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN = (1 << 0),
+} virDomainSnapshotDeleteFlags;
+
+int virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+int virDomainSnapshotFree(virDomainSnapshotPtr snapshot);
/* A generic callback definition. Specific events usually have a customization
* with extra parameters */
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index f69d07e..3bbb293 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -71,7 +71,8 @@ typedef enum {
VIR_FROM_CPU, /* Error from CPU driver */
VIR_FROM_XENAPI, /* Error from XenAPI */
VIR_FROM_NWFILTER, /* Error from network filter driver */
- VIR_FROM_HOOK /* Error from Synchronous hooks */
+ VIR_FROM_HOOK, /* Error from Synchronous hooks */
+ VIR_FROM_DOMAIN_SNAPSHOT, /* Error from domain snapshot */
} virErrorDomain;
@@ -183,6 +184,8 @@ typedef enum {
VIR_ERR_MIGRATE_PERSIST_FAILED, /* a migration worked, but making the
VM persist on the dest host failed */
VIR_ERR_HOOK_SCRIPT_FAILED, /* a synchronous hook script failed */
+ VIR_ERR_INVALID_DOMAIN_SNAPSHOT, /* invalid domain snapshot */
+ VIR_ERR_NO_DOMAIN_SNAPSHOT, /* domain snapshot not found */
} virErrorNumber;
/**
diff --git a/python/generator.py b/python/generator.py
index a24e122..cb9f3d9 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -241,6 +241,8 @@ py_types = {
'const virStreamPtr': ('O', "virStream",
"virStreamPtr", "virStreamPtr"),
'virStream *': ('O', "virStream",
"virStreamPtr", "virStreamPtr"),
'const virStream *': ('O', "virStream",
"virStreamPtr", "virStreamPtr"),
+
+ 'virDomainSnapshotPtr': ('O', "virDomainSnapshot",
"virDomainSnapshotPtr", "virDomainSnapshotPtr"),
}
py_return_types = {
@@ -317,6 +319,7 @@ skip_impl = (
'virNodeListDevices',
'virNodeDeviceListCaps',
'virConnectBaselineCPU',
+ 'virDomainSnapshotListNames',
)
diff --git a/python/typewrappers.c b/python/typewrappers.c
index b33822c..d0f703c 100644
--- a/python/typewrappers.c
+++ b/python/typewrappers.c
@@ -228,6 +228,21 @@ libvirt_virStreamPtrWrap(virStreamPtr node)
}
PyObject *
+libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node)
+{
+ PyObject *ret;
+
+ if (node == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) node, (char *)
"virDomainSnapshotPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
libvirt_virEventHandleCallbackWrap(virEventHandleCallback node)
{
PyObject *ret;
diff --git a/python/typewrappers.h b/python/typewrappers.h
index 8e1998e..c0e69d8 100644
--- a/python/typewrappers.h
+++ b/python/typewrappers.h
@@ -101,6 +101,15 @@ typedef struct {
} PyvirStream_Object;
+#define PyvirDomainSnapshot_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyvirDomainSnapshot_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ virDomainSnapshotPtr obj;
+} PyvirDomainSnapshot_Object;
+
+
#define PyvirEventHandleCallback_Get(v) (((v) == Py_None) ? NULL : \
(((PyvirEventHandleCallback_Object *)(v))->obj))
@@ -155,6 +164,7 @@ PyObject * libvirt_virVoidPtrWrap(void* node);
PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node);
PyObject * libvirt_virSecretPtrWrap(virSecretPtr node);
PyObject * libvirt_virStreamPtrWrap(virStreamPtr node);
+PyObject * libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node);
/* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl):
diff --git a/src/datatypes.c b/src/datatypes.c
index a361da6..c514f41 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -129,6 +129,20 @@ virSecretFreeName(void *secret_, const char *name ATTRIBUTE_UNUSED)
}
/**
+ * 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:
*
* Allocates a new hypervisor connection structure
@@ -337,6 +351,7 @@ virGetDomain(virConnectPtr conn, const char *name, const unsigned char
*uuid) {
ret->id = -1;
if (uuid != NULL)
memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN);
+ ret->snapshots = virHashCreate(20);
if (virHashAddEntry(conn->domains, name, ret) < 0) {
virMutexUnlock(&conn->lock);
@@ -389,6 +404,8 @@ virReleaseDomain(virDomainPtr domain) {
domain->magic = -1;
domain->id = -1;
VIR_FREE(domain->name);
+ if (domain->snapshots != NULL)
+ virHashFree(domain->snapshots, (virHashDeallocator)
virDomainSnapshotFreeName);
VIR_FREE(domain);
if (conn) {
@@ -1504,3 +1521,108 @@ virUnrefNWFilter(virNWFilterPtr pool) {
virMutexUnlock(&pool->conn->lock);
return (refs);
}
+
+
+virDomainSnapshotPtr
+virGetDomainSnapshot(virDomainPtr domain, const char *name)
+{
+ virDomainSnapshotPtr ret = NULL;
+
+ if ((!VIR_IS_DOMAIN(domain)) || (name == NULL)) {
+ virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(NULL);
+ }
+ 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(domain->conn, 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);
+ }
+ ret->refs++;
+ virMutexUnlock(&domain->conn->lock);
+ return(ret);
+
+ error:
+ if (ret != NULL) {
+ VIR_FREE(ret->name);
+ VIR_FREE(ret);
+ }
+ return(NULL);
+}
+
+
+static void
+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(domain->conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("snapshot missing from domain hash
table"));
+ domain = NULL;
+ }
+
+ snapshot->magic = -1;
+ VIR_FREE(snapshot->name);
+ VIR_FREE(snapshot);
+
+ if (domain) {
+ DEBUG("unref domain %p %d", domain, domain->refs);
+ domain->refs--;
+ if (domain->refs == 0) {
+ virReleaseDomain(domain);
+ /* Already unlocked mutex */
+ return;
+ }
+ virMutexUnlock(&domain->conn->lock);
+ }
+}
+
+int
+virUnrefDomainSnapshot(virDomainSnapshotPtr snapshot)
+{
+ int refs;
+
+ if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+ virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(-1);
+ }
+
+ virMutexLock(&snapshot->domain->conn->lock);
+ DEBUG("unref snapshot %p %s %d", snapshot, snapshot->name,
snapshot->refs);
+ snapshot->refs--;
+ refs = snapshot->refs;
+ if (refs == 0) {
+ virReleaseDomainSnapshot(snapshot);
+ /* Already unlocked mutex */
+ return (0);
+ }
+
+ virMutexUnlock(&snapshot->domain->conn->lock);
+ return (refs);
+}
diff --git a/src/datatypes.h b/src/datatypes.h
index 4663c9c..bbeb7cf 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -130,6 +130,15 @@
# define VIR_IS_NWFILTER(obj) ((obj) && (obj)->magic==VIR_NWFILTER_MAGIC)
# define VIR_IS_CONNECTED_NWFILTER(obj) (VIR_IS_NWFILTER(obj) &&
VIR_IS_CONNECT((obj)->conn))
+/**
+ * VIR_SNAPSHOT_MAGIC:
+ *
+ * magic value used to protect the API when pointers to snapshot structures
+ * are passed down by the users.
+ */
+# define VIR_SNAPSHOT_MAGIC 0x6666DEAD
+# define VIR_IS_SNAPSHOT(obj) ((obj) &&
(obj)->magic==VIR_SNAPSHOT_MAGIC)
+# define VIR_IS_DOMAIN_SNAPSHOT(obj) (VIR_IS_SNAPSHOT(obj) &&
VIR_IS_DOMAIN((obj)->domain))
/**
* _virConnect:
@@ -202,6 +211,7 @@ 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 */
};
/**
@@ -304,6 +314,17 @@ struct _virStream {
void *privateData;
};
+/**
+ * _virDomainSnapshot
+ *
+ * Internal structure associated with a domain snapshot
+ */
+struct _virDomainSnapshot {
+ unsigned int magic;
+ int refs;
+ char *name;
+ virDomainPtr domain;
+};
/************************************************************************
* *
@@ -368,4 +389,8 @@ virNWFilterPtr virGetNWFilter(virConnectPtr conn,
const unsigned char *uuid);
int virUnrefNWFilter(virNWFilterPtr pool);
+virDomainSnapshotPtr virGetDomainSnapshot(virDomainPtr domain,
+ const char *name);
+int virUnrefDomainSnapshot(virDomainSnapshotPtr pool);
+
#endif
diff --git a/src/driver.h b/src/driver.h
index 8f86463..ef54b5e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -402,6 +402,44 @@ typedef int
(*virDrvDomainEventDeregisterAny)(virConnectPtr conn,
int callbackID);
+typedef virDomainSnapshotPtr
+ (*virDrvDomainSnapshotCreateXML)(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags);
+
+typedef char *
+ (*virDrvDomainSnapshotDumpXML)(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+typedef int
+ (*virDrvDomainSnapshotNum)(virDomainPtr domain, unsigned int flags);
+
+typedef int
+ (*virDrvDomainSnapshotListNames)(virDomainPtr domain, char **names,
+ int nameslen,
+ unsigned int flags);
+
+typedef virDomainSnapshotPtr
+ (*virDrvDomainSnapshotLookupByName)(virDomainPtr domain,
+ const char *name,
+ unsigned int flags);
+
+typedef int
+ (*virDrvDomainHasCurrentSnapshot)(virDomainPtr domain, unsigned int flags);
+
+typedef virDomainSnapshotPtr
+ (*virDrvDomainSnapshotCurrent)(virDomainPtr domain,
+ unsigned int flags);
+
+typedef int
+ (*virDrvDomainRevertToSnapshot)(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+typedef int
+ (*virDrvDomainSnapshotDelete)(virDomainSnapshotPtr snapshot,
+ unsigned int flags);
+
+
/**
* _virDriver:
*
@@ -499,6 +537,15 @@ struct _virDriver {
virDrvDomainMigrateSetMaxDowntime domainMigrateSetMaxDowntime;
virDrvDomainEventRegisterAny domainEventRegisterAny;
virDrvDomainEventDeregisterAny domainEventDeregisterAny;
+ virDrvDomainSnapshotCreateXML domainSnapshotCreateXML;
+ virDrvDomainSnapshotDumpXML domainSnapshotDumpXML;
+ virDrvDomainSnapshotNum domainSnapshotNum;
+ virDrvDomainSnapshotListNames domainSnapshotListNames;
+ virDrvDomainSnapshotLookupByName domainSnapshotLookupByName;
+ virDrvDomainHasCurrentSnapshot domainHasCurrentSnapshot;
+ virDrvDomainSnapshotCurrent domainSnapshotCurrent;
+ virDrvDomainRevertToSnapshot domainRevertToSnapshot;
+ virDrvDomainSnapshotDelete domainSnapshotDelete;
};
typedef int
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index 7a92c4d..c7c248e 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -3389,6 +3389,15 @@ static virDriver esxDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
diff --git a/src/libvirt.c b/src/libvirt.c
index 5247fe7..25e358c 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -683,6 +683,31 @@ virLibNWFilterError(virNWFilterPtr pool, virErrorNumber error,
}
/**
+ * virLibDomainSnapshotError:
+ * @snapshot: the snapshot if available
+ * @error: the error number
+ * @info: extra information string
+ *
+ * Handle an error at the domain snapshot level
+ */
+static void
+virLibDomainSnapshotError(virDomainSnapshotPtr snapshot, virErrorNumber error, const char
*info)
+{
+ virConnectPtr conn = NULL;
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK)
+ return;
+
+ errmsg = virErrorMsg(error, info);
+ if (error != VIR_ERR_INVALID_DOMAIN_SNAPSHOT)
+ conn = snapshot->domain->conn;
+
+ virRaiseError(conn, NULL, NULL, VIR_FROM_DOMAIN_SNAPSHOT, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/**
* virRegisterNetworkDriver:
* @driver: pointer to a network driver block
*
@@ -12136,3 +12161,434 @@ error:
virDispatchError(conn);
return -1;
}
+
+/**
+ * virDomainSnapshotCreateXML:
+ * @domain: a domain object
+ * @xmlDesc: string containing an XML description of the domain
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Creates a new snapshot of a domain based on the snapshot xml
+ * contained in xmlDesc.
+ *
+ * Returns an (opaque) virDomainSnapshotPtr on success, NULL on failure.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ DEBUG("domain=%p, xmlDesc=%s, flags=%u", domain, xmlDesc, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return NULL;
+ }
+
+ conn = domain->conn;
+ if (conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->domainSnapshotCreateXML) {
+ virDomainSnapshotPtr ret;
+ ret = conn->driver->domainSnapshotCreateXML(domain, xmlDesc, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+/**
+ * virDomainSnapshotGetXMLDesc:
+ * @snapshot: a domain snapshot object
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Provide an XML description of the domain snapshot.
+ *
+ * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
+ * the caller must free() the returned value.
+ */
+char *
+virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ DEBUG("snapshot=%p, flags=%d", snapshot, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+ virLibDomainSnapshotError(NULL, VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+ __FUNCTION__);
+ virDispatchError(NULL);
+ return (NULL);
+ }
+
+ conn = snapshot->domain->conn;
+
+ if ((conn->flags & VIR_CONNECT_RO) && (flags &
VIR_DOMAIN_XML_SECURE)) {
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED,
+ _("virDomainSnapshotGetXMLDesc with secure flag"));
+ goto error;
+ }
+
+ flags &= VIR_DOMAIN_XML_FLAGS_MASK;
+
+ if (conn->driver->domainSnapshotDumpXML) {
+ char *ret;
+ ret = conn->driver->domainSnapshotDumpXML(snapshot, flags);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+/**
+ * virDomainSnapshotNum:
+ * @domain: a domain object
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Provides the number of domain snapshots for this domain..
+ *
+ * Returns the number of domain snapshost found or -1 in case of error.
+ */
+int
+virDomainSnapshotNum(virDomainPtr domain, unsigned int flags)
+{
+ virConnectPtr conn;
+ DEBUG("domain=%p", domain);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = domain->conn;
+ if (conn->driver->domainSnapshotNum) {
+ int ret = conn->driver->domainSnapshotNum(domain, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virDomainSnapshotListNames:
+ * @domain: a domain object
+ * @names: array to collect the list of names of snapshots
+ * @nameslen: size of @names
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Collect the list of domain snapshots for the given domain, and store
+ * their names in @names. Caller is responsible for freeing each member
+ * of the array.
+ *
+ * Returns the number of domain snapshots found or -1 in case of error.
+ */
+int
+virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ DEBUG("domain=%p, names=%p, nameslen=%d, flags=%u",
+ domain, names, nameslen, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = domain->conn;
+
+ if ((names == NULL) || (nameslen < 0)) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->domainSnapshotListNames) {
+ int ret = conn->driver->domainSnapshotListNames(domain, names,
+ nameslen, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virDomainSnapshotLookupByName:
+ * @domain: a domain object
+ * @name: name for the domain snapshot
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Try to lookup a domain snapshot based on its name.
+ *
+ * Returns a domain snapshot object or NULL in case of failure. If the
+ * domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
+ * error is raised.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotLookupByName(virDomainPtr domain,
+ const char *name,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ DEBUG("domain=%p, name=%s, flags=%u", domain, name, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (NULL);
+ }
+
+ conn = domain->conn;
+
+ if (name == NULL) {
+ virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ if (conn->driver->domainSnapshotLookupByName) {
+ virDomainSnapshotPtr dom;
+ dom = conn->driver->domainSnapshotLookupByName(domain, name, flags);
+ if (!dom)
+ goto error;
+ return dom;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+/**
+ * virDomainHasCurrentSnapshot:
+ * @domain: pointer to the domain object
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Determine if the domain has a current snapshot.
+ *
+ * Returns 1 if such snapshot exists, 0 if it doesn't, -1 on error.
+ */
+int
+virDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
+{
+ virConnectPtr conn;
+ DEBUG("domain=%p, flags=%u", domain, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainHasCurrentSnapshot) {
+ int ret = conn->driver->domainHasCurrentSnapshot(domain, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virDomainSnapshotCurrent:
+ * @domain: a domain object
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Get the current snapshot for a domain, if any.
+ *
+ * Returns a domain snapshot object or NULL in case of failure. If the
+ * current domain snapshot cannot be found, then the VIR_ERR_NO_DOMAIN_SNAPSHOT
+ * error is raised.
+ */
+virDomainSnapshotPtr
+virDomainSnapshotCurrent(virDomainPtr domain,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+ DEBUG("domain=%p, flags=%u", domain, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return (NULL);
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainSnapshotCurrent) {
+ virDomainSnapshotPtr snap;
+ snap = conn->driver->domainSnapshotCurrent(domain, flags);
+ if (!snap)
+ goto error;
+ return snap;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return NULL;
+}
+
+/**
+ * virDomainRevertToSnapshot
+ * @snapshot: a domain snapshot object
+ * @flags: unused flag parameters; callers should pass 0
+ *
+ * Revert the domain to a given snapshot.
+ *
+ * Returns 0 if the creation is successful, -1 on error.
+ */
+int
+virDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ DEBUG("snapshot=%p, flags=%u", snapshot, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+ virLibDomainSnapshotError(NULL, VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+ __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = snapshot->domain->conn;
+
+ if (conn->driver->domainRevertToSnapshot) {
+ int ret = conn->driver->domainRevertToSnapshot(snapshot, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virDomainSnapshotDelete
+ * @snapshot: a domain snapshot object
+ * @flags: flag parameters
+ *
+ * Delete the snapshot.
+ *
+ * If @flags is 0, then just this snapshot is deleted, and changes from
+ * this snapshot are automatically pushed to children snapshots. If
+ * flags is VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, then this snapshot
+ * and any children snapshots are deleted.
+ *
+ * Returns 0 if the snapshot was successfully deleted, -1 on error.
+ */
+int
+virDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ DEBUG("snapshot=%p, flags=%u", snapshot, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+ virLibDomainSnapshotError(NULL, VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+ __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ conn = snapshot->domain->conn;
+
+ if (conn->driver->domainSnapshotDelete) {
+ int ret = conn->driver->domainSnapshotDelete(snapshot, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+/**
+ * virDomainSnapshotFree:
+ * @snapshot: a domain snapshot object
+ *
+ * Free the domain snapshot object. The snapshot itself is not modified.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainSnapshotFree(virDomainSnapshotPtr snapshot)
+{
+ DEBUG("snapshot=%p", snapshot);
+
+ virResetLastError();
+
+ if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
+ virLibDomainSnapshotError(NULL, VIR_ERR_INVALID_DOMAIN_SNAPSHOT,
+ __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ if (virUnrefDomainSnapshot(snapshot) < 0) {
+ virDispatchError(NULL);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 878eda3..86aacd7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -109,6 +109,7 @@ virGetStream;
virUnrefStream;
virGetNWFilter;
virUnrefNWFilter;
+virGetDomainSnapshot;
# domain_conf.h
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 2f812a1..370abc4 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -378,6 +378,16 @@ LIBVIRT_0.7.8 {
virNWFilterRef;
virNWFilterDefineXML;
virNWFilterUndefine;
+ virDomainSnapshotCreateXML;
+ virDomainSnapshotGetXMLDesc;
+ virDomainSnapshotNum;
+ virDomainSnapshotListNames;
+ virDomainSnapshotLookupByName;
+ virDomainHasCurrentSnapshot;
+ virDomainSnapshotCurrent;
+ virDomainRevertToSnapshot;
+ virDomainSnapshotDelete;
+ virDomainSnapshotFree;
} LIBVIRT_0.7.7;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9caefa1..c718d82 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2538,6 +2538,15 @@ static virDriver lxcDriver = {
NULL, /* domainMigrateSetMaxDowntime */
lxcDomainEventRegisterAny, /* domainEventRegisterAny */
lxcDomainEventDeregisterAny, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
static virStateDriver lxcStateDriver = {
diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c
index e901a03..1767b8b 100644
--- a/src/opennebula/one_driver.c
+++ b/src/opennebula/one_driver.c
@@ -792,6 +792,15 @@ static virDriver oneDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
static virStateDriver oneStateDriver = {
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index 6176577..a7e9ac2 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -1544,6 +1544,15 @@ static virDriver openvzDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
int openvzRegister(void) {
diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c
index 4f7efdb..4b1a35f 100644
--- a/src/phyp/phyp_driver.c
+++ b/src/phyp/phyp_driver.c
@@ -1651,6 +1651,15 @@ virDriver phypDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
int
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 70d2781..02ed95f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10312,6 +10312,15 @@ static virDriver qemuDriver = {
qemuDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */
qemuDomainEventRegisterAny, /* domainEventRegisterAny */
qemuDomainEventDeregisterAny, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 3b8be21..b9f6371 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -254,6 +254,7 @@ static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn,
remote_no
static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn,
remote_nonnull_storage_vol vol);
static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn,
remote_nonnull_node_device dev);
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret
secret);
+static virDomainSnapshotPtr get_nonnull_domain_snapshot (virDomainPtr domain,
remote_nonnull_domain_snapshot snapshot);
static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr
net_src);
static void make_nonnull_interface (remote_nonnull_interface *interface_dst,
virInterfacePtr interface_src);
@@ -261,6 +262,7 @@ static void make_nonnull_storage_pool (remote_nonnull_storage_pool
*pool_dst, vi
static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst,
virStorageVolPtr vol_src);
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr
secret_src);
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr
nwfilter_src);
+static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst,
virDomainSnapshotPtr snapshot_src);
void remoteDomainEventFired(int watch, int fd, int event, void *data);
void remoteDomainEventQueueFlush(int timer, void *opaque);
/*----------------------------------------------------------------------*/
@@ -8301,6 +8303,291 @@ done:
return rv;
}
+static virDomainSnapshotPtr
+remoteDomainSnapshotCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ virDomainSnapshotPtr snapshot = NULL;
+ remote_domain_snapshot_create_xml_args args;
+ remote_domain_snapshot_create_xml_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.domain, domain);
+ args.xml_desc = (char *) xmlDesc;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML,
+ (xdrproc_t) xdr_remote_domain_snapshot_create_xml_args, (char *)
&args,
+ (xdrproc_t) xdr_remote_domain_snapshot_create_xml_ret, (char *) &ret)
== -1)
+ goto done;
+
+ snapshot = get_nonnull_domain_snapshot(domain, ret.snap);
+ xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_create_xml_ret, (char *)
&ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return snapshot;
+}
+
+
+static char *
+remoteDomainSnapshotDumpXML(virDomainSnapshotPtr snapshot, unsigned int flags)
+{
+ char *rv = NULL;
+ remote_domain_snapshot_dump_xml_args args;
+ remote_domain_snapshot_dump_xml_ret ret;
+ struct private_data *priv = snapshot->domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain_snapshot(&args.snap, snapshot);
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (snapshot->domain->conn, priv, 0,
REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML,
+ (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_args, (char *) &args,
+ (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_ret, (char *) &ret) ==
-1)
+ goto done;
+
+ /* Caller frees. */
+ rv = ret.xml;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static int
+remoteDomainSnapshotNum (virDomainPtr domain, unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_snapshot_num_args args;
+ remote_domain_snapshot_num_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain (&args.domain, domain);
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM,
+ (xdrproc_t) xdr_remote_domain_snapshot_num_args, (char *) &args,
+ (xdrproc_t) xdr_remote_domain_snapshot_num_ret, (char *) &ret) == -1)
+ goto done;
+
+ rv = ret.num;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static int
+remoteDomainSnapshotListNames (virDomainPtr domain, char **const names,
+ int nameslen, unsigned int flags)
+{
+ int rv = -1;
+ int i;
+ remote_domain_snapshot_list_names_args args;
+ remote_domain_snapshot_list_names_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ if (nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) {
+ errorf (domain->conn, VIR_ERR_RPC,
+ _("too many remote domain snapshot names: %d > %d"),
+ nameslen, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX);
+ goto done;
+ }
+
+ make_nonnull_domain(&args.domain, domain);
+ args.nameslen = nameslen;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES,
+ (xdrproc_t) xdr_remote_domain_snapshot_list_names_args, (char *)
&args,
+ (xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret)
== -1)
+ goto done;
+
+ if (ret.names.names_len > nameslen) {
+ errorf (domain->conn, VIR_ERR_RPC,
+ _("too many remote domain snapshots: %d > %d"),
+ ret.names.names_len, nameslen);
+ goto cleanup;
+ }
+
+ /* This call is caller-frees (although that isn't clear from
+ * the documentation). However xdr_free will free up both the
+ * names and the list of pointers, so we have to strdup the
+ * names here.
+ */
+ for (i = 0; i < ret.names.names_len; ++i) {
+ names[i] = strdup (ret.names.names_val[i]);
+
+ if (names[i] == NULL) {
+ for (--i; i >= 0; --i)
+ VIR_FREE(names[i]);
+
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ rv = ret.names.names_len;
+
+cleanup:
+ xdr_free ((xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static virDomainSnapshotPtr
+remoteDomainSnapshotLookupByName (virDomainPtr domain, const char *name,
+ unsigned int flags)
+{
+ virDomainSnapshotPtr snapshot = NULL;
+ remote_domain_snapshot_lookup_by_name_args args;
+ remote_domain_snapshot_lookup_by_name_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain(&args.domain, domain);
+ args.name = (char *) name;
+ args.flags = flags;
+
+ memset (&ret, 0, sizeof ret);
+ if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME,
+ (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_args, (char *)
&args,
+ (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)
&ret) == -1)
+ goto done;
+
+ snapshot = get_nonnull_domain_snapshot (domain, ret.snap);
+ xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)
&ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return snapshot;
+}
+
+
+static int
+remoteDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_has_current_snapshot_args args;
+ remote_domain_has_current_snapshot_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain(&args.domain, domain);
+ args.flags = flags;
+
+ if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT,
+ (xdrproc_t) xdr_remote_domain_has_current_snapshot_args, (char *)
&args,
+ (xdrproc_t) xdr_remote_domain_has_current_snapshot_ret, (char *) &ret)
== -1)
+ goto done;
+
+ rv = ret.result;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static virDomainSnapshotPtr
+remoteDomainSnapshotCurrent(virDomainPtr domain,
+ unsigned int flags)
+{
+ virDomainSnapshotPtr snapshot = NULL;
+ remote_domain_snapshot_current_args args;
+ remote_domain_snapshot_current_ret ret;
+ struct private_data *priv = domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain(&args.domain, domain);
+ args.flags = flags;
+
+ memset(&ret, 0, sizeof ret);
+ if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT,
+ (xdrproc_t) xdr_remote_domain_snapshot_current_args, (char *) &args,
+ (xdrproc_t) xdr_remote_domain_snapshot_current_ret, (char *) &ret) ==
-1)
+ goto done;
+
+ snapshot = get_nonnull_domain_snapshot(domain, ret.snap);
+ xdr_free((xdrproc_t) &xdr_remote_domain_snapshot_current_ret, (char *)
&ret);
+
+done:
+ remoteDriverUnlock(priv);
+ return snapshot;
+}
+
+
+static int
+remoteDomainRevertToSnapshot (virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_revert_to_snapshot_args args;
+ struct private_data *priv = snapshot->domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain_snapshot(&args.snap, snapshot);
+ args.flags = flags;
+
+ if (call (snapshot->domain->conn, priv, 0,
REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT,
+ (xdrproc_t) xdr_remote_domain_revert_to_snapshot_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
+static int
+remoteDomainSnapshotDelete (virDomainSnapshotPtr snapshot,
+ unsigned int flags)
+{
+ int rv = -1;
+ remote_domain_snapshot_delete_args args;
+ struct private_data *priv = snapshot->domain->conn->privateData;
+
+ remoteDriverLock(priv);
+
+ make_nonnull_domain_snapshot(&args.snap, snapshot);
+ args.flags = flags;
+
+ if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE,
+ (xdrproc_t) xdr_remote_domain_snapshot_delete_args, (char *) &args,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto done;
+
+ rv = 0;
+
+done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
static int remoteDomainEventRegisterAny(virConnectPtr conn,
virDomainPtr dom,
@@ -9671,6 +9958,12 @@ get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter
nwfilter)
return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
}
+static virDomainSnapshotPtr
+get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot
snapshot)
+{
+ return virGetDomainSnapshot(domain, snapshot.name);
+}
+
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
@@ -9726,6 +10019,13 @@ make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst,
virNWFilterPtr nwf
memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
}
+static void
+make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst,
virDomainSnapshotPtr snapshot_src)
+{
+ snapshot_dst->name = snapshot_src->name;
+ make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain);
+}
+
/*----------------------------------------------------------------------*/
unsigned long remoteVersion(void)
@@ -9818,6 +10118,15 @@ static virDriver remote_driver = {
remoteDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */
remoteDomainEventRegisterAny, /* domainEventRegisterAny */
remoteDomainEventDeregisterAny, /* domainEventDeregisterAny */
+ remoteDomainSnapshotCreateXML, /* domainSnapshotCreateXML */
+ remoteDomainSnapshotDumpXML, /* domainSnapshotDumpXML */
+ remoteDomainSnapshotNum, /* domainSnapshotNum */
+ remoteDomainSnapshotListNames, /* domainSnapshotListNames */
+ remoteDomainSnapshotLookupByName, /* domainSnapshotLookupByName */
+ remoteDomainHasCurrentSnapshot, /* domainHasCurrentSnapshot */
+ remoteDomainSnapshotCurrent, /* domainSnapshotCurrent */
+ remoteDomainRevertToSnapshot, /* domainRevertToSnapshot */
+ remoteDomainSnapshotDelete, /* domainSnapshotDelete */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index f252d85..7afe13d 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -128,6 +128,17 @@ xdr_remote_nonnull_secret (XDR *xdrs, remote_nonnull_secret *objp)
}
bool_t
+xdr_remote_nonnull_domain_snapshot (XDR *xdrs, remote_nonnull_domain_snapshot *objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+ return FALSE;
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_domain (XDR *xdrs, remote_domain *objp)
{
@@ -3289,6 +3300,176 @@ xdr_remote_domain_event_graphics_msg (XDR *xdrs,
remote_domain_event_graphics_ms
}
bool_t
+xdr_remote_domain_snapshot_create_xml_args (XDR *xdrs,
remote_domain_snapshot_create_xml_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->xml_desc))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_create_xml_ret (XDR *xdrs,
remote_domain_snapshot_create_xml_ret *objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_dump_xml_args (XDR *xdrs, remote_domain_snapshot_dump_xml_args
*objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_dump_xml_ret (XDR *xdrs, remote_domain_snapshot_dump_xml_ret
*objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_num_args (XDR *xdrs, remote_domain_snapshot_num_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_num_ret (XDR *xdrs, remote_domain_snapshot_num_ret *objp)
+{
+
+ if (!xdr_int (xdrs, &objp->num))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_list_names_args (XDR *xdrs,
remote_domain_snapshot_list_names_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->nameslen))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_list_names_ret (XDR *xdrs,
remote_domain_snapshot_list_names_ret *objp)
+{
+ char **objp_cpp0 = (char **) (void *) &objp->names.names_val;
+
+ if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len,
REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX,
+ sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_lookup_by_name_args (XDR *xdrs,
remote_domain_snapshot_lookup_by_name_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_lookup_by_name_ret (XDR *xdrs,
remote_domain_snapshot_lookup_by_name_ret *objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_has_current_snapshot_args (XDR *xdrs,
remote_domain_has_current_snapshot_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_has_current_snapshot_ret (XDR *xdrs,
remote_domain_has_current_snapshot_ret *objp)
+{
+
+ if (!xdr_int (xdrs, &objp->result))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_current_args (XDR *xdrs, remote_domain_snapshot_current_args
*objp)
+{
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->domain))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_current_ret (XDR *xdrs, remote_domain_snapshot_current_ret
*objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_revert_to_snapshot_args (XDR *xdrs,
remote_domain_revert_to_snapshot_args *objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_snapshot_delete_args (XDR *xdrs, remote_domain_snapshot_delete_args
*objp)
+{
+
+ if (!xdr_remote_nonnull_domain_snapshot (xdrs, &objp->snap))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->flags))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
{
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index d898502..fb65211 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -42,6 +42,7 @@ typedef remote_nonnull_string *remote_string;
#define REMOTE_AUTH_SASL_DATA_MAX 65536
#define REMOTE_AUTH_TYPE_LIST_MAX 20
#define REMOTE_DOMAIN_MEMORY_STATS_MAX 1024
+#define REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX 1024
#define REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX 65536
#define REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX 65536
#define REMOTE_SECURITY_MODEL_MAX VIR_SECURITY_MODEL_BUFLEN
@@ -103,6 +104,12 @@ struct remote_nonnull_secret {
};
typedef struct remote_nonnull_secret remote_nonnull_secret;
+struct remote_nonnull_domain_snapshot {
+ remote_nonnull_string name;
+ remote_nonnull_domain domain;
+};
+typedef struct remote_nonnull_domain_snapshot remote_nonnull_domain_snapshot;
+
typedef remote_nonnull_domain *remote_domain;
typedef remote_nonnull_network *remote_network;
@@ -1860,6 +1867,101 @@ struct remote_domain_event_graphics_msg {
} subject;
};
typedef struct remote_domain_event_graphics_msg remote_domain_event_graphics_msg;
+
+struct remote_domain_snapshot_create_xml_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string xml_desc;
+ int flags;
+};
+typedef struct remote_domain_snapshot_create_xml_args
remote_domain_snapshot_create_xml_args;
+
+struct remote_domain_snapshot_create_xml_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+typedef struct remote_domain_snapshot_create_xml_ret
remote_domain_snapshot_create_xml_ret;
+
+struct remote_domain_snapshot_dump_xml_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+typedef struct remote_domain_snapshot_dump_xml_args
remote_domain_snapshot_dump_xml_args;
+
+struct remote_domain_snapshot_dump_xml_ret {
+ remote_nonnull_string xml;
+};
+typedef struct remote_domain_snapshot_dump_xml_ret remote_domain_snapshot_dump_xml_ret;
+
+struct remote_domain_snapshot_num_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+typedef struct remote_domain_snapshot_num_args remote_domain_snapshot_num_args;
+
+struct remote_domain_snapshot_num_ret {
+ int num;
+};
+typedef struct remote_domain_snapshot_num_ret remote_domain_snapshot_num_ret;
+
+struct remote_domain_snapshot_list_names_args {
+ remote_nonnull_domain domain;
+ int nameslen;
+ int flags;
+};
+typedef struct remote_domain_snapshot_list_names_args
remote_domain_snapshot_list_names_args;
+
+struct remote_domain_snapshot_list_names_ret {
+ struct {
+ u_int names_len;
+ remote_nonnull_string *names_val;
+ } names;
+};
+typedef struct remote_domain_snapshot_list_names_ret
remote_domain_snapshot_list_names_ret;
+
+struct remote_domain_snapshot_lookup_by_name_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string name;
+ int flags;
+};
+typedef struct remote_domain_snapshot_lookup_by_name_args
remote_domain_snapshot_lookup_by_name_args;
+
+struct remote_domain_snapshot_lookup_by_name_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+typedef struct remote_domain_snapshot_lookup_by_name_ret
remote_domain_snapshot_lookup_by_name_ret;
+
+struct remote_domain_has_current_snapshot_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+typedef struct remote_domain_has_current_snapshot_args
remote_domain_has_current_snapshot_args;
+
+struct remote_domain_has_current_snapshot_ret {
+ int result;
+};
+typedef struct remote_domain_has_current_snapshot_ret
remote_domain_has_current_snapshot_ret;
+
+struct remote_domain_snapshot_current_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+typedef struct remote_domain_snapshot_current_args remote_domain_snapshot_current_args;
+
+struct remote_domain_snapshot_current_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+typedef struct remote_domain_snapshot_current_ret remote_domain_snapshot_current_ret;
+
+struct remote_domain_revert_to_snapshot_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+typedef struct remote_domain_revert_to_snapshot_args
remote_domain_revert_to_snapshot_args;
+
+struct remote_domain_snapshot_delete_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+typedef struct remote_domain_snapshot_delete_args remote_domain_snapshot_delete_args;
#define REMOTE_PROGRAM 0x20008086
#define REMOTE_PROTOCOL_VERSION 1
@@ -2045,6 +2147,15 @@ enum remote_procedure {
REMOTE_PROC_LIST_NWFILTERS = 179,
REMOTE_PROC_NWFILTER_DEFINE_XML = 180,
REMOTE_PROC_NWFILTER_UNDEFINE = 181,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML = 182,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML = 183,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 184,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 185,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 186,
+ REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT = 187,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 188,
+ REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 189,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 190,
};
typedef enum remote_procedure remote_procedure;
@@ -2088,6 +2199,7 @@ extern bool_t xdr_remote_nonnull_storage_pool (XDR *,
remote_nonnull_storage_po
extern bool_t xdr_remote_nonnull_storage_vol (XDR *, remote_nonnull_storage_vol*);
extern bool_t xdr_remote_nonnull_node_device (XDR *, remote_nonnull_node_device*);
extern bool_t xdr_remote_nonnull_secret (XDR *, remote_nonnull_secret*);
+extern bool_t xdr_remote_nonnull_domain_snapshot (XDR *,
remote_nonnull_domain_snapshot*);
extern bool_t xdr_remote_domain (XDR *, remote_domain*);
extern bool_t xdr_remote_network (XDR *, remote_network*);
extern bool_t xdr_remote_nwfilter (XDR *, remote_nwfilter*);
@@ -2380,6 +2492,22 @@ extern bool_t xdr_remote_domain_event_io_error_msg (XDR *,
remote_domain_event_
extern bool_t xdr_remote_domain_event_graphics_address (XDR *,
remote_domain_event_graphics_address*);
extern bool_t xdr_remote_domain_event_graphics_identity (XDR *,
remote_domain_event_graphics_identity*);
extern bool_t xdr_remote_domain_event_graphics_msg (XDR *,
remote_domain_event_graphics_msg*);
+extern bool_t xdr_remote_domain_snapshot_create_xml_args (XDR *,
remote_domain_snapshot_create_xml_args*);
+extern bool_t xdr_remote_domain_snapshot_create_xml_ret (XDR *,
remote_domain_snapshot_create_xml_ret*);
+extern bool_t xdr_remote_domain_snapshot_dump_xml_args (XDR *,
remote_domain_snapshot_dump_xml_args*);
+extern bool_t xdr_remote_domain_snapshot_dump_xml_ret (XDR *,
remote_domain_snapshot_dump_xml_ret*);
+extern bool_t xdr_remote_domain_snapshot_num_args (XDR *,
remote_domain_snapshot_num_args*);
+extern bool_t xdr_remote_domain_snapshot_num_ret (XDR *,
remote_domain_snapshot_num_ret*);
+extern bool_t xdr_remote_domain_snapshot_list_names_args (XDR *,
remote_domain_snapshot_list_names_args*);
+extern bool_t xdr_remote_domain_snapshot_list_names_ret (XDR *,
remote_domain_snapshot_list_names_ret*);
+extern bool_t xdr_remote_domain_snapshot_lookup_by_name_args (XDR *,
remote_domain_snapshot_lookup_by_name_args*);
+extern bool_t xdr_remote_domain_snapshot_lookup_by_name_ret (XDR *,
remote_domain_snapshot_lookup_by_name_ret*);
+extern bool_t xdr_remote_domain_has_current_snapshot_args (XDR *,
remote_domain_has_current_snapshot_args*);
+extern bool_t xdr_remote_domain_has_current_snapshot_ret (XDR *,
remote_domain_has_current_snapshot_ret*);
+extern bool_t xdr_remote_domain_snapshot_current_args (XDR *,
remote_domain_snapshot_current_args*);
+extern bool_t xdr_remote_domain_snapshot_current_ret (XDR *,
remote_domain_snapshot_current_ret*);
+extern bool_t xdr_remote_domain_revert_to_snapshot_args (XDR *,
remote_domain_revert_to_snapshot_args*);
+extern bool_t xdr_remote_domain_snapshot_delete_args (XDR *,
remote_domain_snapshot_delete_args*);
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
extern bool_t xdr_remote_message_type (XDR *, remote_message_type*);
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
@@ -2397,6 +2525,7 @@ extern bool_t xdr_remote_nonnull_storage_pool ();
extern bool_t xdr_remote_nonnull_storage_vol ();
extern bool_t xdr_remote_nonnull_node_device ();
extern bool_t xdr_remote_nonnull_secret ();
+extern bool_t xdr_remote_nonnull_domain_snapshot ();
extern bool_t xdr_remote_domain ();
extern bool_t xdr_remote_network ();
extern bool_t xdr_remote_nwfilter ();
@@ -2689,6 +2818,22 @@ extern bool_t xdr_remote_domain_event_io_error_msg ();
extern bool_t xdr_remote_domain_event_graphics_address ();
extern bool_t xdr_remote_domain_event_graphics_identity ();
extern bool_t xdr_remote_domain_event_graphics_msg ();
+extern bool_t xdr_remote_domain_snapshot_create_xml_args ();
+extern bool_t xdr_remote_domain_snapshot_create_xml_ret ();
+extern bool_t xdr_remote_domain_snapshot_dump_xml_args ();
+extern bool_t xdr_remote_domain_snapshot_dump_xml_ret ();
+extern bool_t xdr_remote_domain_snapshot_num_args ();
+extern bool_t xdr_remote_domain_snapshot_num_ret ();
+extern bool_t xdr_remote_domain_snapshot_list_names_args ();
+extern bool_t xdr_remote_domain_snapshot_list_names_ret ();
+extern bool_t xdr_remote_domain_snapshot_lookup_by_name_args ();
+extern bool_t xdr_remote_domain_snapshot_lookup_by_name_ret ();
+extern bool_t xdr_remote_domain_has_current_snapshot_args ();
+extern bool_t xdr_remote_domain_has_current_snapshot_ret ();
+extern bool_t xdr_remote_domain_snapshot_current_args ();
+extern bool_t xdr_remote_domain_snapshot_current_ret ();
+extern bool_t xdr_remote_domain_revert_to_snapshot_args ();
+extern bool_t xdr_remote_domain_snapshot_delete_args ();
extern bool_t xdr_remote_procedure ();
extern bool_t xdr_remote_message_type ();
extern bool_t xdr_remote_message_status ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index bf87c33..b36ae1b 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -121,6 +121,9 @@ const REMOTE_AUTH_TYPE_LIST_MAX = 20;
/* Upper limit on list of memory stats */
const REMOTE_DOMAIN_MEMORY_STATS_MAX = 1024;
+/* Upper limit on lists of domain snapshots. */
+const REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX = 1024;
+
/* Maximum length of a block peek buffer message.
* Note applications need to be aware of this limit and issue multiple
* requests for large amounts of data.
@@ -216,6 +219,12 @@ struct remote_nonnull_secret {
remote_nonnull_string usageID;
};
+/* A snapshot which may not be NULL. */
+struct remote_nonnull_domain_snapshot {
+ remote_nonnull_string name;
+ remote_nonnull_domain domain;
+};
+
/* A domain or network which may be NULL. */
typedef remote_nonnull_domain *remote_domain;
typedef remote_nonnull_network *remote_network;
@@ -1647,6 +1656,83 @@ struct remote_domain_event_graphics_msg {
remote_domain_event_graphics_identity
subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
+struct remote_domain_snapshot_create_xml_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string xml_desc;
+ int flags;
+};
+
+struct remote_domain_snapshot_create_xml_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+
+struct remote_domain_snapshot_dump_xml_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+
+struct remote_domain_snapshot_dump_xml_ret {
+ remote_nonnull_string xml;
+};
+
+struct remote_domain_snapshot_num_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+
+struct remote_domain_snapshot_num_ret {
+ int num;
+};
+
+struct remote_domain_snapshot_list_names_args {
+ remote_nonnull_domain domain;
+ int nameslen;
+ int flags;
+};
+
+struct remote_domain_snapshot_list_names_ret {
+ remote_nonnull_string names<REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX>;
+};
+
+struct remote_domain_snapshot_lookup_by_name_args {
+ remote_nonnull_domain domain;
+ remote_nonnull_string name;
+ int flags;
+};
+
+struct remote_domain_snapshot_lookup_by_name_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+
+struct remote_domain_has_current_snapshot_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+
+struct remote_domain_has_current_snapshot_ret {
+ int result;
+};
+
+struct remote_domain_snapshot_current_args {
+ remote_nonnull_domain domain;
+ int flags;
+};
+
+struct remote_domain_snapshot_current_ret {
+ remote_nonnull_domain_snapshot snap;
+};
+
+struct remote_domain_revert_to_snapshot_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+
+struct remote_domain_snapshot_delete_args {
+ remote_nonnull_domain_snapshot snap;
+ int flags;
+};
+
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -1852,7 +1938,16 @@ enum remote_procedure {
REMOTE_PROC_LIST_NWFILTERS = 179,
REMOTE_PROC_NWFILTER_DEFINE_XML = 180,
- REMOTE_PROC_NWFILTER_UNDEFINE = 181
+ REMOTE_PROC_NWFILTER_UNDEFINE = 181,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML = 182,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML = 183,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 184,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 185,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 186,
+ REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT = 187,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 188,
+ REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 189,
+ REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 190
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 646c7db..e322010 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5306,6 +5306,15 @@ static virDriver testDriver = {
NULL, /* domainMigrateSetMaxDowntime */
testDomainEventRegisterAny, /* domainEventRegisterAny */
testDomainEventDeregisterAny, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
static virNetworkDriver testNetworkDriver = {
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 08fbf93..47ee5ef 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -1937,6 +1937,15 @@ static virDriver umlDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 2537110..d29f95b 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -184,6 +184,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_HOOK:
dom = "Sync Hook ";
break;
+ case VIR_FROM_DOMAIN_SNAPSHOT:
+ dom = "Domain Snapshot ";
+ break;
}
return(dom);
}
@@ -1153,6 +1156,18 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("Hook script execution failed: %s");
break;
+ case VIR_ERR_INVALID_DOMAIN_SNAPSHOT:
+ if (info == NULL)
+ errmsg = _("Invalid snapshot");
+ else
+ errmsg = _("Invalid snapshot: %s");
+ break;
+ case VIR_ERR_NO_DOMAIN_SNAPSHOT:
+ if (info == NULL)
+ errmsg = _("Domain snapshot not found");
+ else
+ errmsg = _("Domain snapshot not found: %s");
+ break;
}
return (errmsg);
}
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 59ad1b8..dac386d 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -7184,6 +7184,15 @@ virDriver NAME(Driver) = {
vboxDomainEventRegisterAny, /* domainEventRegisterAny */
vboxDomainEventDeregisterAny, /* domainEventDeregisterAny */
#endif
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
virNetworkDriver NAME(NetworkDriver) = {
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index ebdc600..04489a5 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -1980,6 +1980,15 @@ static virDriver xenUnifiedDriver = {
NULL, /* domainMigrateSetMaxDowntime */
xenUnifiedDomainEventRegisterAny, /* domainEventRegisterAny */
xenUnifiedDomainEventDeregisterAny, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
/**
diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c
index dcfdc1e..19ff9da 100644
--- a/src/xenapi/xenapi_driver.c
+++ b/src/xenapi/xenapi_driver.c
@@ -1783,6 +1783,15 @@ static virDriver xenapiDriver = {
NULL, /* domainMigrateSetMaxDowntime */
NULL, /* domainEventRegisterAny */
NULL, /* domainEventDeregisterAny */
+ NULL, /* domainSnapshotCreateXML */
+ NULL, /* domainSnapshotDumpXML */
+ NULL, /* domainSnapshotNum */
+ NULL, /* domainSnapshotListNames */
+ NULL, /* domainSnapshotLookupByName */
+ NULL, /* domainHasCurrentSnapshot */
+ NULL, /* domainSnapshotCurrent */
+ NULL, /* domainRevertToSnapshot */
+ NULL, /* domainSnapshotDelete */
};
/**
--
1.6.6.1