Copies heavily from existing virDomainSnapshot handling, regarding
what special cases the generator has to be taught and what overrides
need to be written.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Python counterparts to my incremental backup patches. An earlier
version was already reviewed by Dan; the main diff here is the
addition of virDomainSnapshotCreateXML2 handling.
HACKING | 2 +
MANIFEST.in | 1 +
generator.py | 37 ++++++++--
libvirt-override-api.xml | 12 ++++
libvirt-override-virDomain.py | 13 ++++
libvirt-override-virDomainCheckpoint.py | 19 +++++
libvirt-override.c | 96 +++++++++++++++++++++++++
sanitytest.py | 11 +--
typewrappers.c | 13 ++++
typewrappers.h | 10 +++
10 files changed, 206 insertions(+), 8 deletions(-)
create mode 100644 libvirt-override-virDomainCheckpoint.py
diff --git a/HACKING b/HACKING
index 6eeb9e6..39e7cd3 100644
--- a/HACKING
+++ b/HACKING
@@ -28,6 +28,8 @@ hand written source files
the virConnect class
- libvirt-override-virDomain.py - high level overrides in
the virDomain class
+ - libvirt-override-virDomainCheckpoint.py - high level overrides in
+ the virDomainCheckpoint class
- libvirt-override-virDomainSnapshot.py - high level overrides in
the virDomainSnapshot class
- libvirt-override-virStoragePool.py - high level overrides in
diff --git a/MANIFEST.in b/MANIFEST.in
index b6788f4..5d2f559 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -23,6 +23,7 @@ include libvirt-override.c
include libvirt-override.py
include libvirt-override-virConnect.py
include libvirt-override-virDomain.py
+include libvirt-override-virDomainCheckpoint.py
include libvirt-override-virDomainSnapshot.py
include libvirt-override-virStoragePool.py
include libvirt-override-virStream.py
diff --git a/generator.py b/generator.py
index ffa3ce5..a16f9b1 100755
--- a/generator.py
+++ b/generator.py
@@ -35,6 +35,7 @@ libvirt_headers = [
"libvirt",
"libvirt-common",
"libvirt-domain",
+ "libvirt-domain-checkpoint",
"libvirt-domain-snapshot",
"libvirt-event",
"libvirt-host",
@@ -364,6 +365,10 @@ py_types = {
'virStream *': ('O', "virStream",
"virStreamPtr", "virStreamPtr"),
'const virStream *': ('O', "virStream",
"virStreamPtr", "virStreamPtr"),
+ 'virDomainCheckpointPtr': ('O', "virDomainCheckpoint",
"virDomainCheckpointPtr", "virDomainCheckpointPtr"),
+ 'virDomainCheckpoint *': ('O', "virDomainCheckpoint",
"virDomainCheckpointPtr", "virDomainCheckpointPtr"),
+ 'const virDomainCheckpoint *': ('O',
"virDomainCheckpoint", "virDomainCheckpointPtr",
"virDomainCheckpointPtr"),
+
'virDomainSnapshotPtr': ('O', "virDomainSnapshot",
"virDomainSnapshotPtr", "virDomainSnapshotPtr"),
'virDomainSnapshot *': ('O', "virDomainSnapshot",
"virDomainSnapshotPtr", "virDomainSnapshotPtr"),
'const virDomainSnapshot *': ('O', "virDomainSnapshot",
"virDomainSnapshotPtr", "virDomainSnapshotPtr"),
@@ -536,6 +541,8 @@ skip_function = (
'virSaveLastError', # We have our own python error wrapper
'virFreeError', # Only needed if we use virSaveLastError
'virConnectListAllDomains', # overridden in virConnect.py
+ 'virDomainListAllCheckpoints', # overridden in virDomain.py
+ 'virDomainCheckpointListAllChildren', # overridden in virDomainCheckpoint.py
'virDomainListAllSnapshots', # overridden in virDomain.py
'virDomainSnapshotListAllChildren', # overridden in virDomainSnapshot.py
'virConnectListAllStoragePools', # overridden in virConnect.py
@@ -582,6 +589,7 @@ skip_function = (
"virStoragePoolRef",
"virStorageVolRef",
"virStreamRef",
+ "virDomainCheckpointRef",
"virDomainSnapshotRef",
# This functions shouldn't be called via the bindings (and even the docs
@@ -594,6 +602,8 @@ skip_function = (
"virNWFilterGetConnect",
"virStoragePoolGetConnect",
"virStorageVolGetConnect",
+ "virDomainCheckpointGetConnect",
+ "virDomainCheckpointGetDomain",
"virDomainSnapshotGetConnect",
"virDomainSnapshotGetDomain",
@@ -1023,6 +1033,8 @@ classes_type = {
"virStream *": ("._o", "virStream(self, _obj=%s)",
"virStream"),
"virConnectPtr": ("._o", "virConnect(_obj=%s)",
"virConnect"),
"virConnect *": ("._o", "virConnect(_obj=%s)",
"virConnect"),
+ "virDomainCheckpointPtr": ("._o",
"virDomainCheckpoint(self,_obj=%s)", "virDomainCheckpoint"),
+ "virDomainCheckpoint *": ("._o", "virDomainCheckpoint(self,
_obj=%s)", "virDomainCheckpoint"),
"virDomainSnapshotPtr": ("._o",
"virDomainSnapshot(self,_obj=%s)", "virDomainSnapshot"),
"virDomainSnapshot *": ("._o", "virDomainSnapshot(self,
_obj=%s)", "virDomainSnapshot"),
}
@@ -1031,7 +1043,7 @@ primary_classes = ["virDomain", "virNetwork",
"virInterface",
"virStoragePool", "virStorageVol",
"virConnect", "virNodeDevice",
"virSecret",
"virNWFilter", "virNWFilterBinding",
- "virStream", "virDomainSnapshot"]
+ "virStream", "virDomainCheckpoint",
"virDomainSnapshot"]
classes_destructors = {
"virDomain": "virDomainFree",
@@ -1043,6 +1055,7 @@ classes_destructors = {
"virSecret": "virSecretFree",
"virNWFilter": "virNWFilterFree",
"virNWFilterBinding": "virNWFilterBindingFree",
+ "virDomainCheckpoint": "virDomainCheckpointFree",
"virDomainSnapshot": "virDomainSnapshotFree",
# We hand-craft __del__ for this one
#"virStream": "virStreamFree",
@@ -1053,6 +1066,7 @@ class_skip_connect_impl = {
}
class_domain_impl = {
+ "virDomainCheckpoint": True,
"virDomainSnapshot": True,
}
@@ -1171,6 +1185,18 @@ def nameFixup(name, classe, type, file):
elif name[0:12] == "virDomainGet":
func = name[12:]
func = func[0:1].lower() + func[1:]
+ elif name[0:31] == "virDomainCheckpointLookupByName":
+ func = name[9:]
+ func = func[0:1].lower() + func[1:]
+ elif name[0:28] == "virDomainCheckpointCreateXML":
+ func = name[9:]
+ func = func[0:1].lower() + func[1:]
+ elif name[0:26] == "virDomainCheckpointCurrent":
+ func = name[9:]
+ func = func[0:1].lower() + func[1:]
+ elif name[0:19] == "virDomainCheckpoint":
+ func = name[19:]
+ func = func[0:1].lower() + func[1:]
elif name[0:29] == "virDomainSnapshotLookupByName":
func = name[9:]
func = func[0:1].lower() + func[1:]
@@ -1183,6 +1209,9 @@ def nameFixup(name, classe, type, file):
elif name[0:20] == "virDomainSnapshotNum":
func = name[9:]
func = func[0:1].lower() + func[1:]
+ elif name[0:27] == "virDomainSnapshotCreateXML2":
+ func = name[9:]
+ func = func[0:1].lower() + func[1:]
elif name[0:26] == "virDomainSnapshotCreateXML":
func = name[9:]
func = func[0:1].lower() + func[1:]
@@ -1501,7 +1530,7 @@ def buildWrappers(module):
"virStorageVol", "virNodeDevice",
"virSecret","virStream",
"virNWFilter", "virNWFilterBinding" ]:
classes.write(" def __init__(self, conn, _obj=None):\n")
- elif classname in [ 'virDomainSnapshot' ]:
+ elif classname in [ "virDomainCheckpoint",
"virDomainSnapshot" ]:
classes.write(" def __init__(self, dom, _obj=None):\n")
else:
classes.write(" def __init__(self, _obj=None):\n")
@@ -1513,7 +1542,7 @@ def buildWrappers(module):
classes.write(" self._conn = conn\n" + \
" if not isinstance(conn, virConnect):\n"
+ \
" self._conn = conn._conn\n")
- elif classname in [ "virDomainSnapshot" ]:
+ elif classname in [ "virDomainCheckpoint",
"virDomainSnapshot" ]:
classes.write(" self._dom = dom\n")
classes.write(" self._conn = dom.connect()\n")
classes.write(" if type(_obj).__name__ not in
[\"PyCapsule\", \"PyCObject\"]:\n")
@@ -1641,7 +1670,7 @@ def buildWrappers(module):
classes.write(
" if ret is None:raise libvirtError('%s()
failed', vol=self)\n" %
(name))
- elif classname == "virDomainSnapshot":
+ elif classname in [ "virDomainCheckpoint",
"virDomainSnapshot"]:
classes.write(
" if ret is None:raise libvirtError('%s()
failed', dom=self._dom)\n" %
(name))
diff --git a/libvirt-override-api.xml b/libvirt-override-api.xml
index 7f578e0..1edf0c5 100644
--- a/libvirt-override-api.xml
+++ b/libvirt-override-api.xml
@@ -576,6 +576,18 @@
<arg name='flags' type='unsigned int' info='flags'/>
<return type='int' info="0 on success, -1 on error"/>
</function>
+ <function name='virDomainListAllCheckpoints' file='python'>
+ <info>returns the list of checkpoints for the given domain</info>
+ <arg name='dom' type='virDomainPtr' info='pointer to the
domain'/>
+ <arg name='flags' type='unsigned int' info='flags'/>
+ <return type='char *' info='the list of checkpoints or None in case
of error'/>
+ </function>
+ <function name='virDomainCheckpointListAllChildren'
file='python'>
+ <info>collect the list of child checkpoint names for the given
checkpoint</info>
+ <arg name='checkpoint' type='virDomainCheckpointPtr'
info='pointer to the checkpoint'/>
+ <arg name='flags' type='unsigned int' info='flags'/>
+ <return type='char *' info='the list of checkpoints or None in case
of error'/>
+ </function>
<function name='virDomainGetBlockJobInfo' file='python'>
<info>Get progress information for a block job</info>
<arg name='dom' type='virDomainPtr' info='pointer to the
domain'/>
diff --git a/libvirt-override-virDomain.py b/libvirt-override-virDomain.py
index 7c417b8..7ce34f1 100644
--- a/libvirt-override-virDomain.py
+++ b/libvirt-override-virDomain.py
@@ -11,6 +11,19 @@
return retlist
+ def listAllCheckpoints(self, flags=0):
+ """List all checkpoints and returns a list of checkpoint
objects"""
+ ret = libvirtmod.virDomainListAllCheckpoints(self._o, flags)
+ if ret is None:
+ raise libvirtError("virDomainListAllCheckpoints() failed",
conn=self)
+
+ retlist = list()
+ for chkptr in ret:
+ retlist.append(virDomainCheckpoint(self, _obj=chkptr))
+
+ return retlist
+
+
def createWithFiles(self, files, flags=0):
"""Launch a defined domain. If the call succeeds the domain moves
from the
defined to the running domains pools.
diff --git a/libvirt-override-virDomainCheckpoint.py
b/libvirt-override-virDomainCheckpoint.py
new file mode 100644
index 0000000..371b0fd
--- /dev/null
+++ b/libvirt-override-virDomainCheckpoint.py
@@ -0,0 +1,19 @@
+ def getConnect(self):
+ """Get the connection that owns the domain that a checkpoint was
created for"""
+ return self.connect()
+
+ def getDomain(self):
+ """Get the domain that a checkpoint was created
for"""
+ return self.domain()
+
+ def listAllChildren(self, flags=0):
+ """List all child checkpoints and returns a list of checkpoint
objects"""
+ ret = libvirtmod.virDomainCheckpointListAllChildren(self._o, flags)
+ if ret is None:
+ raise libvirtError("virDomainCheckpointListAllChildren() failed",
conn=self)
+
+ retlist = list()
+ for chkptr in ret:
+ retlist.append(virDomainCheckpoint(self, _obj=chkptr))
+
+ return retlist
diff --git a/libvirt-override.c b/libvirt-override.c
index c5e2908..777f533 100644
--- a/libvirt-override.c
+++ b/libvirt-override.c
@@ -2325,6 +2325,98 @@ libvirt_virConnectListDefinedDomains(PyObject *self
ATTRIBUTE_UNUSED,
goto cleanup;
}
+#if LIBVIR_CHECK_VERSION(5, 1, 0)
+static PyObject *
+libvirt_virDomainListAllCheckpoints(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval = NULL;
+ virDomainCheckpointPtr *chks = NULL;
+ int c_retval;
+ ssize_t i;
+ virDomainPtr dom;
+ PyObject *pyobj_dom;
+ unsigned int flags;
+
+ if (!PyArg_ParseTuple(args, (char *)"OI:virDomainListAllCheckpoints",
+ &pyobj_dom, &flags))
+ return NULL;
+ dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virDomainListAllCheckpoints(dom, &chks, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ if (!(py_retval = PyList_New(c_retval)))
+ goto cleanup;
+
+ for (i = 0; i < c_retval; i++) {
+ VIR_PY_LIST_SET_GOTO(py_retval, i,
+ libvirt_virDomainCheckpointPtrWrap(chks[i]), error);
+ chks[i] = NULL;
+ }
+
+ cleanup:
+ for (i = 0; i < c_retval; i++)
+ if (chks[i])
+ virDomainCheckpointFree(chks[i]);
+ VIR_FREE(chks);
+ return py_retval;
+
+ error:
+ Py_CLEAR(py_retval);
+ goto cleanup;
+}
+
+static PyObject *
+libvirt_virDomainCheckpointListAllChildren(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval = NULL;
+ virDomainCheckpointPtr *chks = NULL;
+ int c_retval;
+ ssize_t i;
+ virDomainCheckpointPtr parent;
+ PyObject *pyobj_parent;
+ unsigned int flags;
+
+ if (!PyArg_ParseTuple(args, (char
*)"OI:virDomainCheckpointListAllChildren",
+ &pyobj_parent, &flags))
+ return NULL;
+ parent = (virDomainCheckpointPtr) PyvirDomainCheckpoint_Get(pyobj_parent);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ c_retval = virDomainCheckpointListAllChildren(parent, &chks, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (c_retval < 0)
+ return VIR_PY_NONE;
+
+ if (!(py_retval = PyList_New(c_retval)))
+ goto cleanup;
+
+ for (i = 0; i < c_retval; i++) {
+ VIR_PY_LIST_SET_GOTO(py_retval, i,
+ libvirt_virDomainCheckpointPtrWrap(chks[i]), error);
+ chks[i] = NULL;
+ }
+
+ cleanup:
+ for (i = 0; i < c_retval; i++)
+ if (chks[i])
+ virDomainCheckpointFree(chks[i]);
+ VIR_FREE(chks);
+ return py_retval;
+
+ error:
+ Py_CLEAR(py_retval);
+ goto cleanup;
+}
+#endif /* LIBVIR_CHECK_VERSION(5, 1, 0) */
+
static PyObject *
libvirt_virDomainSnapshotListNames(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args)
@@ -10100,6 +10192,10 @@ static PyMethodDef libvirtMethods[] = {
#if LIBVIR_CHECK_VERSION(1, 0, 3)
{(char *) "virDomainGetJobStats", libvirt_virDomainGetJobStats,
METH_VARARGS, NULL},
#endif /* LIBVIR_CHECK_VERSION(1, 0, 3) */
+#if LIBVIR_CHECK_VERSION(5, 1, 0)
+ {(char *) "virDomainListAllCheckpoints",
libvirt_virDomainListAllCheckpoints, METH_VARARGS, NULL},
+ {(char *) "virDomainCheckpointListAllChildren",
libvirt_virDomainCheckpointListAllChildren, METH_VARARGS, NULL},
+#endif /* LIBVIR_CHECK_VERSION(5, 1, 0) */
{(char *) "virDomainSnapshotListNames", libvirt_virDomainSnapshotListNames,
METH_VARARGS, NULL},
#if LIBVIR_CHECK_VERSION(0, 9, 13)
{(char *) "virDomainListAllSnapshots", libvirt_virDomainListAllSnapshots,
METH_VARARGS, NULL},
diff --git a/sanitytest.py b/sanitytest.py
index 68dde6b..b044231 100644
--- a/sanitytest.py
+++ b/sanitytest.py
@@ -249,13 +249,13 @@ for name in sorted(basicklassmap):
# Remove 'Get' prefix from most APIs, except those in virConnect
# and virDomainSnapshot namespaces which stupidly used a different
# convention which we now can't fix without breaking API
- if func[0:3] == "Get" and klass not in ["virConnect",
"virDomainSnapshot", "libvirt"]:
+ if func[0:3] == "Get" and klass not in ["virConnect",
"virDomainCheckpoint", "virDomainSnapshot", "libvirt"]:
if func not in ["GetCPUStats", "GetTime"]:
func = func[3:]
# The object creation and lookup APIs all have to get re-mapped
# into the parent class
- if func in ["CreateXML", "CreateLinux",
"CreateXMLWithFiles",
+ if func in ["CreateXML", "CreateXML2", "CreateLinux",
"CreateXMLWithFiles",
"DefineXML", "CreateXMLFrom",
"LookupByUUID",
"LookupByUUIDString", "LookupByVolume"
"LookupByName",
"LookupByID", "LookupByName",
"LookupByKey", "LookupByPath",
@@ -266,7 +266,7 @@ for name in sorted(basicklassmap):
if klass != "virDomain":
func = klass[3:] + func
- if klass == "virDomainSnapshot":
+ if klass in [ "virDomainCheckpoint", "virDomainSnapshot"]:
klass = "virDomain"
func = func[6:]
elif klass == "virStorageVol" and func in
["StorageVolCreateXMLFrom", "StorageVolCreateXML"]:
@@ -297,10 +297,13 @@ for name in sorted(basicklassmap):
if func[0:6] == "Change":
klass = "virConnect"
- # Need to special case the snapshot APIs
+ # Need to special case the checkpoint and snapshot APIs
if klass == "virDomainSnapshot" and func in ["Current",
"ListNames", "Num"]:
klass = "virDomain"
func = "snapshot" + func
+ elif klass == "virDomainCheckpoint" and func == "Current":
+ klass = "virDomain"
+ func = "checkpoint" + func
# Names should start with lowercase letter...
func = func[0:1].lower() + func[1:]
diff --git a/typewrappers.c b/typewrappers.c
index 9ba14b4..cd7a70b 100644
--- a/typewrappers.c
+++ b/typewrappers.c
@@ -568,6 +568,19 @@ libvirt_virStreamPtrWrap(virStreamPtr node)
return ret;
}
+PyObject *
+libvirt_virDomainCheckpointPtrWrap(virDomainCheckpointPtr node)
+{
+ PyObject *ret;
+
+ if (node == NULL) {
+ return VIR_PY_NONE;
+ }
+
+ ret = libvirt_buildPyObject(node, "virDomainCheckpointPtr", NULL);
+ return ret;
+}
+
PyObject *
libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node)
{
diff --git a/typewrappers.h b/typewrappers.h
index 4423774..198397b 100644
--- a/typewrappers.h
+++ b/typewrappers.h
@@ -128,6 +128,15 @@ typedef struct {
} PyvirStream_Object;
+#define PyvirDomainCheckpoint_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyvirDomainCheckpoint_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ virDomainCheckpointPtr obj;
+} PyvirDomainCheckpoint_Object;
+
+
#define PyvirDomainSnapshot_Get(v) (((v) == Py_None) ? NULL : \
(((PyvirDomainSnapshot_Object *)(v))->obj))
@@ -204,6 +213,7 @@ PyObject * libvirt_virSecretPtrWrap(virSecretPtr node);
PyObject * libvirt_virNWFilterPtrWrap(virNWFilterPtr node);
PyObject * libvirt_virNWFilterBindingPtrWrap(virNWFilterBindingPtr node);
PyObject * libvirt_virStreamPtrWrap(virStreamPtr node);
+PyObject * libvirt_virDomainCheckpointPtrWrap(virDomainCheckpointPtr node);
PyObject * libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node);
--
2.20.1