From 358a8640fa03b6d79645d1794e28a4259bea7ec3 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 7 Feb 2019 16:36:16 -0600 Subject: [PATCH] Add virDomainCheckpoint APIs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Daniel P. Berrangé --- HACKING | 2 + MANIFEST.in | 1 + generator.py | 31 +++++++++-- libvirt-override-api.xml | 12 +++++ libvirt-override-virDomain.py | 13 +++++ libvirt-override-virDomainCheckpoint.py | 19 +++++++ libvirt-override.c | 96 +++++++++++++++++++++++++++++++++ sanitytest.py | 6 +-- typewrappers.c | 13 +++++ typewrappers.h | 10 ++++ 10 files changed, 196 insertions(+), 7 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 5ade948..af86f5b 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-virNetwork.py include libvirt-override-virStoragePool.py diff --git a/generator.py b/generator.py index 9dedc18..8922f93 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", @@ -368,6 +369,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"), @@ -542,6 +547,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 @@ -590,6 +597,7 @@ skip_function = ( "virStoragePoolRef", "virStorageVolRef", "virStreamRef", + "virDomainCheckpointRef", "virDomainSnapshotRef", # This functions shouldn't be called via the bindings (and even the docs @@ -603,6 +611,8 @@ skip_function = ( "virNWFilterGetConnect", "virStoragePoolGetConnect", "virStorageVolGetConnect", + "virDomainCheckpointGetConnect", + "virDomainCheckpointGetDomain", "virDomainSnapshotGetConnect", "virDomainSnapshotGetDomain", @@ -1034,6 +1044,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"), } @@ -1042,7 +1054,7 @@ primary_classes = ["virDomain", "virNetwork", "virNetworkPort", "virInterface", "virStoragePool", "virStorageVol", "virConnect", "virNodeDevice", "virSecret", "virNWFilter", "virNWFilterBinding", - "virStream", "virDomainSnapshot"] + "virStream", "virDomainCheckpoint", "virDomainSnapshot"] classes_destructors = { "virDomain": "virDomainFree", @@ -1055,6 +1067,7 @@ classes_destructors = { "virSecret": "virSecretFree", "virNWFilter": "virNWFilterFree", "virNWFilterBinding": "virNWFilterBindingFree", + "virDomainCheckpoint": "virDomainCheckpointFree", "virDomainSnapshot": "virDomainSnapshotFree", # We hand-craft __del__ for this one #"virStream": "virStreamFree", @@ -1065,6 +1078,7 @@ class_skip_connect_impl = { } class_domain_impl = { + "virDomainCheckpoint": True, "virDomainSnapshot": True, } @@ -1189,6 +1203,15 @@ 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: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:] @@ -1525,7 +1548,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") @@ -1537,7 +1560,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") @@ -1665,7 +1688,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 6e29c1e..9c4d71d 100644 --- a/libvirt-override-api.xml +++ b/libvirt-override-api.xml @@ -576,6 +576,18 @@ + + returns the list of checkpoints for the given domain + + + + + + collect the list of child checkpoint names for the given checkpoint + + + + Get progress information for a block job 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 5ae4406..42f8198 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, 6, 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, 6, 0) */ + static PyObject * libvirt_virDomainSnapshotListNames(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) @@ -10238,6 +10330,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, 6, 0) + {(char *) "virDomainListAllCheckpoints", libvirt_virDomainListAllCheckpoints, METH_VARARGS, NULL}, + {(char *) "virDomainCheckpointListAllChildren", libvirt_virDomainCheckpointListAllChildren, METH_VARARGS, NULL}, +#endif /* LIBVIR_CHECK_VERSION(5, 6, 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 9743f6f..e87b57d 100644 --- a/sanitytest.py +++ b/sanitytest.py @@ -249,7 +249,7 @@ 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:] @@ -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"]: @@ -300,7 +300,7 @@ 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 diff --git a/typewrappers.c b/typewrappers.c index 5710744..2507859 100644 --- a/typewrappers.c +++ b/typewrappers.c @@ -582,6 +582,19 @@ libvirt_virStreamPtrWrap(virStreamPtr node) } 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) { PyObject *ret; diff --git a/typewrappers.h b/typewrappers.h index 518ad00..6b38690 100644 --- a/typewrappers.h +++ b/typewrappers.h @@ -140,6 +140,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)) @@ -217,6 +226,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.11.4.GIT