Create a new file for managing a list of checkpoint objects, borrowing heavily from existing virDomainSnapshotObjList paradigms. Note that while checkpoints definitely have a use case for multiple children to a single parent (create a base snapshot, create a child snapshot, revert to the base, then create another child snapshot), it's harder to predict how checkpoints will play out with reverting to prior points in time. Thus, in initial use, we may find that in a list of checkpoints, you never have more than one child. However, as the snapshot machinery is already generic, it is easier to reuse the generic machinery that tracks relations between domain moments than it is to open-code a new list-management scheme just for checkpoints. The virDomainMomentObjList code is not quite polymorphic enough until we patch virDomainMomentDef to be a proper virObject, but doing that is a bigger audit. So for now, I had to duplicate the cleanup calls based on a bool flag for which type needs cleaning. Oh well. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/conf/checkpoint_conf.h | 7 + src/conf/domain_conf.h | 2 + src/conf/virconftypes.h | 6 + src/conf/virdomaincheckpointobjlist.h | 74 +++++++++ src/conf/virdomainmomentobjlist.h | 2 +- src/conf/virdomainobjlist.h | 9 +- src/conf/Makefile.inc.am | 2 + src/conf/checkpoint_conf.c | 86 ++++++++++ src/conf/domain_conf.c | 6 + src/conf/virdomaincheckpointobjlist.c | 222 ++++++++++++++++++++++++++ src/conf/virdomainmomentobjlist.c | 40 ++++- src/conf/virdomainobjlist.c | 13 +- src/conf/virdomainsnapshotobjlist.c | 2 +- src/libvirt_private.syms | 18 +++ 14 files changed, 478 insertions(+), 11 deletions(-) create mode 100644 src/conf/virdomaincheckpointobjlist.h create mode 100644 src/conf/virdomaincheckpointobjlist.c diff --git a/src/conf/checkpoint_conf.h b/src/conf/checkpoint_conf.h index 6647d0cd7c..1432c884e9 100644 --- a/src/conf/checkpoint_conf.h +++ b/src/conf/checkpoint_conf.h @@ -91,6 +91,13 @@ char *virDomainCheckpointDefFormat(virDomainCheckpointDefPtr def, unsigned int flags); int virDomainCheckpointAlignDisks(virDomainCheckpointDefPtr checkpoint); +int virDomainCheckpointRedefinePrep(virDomainPtr domain, + virDomainObjPtr vm, + virDomainCheckpointDefPtr *def, + virDomainMomentObjPtr *checkpoint, + virDomainXMLOptionPtr xmlopt, + bool *update_current); + VIR_ENUM_DECL(virDomainCheckpoint); #endif /* LIBVIRT_CHECKPOINT_CONF_H */ diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4a25480662..9d7bc07dcd 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2520,6 +2520,8 @@ struct _virDomainObj { bool hasManagedSave; + virDomainCheckpointObjListPtr checkpoints; + void *privateData; void (*privateDataFreeFunc)(void *); diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index f01721c6d5..d3cc199c43 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -349,4 +349,10 @@ typedef virDomainXMLPrivateDataCallbacks *virDomainXMLPrivateDataCallbacksPtr; typedef struct _virDomainXenbusControllerOpts virDomainXenbusControllerOpts; typedef virDomainXenbusControllerOpts *virDomainXenbusControllerOptsPtr; +typedef struct _virDomainCheckpointObj virDomainCheckpointObj; +typedef virDomainCheckpointObj *virDomainCheckpointObjPtr; + +typedef struct _virDomainCheckpointObjList virDomainCheckpointObjList; +typedef virDomainCheckpointObjList *virDomainCheckpointObjListPtr; + #endif /* LIBVIRT_VIRCONFTYPES_H */ diff --git a/src/conf/virdomaincheckpointobjlist.h b/src/conf/virdomaincheckpointobjlist.h new file mode 100644 index 0000000000..954979beb7 --- /dev/null +++ b/src/conf/virdomaincheckpointobjlist.h @@ -0,0 +1,74 @@ +/* + * virdomaincheckpointobjlist.h: handle a tree of checkpoint objects + * (derived from virdomainsnapshotobjlist.h) + * + * Copyright (C) 2006-2019 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBVIRT_VIRDOMAINCHECKPOINTOBJLIST_H +# define LIBVIRT_VIRDOMAINCHECKPOINTOBJLIST_H + +# include "internal.h" +# include "virdomainmomentobjlist.h" +# include "virbuffer.h" + +virDomainCheckpointObjListPtr virDomainCheckpointObjListNew(void); +void virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints); + +virDomainMomentObjPtr virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints, + virDomainCheckpointDefPtr def); + +virDomainMomentObjPtr virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints, + const char *name); +virDomainMomentObjPtr virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints); +const char *virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints); +void virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr checkpoint); +bool virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr checkpoint); +void virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints); +int virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints, + virHashIterator iter, + void *data); +int virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints); + +# define VIR_DOMAIN_CHECKPOINT_FILTERS_METADATA \ + (VIR_DOMAIN_CHECKPOINT_LIST_METADATA | \ + VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA) + +# define VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES \ + (VIR_DOMAIN_CHECKPOINT_LIST_LEAVES | \ + VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES) + +# define VIR_DOMAIN_CHECKPOINT_FILTERS_ALL \ + (VIR_DOMAIN_CHECKPOINT_FILTERS_METADATA | \ + VIR_DOMAIN_CHECKPOINT_FILTERS_LEAVES) + +int virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr from, + virDomainPtr dom, + virDomainCheckpointPtr **objs, + unsigned int flags); + +static inline virDomainCheckpointDefPtr +virDomainCheckpointObjGetDef(virDomainMomentObjPtr obj) +{ + return obj ? (virDomainCheckpointDefPtr) obj->def : NULL; +} + +#endif /* LIBVIRT_VIRDOMAINCHECKPOINTOBJLIST_H */ diff --git a/src/conf/virdomainmomentobjlist.h b/src/conf/virdomainmomentobjlist.h index 04808e1ac7..a7bdcd73c4 100644 --- a/src/conf/virdomainmomentobjlist.h +++ b/src/conf/virdomainmomentobjlist.h @@ -64,7 +64,7 @@ void virDomainMomentMoveChildren(virDomainMomentObjPtr from, void virDomainMomentSetParent(virDomainMomentObjPtr moment, virDomainMomentObjPtr parent); -virDomainMomentObjListPtr virDomainMomentObjListNew(void); +virDomainMomentObjListPtr virDomainMomentObjListNew(bool snapshot); void virDomainMomentObjListFree(virDomainMomentObjListPtr moments); virDomainMomentObjPtr virDomainMomentAssignDef(virDomainMomentObjListPtr moments, diff --git a/src/conf/virdomainobjlist.h b/src/conf/virdomainobjlist.h index c1ffee76ad..32f3dcfcc2 100644 --- a/src/conf/virdomainobjlist.h +++ b/src/conf/virdomainobjlist.h @@ -1,7 +1,7 @@ /* * virdomainobjlist.h: domain objects list utilities * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. * @@ -121,13 +121,18 @@ int virDomainObjListForEach(virDomainObjListPtr doms, (VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT | \ VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) +# define VIR_CONNECT_LIST_DOMAINS_FILTERS_CHECKPOINT \ + (VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT | \ + VIR_CONNECT_LIST_DOMAINS_NO_CHECKPOINT) + # define VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL \ (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE | \ VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT | \ VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE | \ VIR_CONNECT_LIST_DOMAINS_FILTERS_MANAGEDSAVE | \ VIR_CONNECT_LIST_DOMAINS_FILTERS_AUTOSTART | \ - VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT) + VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT | \ + VIR_CONNECT_LIST_DOMAINS_FILTERS_CHECKPOINT) int virDomainObjListCollect(virDomainObjListPtr doms, virConnectPtr conn, diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am index 913e21e2d1..534b5b04dd 100644 --- a/src/conf/Makefile.inc.am +++ b/src/conf/Makefile.inc.am @@ -31,6 +31,8 @@ DOMAIN_CONF_SOURCES = \ conf/numa_conf.c \ conf/numa_conf.h \ conf/virconftypes.h \ + conf/virdomaincheckpointobjlist.c \ + conf/virdomaincheckpointobjlist.h \ conf/virdomainobjlist.c \ conf/virdomainobjlist.h \ conf/virdomainmomentobjlist.c \ diff --git a/src/conf/checkpoint_conf.c b/src/conf/checkpoint_conf.c index bdcf763a48..3dd2acf886 100644 --- a/src/conf/checkpoint_conf.c +++ b/src/conf/checkpoint_conf.c @@ -37,6 +37,7 @@ #include "virerror.h" #include "virxml.h" #include "virstring.h" +#include "virdomaincheckpointobjlist.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT @@ -551,3 +552,88 @@ virDomainCheckpointDefFormat(virDomainCheckpointDefPtr def, return virBufferContentAndReset(&buf); } + + +int +virDomainCheckpointRedefinePrep(virDomainPtr domain, + virDomainObjPtr vm, + virDomainCheckpointDefPtr *defptr, + virDomainMomentObjPtr *chk, + virDomainXMLOptionPtr xmlopt, + bool *update_current) +{ + virDomainCheckpointDefPtr def = *defptr; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virDomainMomentObjPtr other; + virDomainCheckpointDefPtr otherdef; + + virUUIDFormat(domain->uuid, uuidstr); + + /* TODO: Move this and snapshot version into virDomainMoment */ + /* Prevent circular chains */ + if (def->common.parent) { + if (STREQ(def->common.name, def->common.parent)) { + virReportError(VIR_ERR_INVALID_ARG, + _("cannot set checkpoint %s as its own parent"), + def->common.name); + return -1; + } + other = virDomainCheckpointFindByName(vm->checkpoints, def->common.parent); + if (!other) { + virReportError(VIR_ERR_INVALID_ARG, + _("parent %s for checkpoint %s not found"), + def->common.parent, def->common.name); + return -1; + } + otherdef = virDomainCheckpointObjGetDef(other); + while (otherdef->common.parent) { + if (STREQ(otherdef->common.parent, def->common.name)) { + virReportError(VIR_ERR_INVALID_ARG, + _("parent %s would create cycle to %s"), + otherdef->common.name, def->common.name); + return -1; + } + other = virDomainCheckpointFindByName(vm->checkpoints, + otherdef->common.parent); + if (!other) { + VIR_WARN("checkpoints are inconsistent for %s", + vm->def->name); + break; + } + otherdef = virDomainCheckpointObjGetDef(other); + } + } + + if (!def->common.dom || + memcmp(def->common.dom->uuid, domain->uuid, VIR_UUID_BUFLEN)) { + virReportError(VIR_ERR_INVALID_ARG, + _("definition for checkpoint %s must use uuid %s"), + def->common.name, uuidstr); + return -1; + } + if (virDomainCheckpointAlignDisks(def) < 0) + return -1; + + other = virDomainCheckpointFindByName(vm->checkpoints, def->common.name); + otherdef = other ? virDomainCheckpointObjGetDef(other) : NULL; + if (other) { + if (!virDomainDefCheckABIStability(otherdef->common.dom, + def->common.dom, xmlopt)) + return -1; + + if (other == virDomainCheckpointGetCurrent(vm->checkpoints)) { + *update_current = true; + virDomainCheckpointSetCurrent(vm->checkpoints, NULL); + } + + /* Drop and rebuild the parent relationship, but keep all + * child relations by reusing chk. */ + virDomainMomentDropParent(other); + virDomainCheckpointDefFree(otherdef); + other->def = &(*defptr)->common; + *defptr = NULL; + *chk = other; + } + + return 0; +} diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fc45d6c680..c47d961987 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -29,6 +29,7 @@ #include "configmake.h" #include "internal.h" #include "virerror.h" +#include "checkpoint_conf.h" #include "datatypes.h" #include "domain_addr.h" #include "domain_conf.h" @@ -58,6 +59,7 @@ #include "virhostdev.h" #include "virmdev.h" #include "virdomainsnapshotobjlist.h" +#include "virdomaincheckpointobjlist.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -3343,6 +3345,7 @@ static void virDomainObjDispose(void *obj) (dom->privateDataFreeFunc)(dom->privateData); virDomainSnapshotObjListFree(dom->snapshots); + virDomainCheckpointObjListFree(dom->checkpoints); } virDomainObjPtr @@ -3372,6 +3375,9 @@ virDomainObjNew(virDomainXMLOptionPtr xmlopt) if (!(domain->snapshots = virDomainSnapshotObjListNew())) goto error; + if (!(domain->checkpoints = virDomainCheckpointObjListNew())) + goto error; + virObjectLock(domain); virDomainObjSetState(domain, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN); diff --git a/src/conf/virdomaincheckpointobjlist.c b/src/conf/virdomaincheckpointobjlist.c new file mode 100644 index 0000000000..239d5e1c5b --- /dev/null +++ b/src/conf/virdomaincheckpointobjlist.c @@ -0,0 +1,222 @@ +/* + * virdomaincheckpointobjlist.c: handle a tree of checkpoint objects + * (derived from virdomainsnapshotobjlist.c) + * + * Copyright (C) 2006-2019 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "internal.h" +#include "virdomaincheckpointobjlist.h" +#include "checkpoint_conf.h" +#include "virlog.h" +#include "virerror.h" +#include "datatypes.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_DOMAIN_CHECKPOINT + +VIR_LOG_INIT("conf.virdomaincheckpointobjlist"); + +struct _virDomainCheckpointObjList { + virDomainMomentObjListPtr base; +}; + +virDomainMomentObjPtr +virDomainCheckpointAssignDef(virDomainCheckpointObjListPtr checkpoints, + virDomainCheckpointDefPtr def) +{ + return virDomainMomentAssignDef(checkpoints->base, &def->common); +} + + +static bool +virDomainCheckpointFilter(virDomainMomentObjPtr obj ATTRIBUTE_UNUSED, + unsigned int flags) +{ + /* For now, we have no further filters than what the common code handles. */ + virCheckFlags(0, false); + return true; +} + + +virDomainCheckpointObjListPtr +virDomainCheckpointObjListNew(void) +{ + virDomainCheckpointObjListPtr checkpoints; + + if (VIR_ALLOC(checkpoints) < 0) + return NULL; + checkpoints->base = virDomainMomentObjListNew(false); + if (!checkpoints->base) { + VIR_FREE(checkpoints); + return NULL; + } + return checkpoints; +} + + +void +virDomainCheckpointObjListFree(virDomainCheckpointObjListPtr checkpoints) +{ + if (!checkpoints) + return; + virDomainMomentObjListFree(checkpoints->base); + VIR_FREE(checkpoints); +} + + +static int +virDomainCheckpointObjListGetNames(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr from, + char **const names, + int maxnames, + unsigned int flags) +{ + /* We intentionally chose our public flags to match the common flags */ + verify(VIR_DOMAIN_CHECKPOINT_LIST_ROOTS == + (int) VIR_DOMAIN_MOMENT_LIST_ROOTS); + verify(VIR_DOMAIN_CHECKPOINT_LIST_TOPOLOGICAL == + (int) VIR_DOMAIN_MOMENT_LIST_TOPOLOGICAL); + verify(VIR_DOMAIN_CHECKPOINT_LIST_LEAVES == + (int) VIR_DOMAIN_MOMENT_LIST_LEAVES); + verify(VIR_DOMAIN_CHECKPOINT_LIST_NO_LEAVES == + (int) VIR_DOMAIN_MOMENT_LIST_NO_LEAVES); + verify(VIR_DOMAIN_CHECKPOINT_LIST_METADATA == + (int) VIR_DOMAIN_MOMENT_LIST_METADATA); + verify(VIR_DOMAIN_CHECKPOINT_LIST_NO_METADATA == + (int) VIR_DOMAIN_MOMENT_LIST_NO_METADATA); + + return virDomainMomentObjListGetNames(checkpoints->base, from, names, + maxnames, flags, + virDomainCheckpointFilter, 0); +} + + +virDomainMomentObjPtr +virDomainCheckpointFindByName(virDomainCheckpointObjListPtr checkpoints, + const char *name) +{ + return virDomainMomentFindByName(checkpoints->base, name); +} + + +/* Return the current checkpoint, or NULL */ +virDomainMomentObjPtr +virDomainCheckpointGetCurrent(virDomainCheckpointObjListPtr checkpoints) +{ + return virDomainMomentGetCurrent(checkpoints->base); +} + + +/* Return the current checkpoint's name, or NULL */ +const char * +virDomainCheckpointGetCurrentName(virDomainCheckpointObjListPtr checkpoints) +{ + return virDomainMomentGetCurrentName(checkpoints->base); +} + + +/* Update the current checkpoint, using NULL if no current remains */ +void +virDomainCheckpointSetCurrent(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr checkpoint) +{ + virDomainMomentSetCurrent(checkpoints->base, checkpoint); +} + + +/* Remove checkpoint from the list; return true if it was current */ +bool +virDomainCheckpointObjListRemove(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr checkpoint) +{ + return virDomainMomentObjListRemove(checkpoints->base, checkpoint); +} + + +/* Remove all checkpoints tracked in the list */ +void +virDomainCheckpointObjListRemoveAll(virDomainCheckpointObjListPtr checkpoints) +{ + return virDomainMomentObjListRemoveAll(checkpoints->base); +} + + +int +virDomainCheckpointForEach(virDomainCheckpointObjListPtr checkpoints, + virHashIterator iter, + void *data) +{ + return virDomainMomentForEach(checkpoints->base, iter, data); +} + + +/* Populate parent link and child count of all checkpoints, with all + * assigned defs having relations starting as 0/NULL. Return 0 on + * success, -1 if a parent is missing or if a circular relationship + * was requested. */ +int +virDomainCheckpointUpdateRelations(virDomainCheckpointObjListPtr checkpoints) +{ + return virDomainMomentUpdateRelations(checkpoints->base); +} + + +int +virDomainListCheckpoints(virDomainCheckpointObjListPtr checkpoints, + virDomainMomentObjPtr from, + virDomainPtr dom, + virDomainCheckpointPtr **snaps, + unsigned int flags) +{ + int count = virDomainCheckpointObjListGetNames(checkpoints, from, NULL, + 0, flags); + virDomainCheckpointPtr *list = NULL; + char **names; + int ret = -1; + size_t i; + + if (!snaps || count < 0) + return count; + if (VIR_ALLOC_N(names, count) < 0 || + VIR_ALLOC_N(list, count + 1) < 0) + goto cleanup; + + if (virDomainCheckpointObjListGetNames(checkpoints, from, names, count, + flags) < 0) + goto cleanup; + for (i = 0; i < count; i++) + if ((list[i] = virGetDomainCheckpoint(dom, names[i])) == NULL) + goto cleanup; + + ret = count; + *snaps = list; + + cleanup: + for (i = 0; i < count; i++) + VIR_FREE(names[i]); + VIR_FREE(names); + if (ret < 0 && list) { + for (i = 0; i < count; i++) + virObjectUnref(list[i]); + VIR_FREE(list); + } + return ret; +} diff --git a/src/conf/virdomainmomentobjlist.c b/src/conf/virdomainmomentobjlist.c index b9ca5b1318..299cd17d99 100644 --- a/src/conf/virdomainmomentobjlist.c +++ b/src/conf/virdomainmomentobjlist.c @@ -32,6 +32,8 @@ /* FIXME: using virObject would allow us to not need this */ #include "snapshot_conf.h" #include "virdomainsnapshotobjlist.h" +#include "checkpoint_conf.h" +#include "virdomaincheckpointobjlist.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -197,7 +199,21 @@ virDomainMomentObjNew(void) static void -virDomainMomentObjFree(virDomainMomentObjPtr moment) +virDomainCheckpointObjFree(virDomainMomentObjPtr moment) +{ + if (!moment) + return; + + VIR_DEBUG("obj=%p", moment); + + /* FIXME: Make this polymorphic by inheriting from virObject */ + virDomainCheckpointDefFree(virDomainCheckpointObjGetDef(moment)); + VIR_FREE(moment); +} + + +static void +virDomainSnapshotObjFree(virDomainMomentObjPtr moment) { if (!moment) return; @@ -238,23 +254,35 @@ virDomainMomentAssignDef(virDomainMomentObjListPtr moments, static void -virDomainMomentObjListDataFree(void *payload, - const void *name ATTRIBUTE_UNUSED) +virDomainCheckpointObjListDataFree(void *payload, + const void *name ATTRIBUTE_UNUSED) { virDomainMomentObjPtr obj = payload; - virDomainMomentObjFree(obj); + virDomainCheckpointObjFree(obj); +} + + +static void +virDomainSnapshotObjListDataFree(void *payload, + const void *name ATTRIBUTE_UNUSED) +{ + virDomainMomentObjPtr obj = payload; + + virDomainSnapshotObjFree(obj); } virDomainMomentObjListPtr -virDomainMomentObjListNew(void) +virDomainMomentObjListNew(bool snapshot) { virDomainMomentObjListPtr moments; if (VIR_ALLOC(moments) < 0) return NULL; - moments->objs = virHashCreate(50, virDomainMomentObjListDataFree); + moments->objs = virHashCreate(50, + snapshot ? virDomainSnapshotObjListDataFree : + virDomainCheckpointObjListDataFree); if (!moments->objs) { VIR_FREE(moments); return NULL; diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c index a814fc10a3..454e482869 100644 --- a/src/conf/virdomainobjlist.c +++ b/src/conf/virdomainobjlist.c @@ -1,7 +1,7 @@ /* * virdomainobjlist.c: domain objects list utilities * - * Copyright (C) 2006-2015 Red Hat, Inc. + * Copyright (C) 2006-2019 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. * @@ -25,12 +25,14 @@ #include "internal.h" #include "datatypes.h" #include "virdomainobjlist.h" +#include "checkpoint_conf.h" #include "snapshot_conf.h" #include "viralloc.h" #include "virfile.h" #include "virlog.h" #include "virstring.h" #include "virdomainsnapshotobjlist.h" +#include "virdomaincheckpointobjlist.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -880,6 +882,15 @@ virDomainObjMatchFilter(virDomainObjPtr vm, return false; } + /* filter by checkpoint existence */ + if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_CHECKPOINT)) { + int nchk = virDomainListCheckpoints(vm->checkpoints, NULL, NULL, + NULL, 0); + if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_CHECKPOINT) && nchk > 0) || + (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_CHECKPOINT) && nchk <= 0))) + return false; + } + return true; } #undef MATCH diff --git a/src/conf/virdomainsnapshotobjlist.c b/src/conf/virdomainsnapshotobjlist.c index 4ddc2a4b65..362cd1d292 100644 --- a/src/conf/virdomainsnapshotobjlist.c +++ b/src/conf/virdomainsnapshotobjlist.c @@ -86,7 +86,7 @@ virDomainSnapshotObjListNew(void) if (VIR_ALLOC(snapshots) < 0) return NULL; - snapshots->base = virDomainMomentObjListNew(); + snapshots->base = virDomainMomentObjListNew(true); if (!snapshots->base) { VIR_FREE(snapshots); return NULL; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5be63c7b3d..2aca241bd7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -70,9 +70,12 @@ virCapabilitiesSetNetPrefix; # conf/checkpoint_conf.h +virDomainCheckpointAlignDisks; virDomainCheckpointDefFormat; virDomainCheckpointDefFree; virDomainCheckpointDefParseString; +virDomainCheckpointFormatConvertXMLFlags; +virDomainCheckpointRedefinePrep; virDomainCheckpointTypeFromString; virDomainCheckpointTypeToString; @@ -968,6 +971,21 @@ virChrdevFree; virChrdevOpen; +# conf/virdomaincheckpointobjlist.h +virDomainCheckpointAssignDef; +virDomainCheckpointFindByName; +virDomainCheckpointForEach; +virDomainCheckpointGetCurrent; +virDomainCheckpointGetCurrentName; +virDomainCheckpointObjListFree; +virDomainCheckpointObjListNew; +virDomainCheckpointObjListRemove; +virDomainCheckpointObjListRemoveAll; +virDomainCheckpointSetCurrent; +virDomainCheckpointUpdateRelations; +virDomainListCheckpoints; + + # conf/virdomainmomentobjlist.h virDomainMomentDropChildren; virDomainMomentDropParent; -- 2.20.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list