[libvirt] [PATCH] vbox: fix a bug in _machineStateInactive
This function returned non-inactive domains instead of active domains. This broke virConnectNumOfDefinedDomains() and virConnectListDefinedDomains() functions. --- src/vbox/vbox_tmpl.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index de8744d..37ec8e1 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -4607,8 +4607,8 @@ static bool _machineStateOnline(PRUint32 state) static bool _machineStateInactive(PRUint32 state) { -return ((state MachineState_FirstOnline) -(state MachineState_LastOnline)); +return ((state MachineState_FirstOnline) || +(state MachineState_LastOnline)); } static bool _machineStateNotStart(PRUint32 state) -- 1.7.10.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 00/66] vbox: Rewrite vbox domain driver
Le Wednesday 13 August 2014 17:18:44, Michal Privoznik a écrit : [CC-ing Yohan BELLEGUIC and Manuel VIVES] On 12.08.2014 17:31, Michal Privoznik wrote: On 11.08.2014 12:06, Taowei wrote: This series of patches rewrite the vbox's domain driver. The driver is separated into two parts: the version specified and the common part. The common driver use vboxUniformedAPI to build a general driver for all vbox versions. The vboxUniformedAPI take the responsiblity to communicate with virtualbox. Since there are some incompatible changes in virtualbox, vboxUniformedAPI should be aware of these changes and provide a uniformed api for the upper layer. The significant result of this patch is that we replace all vir${vbox_version}Driver into one virCommonDriver. So, we will have only one vbox driver implementation for all vbox versions in libvirt. PS: I have send part of my patches before: https://www.redhat.com/archives/libvir-list/2014-July/msg00937.html But I have to resend it beacuse I did some improvement on previous patches: *Remove the test case for vboxUniformedAPI, because it would raise break strict-aliasing rules warning in some distibutions *Merged the flag fdWatchNeedInitialize into domainEventCallbacks, So, we use one flag to indicate whether vbox support callbacks as well as we need to initialize variables for it. Taowei (66): vbox: Begin to rewrite, vboxConnectOpen vbox: Rewrite vboxConnectClose vbox: Rewrite vboxDomainSave vbox: Rewrite vboxConnectGetVersion vbox: Rewrite vboxConnectGetHostname vbox: Rewrite vboxConnectIsSecure vbox: Rewrite vboxConnectIsEncrypted vbox: Rewrite vboxConnectIsAlive vbox: Rewrite vboxConnectGetMaxVcpus vbox: Rewrite vboxConnectGetCapabilities vbox: Rewrite vboxConnectListDomains vbox: Rewrite vboxConnectNumOfDomains vbox: Rewrite vboxDomainLookupById vbox: Rewrite vboxDomainLookupByUUID vbox: Rewrite vboxDomainUndefineFlags vbox: Rewrite vboxDomainDefineXML vbox: Rewrite vboxDomainCreateWithFlags vbox: Rewrite vboxDomainCreate vbox: Rewrite vboxDomainCreateXML vbox: Rewrite vboxDomainLookupByName vbox: Rewrite vboxDomainIsActive vbox: Rewrite vboxDomainIsPersistent vbox: Rewrite vboxDomainIsUpdated vbox: Rewrite vboxDomainSuspend vbox: Rewrite vboxDomainResume vbox: Rewrite vboxDomainShutdownFlags vbox: Rewrite vboxDomainShutdown vbox: Rewrite vboxDomainReboot vbox: Rewrite vboxDomainDestroyFlags vbox: Rewrite vboxDomainDestroy vbox: Rewrite vboxDomainGetOSType vbox: Rewrite vboxDomainSetMemory vbox: Rewrite vboxDomainGetInfo vbox: Rewrite vboxDomainGetState vbox: Rewrite vboxDomainSetVcpusFlags vbox: Rewrite vboxDomainSetVcpus vbox: Rewrite vboxDomainGetVcpusFlags vbox: Rewrite vboxDomainGetMaxVcpus vbox: Add API for vboxDomainGetXMLDesc vbox: Rewrite vboxDomainGetXMLDesc vbox: Rewrite vboxConnectListDefinedDomains vbox: Rewrite vboxConnectNumOfDefinedDomains vbox: Rewrite vboxDomainUndefine vbox: Rewrite vboxDomainAttachDevice vbox: Rewrite vboxDomainAttachDeviceFlags vbox: Rewrite vboxDomainUpdateDeviceFlags vbox: Rewrite vboxDomainDetachDevice vbox: Rewrite vboxDomainDetachDeviceFlags vbox: Add API for vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotCreateXML vbox: Rewrite vboxDomainSnapshotGetXMLDesc vbox: Rewrite vboxDomainSnapshotNum vbox: Rewrite vboxDomainSnapshotListNames vbox: Rewrite vboxSnapshotLookupByName vbox: Rewrite vboxDomainHasCurrentSnapshot vbox: Rewrite vboxDomainSnapshotGetParent vbox: Rewrite vboxDomainSnapshotCurrent vbox: Rewrite vboxDomainSnapshotIsCurrent vbox: Rewrite vboxDomainSnapshotHasMetadata vbox: Rewrite vboxDomainRevertToSnapshot vbox: Rewrite vboxDomainSnapshotDelete vbox: Rewrite vboxDomainScreenshot vbox: Rewrite vboxConnectListAllDomains vbox: Rewrite vboxNode functions vbox: Add registerDomainEvent vbox: Introducing vboxCommonDriver po/POTFILES.in|1 + src/Makefile.am |5 +- src/vbox/README |7 +- src/vbox/vbox_common.c| 7550 + src/vbox/vbox_common.h| 306 + src/vbox/vbox_driver.c| 40 +- src/vbox/vbox_install_api.h | 26 + src/vbox/vbox_tmpl.c |14557 + src/vbox/vbox_uniformed_api.h | 551 ++ 9 files changed, 13186 insertions(+), 9857 deletions(-) create mode 100644 src/vbox/vbox_common.c create mode 100644 src/vbox/vbox_common.h create mode 100644 src/vbox/vbox_install_api.h create mode 100644 src/vbox/vbox_uniformed_api.h ACK to all the patches. I've fixed all the small nits I found. I'm keeping
[libvirt] [PATCH] vbox: fix a segfault when taking a snapshot
there is a segfault in the vbox driver when taking a snapshot in the following functions: - vboxDomainGetXMLDesc - vboxSnapshotGetReadWriteDisks - vboxSnapshotGetReadOnlyDisks The virStorageSourcePtr in virDomainDiskDef was not correctly allocated. --- src/vbox/vbox_tmpl.c | 24 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 1ed2729..6365f2a 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -2872,10 +2872,12 @@ static char *vboxDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) { /* Allocate mem, if fails return error */ if (VIR_ALLOC_N(def-disks, def-ndisks) = 0) { for (i = 0; i def-ndisks; i++) { -if (VIR_ALLOC(def-disks[i]) 0) { +virDomainDiskDefPtr disk = virDomainDiskDefNew(); +if (!disk) { error = true; break; } +def-disks[i] = disk; } } else { error = true; @@ -7175,6 +7177,10 @@ int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, /* Allocate mem, if fails return error */ if (VIR_ALLOC_N(def-disks, def-ndisks) 0) goto cleanup; +for (i = 0; i def-ndisks; i++) { +if (VIR_ALLOC(def-disks[i].src) 0) +goto cleanup; +} if (!vboxGetMaxPortSlotValues(data-vboxObj, maxPortPerInst, maxSlotPerPort)) goto cleanup; @@ -7302,11 +7308,11 @@ int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, ret = 0; cleanup: if (ret 0) { -for (i = 0; i def-dom-ndisks; i++) -VIR_FREE(def-dom-disks[i]); -VIR_FREE(def-dom-disks); -def-dom-ndisks = 0; -ret = -1; +for (i = 0; i def-ndisks; i++) { +VIR_FREE(def-disks[i].src); +} +VIR_FREE(def-disks); +def-ndisks = 0; } VBOX_RELEASE(snap); return ret; @@ -7380,8 +7386,10 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, /* Allocate mem, if fails return error */ if (VIR_ALLOC_N(def-dom-disks, def-dom-ndisks) = 0) { for (i = 0; i def-dom-ndisks; i++) { -if (VIR_ALLOC(def-dom-disks[i]) 0) +virDomainDiskDefPtr diskDef = virDomainDiskDefNew(); +if (!diskDef) goto cleanup; +def-dom-disks[i] = diskDef; } } else { goto cleanup; @@ -7516,7 +7524,7 @@ int vboxSnapshotGetReadOnlyDisks(virDomainSnapshotPtr snapshot, cleanup: if (ret 0) { for (i = 0; i def-dom-ndisks; i++) -VIR_FREE(def-dom-disks[i]); +virDomainDiskDefFree(def-dom-disks[i]); VIR_FREE(def-dom-disks); def-dom-ndisks = 0; } -- 1.7.10.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/3] vbox: snapshot: Avoid memleak in virVBoxSnapshotConfAllChildren
Le Tuesday 17 June 2014 11:24:08, Peter Krempa a écrit : On re-allocation failure the function would leak already allocated memory. --- src/vbox/vbox_snapshot_conf.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vbox/vbox_snapshot_conf.c b/src/vbox/vbox_snapshot_conf.c index 30ac6fe..69c7e42 100644 --- a/src/vbox/vbox_snapshot_conf.c +++ b/src/vbox/vbox_snapshot_conf.c @@ -483,18 +483,24 @@ virVBoxSnapshotConfAllChildren(virVBoxSnapshotConfHardDiskPtr disk, for (i = 0; i disk-nchildren; i++) { tempSize = virVBoxSnapshotConfAllChildren(disk-children[i], tempList); if (VIR_EXPAND_N(ret, returnSize, tempSize) 0) -return 0; +goto error; for (j = 0; j tempSize; j++) { ret[returnSize - tempSize + j] = tempList[j]; } } if (VIR_EXPAND_N(ret, returnSize, 1) 0) -return 0; +goto error; ret[returnSize - 1] = disk; *list = ret; return returnSize; + + error: +for (i = 0; i returnSize; i++) +virVboxSnapshotConfHardDiskFree(ret[i]); +VIR_FREE(ret); +return 0; } I think we don't have to use virVboxSnapshotConfHardDiskFree because there is not memory allocation in this function. It's just a pointer recopy, so if the disks are freed, this might lead to a segfault or a bad behaviour. void -- Yohan BELLEGUIC Software Engineer - diateam : Architectes de l'information Phone : +33 (0)2 98 050 050 Fax : +33 (0)2 98 050 05 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/3] vbox: snapshot: Avoid memleaks in functions dealing with disk arrays
Le Tuesday 17 June 2014 11:24:09, Peter Krempa a écrit : In virVBoxSnapshotConfRemoveFakeDisks and virVBoxSnapshotConfDiskIsInMediaRegistry the disk array constructed from all the disks would be leaked at the end of the function and on allocation errors. Also the temporary disk list would be leaked. Add a cleanup section and free the memory properly. Found by coverity. --- src/vbox/vbox_snapshot_conf.c | 54 +++ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/vbox/vbox_snapshot_conf.c b/src/vbox/vbox_snapshot_conf.c index 69c7e42..49fd2b6 100644 --- a/src/vbox/vbox_snapshot_conf.c +++ b/src/vbox/vbox_snapshot_conf.c @@ -1471,28 +1471,45 @@ virVBoxSnapshotConfRemoveFakeDisks(virVBoxSnapshotConfMachinePtr machine) size_t diskSize = 0; virVBoxSnapshotConfHardDiskPtr *tempList = NULL; virVBoxSnapshotConfHardDiskPtr *diskList = NULL; + if (VIR_ALLOC_N(diskList, 0) 0) -return ret; +return -1; for (i = 0; i machine-mediaRegistry-ndisks; i++) { tempSize = virVBoxSnapshotConfAllChildren(machine-mediaRegistry-disks[i], tempList); if (VIR_EXPAND_N(diskList, diskSize, tempSize) 0) -return ret; -for (j = 0; j tempSize; j++) { +goto cleanup; + +for (j = 0; j tempSize; j++) diskList[diskSize - tempSize + j] = tempList[j]; -} + +VIR_FREE(tempList); } + for (i = 0; i diskSize; i++) { if (strstr(diskList[i]-location, fake) != NULL) { if (virVBoxSnapshotConfRemoveHardDisk(machine-mediaRegistry, diskList[i]-uuid) 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _(Unable to remove hard disk %s from media registry), diskList[i]-location); -return ret; +goto cleanup; } } } + ret = 0; + + cleanup: +for (i = 0; i diskSize; i++) +virVboxSnapshotConfHardDiskFree(diskList[i]); +VIR_FREE(diskList); + +if (tempList) { +for (i = 0; i tempSize; i++) +virVboxSnapshotConfHardDiskFree(tempList[i]); +VIR_FREE(tempList); +} Same comments than the previous patch + return ret; } @@ -1513,24 +1530,41 @@ virVBoxSnapshotConfDiskIsInMediaRegistry(virVBoxSnapshotConfMachinePtr machine, size_t diskSize = 0; virVBoxSnapshotConfHardDiskPtr *tempList = NULL; virVBoxSnapshotConfHardDiskPtr *diskList = NULL; + if (VIR_ALLOC_N(diskList, 0) 0) -return ret; +return -1; for (i = 0; i machine-mediaRegistry-ndisks; i++) { tempSize = virVBoxSnapshotConfAllChildren(machine-mediaRegistry-disks[i], tempList); if (VIR_EXPAND_N(diskList, diskSize, tempSize) 0) -return ret; -for (j = 0; j tempSize; j++) { +goto cleanup; + +for (j = 0; j tempSize; j++) diskList[diskSize - tempSize + j] = tempList[j]; -} + +VIR_FREE(tempList); } + for (i = 0; i diskSize; i++) { if (STREQ(diskList[i]-location, location)) { ret = 1; -return ret; +goto cleanup; } } + ret = 0; + + cleanup: +for (i = 0; i diskSize; i++) +virVboxSnapshotConfHardDiskFree(diskList[i]); +VIR_FREE(diskList); + +if (tempList) { +for (i = 0; i tempSize; i++) +virVboxSnapshotConfHardDiskFree(tempList[i]); +VIR_FREE(tempList); +} Same comments than the previous patch + return ret; } -- Yohan BELLEGUIC Software Engineer - diateam : Architectes de l'information Phone : +33 (0)2 98 050 050 Fax : +33 (0)2 98 050 05 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v8 0/4] Handling of undefine and re define snapshots with VirtualBox 4.2 or higher
Hello, This is a new series of patches in order to support undefining and redefining snapshots with VirtualBox 4.2 or higher. These patches are based on Manuel Vives' patches, taking into account Daniel P. Berrange's remarks. The VirtualBox API provides only high level operations to manipulate snapshots, so it not possible to support flags like VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE and VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY with only API calls. Following an IRC talk with Eric Blake, the decision was made to emulate these behaviours by manipulating directly the .vbox XML files. The first patch adds extra details in the snapshot XML returned by libvirt. We will need those details in order to redefine the snapshots. The second patch adds a new API to manipulate the VirtualBox XML file. It provides several structs describing the VirtualBox XML file nodes and functions which can manipulate these structs. The third patch adds support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML. The idea is to unregister the machine, add the snapshot in the Virtualbox XML file and re-register the machine. However, VirtualBox forbids a machine to have snapshots but no current snapshot. So, if the real current snapshot has not been redefined yet, we create fake disks, allowing us to have an intermediate state in order to not corrupt the snapshot's read-write disks. These fake disks will be deleted during the next redefine. The fourth and last patch adds support of the VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY flag in virDomainSnapshotDelete. As in the third patch, we also create fake disks to not corrupt the snapshot's read-write disks. The patches were only tested with VirtualBox 4.3.10 and VirtualBox 4.2.24. Regards Yohan BELLEGUIC v8: * Fix patches according to Daniel P. Berrange review (May 01, 2014) * Rename all the methods in vbox_snapshot.{c,h} * Add a test case for serialize and deserialize a virVBoxSnapshotConfMachine * Fix memory leaks v7: * Add vbox_snapshot_conf.{h,c} files to (de)serialize VirtualBox XML files * Update the code to use the API exposed by vbox_snapshot_conf.h * Handle the fact that VirtualBox forbids a machine to have snapshots but no current snapshot v6: * Rebased because of a massive change in vbox_tmpl.c due to changes in the handling of different versions of VirtualBox v5: * The patches are modified according to a first review by Laine Stump: * renamed virSearchUuid to virSearchRegex and moved it from viruuid.{c,h} to virstring.{c,h}. * Various fixes. v4: * The code is compliant with Virtualbox 4.3 API * Some minor modifications in order to satisfy make syntax-check v3: * Use of STREQ_NULLABLE instead of STREQ in one case * Fix the method for finding uuids according to Ján Tomko review v2: * Fix a licence problem with the method for string replacement Manuel VIVES (1): vbox_tmpl.c: Better XML description for snapshots Yohan BELLEGUIC (3): Add vbox_snapshot_conf struct vbox_tmpl.c: Patch for redefining snapshots vbox_tmpl.c: Add function for undefining snapshot po/POTFILES.in |1 + src/Makefile.am|1 + src/vbox/vbox_snapshot_conf.c | 1490 +++ src/vbox/vbox_snapshot_conf.h | 105 ++ src/vbox/vbox_tmpl.c | 1982 +++- tests/Makefile.am | 15 + tests/vboxsnapshotxmldata/2disks-1snap.vbox| 322 tests/vboxsnapshotxmldata/2disks-2snap.vbox| 478 + .../vboxsnapshotxmldata/2disks-3snap-brother.vbox | 786 tests/vboxsnapshotxmldata/2disks-3snap.vbox| 636 +++ tests/vboxsnapshotxmldata/2disks-nosnap.vbox | 168 ++ tests/vboxsnapshotxmltest.c| 161 ++ 12 files changed, 6100 insertions(+), 45 deletions(-) create mode 100644 src/vbox/vbox_snapshot_conf.c create mode 100644 src/vbox/vbox_snapshot_conf.h create mode 100644 tests/vboxsnapshotxmldata/2disks-1snap.vbox create mode 100644 tests/vboxsnapshotxmldata/2disks-2snap.vbox create mode 100644 tests/vboxsnapshotxmldata/2disks-3snap-brother.vbox create mode 100644 tests/vboxsnapshotxmldata/2disks-3snap.vbox create mode 100644 tests/vboxsnapshotxmldata/2disks-nosnap.vbox create mode 100644 tests/vboxsnapshotxmltest.c -- 1.7.10.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v8 1/4] vbox_tmpl.c: Better XML description for snapshots
From: Manuel VIVES manuel.vi...@diateam.net It will be needed for the future patches because we will redefine snapshots --- src/vbox/vbox_tmpl.c | 476 +- 1 file changed, 471 insertions(+), 5 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index e124e69..5d4a7ba 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -58,6 +58,8 @@ #include fdstream.h #include viruri.h #include virstring.h +#include virtime.h +#include virutil.h /* This one changes from version to version. */ #if VBOX_API_VERSION == 2002000 @@ -6039,7 +6041,9 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL); if (!(def = virDomainSnapshotDefParseString(xmlDesc, data-caps, -data-xmlopt, 0, 0))) +data-xmlopt, -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) goto cleanup; if (def-ndisks) { @@ -6130,6 +6134,431 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, return ret; } +#if VBOX_API_VERSION =4002000 +static +int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, +virDomainSnapshotPtr snapshot) +{ +virDomainPtr dom = snapshot-domain; +VBOX_OBJECT_CHECK(dom-conn, int, -1); +vboxIID domiid = VBOX_IID_INITIALIZER; +IMachine *machine = NULL; +ISnapshot *snap = NULL; +IMachine *snapMachine = NULL; +vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; +PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; +PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; +int diskCount = 0; +nsresult rc; +vboxIID snapIid = VBOX_IID_INITIALIZER; +char *snapshotUuidStr = NULL; +size_t i = 0; + +vboxIIDFromUUID(domiid, dom-uuid); +rc = VBOX_OBJECT_GET_MACHINE(domiid.value, machine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(no domain with matching UUID)); +goto cleanup; +} +if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot-name))) +goto cleanup; + +rc = snap-vtbl-GetId(snap, snapIid.value); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Could not get snapshot id)); +goto cleanup; +} + +VBOX_UTF16_TO_UTF8(snapIid.value, snapshotUuidStr); +rc = snap-vtbl-GetMachine(snap, snapMachine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(could not get machine)); +goto cleanup; +} +def-ndisks = 0; +rc = vboxArrayGet(mediumAttachments, snapMachine, snapMachine-vtbl-GetMediumAttachments); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(no medium attachments)); +goto cleanup; +} +/* get the number of attachments */ +for (i = 0; i mediumAttachments.count; i++) { +IMediumAttachment *imediumattach = mediumAttachments.items[i]; +if (imediumattach) { +IMedium *medium = NULL; + +rc = imediumattach-vtbl-GetMedium(imediumattach, medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get medium)); +goto cleanup; +} +if (medium) { +def-ndisks++; +VBOX_RELEASE(medium); +} +} +} +/* Allocate mem, if fails return error */ +if (VIR_ALLOC_N(def-disks, def-ndisks) 0) +goto cleanup; + +if (!vboxGetMaxPortSlotValues(data-vboxObj, maxPortPerInst, maxSlotPerPort)) +goto cleanup; + +/* get the attachment details here */ +for (i = 0; i mediumAttachments.count diskCount def-ndisks; i++) { +IStorageController *storageController = NULL; +PRUnichar *storageControllerName = NULL; +PRUint32 deviceType = DeviceType_Null; +PRUint32 storageBus = StorageBus_Null; +IMedium *disk = NULL; +PRUnichar *childLocUtf16 = NULL; +char *childLocUtf8 = NULL; +PRUint32 deviceInst = 0; +PRInt32devicePort = 0; +PRInt32deviceSlot = 0; +vboxArray children = VBOX_ARRAY_INITIALIZER; +vboxArray snapshotIids = VBOX_ARRAY_INITIALIZER; +IMediumAttachment *imediumattach = mediumAttachments.items[i]; +size_t j = 0; +size_t k = 0; +if (!imediumattach) +continue; +rc = imediumattach-vtbl-GetMedium(imediumattach, disk); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, +
[libvirt] [PATCH v8 4/4] vbox_tmpl.c: Add function for undefining snapshot
All snapshots information will be deleted from the vbox XML, but differencing disks will be kept so the user will be able to redefine the snapshot. --- src/vbox/vbox_tmpl.c | 464 +- 1 file changed, 463 insertions(+), 1 deletion(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a7f15d4..eb577f4 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8364,7 +8364,454 @@ vboxDomainSnapshotDeleteTree(vboxGlobalData *data, return ret; } +#if VBOX_API_VERSION = 4002000 +static int +vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) +{ +/* + * This function will remove the node in the vbox xml corresponding to the snapshot. + * It is usually called by vboxDomainSnapshotDelete() with the flag + * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY. + * If you want to use it anywhere else, be careful, if the snapshot you want to delete + * has children, the result is not granted, they will probably will be deleted in the + * xml, but you may have a problem with hard drives. + * + * If the snapshot which is being deleted is the current one, we will set the current + * snapshot of the machine to the parent of this snapshot. Before writing the modified + * xml file, we undefine the machine from vbox. After writing the file, we redefine + * the machine with the new file. + */ + +virDomainPtr dom = snapshot-domain; +VBOX_OBJECT_CHECK(dom-conn, int, -1); +virDomainSnapshotDefPtr def= NULL; +char *defXml = NULL; +vboxIID domiid = VBOX_IID_INITIALIZER; +nsresult rc; +IMachine *machine = NULL; +PRUnichar *settingsFilePathUtf16 = NULL; +char *settingsFilepath = NULL; +virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; +int isCurrent = -1; +int it = 0; +PRUnichar *machineNameUtf16 = NULL; +char *machineName = NULL; +char *nameTmpUse = NULL; +char *machineLocationPath = NULL; +PRUint32 aMediaSize = 0; +IMedium **aMedia = NULL; +defXml = vboxDomainSnapshotGetXMLDesc(snapshot, 0); +if (!defXml) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get XML Desc of snapshot)); +goto cleanup; +} +def = virDomainSnapshotDefParseString(defXml, + data-caps, + data-xmlopt, + -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); +if (!def) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get a virDomainSnapshotDefPtr)); +goto cleanup; +} + +vboxIIDFromUUID(domiid, dom-uuid); +rc = VBOX_OBJECT_GET_MACHINE(domiid.value, machine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_NO_DOMAIN, %s, + _(no domain with matching UUID)); +goto cleanup; +} +rc = machine-vtbl-GetSettingsFilePath(machine, settingsFilePathUtf16); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get settings file path)); +goto cleanup; +} +VBOX_UTF16_TO_UTF8(settingsFilePathUtf16, settingsFilepath); + +/*Getting the machine name to retrieve the machine location path.*/ +rc = machine-vtbl-GetName(machine, machineNameUtf16); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get machine name)); +goto cleanup; +} +VBOX_UTF16_TO_UTF8(machineNameUtf16, machineName); +if (virAsprintf(nameTmpUse, %s.vbox, machineName) 0) +goto cleanup; +machineLocationPath = virStringReplace(settingsFilepath, nameTmpUse, ); +if (machineLocationPath == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get the machine location path)); +goto cleanup; +} +snapshotMachineDesc = virVBoxSnapshotConfLoadVboxFile(settingsFilepath, machineLocationPath); +if (!snapshotMachineDesc) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot create a vboxSnapshotXmlPtr)); +goto cleanup; +} + +isCurrent = virVBoxSnapshotConfIsCurrentSnapshot(snapshotMachineDesc, def-name); +if (isCurrent 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to know if the snapshot is the current snapshot)); +goto cleanup; +} +if (isCurrent) { +/* + * If the snapshot is the current snapshot, it means that the machine has read-write + * disks. The first thing to do is to manipulate VirtualBox API to create + * differential read-write disks if the parent snapshot is not null. + */ +if (def-parent != NULL) { +
[libvirt] [PATCH v8 3/4] vbox_tmpl.c: Patch for redefining snapshots
The machine is unregistered and its vbox XML file is changed in order to add snapshot information. The machine is then registered with the snapshot to redefine. --- src/vbox/vbox_tmpl.c | 976 +- 1 file changed, 970 insertions(+), 6 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 5d4a7ba..a7f15d4 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -43,6 +43,7 @@ #include datatypes.h #include domain_conf.h #include snapshot_conf.h +#include vbox_snapshot_conf.h #include network_conf.h #include virerror.h #include domain_event.h @@ -6015,6 +6016,958 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } +#if VBOX_API_VERSION = 4002000 +static int vboxCloseDisksRecursively(virDomainPtr dom, char *location) +{ +VBOX_OBJECT_CHECK(dom-conn, int, -1); +nsresult rc; +size_t i = 0; +PRUnichar *locationUtf = NULL; +IMedium *medium = NULL; +IMedium **children = NULL; +PRUint32 childrenSize = 0; +VBOX_UTF8_TO_UTF16(location, locationUtf); +rc = data-vboxObj-vtbl-OpenMedium(data-vboxObj, + locationUtf, + DeviceType_HardDisk, + AccessMode_ReadWrite, + false, + medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Unable to open HardDisk, rc=%08x), + (unsigned)rc); +goto cleanup; +} +rc = medium-vtbl-GetChildren(medium, childrenSize, children); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s + , _(Unable to get disk children)); +goto cleanup; +} +for (i = 0; i childrenSize; i++) { +IMedium *childMedium = children[i]; +if (childMedium) { +PRUnichar *childLocationUtf = NULL; +char *childLocation = NULL; +rc = childMedium-vtbl-GetLocation(childMedium, childLocationUtf); +VBOX_UTF16_TO_UTF8(childLocationUtf, childLocation); +VBOX_UTF16_FREE(childLocationUtf); +if (vboxCloseDisksRecursively(dom, childLocation) 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s + , _(Unable to close disk children)); +goto cleanup; +} +VIR_FREE(childLocation); +} +} +rc = medium-vtbl-Close(medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, + _(Unable to close HardDisk, rc=%08x), + (unsigned)rc); +goto cleanup; +} + +ret = 0; + cleanup: +VBOX_UTF16_FREE(locationUtf); +return ret; +} + +static int +vboxSnapshotRedefine(virDomainPtr dom, + virDomainSnapshotDefPtr def, + bool isCurrent) +{ +/* + * If your snapshot has a parent, + * it will only be redefined if you have already + * redefined the parent. + * + * The general algorithm of this function is below : + * First of all, we are going to create our vboxSnapshotXmlMachinePtr struct from + * the machine settings path. + * Then, if the machine current snapshot xml file is saved in the machine location, + * it means that this snapshot was previously modified by us and has fake disks. + * Fake disks are added when the flag VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT was not set + * yet, in order to not corrupt read-only disks. The first thing to do is to remove those + * disks and restore the read-write disks, if any, in the vboxSnapshotXmlMachinePtr struct. + * We also delete the current snapshot xml file. + * + * After that, we are going to register the snapshot read-only disks that we want to redefine, + * if they are not in the media registry struct. + * + * The next step is to unregister the machine and close all disks. + * + * Then, we check if the flag VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE has already been set. + * If this flag was set, we just add read-write disks to the media registry + * struct. Otherwise, we save the snapshot xml file into the machine location in order + * to recover the read-write disks during the next redefine and we create differential disks + * from the snapshot read-only disks and add them to the media registry struct. + * + * Finally, we register the machine with the new virtualbox description file. + */ +VBOX_OBJECT_CHECK(dom-conn, int, -1); +vboxIID domiid = VBOX_IID_INITIALIZER; +IMachine *machine = NULL; +nsresult rc; +PRUnichar *settingsFilePath = NULL; +char *settingsFilePath_Utf8 = NULL; +virVBoxSnapshotConfMachinePtr snapshotMachineDesc = NULL; +char *currentSnapshotXmlFilePath = NULL; +
[libvirt] [PATCH v7 1/4] vbox_tmpl.c: Better XML description for snapshots
From: Manuel VIVES manuel.vi...@diateam.net It will be needed for the future patches because we will redefine snapshots --- src/vbox/vbox_tmpl.c | 513 +- 1 file changed, 504 insertions(+), 9 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index a305fe2..ac000cf 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -38,6 +38,7 @@ #include sys/types.h #include sys/stat.h #include fcntl.h +#include libxml/xmlwriter.h #include internal.h #include datatypes.h @@ -58,6 +59,8 @@ #include fdstream.h #include viruri.h #include virstring.h +#include virtime.h +#include virutil.h /* This one changes from version to version. */ #if VBOX_API_VERSION == 2002000 @@ -294,6 +297,13 @@ static void vboxDriverUnlock(vboxGlobalData *data) virMutexUnlock(data-lock); } +typedef enum { +VBOX_STORAGE_DELETE_FLAG = 0, +#if VBOX_API_VERSION = 4002000 +VBOX_STORAGE_CLOSE_FLAG = 1, +#endif +} vboxStorageDeleteOrCloseFlags; + #if VBOX_API_VERSION == 2002000 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) @@ -6039,7 +6049,9 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, NULL); if (!(def = virDomainSnapshotDefParseString(xmlDesc, data-caps, -data-xmlopt, 0, 0))) +data-xmlopt, -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE))) goto cleanup; if (def-ndisks) { @@ -6130,6 +6142,436 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom, return ret; } +#if VBOX_API_VERSION =4002000 +static +int vboxSnapshotGetReadWriteDisks(virDomainSnapshotDefPtr def, +virDomainSnapshotPtr snapshot) +{ +virDomainPtr dom = snapshot-domain; +VBOX_OBJECT_CHECK(dom-conn, int, -1); +vboxIID domiid = VBOX_IID_INITIALIZER; +IMachine *machine = NULL; +ISnapshot *snap = NULL; +IMachine *snapMachine = NULL; +vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER; +PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {}; +PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {}; +int diskCount = 0; +nsresult rc; +vboxIID snapIid = VBOX_IID_INITIALIZER; +char *snapshotUuidStr = NULL; +size_t i = 0; + +vboxIIDFromUUID(domiid, dom-uuid); +rc = VBOX_OBJECT_GET_MACHINE(domiid.value, machine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(no domain with matching UUID)); +goto cleanup; +} +if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot-name))) +goto cleanup; + +rc = snap-vtbl-GetId(snap, snapIid.value); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Could not get snapshot id)); +goto cleanup; +} + +VBOX_UTF16_TO_UTF8(snapIid.value, snapshotUuidStr); +rc = snap-vtbl-GetMachine(snap, snapMachine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(could not get machine)); +goto cleanup; +} +def-ndisks = 0; +rc = vboxArrayGet(mediumAttachments, snapMachine, snapMachine-vtbl-GetMediumAttachments); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(no medium attachments)); +goto cleanup; +} +/* get the number of attachments */ +for (i = 0; i mediumAttachments.count; i++) { +IMediumAttachment *imediumattach = mediumAttachments.items[i]; +if (imediumattach) { +IMedium *medium = NULL; + +rc = imediumattach-vtbl-GetMedium(imediumattach, medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get medium)); +goto cleanup; +} +if (medium) { +def-ndisks++; +VBOX_RELEASE(medium); +} +} +} +/* Allocate mem, if fails return error */ +if (VIR_ALLOC_N(def-disks, def-ndisks) 0) +goto cleanup; + +if (!vboxGetMaxPortSlotValues(data-vboxObj, maxPortPerInst, maxSlotPerPort)) +goto cleanup; + +/* get the attachment details here */ +for (i = 0; i mediumAttachments.count diskCount def-ndisks; i++) { +IStorageController *storageController = NULL; +PRUnichar *storageControllerName = NULL; +PRUint32 deviceType = DeviceType_Null; +PRUint32 storageBus = StorageBus_Null; +IMedium *disk = NULL; +PRUnichar *childLocUtf16 = NULL; +char *childLocUtf8 = NULL; +PRUint32 deviceInst = 0; +PRInt32
[libvirt] [PATCH v7 0/4] Handling of undefine and re define snapshots with VirtualBox 4.2 or higher
Hello, This is a new series of patches in order to support undefining and redefining snapshots with VirtualBox 4.2 or higher. These patches are based on Manuel Vives' patches, taking into account Daniel P. Berrange's remarks. The VirtualBox API provides only high level operations to manipulate snapshots, so it not possible to support flags like VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE and VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY with only API calls. Following an IRC talk with Eric Blake, the decision was made to emulate these behaviours by manipulating directly the .vbox XML files. The first patch adds extra details in the snapshot XML returned by libvirt. We will need those details in order to redefine the snapshots. The second patch adds a new API to manipulate the VirtualBox XML file. It provides several structs describing the VirtualBox XML file nodes and functions which can manipulate these structs. The third patch adds support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML. The idea is to unregister the machine, add the snapshot in the Virtualbox XML file and re-register the machine. However, VirtualBox forbids a machine to have snapshots but no current snapshot. So, if the real current snapshot has not been redefined yet, we create fake disks, allowing us to have an intermediate state in order to not corrupt the snapshot's read-write disks. These fake disks will be deleted during the next redefine. The fourth and last patch adds support of the VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY flag in virDomainSnapshotDelete. As in the third patch, we also create fake disks to not corrupt the snapshot's read-write disks. The patches were only tested with VirtualBox 4.3.10 and VirtualBox 4.2.24. Regards Yohan BELLEGUIC v7: * Add vbox_snapshot_conf.{h,c} files to (de)serialize VirtualBox XML files * Update the code to use the API exposed by vbox_snapshot_conf.h * Handle the fact that VirtualBox forbids a machine to have snapshots but no current snapshot v6: * Rebased because of a massive change in vbox_tmpl.c due to changes in the handling of different versions of VirtualBox v5: * The patches are modified according to a first review by Laine Stump: * renamed virSearchUuid to virSearchRegex and moved it from viruuid.{c,h} to virstring.{c,h}. * Various fixes. v4: * The code is compliant with Virtualbox 4.3 API * Some minor modifications in order to satisfy make syntax-check v3: * Use of STREQ_NULLABLE instead of STREQ in one case * Fix the method for finding uuids according to Ján Tomko review v2: * Fix a licence problem with the method for string replacement Manuel VIVES (1): vbox_tmpl.c: Better XML description for snapshots Yohan BELLEGUIC (3): Add vbox_snapshot_conf struct vbox_tmpl.c: Patch for redefining snapshots vbox_tmpl.c: Add function for undefining snapshot po/POTFILES.in|1 + src/Makefile.am |1 + src/vbox/vbox_snapshot_conf.c | 1383 + src/vbox/vbox_snapshot_conf.h | 100 ++ src/vbox/vbox_tmpl.c | 2225 + 5 files changed, 3538 insertions(+), 172 deletions(-) create mode 100644 src/vbox/vbox_snapshot_conf.c create mode 100644 src/vbox/vbox_snapshot_conf.h -- 1.7.10.4 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v7 4/4] vbox_tmpl.c: Add function for undefining snapshot
All snapshots information will be deleted from the vbox XML, but differencing disks will be kept so the user will be able to redefine the snapshot. --- src/vbox/vbox_tmpl.c | 453 +- 1 file changed, 452 insertions(+), 1 deletion(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index f8667f6..c5b5074 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -8347,7 +8347,443 @@ vboxDomainSnapshotDeleteTree(vboxGlobalData *data, return ret; } +#if VBOX_API_VERSION = 4002000 +static int +vboxDomainSnapshotDeleteMetadataOnly(virDomainSnapshotPtr snapshot) +{ +/* + * This function will remove the node in the vbox xml corresponding to the snapshot. + * It is usually called by vboxDomainSnapshotDelete() with the flag + * VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY. + * If you want to use it anywhere else, be careful, if the snapshot you want to delete + * has children, the result is not granted, they will probably will be deleted in the + * xml, but you may have a problem with hard drives. + * + * If the snapshot which is being deleted is the current one, we will set the current + * snapshot of the machine to the parent of this snapshot. Before writing the modified + * xml file, we undefine the machine from vbox. After writing the file, we redefine + * the machine with the new file. + */ + +virDomainPtr dom = snapshot-domain; +VBOX_OBJECT_CHECK(dom-conn, int, -1); +virDomainSnapshotDefPtr def= NULL; +char *defXml = NULL; +vboxIID domiid = VBOX_IID_INITIALIZER; +nsresult rc; +IMachine *machine = NULL; +PRUnichar *settingsFilePathUtf16 = NULL; +char *settingsFilepath = NULL; +vboxSnapshotXmlMachinePtr snapshotMachineDesc = NULL; +int isCurrent = -1; +int it = 0; +PRUnichar *machineNameUtf16 = NULL; +char *machineName = NULL; +char *nameTmpUse = NULL; +char *machineLocationPath = NULL; +PRUint32 aMediaSize = 0; +IMedium **aMedia = NULL; + +defXml = vboxDomainSnapshotGetXMLDesc(snapshot, 0); +if (!defXml) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get XML Desc of snapshot)); +goto cleanup; +} +def = virDomainSnapshotDefParseString(defXml, + data-caps, + data-xmlopt, + -1, + VIR_DOMAIN_SNAPSHOT_PARSE_DISKS | + VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE); +if (!def) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get a virDomainSnapshotDefPtr)); +goto cleanup; +} + +vboxIIDFromUUID(domiid, dom-uuid); +rc = VBOX_OBJECT_GET_MACHINE(domiid.value, machine); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_NO_DOMAIN, %s, + _(no domain with matching UUID)); +goto cleanup; +} +rc = machine-vtbl-GetSettingsFilePath(machine, settingsFilePathUtf16); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get settings file path)); +goto cleanup; +} +VBOX_UTF16_TO_UTF8(settingsFilePathUtf16, settingsFilepath); +/*Getting the machine name to retrieve the machine location path.*/ +rc = machine-vtbl-GetName(machine, machineNameUtf16); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot get machine name)); +goto cleanup; +} +VBOX_UTF16_TO_UTF8(machineNameUtf16, machineName); +if (virAsprintf(nameTmpUse, %s.vbox, machineName) 0) +goto cleanup; +machineLocationPath = virStringReplace(settingsFilepath, nameTmpUse, ); +if (machineLocationPath == NULL) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to get the machine location path)); +goto cleanup; +} +snapshotMachineDesc = vboxSnapshotLoadVboxFile(settingsFilepath, machineLocationPath); +if (!snapshotMachineDesc) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(cannot create a vboxSnapshotXmlPtr)); +goto cleanup; +} + +isCurrent = isCurrentSnapshot(snapshotMachineDesc, def-name); +if (isCurrent 0) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s, + _(Unable to know if the snapshot is the current snapshot)); +goto cleanup; +} +if (isCurrent) { +/* + * If the snapshot is the current snapshot, it means that the machine has read-write + * disks. The first thing to do is to manipulate VirtualBox API to create + * differential read-write disks if the parent snapshot is not null. + */ +if (def-parent != NULL) { +for (it = 0; it
[libvirt] [PATCH v7 3/4] vbox_tmpl.c: Patch for redefining snapshots
The machine is unregistered and its vbox XML file is changed in order to add snapshot information. The machine is then registered with the snapshot to redefine. --- src/vbox/vbox_tmpl.c | 949 +- 1 file changed, 942 insertions(+), 7 deletions(-) diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index ac000cf..f8667f6 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -38,12 +38,12 @@ #include sys/types.h #include sys/stat.h #include fcntl.h -#include libxml/xmlwriter.h #include internal.h #include datatypes.h #include domain_conf.h #include snapshot_conf.h +#include vbox_snapshot_conf.h #include network_conf.h #include virerror.h #include domain_event.h @@ -6023,6 +6023,930 @@ vboxDomainSnapshotGet(vboxGlobalData *data, return snapshot; } +#if VBOX_API_VERSION = 4002000 +static int vboxCloseDisksRecursively(virDomainPtr dom, char *location) +{ +VBOX_OBJECT_CHECK(dom-conn, int, -1); +nsresult rc; +size_t i = 0; +PRUnichar *locationUtf = NULL; +IMedium *medium = NULL; +IMedium **children = NULL; +PRUint32 childrenSize = 0; +VBOX_UTF8_TO_UTF16(location, locationUtf); +rc = data-vboxObj-vtbl-OpenMedium(data-vboxObj, + locationUtf, + DeviceType_HardDisk, + AccessMode_ReadWrite, + false, + medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s %x + , _(Unable to open HardDisk), rc); +goto cleanup; +} +rc = medium-vtbl-GetChildren(medium, childrenSize, children); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s + , _(Unable to get disk children)); +goto cleanup; +} +for (i = 0; i childrenSize; i++) { +IMedium *childMedium = children[i]; +if (childMedium) { +PRUnichar *childLocationUtf = NULL; +char *childLocation = NULL; +rc = childMedium-vtbl-GetLocation(childMedium, childLocationUtf); +VBOX_UTF16_TO_UTF8(childLocationUtf, childLocation); +VBOX_UTF16_FREE(childLocationUtf); +if (vboxCloseDisksRecursively(dom, childLocation) 0) { +VIR_DEBUG(Something wrong in the recurse); +goto cleanup; +} +VIR_FREE(childLocation); +} +} +rc = medium-vtbl-Close(medium); +if (NS_FAILED(rc)) { +virReportError(VIR_ERR_INTERNAL_ERROR, %s %x + , _(Unable to CLOSE HardDisk), rc); +goto cleanup; +} + +ret = 0; + cleanup: +VBOX_UTF16_FREE(locationUtf); +return ret; +} + +static int +vboxSnapshotRedefine(virDomainPtr dom, + virDomainSnapshotDefPtr def, + bool isCurrent) +{ +/* + * If your snapshot has a parent, + * it will only be redefined if you have already + * redefined the parent. + * + * The general algorithm of this function is below : + * First of all, we are going to create our vboxSnapshotXmlMachinePtr struct from + * the machine settings path. + * Then, if the machine current snapshot xml file is saved in the machine location, + * it means that this snapshot was previously modified by us and has fake disks. + * Fake disks are added when the flag VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT was not set + * yet, in order to not corrupt read-only disks. The first thing to do is to remove those + * disks and restore the read-write disks, if any, in the vboxSnapshotXmlMachinePtr struct. + * We also delete the current snapshot xml file. + * + * After that, we are going to register the snapshot read-only disks that we want to redefine, + * if they are not in the media registry struct. + * + * The next step is to unregister the machine and close all disks. + * + * Then, we check if the flag VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE has already been set. + * If this flag was set, we just add read-write disks to the media registry + * struct. Otherwise, we save the snapshot xml file into the machine location in order + * to recover the read-write disks during the next redefine and we create differential disks + * from the snapshot read-only disks and add them to the media registry struct. + * + * Finally, we register the machine with the new virtualbox description file. + */ +VBOX_OBJECT_CHECK(dom-conn, int, -1); +vboxIID domiid = VBOX_IID_INITIALIZER; +IMachine *machine = NULL; +nsresult rc; +PRUnichar *settingsFilePath = NULL; +char *settingsFilePath_Utf8 = NULL; +vboxSnapshotXmlMachinePtr snapshotMachineDesc = NULL; +char *currentSnapshotXmlFilePath = NULL; +PRUnichar
[libvirt] [PATCH v7 2/4] Add vbox_snapshot_conf struct
This structure contains the data to be saved in the VirtualBox XML file and can be manipulated with severals exposed functions. The structure is created by vboxSnapshotLoadVboxFile taking the machine XML file. It also can rewrite the XML by using vboxSnapshotSaveVboxFile. --- po/POTFILES.in|1 + src/Makefile.am |1 + src/vbox/vbox_snapshot_conf.c | 1383 + src/vbox/vbox_snapshot_conf.h | 100 +++ 4 files changed, 1485 insertions(+) create mode 100644 src/vbox/vbox_snapshot_conf.c create mode 100644 src/vbox/vbox_snapshot_conf.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 122b853..ad56b88 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -208,6 +208,7 @@ src/util/virxml.c src/vbox/vbox_MSCOMGlue.c src/vbox/vbox_XPCOMCGlue.c src/vbox/vbox_driver.c +src/vbox/vbox_snapshot_conf.c src/vbox/vbox_tmpl.c src/vmware/vmware_conf.c src/vmware/vmware_driver.c diff --git a/src/Makefile.am b/src/Makefile.am index 21d56fc..37f4df0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -658,6 +658,7 @@ VMWARE_DRIVER_SOURCES = \ VBOX_DRIVER_SOURCES = \ vbox/vbox_glue.c vbox/vbox_glue.h \ vbox/vbox_driver.c vbox/vbox_driver.h \ + vbox/vbox_snapshot_conf.c vbox/vbox_snapshot_conf.h \ vbox/vbox_V2_2.c vbox/vbox_CAPI_v2_2.h \ vbox/vbox_V3_0.c vbox/vbox_CAPI_v3_0.h \ vbox/vbox_V3_1.c vbox/vbox_CAPI_v3_1.h \ diff --git a/src/vbox/vbox_snapshot_conf.c b/src/vbox/vbox_snapshot_conf.c new file mode 100644 index 000..81e780a --- /dev/null +++ b/src/vbox/vbox_snapshot_conf.c @@ -0,0 +1,1383 @@ +/* + * Copyright 2014, diateam (www.diateam.net) + * + * 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 vbox_snapshot_conf.h +#include virerror.h +#include viralloc.h +#include virlog.h +#include virstring.h +#include virxml.h + +#include libxml/xpathInternals.h +#include libxml2/libxml/xmlwriter.h + +#define VIR_FROM_THIS VIR_FROM_VBOX +VIR_LOG_INIT(vbox.vbox_snapshot_conf); + +static vboxSnapshotXmlHardDiskPtr createvboxSnapshotXmlHardDiskPtr(xmlNodePtr diskNode, + xmlXPathContextPtr xPathContext, + char *machineLocation) +{ +vboxSnapshotXmlHardDiskPtr hardDisk = NULL; +xmlNodePtr *nodes = NULL; +char *uuid = NULL; +char **searchTabResult = NULL; +int resultSize = 0; +size_t i = 0; +int result = -1; +char *location = NULL; +char *tmp = NULL; +if (VIR_ALLOC(hardDisk) 0) +goto cleanup; + +xPathContext-node = diskNode; + +hardDisk-nchildren = virXPathNodeSet(./vbox:HardDisk, xPathContext, nodes); +if (hardDisk-nchildren VIR_ALLOC_N(hardDisk-children, hardDisk-nchildren) 0) +goto cleanup; +for (i = 0; i hardDisk-nchildren; i++) { +hardDisk-children[i] = createvboxSnapshotXmlHardDiskPtr(nodes[i], xPathContext, machineLocation); +if (hardDisk-children[i] == NULL) +goto cleanup; +hardDisk-children[i]-parent = hardDisk; +} +uuid = virXMLPropString(diskNode, uuid); +/*we use virStringSearch because the uuid is between brackets*/ +resultSize = virStringSearch(uuid, + VBOX_UUID_REGEX, + 1, + searchTabResult); +if (resultSize != 1) { +virReportError(VIR_ERR_XML_ERROR, %s + , _(Cannot parse HardDisk 'uuid' attribute)); +goto cleanup; +} +if (VIR_STRDUP(hardDisk-uuid, searchTabResult[0]) 0) +goto cleanup; + +location = virXMLPropString(diskNode, location); +if (location == NULL) { +virReportError(VIR_ERR_XML_ERROR, %s + , _(Cannot parse HardDisk 'location' attribute)); +goto cleanup; +} +if (location[0] != '/') { +/*The location is a relative path, so we must change it into an absolute one. */ +if (virAsprintf(tmp, %s%s, machineLocation, location) 0) +goto cleanup;