[libvirt] [PATCH] Added snapshot backing store parameters to virsh vol-create-as.

--- tools/virsh.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 7 ++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 1279f41..3ba549b 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -5274,6 +5274,8 @@ static const vshCmdOptDef opts_vol_create_as[] = { {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ, N_("size of the vol with optional k,M,G,T suffix")}, {"allocation", VSH_OT_STRING, 0, N_("initial allocation size with optional k,M,G,T suffix")}, {"format", VSH_OT_STRING, 0, N_("file format type raw,bochs,qcow,qcow2,vmdk")}, + {"snapshot-source-vol", VSH_OT_STRING, 0, N_("the source volume if taking a snapshot")}, + {"snapshot-source-format", VSH_OT_STRING, 0, N_("format of the source volume if taking a snapshot")}, {NULL, 0, 0, NULL} }; @@ -5313,6 +5315,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) int found; char *xml; char *name, *capacityStr, *allocationStr, *format; + char *snapshotStrVol, *snapshotStrFormat; unsigned long long capacity, allocation = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -5339,6 +5342,8 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) vshError(ctl, _("Malformed size %s"), allocationStr); format = vshCommandOptString(cmd, "format", &found); + snapshotStrVol = vshCommandOptString(cmd, "snapshot-source-vol", &found); + snapshotStrFormat = vshCommandOptString(cmd, "snapshot-source-format", &found); virBufferAddLit(&buf, "<volume>\n"); virBufferVSprintf(&buf, " <name>%s</name>\n", name); @@ -5351,8 +5356,53 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) virBufferVSprintf(&buf, " <format type='%s'/>\n",format); virBufferAddLit(&buf, " </target>\n"); } - virBufferAddLit(&buf, "</volume>\n"); + // Convert the snapshot parameters into backingStore XML + if (snapshotStrVol) { + // Use the name of the snapshot source volume to retrieve its device path + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' as name\n", cmd->def->name, snapshotStrVol); + virStorageVolPtr snapVol = virStorageVolLookupByName(pool, snapshotStrVol); + if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as name\n", cmd->def->name, snapshotStrVol); + + if (snapVol == NULL) { + // Snapshot source volume was not found by name. Try using the snapshot-source-vol parameter as a key + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' as key\n", cmd->def->name, snapshotStrVol); + snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol); + if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as key\n", cmd->def->name, snapshotStrVol); + } + if (snapVol == NULL) { + // Snapshot source volume was not found by key either. Try using the snapshot-source-vol parameter as a path + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' by path\n", cmd->def->name, snapshotStrVol); + snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol); + if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as path\n", cmd->def->name, snapshotStrVol); + } + if (snapVol == NULL) { + vshError(ctl, _("failed to get vol '%s'"), snapshotStrVol); + return FALSE; + } + + char *snapshotStrVolPath; + if ((snapshotStrVolPath = virStorageVolGetPath(snapVol)) == NULL) { + virStorageVolFree(snapVol); + return FALSE; + } + + // Create the XML for the backing store + virBufferAddLit(&buf, " <backingStore>\n"); + virBufferVSprintf(&buf, " <path>%s</path>\n",snapshotStrVolPath); + if (snapshotStrFormat) + virBufferVSprintf(&buf, " <format type='%s'/>\n",snapshotStrFormat); + virBufferAddLit(&buf, " </backingStore>\n"); + + // Cleanup snapshot allocations + VIR_FREE(snapshotStrVolPath); + virStorageVolFree(snapVol); + } + + virBufferAddLit(&buf, "</volume>\n"); if (virBufferError(&buf)) { vshPrint(ctl, "%s", _("Failed to allocate XML buffer")); diff --git a/tools/virsh.pod b/tools/virsh.pod index cab931c..b1a8544 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -782,7 +782,8 @@ source volume is in. I<vol-name-or-key> is the name or UUID of the source volume. =item B<vol-create-as> I<pool-or-uuid> I<name> I<capacity> optional -I<--allocation> I<size> I<--format> I<string> +I<--allocation> I<size> I<--format> I<string> I<--snapshot-source-vol> I<vol-name-or-key> +I<--snapshot-source-format> I<string> Create a volume from a set of arguments. I<pool-or-uuid> is the name or UUID of the storage pool to create the volume @@ -794,6 +795,10 @@ I<--allocation> I<size> is the initial size to be allocated in the volume, with optional k, M, G, or T suffix. I<--format> I<string> is used in file based storage pools to specify the volume file format to use; raw, bochs, qcow, qcow2, vmdk. +I<--snapshot-source-vol> I<vol-name-or-key> is the source backing volume to be used if +taking a snapshot of an existing volume. +I<--snapshot-source-format> I<string> is the format of the snapshot backing volume; +raw, bochs, qcow, qcow2, vmdk. =item B<vol-clone> [optional I<--pool> I<pool-or-uuid>] I<vol-name-or-key> I<name> -- 1.7.0.1

On 06/06/2010 07:09 PM, Justin Clift wrote:
--- tools/virsh.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 7 ++++++- 2 files changed, 57 insertions(+), 2 deletions(-)
This is the resubmitted patch, now checking the given volume string as a path and key if not found as a volume name. Also now alters the user if the volume isn't found, plus includes level 5 debugging output in case it's useful. As a style thought, I generally put a fair number of comments in the code I write. Not seeing many in the existing virsh.c code, so does that mean they shouldn't be included? Regards and best wishes, Justin Clift -- Salasaga - Open Source eLearning IDE http://www.salasaga.org

On 06/06/10 - 07:09:37PM, Justin Clift wrote:
--- tools/virsh.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- tools/virsh.pod | 7 ++++++- 2 files changed, 57 insertions(+), 2 deletions(-)
Hey Justin, There are a few issues with this patch stylistically: 1) First, it didn't apply here; it seems like carriage returns were added at 80 characters, which made for a corrupt patch. I know you mentioned you were going to use git-send-mail for patches; did you use it for this one? 2) While comments are definitely appreciated, we use the C-style /* */ for comments instead of C++ style //. 3) Please wrap lines at 80 columns wherever possible. You don't have to do it in the middle of strings, but splitting along commas and other punctuation makes the patches easier to read. A few more comments inline...
diff --git a/tools/virsh.c b/tools/virsh.c index 1279f41..3ba549b 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -5274,6 +5274,8 @@ static const vshCmdOptDef opts_vol_create_as[] = { {"capacity", VSH_OT_DATA, VSH_OFLAG_REQ, N_("size of the vol with optional k,M,G,T suffix")}, {"allocation", VSH_OT_STRING, 0, N_("initial allocation size with optional k,M,G,T suffix")}, {"format", VSH_OT_STRING, 0, N_("file format type raw,bochs,qcow,qcow2,vmdk")}, + {"snapshot-source-vol", VSH_OT_STRING, 0, N_("the source volume if taking a snapshot")}, + {"snapshot-source-format", VSH_OT_STRING, 0, N_("format of the source volume if taking a snapshot")}, {NULL, 0, 0, NULL} }; @@ -5313,6 +5315,7 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) int found; char *xml; char *name, *capacityStr, *allocationStr, *format; + char *snapshotStrVol, *snapshotStrFormat; unsigned long long capacity, allocation = 0; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -5339,6 +5342,8 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) vshError(ctl, _("Malformed size %s"), allocationStr); format = vshCommandOptString(cmd, "format", &found); + snapshotStrVol = vshCommandOptString(cmd, "snapshot-source-vol", &found); + snapshotStrFormat = vshCommandOptString(cmd, "snapshot-source-format", &found); virBufferAddLit(&buf, "<volume>\n"); virBufferVSprintf(&buf, " <name>%s</name>\n", name); @@ -5351,8 +5356,53 @@ cmdVolCreateAs(vshControl *ctl, const vshCmd *cmd) virBufferVSprintf(&buf, " <format type='%s'/>\n",format); virBufferAddLit(&buf, " </target>\n"); } - virBufferAddLit(&buf, "</volume>\n"); + // Convert the snapshot parameters into backingStore XML + if (snapshotStrVol) { + // Use the name of the snapshot source volume to retrieve its device path + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' as name\n", cmd->def->name, snapshotStrVol); + virStorageVolPtr snapVol = virStorageVolLookupByName(pool, snapshotStrVol);
We don't typically mix declarations and code. It's actually not entirely true (you'll see examples of it if you look around hard enough), but it's kind of surprising to see new variables in the middle of blocks of code. Please move this to the top.
+ if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as name\n", cmd->def->name, snapshotStrVol); + + if (snapVol == NULL) { + // Snapshot source volume was not found by name. Try using the snapshot-source-vol parameter as a key + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' as key\n", cmd->def->name, snapshotStrVol); + snapVol = virStorageVolLookupByKey(ctl->conn, snapshotStrVol); + if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as key\n", cmd->def->name, snapshotStrVol); + } + if (snapVol == NULL) { + // Snapshot source volume was not found by key either. Try using the snapshot-source-vol parameter as a path + vshDebug(ctl, 5, "%s: Looking up backing store volume '%s' by path\n", cmd->def->name, snapshotStrVol); + snapVol = virStorageVolLookupByPath(ctl->conn, snapshotStrVol); + if (snapVol) + vshDebug(ctl, 5, "%s: Backing store volume found using '%s' as path\n", cmd->def->name, snapshotStrVol); + } + if (snapVol == NULL) { + vshError(ctl, _("failed to get vol '%s'"), snapshotStrVol); + return FALSE; + } + + char *snapshotStrVolPath; + if ((snapshotStrVolPath = virStorageVolGetPath(snapVol)) == NULL) { + virStorageVolFree(snapVol); + return FALSE; + } + + // Create the XML for the backing store + virBufferAddLit(&buf, " <backingStore>\n"); + virBufferVSprintf(&buf, " <path>%s</path>\n",snapshotStrVolPath);
I'm not entirely certain because of the broken patch, but it seems like you need to add 4 spaces before <path>.
+ if (snapshotStrFormat) + virBufferVSprintf(&buf, " <format type='%s'/>\n",snapshotStrFormat);
Here, you'll have to handle the case where the user passed in NULL for snapshotStrFormat.
+ virBufferAddLit(&buf, " </backingStore>\n"); + + // Cleanup snapshot allocations + VIR_FREE(snapshotStrVolPath); + virStorageVolFree(snapVol); + } + + virBufferAddLit(&buf, "</volume>\n");
Overall, it looks OK. I'm not a huge fan of the separation of --snapshot-source-vol and --snapshot-source-format, since it makes it too easy to mess up one or the other. On the other hand, it is a bit easier than making XML by hand, and I don't have any better ideas, so maybe we should leave it as-is. If we do leave it, I think you'll want to add some code to check for all 4 cases of: snapshotStrVol == NULL, snapshotStrFormat == NULL snapshotStrVol == specified, snapshotStrFormat == NULL snapshotStrVol == specified, snapshotStrFormat == specified snapshotStrVol == NULL, snapshotStrFormat == specified -- Chris Lalancette
participants (2)
-
Chris Lalancette
-
Justin Clift