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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list