[libvirt] [PATCHv6 4/5] vbox_tmpl.c: Patch for redefining snapshots

2014-01-23 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c | 1083 +-
 1 file changed, 1075 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 0d7809a..50b541d 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002000
@@ -280,9 +281,19 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 400 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol,
+unsigned int flags,
+unsigned int flagDeleteOrClose);
 
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
@@ -5956,6 +5967,1055 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002000
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+char *xmlName;
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot")) {
+if ((xmlName = virXMLPropString(cur_node, "name"))) {
+if (STREQ(xmlName, name)) {
+VIR_FREE(xmlName);
+*snap_node = cur_node;
+return;
+}
+VIR_FREE(xmlName);
+}
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, name,
+  snap_node);
+}
+}
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("null pointer to disk"));
+goto cleanup;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+ret = 0;
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot get disk location"));
+goto cleanup;
+}
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot get children disks"));
+goto cleanup;
+}
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot refresh state"));
+goto cleanup;
+}
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("error while closing disk"));
+goto cleanup;
+}
+ret = 0;
+}
+cleanup:
+VBOX_UTF8_FREE(location_utf8);
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->d

[libvirt] [PATCHv6 2/5] virstring.h/c: Util method for making some find and replace in strings

2014-01-23 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   66 +-
 src/util/virstring.h |1 +
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 68ca39d..5103919 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1778,6 +1778,7 @@ virStringSortRevCompare;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 3c93450..b6f6192 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -618,7 +618,6 @@ size_t virStringListLength(char **strings)
 return i;
 }
 
-
 /**
  * virStringSortCompare:
  *
@@ -742,3 +741,68 @@ cleanup:
 VIR_FREE(pmatch);
 return ret;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret = NULL;
+size_t i = strlen(haystack);
+size_t count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+int diff_len = newneedle_len - oldneedle_len;
+size_t totalLength = 0;
+size_t numberOfElementsToAllocate = 0;
+if (!haystack || !oldneedle || !newneedle) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("null value for haystack, oldneedle or newneedle"));
+goto cleanup;
+}
+if (oldneedle_len == 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("oldneedle cannot be empty"));
+goto cleanup;
+}
+if (diff_len == 0 && memcmp(oldneedle, newneedle, newneedle_len) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (memcmp(&haystack[i], oldneedle, oldneedle_len) == 0) {
+count ++;
+i += oldneedle_len - 1;
+}
+}
+numberOfElementsToAllocate = (i + count * (newneedle_len - oldneedle_len));
+
+if (VIR_ALLOC_N(ret, numberOfElementsToAllocate) < 0)
+goto cleanup;
+
+totalLength = sizeof(char) * numberOfElementsToAllocate;
+i = 0;
+while (*haystack) {
+if (memcmp(haystack, oldneedle, oldneedle_len) == 0) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+VIR_FREE(ret);
+goto cleanup;
+}
+totalLength -= newneedle_len;
+i += newneedle_len;
+haystack += oldneedle_len;
+} else {
+ret[i++] = *haystack++;
+totalLength --;
+}
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index fe05403..2df0695 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -227,6 +227,7 @@ int virStringSortCompare(const void *a, const void *b);
 int virStringSortRevCompare(const void *a, const void *b);
 
 int virSearchRegex(const char *sourceString, unsigned int occurrence, const 
char *regexp, char **result);
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
 
 
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv6 3/5] vbox_tmpl.c: Better XML description for snapshots

2014-01-23 Thread Manuel VIVES
It will be needed for the future patches because we will
redefine snapshots
---
 src/vbox/vbox_tmpl.c |  511 +-
 1 file changed, 503 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 1be4dc4..0d7809a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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
@@ -289,6 +292,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) {
@@ -5972,7 +5982,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) {
@@ -6063,6 +6075,436 @@ cleanup:
 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  

[libvirt] [PATCHv6 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2014-01-23 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  448 +-
 1 file changed, 447 insertions(+), 1 deletion(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 50b541d..6171a79 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6176,6 +6176,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8412,8 +8474,377 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002000
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+goto cleanup;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+goto cleanup;
+}
+for (i = 0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
 
 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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+

[libvirt] [PATCHv6 1/5] virstring.h/c: Util method for finding regexp patterns in some strings

2014-01-23 Thread Manuel VIVES
---
 po/POTFILES.in   |1 +
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   97 ++
 src/util/virstring.h |3 ++
 4 files changed, 102 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0359b2f..738cfb1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -188,6 +188,7 @@ src/util/virscsi.c
 src/util/virsocketaddr.c
 src/util/virstatslinux.c
 src/util/virstoragefile.c
+src/util/virstring.c
 src/util/virsysinfo.c
 src/util/virerror.c
 src/util/virerror.h
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d1a58f9..68ca39d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1763,6 +1763,7 @@ virStorageFileResize;
 # util/virstring.h
 virArgvToString;
 virAsprintfInternal;
+virSearchRegex;
 virSkipSpaces;
 virSkipSpacesAndBackslash;
 virSkipSpacesBackwards;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 8d0ca70..3c93450 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "virstring.h"
@@ -645,3 +646,99 @@ int virStringSortRevCompare(const void *a, const void *b)
 
 return strcmp(*sb, *sa);
 }
+
+/**
+ * virSearchRegex:
+ * Allows you to get the nth occurrence of a substring in sourceString which 
matches
+ * a POSIX Extended regular expression pattern.
+ * If there is no substring, result is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: return occurrence 'n' (starting from 0) of a sub-string that
+ *  matches the pattern.
+ * @regexp: POSIX Extended regular expression pattern used for matching
+ * @result: nth occurrence substring matching the @regexp pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0
+773ab075-4cd7-4fc2-8b6e-21c84e9cb391
+bbb3c75c-d60f-43b0-b802-fd56b84a4222
+60c04aa1-0375-4654-8d9f-e149d9885273
+4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+virSearchRegex(source,
+   4,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret1);
+//ret1 = "4548d465-9891-4c34-a184-3b1c34a26aa8"
+virSearchRegex(source,
+   0,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret2);
+//ret2 = "6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchRegex(source,
+   1,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret3);
+//ret3 = "773ab075-4cd7-4fc2-8b6e-21c84e9cb391"
+ * @endcode
+ */
+
+int
+virSearchRegex(const char *sourceString,
+   unsigned int occurrence,
+   const char *regexp,
+   char **result)
+{
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+int ret = -1;
+int regError = -1;
+
+regError = regcomp(&pregUuidBracket, regexp, REG_EXTENDED);
+if (regError != 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Error while compiling regular expression: %d"),
+   regError);
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) < 0)
+goto cleanup;
+
+while (i < (occurrence+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+regoff_t start = pmatch[0].rm_so;
+regoff_t end = pmatch[0].rm_eo;
+if (i == occurrence ||
+(occurrence > i && regexec(&pregUuidBracket, 
&sourceString[end],
+ nmatch, pmatch, 0) != 0)) {
+/* We copy only if i == position (so that it is the uuid we're 
looking for),
+ * or position > i AND there is no matches left in the rest of 
the string
+ * (this is the case where we give a biggest @occurence than 
the
+ * number of matches and we want to return the last one)
+ */
+if (VIR_STRNDUP(*result, sourceString + start, end - start) < 
0)
+goto cleanup;
+
+ret = 1;
+goto cleanup;
+}
+sourceString = &sourceString[end];
+} else {
+break;
+ret = 0;
+goto cleanup;
+}
+++i;
+}
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 13a6e5a..fe05403 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -226,4 +226,7 @@ siz

[libvirt] [PATCHv6 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2014-01-23 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately to
validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling regexp and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only tested with Virtualbox 4.2 but the code is
compliant with Virtualbox 4.3 API.

Regards,
Manuel VIVES

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 (5):
  virstring.h/c: Util method for finding regexp patterns in some
strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 po/POTFILES.in   |1 +
 src/libvirt_private.syms |2 +
 src/util/virstring.c |  163 +++-
 src/util/virstring.h |4 +
 src/vbox/vbox_tmpl.c | 2346 ++
 5 files changed, 2346 insertions(+), 170 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3] vbox: add support for v4.2.20+ and v4.3.4+

2014-01-20 Thread Manuel VIVES
Hi,

While working on adding virDomain*Stats support to the vbox driver, we
found bugs in the VirtualBox API C bindings. These bugs have been fixed
in versions 4.2.20 and 4.3.4.
However, the changes in the C bindings are incompatible with the 
vbox_CAPI_v4_2.h
and vbox_CAPI_v4_3.h files which are bundled in libvirt source code. This is 
why the
following patch adds vbox_CAPI_v4_2_20.h and vbox_CAPI_v4_3_4.h.

As stated by Matthias Bolte, the actual underlying problem here is that
libvirt assumes that VirtualBox API can only change between release versions
(4.2 -> 4.3), but we have a case here where it changed (or got fixed) between
minor versions (4.2.18 -> 4.2.20).

This patch makes the VBOX_API_VERSION represent the full API
version number (i.e 4002 => 4002000) so there are specific version
numbers for Vbox 4.2.20 (4002020) and 4.3.4 (4003004)

As the patch is too big for the mailing list, it is publicly available
at http://git-lab.diateam.net/cots/libvirt.git/ with the branch name
'vbox-4.2.20-4.3.4-support-v3'

Regards,
Manuel VIVES

v3: 
- Changed the commit message for being more precise.
- Resend after freeze.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v2] vbox: add support for v4.2.20+ and v4.3.4+

2014-01-14 Thread Manuel VIVES
Hi,

While working on adding virDomain*Stats support to the vbox driver, we
found bugs in the VirtualBox API C bindings. These bugs have been fixed
in versions 4.2.20 and 4.3.4.
However, the changes in the C bindings are incompatible with the 
vbox_CAPI_v4_2.h
and vbox_CAPI_v4_3.h files which are bundled in libvirt source code. This is 
why the
following patch adds vbox_CAPI_v4_2_20.h and vbox_CAPI_v4_3_4.h.

As stated by Matthias Bolte, the actual underlying problem here is that
libvirt assumes that VirtualBox API can only change between release versions
(4.2 -> 4.3), but we have a case here where it changed (or got fixed) between
minor versions (4.2.18 -> 4.2.20).

This patch makes the VBOX_API_VERSION represent the full API
version number (i.e 4002 => 4002000) so there are specific version
numbers for Vbox 4.2.20 (4002020) and 4.3.4 (4003004)

As the patch is too big for the mailing list, it is publicly available
at http://git-lab.diateam.net/cots/libvirt.git/ with the branch name
'vbox-4.2.20-4.3.4-support-v2'

Regards,
Manuel VIVES

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv5 1/5] virstring.h/c: Util method for finding regexp patterns in some strings

2014-01-03 Thread Manuel VIVES
---
 po/POTFILES.in   |1 +
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   97 ++
 src/util/virstring.h |3 ++
 4 files changed, 102 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 49dfc9c..ed09fc1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -189,6 +189,7 @@ src/util/virscsi.c
 src/util/virsocketaddr.c
 src/util/virstatslinux.c
 src/util/virstoragefile.c
+src/util/virstring.c
 src/util/virsysinfo.c
 src/util/virerror.c
 src/util/virerror.h
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2dbb8f8..14ad8f4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1751,6 +1751,7 @@ virStorageFileResize;
 # util/virstring.h
 virArgvToString;
 virAsprintfInternal;
+virSearchRegex;
 virSkipSpaces;
 virSkipSpacesAndBackslash;
 virSkipSpacesBackwards;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 8d0ca70..3c93450 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "virstring.h"
@@ -645,3 +646,99 @@ int virStringSortRevCompare(const void *a, const void *b)
 
 return strcmp(*sb, *sa);
 }
+
+/**
+ * virSearchRegex:
+ * Allows you to get the nth occurrence of a substring in sourceString which 
matches
+ * a POSIX Extended regular expression pattern.
+ * If there is no substring, result is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: return occurrence 'n' (starting from 0) of a sub-string that
+ *  matches the pattern.
+ * @regexp: POSIX Extended regular expression pattern used for matching
+ * @result: nth occurrence substring matching the @regexp pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0
+773ab075-4cd7-4fc2-8b6e-21c84e9cb391
+bbb3c75c-d60f-43b0-b802-fd56b84a4222
+60c04aa1-0375-4654-8d9f-e149d9885273
+4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+virSearchRegex(source,
+   4,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret1);
+//ret1 = "4548d465-9891-4c34-a184-3b1c34a26aa8"
+virSearchRegex(source,
+   0,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret2);
+//ret2 = "6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchRegex(source,
+   1,
+   
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
+   &ret3);
+//ret3 = "773ab075-4cd7-4fc2-8b6e-21c84e9cb391"
+ * @endcode
+ */
+
+int
+virSearchRegex(const char *sourceString,
+   unsigned int occurrence,
+   const char *regexp,
+   char **result)
+{
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+int ret = -1;
+int regError = -1;
+
+regError = regcomp(&pregUuidBracket, regexp, REG_EXTENDED);
+if (regError != 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Error while compiling regular expression: %d"),
+   regError);
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) < 0)
+goto cleanup;
+
+while (i < (occurrence+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+regoff_t start = pmatch[0].rm_so;
+regoff_t end = pmatch[0].rm_eo;
+if (i == occurrence ||
+(occurrence > i && regexec(&pregUuidBracket, 
&sourceString[end],
+ nmatch, pmatch, 0) != 0)) {
+/* We copy only if i == position (so that it is the uuid we're 
looking for),
+ * or position > i AND there is no matches left in the rest of 
the string
+ * (this is the case where we give a biggest @occurence than 
the
+ * number of matches and we want to return the last one)
+ */
+if (VIR_STRNDUP(*result, sourceString + start, end - start) < 
0)
+goto cleanup;
+
+ret = 1;
+goto cleanup;
+}
+sourceString = &sourceString[end];
+} else {
+break;
+ret = 0;
+goto cleanup;
+}
+++i;
+}
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 13a6e5a..fe05403 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -226,4 +226,7 @@ siz

[libvirt] [PATCHv5 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2014-01-03 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  448 +-
 1 file changed, 447 insertions(+), 1 deletion(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index a43a875..009ff3a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6171,6 +6171,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8407,8 +8469,377 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+goto cleanup;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+goto cleanup;
+}
+for (i=0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
 
 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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMach

[libvirt] [PATCHv5 4/5] vbox_tmpl.c: Patch for redefining snapshots

2014-01-03 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c | 1083 +-
 1 file changed, 1075 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 98724c1..a43a875 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -276,9 +277,19 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol,
+unsigned int flags,
+unsigned int flagDeleteOrClose);
 
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
@@ -5951,6 +5962,1055 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+char *xmlName;
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot")) {
+if ((xmlName = virXMLPropString(cur_node, "name"))) {
+if (STREQ(xmlName, name)) {
+VIR_FREE(xmlName);
+*snap_node = cur_node;
+return;
+}
+VIR_FREE(xmlName);
+}
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, name,
+  snap_node);
+}
+}
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("null pointer to disk"));
+goto cleanup;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+ret = 0;
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot get disk location"));
+goto cleanup;
+}
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot get children disks"));
+goto cleanup;
+}
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("cannot refresh state"));
+goto cleanup;
+}
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("error while closing disk"));
+goto cleanup;
+}
+ret = 0;
+}
+cleanup:
+VBOX_UTF8_FREE(location_utf8);
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child

[libvirt] [PATCHv5 2/5] virstring.h/c: Util method for making some find and replace in strings

2014-01-03 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   66 +-
 src/util/virstring.h |1 +
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 14ad8f4..17aadfe 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1766,6 +1766,7 @@ virStringSortRevCompare;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 3c93450..b6f6192 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -618,7 +618,6 @@ size_t virStringListLength(char **strings)
 return i;
 }
 
-
 /**
  * virStringSortCompare:
  *
@@ -742,3 +741,68 @@ cleanup:
 VIR_FREE(pmatch);
 return ret;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret = NULL;
+size_t i = strlen(haystack);
+size_t count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+int diff_len = newneedle_len - oldneedle_len;
+size_t totalLength = 0;
+size_t numberOfElementsToAllocate = 0;
+if (!haystack || !oldneedle || !newneedle) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("null value for haystack, oldneedle or newneedle"));
+goto cleanup;
+}
+if (oldneedle_len == 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("oldneedle cannot be empty"));
+goto cleanup;
+}
+if (diff_len == 0 && memcmp(oldneedle, newneedle, newneedle_len) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (memcmp(&haystack[i], oldneedle, oldneedle_len) == 0) {
+count ++;
+i += oldneedle_len - 1;
+}
+}
+numberOfElementsToAllocate = (i + count * (newneedle_len - oldneedle_len));
+
+if (VIR_ALLOC_N(ret, numberOfElementsToAllocate) < 0)
+goto cleanup;
+
+totalLength = sizeof(char) * numberOfElementsToAllocate;
+i = 0;
+while (*haystack) {
+if (memcmp(haystack, oldneedle, oldneedle_len) == 0) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+VIR_FREE(ret);
+goto cleanup;
+}
+totalLength -= newneedle_len;
+i += newneedle_len;
+haystack += oldneedle_len;
+} else {
+ret[i++] = *haystack++;
+totalLength --;
+}
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index fe05403..2df0695 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -227,6 +227,7 @@ int virStringSortCompare(const void *a, const void *b);
 int virStringSortRevCompare(const void *a, const void *b);
 
 int virSearchRegex(const char *sourceString, unsigned int occurrence, const 
char *regexp, char **result);
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
 
 
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv5 3/5] vbox_tmpl.c: Better XML description for snapshots

2014-01-03 Thread Manuel VIVES
It will be needed for the future patches because we will
redefine snapshots
---
 src/vbox/vbox_tmpl.c |  510 +-
 1 file changed, 502 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 385ee54..98724c1 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -285,6 +288,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5968,7 +5977,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) {
@@ -6059,6 +6070,436 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+ 

[libvirt] [PATCHv5 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2014-01-03 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately to
validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling regexp and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only tested with Virtualbox 4.2 but the code is
compliant with Virtualbox 4.3 API.

Regards,
Manuel VIVES

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 (5):
  virstring.h/c: Util method for finding regexp patterns in some
strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 po/POTFILES.in   |1 +
 src/libvirt_private.syms |2 +
 src/util/virstring.c |  163 +++-
 src/util/virstring.h |4 +
 src/vbox/vbox_tmpl.c | 2347 ++
 5 files changed, 2346 insertions(+), 171 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCHv4 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-12-23 Thread Manuel VIVES
> On 11/25/2013 07:23 PM, Manuel VIVES wrote:
> > It will be needed for the futur patches because we will
> > redefine snapshots
> 
> s/futur/future/ :-)
> 
> > ---
> > 
> >  src/conf/domain_conf.c |2 +-
> >  src/vbox/vbox_tmpl.c   |  427
> >  ++-- 2 files changed, 417
> >  insertions(+), 12 deletions(-)
> > 
> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> > index 7b0e3ea..ae20eb5 100644
> > --- a/src/conf/domain_conf.c
> > +++ b/src/conf/domain_conf.c
> > @@ -17054,7 +17054,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
> > 
> >  if (virDomainChrDefFormat(buf, &console, flags) < 0)
> >  
> >  goto error;
> >  
> >  }
> > 
> > -if (STREQ(def->os.type, "hvm") &&
> > +if (STREQ_NULLABLE(def->os.type, "hvm") &&
> > 
> >  def->nconsoles == 0 &&
> >  def->nserials > 0) {
> >  virDomainChrDef console;
> 
> This hunk should be a separate patch. BTW, is it valid for vbox domains
> to not have a valid os.type? virDomainDefPostParseInternal() requires it
> to be set, and there are several other places in domain_conf.c that
> compare it without allowing for NULL, so if NULL is valid, those other
> places should at least get scrutiny, or you should make sure that it's
> set when you construct the domain object in the vbox driver.
> 

This portion was safely removed from the patch.

> > diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
> > index 983a595..e05ed97 100644
> > --- a/src/vbox/vbox_tmpl.c
> > +++ b/src/vbox/vbox_tmpl.c
> > @@ -38,6 +38,7 @@
> > 
> >  #include 
> >  #include 
> >  #include 
> > 
> > +#include 
> > 
> >  #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 == 2002
> > 
> > @@ -273,10 +276,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
> > 
> >  #endif /* VBOX_API_VERSION >= 4000 */
> > 
> > +#define reportInternalErrorIfNS_FAILED(message) \
> > +if (NS_FAILED(rc)) { \
> > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
> > +goto cleanup; \
> > +}
> > +
> > +
> 
> I would prefer these if() clauses with goto to be explicitly in the
> code, rather than hidden in a macro. That way it's easier to see all
> potential code paths when scanning through the code. If you have a goto
> hidden in a macro, then it's not immediately visible and that can only
> lead to problems.

I removed this macro in order to have 'goto' instructions clearly
visible but it increases the size of the patch.

> >  static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char
> >  *xml); static int vboxDomainCreate(virDomainPtr dom);
> >  static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int
> >  flags);
> > 
> > -
> > 
> >  static void vboxDriverLock(vboxGlobalData *data) {
> 
> You should leave in that blank line, as it separates static function
> declarations from a function definition.
> 
> >  virMutexLock(&data->lock);
> >  
> >  }
> > 
> > @@ -285,6 +294,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
> > 
> >  virMutexUnlock(&data->lock);
> >  
> >  }
> > 
> > +typedef enum {
> > +VBOX_STORAGE_DELETE_FLAG = 0,
> > +#if VBOX_API_VERSION >= 4002
> > +VBOX_STORAGE_CLOSE_FLAG = 1,
> > +#endif
> > +} vboxStorageDeleteOrCloseFlags;
> > 
> >  #if VBOX_API_VERSION == 2002
> >  
> >  static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
> > 
> > @@ -5957,7 +5972,8 @@ 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_DIS

Re: [libvirt] [PATCHv4 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-12-23 Thread Manuel VIVES
> On 11/25/2013 07:23 PM, Manuel VIVES wrote:
> > The snapshots are saved in xml files, and then can be redefined
> > ---
> > 
> >  src/vbox/vbox_tmpl.c |  852
> >  +- 1 file changed, 844
> >  insertions(+), 8 deletions(-)
> > 
> > diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
> > index e05ed97..23f8aab 100644
> > --- a/src/vbox/vbox_tmpl.c
> > +++ b/src/vbox/vbox_tmpl.c
> > @@ -61,6 +61,7 @@
> > 
> >  #include "virstring.h"
> >  #include "virtime.h"
> >  #include "virutil.h"
> > 
> > +#include "dirname.h"
> > 
> >  /* This one changes from version to version. */
> >  #if VBOX_API_VERSION == 2002
> > 
> > @@ -276,6 +277,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
> > 
> >  #endif /* VBOX_API_VERSION >= 4000 */
> > 
> > +/*This error is a bit specific
> > + *In the VBOX API it is named E_ACCESSDENIED
> > + *It is returned when the called object is not ready. In
> > + *particular when we do any call on a disk which has been closed
> > +*/
> > +#define VBOX_E_ACCESSDENIED 0x80070005
> 
> Is this code not defined anywhere in vbox API include files?
> 

I did not find this code anywhere in the API, so I defined it here.

> >  #define reportInternalErrorIfNS_FAILED(message) \
> >  
> >  if (NS_FAILED(rc)) { \
> >  
> >  virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
> > 
> > @@ -286,6 +293,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
> > 
> >  static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char
> >  *xml); static int vboxDomainCreate(virDomainPtr dom);
> >  static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int
> >  flags);
> > 
> > +static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn,
> > const char *path); +static int vboxStorageDeleteOrClose(virStorageVolPtr
> > vol, unsigned int flags, unsigned int flagDeleteOrClose);
> 
> The above line looks to be > 80 columns.
> 
> >  static void vboxDriverLock(vboxGlobalData *data) {
> >  
> >  virMutexLock(&data->lock);
> >  
> >  }
> > 
> > @@ -5946,6 +5955,827 @@ cleanup:
> >  return snapshot;
> >  
> >  }
> > 
> > +#if VBOX_API_VERSION >=4002
> > +static void
> > +vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
> > +   const char *name,
> > +   xmlNodePtr *snap_node)
> > +{
> > +xmlNodePtr cur_node = NULL;
> > +
> > +for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
> > +if (cur_node->type == XML_ELEMENT_NODE) {
> > +if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot")
> > && +STREQ(virXMLPropString(cur_node, "name"), name)) {
> 
> Two problems here:
> 
> 1) virXMLPropString() could return NULL in case it doesn't find the
> property you're looking for, and you haven't allowed for that.
> 
> 2) virXMLPropString returns a *copy* of the string, and you need to
> VIR_FREE() it after you're finished with it. But you haven't even saved
> a copy of the pointer, so you have no way of doing that.
> 
> So every time you call virXMLPropString(), you're either going to leak a
> string, or segv libvirtd.
> 
> > +*snap_node = cur_node;
> > +return;
> > +}
> > +}
> > +if (cur_node->children)
> > +   
> > vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, name,
> > snap_node); +}
> > +}
> > +
> > +
> > +
> > +
> > +static int
> > +vboxDetachAndCloseDisks(virDomainPtr dom,
> > +IMedium *disk)
> > +{
> > +VBOX_OBJECT_CHECK(dom->conn, int, -1);
> > +nsresult rc;
> > +PRUnichar *location = NULL;
> > +vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
> > +virStorageVolPtr volPtr = NULL;
> > +char *location_utf8 = NULL;
> > +PRUint32 dummyState = 0;
> > +size_t i = 0;
> > +if (disk == NULL) {
> > +VIR_DEBUG("Null pointer to disk");
> > +return -1;
> 
> If something is an error, and will end up failing an operation, then you
> need to log an error message rather than just outputting a debug
> message. This is true even if the error c

Re: [libvirt] [PATCHv4 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-12-23 Thread Manuel VIVES
> On 11/25/2013 07:23 PM, Manuel VIVES wrote:
> > ---
> > 
> >  src/libvirt_private.syms |1 +
> >  src/util/virstring.c |   48
> >  ++ src/util/virstring.h
> >  |2 ++
> >  3 files changed, 51 insertions(+)
> > 
> > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> > index 99cc32a..b761fb6 100644
> > --- a/src/libvirt_private.syms
> > +++ b/src/libvirt_private.syms
> > @@ -1750,6 +1750,7 @@ virStringListLength;
> > 
> >  virStringSplit;
> >  virStrncpy;
> >  virStrndup;
> > 
> > +virStrReplace;
> > 
> >  virStrToDouble;
> >  virStrToLong_i;
> >  virStrToLong_l;
> > 
> > diff --git a/src/util/virstring.c b/src/util/virstring.c
> > index d11db5c..a30a4ef 100644
> > --- a/src/util/virstring.c
> > +++ b/src/util/virstring.c
> > @@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
> > 
> >  return i;
> >  
> >  }
> > 
> > +
> > +/*
> > + virStrReplace(haystack, oldneedle, newneedle) --
> > +  Search haystack and replace all occurences of oldneedle with
> > newneedle. +  Return a string with all the replacements in case of
> > success, NULL in case +  of failure
> > +*/
> > +char *
> > +virStrReplace(char *haystack,
> > +  const char *oldneedle, const char *newneedle)
> > +{
> > +char *ret;
> > +size_t i, count = 0;
> > +size_t newneedle_len = strlen(newneedle);
> > +size_t oldneedle_len = strlen(oldneedle);
> > +size_t totalLength = 0;
> > +if (strlen(oldneedle) == 0) {
> 
> You can just check oldneedle_len here since it already contains
> strlen(oldneedle).
> 
> Also, should this really be a NOP? It makes no sense to ask to replace
> all occurrences of "" with anything (kind of like dividing by 0), so I
> think it should rather be an error (likewise, do we need to check for
> !oldneedle or !newneedle ? Or are the callers controlled enough that we
> can just put that requirement on them? If the latter, then the
> declaration in the .h file needs to have "ATTRIBUTE_NONNULL(2),
> ATTRIBUTE_NONNULL(3) (and we probably should have ATTRIBUTE_NONNULL(1)
> in any case, unless there is a danger a caller could send a null haystack)
> 

I'm going to modify my patch in order to return an error if oldneedle
is empty.
I also looked at ATTRIBUTE_NONNULL and I did't really understand the
purpose so if someone could explain it ;)
But maybe I should also include the !oldneedle, the !newneedle and
!haystack tests inside the method, what do you think?

> > +ignore_value(VIR_STRDUP(ret, haystack));
> > +goto cleanup;
> > +}
> > +
> > +for (i = 0; haystack[i] != '\0'; i++) {
> > +if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
> 
> This just makes no sense. strstr is used to search for a substring
> within a string. Here you are searching for a substring, but only
> counting it if the match is at the beginning of the string. If you're
> going to do that, why not just use memcmp() instead and save all the
> extra scanning?
> 
> Or better yet, just let strstr() do its work and  set "i = [return from
> strstr] + oldneedle_len" when you get a match.
> 
> > +count++;
> > +i += oldneedle_len - 1;
> > +}
> > +}
> 
> Okay, so at this point i == strlen(haystack)...
> 
> > +if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len)))
> > < 0) {
> 
> You need to allocate one extra byte for the terminating \0.
> 
> > +ret = NULL;
> 
> No need to set ret = NULL - that is done by VIR_ALLOC_N.
> 
> > +goto cleanup;
> > +}
> > +totalLength = sizeof(char *)*(i + count * (newneedle_len -
> > oldneedle_len));
> 
> This is incorrect and potentially dangerous - "sizeof(char*) is the size
> of a char* (usually 8 bytes), NOT the size of a char (1 byte), so you're
> telling virStrcpy() that there are 8 times as many bytes available as
> there actually are.
> 
> > +i = 0;
> > +while (*haystack) {
> > +if (strstr(haystack, oldneedle) == haystack) {
> 
> Again, if you're only going to count a match when it is exactly at the
> start of the string, you should just use memcmp instead of strstr. Or
> alternately, make the algorithm more intelligent so that it takes
> advantage of any platform-specific optimizations that may be hidden in
> strstr.
> 
> > +i

Re: [libvirt] [PATCHv4 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-12-23 Thread Manuel VIVES
> On 11/25/2013 07:23 PM, Manuel VIVES wrote:
> > ---
> > 
> >  po/POTFILES.in   |1 +
> >  src/libvirt_private.syms |1 +
> >  src/util/viruuid.c   |   81
> >  ++ src/util/viruuid.h  
> >  |1 +
> >  4 files changed, 84 insertions(+)
> > 
> > diff --git a/po/POTFILES.in b/po/POTFILES.in
> > index 15afdec..451a6fc 100644
> > --- a/po/POTFILES.in
> > +++ b/po/POTFILES.in
> > @@ -196,6 +196,7 @@ src/util/virtypedparam.c
> > 
> >  src/util/viruri.c
> >  src/util/virusb.c
> >  src/util/virutil.c
> > 
> > +src/util/viruuid.c
> > 
> >  src/util/virxml.c
> >  src/vbox/vbox_MSCOMGlue.c
> >  src/vbox/vbox_XPCOMCGlue.c
> > 
> > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> > index a705c56..99cc32a 100644
> > --- a/src/libvirt_private.syms
> > +++ b/src/libvirt_private.syms
> > @@ -1915,6 +1915,7 @@ virValidateWWN;
> > 
> >  # util/viruuid.h
> >  virGetHostUUID;
> > 
> > +virSearchUuid;
> > 
> >  virSetHostUUIDStr;
> >  virUUIDFormat;
> >  virUUIDGenerate;
> > 
> > diff --git a/src/util/viruuid.c b/src/util/viruuid.c
> > index c5fa9a8..2cda4ac 100644
> > --- a/src/util/viruuid.c
> > +++ b/src/util/viruuid.c
> > @@ -34,6 +34,7 @@
> > 
> >  #include 
> >  #include 
> >  #include 
> > 
> > +#include 
> > 
> >  #include "c-ctype.h"
> >  #include "internal.h"
> > 
> > @@ -43,11 +44,14 @@
> > 
> >  #include "viralloc.h"
> >  #include "virfile.h"
> >  #include "virrandom.h"
> > 
> > +#include "virstring.h"
> > 
> >  #ifndef ENODATA
> >  # define ENODATA EIO
> >  #endif
> > 
> > +#define VIR_FROM_THIS VIR_FROM_NONE
> > +
> > 
> >  static unsigned char host_uuid[VIR_UUID_BUFLEN];
> >  
> >  static int
> > 
> > @@ -333,3 +337,80 @@ int virGetHostUUID(unsigned char *uuid)
> > 
> >  return ret;
> >  
> >  }
> > 
> > +
> > +
> > +/**
> > + * virSearchUuid:
> > + * Allows you to get the nth occurrence of a substring in sourceString
> > which matches an uuid pattern. + * If there is no substring, ret is not
> > modified.
> > + * return -1 on error, 0 if not found and 1 if found.
> 
> Hah! I accidentally started reviewing an earlier version of this patch,
> and lack of a way to indicate error to the caller was one of my
> criticisms :-)
> 
> > + *
> > + * @sourceString: String to parse
> > + * @occurrence: We will return the nth occurrence of uuid in substring,
> > if equals to 0 (or negative), will return the first occurence + * @ret:
> > nth occurrence substring matching an uuid pattern
> > + * @code
> > +char *source = "6853a496-1c10-472e-867a-8244937bd6f0
> > 773ab075-4cd7-4fc2-8b6e-21c84e9cb391
> > bbb3c75c-d60f-43b0-b802-fd56b84a4222
> > 60c04aa1-0375-4654-8d9f-e149d9885273
> > 4548d465-9891-4c34-a184-3b1c34a26aa8"; +char *ret1=NULL;
> > +char *ret2=NULL;
> > +char *ret3=NULL;
> > +char *ret4=NULL;
> > +virSearchUuid(source, 4,&ret1);  //ret1 =
> > "60c04aa1-0375-4654-8d9f-e149d9885273" +virSearchUuid(source,
> > 0,&ret2);  //ret2 = "6853a496-1c10-472e-867a-8244937bd6f0" +   
> > virSearchUuid(source, 1,&ret3);  //ret3 =
> > "6853a496-1c10-472e-867a-8244937bd6f0" +virSearchUuid(source,
> > -4,&ret4); //ret4 = "6853a496-1c10-472e-867a-8244937bd6f0"
> 
> What is the use of having occurrence == -n, 0, or 1 yield the same
> result? It makes more sense to define the function as "return occurrence
> 'n' (starting from 0) of a sub-string that matches the pattern for a
> uuid". Documenting is then much simpler, and it's easier to know the
> "best" way to get the first occurrence (since there is only one way to
> do it).
> 
> This seems like a very specific use case for a more general function.
> How about making a virSearchRegex() function (or maybe some other name)
> which took the regex as another arg? That would make it more likely that
> the code would be reused.
> 
I have modified this method, so now it takes a regex as argument and
I have renamed it to 'virSearchRegex'. Should I move it in another file
(it is still in viruuid.c/h)?


> > + * @endcode
> > + */
> > +
> > +int
> > +virSearchUuid(const char *sourceStrin

[libvirt] [PATCHv4 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-11-25 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |2 +-
 src/vbox/vbox_tmpl.c   |  427 ++--
 2 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7b0e3ea..ae20eb5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -17054,7 +17054,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
+if (STREQ_NULLABLE(def->os.type, "hvm") &&
 def->nconsoles == 0 &&
 def->nserials > 0) {
 virDomainChrDef console;
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 983a595..e05ed97 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -273,10 +276,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -285,6 +294,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5957,7 +5972,8 @@ 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) {
@@ -5965,7 +5981,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5973,7 +5988,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -6048,6 +6062,344 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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);
+reportInternalErrorIfNS_FAILED("no domain with matching UUID");
+if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) {
+ret = -1;
+goto cleanup;
+}
+rc = snap->vtbl->GetId(snap, &snapIid.value);
+reportInternalErrorIfNS_FAILED("Could not get snapshot id");
+
+VBOX_UTF16_TO_UTF8(snapIid.value, &snapshotUuidStr);
+rc = snap->vtbl->GetMachine(snap, &snapMachine);
+reportInternalErrorIfNS_FAILED("could not get machine");
+def->ndisks = 0;
+rc = vboxArrayGet(&mediumAttachments, snapMachine, 
snapMachine->vtbl->GetMediumAttachments);
+reportInternalErrorIfNS_FAILED("no medium attachments");
+/* get the number of attachments */
+for (i = 0; i < mediumAttachments.count; i++) {
+IMediumAttachment *imediumattach = m

[libvirt] [PATCHv4 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-11-25 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  391 ++
 1 file changed, 391 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 23f8aab..9b50c2e 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6132,6 +6132,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8076,8 +8138,319 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (i=0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
 
 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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMac

[libvirt] [PATCHv4 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-11-25 Thread Manuel VIVES
---
 po/POTFILES.in   |1 +
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 4 files changed, 84 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 15afdec..451a6fc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -196,6 +196,7 @@ src/util/virtypedparam.c
 src/util/viruri.c
 src/util/virusb.c
 src/util/virutil.c
+src/util/viruuid.c
 src/util/virxml.c
 src/vbox/vbox_MSCOMGlue.c
 src/vbox/vbox_XPCOMCGlue.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a705c56..99cc32a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1915,6 +1915,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..2cda4ac 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,80 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Allows you to get the nth occurrence of a substring in sourceString which 
matches an uuid pattern.
+ * If there is no substring, ret is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+int
+virSearchUuid(const char *sourceString, int occurrence, char **ret)
+{
+unsigned int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+int retCode = 0;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Error while compiling regular expression"));
+return -1;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+retCode = -1;
+goto cleanup;
+}
+
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+regoff_t start = pmatch[0].rm_so;
+regoff_t end = pmatch[0].rm_eo;
+if (i == position || (position > i && regexec(&pregUuidBracket, 
&sourceString[end], nmatch, pmatch, 0) != 0)) {
+/* We copy only if i == position (so that it is the uuid we're 
looking for), or position > i AND
+ * there is no matches left in the rest of the string (this is 
the case where we
+ * give a biggest @occurence than the number of matches and we 
want to return the last
+ * one)
+ */
+if (VIR_STRNDUP(*ret, sourceString + start, end - start) < 0) {
+retCode = -1;
+goto cleanup;
+}
+retCode = 1;
+goto cleanup;
+}
+
+sourceString = &sourceString[end];
+} else {
+break;
+retCode = 0;
+goto cleanup;
+}
+++i;
+}
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return retCode;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..2ce4fce 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+int virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
li

[libvirt] [PATCHv4 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-11-25 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  852 +-
 1 file changed, 844 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index e05ed97..23f8aab 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -276,6 +277,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -286,6 +293,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5946,6 +5955,827 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cu

[libvirt] [PATCHv4 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-11-25 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 ++
 3 files changed, 51 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 99cc32a..b761fb6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1750,6 +1750,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index d11db5c..a30a4ef 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret;
+size_t i, count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+size_t totalLength = 0;
+if (strlen(oldneedle) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
+count++;
+i += oldneedle_len - 1;
+}
+}
+if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len))) < 0) {
+ret = NULL;
+goto cleanup;
+}
+totalLength = sizeof(char *)*(i + count * (newneedle_len - oldneedle_len));
+i = 0;
+while (*haystack) {
+if (strstr(haystack, oldneedle) == haystack) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+ret = NULL;
+goto cleanup;
+}
+i += newneedle_len;
+haystack += oldneedle_len;
+} else
+ret[i++] = *haystack++;
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..90522bd 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,6 @@ size_t virStringListLength(char **strings);
 virAsprintfInternal(false, 0, NULL, NULL, 0, \
 strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv4 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-11-25 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately to
validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only tested with Virtualbox 4.2 but the code is
compliant with Virtualbox 4.3 API.

Regards,
Manuel VIVES

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 (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 po/POTFILES.in   |1 +
 src/conf/domain_conf.c   |2 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1854 +++---
 8 files changed, 1879 insertions(+), 112 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv3 RESEND 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-10-18 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  387 ++
 1 file changed, 387 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index b52695f..de6602b 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6057,6 +6057,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -7997,7 +8059,314 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (i=0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMac

[libvirt] [PATCHv3 RESEND 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-10-18 Thread Manuel VIVES
---
 po/POTFILES.in   |1 +
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 4 files changed, 84 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 15afdec..451a6fc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -196,6 +196,7 @@ src/util/virtypedparam.c
 src/util/viruri.c
 src/util/virusb.c
 src/util/virutil.c
+src/util/viruuid.c
 src/util/virxml.c
 src/vbox/vbox_MSCOMGlue.c
 src/vbox/vbox_XPCOMCGlue.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 84c1c28..c498ab6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1897,6 +1897,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..490676b 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,80 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Allows you to get the nth occurrence of a substring in sourceString which 
matches an uuid pattern.
+ * If there is no substring, ret is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+int
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+unsigned int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+int retCode = 0;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,"%s",
+   _("Error while compiling regular expression"));
+return -1;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+retCode = -1;
+goto cleanup;
+}
+
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+regoff_t start = pmatch[0].rm_so;
+regoff_t end = pmatch[0].rm_eo;
+if (i == position || (position > i && regexec(&pregUuidBracket, 
&sourceString[end], nmatch, pmatch, 0) != 0)) {
+/* We copy only if i == position (so that it is the uuid we're 
looking for), or position > i AND
+ * there is no matches left in the rest of the string (this is 
the case where we
+ * give a biggest @occurence than the number of matches and we 
want to return the last
+ * one)
+ */
+if (VIR_STRNDUP(*ret, sourceString + start, end - start) < 0) {
+retCode = -1;
+goto cleanup;
+}
+retCode = 1;
+goto cleanup;
+}
+
+sourceString = &sourceString[end];
+} else {
+break;
+retCode = 0;
+goto cleanup;
+}
+++i;
+}
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return retCode;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..2ce4fce 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+int virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libv

[libvirt] [PATCHv3 RESEND 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-10-18 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  848 +-
 1 file changed, 840 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index ce070c6..b52695f 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5871,6 +5880,823 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cu

[libvirt] [PATCHv3 RESEND 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-10-18 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 ++
 3 files changed, 51 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c498ab6..77347ec 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1735,6 +1735,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index d11db5c..a30a4ef 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret;
+size_t i, count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+size_t totalLength = 0;
+if (strlen(oldneedle) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
+count++;
+i += oldneedle_len - 1;
+}
+}
+if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len))) < 0) {
+ret = NULL;
+goto cleanup;
+}
+totalLength = sizeof(char *)*(i + count * (newneedle_len - oldneedle_len));
+i = 0;
+while (*haystack) {
+if (strstr(haystack, oldneedle) == haystack) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+ret = NULL;
+goto cleanup;
+}
+i += newneedle_len;
+haystack += oldneedle_len;
+} else
+ret[i++] = *haystack++;
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..90522bd 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,6 @@ size_t virStringListLength(char **strings);
 virAsprintfInternal(false, 0, NULL, NULL, 0, \
 strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv3 RESEND 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-10-18 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |2 +-
 src/vbox/vbox_tmpl.c   |  427 ++--
 2 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 562d98b..cb4112f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16923,7 +16923,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
+if (STREQ_NULLABLE(def->os.type, "hvm") &&
 def->nconsoles == 0 &&
 def->nserials > 0) {
 virDomainChrDef console;
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index cf34f5c..ce070c6 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5882,7 +5897,8 @@ 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) {
@@ -5890,7 +5906,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5898,7 +5913,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5973,6 +5987,344 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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);
+reportInternalErrorIfNS_FAILED("no domain with matching UUID");
+if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) {
+ret = -1;
+goto cleanup;
+}
+rc = snap->vtbl->GetId(snap, &snapIid.value);
+reportInternalErrorIfNS_FAILED("Could not get snapshot id");
+
+VBOX_UTF16_TO_UTF8(snapIid.value, &snapshotUuidStr);
+rc = snap->vtbl->GetMachine(snap, &snapMachine);
+reportInternalErrorIfNS_FAILED("could not get machine");
+def->ndisks = 0;
+rc = vboxArrayGet(&mediumAttachments, snapMachine, 
snapMachine->vtbl->GetMediumAttachments);
+reportInternalErrorIfNS_FAILED("no medium attachments");
+/* get the number of attachments */
+for (i = 0; i < mediumAttachments.count; i++) {
+IMediumAttachment *imediumattach = m

[libvirt] [PATCHv3 RESEND 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-10-18 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately to
validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES

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 (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 po/POTFILES.in   |1 +
 src/conf/domain_conf.c   |2 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1846 +++---
 8 files changed, 1871 insertions(+), 112 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv3 RESEND 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-09-16 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  848 +-
 1 file changed, 840 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index ded179f..2b07dec 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5896,6 +5905,823 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cu

[libvirt] [PATCHv3 RESEND 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-09-16 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  387 ++
 1 file changed, 387 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 2b07dec..4bc1054 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6082,6 +6082,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8022,7 +8084,314 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (i=0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMac

[libvirt] [PATCHv3 RESEND 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-09-16 Thread Manuel VIVES
---
 po/POTFILES.in   |1 +
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 4 files changed, 84 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2a0605b..029331b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -195,6 +195,7 @@ src/util/virtypedparam.c
 src/util/viruri.c
 src/util/virusb.c
 src/util/virutil.c
+src/util/viruuid.c
 src/util/virxml.c
 src/vbox/vbox_MSCOMGlue.c
 src/vbox/vbox_XPCOMCGlue.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 35f0f1b..a6af540 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2080,6 +2080,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..490676b 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,80 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Allows you to get the nth occurrence of a substring in sourceString which 
matches an uuid pattern.
+ * If there is no substring, ret is not modified.
+ * return -1 on error, 0 if not found and 1 if found.
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+int
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+unsigned int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+int retCode = 0;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,"%s",
+   _("Error while compiling regular expression"));
+return -1;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+retCode = -1;
+goto cleanup;
+}
+
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+regoff_t start = pmatch[0].rm_so;
+regoff_t end = pmatch[0].rm_eo;
+if (i == position || (position > i && regexec(&pregUuidBracket, 
&sourceString[end], nmatch, pmatch, 0) != 0)) {
+/* We copy only if i == position (so that it is the uuid we're 
looking for), or position > i AND
+ * there is no matches left in the rest of the string (this is 
the case where we
+ * give a biggest @occurence than the number of matches and we 
want to return the last
+ * one)
+ */
+if (VIR_STRNDUP(*ret, sourceString + start, end - start) < 0) {
+retCode = -1;
+goto cleanup;
+}
+retCode = 1;
+goto cleanup;
+}
+
+sourceString = &sourceString[end];
+} else {
+break;
+retCode = 0;
+goto cleanup;
+}
+++i;
+}
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return retCode;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..2ce4fce 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+int virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libv

[libvirt] [PATCHv3 RESEND 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-09-16 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 ++
 3 files changed, 51 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a6af540..b5f83c3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1920,6 +1920,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index d11db5c..a30a4ef 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret;
+size_t i, count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+size_t totalLength = 0;
+if (strlen(oldneedle) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
+count++;
+i += oldneedle_len - 1;
+}
+}
+if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len))) < 0) {
+ret = NULL;
+goto cleanup;
+}
+totalLength = sizeof(char *)*(i + count * (newneedle_len - oldneedle_len));
+i = 0;
+while (*haystack) {
+if (strstr(haystack, oldneedle) == haystack) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+ret = NULL;
+goto cleanup;
+}
+i += newneedle_len;
+haystack += oldneedle_len;
+} else
+ret[i++] = *haystack++;
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..90522bd 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,6 @@ size_t virStringListLength(char **strings);
 virAsprintfInternal(false, 0, NULL, NULL, 0, \
 strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv3 RESEND 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-09-16 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility 
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately 
to validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the 
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES

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 (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 po/POTFILES.in   |1 +
 src/conf/domain_conf.c   |2 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 +
 src/util/viruuid.c   |   81 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1846 +++---
 8 files changed, 1871 insertions(+), 112 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCHv3 RESEND 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-09-16 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |2 +-
 src/vbox/vbox_tmpl.c   |  427 ++--
 2 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 108f092..e7bf73e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16816,7 +16816,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
+if (STREQ_NULLABLE(def->os.type, "hvm") &&
 def->nconsoles == 0 &&
 def->nserials > 0) {
 virDomainChrDef console;
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 5e5ea85..ded179f 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5907,7 +5922,8 @@ 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) {
@@ -5915,7 +5931,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5923,7 +5938,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5998,6 +6012,344 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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);
+reportInternalErrorIfNS_FAILED("no domain with matching UUID");
+if (!(snap = vboxDomainSnapshotGet(data, dom, machine, snapshot->name))) {
+ret = -1;
+goto cleanup;
+}
+rc = snap->vtbl->GetId(snap, &snapIid.value);
+reportInternalErrorIfNS_FAILED("Could not get snapshot id");
+
+VBOX_UTF16_TO_UTF8(snapIid.value, &snapshotUuidStr);
+rc = snap->vtbl->GetMachine(snap, &snapMachine);
+reportInternalErrorIfNS_FAILED("could not get machine");
+def->ndisks = 0;
+rc = vboxArrayGet(&mediumAttachments, snapMachine, 
snapMachine->vtbl->GetMediumAttachments);
+reportInternalErrorIfNS_FAILED("no medium attachments");
+/* get the number of attachments */
+for (i = 0; i < mediumAttachments.count; i++) {
+IMediumAttachment *imediumattach = m

[libvirt] [PATCHv2 RESEND 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-09-02 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 3 files changed, 81 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 35f0f1b..a6af540 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2080,6 +2080,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..3786393 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,78 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Return the nth occurrence of a substring in sourceString which matches an 
uuid pattern
+ * If there is no substring, ret is not modified
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+char **
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+VIR_DEBUG("Error while compiling regular expression");
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+char *substring = NULL;
+int start = pmatch[0].rm_so;
+int end = pmatch[0].rm_eo;
+size_t size = end - start;
+if (VIR_ALLOC_N(substring, (size + 1)) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+if (substring) {
+if (virStrncpy(substring, &sourceString[start], size, size + 
1)) {
+substring[size] = '\0';
+if (VIR_STRDUP(*ret, substring) < 0) {
+VIR_DEBUG("cannot duplicate %s", substring);
+goto cleanup;
+}
+}
+VIR_FREE(substring);
+}
+sourceString = &sourceString[end];
+}
+++i;
+}
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..276e85f 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+char ** virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 RESEND 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-09-02 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |   20 ++-
 src/vbox/vbox_tmpl.c   |  427 ++--
 2 files changed, 427 insertions(+), 20 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f1623f1..c98ff63 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16810,15 +16810,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
-def->nconsoles == 0 &&
-def->nserials > 0) {
-virDomainChrDef console;
-memcpy(&console, def->serials[n], sizeof(console));
-console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
-if (virDomainChrDefFormat(buf, &console, flags) < 0)
-goto error;
+if (def->os.type) {
+if (STREQ(def->os.type, "hvm") &&
+def->nconsoles == 0 &&
+def->nserials > 0) {
+virDomainChrDef console;
+memcpy(&console, def->serials[n], sizeof(console));
+console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+if (virDomainChrDefFormat(buf, &console, flags) < 0)
+goto error;
+}
 }
 
 for (n = 0; n < def->nchannels; n++)
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 5e5ea85..ded179f 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5907,7 +5922,8 @@ 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) {
@@ -5915,7 +5931,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5923,7 +5938,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5998,6 +6012,344 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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);
+reportInternalErrorIf

[libvirt] [PATCHv2 RESEND 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-09-02 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  387 ++
 1 file changed, 387 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 2b07dec..4bc1054 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6082,6 +6082,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8022,7 +8084,314 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+size_t i = 0;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (i=0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMac

[libvirt] [PATCHv2 RESEND 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-09-02 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility 
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately 
to validate the utility functions.

This 2nd version brings a different function for string replacement, because of 
the license problem with
the first one.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the 
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES


Manuel VIVES (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 src/conf/domain_conf.c   |   20 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1846 +++---
 7 files changed, 1878 insertions(+), 120 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 RESEND 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-09-02 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  848 +-
 1 file changed, 840 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index ded179f..2b07dec 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5896,6 +5905,823 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+size_t i = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cu

[libvirt] [PATCHv2 RESEND 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-09-02 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 ++
 3 files changed, 51 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a6af540..b5f83c3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1920,6 +1920,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index d11db5c..a30a4ef 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret;
+size_t i, count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+size_t totalLength = 0;
+if (strlen(oldneedle) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
+count++;
+i += oldneedle_len - 1;
+}
+}
+if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len))) < 0) {
+ret = NULL;
+goto cleanup;
+}
+totalLength = sizeof(char *)*(i + count * (newneedle_len - oldneedle_len));
+i = 0;
+while (*haystack) {
+if (strstr(haystack, oldneedle) == haystack) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+ret = NULL;
+goto cleanup;
+}
+i += newneedle_len;
+haystack += oldneedle_len;
+} else
+ret[i++] = *haystack++;
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..90522bd 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,6 @@ size_t virStringListLength(char **strings);
 virAsprintfInternal(false, 0, NULL, NULL, 0, \
 strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-08-01 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |   20 ++-
 src/vbox/vbox_tmpl.c   |  424 ++--
 2 files changed, 424 insertions(+), 20 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e3aec69..98bd89d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16711,15 +16711,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
-def->nconsoles == 0 &&
-def->nserials > 0) {
-virDomainChrDef console;
-memcpy(&console, def->serials[n], sizeof(console));
-console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
-if (virDomainChrDefFormat(buf, &console, flags) < 0)
-goto error;
+if (def->os.type) {
+if (STREQ(def->os.type, "hvm") &&
+def->nconsoles == 0 &&
+def->nserials > 0) {
+virDomainChrDef console;
+memcpy(&console, def->serials[n], sizeof(console));
+console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+if (virDomainChrDefFormat(buf, &console, flags) < 0)
+goto error;
+}
 }
 
 for (n = 0; n < def->nchannels; n++)
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 5e5ea85..6a5f41a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5907,7 +5922,8 @@ 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) {
@@ -5915,7 +5931,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5923,7 +5938,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5998,6 +6012,341 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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;
+vboxIIDFromUUID(&domiid, dom->uuid);
+rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
+reportInternalErrorIfNS_FAILED("no domai

[libvirt] [PATCHv2 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-08-01 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 3 files changed, 81 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a958d94..4127f14 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2077,6 +2077,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..3786393 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,78 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Return the nth occurrence of a substring in sourceString which matches an 
uuid pattern
+ * If there is no substring, ret is not modified
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+char **
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+VIR_DEBUG("Error while compiling regular expression");
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+char *substring = NULL;
+int start = pmatch[0].rm_so;
+int end = pmatch[0].rm_eo;
+size_t size = end - start;
+if (VIR_ALLOC_N(substring, (size + 1)) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+if (substring) {
+if (virStrncpy(substring, &sourceString[start], size, size + 
1)) {
+substring[size] = '\0';
+if (VIR_STRDUP(*ret, substring) < 0) {
+VIR_DEBUG("cannot duplicate %s", substring);
+goto cleanup;
+}
+}
+VIR_FREE(substring);
+}
+sourceString = &sourceString[end];
+}
+++i;
+}
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..276e85f 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+char ** virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-08-01 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  386 ++
 1 file changed, 386 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 4138702..e1df58e 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6081,6 +6081,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8017,8 +8079,314 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (size_t i = 0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
 
 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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMachine *mach

[libvirt] [PATCHv2 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-08-01 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility 
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately 
to validate the utility functions.

This 2nd version brings a different function for string replacement, because of 
the license problem with
the first one.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the 
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES


Manuel VIVES (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 src/conf/domain_conf.c   |   20 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1842 +++---
 7 files changed, 1873 insertions(+), 121 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-08-01 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |   48 ++
 src/util/virstring.h |2 ++
 3 files changed, 51 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4127f14..70ed546 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1917,6 +1917,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index d11db5c..a30a4ef 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -616,3 +616,51 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Return a string with all the replacements in case of success, NULL in case
+  of failure
+*/
+char *
+virStrReplace(char *haystack,
+  const char *oldneedle, const char *newneedle)
+{
+char *ret;
+size_t i, count = 0;
+size_t newneedle_len = strlen(newneedle);
+size_t oldneedle_len = strlen(oldneedle);
+size_t totalLength = 0;
+if (strlen(oldneedle) == 0) {
+ignore_value(VIR_STRDUP(ret, haystack));
+goto cleanup;
+}
+
+for (i = 0; haystack[i] != '\0'; i++) {
+if (strstr(&haystack[i], oldneedle) == &haystack[i]) {
+count++;
+i += oldneedle_len - 1;
+}
+}
+if (VIR_ALLOC_N(ret, (i + count * (newneedle_len - oldneedle_len))) < 0) {
+ret = NULL;
+goto cleanup;
+}
+totalLength = sizeof(char *)*(i + count * (newneedle_len - oldneedle_len));
+i = 0;
+while (*haystack) {
+if (strstr(haystack, oldneedle) == haystack) {
+if (virStrcpy(&ret[i], newneedle, totalLength) == NULL) {
+ret = NULL;
+goto cleanup;
+}
+i += newneedle_len;
+haystack += oldneedle_len;
+} else
+ret[i++] = *haystack++;
+}
+ret[i] = '\0';
+cleanup:
+return ret;
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index b390150..90522bd 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -223,4 +223,6 @@ size_t virStringListLength(char **strings);
 virAsprintfInternal(false, 0, NULL, NULL, 0, \
 strp, __VA_ARGS__)
 
+char * virStrReplace(char *haystack, const char *oldneedle, const char 
*newneedle);
+
 #endif /* __VIR_STRING_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCHv2 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-08-01 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  846 +-
 1 file changed, 838 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 6a5f41a..4138702 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5896,6 +5905,821 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (size_t i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cur && xmlIsBl

[libvirt] [RESEND PATCH 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-07-19 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  380 ++
 1 file changed, 380 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 83cb863..75bc1ed 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6081,6 +6081,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8004,7 +8066,307 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (size_t i = 0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMachine *mach

[libvirt] [RESEND PATCH 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-07-19 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  833 +-
 1 file changed, 825 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 3dd9e8a..83cb863 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5896,6 +5905,808 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (size_t i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cur && xmlIsBl

[libvirt] [RESEND PATCH 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-07-19 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |   20 ++-
 src/vbox/vbox_tmpl.c   |  426 ++--
 2 files changed, 425 insertions(+), 21 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 57cd9b1..5a5783f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16689,15 +16689,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
-def->nconsoles == 0 &&
-def->nserials > 0) {
-virDomainChrDef console;
-memcpy(&console, def->serials[n], sizeof(console));
-console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
-if (virDomainChrDefFormat(buf, &console, flags) < 0)
-goto error;
+if (def->os.type) {
+if (STREQ(def->os.type, "hvm") &&
+def->nconsoles == 0 &&
+def->nserials > 0) {
+virDomainChrDef console;
+memcpy(&console, def->serials[n], sizeof(console));
+console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+if (virDomainChrDefFormat(buf, &console, flags) < 0)
+goto error;
+}
 }
 
 for (n = 0; n < def->nchannels; n++)
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 5e5ea85..3dd9e8a 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -3395,9 +3410,9 @@ sharedFoldersCleanup:
 VBOX_UTF8_FREE(productIdUtf8);
 
 USBFilterCount++;
-}
 }
 }
+}
 }
 }
 }
@@ -5907,7 +5922,8 @@ 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) {
@@ -5915,7 +5931,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5923,7 +5938,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -5998,6 +6012,341 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+vboxArray mediumAttachments 

[libvirt] [RESEND PATCH 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-07-19 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |  129 ++
 src/util/virstring.h |6 +++
 3 files changed, 136 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 57a1b50..65e85d4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1901,6 +1901,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 1f4850e..81a3a4d 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -613,3 +613,132 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, haystacksize, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Resulting haystack contains no more than haystacksize characters (including 
the '\0').
+  If haystacksize is too small to make the replacements, do not modify 
haystack at all.
+
+ RETURN VALUES
+ virStrReplace() returns haystack on success and NULL on failure.
+ Failure means there was not enough room to replace all occurences of 
oldneedle.
+ Success is returned otherwise, even if no replacement is made.
+Methods found here: http://stackoverflow.com/a/12546318, author: Brandin
+*/
+char *
+virStrReplace(char *haystack, size_t haystacksize,
+const char *oldneedle, const char *newneedle)
+{
+size_t oldneedle_len = strlen(oldneedle);
+size_t newneedle_len = strlen(newneedle);
+char *oldneedle_ptr;// locates occurences of oldneedle
+char *read_ptr; // where to read in the haystack
+char *write_ptr;// where to write in the haystack
+const char *oldneedle_last =  // the last character in oldneedle
+oldneedle +
+oldneedle_len - 1;
+
+// Case 0: oldneedle is empty
+if (oldneedle_len == 0)
+return (char *)haystack; // nothing to do;
+
+// Case 1: newneedle is not longer than oldneedle
+if (newneedle_len <= oldneedle_len) {
+// Pass 1: Perform copy/replace using read_ptr and write_ptr
+for (oldneedle_ptr = (char *)oldneedle,
+read_ptr = haystack, write_ptr = haystack;
+*read_ptr != '\0';
+read_ptr++, write_ptr++)
+{
+*write_ptr = *read_ptr;
+bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found)  {
+// then perform update
+write_ptr -= oldneedle_len;
+memcpy(write_ptr+1, newneedle, newneedle_len);
+write_ptr += newneedle_len;
+}
+}
+*write_ptr = '\0';
+return (char *)haystack;
+}
+
+// Case 2: newneedle is longer than oldneedle
+else {
+size_t diff_len =   // the amount of extra space needed
+newneedle_len - // to replace oldneedle with newneedle
+oldneedle_len;  // in the expanded haystack
+
+// Pass 1: Perform forward scan, updating write_ptr along the way
+for (oldneedle_ptr = (char *)oldneedle,
+read_ptr = haystack, write_ptr = haystack;
+*read_ptr != '\0';
+read_ptr++, write_ptr++)
+{
+bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found) {
+// then advance write_ptr
+write_ptr += diff_len;
+}
+if (write_ptr >= haystack+haystacksize)
+return NULL; // no more room in haystack
+}
+
+// Pass 2: Walk backwards through haystack, performing copy/replace
+for (oldneedle_ptr = (char *)oldneedle_last;
+write_ptr >= haystack;
+write_ptr--, read_ptr--)
+{
+*write_ptr = *read_ptr;
+bool found = virLocateBackward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found) {
+// then perform replacement
+write_ptr -= diff_len;
+memcpy(write_ptr, newneedle, newneedle_len);
+}
+}
+return (char *)haystack;
+}
+}
+
+// virLocateForward: compare needle_ptr and read_ptr to see if a match occured
+// needle_ptr is updated as appropriate for the next call
+// return true if match occured, false otherwise
+bool
+virLocateForward(char **needle_ptr, char *read_ptr,
+const char *needle, const char *needle_last)
+{
+if (**needle_ptr == *read_ptr) {
+(*needle_ptr)++;
+if (*needle_ptr > needle_last) {
+*needle_ptr = (char *)needle;
+return true;
+}
+}
+else
+*needle_ptr = (char *)needle;
+return false;
+}
+
+// virLocateBackward: compare needle_ptr and read_ptr 

[libvirt] [RESEND PATCH 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-07-19 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

The serie of patches is rather big, and adds among other things some utility 
functions unrelated to VirtualBox in patches 1 & 2.
The code review could be done in several parts: e.g. patches 1 & 2 separately 
to validate the utility functions.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the 
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES


Manuel VIVES (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 src/conf/domain_conf.c   |   20 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |  129 
 src/util/virstring.h |6 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1821 +++---
 7 files changed, 1938 insertions(+), 120 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [RESEND PATCH 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-07-19 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 3 files changed, 81 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7790ede..57a1b50 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2053,6 +2053,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index c5fa9a8..3786393 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -333,3 +337,78 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Return the nth occurrence of a substring in sourceString which matches an 
uuid pattern
+ * If there is no substring, ret is not modified
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+char **
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+size_t i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+VIR_DEBUG("Error while compiling regular expression");
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+char *substring = NULL;
+int start = pmatch[0].rm_so;
+int end = pmatch[0].rm_eo;
+size_t size = end - start;
+if (VIR_ALLOC_N(substring, (size + 1)) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+if (substring) {
+if (virStrncpy(substring, &sourceString[start], size, size + 
1)) {
+substring[size] = '\0';
+if (VIR_STRDUP(*ret, substring) < 0) {
+VIR_DEBUG("cannot duplicate %s", substring);
+goto cleanup;
+}
+}
+VIR_FREE(substring);
+}
+sourceString = &sourceString[end];
+}
+++i;
+}
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..276e85f 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+char ** virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 0/5] Handling of undefine and redefine snapshots with VirtualBox 4.2

2013-06-20 Thread Manuel VIVES
Hi,
This is a serie of patches in order to support undefining and redefining
snapshots with VirtualBox 4.2.

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 taken to emulate these
behaviours by manipulating directly the .vbox XML files.

The first two patches are some util methods for handling uuid and strings that
will be used after.

The third patch brings more details in the snapshot XML returned by libvirt.
We will need those modifications in order to redefine the snapshots.

The fourth patch brings the support of the VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE
and VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT flags in virDomainSnapshotCreateXML.

The fifth and last patch brings the support of the 
VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY
flag in virDomainSnapshotDelete.

The patches are only for Virtualbox 4.2

Regards,
Manuel VIVES

Manuel VIVES (5):
  viruuid.h/c: Util method for finding uuid patterns in some strings
  virstring.h/c: Util method for making some find and replace in
strings
  vbox_tmpl.c: Better XML description for snapshots
  vbox_tmpl.c: Patch for redefining snapshots
  vbox_tmpl.c: Add methods for undefining snapshots

 src/conf/domain_conf.c   |   20 +-
 src/libvirt_private.syms |2 +
 src/util/virstring.c |  129 
 src/util/virstring.h |6 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 src/vbox/vbox_tmpl.c | 1831 +++---
 7 files changed, 1943 insertions(+), 125 deletions(-)

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH 5/5] vbox_tmpl.c: Add methods for undefining snapshots

2013-06-20 Thread Manuel VIVES
All the informations concerning snapshots (and snapshot disks)
will be deleted from the vbox xml. But the differencing disks will be
kept so you will be able to redefine the snapshots.
---
 src/vbox/vbox_tmpl.c |  380 ++
 1 file changed, 380 insertions(+)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 9d62c3e..8c983b3 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -6117,6 +6117,68 @@ vboxSnapshotXmlAppendDiskToMediaRegistry(xmlNodePtr 
*inMediaRegistry,
 }
 }
 
+
+static void
+vboxRemoveAllDisksExceptParentFromMediaRegistry(xmlNodePtr mediaRegistryNode){
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")) {
+xmlNodePtr child = NULL;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we delete it
+ */
+if (child->type == XML_ELEMENT_NODE) {
+xmlUnlinkNode(child);
+xmlFreeNode(child);
+}
+}
+}
+}
+if ((cur_node->children))
+
vboxRemoveAllDisksExceptParentFromMediaRegistry((cur_node->children));
+}
+}
+
+static void
+vboxRemoveDiskFromMediaRegistryIfNoChildren(xmlNodePtr mediaRegistryNode,
+char *diskLocation)
+{
+/*
+ *This function will remove a disk from the media registry only if it 
doesn't
+ *have any children
+ */
+xmlNodePtr cur_node = NULL;
+for (cur_node = mediaRegistryNode; cur_node; cur_node = cur_node->next) {
+if (cur_node) {
+if (cur_node->type == XML_ELEMENT_NODE
+&& !xmlStrcmp(cur_node->name, (const xmlChar *) "HardDisk")
+&& xmlHasProp(cur_node, BAD_CAST "location") != NULL
+&& strstr(diskLocation, (char *)xmlHasProp(cur_node, BAD_CAST 
"location")->children->content) != NULL) {
+
+xmlNodePtr child = NULL;
+bool deleteNode = true;
+for (child = cur_node->children; child; child = child->next) {
+/*We look over all the children
+ *If there is a node element, we don't delete it
+ */
+if (child->type == XML_ELEMENT_NODE)
+deleteNode = false;
+}
+if (deleteNode) {
+xmlUnlinkNode(cur_node);
+xmlFreeNode(cur_node);
+}
+return;
+}
+}
+if ((cur_node->children))
+vboxRemoveDiskFromMediaRegistryIfNoChildren((cur_node->children), 
diskLocation);
+}
+}
+
 static int
 vboxSnapshotGenerateVboxXML(xmlNodePtr rootElementVboxXML,
 char *storageControllerString,
@@ -8047,8 +8109,308 @@ cleanup:
 vboxArrayRelease(&children);
 return ret;
 }
+#if VBOX_API_VERSION >= 4002
+static int
+vboxCloseDisk(virDomainPtr dom,
+  IMedium *baseDisk) {
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+if (!baseDisk)
+return -1;
+
+rc = vboxArrayGet(&childrenDiskArray, baseDisk, 
baseDisk->vtbl->GetChildren);
+if (NS_FAILED(rc)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("could not get children disks"));
+ret = -1;
+goto cleanup;
+}
+for (int i = 0; i < childrenDiskArray.count; ++i)
+vboxCloseDisk(dom, childrenDiskArray.items[i]);
+
+baseDisk->vtbl->Close(baseDisk);
+ret = 0;
+cleanup:
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
 
 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, we will set the 
current snapshot of the machine to
+ *its parent.
+ *
+ *Before the writing of the modified xml file, we undefine the machine 
from vbox
+ *After the modification, we redefine the machine
+ */
+
+virDomainPtr dom = snapshot->domain;
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+IMachine *machine

[libvirt] [PATCH 4/5] vbox_tmpl.c: Patch for redefining snapshots

2013-06-20 Thread Manuel VIVES
The snapshots are saved in xml files, and then can be redefined
---
 src/vbox/vbox_tmpl.c |  833 +-
 1 file changed, 825 insertions(+), 8 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 6d8dba7..9d62c3e 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -61,6 +61,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "virutil.h"
+#include "dirname.h"
 
 /* This one changes from version to version. */
 #if VBOX_API_VERSION == 2002
@@ -274,6 +275,12 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+/*This error is a bit specific
+ *In the VBOX API it is named E_ACCESSDENIED
+ *It is returned when the called object is not ready. In
+ *particular when we do any call on a disk which has been closed
+*/
+#define VBOX_E_ACCESSDENIED 0x80070005
 #define reportInternalErrorIfNS_FAILED(message) \
 if (NS_FAILED(rc)) { \
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
@@ -284,6 +291,8 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
+static virStorageVolPtr vboxStorageVolLookupByPath(virConnectPtr conn, const 
char *path);
+static int vboxStorageDeleteOrClose(virStorageVolPtr vol, unsigned int flags, 
unsigned int flagDeleteOrClose);
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -5932,6 +5941,808 @@ cleanup:
 return snapshot;
 }
 
+#if VBOX_API_VERSION >=4002
+static void
+vboxSnapshotXmlRetrieveSnapshotNodeByName(xmlNodePtr a_node,
+   const char *name,
+   xmlNodePtr *snap_node)
+{
+xmlNodePtr cur_node = NULL;
+
+for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+if (cur_node->type == XML_ELEMENT_NODE) {
+if (!xmlStrcmp(cur_node->name, (const xmlChar *) "Snapshot") &&
+STREQ(virXMLPropString(cur_node, "name"), name)) {
+*snap_node = cur_node;
+return;
+}
+}
+if (cur_node->children)
+vboxSnapshotXmlRetrieveSnapshotNodeByName(cur_node->children, 
name, snap_node);
+}
+}
+
+
+
+
+static int
+vboxDetachAndCloseDisks(virDomainPtr dom,
+IMedium *disk)
+{
+VBOX_OBJECT_CHECK(dom->conn, int, -1);
+nsresult rc;
+PRUnichar *location = NULL;
+vboxArray childrenDiskArray = VBOX_ARRAY_INITIALIZER;
+virStorageVolPtr volPtr = NULL;
+char *location_utf8 = NULL;
+PRUint32 dummyState = 0;
+if (disk == NULL) {
+VIR_DEBUG("Null pointer to disk");
+return -1;
+}
+rc = disk->vtbl->GetLocation(disk, &location);
+if (rc == VBOX_E_ACCESSDENIED) {
+VIR_DEBUG("Disk already closed");
+goto cleanup;
+}
+reportInternalErrorIfNS_FAILED("cannot get disk location");
+rc = vboxArrayGet(&childrenDiskArray, disk, disk->vtbl->GetChildren);
+reportInternalErrorIfNS_FAILED("cannot get children disks");
+for (int i = 0; i < childrenDiskArray.count; ++i) {
+IMedium *childDisk = childrenDiskArray.items[i];
+if (childDisk) {
+vboxDetachAndCloseDisks(dom, childDisk);
+}
+}
+rc = disk->vtbl->RefreshState(disk, &dummyState);
+reportInternalErrorIfNS_FAILED("cannot refresh state");
+VBOX_UTF16_TO_UTF8(location, &location_utf8);
+volPtr = vboxStorageVolLookupByPath(dom->conn, location_utf8);
+
+if (volPtr) {
+VIR_DEBUG("Closing %s", location_utf8);
+if (vboxStorageDeleteOrClose(volPtr, 0, VBOX_STORAGE_CLOSE_FLAG) != 0) 
{
+VIR_DEBUG("Error while closing disk");
+}
+}
+VBOX_UTF8_FREE(location_utf8);
+cleanup:
+VBOX_UTF16_FREE(location);
+vboxArrayRelease(&childrenDiskArray);
+return ret;
+}
+
+static void
+vboxSnapshotXmlAddChild(xmlNodePtr parent,
+xmlNodePtr child)
+{
+/*Used in order to add child without writing the stuff concerning xml 
namespaces*/
+xmlBufferPtr tmpBuf = xmlBufferCreate();
+char *tmpString = NULL;
+xmlNodePtr tmpNode = NULL;
+xmlNodeDump(tmpBuf, parent->doc, child, 0, 0);
+ignore_value(VIR_STRDUP(tmpString, (char *)xmlBufferContent(tmpBuf)));
+xmlParseInNodeContext(parent, tmpString, (int)strlen(tmpString), 0, 
&tmpNode);
+if (tmpNode) {
+if (xmlAddChild(parent, xmlCopyNode(tmpNode, 1)) == NULL) {
+VIR_DEBUG("Error while adding %s to %s", (char *)tmpNode->name, 
(char *)parent->name);
+}
+}
+xmlFree(tmpNode);
+xmlBufferFree(tmpBuf);
+}
+
+static void
+vboxSnapshotXmlRetrieveMachineNode(xmlNodePtr root,
+xmlNodePtr *machineNode)
+{
+xmlNodePtr cur = root->xmlChildrenNode;
+while (cur && xmlIsBlank

[libvirt] [PATCH 2/5] virstring.h/c: Util method for making some find and replace in strings

2013-06-20 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/virstring.c |  129 ++
 src/util/virstring.h |6 +++
 3 files changed, 136 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6511044..09ad1c1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1829,6 +1829,7 @@ virStringListLength;
 virStringSplit;
 virStrncpy;
 virStrndup;
+virStrReplace;
 virStrToDouble;
 virStrToLong_i;
 virStrToLong_l;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 1937f82..9526a7d 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -608,3 +608,132 @@ size_t virStringListLength(char **strings)
 
 return i;
 }
+
+/*
+ virStrReplace(haystack, haystacksize, oldneedle, newneedle) --
+  Search haystack and replace all occurences of oldneedle with newneedle.
+  Resulting haystack contains no more than haystacksize characters (including 
the '\0').
+  If haystacksize is too small to make the replacements, do not modify 
haystack at all.
+
+ RETURN VALUES
+ virStrReplace() returns haystack on success and NULL on failure.
+ Failure means there was not enough room to replace all occurences of 
oldneedle.
+ Success is returned otherwise, even if no replacement is made.
+Methods found here: http://stackoverflow.com/a/12546318, author: Brandin
+*/
+char *
+virStrReplace(char *haystack, size_t haystacksize,
+const char *oldneedle, const char *newneedle)
+{
+size_t oldneedle_len = strlen(oldneedle);
+size_t newneedle_len = strlen(newneedle);
+char *oldneedle_ptr;// locates occurences of oldneedle
+char *read_ptr; // where to read in the haystack
+char *write_ptr;// where to write in the haystack
+const char *oldneedle_last =  // the last character in oldneedle
+oldneedle +
+oldneedle_len - 1;
+
+// Case 0: oldneedle is empty
+if (oldneedle_len == 0)
+return (char *)haystack; // nothing to do;
+
+// Case 1: newneedle is not longer than oldneedle
+if (newneedle_len <= oldneedle_len) {
+// Pass 1: Perform copy/replace using read_ptr and write_ptr
+for (oldneedle_ptr = (char *)oldneedle,
+read_ptr = haystack, write_ptr = haystack;
+*read_ptr != '\0';
+read_ptr++, write_ptr++)
+{
+*write_ptr = *read_ptr;
+bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found)  {
+// then perform update
+write_ptr -= oldneedle_len;
+memcpy(write_ptr+1, newneedle, newneedle_len);
+write_ptr += newneedle_len;
+}
+}
+*write_ptr = '\0';
+return (char *)haystack;
+}
+
+// Case 2: newneedle is longer than oldneedle
+else {
+size_t diff_len =   // the amount of extra space needed
+newneedle_len - // to replace oldneedle with newneedle
+oldneedle_len;  // in the expanded haystack
+
+// Pass 1: Perform forward scan, updating write_ptr along the way
+for (oldneedle_ptr = (char *)oldneedle,
+read_ptr = haystack, write_ptr = haystack;
+*read_ptr != '\0';
+read_ptr++, write_ptr++)
+{
+bool found = virLocateForward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found) {
+// then advance write_ptr
+write_ptr += diff_len;
+}
+if (write_ptr >= haystack+haystacksize)
+return NULL; // no more room in haystack
+}
+
+// Pass 2: Walk backwards through haystack, performing copy/replace
+for (oldneedle_ptr = (char *)oldneedle_last;
+write_ptr >= haystack;
+write_ptr--, read_ptr--)
+{
+*write_ptr = *read_ptr;
+bool found = virLocateBackward(&oldneedle_ptr, read_ptr,
+oldneedle, oldneedle_last);
+if (found) {
+// then perform replacement
+write_ptr -= diff_len;
+memcpy(write_ptr, newneedle, newneedle_len);
+}
+}
+return (char *)haystack;
+}
+}
+
+// virLocateForward: compare needle_ptr and read_ptr to see if a match occured
+// needle_ptr is updated as appropriate for the next call
+// return true if match occured, false otherwise
+bool
+virLocateForward(char **needle_ptr, char *read_ptr,
+const char *needle, const char *needle_last)
+{
+if (**needle_ptr == *read_ptr) {
+(*needle_ptr)++;
+if (*needle_ptr > needle_last) {
+*needle_ptr = (char *)needle;
+return true;
+}
+}
+else
+*needle_ptr = (char *)needle;
+return false;
+}
+
+// virLocateBackward: compare needle_ptr and read_ptr 

[libvirt] [PATCH 3/5] vbox_tmpl.c: Better XML description for snapshots

2013-06-20 Thread Manuel VIVES
It will be needed for the futur patches because we will
redefine snapshots
---
 src/conf/domain_conf.c |   20 ++-
 src/vbox/vbox_tmpl.c   |  430 ++--
 2 files changed, 427 insertions(+), 23 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2373397..085a90f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16355,15 +16355,17 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 if (virDomainChrDefFormat(buf, &console, flags) < 0)
 goto error;
 }
-if (STREQ(def->os.type, "hvm") &&
-def->nconsoles == 0 &&
-def->nserials > 0) {
-virDomainChrDef console;
-memcpy(&console, def->serials[n], sizeof(console));
-console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
-if (virDomainChrDefFormat(buf, &console, flags) < 0)
-goto error;
+if (def->os.type) {
+if (STREQ(def->os.type, "hvm") &&
+def->nconsoles == 0 &&
+def->nserials > 0) {
+virDomainChrDef console;
+memcpy(&console, def->serials[n], sizeof(console));
+console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
+if (virDomainChrDefFormat(buf, &console, flags) < 0)
+goto error;
+}
 }
 
 for (n = 0; n < def->nchannels; n++)
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index d6d34c1..6d8dba7 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #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 == 2002
@@ -271,10 +274,16 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000 */
 
+#define reportInternalErrorIfNS_FAILED(message) \
+if (NS_FAILED(rc)) { \
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(message)); \
+goto cleanup; \
+}
+
+
 static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 static int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
-
 static void vboxDriverLock(vboxGlobalData *data) {
 virMutexLock(&data->lock);
 }
@@ -283,6 +292,12 @@ static void vboxDriverUnlock(vboxGlobalData *data) {
 virMutexUnlock(&data->lock);
 }
 
+typedef enum {
+VBOX_STORAGE_DELETE_FLAG = 0,
+#if VBOX_API_VERSION >= 4002
+VBOX_STORAGE_CLOSE_FLAG = 1,
+#endif
+} vboxStorageDeleteOrCloseFlags;
 #if VBOX_API_VERSION == 2002
 
 static void nsIDtoChar(unsigned char *uuid, const nsID *iid) {
@@ -5943,7 +5958,8 @@ 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) {
@@ -5951,7 +5967,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("disk snapshots not supported yet"));
 goto cleanup;
 }
-
 vboxIIDFromUUID(&domiid, dom->uuid);
 rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
 if (NS_FAILED(rc)) {
@@ -5959,7 +5974,6 @@ vboxDomainSnapshotCreateXML(virDomainPtr dom,
_("no domain with matching UUID"));
 goto cleanup;
 }
-
 rc = machine->vtbl->GetState(machine, &state);
 if (NS_FAILED(rc)) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -6034,6 +6048,341 @@ cleanup:
 return ret;
 }
 
+#if VBOX_API_VERSION >=4002
+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;
+bool error = false;
+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;
+vboxIIDFromUUID(&domiid, dom->uuid);
+rc = VBOX_OBJECT_GET_MACHINE(domiid.value, &machine);
+reportInternalErrorIfNS_FAILED("no domai

[libvirt] [PATCH 1/5] viruuid.h/c: Util method for finding uuid patterns in some strings

2013-06-20 Thread Manuel VIVES
---
 src/libvirt_private.syms |1 +
 src/util/viruuid.c   |   79 ++
 src/util/viruuid.h   |1 +
 3 files changed, 81 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b449293..6511044 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1974,6 +1974,7 @@ virValidateWWN;
 
 # util/viruuid.h
 virGetHostUUID;
+virSearchUuid;
 virSetHostUUIDStr;
 virUUIDFormat;
 virUUIDGenerate;
diff --git a/src/util/viruuid.c b/src/util/viruuid.c
index 9f4bb13..cf72e73 100644
--- a/src/util/viruuid.c
+++ b/src/util/viruuid.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "c-ctype.h"
 #include "internal.h"
@@ -43,11 +44,14 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virrandom.h"
+#include "virstring.h"
 
 #ifndef ENODATA
 # define ENODATA EIO
 #endif
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 static unsigned char host_uuid[VIR_UUID_BUFLEN];
 
 static int
@@ -332,3 +336,78 @@ int virGetHostUUID(unsigned char *uuid)
 
 return ret;
 }
+
+
+/**
+ * virSearchUuid:
+ * Return the nth occurrence of a substring in sourceString which matches an 
uuid pattern
+ * If there is no substring, ret is not modified
+ *
+ * @sourceString: String to parse
+ * @occurrence: We will return the nth occurrence of uuid in substring, if 
equals to 0 (or negative), will return the first occurence
+ * @ret: nth occurrence substring matching an uuid pattern
+ * @code
+char *source = "6853a496-1c10-472e-867a-8244937bd6f0 
773ab075-4cd7-4fc2-8b6e-21c84e9cb391 bbb3c75c-d60f-43b0-b802-fd56b84a4222 
60c04aa1-0375-4654-8d9f-e149d9885273 4548d465-9891-4c34-a184-3b1c34a26aa8";
+char *ret1=NULL;
+char *ret2=NULL;
+char *ret3=NULL;
+char *ret4=NULL;
+virSearchUuid(source, 4,&ret1);  //ret1 = 
"60c04aa1-0375-4654-8d9f-e149d9885273"
+virSearchUuid(source, 0,&ret2);  //ret2 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, 1,&ret3);  //ret3 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+virSearchUuid(source, -4,&ret4); //ret4 = 
"6853a496-1c10-472e-867a-8244937bd6f0"
+ * @endcode
+ */
+
+char **
+virSearchUuid(const char *sourceString, int occurrence,char **ret)
+{
+int position = ((occurrence -1) > 0) ? (occurrence -1) : 0;
+
+const char *uuidRegex = 
"([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})";
+regex_t pregUuidBracket;
+unsigned int i = 0;
+size_t nmatch = 0;
+regmatch_t *pmatch = NULL;
+if (regcomp(&pregUuidBracket, uuidRegex, REG_EXTENDED) != 0) {
+VIR_DEBUG("Error while compiling regular expression");
+goto cleanup;
+}
+nmatch = pregUuidBracket.re_nsub;
+if (VIR_ALLOC_N(pmatch, nmatch) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+while (i < (position+1)) {
+if (regexec(&pregUuidBracket, sourceString, nmatch, pmatch, 0) == 0) {
+char *substring = NULL;
+int start = pmatch[0].rm_so;
+int end = pmatch[0].rm_eo;
+size_t size = end - start;
+if (VIR_ALLOC_N(substring, (size + 1)) != 0) {
+virReportOOMError();
+goto cleanup;
+}
+if (substring) {
+if (virStrncpy(substring, &sourceString[start], size, size + 
1)) {
+substring[size] = '\0';
+if (VIR_STRDUP(*ret, substring) < 0) {
+VIR_DEBUG("cannot duplicate %s", substring);
+goto cleanup;
+}
+}
+VIR_FREE(substring);
+}
+sourceString = &sourceString[end];
+}
+++i;
+}
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+
+cleanup:
+regfree(&pregUuidBracket);
+VIR_FREE(pmatch);
+return ret;
+}
diff --git a/src/util/viruuid.h b/src/util/viruuid.h
index bebd338..276e85f 100644
--- a/src/util/viruuid.h
+++ b/src/util/viruuid.h
@@ -40,4 +40,5 @@ int virUUIDParse(const char *uuidstr,
 const char *virUUIDFormat(const unsigned char *uuid,
   char *uuidstr) ATTRIBUTE_NONNULL(1) 
ATTRIBUTE_NONNULL(2);
 
+char ** virSearchUuid(const char *sourceString, int occurrence, char **ret);
 #endif /* __VIR_UUID_H__ */
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH RESEND 3/5] Makefile.am additions for VirtualBox v4.2

2013-05-22 Thread Manuel VIVES
From: ryan woodsmall 

---
 src/Makefile.am |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 430a356..467ec5d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -593,7 +593,8 @@ VBOX_DRIVER_SOURCES =   
\
vbox/vbox_V3_1.c vbox/vbox_CAPI_v3_1.h  \
vbox/vbox_V3_2.c vbox/vbox_CAPI_v3_2.h  \
vbox/vbox_V4_0.c vbox/vbox_CAPI_v4_0.h  \
-   vbox/vbox_V4_1.c vbox/vbox_CAPI_v4_1.h
+   vbox/vbox_V4_1.c vbox/vbox_CAPI_v4_1.h  \
+   vbox/vbox_V4_2.c vbox/vbox_CAPI_v4_2.h
 
 VBOX_DRIVER_EXTRA_DIST =   \
vbox/vbox_tmpl.c vbox/README\
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH RESEND 2/5] vbox version-specific C file for VirtualBox v4.2

2013-05-22 Thread Manuel VIVES
From: ryan woodsmall 

---
 src/vbox/vbox_V4_2.c |   13 +
 1 file changed, 13 insertions(+)
 create mode 100644 src/vbox/vbox_V4_2.c

diff --git a/src/vbox/vbox_V4_2.c b/src/vbox/vbox_V4_2.c
new file mode 100644
index 000..8c5b61c
--- /dev/null
+++ b/src/vbox/vbox_V4_2.c
@@ -0,0 +1,13 @@
+/** @file vbox_V4_2.c
+ * C file to include support for multiple versions of VirtualBox
+ * at runtime.
+ */
+
+#include 
+
+/** The API Version */
+#define VBOX_API_VERSION4002
+/** Version specific prefix. */
+#define NAME(name)  vbox42##name
+
+#include "vbox_tmpl.c"
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH RESEND 4/5] vbox driver support for VirtualBox v4.2

2013-05-22 Thread Manuel VIVES
From: ryan woodsmall 

---
 src/vbox/vbox_driver.c |8 
 1 file changed, 8 insertions(+)

diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c
index a68f33d..9d07574 100644
--- a/src/vbox/vbox_driver.c
+++ b/src/vbox/vbox_driver.c
@@ -61,6 +61,9 @@ extern virStorageDriver vbox40StorageDriver;
 extern virDriver vbox41Driver;
 extern virNetworkDriver vbox41NetworkDriver;
 extern virStorageDriver vbox41StorageDriver;
+extern virDriver vbox42Driver;
+extern virNetworkDriver vbox42NetworkDriver;
+extern virStorageDriver vbox42StorageDriver;
 
 static virDriver vboxDriverDummy;
 
@@ -124,6 +127,11 @@ int vboxRegister(void) {
 driver= &vbox41Driver;
 networkDriver = &vbox41NetworkDriver;
 storageDriver = &vbox41StorageDriver;
+} else if (uVersion >= 4001051 && uVersion < 4002051) {
+VIR_DEBUG("VirtualBox API version: 4.2");
+driver= &vbox42Driver;
+networkDriver = &vbox42NetworkDriver;
+storageDriver = &vbox42StorageDriver;
 } else {
 VIR_DEBUG("Unsupported VirtualBox API version: %u", uVersion);
 }
-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH RESEND 5/5] vbox template support for VirtualBox v4.2

2013-05-22 Thread Manuel VIVES
From: ryan woodsmall 

---
 src/vbox/vbox_tmpl.c |   90 --
 1 file changed, 80 insertions(+), 10 deletions(-)

diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index d37888c..5bef956 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -72,6 +72,8 @@
 # include "vbox_CAPI_v4_0.h"
 #elif VBOX_API_VERSION == 4001
 # include "vbox_CAPI_v4_1.h"
+#elif VBOX_API_VERSION == 4002
+# include "vbox_CAPI_v4_2.h"
 #else
 # error "Unsupport VBOX_API_VERSION"
 #endif
@@ -4178,9 +4180,12 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData 
*data, IMachine *machine)
 continue;
 }
 
-# if VBOX_API_VERSION >= 4000
+# if VBOX_API_VERSION >= 4000 && VBOX_API_VERSION < 4002
 data->vboxObj->vtbl->FindMedium(data->vboxObj, mediumFileUtf16,
 deviceType, &medium);
+# elif VBOX_API_VERSION >= 4002
+data->vboxObj->vtbl->OpenMedium(data->vboxObj, mediumFileUtf16,
+deviceType, accessMode, PR_FALSE, 
&medium);
 # endif
 
 if (!medium) {
@@ -4920,7 +4925,11 @@ vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, 
IMachine *machine)
 machine->vtbl->GetUSBController(machine, &USBController);
 if (USBController) {
 USBController->vtbl->SetEnabled(USBController, 1);
+#if VBOX_API_VERSION < 4002
 USBController->vtbl->SetEnabledEhci(USBController, 1);
+#else
+USBController->vtbl->SetEnabledEHCI(USBController, 1);
+#endif
 
 for (i = 0; i < def->nhostdevs; i++) {
 if (def->hostdevs[i]->mode ==
@@ -5025,10 +5034,18 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr 
conn, const char *xml) {
 vboxIID mchiid = VBOX_IID_INITIALIZER;
 virDomainDefPtr def = NULL;
 PRUnichar *machineNameUtf16 = NULL;
-#if VBOX_API_VERSION >= 3002
+#if VBOX_API_VERSION >= 3002 && VBOX_API_VERSION < 4002
 PRBool override = PR_FALSE;
 #endif
 nsresult rc;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+#if VBOX_API_VERSION >= 4002
+const char *flagsUUIDPrefix = "UUID=";
+const char *flagsForceOverwrite = "forceOverwrite=0";
+const char *flagsSeparator = ",";
+char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + 
strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1];
+PRUnichar *createFlagsUtf16 = NULL;
+#endif
 
 if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt,
 1 << VIR_DOMAIN_VIRT_VBOX,
@@ -5038,6 +5055,8 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr 
conn, const char *xml) {
 
 VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16);
 vboxIIDFromUUID(&iid, def->uuid);
+virUUIDFormat(def->uuid, uuidstr);
+
 #if VBOX_API_VERSION < 3002
 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
 machineNameUtf16,
@@ -5053,7 +5072,7 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr 
conn, const char *xml) {
 iid.value,
 override,
 &machine);
-#else /* VBOX_API_VERSION >= 4000 */
+#elif VBOX_API_VERSION >= 4000 && VBOX_API_VERSION < 4002
 rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
 NULL,
 machineNameUtf16,
@@ -5061,7 +5080,23 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr 
conn, const char *xml) {
 iid.value,
 override,
 &machine);
-#endif /* VBOX_API_VERSION >= 4000 */
+#else /* VBOX_API_VERSION >= 4002 */
+snprintf(createFlags, sizeof(createFlags), "%s%s%s%s",
+ flagsUUIDPrefix,
+ uuidstr,
+ flagsSeparator,
+ flagsForceOverwrite
+);
+VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16);
+rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
+NULL,
+machineNameUtf16,
+0,
+nsnull,
+nsnull,
+createFlagsUtf16,
+&machine);
+#endif /* VBOX_API_VERSION >= 4002 */
 VBOX_UTF16_FREE(machineNameUtf16);
 
 if (NS_FAILED(rc)) {
@@ -7845,15 +7880,26 @@ static virNetworkPtr 
vboxNetworkDefineCreateXML(virConnectPtr conn, const char *
  * IP and enables the interface so even if the dhcpserver is not
  * started the interface is still up and running
  */
+#if VBOX_API_VERSION < 4002
  

[libvirt] [PATCH RESEND 0/5] VirtualBox version 4.2 support for libvirt vbox driver

2013-05-22 Thread Manuel VIVES
Hello,

I'm re-sending this patch for reviewing.
If necessary I'm willing to make
some changes to those patches.

I'm currently working on a better management for snapshots with virtualbox, 
and my work is based on Virtualbox 4.2 so that's why I'm re sending this patch.

Regards,
Manuel VIVES

Ryan Woodsmall said originally:

"This patch set adds VirtualBox 4.2 initial support for the libvirt vbox driver.
I've tested enough to check capabilities, create a VM, destroy it, etc. Five
patches total:

- Patch 1 is the C API header file from Oracle, cleaned up for libvirt.
- Patch 2 is the version specific source file for version dependency.
- Patch 3 is the src/Makefile.am change to pick up the two new files.
- Patch 4 is the vbox driver support for the new VirtualBox API/version.
- Patch 5 is the vbox_tmpl.c template support for the new version.

A few things have changed in the VirtualBox API - some small (capitalizations
of things in function names like Ip to IP and Dhcp to DHCP) and some much larger
(FindMedium is superceded by OpenMedium). The biggest change for the sake of 
this
patch set is the signature of CreateMachine is quite a bit different. Using the
Oracle source as a guide, to spin up a VM with a given UUID, it looks like a 
text
flag has to be passed in a new argument to CreateMachine. This flag is built in 
the
VirtualBox 4.2 specific ifdefs and is kind of ugly but works. Additionally, 
there
is now (unused) VM groups support in CreateMachine and the previous 'osTypeId' 
arg
is currently set to nsnull as in the Oracle code.

The FindMedium to OpenMedium changes were more straightforward and are pretty 
clear.
The rest of the vbox template changes are basically spelling/capitalization 
changes
from the looks of things.

This probably isn't perfect, but it works on git and patched against 0.10.2 for 
a
few quick tests. Not currently on the list, so ping me directly if you need any
other info on these, or if anything could use additional work. Thanks! "

ryan woodsmall (5):
  vbox C API header for VirtualBox v4.2
  vbox version-specific C file for VirtualBox v4.2
  Makefile.am additions for VirtualBox v4.2
  vbox driver support for VirtualBox v4.2
  vbox template support for VirtualBox v4.2

 src/Makefile.am   |3 +-
 src/vbox/vbox_CAPI_v4_2.h | 8855 +
 src/vbox/vbox_V4_2.c  |   13 +
 src/vbox/vbox_driver.c|8 +
 src/vbox/vbox_tmpl.c  |   90 +-
 5 files changed, 8958 insertions(+), 11 deletions(-)
 create mode 100644 src/vbox/vbox_CAPI_v4_2.h
 create mode 100644 src/vbox/vbox_V4_2.c

-- 
1.7.10.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 0/5] VirtualBox version 4.2 support for libvirt vbox driver

2013-04-16 Thread Manuel VIVES
Peter Krempa  redhat.com> writes:

> 
> On 10/02/12 11:00, ryan woodsmall wrote:
> > This patch set adds VirtualBox 4.2 initial support for the libvirt vbox 
driver.
> > I've tested enough to check capabilities, create a VM, destroy it, etc. 
Five
> > patches total:
> >
> > - Patch 1 is the C API header file from Oracle, cleaned up for libvirt.
> > - Patch 2 is the version specific source file for version dependency.
> > - Patch 3 is the src/Makefile.am change to pick up the two new files.
> > - Patch 4 is the vbox driver support for the new VirtualBox API/version.
> > - Patch 5 is the vbox_tmpl.c template support for the new version.
> >
> > A few things have changed in the VirtualBox API - some small 
(capitalizations
> > of things in function names like Ip to IP and Dhcp to DHCP) and some 
much larger
> > (FindMedium is superceded by OpenMedium). The biggest change for the 
sake of this
> > patch set is the signature of CreateMachine is quite a bit different. 
Using the
> > Oracle source as a guide, to spin up a VM with a given UUID, it looks 
like a text
> > flag has to be passed in a new argument to CreateMachine. This flag is 
built in the
> > VirtualBox 4.2 specific ifdefs and is kind of ugly but works. 
Additionally, there
> > is now (unused) VM groups support in CreateMachine and the previous 
'osTypeId' arg
> > is currently set to nsnull as in the Oracle code.
> >
> > The FindMedium to OpenMedium changes were more straightforward and are 
pretty clear.
> > The rest of the vbox template changes are basically 
spelling/capitalization changes
> > from the looks of things.
> >
> > This probably isn't perfect, but it works on git and patched against 
0.10.2 for a
> > few quick tests. Not currently on the list, so ping me directly if you 
need any
> > other info on these, or if anything could use additional work. Thanks! -
r
> >
> >
> > ryan woodsmall (5):
> >vbox C API header for VirtualBox v4.2
> >vbox version-specific C file for VirtualBox v4.2
> >Makefile.am additions for VirtualBox v4.2
> >vbox driver support for VirtualBox v4.2
> >vbox template support for VirtualBox v4.2
> >
> >   src/Makefile.am   |3 +-
> >   src/vbox/vbox_CAPI_v4_2.h | 8855 
+
> >   src/vbox/vbox_V4_2.c  |   13 +
> >   src/vbox/vbox_driver.c|8 +
> >   src/vbox/vbox_tmpl.c  |   90 +-
> >   5 files changed, 8958 insertions(+), 11 deletions(-)
> >   create mode 100644 src/vbox/vbox_CAPI_v4_2.h
> >   create mode 100644 src/vbox/vbox_V4_2.c
> 
> As the patches can still be cleanly applied on the current master I'll 
> try to do a test/review and hopefully get it merged.
> 
> Peter
> 
> 

The 4 first patches can still be applied on the current master and I could 
apply the fifth one by rebasing Peter Krempa's repo on current master and 
then regenerating the patch and apply it. 
They work flawlessly with VirtualBox 4.2.12 r84980.
Could anyone review them for inclusion? If necessary I'm willing to make 
some changes to those patches and/or to provide the rebased fifth patch.
Regards, 
Manuel


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list