Take care of escaping '"' and '|' (the escape character).
Add tests for this.
---
src/esx/esx_vmx.c | 124 ++++++++++++++++++++++++-----
tests/vmx2xmldata/vmx2xml-annotation.vmx | 3 +
tests/vmx2xmldata/vmx2xml-annotation.xml | 16 ++++
tests/vmx2xmltest.c | 2 +
tests/xml2vmxdata/xml2vmx-annotation.vmx | 10 +++
tests/xml2vmxdata/xml2vmx-annotation.xml | 9 ++
tests/xml2vmxtest.c | 2 +
7 files changed, 144 insertions(+), 22 deletions(-)
create mode 100644 tests/vmx2xmldata/vmx2xml-annotation.vmx
create mode 100644 tests/vmx2xmldata/vmx2xml-annotation.xml
create mode 100644 tests/xml2vmxdata/xml2vmx-annotation.vmx
create mode 100644 tests/xml2vmxdata/xml2vmx-annotation.xml
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 12cd005..bb86b4d 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -843,6 +843,9 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
long long numvcpus = 0;
char *sched_cpu_affinity = NULL;
char *guestOS = NULL;
+ char *annotation = NULL;
+ char *tmp;
+ int length;
int controller;
int bus;
int port;
@@ -947,6 +950,33 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
goto cleanup;
}
+ /* vmx:annotation -> def:description */
+ if (esxUtil_GetConfigString(conf, "annotation", &def->description,
+ true) < 0) {
+ goto cleanup;
+ }
+
+ /* Replace '|22' with '"' and '|7C' with '|' */
+ if (def->description != NULL) {
+ length = strlen(def->description) + 1;
+ tmp = def->description;
+
+ while (*tmp != '\0') {
+ if (STRPREFIX(tmp, "|22")) {
+ *tmp = '"';
+ memmove(tmp + 1, tmp + 3, length - 3);
+ length -= 2;
+ } else if (STRPREFIX(tmp, "|7C") || STRPREFIX(tmp,
"|7c")) {
+ *tmp = '|';
+ memmove(tmp + 1, tmp + 3, length - 3);
+ length -= 2;
+ }
+
+ ++tmp;
+ --length;
+ }
+ }
+
/* vmx:memsize -> def:maxmem */
if (esxUtil_GetConfigLong(conf, "memsize", &memsize, 32, true) < 0)
{
goto cleanup;
@@ -1304,6 +1334,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char
*vmx,
virConfFree(conf);
VIR_FREE(sched_cpu_affinity);
VIR_FREE(guestOS);
+ VIR_FREE(annotation);
return def;
}
@@ -2314,10 +2345,15 @@ char *
esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
esxVI_ProductVersion productVersion)
{
+ char *vmx = NULL;
int i;
int sched_cpu_affinity_length;
unsigned char zero[VIR_UUID_BUFLEN];
virBuffer buffer = VIR_BUFFER_INITIALIZER;
+ int length;
+ char *tmp1;
+ char *tmp2;
+ char *annotation = NULL;
bool scsi_present[4] = { false, false, false, false };
int scsi_virtualDev[4] = { -1, -1, -1, -1 };
bool floppy_present[2] = { false, false };
@@ -2361,7 +2397,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
default:
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected product version"));
- goto failure;
+ goto cleanup;
}
/* def:arch -> vmx:guestOS */
@@ -2373,7 +2409,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML attribute 'arch' of entry
'os/type' "
"to be 'i686' or 'x86_64' but found
'%s'"), def->os.arch);
- goto failure;
+ goto cleanup;
}
/* def:uuid -> vmx:uuid.action, vmx:uuid.bios */
@@ -2392,13 +2428,53 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
/* def:name -> vmx:displayName */
virBufferVSprintf(&buffer, "displayName = \"%s\"\n",
def->name);
+ /* def:description -> vmx:annotation */
+ if (def->description != NULL) {
+ /* Replace '"' with '|22' and '|' with '|7C'
*/
+ length = 1; /* 1 byte for termination */
+ tmp1 = def->description;
+
+ while (*tmp1 != '\0') {
+ if (*tmp1 == '"' || *tmp1 == '|') {
+ length += 2;
+ }
+
+ ++tmp1;
+ ++length;
+ }
+
+ if (VIR_ALLOC_N(annotation, length) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ tmp1 = def->description;
+ tmp2 = annotation;
+
+ while (*tmp1 != '\0') {
+ if (*tmp1 == '"') {
+ *tmp2++ = '|'; *tmp2++ = '2'; *tmp2++ = '2';
+ } else if (*tmp1 == '|') {
+ *tmp2++ = '|'; *tmp2++ = '7'; *tmp2++ = 'C';
+ } else {
+ *tmp2++ = *tmp1;
+ }
+
+ ++tmp1;
+ }
+
+ *tmp2 = '\0';
+
+ virBufferVSprintf(&buffer, "annotation = \"%s\"\n",
annotation);
+ }
+
/* def:maxmem -> vmx:memsize */
if (def->maxmem <= 0 || def->maxmem % 4096 != 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'memory' to be an unsigned
"
"integer (multiple of 4096) but found %lld"),
(unsigned long long)def->maxmem);
- goto failure;
+ goto cleanup;
}
/* Scale from kilobytes to megabytes */
@@ -2412,7 +2488,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
_("Expecting domain XML entry 'currentMemory' to be an
"
"unsigned integer (multiple of 1024) but found %lld"),
(unsigned long long)def->memory);
- goto failure;
+ goto cleanup;
}
/* Scale from kilobytes to megabytes */
@@ -2426,7 +2502,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
_("Expecting domain XML entry 'vcpu' to be an unsigned
"
"integer (1 or a multiple of 2) but found %d"),
(int)def->vcpus);
- goto failure;
+ goto cleanup;
}
virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n",
(int)def->vcpus);
@@ -2448,7 +2524,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
_("Expecting domain XML attribute 'cpuset' of entry
"
"'vcpu' to contains at least %d CPU(s)"),
(int)def->vcpus);
- goto failure;
+ goto cleanup;
}
for (i = 0; i < def->cpumasklen; ++i) {
@@ -2471,7 +2547,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
switch (def->graphics[i]->type) {
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
if (esxVMX_FormatVNC(def->graphics[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2480,7 +2556,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported graphics type '%s'"),
virDomainGraphicsTypeToString(def->graphics[i]->type));
- goto failure;
+ goto cleanup;
}
}
@@ -2488,13 +2564,13 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
for (i = 0; i < def->ndisks; ++i) {
if (esxVMX_VerifyDiskAddress(caps, def->disks[i]) < 0 ||
esxVMX_HandleLegacySCSIDiskDriverName(def, def->disks[i]) < 0) {
- goto failure;
+ goto cleanup;
}
}
if (esxVMX_GatherSCSIControllers(ctx, def, scsi_virtualDev,
scsi_present) < 0) {
- goto failure;
+ goto cleanup;
}
for (i = 0; i < 4; ++i) {
@@ -2513,14 +2589,14 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
switch (def->disks[i]->device) {
case VIR_DOMAIN_DISK_DEVICE_DISK:
if (esxVMX_FormatHardDisk(ctx, def->disks[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
case VIR_DOMAIN_DISK_DEVICE_CDROM:
if (esxVMX_FormatCDROM(ctx, def->disks[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2528,7 +2604,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
if (esxVMX_FormatFloppy(ctx, def->disks[i], &buffer,
floppy_present) < 0) {
- goto failure;
+ goto cleanup;
}
break;
@@ -2537,7 +2613,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Unsupported disk device type '%s'"),
virDomainDiskDeviceTypeToString(def->disks[i]->device));
- goto failure;
+ goto cleanup;
}
}
@@ -2554,7 +2630,7 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
/* def:nets */
for (i = 0; i < def->nnets; ++i) {
if (esxVMX_FormatEthernet(def->nets[i], i, &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
@@ -2570,29 +2646,33 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps,
virDomainDefPtr def,
/* def:serials */
for (i = 0; i < def->nserials; ++i) {
if (esxVMX_FormatSerial(ctx, def->serials[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
/* def:parallels */
for (i = 0; i < def->nparallels; ++i) {
if (esxVMX_FormatParallel(ctx, def->parallels[i], &buffer) < 0) {
- goto failure;
+ goto cleanup;
}
}
/* Get final VMX output */
if (virBufferError(&buffer)) {
virReportOOMError();
- goto failure;
+ goto cleanup;
}
- return virBufferContentAndReset(&buffer);
+ vmx = virBufferContentAndReset(&buffer);
- failure:
- virBufferFreeAndReset(&buffer);
+ cleanup:
+ if (vmx == NULL) {
+ virBufferFreeAndReset(&buffer);
+ }
+
+ VIR_FREE(annotation);
- return NULL;
+ return vmx;
}
diff --git a/tests/vmx2xmldata/vmx2xml-annotation.vmx
b/tests/vmx2xmldata/vmx2xml-annotation.vmx
new file mode 100644
index 0000000..1ac420c
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-annotation.vmx
@@ -0,0 +1,3 @@
+config.version = "8"
+virtualHW.version = "4"
+annotation = "Some |7Ctext|7C to test the |22escaping|22:
|7C|7C|22|22|7C|7C|22|7C"
diff --git a/tests/vmx2xmldata/vmx2xml-annotation.xml
b/tests/vmx2xmldata/vmx2xml-annotation.xml
new file mode 100644
index 0000000..37c6ca9
--- /dev/null
+++ b/tests/vmx2xmldata/vmx2xml-annotation.xml
@@ -0,0 +1,16 @@
+<domain type='vmware'>
+ <uuid>00000000-0000-0000-0000-000000000000</uuid>
+ <description>Some |text| to test the "escaping":
||""||"|</description>
+ <memory>32768</memory>
+ <currentMemory>32768</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686'>hvm</type>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ </devices>
+</domain>
diff --git a/tests/vmx2xmltest.c b/tests/vmx2xmltest.c
index 50e7d0c..67296d6 100644
--- a/tests/vmx2xmltest.c
+++ b/tests/vmx2xmltest.c
@@ -280,6 +280,8 @@ mymain(int argc, char **argv)
DO_TEST("gsx-in-the-wild-3", "gsx-in-the-wild-3",
esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-4", "gsx-in-the-wild-4",
esxVI_ProductVersion_ESX35);
+ DO_TEST("annotation", "annotation", esxVI_ProductVersion_ESX35);
+
virCapabilitiesFree(caps);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/tests/xml2vmxdata/xml2vmx-annotation.vmx
b/tests/xml2vmxdata/xml2vmx-annotation.vmx
new file mode 100644
index 0000000..d5bd4b4
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-annotation.vmx
@@ -0,0 +1,10 @@
+config.version = "8"
+virtualHW.version = "4"
+guestOS = "other"
+uuid.bios = "56 4d 9b ef ac d9 b4 e0-c8 f0 ae a8 b9 10 35 15"
+displayName = "annotation"
+annotation = "Some |7Ctext|7C to test the |22escaping|22:
|7C|7C|22|22|7C|7C|22|7C"
+memsize = "4"
+numvcpus = "1"
+floppy0.present = "false"
+floppy1.present = "false"
diff --git a/tests/xml2vmxdata/xml2vmx-annotation.xml
b/tests/xml2vmxdata/xml2vmx-annotation.xml
new file mode 100644
index 0000000..d33827d
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-annotation.xml
@@ -0,0 +1,9 @@
+<domain type='vmware'>
+ <name>annotation</name>
+ <uuid>564d9bef-acd9-b4e0-c8f0-aea8b9103515</uuid>
+ <description>Some |text| to test the "escaping":
||""||"|</description>
+ <memory>4096</memory>
+ <os>
+ <type>hvm</type>
+ </os>
+</domain>
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 71ce14a..2a457b4 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -273,6 +273,8 @@ mymain(int argc, char **argv)
DO_TEST("gsx-in-the-wild-3", "gsx-in-the-wild-3",
esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-4", "gsx-in-the-wild-4",
esxVI_ProductVersion_ESX35);
+ DO_TEST("annotation", "annotation", esxVI_ProductVersion_ESX35);
+
virCapabilitiesFree(caps);
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
--
1.7.0.4