From 898951046de070a95aa510fe09a309f7626c5343 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Feb 05 2015 11:54:37 +0000 Subject: import libvirt-1.1.1-29.el7_0.7 --- diff --git a/SOURCES/libvirt-Add-invariant-TSC-cpu-flag.patch b/SOURCES/libvirt-Add-invariant-TSC-cpu-flag.patch new file mode 100644 index 0000000..dfc59fd --- /dev/null +++ b/SOURCES/libvirt-Add-invariant-TSC-cpu-flag.patch @@ -0,0 +1,108 @@ +From 65d750dec286074fc48fdaa64eb3f5029626506f Mon Sep 17 00:00:00 2001 +Message-Id: <65d750dec286074fc48fdaa64eb3f5029626506f@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Tue, 6 May 2014 13:55:44 +0200 +Subject: [PATCH] Add invariant TSC cpu flag + +Add suport for invariant TSC flag (CPUID 0x80000007, bit 8 of EDX). +If this flag is enabled, the TSC ticks at a constant rate across +all ACPI P-, C- and T-states. + +This can be enabled by adding: + +to the element. + +Migration and saving the domain does not work with this flag. + +QEMU support: http://git.qemu.org/?p=qemu.git;a=commitdiff;h=303752a + +The feature name "invtsc" differs from the name "" used by the linux kernel: +https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/powerflags.c?id=30321c7b#n18 + +(cherry picked from commit fba6bc47cbcabbe08d42279691efb0dff3b9c997) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark +--- + src/cpu/cpu_map.xml | 5 +++++ + src/qemu/qemu_migration.c | 15 +++++++++++++++ + src/qemu/qemu_process.c | 15 +++++++++++++++ + 3 files changed, 35 insertions(+) + +diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml +index 6d51283..aa10019 100644 +--- a/src/cpu/cpu_map.xml ++++ b/src/cpu/cpu_map.xml +@@ -327,6 +327,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index deacb66..d979d50 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -1506,6 +1506,21 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, + return false; + } + ++ for (i = 0; i < def->cpu->nfeatures; i++) { ++ virCPUFeatureDefPtr feature = &def->cpu->features[i]; ++ ++ if (feature->policy != VIR_CPU_FEATURE_REQUIRE) ++ continue; ++ ++ /* QEMU blocks migration and save with invariant TSC enabled */ ++ if (STREQ(feature->name, "invtsc")) { ++ virReportError(VIR_ERR_OPERATION_INVALID, ++ _("domain has CPU feature: %s"), ++ feature->name); ++ return false; ++ } ++ } ++ + return true; + } + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 3eda15b..8c07397 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -3520,6 +3520,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm) + virCPUDataPtr guestcpu = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + bool ret = false; ++ size_t i; + + switch (arch) { + case VIR_ARCH_I686: +@@ -3538,6 +3539,20 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm) + goto cleanup; + } + } ++ ++ for (i = 0; i < def->cpu->nfeatures; i++) { ++ virCPUFeatureDefPtr feature = &def->cpu->features[i]; ++ ++ if (feature->policy != VIR_CPU_FEATURE_REQUIRE) ++ continue; ++ ++ if (STREQ(feature->name, "invtsc") && ++ !cpuHasFeature(guestcpu, feature->name)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("host doesn't support invariant TSC")); ++ goto cleanup; ++ } ++ } + break; + + default: +-- +2.2.2 + diff --git a/SOURCES/libvirt-Also-filter-out-non-migratable-features-out-of-host-passthrough.patch b/SOURCES/libvirt-Also-filter-out-non-migratable-features-out-of-host-passthrough.patch new file mode 100644 index 0000000..a46e51c --- /dev/null +++ b/SOURCES/libvirt-Also-filter-out-non-migratable-features-out-of-host-passthrough.patch @@ -0,0 +1,78 @@ +From b2c63abced4d6e2f263125ab903917549fcd3abd Mon Sep 17 00:00:00 2001 +Message-Id: +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Mon, 29 Sep 2014 12:44:43 +0200 +Subject: [PATCH] Also filter out non-migratable features out of + host-passthrough + +Commit de0aeaf filtered them out from the host-model features, +to allow host-model to be migratable by default. + +Even though they are not passed to QEMU for host-passthrough, +(and not enabled by default) filter them out too +so the user does not think the domain has them. + +https://bugzilla.redhat.com/show_bug.cgi?id=1147584 +(cherry picked from commit f53bb1af90737205fdbfd26dc99865c02457d8c9) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark + +Conflicts: + src/cpu/cpu_x86.c -- context; const virCPUDefPtr vs. const + virCPUDef * (changed by d694ae0c) +--- + src/cpu/cpu_x86.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index 341a7f5..dffa488 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -1984,7 +1984,8 @@ cleanup: + + static int + x86UpdateHostModel(virCPUDefPtr guest, +- const virCPUDefPtr host) ++ const virCPUDefPtr host, ++ bool passthrough) + { + virCPUDefPtr oldguest = NULL; + const struct x86_map *map; +@@ -1992,8 +1993,6 @@ x86UpdateHostModel(virCPUDefPtr guest, + size_t i; + int ret = -1; + +- guest->match = VIR_CPU_MATCH_EXACT; +- + if (!(map = virCPUx86GetMap())) + goto cleanup; + +@@ -2016,8 +2015,7 @@ x86UpdateHostModel(virCPUDefPtr guest, + } + } + } +- +- for (i = 0; i < oldguest->nfeatures; i++) { ++ for (i = 0; !passthrough && i < oldguest->nfeatures; i++) { + if (virCPUDefUpdateFeature(guest, + oldguest->features[i].name, + oldguest->features[i].policy) < 0) +@@ -2041,12 +2039,12 @@ x86Update(virCPUDefPtr guest, + return x86UpdateCustom(guest, host); + + case VIR_CPU_MODE_HOST_MODEL: +- return x86UpdateHostModel(guest, host); ++ guest->match = VIR_CPU_MATCH_EXACT; ++ return x86UpdateHostModel(guest, host, false); + + case VIR_CPU_MODE_HOST_PASSTHROUGH: + guest->match = VIR_CPU_MATCH_MINIMUM; +- virCPUDefFreeModel(guest); +- return virCPUDefCopyModel(guest, host, true); ++ return x86UpdateHostModel(guest, host, true); + + case VIR_CPU_MODE_LAST: + break; +-- +2.2.2 + diff --git a/SOURCES/libvirt-Don-t-include-non-migratable-features-in-host-model.patch b/SOURCES/libvirt-Don-t-include-non-migratable-features-in-host-model.patch new file mode 100644 index 0000000..9248460 --- /dev/null +++ b/SOURCES/libvirt-Don-t-include-non-migratable-features-in-host-model.patch @@ -0,0 +1,261 @@ +From 10be3da4947fc7923732e2056516a41514bd1695 Mon Sep 17 00:00:00 2001 +Message-Id: <10be3da4947fc7923732e2056516a41514bd1695@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 5 Sep 2014 09:50:36 +0200 +Subject: [PATCH] Don't include non-migratable features in host-model + +Commit fba6bc4 introduced support for the 'invtsc' feature, +which blocks migration. We should not include it in the +host-model CPU by default, because it's intended to be used +with migration. + +https://bugzilla.redhat.com/show_bug.cgi?id=1138221 +(cherry picked from commit de0aeafe9ce3eb414c8b5d3aa8995d776a2952de) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark + +Conflicts: + src/cpu/cpu_x86.c - context -- missing {} (fixed by ff78ff7c) +--- + src/cpu/cpu_map.xml | 2 +- + src/cpu/cpu_x86.c | 65 ++++++++++++++++++++++-- + tests/cputest.c | 1 + + tests/cputestdata/x86-host-invtsc+host-model.xml | 22 ++++++++ + tests/cputestdata/x86-host-invtsc.xml | 27 ++++++++++ + 5 files changed, 111 insertions(+), 6 deletions(-) + create mode 100644 tests/cputestdata/x86-host-invtsc+host-model.xml + create mode 100644 tests/cputestdata/x86-host-invtsc.xml + +diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml +index aa10019..28bc5ec 100644 +--- a/src/cpu/cpu_map.xml ++++ b/src/cpu/cpu_map.xml +@@ -328,7 +328,7 @@ + + + +- ++ + + + +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index 4e77550..8ced69d 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -87,6 +87,7 @@ struct x86_map { + struct x86_vendor *vendors; + struct x86_feature *features; + struct x86_model *models; ++ struct x86_feature *migrate_blockers; + }; + + static struct x86_map* virCPUx86Map = NULL; +@@ -590,6 +591,28 @@ x86FeatureFree(struct x86_feature *feature) + + + static struct x86_feature * ++x86FeatureCopy(const struct x86_feature *src) ++{ ++ struct x86_feature *feature; ++ ++ if (VIR_ALLOC(feature) < 0) ++ return NULL; ++ ++ if (VIR_STRDUP(feature->name, src->name) < 0) ++ goto error; ++ ++ if ((feature->data = x86DataCopy(src->data)) == NULL) ++ goto error; ++ ++ return feature; ++ ++ error: ++ x86FeatureFree(feature); ++ return NULL; ++} ++ ++ ++static struct x86_feature * + x86FeatureFind(const struct x86_map *map, + const char *name) + { +@@ -675,6 +698,9 @@ x86FeatureLoad(xmlXPathContextPtr ctxt, + int ret = 0; + size_t i; + int n; ++ char *str = NULL; ++ bool migratable = true; ++ struct x86_feature *migrate_blocker = NULL; + + if (!(feature = x86FeatureNew())) + goto error; +@@ -692,6 +718,10 @@ x86FeatureLoad(xmlXPathContextPtr ctxt, + goto ignore; + } + ++ str = virXPathString("string(@migratable)", ctxt); ++ if (STREQ_NULLABLE(str, "no")) ++ migratable = false; ++ + n = virXPathNodeSet("./cpuid", ctxt, &nodes); + if (n < 0) + goto ignore; +@@ -708,6 +738,14 @@ x86FeatureLoad(xmlXPathContextPtr ctxt, + goto error; + } + ++ if (!migratable) { ++ if ((migrate_blocker = x86FeatureCopy(feature)) == NULL) ++ goto error; ++ ++ migrate_blocker->next = map->migrate_blockers; ++ map->migrate_blockers = migrate_blocker; ++ } ++ + if (map->features == NULL) + map->features = feature; + else { +@@ -718,6 +756,7 @@ x86FeatureLoad(xmlXPathContextPtr ctxt, + out: + ctxt->node = ctxt_node; + VIR_FREE(nodes); ++ VIR_FREE(str); + + return ret; + +@@ -726,6 +765,7 @@ error: + + ignore: + x86FeatureFree(feature); ++ x86FeatureFree(migrate_blocker); + goto out; + } + +@@ -1061,6 +1101,12 @@ x86MapFree(struct x86_map *map) + x86VendorFree(vendor); + } + ++ while (map->migrate_blockers != NULL) { ++ struct x86_feature *migrate_blocker = map->migrate_blockers; ++ map->migrate_blockers = migrate_blocker->next; ++ x86FeatureFree(migrate_blocker); ++ } ++ + VIR_FREE(map); + } + +@@ -1941,16 +1987,15 @@ x86UpdateHostModel(virCPUDefPtr guest, + const virCPUDefPtr host) + { + virCPUDefPtr oldguest = NULL; ++ const struct x86_map *map; ++ const struct x86_feature *feat; + size_t i; + int ret = -1; + + guest->match = VIR_CPU_MATCH_EXACT; + +- /* no updates are required */ +- if (guest->nfeatures == 0) { +- virCPUDefFreeModel(guest); +- return virCPUDefCopyModel(guest, host, true); +- } ++ if (!(map = virCPUx86GetMap())) ++ goto cleanup; + + /* update the host model according to the desired configuration */ + if (!(oldguest = virCPUDefCopy(guest))) +@@ -1960,6 +2005,16 @@ x86UpdateHostModel(virCPUDefPtr guest, + if (virCPUDefCopyModel(guest, host, true) < 0) + goto cleanup; + ++ /* Remove non-migratable features by default ++ * Note: this only works as long as no CPU model contains non-migratable ++ * features directly */ ++ for (i = 0; i < guest->nfeatures; i++) { ++ for (feat = map->migrate_blockers; feat; feat = feat->next) { ++ if (STREQ(feat->name, guest->features[i].name)) ++ VIR_DELETE_ELEMENT_INPLACE(guest->features, i, guest->nfeatures); ++ } ++ } ++ + for (i = 0; i < oldguest->nfeatures; i++) { + if (virCPUDefUpdateFeature(guest, + oldguest->features[i].name, +diff --git a/tests/cputest.c b/tests/cputest.c +index 6a1cfeb..153556a 100644 +--- a/tests/cputest.c ++++ b/tests/cputest.c +@@ -591,6 +591,7 @@ mymain(void) + DO_TEST_UPDATE("x86", "host", "host-model", VIR_CPU_COMPARE_IDENTICAL); + DO_TEST_UPDATE("x86", "host", "host-model-nofallback", VIR_CPU_COMPARE_IDENTICAL); + DO_TEST_UPDATE("x86", "host", "host-passthrough", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_UPDATE("x86", "host-invtsc", "host-model", VIR_CPU_COMPARE_SUPERSET); + + /* computing baseline CPUs */ + DO_TEST_BASELINE("x86", "incompatible-vendors", -1); +diff --git a/tests/cputestdata/x86-host-invtsc+host-model.xml b/tests/cputestdata/x86-host-invtsc+host-model.xml +new file mode 100644 +index 0000000..ad1bbf8 +--- /dev/null ++++ b/tests/cputestdata/x86-host-invtsc+host-model.xml +@@ -0,0 +1,22 @@ ++ ++ SandyBridge ++ Intel ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/x86-host-invtsc.xml b/tests/cputestdata/x86-host-invtsc.xml +new file mode 100644 +index 0000000..f558399 +--- /dev/null ++++ b/tests/cputestdata/x86-host-invtsc.xml +@@ -0,0 +1,27 @@ ++ ++ x86_64 ++ SandyBridge ++ Intel ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +-- +2.2.2 + diff --git a/SOURCES/libvirt-Fix-leak-in-x86UpdateHostModel.patch b/SOURCES/libvirt-Fix-leak-in-x86UpdateHostModel.patch new file mode 100644 index 0000000..d24d94e --- /dev/null +++ b/SOURCES/libvirt-Fix-leak-in-x86UpdateHostModel.patch @@ -0,0 +1,34 @@ +From 310634521378f3ae84f0f73293a591681f24648f Mon Sep 17 00:00:00 2001 +Message-Id: <310634521378f3ae84f0f73293a591681f24648f@dist-git> +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Thu, 18 Sep 2014 11:55:52 +0200 +Subject: [PATCH] Fix leak in x86UpdateHostModel + +Commit de0aeaf introduced a memory leak. + +(cherry picked from commit 5b5631dedf59e540661bfeac774e543d8d38531b) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark +--- + src/cpu/cpu_x86.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index 8ced69d..341a7f5 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -2010,8 +2010,10 @@ x86UpdateHostModel(virCPUDefPtr guest, + * features directly */ + for (i = 0; i < guest->nfeatures; i++) { + for (feat = map->migrate_blockers; feat; feat = feat->next) { +- if (STREQ(feat->name, guest->features[i].name)) ++ if (STREQ(feat->name, guest->features[i].name)) { ++ VIR_FREE(guest->features[i].name); + VIR_DELETE_ELEMENT_INPLACE(guest->features, i, guest->nfeatures); ++ } + } + } + +-- +2.2.2 + diff --git a/SOURCES/libvirt-Fix-libvirtd-crash-when-removing-metadata.patch b/SOURCES/libvirt-Fix-libvirtd-crash-when-removing-metadata.patch new file mode 100644 index 0000000..339b932 --- /dev/null +++ b/SOURCES/libvirt-Fix-libvirtd-crash-when-removing-metadata.patch @@ -0,0 +1,37 @@ +From 04e1195be4e5e52da19050e2fadae95e9525ef3b Mon Sep 17 00:00:00 2001 +Message-Id: <04e1195be4e5e52da19050e2fadae95e9525ef3b@dist-git> +From: Erik Skultety +Date: Thu, 22 Jan 2015 16:25:16 +0100 +Subject: [PATCH] Fix libvirtd crash when removing metadata + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +When trying to remove nonexistent metadata from XML, libvirt daemon +crashes due to dereferencing NULL pointer. + +Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1143955 + +(cherry picked from commit 288c47406cffa7a6eb9e9c29764850b0cdeb5508) + +Signed-off-by: Jiri Denemark +--- + src/util/virxml.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/util/virxml.c b/src/util/virxml.c +index 88c1fcc..6cee8e1 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -979,6 +979,9 @@ virXMLFindChildNodeByNs(xmlNodePtr root, + { + xmlNodePtr next; + ++ if (!root) ++ return NULL; ++ + for (next = root->children; next; next = next->next) { + if (next->ns && + STREQ_NULLABLE((const char *) next->ns->href, uri)) +-- +2.2.1 + diff --git a/SOURCES/libvirt-Fix-possible-memory-leak-in-util-virxml.c.patch b/SOURCES/libvirt-Fix-possible-memory-leak-in-util-virxml.c.patch new file mode 100644 index 0000000..557effe --- /dev/null +++ b/SOURCES/libvirt-Fix-possible-memory-leak-in-util-virxml.c.patch @@ -0,0 +1,37 @@ +From a26ded37a2e5d1deaa34fcc83d8cc6c4067ad040 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Pavel Hrdina +Date: Thu, 22 Jan 2015 15:53:56 +0100 +Subject: [PATCH] Fix possible memory leak in util/virxml.c + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +A "xmlstr" string may not be assigned into a "doc" pointer and it +could cause memory leak. To fix it if the "doc" pointer is NULL and +the "xmlstr" string is not assigned we should free it. + +This has been found by coverity. + +Signed-off-by: Pavel Hrdina +(cherry picked from commit 67fbf129fc8727c98f7c4123c12a48938ccdf3fa) +Signed-off-by: Jiri Denemark +--- + src/util/virxml.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/util/virxml.c b/src/util/virxml.c +index de1e1e0..88a1196 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -1047,6 +1047,8 @@ virXMLExtractNamespaceXML(xmlNodePtr root, + cleanup: + if (doc) + *doc = xmlstr; ++ else ++ VIR_FREE(xmlstr); + xmlFreeNode(nodeCopy); + return ret; + } +-- +2.2.1 + diff --git a/SOURCES/libvirt-Fix-segfault-when-starting-a-domain-with-no-cpu-definition.patch b/SOURCES/libvirt-Fix-segfault-when-starting-a-domain-with-no-cpu-definition.patch new file mode 100644 index 0000000..9ad371f --- /dev/null +++ b/SOURCES/libvirt-Fix-segfault-when-starting-a-domain-with-no-cpu-definition.patch @@ -0,0 +1,46 @@ +From d0a2e30fb26302eaaa5efa0f2d1d1fbe7853934a Mon Sep 17 00:00:00 2001 +Message-Id: +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Wed, 2 Jul 2014 10:35:31 +0200 +Subject: [PATCH] Fix segfault when starting a domain with no cpu definition + +My commit fba6bc4 iterated over the features in cpu definition +without checking if there is one. + +(cherry picked from commit 1cd8f500ee133653ecb9d1b7f72b2b2e9870a1c3) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark +--- + src/qemu/qemu_migration.c | 2 +- + src/qemu/qemu_process.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c +index d979d50..2e495a8 100644 +--- a/src/qemu/qemu_migration.c ++++ b/src/qemu/qemu_migration.c +@@ -1506,7 +1506,7 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, + return false; + } + +- for (i = 0; i < def->cpu->nfeatures; i++) { ++ for (i = 0; def->cpu && i < def->cpu->nfeatures; i++) { + virCPUFeatureDefPtr feature = &def->cpu->features[i]; + + if (feature->policy != VIR_CPU_FEATURE_REQUIRE) +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 8c07397..11d5af5 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -3540,7 +3540,7 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm) + } + } + +- for (i = 0; i < def->cpu->nfeatures; i++) { ++ for (i = 0; def->cpu && i < def->cpu->nfeatures; i++) { + virCPUFeatureDefPtr feature = &def->cpu->features[i]; + + if (feature->policy != VIR_CPU_FEATURE_REQUIRE) +-- +2.2.2 + diff --git a/SOURCES/libvirt-conf-Add-support-for-requesting-of-XML-metadata-via-the-API.patch b/SOURCES/libvirt-conf-Add-support-for-requesting-of-XML-metadata-via-the-API.patch new file mode 100644 index 0000000..4c63a12 --- /dev/null +++ b/SOURCES/libvirt-conf-Add-support-for-requesting-of-XML-metadata-via-the-API.patch @@ -0,0 +1,236 @@ +From 25d339a412b1a3d3436d3ff3c9ed63139c8f2428 Mon Sep 17 00:00:00 2001 +Message-Id: <25d339a412b1a3d3436d3ff3c9ed63139c8f2428@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:45 +0100 +Subject: [PATCH] conf: Add support for requesting of XML metadata via the API + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The virDomainGetMetadata function was designed to support also retrieval +of app specific metadata from the element. This functionality +was never implemented originally. + +(cherry picked from commit ac38bff077642daa17f9a82480062ebef4c11a7b) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 19 ++++---- + src/libvirt_private.syms | 1 + + src/util/virxml.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++ + src/util/virxml.h | 7 +++ + 4 files changed, 140 insertions(+), 9 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 6817e0e..c104218 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18987,7 +18987,6 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + unsigned int flags) + { + virDomainDefPtr def; +- char *field = NULL; + char *ret = NULL; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | +@@ -19002,17 +19001,21 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + + switch ((virDomainMetadataType) type) { + case VIR_DOMAIN_METADATA_DESCRIPTION: +- field = def->description; ++ if (VIR_STRDUP(ret, def->description) < 0) ++ goto cleanup; + break; + + case VIR_DOMAIN_METADATA_TITLE: +- field = def->title; ++ if (VIR_STRDUP(ret, def->title) < 0) ++ goto cleanup; + break; + + case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _(" element is not yet supported")); +- goto cleanup; ++ if (!def->metadata) ++ break; ++ ++ if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0) ++ goto cleanup; + break; + + default: +@@ -19022,12 +19025,10 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + break; + } + +- if (!field) ++ if (!ret) + virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s", + _("Requested metadata element is not present")); + +- ignore_value(VIR_STRDUP(ret, field)); +- + cleanup: + return ret; + } +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 3df4379..1fbee18 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -2140,6 +2140,7 @@ virUUIDParse; + + # util/virxml.h + virXMLChildElementCount; ++virXMLExtractNamespaceXML; + virXMLNodeToString; + virXMLParseHelper; + virXMLPickShellSafeComment; +diff --git a/src/util/virxml.c b/src/util/virxml.c +index 9bb8bf0..9048d78 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -928,3 +928,125 @@ cleanup: + + return ret; + } ++ ++typedef int (*virXMLForeachCallback)(xmlNodePtr node, ++ void *opaque); ++ ++static int ++virXMLForeachNode(xmlNodePtr root, ++ virXMLForeachCallback cb, ++ void *opaque); ++ ++static int ++virXMLForeachNode(xmlNodePtr root, ++ virXMLForeachCallback cb, ++ void *opaque) ++{ ++ xmlNodePtr next; ++ int ret; ++ ++ for (next = root; next; next = next->next) { ++ if ((ret = cb(next, opaque)) != 0) ++ return ret; ++ ++ /* recurse into children */ ++ if (next->children) { ++ if ((ret = virXMLForeachNode(next->children, cb, opaque)) != 0) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++static int ++virXMLRemoveElementNamespace(xmlNodePtr node, ++ void *opaque) ++{ ++ const char *uri = opaque; ++ ++ if (node->ns && ++ STREQ_NULLABLE((const char *)node->ns->href, uri)) ++ xmlSetNs(node, NULL); ++ return 0; ++} ++ ++ ++xmlNodePtr ++virXMLFindChildNodeByNs(xmlNodePtr root, ++ const char *uri) ++{ ++ xmlNodePtr next; ++ ++ for (next = root->children; next; next = next->next) { ++ if (next->ns && ++ STREQ_NULLABLE((const char *) next->ns->href, uri)) ++ return next; ++ } ++ ++ return NULL; ++} ++ ++ ++/** ++ * virXMLExtractNamespaceXML: extract a sub-namespace of XML as string ++ */ ++int ++virXMLExtractNamespaceXML(xmlNodePtr root, ++ const char *uri, ++ char **doc) ++{ ++ xmlNodePtr node; ++ xmlNodePtr nodeCopy = NULL; ++ xmlNsPtr actualNs; ++ xmlNsPtr prevNs = NULL; ++ char *xmlstr = NULL; ++ int ret = -1; ++ ++ if (!(node = virXMLFindChildNodeByNs(root, uri))) { ++ /* node not found */ ++ ret = 1; ++ goto cleanup; ++ } ++ ++ /* copy the node so that we can modify the namespace */ ++ if (!(nodeCopy = xmlCopyNode(node, 1))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("Failed to copy XML node")); ++ goto cleanup; ++ } ++ ++ virXMLForeachNode(nodeCopy, virXMLRemoveElementNamespace, ++ (void *)uri); ++ ++ /* remove the namespace declaration ++ * - it's only a single linked list ... doh */ ++ for (actualNs = nodeCopy->nsDef; actualNs; actualNs = actualNs->next) { ++ if (STREQ_NULLABLE((const char *)actualNs->href, uri)) { ++ ++ /* unlink */ ++ if (prevNs) ++ prevNs->next = actualNs->next; ++ else ++ nodeCopy->nsDef = actualNs->next; ++ ++ /* discard */ ++ xmlFreeNs(actualNs); ++ break; ++ } ++ ++ prevNs = actualNs; ++ } ++ ++ if (!(xmlstr = virXMLNodeToString(nodeCopy->doc, nodeCopy))) ++ goto cleanup; ++ ++ ret = 0; ++ ++cleanup: ++ if (doc) ++ *doc = xmlstr; ++ xmlFreeNode(nodeCopy); ++ return ret; ++} +diff --git a/src/util/virxml.h b/src/util/virxml.h +index bb34069..7dc6c9d 100644 +--- a/src/util/virxml.h ++++ b/src/util/virxml.h +@@ -165,4 +165,11 @@ int virXMLSaveFile(const char *path, + + char *virXMLNodeToString(xmlDocPtr doc, xmlNodePtr node); + ++xmlNodePtr virXMLFindChildNodeByNs(xmlNodePtr root, ++ const char *uri); ++ ++int virXMLExtractNamespaceXML(xmlNodePtr root, ++ const char *uri, ++ char **doc); ++ + #endif /* __VIR_XML_H__ */ +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-Avoid-false-positive-of-uninitialized-variable-use.patch b/SOURCES/libvirt-conf-Avoid-false-positive-of-uninitialized-variable-use.patch new file mode 100644 index 0000000..5fe8bd7 --- /dev/null +++ b/SOURCES/libvirt-conf-Avoid-false-positive-of-uninitialized-variable-use.patch @@ -0,0 +1,57 @@ +From bb5ed814786f3148d1e54e26e9be10ea332c3058 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:52 +0100 +Subject: [PATCH] conf: Avoid false positive of uninitialized variable use + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +GCC 4.8.0+ whines about variable "new" being uninitialized since +commit 73bfac0e7182a3abd. This is a false positive as the +xmlFreeNode(new) statement can be only reached if new was actually +allocated successfully. + + CC conf/libvirt_conf_la-domain_conf.lo + conf/domain_conf.c: In function 'virDomainDefSetMetadata': + conf/domain_conf.c:18650:24: error: 'new' may be used uninitialized in this function [-Werror=maybe-uninitialized] + xmlFreeNode(new); + +Reported independently by John Ferlan and Michal Privoznik. + +(cherry picked from commit 0d4f469c871fb5997bb24f192924163263445980) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index c4829ff..a2c0d6c 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19043,7 +19043,7 @@ virDomainDefSetMetadata(virDomainDefPtr def, + { + xmlDocPtr doc = NULL; + xmlNodePtr old; +- xmlNodePtr new; ++ xmlNodePtr new = NULL; + char *tmp; + int ret = -1; + +@@ -19092,11 +19092,8 @@ virDomainDefSetMetadata(virDomainDefPtr def, + xmlFreeNode(old); + } + +- /* just delete the metadata */ +- if (!metadata) +- break; +- +- if (!(xmlAddChild(def->metadata, new))) { ++ if (new && ++ !(xmlAddChild(def->metadata, new))) { + xmlFreeNode(new); + virReportOOMError(); + goto cleanup; +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-Don-t-corrupt-metadata-on-OOM.patch b/SOURCES/libvirt-conf-Don-t-corrupt-metadata-on-OOM.patch new file mode 100644 index 0000000..db72519 --- /dev/null +++ b/SOURCES/libvirt-conf-Don-t-corrupt-metadata-on-OOM.patch @@ -0,0 +1,55 @@ +From 550637214e4df0cd44d64e83a0e57fc37f470bdb Mon Sep 17 00:00:00 2001 +Message-Id: <550637214e4df0cd44d64e83a0e57fc37f470bdb@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:51 +0100 +Subject: [PATCH] conf: Don't corrupt metadata on OOM + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +Eric Blake suggested that we could do a little better in case copying of +the metadata to be set fails. With this patch, the old metadata is +discarded after the new string is copied successfuly. + +(cherry picked from commit 7655ed0802eecc3d8486a0360d2326ecd052e477) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 4dbe3fc..c4829ff 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19044,19 +19044,24 @@ virDomainDefSetMetadata(virDomainDefPtr def, + xmlDocPtr doc = NULL; + xmlNodePtr old; + xmlNodePtr new; ++ char *tmp; + int ret = -1; + + switch ((virDomainMetadataType) type) { + case VIR_DOMAIN_METADATA_DESCRIPTION: ++ if (VIR_STRDUP(tmp, metadata) < 0) ++ goto cleanup; ++ + VIR_FREE(def->description); +- if (VIR_STRDUP(def->description, metadata) < 0) +- goto cleanup; ++ def->description = tmp; + break; + + case VIR_DOMAIN_METADATA_TITLE: ++ if (VIR_STRDUP(tmp, metadata) < 0) ++ goto cleanup; ++ + VIR_FREE(def->title); +- if (VIR_STRDUP(def->title, metadata) < 0) +- goto cleanup; ++ def->title = tmp; + break; + + case VIR_DOMAIN_METADATA_ELEMENT: +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-Factor-out-setting-of-metadata-to-simplify-code.patch b/SOURCES/libvirt-conf-Factor-out-setting-of-metadata-to-simplify-code.patch new file mode 100644 index 0000000..36269dc --- /dev/null +++ b/SOURCES/libvirt-conf-Factor-out-setting-of-metadata-to-simplify-code.patch @@ -0,0 +1,167 @@ +From a1871d142620750d21fed3c06053fad60ca3f7c5 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:41 +0100 +Subject: [PATCH] conf: Factor out setting of metadata to simplify code + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The code to set the metadata in a domain definition is common to live +and inactive domains. Factor it out into a common func. + +(cherry picked from commit e9cb66f14e19935db16938ebdf1e407103b4de1e) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 115 +++++++++++++++++++++++-------------------------- + 1 file changed, 54 insertions(+), 61 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 7bfb602..6817e0e 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19032,87 +19032,80 @@ cleanup: + return ret; + } + +-int +-virDomainObjSetMetadata(virDomainObjPtr vm, ++ ++static int ++virDomainDefSetMetadata(virDomainDefPtr def, + int type, + const char *metadata, + const char *key ATTRIBUTE_UNUSED, +- const char *uri ATTRIBUTE_UNUSED, ++ const char *uri ATTRIBUTE_UNUSED) ++{ ++ int ret = -1; ++ ++ switch ((virDomainMetadataType) type) { ++ case VIR_DOMAIN_METADATA_DESCRIPTION: ++ VIR_FREE(def->description); ++ if (VIR_STRDUP(def->description, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_TITLE: ++ VIR_FREE(def->title); ++ if (VIR_STRDUP(def->title, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_ELEMENT: ++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", ++ _(" element is not supported")); ++ goto cleanup; ++ break; ++ ++ default: ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("unknown metadata type")); ++ goto cleanup; ++ break; ++ } ++ ++ ret = 0; ++ ++cleanup: ++ return ret; ++} ++ ++ ++int ++virDomainObjSetMetadata(virDomainObjPtr vm, ++ int type, ++ const char *metadata, ++ const char *key, ++ const char *uri, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, + const char *configDir, + unsigned int flags) + { + virDomainDefPtr persistentDef; +- int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (virDomainLiveConfigHelperMethod(caps, xmlopt, vm, &flags, + &persistentDef) < 0) +- goto cleanup; ++ return -1; + +- if (flags & VIR_DOMAIN_AFFECT_LIVE) { +- switch ((virDomainMetadataType) type) { +- case VIR_DOMAIN_METADATA_DESCRIPTION: +- VIR_FREE(vm->def->description); +- if (VIR_STRDUP(vm->def->description, metadata) < 0) +- goto cleanup; +- break; +- +- case VIR_DOMAIN_METADATA_TITLE: +- VIR_FREE(vm->def->title); +- if (VIR_STRDUP(vm->def->title, metadata) < 0) +- goto cleanup; +- break; +- +- case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _(" element is not supported")); +- goto cleanup; +- break; +- +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; +- break; +- } +- } ++ if (flags & VIR_DOMAIN_AFFECT_LIVE) ++ if (virDomainDefSetMetadata(vm->def, type, metadata, key, uri) < 0) ++ return -1; + + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { +- switch ((virDomainMetadataType) type) { +- case VIR_DOMAIN_METADATA_DESCRIPTION: +- VIR_FREE(persistentDef->description); +- if (VIR_STRDUP(persistentDef->description, metadata) < 0) +- goto cleanup; +- break; +- +- case VIR_DOMAIN_METADATA_TITLE: +- VIR_FREE(persistentDef->title); +- if (VIR_STRDUP(persistentDef->title, metadata) < 0) +- goto cleanup; +- break; +- +- case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _(" element is not supported")); +- goto cleanup; +- +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; +- break; +- } ++ if (virDomainDefSetMetadata(persistentDef, type, metadata, key, uri) < 0) ++ return -1; + + if (virDomainSaveConfig(configDir, persistentDef) < 0) +- goto cleanup; ++ return -1; + } + +- ret = 0; +- +-cleanup: +- return ret; ++ return 0; + } +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-Format-interface-s-driver-more-frequently.patch b/SOURCES/libvirt-conf-Format-interface-s-driver-more-frequently.patch new file mode 100644 index 0000000..507ffbf --- /dev/null +++ b/SOURCES/libvirt-conf-Format-interface-s-driver-more-frequently.patch @@ -0,0 +1,119 @@ +From 4b31aeaaa431a2a0a85bedf205358c2499a8f35d Mon Sep 17 00:00:00 2001 +Message-Id: <4b31aeaaa431a2a0a85bedf205358c2499a8f35d@dist-git> +From: Michal Privoznik +Date: Mon, 19 Jan 2015 12:43:42 +0100 +Subject: [PATCH] conf: Format interface's driver more frequently + +RHEL-7.0.z: https://bugzilla.redhat.com/show_bug.cgi?id=1183447 +RHEL-7.1: https://bugzilla.redhat.com/show_bug.cgi?id=1128751 + +There's this element under which can have +several attributes. However, the driver element is currently formated +only if the driver's name or txmode has been specified. This makes +only a little sense as we parse even partial , for instance: + + + + + + + +But such XML would never get formatted back. + +Signed-off-by: Michal Privoznik +(cherry picked from commit 3085702b5461d3b0b057c37cf5fbff432244f529) +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 4 +- + .../qemuxml2argv-interface-driver.xml | 51 ++++++++++++++++++++++ + tests/qemuxml2xmltest.c | 1 + + 3 files changed, 55 insertions(+), 1 deletion(-) + create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-interface-driver.xml + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index bb2e7ef..922c5e6 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -15387,7 +15387,9 @@ virDomainNetDefFormat(virBufferPtr buf, + virBufferEscapeString(buf, "\n", + def->model); + if (STREQ(def->model, "virtio") && +- (def->driver.virtio.name || def->driver.virtio.txmode)) { ++ (def->driver.virtio.name || def->driver.virtio.txmode || ++ def->driver.virtio.ioeventfd || def->driver.virtio.event_idx || ++ def->driver.virtio.queues)) { + virBufferAddLit(buf, "driver.virtio.name) { + virBufferAsprintf(buf, " name='%s'", +diff --git a/tests/qemuxml2argvdata/qemuxml2argv-interface-driver.xml b/tests/qemuxml2argvdata/qemuxml2argv-interface-driver.xml +new file mode 100644 +index 0000000..ec5ab61 +--- /dev/null ++++ b/tests/qemuxml2argvdata/qemuxml2argv-interface-driver.xml +@@ -0,0 +1,51 @@ ++ ++ test ++ 15d091de-0181-456b-9554-e4382dc1f1ab ++ 1048576 ++ 1048576 ++ 1 ++ ++ hvm ++ ++ ++ ++ ++ ++ destroy ++ restart ++ restart ++ ++ /usr/bin/qemu ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++
++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c +index d16fdc3..11ac108 100644 +--- a/tests/qemuxml2xmltest.c ++++ b/tests/qemuxml2xmltest.c +@@ -255,6 +255,7 @@ mymain(void) + DO_TEST("lease"); + DO_TEST("event_idx"); + DO_TEST("vhost_queues"); ++ DO_TEST("interface-driver"); + DO_TEST("virtio-lun"); + + DO_TEST("usb-redir"); +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-Improve-metadata-type-verification.patch b/SOURCES/libvirt-conf-Improve-metadata-type-verification.patch new file mode 100644 index 0000000..1e32669 --- /dev/null +++ b/SOURCES/libvirt-conf-Improve-metadata-type-verification.patch @@ -0,0 +1,78 @@ +From be61ac8742d24a170a83340b576dbb39635133f6 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:55 +0100 +Subject: [PATCH] conf: Improve metadata type verification + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +Split out checking of invalid metadata type from the switch statement so +that we can use the typecasted enum value to allow tracking addition of +new items by the compliler. + +Also avoids two dead-code break statements. + +(cherry picked from commit 3738166603b2ab11ae30061381f378679b767758) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 36b9ba7..47942ff 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18995,6 +18995,12 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, NULL); + ++ if (type >= VIR_DOMAIN_METADATA_LAST) { ++ virReportError(VIR_ERR_INVALID_ARG, ++ _("unknown metadata type '%d'"), type); ++ goto cleanup; ++ } ++ + if (virDomainLiveConfigHelperMethod(caps, xmlopt, vm, &flags, &def) < 0) + goto cleanup; + +@@ -19021,10 +19027,7 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + goto cleanup; + break; + +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; ++ case VIR_DOMAIN_METADATA_LAST: + break; + } + +@@ -19050,6 +19053,12 @@ virDomainDefSetMetadata(virDomainDefPtr def, + char *tmp; + int ret = -1; + ++ if (type >= VIR_DOMAIN_METADATA_LAST) { ++ virReportError(VIR_ERR_INVALID_ARG, ++ _("unknown metadata type '%d'"), type); ++ goto cleanup; ++ } ++ + switch ((virDomainMetadataType) type) { + case VIR_DOMAIN_METADATA_DESCRIPTION: + if (VIR_STRDUP(tmp, metadata) < 0) +@@ -19103,10 +19112,7 @@ virDomainDefSetMetadata(virDomainDefPtr def, + } + break; + +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; ++ case VIR_DOMAIN_METADATA_LAST: + break; + } + +-- +2.2.1 + diff --git a/SOURCES/libvirt-conf-allow-to-add-XML-metadata-using-the-virDomainSetMetadata-api.patch b/SOURCES/libvirt-conf-allow-to-add-XML-metadata-using-the-virDomainSetMetadata-api.patch new file mode 100644 index 0000000..34ae64a --- /dev/null +++ b/SOURCES/libvirt-conf-allow-to-add-XML-metadata-using-the-virDomainSetMetadata-api.patch @@ -0,0 +1,150 @@ +From febb8d0b48c7a7bf7b587bc43d7e423318f49369 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:46 +0100 +Subject: [PATCH] conf: allow to add XML metadata using the + virDomainSetMetadata api + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The functionality wasn't originally implemented. This patch adds the +ability to modify domain's XML metadata using the API. + +(cherry picked from commit 73bfac0e7182a3abde02304fd2f17845715a9a2e) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- + src/util/virxml.c | 32 ++++++++++++++++++++++++++++++++ + src/util/virxml.h | 4 ++++ + 3 files changed, 78 insertions(+), 5 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index c104218..4dbe3fc 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19038,9 +19038,12 @@ static int + virDomainDefSetMetadata(virDomainDefPtr def, + int type, + const char *metadata, +- const char *key ATTRIBUTE_UNUSED, +- const char *uri ATTRIBUTE_UNUSED) ++ const char *key, ++ const char *uri) + { ++ xmlDocPtr doc = NULL; ++ xmlNodePtr old; ++ xmlNodePtr new; + int ret = -1; + + switch ((virDomainMetadataType) type) { +@@ -19057,9 +19060,42 @@ virDomainDefSetMetadata(virDomainDefPtr def, + break; + + case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _(" element is not supported")); +- goto cleanup; ++ if (metadata) { ++ /* parse and modify the xml from the user */ ++ if (!(doc = virXMLParseString(metadata, _("(metadata_xml)")))) ++ goto cleanup; ++ ++ if (virXMLInjectNamespace(doc->children, uri, key) < 0) ++ goto cleanup; ++ ++ /* create the root node if needed */ ++ if (!def->metadata && ++ !(def->metadata = xmlNewNode(NULL, (unsigned char *)"metadata"))) { ++ virReportOOMError(); ++ goto cleanup; ++ } ++ ++ if (!(new = xmlCopyNode(doc->children, 1))) { ++ virReportOOMError(); ++ goto cleanup; ++ } ++ } ++ ++ /* remove possible other nodes sharing the namespace */ ++ while ((old = virXMLFindChildNodeByNs(def->metadata, uri))) { ++ xmlUnlinkNode(old); ++ xmlFreeNode(old); ++ } ++ ++ /* just delete the metadata */ ++ if (!metadata) ++ break; ++ ++ if (!(xmlAddChild(def->metadata, new))) { ++ xmlFreeNode(new); ++ virReportOOMError(); ++ goto cleanup; ++ } + break; + + default: +@@ -19072,6 +19108,7 @@ virDomainDefSetMetadata(virDomainDefPtr def, + ret = 0; + + cleanup: ++ xmlFreeDoc(doc); + return ret; + } + +diff --git a/src/util/virxml.c b/src/util/virxml.c +index 9048d78..de1e1e0 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -1050,3 +1050,35 @@ cleanup: + xmlFreeNode(nodeCopy); + return ret; + } ++ ++ ++static int ++virXMLAddElementNamespace(xmlNodePtr node, ++ void *opaque) ++{ ++ xmlNsPtr ns = opaque; ++ ++ if (!node->ns) ++ xmlSetNs(node, ns); ++ ++ return 0; ++} ++ ++ ++int ++virXMLInjectNamespace(xmlNodePtr node, ++ const char *uri, ++ const char *key) ++{ ++ xmlNsPtr ns; ++ ++ if (!(ns = xmlNewNs(node, (const unsigned char *)uri, (const unsigned char *)key))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to create a new XML namespace")); ++ return -1; ++ } ++ ++ virXMLForeachNode(node, virXMLAddElementNamespace, ns); ++ ++ return 0; ++} +diff --git a/src/util/virxml.h b/src/util/virxml.h +index 7dc6c9d..d967a2e 100644 +--- a/src/util/virxml.h ++++ b/src/util/virxml.h +@@ -172,4 +172,8 @@ int virXMLExtractNamespaceXML(xmlNodePtr root, + const char *uri, + char **doc); + ++int virXMLInjectNamespace(xmlNodePtr node, ++ const char *uri, ++ const char *key); ++ + #endif /* __VIR_XML_H__ */ +-- +2.2.1 + diff --git a/SOURCES/libvirt-cpu_x86-Resolve-Coverity-RESOURCE_LEAK.patch b/SOURCES/libvirt-cpu_x86-Resolve-Coverity-RESOURCE_LEAK.patch new file mode 100644 index 0000000..954d8af --- /dev/null +++ b/SOURCES/libvirt-cpu_x86-Resolve-Coverity-RESOURCE_LEAK.patch @@ -0,0 +1,63 @@ +From 495bf507eaf0eab638d3cf89a8854d23824b319e Mon Sep 17 00:00:00 2001 +Message-Id: <495bf507eaf0eab638d3cf89a8854d23824b319e@dist-git> +From: John Ferlan +Date: Wed, 27 Aug 2014 14:27:07 -0400 +Subject: [PATCH] cpu_x86: Resolve Coverity RESOURCE_LEAK + +Coverity determined that the copied 'oldguest' would be leaked for +both error and success paths. + +(cherry picked from commit be7b82a283bc789da6cf9edc413ea399636b97b8) +https://bugzilla.redhat.com/show_bug.cgi?id=1185458 +Signed-off-by: Jiri Denemark +--- + src/cpu/cpu_x86.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index 7bd8acb..4e77550 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -1940,8 +1940,9 @@ static int + x86UpdateHostModel(virCPUDefPtr guest, + const virCPUDefPtr host) + { +- virCPUDefPtr oldguest; ++ virCPUDefPtr oldguest = NULL; + size_t i; ++ int ret = -1; + + guest->match = VIR_CPU_MATCH_EXACT; + +@@ -1953,20 +1954,24 @@ x86UpdateHostModel(virCPUDefPtr guest, + + /* update the host model according to the desired configuration */ + if (!(oldguest = virCPUDefCopy(guest))) +- return -1; ++ goto cleanup; + + virCPUDefFreeModel(guest); + if (virCPUDefCopyModel(guest, host, true) < 0) +- return -1; ++ goto cleanup; + + for (i = 0; i < oldguest->nfeatures; i++) { + if (virCPUDefUpdateFeature(guest, + oldguest->features[i].name, + oldguest->features[i].policy) < 0) +- return -1; ++ goto cleanup; + } + +- return 0; ++ ret = 0; ++ ++ cleanup: ++ virCPUDefFree(oldguest); ++ return ret; + } + + +-- +2.2.2 + diff --git a/SOURCES/libvirt-lib-Don-t-force-the-key-argument-when-deleting-metadata.patch b/SOURCES/libvirt-lib-Don-t-force-the-key-argument-when-deleting-metadata.patch new file mode 100644 index 0000000..b09e714 --- /dev/null +++ b/SOURCES/libvirt-lib-Don-t-force-the-key-argument-when-deleting-metadata.patch @@ -0,0 +1,38 @@ +From b0a82f4abc9f4de3db965c84b926322846588278 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:47 +0100 +Subject: [PATCH] lib: Don't force the key argument when deleting metadata + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +virDomainSetMetadata when operating on the metadata element was +requesting the @key argument to be passed even if @metadata was NULL +used to delete the corresponding metadata element. This is not needed as +the key is only used when adding the element and matching is done via +the XML namespace. + +(cherry picked from commit 3b6784d119074e3be8861cc4c30630f299bde121) + +Signed-off-by: Jiri Denemark +--- + src/libvirt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/libvirt.c b/src/libvirt.c +index cbcc24b..874304f 100644 +--- a/src/libvirt.c ++++ b/src/libvirt.c +@@ -10812,7 +10812,8 @@ virDomainSetMetadata(virDomainPtr domain, + break; + case VIR_DOMAIN_METADATA_ELEMENT: + virCheckNonNullArgGoto(uri, error); +- virCheckNonNullArgGoto(key, error); ++ if (metadata) ++ virCheckNonNullArgGoto(key, error); + break; + default: + /* For future expansion */ +-- +2.2.1 + diff --git a/SOURCES/libvirt-lxc-Add-metadata-modification-APIs.patch b/SOURCES/libvirt-lxc-Add-metadata-modification-APIs.patch new file mode 100644 index 0000000..5e90396 --- /dev/null +++ b/SOURCES/libvirt-lxc-Add-metadata-modification-APIs.patch @@ -0,0 +1,106 @@ +From 9c171ebceeed9cf28f0e86e0de604805e3669bdf Mon Sep 17 00:00:00 2001 +Message-Id: <9c171ebceeed9cf28f0e86e0de604805e3669bdf@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:48 +0100 +Subject: [PATCH] lxc: Add metadata modification APIs + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +(cherry picked from commit f9c7b32e5de3fb0ccf2e0858716886bdb35a9913) + +Signed-off-by: Jiri Denemark +--- + src/lxc/lxc_driver.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + +diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c +index 1aaa6e7..e9f2f51 100644 +--- a/src/lxc/lxc_driver.c ++++ b/src/lxc/lxc_driver.c +@@ -4702,6 +4702,74 @@ lxcNodeSuspendForDuration(virConnectPtr conn, + } + + ++static int ++lxcDomainSetMetadata(virDomainPtr dom, ++ int type, ++ const char *metadata, ++ const char *key, ++ const char *uri, ++ unsigned int flags) ++{ ++ virLXCDriverPtr driver = dom->conn->privateData; ++ virDomainObjPtr vm; ++ virLXCDriverConfigPtr cfg = NULL; ++ virCapsPtr caps = NULL; ++ int ret = -1; ++ ++ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | ++ VIR_DOMAIN_AFFECT_CONFIG, -1); ++ ++ if (!(vm = lxcDomObjFromDomain(dom))) ++ return -1; ++ ++ cfg = virLXCDriverGetConfig(driver); ++ ++ if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0) ++ goto cleanup; ++ ++ if (!(caps = virLXCDriverGetCapabilities(driver, false))) ++ goto cleanup; ++ ++ ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps, ++ driver->xmlopt, cfg->configDir, flags); ++ ++cleanup: ++ virObjectUnlock(vm); ++ virObjectUnref(caps); ++ virObjectUnref(cfg); ++ return ret; ++} ++ ++ ++static char * ++lxcDomainGetMetadata(virDomainPtr dom, ++ int type, ++ const char *uri, ++ unsigned int flags) ++{ ++ virLXCDriverPtr driver = dom->conn->privateData; ++ virCapsPtr caps = NULL; ++ virDomainObjPtr vm; ++ char *ret = NULL; ++ ++ if (!(vm = lxcDomObjFromDomain(dom))) ++ return NULL; ++ ++ if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0) ++ goto cleanup; ++ ++ if (!(caps = virLXCDriverGetCapabilities(driver, false))) ++ goto cleanup; ++ ++ ret = virDomainObjGetMetadata(vm, type, uri, caps, driver->xmlopt, flags); ++ ++cleanup: ++ virObjectUnlock(vm); ++ virObjectUnref(caps); ++ return ret; ++} ++ ++ + /* Function Tables */ + static virDriver lxcDriver = { + .no = VIR_DRV_LXC, +@@ -4776,6 +4844,8 @@ static virDriver lxcDriver = { + .domainOpenConsole = lxcDomainOpenConsole, /* 0.8.6 */ + .connectIsAlive = lxcConnectIsAlive, /* 0.9.8 */ + .nodeSuspendForDuration = lxcNodeSuspendForDuration, /* 0.9.8 */ ++ .domainSetMetadata = lxcDomainSetMetadata, /* 1.1.3 */ ++ .domainGetMetadata = lxcDomainGetMetadata, /* 1.1.3 */ + .nodeGetMemoryParameters = lxcNodeGetMemoryParameters, /* 0.10.2 */ + .nodeSetMemoryParameters = lxcNodeSetMemoryParameters, /* 0.10.2 */ + .domainSendProcessSignal = lxcDomainSendProcessSignal, /* 1.0.1 */ +-- +2.2.1 + diff --git a/SOURCES/libvirt-man-virsh-Add-man-page-for-virsh-metadata.patch b/SOURCES/libvirt-man-virsh-Add-man-page-for-virsh-metadata.patch new file mode 100644 index 0000000..ac833d1 --- /dev/null +++ b/SOURCES/libvirt-man-virsh-Add-man-page-for-virsh-metadata.patch @@ -0,0 +1,62 @@ +From 715a29642aaedc6b19b451677cb02658d5924b7f Mon Sep 17 00:00:00 2001 +Message-Id: <715a29642aaedc6b19b451677cb02658d5924b7f@dist-git> +From: Peter Krempa +Date: Wed, 28 Jan 2015 10:33:39 +0100 +Subject: [PATCH] man: virsh: Add man page for "virsh metadata" + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +Patch adding the command forgot to add the man page entry. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1130379 +(cherry picked from commit 992318cbee83dc381c44acfdfdecfb2607279e25) + +Signed-off-by: Jiri Denemark +--- + tools/virsh.pod | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/tools/virsh.pod b/tools/virsh.pod +index f1b09d9..c3ae204 100644 +--- a/tools/virsh.pod ++++ b/tools/virsh.pod +@@ -1073,6 +1073,36 @@ I<--total> for only the total stats, I for only the per-cpu + stats of the CPUs from I, I for only I CPUs' + stats. + ++=item B I [[I<--live>] [I<--config>] | [I<--current>]] ++[I<--edit>] [I] [I] [I] [I<--remove>] ++ ++Show or modify custom XML metadata of a domain. The metadata is a user ++defined XML that allows to store arbitrary XML data in the domain definition. ++Multiple separate custom metadata pieces can be stored in the domain XML. ++The pieces are identified by a private XML namespace provided via the ++I argument. ++ ++Flags I<--live> or I<--config> select whether this command works on live ++or persistent definitions of the domain. If both I<--live> and I<--config> ++are specified, the I<--config> option takes precedence on getting the current ++description and both live configuration and config are updated while setting ++the description. I<--current> is exclusive and implied if none of these was ++specified. ++ ++Flag I<--remove> specifies that the metadata element specified by the I ++argument should be removed rather than updated. ++ ++Flag I<--edit> specifies that an editor with the metadata identified by the ++I argument should be opened and the contents saved back afterwards. ++Otherwise the new contents can be provided via the I argument. ++ ++When setting metadata via I<--edit> or I the I argument must be ++specified and is used to prefix the custom elements to bind them ++to the private namespace. ++ ++If neither of I<--edit> and I are specified the XML metadata corresponding ++to the I namespace is displayed instead of being modified. ++ + =item B [I<--live>] [I<--offline>] [I<--direct>] [I<--p2p> [I<--tunnelled>]] + [I<--persistent>] [I<--undefinesource>] [I<--suspend>] [I<--copy-storage-all>] + [I<--copy-storage-inc>] [I<--change-protection>] [I<--unsafe>] [I<--verbose>] +-- +2.2.2 + diff --git a/SOURCES/libvirt-metadata-track-title-edits-across-libvirtd-restart.patch b/SOURCES/libvirt-metadata-track-title-edits-across-libvirtd-restart.patch new file mode 100644 index 0000000..bcb0f33 --- /dev/null +++ b/SOURCES/libvirt-metadata-track-title-edits-across-libvirtd-restart.patch @@ -0,0 +1,135 @@ +From d60a5ab6fd5ba1ef21687eb995c7c2c2ffbd892c Mon Sep 17 00:00:00 2001 +Message-Id: +From: Eric Blake +Date: Thu, 22 Jan 2015 15:53:54 +0100 +Subject: [PATCH] metadata: track title edits across libvirtd restart + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 +https://bugzilla.redhat.com/show_bug.cgi?id=1122205 + +Although the edits were changing in-memory XML, it was not flushed +to disk; so unless some other action changes XML, a libvirtd restart +would lose the changed information. + +* src/conf/domain_conf.c (virDomainObjSetMetadata): Add parameter, +to save live status across restarts. +(virDomainSaveXML): Allow for test driver. +* src/conf/domain_conf.h (virDomainObjSetMetadata): Adjust +signature. +* src/bhyve/bhyve_driver.c (bhyveDomainSetMetadata): Adjust caller. +* src/lxc/lxc_driver.c (lxcDomainSetMetadata): Likewise. +* src/qemu/qemu_driver.c (qemuDomainSetMetadata): Likewise. +* src/test/test_driver.c (testDomainSetMetadata): Likewise. + +Signed-off-by: Eric Blake +(cherry picked from commit 60e49440598b4aeb4a32bf23bfa5ed85672cbd6a) + +Conflicts: + src/bhyve/bhyve_driver.c - bhyve driver is missing +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 13 +++++++++++-- + src/conf/domain_conf.h | 1 + + src/lxc/lxc_driver.c | 3 ++- + src/qemu/qemu_driver.c | 3 ++- + src/test/test_driver.c | 2 +- + 5 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index a2c0d6c..36b9ba7 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -17491,6 +17491,9 @@ virDomainSaveXML(const char *configDir, + char *configFile = NULL; + int ret = -1; + ++ if (!configDir) ++ return 0; ++ + if ((configFile = virDomainConfigFile(configDir, def->name)) == NULL) + goto cleanup; + +@@ -19123,6 +19126,7 @@ virDomainObjSetMetadata(virDomainObjPtr vm, + const char *uri, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ const char *stateDir, + const char *configDir, + unsigned int flags) + { +@@ -19135,12 +19139,17 @@ virDomainObjSetMetadata(virDomainObjPtr vm, + &persistentDef) < 0) + return -1; + +- if (flags & VIR_DOMAIN_AFFECT_LIVE) ++ if (flags & VIR_DOMAIN_AFFECT_LIVE) { + if (virDomainDefSetMetadata(vm->def, type, metadata, key, uri) < 0) + return -1; + ++ if (virDomainSaveStatus(xmlopt, stateDir, vm) < 0) ++ return -1; ++ } ++ + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { +- if (virDomainDefSetMetadata(persistentDef, type, metadata, key, uri) < 0) ++ if (virDomainDefSetMetadata(persistentDef, type, metadata, key, ++ uri) < 0) + return -1; + + if (virDomainSaveConfig(configDir, persistentDef) < 0) +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index eaeea03..ef64d88 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2785,6 +2785,7 @@ int virDomainObjSetMetadata(virDomainObjPtr vm, + const char *uri, + virCapsPtr caps, + virDomainXMLOptionPtr xmlopt, ++ const char *stateDir, + const char *configDir, + unsigned int flags); + +diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c +index e9f2f51..c47a206 100644 +--- a/src/lxc/lxc_driver.c ++++ b/src/lxc/lxc_driver.c +@@ -4731,7 +4731,8 @@ lxcDomainSetMetadata(virDomainPtr dom, + goto cleanup; + + ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps, +- driver->xmlopt, cfg->configDir, flags); ++ driver->xmlopt, cfg->stateDir, ++ cfg->configDir, flags); + + cleanup: + virObjectUnlock(vm); +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 57583e8..2ee3582 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -15887,7 +15887,8 @@ qemuDomainSetMetadata(virDomainPtr dom, + goto cleanup; + + ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps, +- driver->xmlopt, cfg->configDir, flags); ++ driver->xmlopt, cfg->stateDir, ++ cfg->configDir, flags); + + cleanup: + virObjectUnlock(vm); +diff --git a/src/test/test_driver.c b/src/test/test_driver.c +index 4d23738..e398130 100644 +--- a/src/test/test_driver.c ++++ b/src/test/test_driver.c +@@ -2585,7 +2585,7 @@ static int testDomainSetMetadata(virDomainPtr dom, + + ret = virDomainObjSetMetadata(privdom, type, metadata, key, uri, + privconn->caps, privconn->xmlopt, +- NULL, flags); ++ NULL, NULL, flags); + + cleanup: + if (privdom) +-- +2.2.1 + diff --git a/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainGetMetadata-for-universal-use.patch b/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainGetMetadata-for-universal-use.patch new file mode 100644 index 0000000..8d58e49 --- /dev/null +++ b/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainGetMetadata-for-universal-use.patch @@ -0,0 +1,196 @@ +From 135eeb60e3d7b1cda9f48bdd38542bb3c06e2638 Mon Sep 17 00:00:00 2001 +Message-Id: <135eeb60e3d7b1cda9f48bdd38542bb3c06e2638@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:39 +0100 +Subject: [PATCH] qemu: Factor out body of qemuDomainGetMetadata for universal + use + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The function implemented common behavior that can be reused for other +hypervisor drivers that use the virDomainObj data structures. Factor out +the core into a separate helper func. + +(cherry picked from commit 99c51af2ee42de980c258ecb52cf20f96c69ff83) + +Conflicts: + src/conf/domain_conf.h - context + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/conf/domain_conf.h | 7 ++++++ + src/libvirt_private.syms | 1 + + src/qemu/qemu_driver.c | 49 +++++------------------------------------- + 4 files changed, 68 insertions(+), 44 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 922c5e6..b052924 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -18976,3 +18976,58 @@ virDomainDiskSourceIsBlockType(virDomainDiskDefPtr def) + } + return false; + } ++ ++ ++char * ++virDomainObjGetMetadata(virDomainObjPtr vm, ++ int type, ++ const char *uri ATTRIBUTE_UNUSED, ++ virCapsPtr caps, ++ virDomainXMLOptionPtr xmlopt, ++ unsigned int flags) ++{ ++ virDomainDefPtr def; ++ char *field = NULL; ++ char *ret = NULL; ++ ++ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | ++ VIR_DOMAIN_AFFECT_CONFIG, NULL); ++ ++ if (virDomainLiveConfigHelperMethod(caps, xmlopt, vm, &flags, &def) < 0) ++ goto cleanup; ++ ++ /* use correct domain definition according to flags */ ++ if (flags & VIR_DOMAIN_AFFECT_LIVE) ++ def = vm->def; ++ ++ switch ((virDomainMetadataType) type) { ++ case VIR_DOMAIN_METADATA_DESCRIPTION: ++ field = def->description; ++ break; ++ ++ case VIR_DOMAIN_METADATA_TITLE: ++ field = def->title; ++ break; ++ ++ case VIR_DOMAIN_METADATA_ELEMENT: ++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", ++ _(" element is not yet supported")); ++ goto cleanup; ++ break; ++ ++ default: ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("unknown metadata type")); ++ goto cleanup; ++ break; ++ } ++ ++ if (!field) ++ virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s", ++ _("Requested metadata element is not present")); ++ ++ ignore_value(VIR_STRDUP(ret, field)); ++ ++cleanup: ++ return ret; ++} +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 00e66ae..08c677f 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2771,4 +2771,11 @@ int virDomainDefFindDevice(virDomainDefPtr def, + bool virDomainDiskSourceIsBlockType(virDomainDiskDefPtr def) + ATTRIBUTE_NONNULL(1); + ++char *virDomainObjGetMetadata(virDomainObjPtr vm, ++ int type, ++ const char *uri, ++ virCapsPtr caps, ++ virDomainXMLOptionPtr xmlopt, ++ unsigned int flags); ++ + #endif /* __DOMAIN_CONF_H */ +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 5cf7039..40007e1 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -313,6 +313,7 @@ virDomainNostateReasonTypeFromString; + virDomainNostateReasonTypeToString; + virDomainObjAssignDef; + virDomainObjCopyPersistentDef; ++virDomainObjGetMetadata; + virDomainObjGetPersistentDef; + virDomainObjGetState; + virDomainObjListAdd; +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index b0d4f33..3beed9a 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -15958,21 +15958,16 @@ cleanup: + static char * + qemuDomainGetMetadata(virDomainPtr dom, + int type, +- const char *uri ATTRIBUTE_UNUSED, ++ const char *uri, + unsigned int flags) + { + virQEMUDriverPtr driver = dom->conn->privateData; ++ virCapsPtr caps = NULL; + virDomainObjPtr vm; +- virDomainDefPtr def; + char *ret = NULL; +- char *field = NULL; +- virCapsPtr caps = NULL; +- +- virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | +- VIR_DOMAIN_AFFECT_CONFIG, NULL); + + if (!(vm = qemuDomObjFromDomain(dom))) +- goto cleanup; ++ return NULL; + + if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; +@@ -15980,44 +15975,10 @@ qemuDomainGetMetadata(virDomainPtr dom, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto cleanup; + +- if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags, &def) < 0) +- goto cleanup; +- +- /* use correct domain definition according to flags */ +- if (flags & VIR_DOMAIN_AFFECT_LIVE) +- def = vm->def; +- +- switch ((virDomainMetadataType) type) { +- case VIR_DOMAIN_METADATA_DESCRIPTION: +- field = def->description; +- break; +- case VIR_DOMAIN_METADATA_TITLE: +- field = def->title; +- break; +- case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _("QEMU driver does not support " +- " element")); +- goto cleanup; +- break; +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; +- break; +- } +- +- if (!field) { +- virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s", +- _("Requested metadata element is not present")); +- goto cleanup; +- } +- +- ignore_value(VIR_STRDUP(ret, field)); ++ ret = virDomainObjGetMetadata(vm, type, uri, caps, driver->xmlopt, flags); + + cleanup: +- if (vm) +- virObjectUnlock(vm); ++ virObjectUnlock(vm); + virObjectUnref(caps); + return ret; + } +-- +2.2.1 + diff --git a/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainSetMetadata-for-universal-use.patch b/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainSetMetadata-for-universal-use.patch new file mode 100644 index 0000000..90df9d5 --- /dev/null +++ b/SOURCES/libvirt-qemu-Factor-out-body-of-qemuDomainSetMetadata-for-universal-use.patch @@ -0,0 +1,254 @@ +From eff5466a6e7ca4c5b324e091c2be00e8fa71a338 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:40 +0100 +Subject: [PATCH] qemu: Factor out body of qemuDomainSetMetadata for universal + use + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The function implemented common behavior that can be reused for other +hypervisor drivers that use the virDomainObj data structures. Factor out +the core into a separate helper func. + +(cherry picked from commit f87a7c67de946f941fddde44d5959baaac6c7de4) + +Signed-off-by: Jiri Denemark +--- + src/conf/domain_conf.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/conf/domain_conf.h | 10 ++++++ + src/libvirt_private.syms | 1 + + src/qemu/qemu_driver.c | 73 ++++------------------------------------- + 4 files changed, 103 insertions(+), 66 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index b052924..7bfb602 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19031,3 +19031,88 @@ virDomainObjGetMetadata(virDomainObjPtr vm, + cleanup: + return ret; + } ++ ++int ++virDomainObjSetMetadata(virDomainObjPtr vm, ++ int type, ++ const char *metadata, ++ const char *key ATTRIBUTE_UNUSED, ++ const char *uri ATTRIBUTE_UNUSED, ++ virCapsPtr caps, ++ virDomainXMLOptionPtr xmlopt, ++ const char *configDir, ++ unsigned int flags) ++{ ++ virDomainDefPtr persistentDef; ++ int ret = -1; ++ ++ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | ++ VIR_DOMAIN_AFFECT_CONFIG, -1); ++ ++ if (virDomainLiveConfigHelperMethod(caps, xmlopt, vm, &flags, ++ &persistentDef) < 0) ++ goto cleanup; ++ ++ if (flags & VIR_DOMAIN_AFFECT_LIVE) { ++ switch ((virDomainMetadataType) type) { ++ case VIR_DOMAIN_METADATA_DESCRIPTION: ++ VIR_FREE(vm->def->description); ++ if (VIR_STRDUP(vm->def->description, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_TITLE: ++ VIR_FREE(vm->def->title); ++ if (VIR_STRDUP(vm->def->title, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_ELEMENT: ++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", ++ _(" element is not supported")); ++ goto cleanup; ++ break; ++ ++ default: ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("unknown metadata type")); ++ goto cleanup; ++ break; ++ } ++ } ++ ++ if (flags & VIR_DOMAIN_AFFECT_CONFIG) { ++ switch ((virDomainMetadataType) type) { ++ case VIR_DOMAIN_METADATA_DESCRIPTION: ++ VIR_FREE(persistentDef->description); ++ if (VIR_STRDUP(persistentDef->description, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_TITLE: ++ VIR_FREE(persistentDef->title); ++ if (VIR_STRDUP(persistentDef->title, metadata) < 0) ++ goto cleanup; ++ break; ++ ++ case VIR_DOMAIN_METADATA_ELEMENT: ++ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", ++ _(" element is not supported")); ++ goto cleanup; ++ ++ default: ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("unknown metadata type")); ++ goto cleanup; ++ break; ++ } ++ ++ if (virDomainSaveConfig(configDir, persistentDef) < 0) ++ goto cleanup; ++ } ++ ++ ret = 0; ++ ++cleanup: ++ return ret; ++} +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 08c677f..eaeea03 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2778,4 +2778,14 @@ char *virDomainObjGetMetadata(virDomainObjPtr vm, + virDomainXMLOptionPtr xmlopt, + unsigned int flags); + ++int virDomainObjSetMetadata(virDomainObjPtr vm, ++ int type, ++ const char *metadata, ++ const char *key, ++ const char *uri, ++ virCapsPtr caps, ++ virDomainXMLOptionPtr xmlopt, ++ const char *configDir, ++ unsigned int flags); ++ + #endif /* __DOMAIN_CONF_H */ +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 40007e1..61d8d26 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -331,6 +331,7 @@ virDomainObjListRemove; + virDomainObjListRemoveLocked; + virDomainObjNew; + virDomainObjSetDefTransient; ++virDomainObjSetMetadata; + virDomainObjSetState; + virDomainObjTaint; + virDomainPausedReasonTypeFromString; +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 3beed9a..57583e8 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -15862,22 +15862,21 @@ static int + qemuDomainSetMetadata(virDomainPtr dom, + int type, + const char *metadata, +- const char *key ATTRIBUTE_UNUSED, +- const char *uri ATTRIBUTE_UNUSED, ++ const char *key, ++ const char *uri, + unsigned int flags) + { + virQEMUDriverPtr driver = dom->conn->privateData; + virDomainObjPtr vm; +- virDomainDefPtr persistentDef; +- int ret = -1; + virQEMUDriverConfigPtr cfg = NULL; + virCapsPtr caps = NULL; ++ int ret = -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + + if (!(vm = qemuDomObjFromDomain(dom))) +- goto cleanup; ++ return -1; + + cfg = virQEMUDriverGetConfig(driver); + +@@ -15887,69 +15886,11 @@ qemuDomainSetMetadata(virDomainPtr dom, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto cleanup; + +- if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags, +- &persistentDef) < 0) +- goto cleanup; +- +- if (flags & VIR_DOMAIN_AFFECT_LIVE) { +- switch ((virDomainMetadataType) type) { +- case VIR_DOMAIN_METADATA_DESCRIPTION: +- VIR_FREE(vm->def->description); +- if (VIR_STRDUP(vm->def->description, metadata) < 0) +- goto cleanup; +- break; +- case VIR_DOMAIN_METADATA_TITLE: +- VIR_FREE(vm->def->title); +- if (VIR_STRDUP(vm->def->title, metadata) < 0) +- goto cleanup; +- break; +- case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _("QEmu driver does not support modifying " +- " element")); +- goto cleanup; +- break; +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; +- break; +- } +- } +- +- if (flags & VIR_DOMAIN_AFFECT_CONFIG) { +- switch ((virDomainMetadataType) type) { +- case VIR_DOMAIN_METADATA_DESCRIPTION: +- VIR_FREE(persistentDef->description); +- if (VIR_STRDUP(persistentDef->description, metadata) < 0) +- goto cleanup; +- break; +- case VIR_DOMAIN_METADATA_TITLE: +- VIR_FREE(persistentDef->title); +- if (VIR_STRDUP(persistentDef->title, metadata) < 0) +- goto cleanup; +- break; +- case VIR_DOMAIN_METADATA_ELEMENT: +- virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", +- _("QEMU driver does not support " +- " element")); +- goto cleanup; +- default: +- virReportError(VIR_ERR_INVALID_ARG, "%s", +- _("unknown metadata type")); +- goto cleanup; +- break; +- } +- +- if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0) +- goto cleanup; +- } +- +- ret = 0; ++ ret = virDomainObjSetMetadata(vm, type, metadata, key, uri, caps, ++ driver->xmlopt, cfg->configDir, flags); + + cleanup: +- if (vm) +- virObjectUnlock(vm); ++ virObjectUnlock(vm); + virObjectUnref(caps); + virObjectUnref(cfg); + return ret; +-- +2.2.1 + diff --git a/SOURCES/libvirt-test-Add-metadata-support-into-the-test-driver.patch b/SOURCES/libvirt-test-Add-metadata-support-into-the-test-driver.patch new file mode 100644 index 0000000..2ee314a --- /dev/null +++ b/SOURCES/libvirt-test-Add-metadata-support-into-the-test-driver.patch @@ -0,0 +1,104 @@ +From 5b8a0bcaacd16703b069ba1cf70e8259534eaf69 Mon Sep 17 00:00:00 2001 +Message-Id: <5b8a0bcaacd16703b069ba1cf70e8259534eaf69@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:49 +0100 +Subject: [PATCH] test: Add support into the test driver + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +(cherry picked from commit f616fbf2a4a31a2f944aae0b75d6e2ab3bef3573) + +Signed-off-by: Jiri Denemark +--- + src/test/test_driver.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/src/test/test_driver.c b/src/test/test_driver.c +index f7eaf06..4d23738 100644 +--- a/src/test/test_driver.c ++++ b/src/test/test_driver.c +@@ -2528,6 +2528,72 @@ cleanup: + return ret; + } + ++static char *testDomainGetMetadata(virDomainPtr dom, ++ int type, ++ const char *uri, ++ unsigned int flags) ++{ ++ testConnPtr privconn = dom->conn->privateData; ++ virDomainObjPtr privdom; ++ char *ret = NULL; ++ ++ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | ++ VIR_DOMAIN_AFFECT_CONFIG, NULL); ++ ++ testDriverLock(privconn); ++ privdom = virDomainObjListFindByName(privconn->domains, ++ dom->name); ++ testDriverUnlock(privconn); ++ ++ if (privdom == NULL) { ++ virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__); ++ goto cleanup; ++ } ++ ++ ret = virDomainObjGetMetadata(privdom, type, uri, privconn->caps, ++ privconn->xmlopt, flags); ++ ++cleanup: ++ if (privdom) ++ virObjectUnlock(privdom); ++ return ret; ++} ++ ++static int testDomainSetMetadata(virDomainPtr dom, ++ int type, ++ const char *metadata, ++ const char *key, ++ const char *uri, ++ unsigned int flags) ++{ ++ testConnPtr privconn = dom->conn->privateData; ++ virDomainObjPtr privdom; ++ int ret = -1; ++ ++ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | ++ VIR_DOMAIN_AFFECT_CONFIG, -1); ++ ++ testDriverLock(privconn); ++ privdom = virDomainObjListFindByName(privconn->domains, ++ dom->name); ++ testDriverUnlock(privconn); ++ ++ if (privdom == NULL) { ++ virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__); ++ goto cleanup; ++ } ++ ++ ret = virDomainObjSetMetadata(privdom, type, metadata, key, uri, ++ privconn->caps, privconn->xmlopt, ++ NULL, flags); ++ ++cleanup: ++ if (privdom) ++ virObjectUnlock(privdom); ++ return ret; ++} ++ ++ + static int testNodeGetCellsFreeMemory(virConnectPtr conn, + unsigned long long *freemems, + int startCell, int maxCells) { +@@ -5815,6 +5881,8 @@ static virDriver testDriver = { + .connectIsAlive = testConnectIsAlive, /* 0.9.8 */ + .nodeGetCPUMap = testNodeGetCPUMap, /* 1.0.0 */ + .domainScreenshot = testDomainScreenshot, /* 1.0.5 */ ++ .domainGetMetadata = testDomainGetMetadata, /* 1.1.3 */ ++ .domainSetMetadata = testDomainSetMetadata, /* 1.1.3 */ + }; + + static virNetworkDriver testNetworkDriver = { +-- +2.2.1 + diff --git a/SOURCES/libvirt-tests-Add-metadata-tests.patch b/SOURCES/libvirt-tests-Add-metadata-tests.patch new file mode 100644 index 0000000..8383adc --- /dev/null +++ b/SOURCES/libvirt-tests-Add-metadata-tests.patch @@ -0,0 +1,299 @@ +From 7cef1905e04cef0996df582bf196902a410b4308 Mon Sep 17 00:00:00 2001 +Message-Id: <7cef1905e04cef0996df582bf196902a410b4308@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:50 +0100 +Subject: [PATCH] tests: Add metadata tests + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +This test exercises the virDomain[Get|Set]Metadata API and tests it for +regressions + +(cherry picked from commit 2e23c77b0061c5f1b2fd5eeca79e3d6e963e7a2f) + +Signed-off-by: Jiri Denemark +--- + tests/Makefile.am | 7 ++ + tests/metadatatest.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 252 insertions(+) + create mode 100644 tests/metadatatest.c + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index e49eadc..ac816fe 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -225,6 +225,8 @@ test_programs += interfacexml2xmltest + + test_programs += cputest + ++test_programs += metadatatest ++ + test_scripts = \ + capabilityschematest \ + interfaceschematest \ +@@ -567,6 +569,11 @@ cputest_SOURCES = \ + testutils.c testutils.h + cputest_LDADD = $(LDADDS) + ++metadatatest_SOURCES = \ ++ metadatatest.c \ ++ testutils.c testutils.h ++metadatatest_LDADD = $(LDADDS) $(LIBXML_LIBS) ++ + virshtest_SOURCES = \ + virshtest.c \ + testutils.c testutils.h +diff --git a/tests/metadatatest.c b/tests/metadatatest.c +new file mode 100644 +index 0000000..6bcf335 +--- /dev/null ++++ b/tests/metadatatest.c +@@ -0,0 +1,245 @@ ++/* ++ * Copyright (C) 2013 Red Hat, Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; If not, see ++ * . ++ * ++ * Author: Peter Krempa ++ */ ++ ++#include ++ ++#include "testutils.h" ++ ++#include "virerror.h" ++#include "virxml.h" ++ ++#define VIR_FROM_THIS VIR_FROM_NONE ++ ++static const char metadata1[] = ++"\n" ++" foobar\n" ++" foofoo\n" ++" zomg\n" ++""; ++ ++ ++static const char metadata1_ns[] = ++"\n" ++" foobar\n" ++" foofoo\n" ++" zomg\n" ++""; ++ ++ ++static const char metadata2[] = ++"\n" ++" baz\n" ++""; ++ ++ ++static const char metadata2_ns[] = ++"\n" ++" baz\n" ++""; ++ ++ ++static char * ++getMetadataFromXML(virDomainPtr dom) ++{ ++ xmlDocPtr doc = NULL; ++ xmlXPathContextPtr ctxt = NULL; ++ xmlNodePtr node; ++ ++ char *xml = NULL; ++ char *ret = NULL; ++ ++ if (!(xml = virDomainGetXMLDesc(dom, 0))) ++ goto cleanup; ++ ++ if (!(doc = virXMLParseStringCtxt(xml, "(domain_definition)", &ctxt))) ++ goto cleanup; ++ ++ if (!(node = virXPathNode("//metadata/*", ctxt))) ++ goto cleanup; ++ ++ ret = virXMLNodeToString(node->doc, node); ++ ++cleanup: ++ VIR_FREE(xml); ++ xmlFreeDoc(doc); ++ xmlXPathFreeContext(ctxt); ++ ++ return ret; ++} ++ ++ ++static void ++metadataXMLConvertApostrophe(char *str) ++{ ++ do { ++ if (*str == '\"') ++ *str = '\''; ++ } while ((*++str) != '\0'); ++} ++ ++ ++static bool ++verifyMetadata(virDomainPtr dom, ++ const char *expectXML, ++ const char *expectAPI, ++ const char *uri) ++{ ++ bool ret = false; ++ char *metadataXML = NULL; ++ char *metadataAPI = NULL; ++ ++ if (!expectAPI) { ++ if ((metadataAPI = virDomainGetMetadata(dom, ++ VIR_DOMAIN_METADATA_ELEMENT, ++ uri, 0))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ "expected no metadata in API, but got:\n[%s]", ++ metadataAPI); ++ goto cleanup; ++ } ++ } else { ++ if (!(metadataAPI = virDomainGetMetadata(dom, ++ VIR_DOMAIN_METADATA_ELEMENT, ++ uri, 0))) ++ goto cleanup; ++ ++ metadataXMLConvertApostrophe(metadataAPI); ++ ++ if (STRNEQ(metadataAPI, expectAPI)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ "XML metadata in API doesn't match expected metadata: " ++ "expected:\n[%s]\ngot:\n[%s]", ++ expectAPI, metadataAPI); ++ goto cleanup; ++ } ++ ++ } ++ ++ if (!expectXML) { ++ if ((metadataXML = getMetadataFromXML(dom))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ "expected no metadata in XML, but got:\n[%s]", ++ metadataXML); ++ goto cleanup; ++ } ++ } else { ++ if (!(metadataXML = getMetadataFromXML(dom))) ++ goto cleanup; ++ ++ metadataXMLConvertApostrophe(metadataXML); ++ ++ if (STRNEQ(metadataXML, expectXML)) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ "XML in dump doesn't match expected metadata: " ++ "expected:\n[%s]\ngot:\n[%s]", ++ expectXML, metadataXML); ++ goto cleanup; ++ } ++ } ++ ++ ret = true; ++ ++cleanup: ++ VIR_FREE(metadataXML); ++ VIR_FREE(metadataAPI); ++ ++ return ret; ++} ++ ++ ++struct metadataTest { ++ virConnectPtr conn; ++ virDomainPtr dom; ++}; ++ ++ ++static int ++testAssignMetadata(const void *data) ++{ ++ const struct metadataTest *test = data; ++ ++ if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT, ++ metadata1, "herp", "http://herp.derp/", 0) < 0) ++ return -1; ++ ++ if (!verifyMetadata(test->dom, metadata1_ns, metadata1, "http://herp.derp/")) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++testRewriteMetadata(const void *data) ++{ ++ const struct metadataTest *test = data; ++ ++ if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT, ++ metadata2, "blurb", "http://herp.derp/", 0) < 0) ++ return -1; ++ ++ if (!verifyMetadata(test->dom, metadata2_ns, metadata2, "http://herp.derp/")) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++testEraseMetadata(const void *data) ++{ ++ const struct metadataTest *test = data; ++ ++ if (virDomainSetMetadata(test->dom, VIR_DOMAIN_METADATA_ELEMENT, ++ NULL, NULL, "http://herp.derp/", 0) < 0) ++ return -1; ++ ++ if (!verifyMetadata(test->dom, NULL, NULL, "http://herp.derp/")) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++mymain(void) ++{ ++ struct metadataTest test; ++ int ret = EXIT_SUCCESS; ++ ++ if (!(test.conn = virConnectOpen("test:///default"))) ++ return EXIT_FAILURE; ++ ++ if (!(test.dom = virDomainLookupByName(test.conn, "test"))) { ++ virConnectClose(test.conn); ++ return EXIT_FAILURE; ++ } ++ ++ if (virtTestRun("Assign metadata ", 1, testAssignMetadata, &test) < 0) ++ ret = EXIT_FAILURE; ++ if (virtTestRun("Rewrite Metadata ", 1, testRewriteMetadata, &test) < 0) ++ ret = EXIT_FAILURE; ++ if (virtTestRun("Erase metadata ", 1, testEraseMetadata, &test) < 0) ++ ret = EXIT_FAILURE; ++ ++ virDomainFree(test.dom); ++ virConnectClose(test.conn); ++ ++ return ret; ++} ++ ++VIRT_TEST_MAIN(mymain) +-- +2.2.1 + diff --git a/SOURCES/libvirt-util-Add-helper-to-convert-libxml2-nodes-to-a-string.patch b/SOURCES/libvirt-util-Add-helper-to-convert-libxml2-nodes-to-a-string.patch new file mode 100644 index 0000000..93d7ceb --- /dev/null +++ b/SOURCES/libvirt-util-Add-helper-to-convert-libxml2-nodes-to-a-string.patch @@ -0,0 +1,84 @@ +From 2e65f52bf904f8ff5587dc42b7c37d94f9dab451 Mon Sep 17 00:00:00 2001 +Message-Id: <2e65f52bf904f8ff5587dc42b7c37d94f9dab451@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:42 +0100 +Subject: [PATCH] util: Add helper to convert libxml2 nodes to a string + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +(cherry picked from commit be0f0c2292e3f171a031086f4d0a39b205c756a3) + +Signed-off-by: Jiri Denemark +--- + src/libvirt_private.syms | 1 + + src/util/virxml.c | 33 +++++++++++++++++++++++++++++++++ + src/util/virxml.h | 2 ++ + 3 files changed, 36 insertions(+) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 61d8d26..3df4379 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -2140,6 +2140,7 @@ virUUIDParse; + + # util/virxml.h + virXMLChildElementCount; ++virXMLNodeToString; + virXMLParseHelper; + virXMLPickShellSafeComment; + virXMLPropString; +diff --git a/src/util/virxml.c b/src/util/virxml.c +index 4769569..9bb8bf0 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -895,3 +895,36 @@ virXMLChildElementCount(xmlNodePtr node) + } + return ret; + } ++ ++ ++/** ++ * virXMLNodeToString: convert an XML node ptr to an XML string ++ * ++ * Returns the XML string of the document or NULL on error. ++ * The caller has to free the string. ++ */ ++char * ++virXMLNodeToString(xmlDocPtr doc, ++ xmlNodePtr node) ++{ ++ xmlBufferPtr xmlbuf = NULL; ++ char *ret = NULL; ++ ++ if (!(xmlbuf = xmlBufferCreate())) { ++ virReportOOMError(); ++ return NULL; ++ } ++ ++ if (xmlNodeDump(xmlbuf, doc, node, 0, 1) == 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to convert the XML node tree")); ++ goto cleanup; ++ } ++ ++ ignore_value(VIR_STRDUP(ret, (const char *)xmlBufferContent(xmlbuf))); ++ ++cleanup: ++ xmlBufferFree(xmlbuf); ++ ++ return ret; ++} +diff --git a/src/util/virxml.h b/src/util/virxml.h +index 364288d..bb34069 100644 +--- a/src/util/virxml.h ++++ b/src/util/virxml.h +@@ -163,4 +163,6 @@ int virXMLSaveFile(const char *path, + const char *warnCommand, + const char *xml); + ++char *virXMLNodeToString(xmlDocPtr doc, xmlNodePtr node); ++ + #endif /* __VIR_XML_H__ */ +-- +2.2.1 + diff --git a/SOURCES/libvirt-util-check-for-an-illegal-character-in-a-XML-namespace-prefix.patch b/SOURCES/libvirt-util-check-for-an-illegal-character-in-a-XML-namespace-prefix.patch new file mode 100644 index 0000000..b896edc --- /dev/null +++ b/SOURCES/libvirt-util-check-for-an-illegal-character-in-a-XML-namespace-prefix.patch @@ -0,0 +1,44 @@ +From 28894754f079527609645607bb44fb268259bf2c Mon Sep 17 00:00:00 2001 +Message-Id: <28894754f079527609645607bb44fb268259bf2c@dist-git> +From: Erik Skultety +Date: Thu, 22 Jan 2015 15:53:57 +0100 +Subject: [PATCH] util: check for an illegal character in a XML namespace + prefix + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +When user tries to insert element metadata providing a namespace +declaration as well, currently we insert the element without any validation +check for XML prefix (if provided). The next VM start would then +fail with parse error. This patch fixes this issue by adding a call to +xmlValidateNCName function to check for illegal characters in the +prefix. +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1143921 + +(cherry picked from commit 2c22954f99a70ed654e4116a18f433afa24d41c5) + +Signed-off-by: Jiri Denemark +--- + src/util/virxml.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/util/virxml.c b/src/util/virxml.c +index 88a1196..88c1fcc 100644 +--- a/src/util/virxml.c ++++ b/src/util/virxml.c +@@ -1074,6 +1074,12 @@ virXMLInjectNamespace(xmlNodePtr node, + { + xmlNsPtr ns; + ++ if (xmlValidateNCName((const unsigned char *)key, 1) != 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to validate prefix for a new XML namespace")); ++ return -1; ++ } ++ + if (!(ns = xmlNewNs(node, (const unsigned char *)uri, (const unsigned char *)key))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to create a new XML namespace")); +-- +2.2.1 + diff --git a/SOURCES/libvirt-virsh-Don-t-shadow-global-variable-remove-in-cmdMetadata.patch b/SOURCES/libvirt-virsh-Don-t-shadow-global-variable-remove-in-cmdMetadata.patch new file mode 100644 index 0000000..614b760 --- /dev/null +++ b/SOURCES/libvirt-virsh-Don-t-shadow-global-variable-remove-in-cmdMetadata.patch @@ -0,0 +1,52 @@ +From 63f44f163b462a7dffefa927df771fcc88ab603f Mon Sep 17 00:00:00 2001 +Message-Id: <63f44f163b462a7dffefa927df771fcc88ab603f@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:53 +0100 +Subject: [PATCH] virsh: Don't shadow global variable "remove" in cmdMetadata + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +Some systems apparently have a global variable/function called remove +and thus break compilation of virsh-domain.c. Rename the variable to +avoid this. + +Reported by GuanQiang. + +(cherry picked from commit 6bf4c779841f858872003ffe6a97df395b2940e6) + +Signed-off-by: Jiri Denemark +--- + tools/virsh-domain.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index a2796e5..dd697f9 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -6894,7 +6894,7 @@ cmdMetadata(vshControl *ctl, const vshCmd *cmd) + bool live = vshCommandOptBool(cmd, "live"); + bool current = vshCommandOptBool(cmd, "current"); + bool edit = vshCommandOptBool(cmd, "edit"); +- bool remove = vshCommandOptBool(cmd, "remove"); ++ bool rem = vshCommandOptBool(cmd, "remove"); + const char *set = NULL; + const char *uri = NULL; + const char *key = NULL; +@@ -6926,12 +6926,12 @@ cmdMetadata(vshControl *ctl, const vshCmd *cmd) + goto cleanup; + } + +- if (set || remove) { ++ if (set || rem) { + if (virDomainSetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, + set, key, uri, flags)) + goto cleanup; + +- if (remove) ++ if (rem) + vshPrint("%s\n", _("Metadata removed")); + else + vshPrint("%s\n", _("Metadata modified")); +-- +2.2.1 + diff --git a/SOURCES/libvirt-virsh-domain-Add-command-to-allow-modifications-of-XML-metadata.patch b/SOURCES/libvirt-virsh-domain-Add-command-to-allow-modifications-of-XML-metadata.patch new file mode 100644 index 0000000..53b1f65 --- /dev/null +++ b/SOURCES/libvirt-virsh-domain-Add-command-to-allow-modifications-of-XML-metadata.patch @@ -0,0 +1,201 @@ +From 7aa95972f21eb0b39c06909360bcf8b51171b263 Mon Sep 17 00:00:00 2001 +Message-Id: <7aa95972f21eb0b39c06909360bcf8b51171b263@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:44 +0100 +Subject: [PATCH] virsh-domain: Add command to allow modifications of XML + metadata + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +The metadata modification functions will support modification of the XML +metadata. Add a virsh command to allow using this approach. + +(cherry picked from commit 01b03f59e76865feed3097cbe6dc0a809caccc14) + +Signed-off-by: Jiri Denemark +--- + tools/virsh-domain.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 161 insertions(+) + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index 6076e8d..a2796e5 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -6813,6 +6813,161 @@ cleanup: + return ret; + } + ++ ++static const vshCmdInfo info_metadata[] = { ++ {.name = "help", ++ .data = N_("show or set domain's custom XML metadata") ++ }, ++ {.name = "desc", ++ .data = N_("Shows or modifies the XML metadata of a domain.") ++ }, ++ {.name = NULL} ++}; ++ ++static const vshCmdOptDef opts_metadata[] = { ++ {.name = "domain", ++ .type = VSH_OT_DATA, ++ .flags = VSH_OFLAG_REQ, ++ .help = N_("domain name, id or uuid") ++ }, ++ {.name = "live", ++ .type = VSH_OT_BOOL, ++ .help = N_("modify/get running state") ++ }, ++ {.name = "config", ++ .type = VSH_OT_BOOL, ++ .help = N_("modify/get persistent configuration") ++ }, ++ {.name = "current", ++ .type = VSH_OT_BOOL, ++ .help = N_("modify/get current state configuration") ++ }, ++ {.name = "edit", ++ .type = VSH_OT_BOOL, ++ .help = N_("use an editor to change the metadata") ++ }, ++ {.name = "uri", ++ .type = VSH_OT_DATA, ++ .flags = VSH_OFLAG_REQ, ++ .help = N_("URI of the namespace") ++ }, ++ {.name = "key", ++ .type = VSH_OT_DATA, ++ .help = N_("key to be used as a namespace identifier"), ++ }, ++ {.name = "set", ++ .type = VSH_OT_DATA, ++ .help = N_("new metadata to set"), ++ }, ++ {.name = "remove", ++ .type = VSH_OT_BOOL, ++ .help = N_("remove the metadata corresponding to an uri") ++ }, ++ {.name = NULL} ++}; ++ ++ ++/* helper to add new metadata using the --edit option */ ++static char * ++vshDomainGetEditMetadata(vshControl *ctl, ++ virDomainPtr dom, ++ const char *uri, ++ unsigned int flags) ++{ ++ char *ret; ++ ++ if (!(ret = virDomainGetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, ++ uri, flags))) { ++ vshResetLibvirtError(); ++ ret = vshStrdup(ctl, "\n"); ++ } ++ ++ return ret; ++} ++ ++ ++static bool ++cmdMetadata(vshControl *ctl, const vshCmd *cmd) ++{ ++ virDomainPtr dom; ++ bool config = vshCommandOptBool(cmd, "config"); ++ bool live = vshCommandOptBool(cmd, "live"); ++ bool current = vshCommandOptBool(cmd, "current"); ++ bool edit = vshCommandOptBool(cmd, "edit"); ++ bool remove = vshCommandOptBool(cmd, "remove"); ++ const char *set = NULL; ++ const char *uri = NULL; ++ const char *key = NULL; ++ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT; ++ bool ret = false; ++ ++ VSH_EXCLUSIVE_OPTIONS_VAR(current, live); ++ VSH_EXCLUSIVE_OPTIONS_VAR(current, config); ++ VSH_EXCLUSIVE_OPTIONS("edit", "set"); ++ VSH_EXCLUSIVE_OPTIONS("remove", "set"); ++ VSH_EXCLUSIVE_OPTIONS("remove", "edit"); ++ ++ if (config) ++ flags |= VIR_DOMAIN_AFFECT_CONFIG; ++ if (live) ++ flags |= VIR_DOMAIN_AFFECT_LIVE; ++ ++ if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) ++ return false; ++ ++ if (vshCommandOptStringReq(ctl, cmd, "uri", &uri) < 0 || ++ vshCommandOptStringReq(ctl, cmd, "key", &key) < 0 || ++ vshCommandOptStringReq(ctl, cmd, "set", &set) < 0) ++ goto cleanup; ++ ++ if ((set || edit) && !key) { ++ vshError(ctl, "%s", ++ _("namespace key is required when modifying metadata")); ++ goto cleanup; ++ } ++ ++ if (set || remove) { ++ if (virDomainSetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, ++ set, key, uri, flags)) ++ goto cleanup; ++ ++ if (remove) ++ vshPrint("%s\n", _("Metadata removed")); ++ else ++ vshPrint("%s\n", _("Metadata modified")); ++ } else if (edit) { ++#define EDIT_GET_XML \ ++ vshDomainGetEditMetadata(ctl, dom, uri, flags) ++#define EDIT_NOT_CHANGED \ ++ vshPrint(ctl, "%s", _("Metadata not changed")); \ ++ ret = true; \ ++ goto edit_cleanup; ++#define EDIT_DEFINE \ ++ (virDomainSetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, doc_edited, \ ++ key, uri, flags) == 0) ++#define EDIT_FREE /* nothing */ ++#include "virsh-edit.c" ++ ++ vshPrint("%s\n", _("Metadata modified")); ++ } else { ++ char *data; ++ /* get */ ++ if (!(data = virDomainGetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, ++ uri, flags))) ++ goto cleanup; ++ ++ vshPrint(ctl, "%s\n", data); ++ VIR_FREE(data); ++ } ++ ++ ret = true; ++ ++cleanup: ++ virDomainFree(dom); ++ return ret; ++} ++ ++ + /* + * "inject-nmi" command + */ +@@ -10603,6 +10758,12 @@ const vshCmdDef domManagementCmds[] = { + .info = info_memtune, + .flags = 0 + }, ++ {.name = "metadata", ++ .handler = cmdMetadata, ++ .opts = opts_metadata, ++ .info = info_metadata, ++ .flags = 0 ++ }, + {.name = "migrate", + .handler = cmdMigrate, + .opts = opts_migrate, +-- +2.2.1 + diff --git a/SOURCES/libvirt-virsh-domain-use-virXMLNodeToString-instead-of-xmlNodeDump.patch b/SOURCES/libvirt-virsh-domain-use-virXMLNodeToString-instead-of-xmlNodeDump.patch new file mode 100644 index 0000000..4c0d45b --- /dev/null +++ b/SOURCES/libvirt-virsh-domain-use-virXMLNodeToString-instead-of-xmlNodeDump.patch @@ -0,0 +1,292 @@ +From 502cf493c7832a3ea5a4cd20dea289d291c7c56b Mon Sep 17 00:00:00 2001 +Message-Id: <502cf493c7832a3ea5a4cd20dea289d291c7c56b@dist-git> +From: Peter Krempa +Date: Thu, 22 Jan 2015 15:53:43 +0100 +Subject: [PATCH] virsh-domain: use virXMLNodeToString instead of xmlNodeDump + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +(cherry picked from commit 3df33d7ad52d27bf9a41ab07e2c0ab631364ae04) + +Conflicts: + tools/virsh-domain.c - context + +Signed-off-by: Jiri Denemark +--- + tools/virsh-domain.c | 113 +++++++++++++-------------------------------------- + 1 file changed, 29 insertions(+), 84 deletions(-) + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index 03f96fb..6076e8d 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -2356,7 +2356,7 @@ cmdDomIfSetLink(vshControl *ctl, const vshCmd *cmd) + xmlXPathContextPtr ctxt = NULL; + xmlXPathObjectPtr obj = NULL; + xmlNodePtr cur = NULL; +- xmlBufferPtr xml_buf = NULL; ++ char *xml_buf = NULL; + + if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) + return false; +@@ -2461,18 +2461,13 @@ hit: + goto cleanup; + } + +- xml_buf = xmlBufferCreate(); +- if (!xml_buf) { +- vshError(ctl, _("Failed to allocate memory")); +- goto cleanup; +- } +- +- if (xmlNodeDump(xml_buf, xml, obj->nodesetval->nodeTab[i], 0, 0) < 0) { ++ if (!(xml_buf = virXMLNodeToString(xml, obj->nodesetval->nodeTab[i]))) { ++ vshSaveLibvirtError(); + vshError(ctl, _("Failed to create XML")); + goto cleanup; + } + +- if (virDomainUpdateDeviceFlags(dom, (char *)xmlBufferContent(xml_buf), flags) < 0) { ++ if (virDomainUpdateDeviceFlags(dom, xml_buf, flags) < 0) { + vshError(ctl, _("Failed to update interface link state")); + goto cleanup; + } else { +@@ -2484,10 +2479,8 @@ cleanup: + xmlXPathFreeObject(obj); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); +- xmlBufferFree(xml_buf); +- +- if (dom) +- virDomainFree(dom); ++ VIR_FREE(xml_buf); ++ virDomainFree(dom); + + return ret; + } +@@ -6092,11 +6085,10 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) + bool ret = false; + char *buffer; + int result; +- const char *snippet; ++ char *snippet = NULL; + + xmlDocPtr xml = NULL; + xmlXPathContextPtr ctxt = NULL; +- xmlBufferPtr xml_buf = NULL; + xmlNodePtr node; + + if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) +@@ -6112,17 +6104,10 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) + if ((node = virXPathNode("/cpu|" + "/domain/cpu|" + "/capabilities/host/cpu", ctxt))) { +- if (!(xml_buf = xmlBufferCreate())) { +- vshError(ctl, _("Can't create XML buffer to extract CPU element.")); ++ if (!(snippet = virXMLNodeToString(xml, node))) { ++ vshSaveLibvirtError(); + goto cleanup; + } +- +- if (xmlNodeDump(xml_buf, xml, node, 0, 0) < 0) { +- vshError(ctl, _("Failed to extract CPU element snippet from domain XML.")); +- goto cleanup; +- } +- +- snippet = (const char *) xmlBufferContent(xml_buf); + } else { + vshError(ctl, _("File '%s' does not contain a element or is not " + "a valid domain or capabilities XML"), from); +@@ -6158,7 +6143,7 @@ cmdCPUCompare(vshControl *ctl, const vshCmd *cmd) + + cleanup: + VIR_FREE(buffer); +- xmlBufferFree(xml_buf); ++ VIR_FREE(snippet); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); + +@@ -6200,7 +6185,6 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) + xmlDocPtr xml = NULL; + xmlNodePtr *node_list = NULL; + xmlXPathContextPtr ctxt = NULL; +- xmlBufferPtr xml_buf = NULL; + virBuffer buf = VIR_BUFFER_INITIALIZER; + size_t i; + +@@ -6233,18 +6217,11 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) + + list = vshCalloc(ctl, count, sizeof(const char *)); + +- if (!(xml_buf = xmlBufferCreate())) +- goto no_memory; +- + for (i = 0; i < count; i++) { +- xmlBufferEmpty(xml_buf); +- +- if (xmlNodeDump(xml_buf, xml, node_list[i], 0, 0) < 0) { +- vshError(ctl, _("Failed to extract element")); ++ if (!(list[i] = virXMLNodeToString(xml, node_list[i]))) { ++ vshSaveLibvirtError(); + goto cleanup; + } +- +- list[i] = vshStrdup(ctl, (const char *)xmlBufferContent(xml_buf)); + } + + result = virConnectBaselineCPU(ctl->conn, list, count, 0); +@@ -6257,7 +6234,6 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) + cleanup: + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); +- xmlBufferFree(xml_buf); + VIR_FREE(result); + if (list != NULL && count > 0) { + for (i = 0; i < count; i++) +@@ -9633,7 +9609,7 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) + xmlXPathObjectPtr obj=NULL; + xmlXPathContextPtr ctxt = NULL; + xmlNodePtr cur = NULL, matchNode = NULL; +- xmlBufferPtr xml_buf = NULL; ++ char *detach_xml = NULL; + const char *mac =NULL, *type = NULL; + char *doc = NULL; + char buf[64]; +@@ -9726,25 +9702,16 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) + goto cleanup; + } + +- hit: +- xml_buf = xmlBufferCreate(); +- if (!xml_buf) { +- vshError(ctl, "%s", _("Failed to allocate memory")); ++hit: ++ if (!(detach_xml = virXMLNodeToString(xml, matchNode))) { ++ vshSaveLibvirtError(); + goto cleanup; + } + +- if (xmlNodeDump(xml_buf, xml, matchNode, 0, 0) < 0) { +- vshError(ctl, "%s", _("Failed to create XML")); +- goto cleanup; +- } +- +- if (flags != 0 || current) { +- ret = virDomainDetachDeviceFlags(dom, +- (char *)xmlBufferContent(xml_buf), +- flags); +- } else { +- ret = virDomainDetachDevice(dom, (char *)xmlBufferContent(xml_buf)); +- } ++ if (flags != 0) ++ ret = virDomainDetachDeviceFlags(dom, detach_xml, flags); ++ else ++ ret = virDomainDetachDevice(dom, detach_xml); + + if (ret != 0) { + vshError(ctl, "%s", _("Failed to detach interface")); +@@ -9753,13 +9720,13 @@ cmdDetachInterface(vshControl *ctl, const vshCmd *cmd) + functionReturn = true; + } + +- cleanup: ++cleanup: + VIR_FREE(doc); ++ VIR_FREE(detach_xml); + virDomainFree(dom); + xmlXPathFreeObject(obj); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(xml); +- xmlBufferFree(xml_buf); + return functionReturn; + } + +@@ -9877,7 +9844,6 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + int type) + { + xmlNodePtr cur = NULL; +- xmlBufferPtr xml_buf = NULL; + const char *disk_type = NULL; + const char *device_type = NULL; + xmlNodePtr new_node = NULL; +@@ -9886,12 +9852,6 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + if (!disk_node) + return NULL; + +- xml_buf = xmlBufferCreate(); +- if (!xml_buf) { +- vshError(NULL, "%s", _("Failed to allocate memory")); +- return NULL; +- } +- + device_type = virXMLPropString(disk_node, "device"); + + if (STREQ_NULLABLE(device_type, "cdrom") || +@@ -9913,7 +9873,7 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + if (type == VSH_PREPARE_DISK_XML_EJECT) { + vshError(NULL, _("The disk device '%s' doesn't have media"), + path); +- goto error; ++ goto cleanup; + } + + if (source) { +@@ -9925,10 +9885,10 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + xmlAddChild(disk_node, new_node); + } else if (type == VSH_PREPARE_DISK_XML_INSERT) { + vshError(NULL, _("No source is specified for inserting media")); +- goto error; ++ goto cleanup; + } else if (type == VSH_PREPARE_DISK_XML_UPDATE) { + vshError(NULL, _("No source is specified for updating media")); +- goto error; ++ goto cleanup; + } + } + +@@ -9936,7 +9896,7 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + if (type == VSH_PREPARE_DISK_XML_INSERT) { + vshError(NULL, _("The disk device '%s' already has media"), + path); +- goto error; ++ goto cleanup; + } + + /* Remove the source if it tends to eject/update media. */ +@@ -9952,30 +9912,15 @@ vshPrepareDiskXML(xmlNodePtr disk_node, + } + } + +- if (xmlNodeDump(xml_buf, NULL, disk_node, 0, 0) < 0) { +- vshError(NULL, "%s", _("Failed to create XML")); +- goto error; ++ if (!(ret = virXMLNodeToString(NULL, disk_node))) { ++ vshSaveLibvirtError(); ++ goto cleanup; + } + +- goto cleanup; +- + cleanup: + VIR_FREE(device_type); + VIR_FREE(disk_type); +- if (xml_buf) { +- int len = xmlBufferLength(xml_buf); +- if (VIR_ALLOC_N(ret, len + 1) < 0) +- return NULL; +- memcpy(ret, (char *)xmlBufferContent(xml_buf), len); +- ret[len] = '\0'; +- xmlBufferFree(xml_buf); +- } + return ret; +- +-error: +- xmlBufferFree(xml_buf); +- xml_buf = NULL; +- goto cleanup; + } + + +-- +2.2.1 + diff --git a/SOURCES/libvirt-virsh-man-Crosslink-desc-and-metadata-sections.patch b/SOURCES/libvirt-virsh-man-Crosslink-desc-and-metadata-sections.patch new file mode 100644 index 0000000..33d7ff9 --- /dev/null +++ b/SOURCES/libvirt-virsh-man-Crosslink-desc-and-metadata-sections.patch @@ -0,0 +1,42 @@ +From 913b0f1385085b9a0a17f835fa56b1ccd2ad65c6 Mon Sep 17 00:00:00 2001 +Message-Id: <913b0f1385085b9a0a17f835fa56b1ccd2ad65c6@dist-git> +From: Peter Krempa +Date: Wed, 28 Jan 2015 10:33:40 +0100 +Subject: [PATCH] virsh: man: Crosslink "desc" and "metadata" sections + +https://bugzilla.redhat.com/show_bug.cgi?id=1184929 + +Those two commands work with a single API so cross-link them. + +(cherry picked from commit c68ae7f61155891651081e523c5576e719f932eb) + +Signed-off-by: Jiri Denemark +--- + tools/virsh.pod | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/virsh.pod b/tools/virsh.pod +index c3ae204..d0dbbca 100644 +--- a/tools/virsh.pod ++++ b/tools/virsh.pod +@@ -581,6 +581,7 @@ effect on the next boot. + Show or modify description and title of a domain. These values are user + fields that allow to store arbitrary textual data to allow easy + identification of domains. Title should be short, although it's not enforced. ++(See also B that works with XML based domain metadata.) + + Flags I<--live> or I<--config> select whether this command works on live + or persistent definitions of the domain. If both I<--live> and I<--config> +@@ -1080,7 +1081,8 @@ Show or modify custom XML metadata of a domain. The metadata is a user + defined XML that allows to store arbitrary XML data in the domain definition. + Multiple separate custom metadata pieces can be stored in the domain XML. + The pieces are identified by a private XML namespace provided via the +-I argument. ++I argument. (See also B that works with textual metadata of ++a domain.) + + Flags I<--live> or I<--config> select whether this command works on live + or persistent definitions of the domain. If both I<--live> and I<--config> +-- +2.2.2 + diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec index d8dc72e..61c1952 100644 --- a/SPECS/libvirt.spec +++ b/SPECS/libvirt.spec @@ -379,7 +379,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 1.1.1 -Release: 29%{?dist}.4%{?extra_release} +Release: 29%{?dist}.7%{?extra_release} License: LGPLv2+ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -911,6 +911,35 @@ Patch518: libvirt-qemu-copy-Accept-format-parameter-when-copying-to-a-non-existi Patch519: libvirt-qemu-reject-rather-than-hang-on-blockcommit-of-active-layer.patch Patch520: libvirt-CVE-2014-7823-dumpxml-security-hole-with-migratable-flag.patch Patch521: libvirt-Fix-crash-when-saving-a-domain-with-type-none-dac-label.patch +Patch522: libvirt-conf-Format-interface-s-driver-more-frequently.patch +Patch523: libvirt-qemu-Factor-out-body-of-qemuDomainGetMetadata-for-universal-use.patch +Patch524: libvirt-qemu-Factor-out-body-of-qemuDomainSetMetadata-for-universal-use.patch +Patch525: libvirt-conf-Factor-out-setting-of-metadata-to-simplify-code.patch +Patch526: libvirt-util-Add-helper-to-convert-libxml2-nodes-to-a-string.patch +Patch527: libvirt-virsh-domain-use-virXMLNodeToString-instead-of-xmlNodeDump.patch +Patch528: libvirt-virsh-domain-Add-command-to-allow-modifications-of-XML-metadata.patch +Patch529: libvirt-conf-Add-support-for-requesting-of-XML-metadata-via-the-API.patch +Patch530: libvirt-conf-allow-to-add-XML-metadata-using-the-virDomainSetMetadata-api.patch +Patch531: libvirt-lib-Don-t-force-the-key-argument-when-deleting-metadata.patch +Patch532: libvirt-lxc-Add-metadata-modification-APIs.patch +Patch533: libvirt-test-Add-metadata-support-into-the-test-driver.patch +Patch534: libvirt-tests-Add-metadata-tests.patch +Patch535: libvirt-conf-Don-t-corrupt-metadata-on-OOM.patch +Patch536: libvirt-conf-Avoid-false-positive-of-uninitialized-variable-use.patch +Patch537: libvirt-virsh-Don-t-shadow-global-variable-remove-in-cmdMetadata.patch +Patch538: libvirt-metadata-track-title-edits-across-libvirtd-restart.patch +Patch539: libvirt-conf-Improve-metadata-type-verification.patch +Patch540: libvirt-Fix-possible-memory-leak-in-util-virxml.c.patch +Patch541: libvirt-util-check-for-an-illegal-character-in-a-XML-namespace-prefix.patch +Patch542: libvirt-Fix-libvirtd-crash-when-removing-metadata.patch +Patch543: libvirt-Add-invariant-TSC-cpu-flag.patch +Patch544: libvirt-cpu_x86-Resolve-Coverity-RESOURCE_LEAK.patch +Patch545: libvirt-Don-t-include-non-migratable-features-in-host-model.patch +Patch546: libvirt-Fix-leak-in-x86UpdateHostModel.patch +Patch547: libvirt-Also-filter-out-non-migratable-features-out-of-host-passthrough.patch +Patch548: libvirt-man-virsh-Add-man-page-for-virsh-metadata.patch +Patch549: libvirt-virsh-man-Crosslink-desc-and-metadata-sections.patch +Patch550: libvirt-Fix-segfault-when-starting-a-domain-with-no-cpu-definition.patch %if %{with_libvirtd} @@ -2704,6 +2733,41 @@ exit 0 %endif %changelog +* Thu Jan 29 2015 Jiri Denemark - 1.1.1-29.el7_0.7 +- Fix segfault when starting a domain with no cpu definition (rhbz#1185458) + +* Wed Jan 28 2015 Jiri Denemark - 1.1.1-29.el7_0.6 +- Add invariant TSC cpu flag (rhbz#1185458) +- cpu_x86: Resolve Coverity RESOURCE_LEAK (rhbz#1185458) +- Don't include non-migratable features in host-model (rhbz#1185458) +- Fix leak in x86UpdateHostModel (rhbz#1185458) +- Also filter out non-migratable features out of host-passthrough (rhbz#1185458) +- man: virsh: Add man page for "virsh metadata" (rhbz#1184929) +- virsh: man: Crosslink "desc" and "metadata" sections (rhbz#1184929) + +* Fri Jan 23 2015 Jiri Denemark - 1.1.1-29.el7_0.5 +- conf: Format interface's driver more frequently (rhbz#1183447) +- qemu: Factor out body of qemuDomainGetMetadata for universal use (rhbz#1184929) +- qemu: Factor out body of qemuDomainSetMetadata for universal use (rhbz#1184929) +- conf: Factor out setting of metadata to simplify code (rhbz#1184929) +- util: Add helper to convert libxml2 nodes to a string (rhbz#1184929) +- virsh-domain: use virXMLNodeToString instead of xmlNodeDump (rhbz#1184929) +- virsh-domain: Add command to allow modifications of XML metadata (rhbz#1184929) +- conf: Add support for requesting of XML metadata via the API (rhbz#1184929) +- conf: allow to add XML metadata using the virDomainSetMetadata api (rhbz#1184929) +- lib: Don't force the key argument when deleting metadata (rhbz#1184929) +- lxc: Add metadata modification APIs (rhbz#1184929) +- test: Add support into the test driver (rhbz#1184929) +- tests: Add metadata tests (rhbz#1184929) +- conf: Don't corrupt metadata on OOM (rhbz#1184929) +- conf: Avoid false positive of uninitialized variable use (rhbz#1184929) +- virsh: Don't shadow global variable "remove" in cmdMetadata (rhbz#1184929) +- metadata: track title edits across libvirtd restart (rhbz#1184929) +- conf: Improve metadata type verification (rhbz#1184929) +- Fix possible memory leak in util/virxml.c (rhbz#1184929) +- util: check for an illegal character in a XML namespace prefix (rhbz#1184929) +- Fix libvirtd crash when removing metadata (rhbz#1184929) + * Tue Dec 9 2014 Jiri Denemark - 1.1.1-29.el7_0.4 - qemu: blockcopy: Don't remove existing disk mirror info (rhbz#1149078) - qemu: copy: Accept 'format' parameter when copying to a non-existing img (rhbz#1149078)