From: Michal Privoznik <mprivozn@xxxxxxxxxx> Changes from previous version: 1) don't print extra/incorrect error on format failure. 2) use cleanup: instead of no_memory: and end: 3) always clear out the destination list at the start. 4) remove bogus "conn->ref++" --- src/conf/interface_conf.c | 38 ++++++++++++++++++++ src/conf/interface_conf.h | 3 ++ src/libvirt_private.syms | 1 + src/test/test_driver.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 0 deletions(-) diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c index f3848bd..10377e7 100644 --- a/src/conf/interface_conf.c +++ b/src/conf/interface_conf.c @@ -1227,6 +1227,44 @@ void virInterfaceObjListFree(virInterfaceObjListPtr interfaces) interfaces->count = 0; } +int virInterfaceObjListClone(virInterfaceObjListPtr src, + virInterfaceObjListPtr dest) +{ + int ret = -1; + unsigned int i, cnt; + + if (!src || !dest) + goto cleanup; + + virInterfaceObjListFree(dest); /* start with an empty list */ + cnt = src->count; + for (i = 0; i < cnt; i++) { + virInterfaceDefPtr def = src->objs[i]->def; + virInterfaceDefPtr backup; + virInterfaceObjPtr iface; + char *xml = virInterfaceDefFormat(def); + + if (!xml) + goto cleanup; + + if ((backup = virInterfaceDefParseString(xml)) == NULL) { + VIR_FREE(xml); + goto cleanup; + } + + VIR_FREE(xml); + if ((iface = virInterfaceAssignDef(dest, backup)) == NULL) + goto cleanup; + virInterfaceObjUnlock(iface); /* was locked by virInterfaceAssignDef */ + } + + ret = cnt; +cleanup: + if ((ret < 0) && dest) + virInterfaceObjListFree(dest); + return ret; +} + virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, const virInterfaceDefPtr def) { diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 6073b49..c5630d4 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -192,6 +192,9 @@ virInterfaceObjPtr virInterfaceFindByName(const virInterfaceObjListPtr void virInterfaceDefFree(virInterfaceDefPtr def); void virInterfaceObjFree(virInterfaceObjPtr iface); void virInterfaceObjListFree(virInterfaceObjListPtr vms); +int virInterfaceObjListClone(virInterfaceObjListPtr src, + virInterfaceObjListPtr dest); + virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, const virInterfaceDefPtr def); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4cb8dda..5f7fdb2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -485,6 +485,7 @@ virInterfaceDefParseNode; virInterfaceDefParseString; virInterfaceFindByMACString; virInterfaceFindByName; +virInterfaceObjListClone; virInterfaceObjListFree; virInterfaceObjLock; virInterfaceObjUnlock; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index e86bc4e..b703e9b 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -85,6 +85,8 @@ struct _testConn { virDomainObjList domains; virNetworkObjList networks; virInterfaceObjList ifaces; + bool transaction_running; + virInterfaceObjList backupIfaces; virStoragePoolObjList pools; virNodeDeviceObjList devs; int numCells; @@ -3455,6 +3457,84 @@ cleanup: return ret; } +static int testInterfaceChangeBegin(virConnectPtr conn, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = conn->privateData; + int ret = -1; + + testDriverLock(privconn); + if (privconn->transaction_running) { + testError(VIR_ERR_OPERATION_INVALID, + _("there is another transaction running.")); + goto cleanup; + } + + privconn->transaction_running = true; + + if (virInterfaceObjListClone(&privconn->ifaces, + &privconn->backupIfaces) < 0) + goto cleanup; + + ret = 0; +cleanup: + testDriverUnlock(privconn); + return ret; +} + +static int testInterfaceChangeCommit(virConnectPtr conn, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = conn->privateData; + int ret = -1; + + testDriverLock(privconn); + + if (!privconn->transaction_running) { + testError(VIR_ERR_OPERATION_INVALID, _("no transaction running, " + "nothing to be commited.")); + goto cleanup; + } + + virInterfaceObjListFree(&privconn->backupIfaces); + privconn->transaction_running = false; + + ret = 0; + +cleanup: + testDriverUnlock(privconn); + + return ret; +} + +static int testInterfaceChangeRollback(virConnectPtr conn, + unsigned int flags ATTRIBUTE_UNUSED) +{ + testConnPtr privconn = conn->privateData; + int ret = -1; + + testDriverLock(privconn); + + if (!privconn->transaction_running) { + testError(VIR_ERR_OPERATION_INVALID, _("no transaction running, " + "nothing to rollback.")); + goto cleanup; + } + + virInterfaceObjListFree(&privconn->ifaces); + privconn->ifaces.count = privconn->backupIfaces.count; + privconn->ifaces.objs = privconn->backupIfaces.objs; + privconn->backupIfaces.count = 0; + privconn->backupIfaces.objs = NULL; + + privconn->transaction_running = false; + + ret = 0; + +cleanup: + testDriverUnlock(privconn); + return ret; +} static char *testInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags ATTRIBUTE_UNUSED) @@ -5428,6 +5508,9 @@ static virInterfaceDriver testInterfaceDriver = { .interfaceCreate = testInterfaceCreate, /* 0.7.0 */ .interfaceDestroy = testInterfaceDestroy, /* 0.7.0 */ .interfaceIsActive = testInterfaceIsActive, /* 0.7.3 */ + .interfaceChangeBegin = testInterfaceChangeBegin, /* 0.9.2 */ + .interfaceChangeCommit = testInterfaceChangeCommit, /* 0.9.2 */ + .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */ }; -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list