[libvirt] [PATCH] virstoragefile: identify GPFS as cluster FS
by Diego Michelotto
GPFS is 'IBM General Parallel File System', also called
'IBM Spectrum Scale', stalls when a process issues a lot
of fsyncs in a short timeframe.
It is better if the VM I/O is not synchronous.
It is racommended to use writeback caching policy.
In order to permit that it is added VIR_FILE_SHFS_GPFS to
the list of shared file systems in virStorageFileIsClusterFS
function.
Signed-off-by: Diego Michelotto <diego.michelotto(a)cnaf.infn.it>
---
src/util/virstoragefile.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index b2e308d81d..0fe2819dc6 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1349,7 +1349,8 @@ int virStorageFileIsClusterFS(const char *path)
return virFileIsSharedFSType(path,
VIR_FILE_SHFS_GFS2 |
VIR_FILE_SHFS_OCFS |
- VIR_FILE_SHFS_CEPH);
+ VIR_FILE_SHFS_CEPH |
+ VIR_FILE_SHFS_GPFS);
}
#ifdef LVS
--
2.20.1
5 years, 8 months
[libvirt] [PATCH 0/2] qemu: Allow creating ppc64 guests with graphics and no USB mouse
by Andrea Bolognani
See patch 2/2.
Andrea Bolognani (2):
tests: Add simple guests with graphics to qemuxml2argv
qemu: Allow creating ppc64 guests with graphics and no USB mouse
src/qemu/qemu_domain.c | 20 +++++++
.../aarch64-virt-graphics.aarch64-latest.args | 59 +++++++++++++++++++
.../aarch64-virt-graphics.xml | 50 ++++++++++++++++
.../ppc64-pseries-graphics.ppc64-latest.args | 47 +++++++++++++++
.../ppc64-pseries-graphics.xml | 44 ++++++++++++++
.../x86_64-pc-graphics.x86_64-latest.args | 51 ++++++++++++++++
tests/qemuxml2argvdata/x86_64-pc-graphics.xml | 55 +++++++++++++++++
.../x86_64-q35-graphics.x86_64-latest.args | 59 +++++++++++++++++++
.../qemuxml2argvdata/x86_64-q35-graphics.xml | 55 +++++++++++++++++
tests/qemuxml2argvtest.c | 6 ++
10 files changed, 446 insertions(+)
create mode 100644 tests/qemuxml2argvdata/aarch64-virt-graphics.aarch64-latest.args
create mode 100644 tests/qemuxml2argvdata/aarch64-virt-graphics.xml
create mode 100644 tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args
create mode 100644 tests/qemuxml2argvdata/ppc64-pseries-graphics.xml
create mode 100644 tests/qemuxml2argvdata/x86_64-pc-graphics.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/x86_64-pc-graphics.xml
create mode 100644 tests/qemuxml2argvdata/x86_64-q35-graphics.x86_64-latest.args
create mode 100644 tests/qemuxml2argvdata/x86_64-q35-graphics.xml
--
2.20.1
5 years, 8 months
[libvirt] [PATCH] conf: fix title and description for virDomainSetMetadata API
by Pavel Hrdina
If we pass XML to virDomainDefineXML API with these two elements:
...
<title></title>
<description></description>
...
libvirt correctly ignores these two elements and they will not appear
in the parsed XML.
However, if we use virDomainSetMetadata API and with "" as value for
title or description we will end up with the parsed XML that contains
these empty elements.
Let's fix the behavior of this API to behave the same as
virDomainDefineXML.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1518042
Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
---
src/conf/domain_conf.c | 6 +++---
tests/metadatatest.c | 23 ++++++++++++++++-------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 477deb777e..2fba58e5c4 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30363,7 +30363,7 @@ virDomainDefSetMetadata(virDomainDefPtr def,
xmlDocPtr doc = NULL;
xmlNodePtr old;
xmlNodePtr new = NULL;
- char *tmp;
+ char *tmp = NULL;
int ret = -1;
if (type >= VIR_DOMAIN_METADATA_LAST) {
@@ -30374,7 +30374,7 @@ virDomainDefSetMetadata(virDomainDefPtr def,
switch ((virDomainMetadataType) type) {
case VIR_DOMAIN_METADATA_DESCRIPTION:
- if (VIR_STRDUP(tmp, metadata) < 0)
+ if (STRNEQ_NULLABLE(metadata, "") && VIR_STRDUP(tmp, metadata) < 0)
goto cleanup;
VIR_FREE(def->description);
@@ -30382,7 +30382,7 @@ virDomainDefSetMetadata(virDomainDefPtr def,
break;
case VIR_DOMAIN_METADATA_TITLE:
- if (VIR_STRDUP(tmp, metadata) < 0)
+ if (STRNEQ_NULLABLE(metadata, "") && VIR_STRDUP(tmp, metadata) < 0)
goto cleanup;
VIR_FREE(def->title);
diff --git a/tests/metadatatest.c b/tests/metadatatest.c
index 786c62e623..a9080b32d7 100644
--- a/tests/metadatatest.c
+++ b/tests/metadatatest.c
@@ -167,6 +167,7 @@ struct metadataTest {
virDomainPtr dom;
const char *data;
+ const char *expect;
int type;
bool fail;
};
@@ -232,7 +233,7 @@ testTextMetadata(const void *data)
actual = virDomainGetMetadata(test->dom, test->type, NULL, 0);
- if (STRNEQ_NULLABLE(test->data, actual)) {
+ if (STRNEQ_NULLABLE(test->expect, actual)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"expected metadata doesn't match actual: "
"expected:'%s'\ngot: '%s'",
@@ -248,10 +249,11 @@ testTextMetadata(const void *data)
return ret;
}
-#define TEST_TEXT_METADATA(INDEX, TYPE, DATA, FAIL) \
+#define TEST_TEXT_METADATA(INDEX, TYPE, DATA, EXPECT, FAIL) \
do { \
test.type = VIR_DOMAIN_METADATA_ ## TYPE; \
test.data = DATA; \
+ test.expect = EXPECT; \
test.fail = FAIL; \
\
if (virTestRun("text metadata: " #TYPE " " INDEX " ", \
@@ -259,9 +261,16 @@ testTextMetadata(const void *data)
ret = EXIT_FAILURE; \
} while (0)
-#define TEST_TITLE(INDEX, DATA) TEST_TEXT_METADATA(INDEX, TITLE, DATA, false)
-#define TEST_TITLE_FAIL(INDEX, DATA) TEST_TEXT_METADATA(INDEX, TITLE, DATA, true)
-#define TEST_DESCR(INDEX, DATA) TEST_TEXT_METADATA(INDEX, DESCRIPTION, DATA, false)
+#define TEST_TITLE(INDEX, DATA) \
+ TEST_TEXT_METADATA(INDEX, TITLE, DATA, DATA, false)
+#define TEST_TITLE_EXPECT(INDEX, DATA, EXPECT) \
+ TEST_TEXT_METADATA(INDEX, TITLE, DATA, EXPECT, false)
+#define TEST_TITLE_FAIL(INDEX, DATA) \
+ TEST_TEXT_METADATA(INDEX, TITLE, DATA, DATA, true)
+#define TEST_DESCR(INDEX, DATA) \
+ TEST_TEXT_METADATA(INDEX, DESCRIPTION, DATA, DATA, false)
+#define TEST_DESCR_EXPECT(INDEX, DATA, EXPECT) \
+ TEST_TEXT_METADATA(INDEX, DESCRIPTION, DATA, EXPECT, false)
static int
mymain(void)
@@ -290,7 +299,7 @@ mymain(void)
TEST_TITLE("2", NULL);
TEST_TITLE("3", "blah");
TEST_TITLE_FAIL("4", "qwe\nrt");
- TEST_TITLE("5", "");
+ TEST_TITLE_EXPECT("5", "", NULL);
TEST_TITLE_FAIL("6", "qwert\n");
TEST_TITLE_FAIL("7", "\n");
@@ -298,7 +307,7 @@ mymain(void)
TEST_DESCR("2", NULL);
TEST_DESCR("3", "qwert");
TEST_DESCR("4", "\n");
- TEST_DESCR("5", "");
+ TEST_DESCR_EXPECT("5", "", NULL);
virDomainFree(test.dom);
virConnectClose(test.conn);
--
2.20.1
5 years, 8 months
[libvirt] [PATCH 0/2] ui: support for authorization control on TLS connections
by Daniel P. Berrangé
This series provides the VNC parts of the authorization control series
previously posted as:
v1: https://lists.gnu.org/archive/html/qemu-devel/2018-06/msg04482.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2018-06/msg05727.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg01639.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2019-02/msg04319.html
The core authz framework is now merged & these patches have all had
positive review. Thus these VNC parts are ready to go into the VNC
maintainer's tree, should the maintainer consider them acceptable.
Note the 2nd patch is modifying the HMP, but I considered it part
of ui/vnc, since that's the only bit of QEMU which ever used these
HMP commands, and it has a dependancy on the first patch merging
first.
Daniel P. Berrangé (2):
vnc: allow specifying a custom authorization object name
monitor: deprecate acl_show, acl_reset, acl_policy, acl_add,
acl_remove
monitor.c | 23 ++++++++++++++++++
qemu-deprecated.texi | 11 +++++++++
qemu-options.hx | 35 ++++++++++++++++++--------
ui/vnc.c | 58 +++++++++++++++++++++++++++++++++++++-------
4 files changed, 108 insertions(+), 19 deletions(-)
--
2.20.1
5 years, 8 months
[libvirt] [PATCH 0/8] qemu: separate out deprecated capabilities
by Ján Tomko
Ján Tomko (8):
DO NOT PUSH: allow skipping selected lines in group-qemu-caps.pl
Introduce virQEMUCapsDeprecated array
Split out virQEMUCapsSetFromNodes
Use virQEMUCapsSetFromNodes where possible
qemustatusxml2xmltests: remove deprecated qemu capabilities
virQEMUCapsSetFromNodes: Skip setting deprecated flags
Delete deprecated qemu capabilities from the enum
DO NOT PUSH: fix capabilities grouping
src/qemu/qemu_capabilities.c | 452 +++++++++---------
src/qemu/qemu_capabilities.h | 305 ++++--------
src/qemu/qemu_domain.c | 16 +-
tests/group-qemu-caps.pl | 21 +
tests/qemucaps2xmltest.c | 17 +-
.../blockjob-mirror-in.xml | 1 -
.../disk-secinfo-upgrade-out.xml | 51 --
.../migration-in-params-in.xml | 53 --
.../migration-out-nbd-out.xml | 51 --
.../migration-out-nbd-tls-in.xml | 51 --
.../migration-out-params-in.xml | 53 --
tests/qemustatusxml2xmldata/modern-in.xml | 51 --
.../qemustatusxml2xmldata/vcpus-multi-in.xml | 1 -
13 files changed, 339 insertions(+), 784 deletions(-)
--
2.19.2
5 years, 8 months
[libvirt] [PATCH 0/4] implement cgroups v2 cpuset controller support
by Pavel Hrdina
Pavel Hrdina (4):
util: implement virCgroupV2(Set|Get)CpusetMems
util: implement virCgroupV2(Set|Get)CpusetMemoryMigrate
util: implement virCgroupV2(Set|Get)CpusetCpus
util: enable cgroups v2 cpuset controller for threads
src/util/vircgroupv2.c | 74 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
--
2.20.1
5 years, 8 months
[libvirt] [PATCH] Drop some useless comparisons and checks
by Michal Privoznik
In these cases the check that is removed has been done a few
lines above already (as can even be seen in the context). Drop
them.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
examples/dommigrate/dommigrate.c | 3 +--
src/conf/nwfilter_conf.c | 4 +---
src/qemu/qemu_command.c | 3 +--
src/qemu/qemu_hotplug.c | 20 +++++++++-----------
src/util/virresctrl.c | 2 +-
tools/virsh-snapshot.c | 5 ++---
6 files changed, 15 insertions(+), 22 deletions(-)
diff --git a/examples/dommigrate/dommigrate.c b/examples/dommigrate/dommigrate.c
index 1b6072d138..60cfb3fb83 100644
--- a/examples/dommigrate/dommigrate.c
+++ b/examples/dommigrate/dommigrate.c
@@ -37,51 +37,50 @@ int
main(int argc, char *argv[])
{
char *src_uri, *dst_uri, *domname;
int ret = 0;
virConnectPtr conn = NULL;
virDomainPtr dom = NULL;
if (argc < 4) {
ret = usage(argv[0], 1);
goto out;
}
src_uri = argv[1];
dst_uri = argv[2];
domname = argv[3];
printf("Attempting to connect to the source hypervisor...\n");
conn = virConnectOpenAuth(src_uri, virConnectAuthPtrDefault, 0);
if (!conn) {
ret = 1;
fprintf(stderr, "No connection to the source hypervisor: %s.\n",
virGetLastErrorMessage());
goto out;
}
printf("Attempting to retrieve domain %s...\n", domname);
dom = virDomainLookupByName(conn, domname);
if (!dom) {
fprintf(stderr, "Failed to find domain %s.\n", domname);
goto cleanup;
}
printf("Attempting to migrate %s to %s...\n", domname, dst_uri);
if ((ret = virDomainMigrateToURI(dom, dst_uri,
VIR_MIGRATE_PEER2PEER,
NULL, 0)) != 0) {
fprintf(stderr, "Failed to migrate domain %s.\n", domname);
goto cleanup;
}
printf("Migration finished with success.\n");
cleanup:
if (dom != NULL)
virDomainFree(dom);
- if (conn != NULL)
- virConnectClose(conn);
+ virConnectClose(conn);
out:
return ret;
}
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index 7cad3ccc57..3f28c7b451 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -2610,128 +2610,126 @@ static virNWFilterDefPtr
virNWFilterDefParseXML(xmlXPathContextPtr ctxt)
{
virNWFilterDefPtr ret;
xmlNodePtr curr = ctxt->node;
char *uuid = NULL;
char *chain = NULL;
char *chain_pri_s = NULL;
virNWFilterEntryPtr entry;
int chain_priority;
const char *name_prefix;
if (VIR_ALLOC(ret) < 0)
return NULL;
ret->name = virXPathString("string(./@name)", ctxt);
if (!ret->name) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("filter has no name"));
goto cleanup;
}
chain_pri_s = virXPathString("string(./@priority)", ctxt);
if (chain_pri_s) {
if (virStrToLong_i(chain_pri_s, NULL, 10, &chain_priority) < 0) {
virReportError(VIR_ERR_INVALID_ARG,
_("Could not parse chain priority '%s'"),
chain_pri_s);
goto cleanup;
}
if (chain_priority < NWFILTER_MIN_FILTER_PRIORITY ||
chain_priority > NWFILTER_MAX_FILTER_PRIORITY) {
virReportError(VIR_ERR_INVALID_ARG,
_("Priority '%d' is outside valid "
"range of [%d,%d]"),
chain_priority,
NWFILTER_MIN_FILTER_PRIORITY,
NWFILTER_MAX_FILTER_PRIORITY);
goto cleanup;
}
}
chain = virXPathString("string(./@chain)", ctxt);
if (chain) {
name_prefix = virNWFilterIsAllowedChain(chain);
if (name_prefix == NULL)
goto cleanup;
ret->chainsuffix = chain;
if (chain_pri_s) {
ret->chainPriority = chain_priority;
} else {
/* assign default priority if none can be found via lookup */
- if (!name_prefix ||
- intMapGetByString(chain_priorities, name_prefix, 0,
- &ret->chainPriority) < 0) {
+ if (intMapGetByString(chain_priorities, name_prefix, 0, &ret->chainPriority) < 0) {
/* assign default chain priority */
ret->chainPriority = (NWFILTER_MAX_FILTER_PRIORITY +
NWFILTER_MIN_FILTER_PRIORITY) / 2;
}
}
chain = NULL;
} else {
if (VIR_STRDUP(ret->chainsuffix,
virNWFilterChainSuffixTypeToString(VIR_NWFILTER_CHAINSUFFIX_ROOT)) < 0)
goto cleanup;
}
uuid = virXPathString("string(./uuid)", ctxt);
ret->uuid_specified = (uuid != NULL);
if (uuid == NULL) {
if (virUUIDGenerate(ret->uuid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("unable to generate uuid"));
goto cleanup;
}
} else {
if (virUUIDParse(uuid, ret->uuid) < 0) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed uuid element"));
goto cleanup;
}
VIR_FREE(uuid);
}
curr = curr->children;
while (curr != NULL) {
if (curr->type == XML_ELEMENT_NODE) {
if (VIR_ALLOC(entry) < 0)
goto cleanup;
if (virXMLNodeNameEqual(curr, "rule")) {
if (!(entry->rule = virNWFilterRuleParse(curr))) {
virNWFilterEntryFree(entry);
goto cleanup;
}
} else if (virXMLNodeNameEqual(curr, "filterref")) {
if (!(entry->include = virNWFilterIncludeParse(curr))) {
virNWFilterEntryFree(entry);
goto cleanup;
}
}
if (entry->rule || entry->include) {
if (VIR_APPEND_ELEMENT_COPY(ret->filterEntries,
ret->nentries, entry) < 0) {
virNWFilterEntryFree(entry);
goto cleanup;
}
} else {
virNWFilterEntryFree(entry);
}
}
curr = curr->next;
}
VIR_FREE(chain);
VIR_FREE(chain_pri_s);
return ret;
cleanup:
virNWFilterDefFree(ret);
VIR_FREE(chain);
VIR_FREE(uuid);
VIR_FREE(chain_pri_s);
return NULL;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 74f34af292..ee70444bd4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4201,31 +4201,30 @@ static int
qemuBuildNVRAMCommandLine(virCommandPtr cmd,
const virDomainDef *def,
virQEMUCapsPtr qemuCaps)
{
if (!def->nvram)
return 0;
if (qemuDomainIsPSeries(def)) {
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVRAM)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("nvram device is not supported by "
"this QEMU binary"));
return -1;
}
char *optstr;
virCommandAddArg(cmd, "-global");
optstr = qemuBuildNVRAMDevStr(def->nvram);
if (!optstr)
return -1;
- if (optstr)
- virCommandAddArg(cmd, optstr);
+ virCommandAddArg(cmd, optstr);
VIR_FREE(optstr);
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("nvram device is only supported for PPC64"));
return -1;
}
return 0;
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 00dbff6b2a..19b7e6e8ea 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3502,52 +3502,50 @@ static int
qemuDomainChangeNetBridge(virDomainObjPtr vm,
virDomainNetDefPtr olddev,
virDomainNetDefPtr newdev)
{
int ret = -1;
const char *oldbridge = virDomainNetGetActualBridgeName(olddev);
const char *newbridge = virDomainNetGetActualBridgeName(newdev);
if (!oldbridge || !newbridge) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge name"));
goto cleanup;
}
VIR_DEBUG("Change bridge for interface %s: %s -> %s",
olddev->ifname, oldbridge, newbridge);
if (virNetDevExists(newbridge) != 1) {
virReportError(VIR_ERR_OPERATION_FAILED,
_("bridge %s doesn't exist"), newbridge);
goto cleanup;
}
- if (oldbridge) {
- ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
- virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
- if (ret < 0) {
- /* warn but continue - possibly the old network
- * had been destroyed and reconstructed, leaving the
- * tap device orphaned.
- */
- VIR_WARN("Unable to detach device %s from bridge %s",
- olddev->ifname, oldbridge);
- }
+ ret = virNetDevBridgeRemovePort(oldbridge, olddev->ifname);
+ virDomainAuditNet(vm, olddev, NULL, "detach", ret == 0);
+ if (ret < 0) {
+ /* warn but continue - possibly the old network
+ * had been destroyed and reconstructed, leaving the
+ * tap device orphaned.
+ */
+ VIR_WARN("Unable to detach device %s from bridge %s",
+ olddev->ifname, oldbridge);
}
ret = virNetDevBridgeAddPort(newbridge, olddev->ifname);
virDomainAuditNet(vm, NULL, newdev, "attach", ret == 0);
if (ret < 0) {
ret = virNetDevBridgeAddPort(oldbridge, olddev->ifname);
virDomainAuditNet(vm, NULL, olddev, "attach", ret == 0);
if (ret < 0) {
virReportError(VIR_ERR_OPERATION_FAILED,
_("unable to recover former state by adding port "
"to bridge %s"), oldbridge);
}
goto cleanup;
}
/* caller will replace entire olddev with newdev in domain nets list */
ret = 0;
cleanup:
return ret;
}
diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c
index 97891b2f8f..0857d4e882 100644
--- a/src/util/virresctrl.c
+++ b/src/util/virresctrl.c
@@ -2111,57 +2111,57 @@ static int
virResctrlAllocMemoryBandwidth(virResctrlInfoPtr resctrl,
virResctrlAllocPtr alloc,
virResctrlAllocPtr free)
{
size_t i;
virResctrlAllocMemBWPtr mem_bw_alloc = alloc->mem_bw;
virResctrlAllocMemBWPtr mem_bw_free = free->mem_bw;
virResctrlInfoMemBWPtr mem_bw_info = resctrl->membw_info;
if (!mem_bw_alloc)
return 0;
- if (mem_bw_alloc && !mem_bw_info) {
+ if (!mem_bw_info) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("RDT Memory Bandwidth allocation unsupported"));
return -1;
}
for (i = 0; i < mem_bw_alloc->nbandwidths; i++) {
if (!mem_bw_alloc->bandwidths[i])
continue;
if (*(mem_bw_alloc->bandwidths[i]) % mem_bw_info->bandwidth_granularity) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Memory Bandwidth allocation of size "
"%u is not divisible by granularity %u"),
*(mem_bw_alloc->bandwidths[i]),
mem_bw_info->bandwidth_granularity);
return -1;
}
if (*(mem_bw_alloc->bandwidths[i]) < mem_bw_info->min_bandwidth) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Memory Bandwidth allocation of size "
"%u is smaller than the minimum "
"allowed allocation %u"),
*(mem_bw_alloc->bandwidths[i]),
mem_bw_info->min_bandwidth);
return -1;
}
if (i > mem_bw_info->max_id) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("bandwidth controller id %zd does not "
"exist, max controller id %u"),
i, mem_bw_info->max_id);
return -1;
}
if (*(mem_bw_alloc->bandwidths[i]) > *(mem_bw_free->bandwidths[i])) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Not enough room for allocation of %u%% "
"bandwidth on node %zd, available bandwidth %u%%"),
*(mem_bw_alloc->bandwidths[i]), i,
*(mem_bw_free->bandwidths[i]));
return -1;
}
}
return 0;
}
diff --git a/tools/virsh-snapshot.c b/tools/virsh-snapshot.c
index e38ebb1f28..025321c58e 100644
--- a/tools/virsh-snapshot.c
+++ b/tools/virsh-snapshot.c
@@ -1046,323 +1046,322 @@ static virshSnapshotListPtr
virshSnapshotListCollect(vshControl *ctl, virDomainPtr dom,
virDomainSnapshotPtr from,
unsigned int orig_flags, bool tree)
{
size_t i;
char **names = NULL;
int count = -1;
bool descendants = false;
bool roots = false;
virDomainSnapshotPtr *snaps;
virshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist));
virshSnapshotListPtr ret = NULL;
const char *fromname = NULL;
int start_index = -1;
int deleted = 0;
bool filter_fallback = false;
unsigned int flags = orig_flags;
virshControlPtr priv = ctl->privData;
/* Try the interface available in 0.9.13 and newer. */
if (!priv->useSnapshotOld) {
if (from)
count = virDomainSnapshotListAllChildren(from, &snaps, flags);
else
count = virDomainListAllSnapshots(dom, &snaps, flags);
/* If we failed because of flags added in 1.0.1, we can do
* fallback filtering. */
if (count < 0 && last_error->code == VIR_ERR_INVALID_ARG &&
flags & (VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS |
VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION)) {
flags &= ~(VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS |
VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION);
vshResetLibvirtError();
filter_fallback = true;
if (from)
count = virDomainSnapshotListAllChildren(from, &snaps, flags);
else
count = virDomainListAllSnapshots(dom, &snaps, flags);
}
}
if (count >= 0) {
/* When mixing --from and --tree, we also want a copy of from
* in the list, but with no parent for that one entry. */
snaplist->snaps = vshCalloc(ctl, count + (tree && from),
sizeof(*snaplist->snaps));
snaplist->nsnaps = count;
for (i = 0; i < count; i++)
snaplist->snaps[i].snap = snaps[i];
VIR_FREE(snaps);
if (tree) {
for (i = 0; i < count; i++) {
if (virshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
&snaplist->snaps[i].parent) < 0)
goto cleanup;
}
if (from) {
snaplist->snaps[snaplist->nsnaps++].snap = from;
virDomainSnapshotRef(from);
}
}
goto success;
}
/* Assume that if we got this far, then the --no-leaves and
* --no-metadata flags were not supported. Disable groups that
* have no impact. */
/* XXX should we emulate --no-leaves? */
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES &&
flags & VIR_DOMAIN_SNAPSHOT_LIST_LEAVES)
flags &= ~(VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES |
VIR_DOMAIN_SNAPSHOT_LIST_LEAVES);
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA &&
flags & VIR_DOMAIN_SNAPSHOT_LIST_METADATA)
flags &= ~(VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA |
VIR_DOMAIN_SNAPSHOT_LIST_METADATA);
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA) {
/* We can emulate --no-metadata if --metadata was supported,
* since it was an all-or-none attribute on old servers. */
count = virDomainSnapshotNum(dom,
VIR_DOMAIN_SNAPSHOT_LIST_METADATA);
if (count < 0)
goto cleanup;
if (count > 0)
return snaplist;
flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA;
}
if (flags & (VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS |
VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION)) {
flags &= ~(VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS |
VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION);
filter_fallback = true;
}
/* This uses the interfaces available in 0.8.0-0.9.6
* (virDomainSnapshotListNames, global list only) and in
* 0.9.7-0.9.12 (addition of virDomainSnapshotListChildrenNames
* for child listing, and new flags), as follows, with [*] by the
* combinations that need parent info (either for filtering
* purposes or for the resulting tree listing):
* old new
* list global as-is global as-is
* list --roots *global + filter global + flags
* list --from *global + filter child as-is
* list --from --descendants *global + filter child + flags
* list --tree *global as-is *global as-is
* list --tree --from *global + filter *child + flags
*
* Additionally, when --tree and --from are both used, from is
* added to the final list as the only element without a parent.
* Otherwise, --from does not appear in the final list.
*/
if (from) {
fromname = virDomainSnapshotGetName(from);
if (!fromname) {
vshError(ctl, "%s", _("Could not get snapshot name"));
goto cleanup;
}
descendants = (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) || tree;
if (tree)
flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
/* Determine if we can use the new child listing API. */
if (priv->useSnapshotOld ||
((count = virDomainSnapshotNumChildren(from, flags)) < 0 &&
last_error->code == VIR_ERR_NO_SUPPORT)) {
/* We can emulate --from. */
/* XXX can we also emulate --leaves? */
vshResetLibvirtError();
priv->useSnapshotOld = true;
flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
goto global;
}
if (tree && count >= 0)
count++;
} else {
global:
/* Global listing (including fallback when --from failed with
* child listing). */
count = virDomainSnapshotNum(dom, flags);
/* Fall back to simulation if --roots was unsupported. */
/* XXX can we also emulate --leaves? */
if (!from && count < 0 && last_error->code == VIR_ERR_INVALID_ARG &&
(flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
vshResetLibvirtError();
roots = true;
flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
count = virDomainSnapshotNum(dom, flags);
}
}
if (count < 0) {
if (!last_error)
vshError(ctl, _("failed to collect snapshot list"));
goto cleanup;
}
if (!count)
goto success;
names = vshCalloc(ctl, sizeof(*names), count);
/* Now that we have a count, collect the list. */
if (from && !priv->useSnapshotOld) {
if (tree) {
- if (count)
- count = virDomainSnapshotListChildrenNames(from, names + 1,
- count - 1, flags);
+ count = virDomainSnapshotListChildrenNames(from, names + 1,
+ count - 1, flags);
if (count >= 0) {
count++;
names[0] = vshStrdup(ctl, fromname);
}
} else {
count = virDomainSnapshotListChildrenNames(from, names,
count, flags);
}
} else {
count = virDomainSnapshotListNames(dom, names, count, flags);
}
if (count < 0)
goto cleanup;
snaplist->snaps = vshCalloc(ctl, sizeof(*snaplist->snaps), count);
snaplist->nsnaps = count;
for (i = 0; i < count; i++) {
snaplist->snaps[i].snap = virDomainSnapshotLookupByName(dom,
names[i], 0);
if (!snaplist->snaps[i].snap)
goto cleanup;
}
/* Collect parents when needed. With the new API, --tree and
* --from together put from as the first element without a parent;
* with the old API we still need to do a post-process filtering
* based on all parent information. */
if (tree || (from && priv->useSnapshotOld) || roots) {
for (i = (from && !priv->useSnapshotOld); i < count; i++) {
if (from && priv->useSnapshotOld && STREQ(names[i], fromname)) {
start_index = i;
if (tree)
continue;
}
if (virshGetSnapshotParent(ctl, snaplist->snaps[i].snap,
&snaplist->snaps[i].parent) < 0)
goto cleanup;
if ((from && ((tree && !snaplist->snaps[i].parent) ||
(!descendants &&
STRNEQ_NULLABLE(fromname,
snaplist->snaps[i].parent)))) ||
(roots && snaplist->snaps[i].parent)) {
virshDomainSnapshotFree(snaplist->snaps[i].snap);
snaplist->snaps[i].snap = NULL;
VIR_FREE(snaplist->snaps[i].parent);
deleted++;
}
}
}
if (tree)
goto success;
if (priv->useSnapshotOld && descendants) {
bool changed = false;
bool remaining = false;
/* Make multiple passes over the list - first pass finds
* direct children and NULLs out all roots and from, remaining
* passes NULL out any undecided entry whose parent is not
* still in list. We mark known descendants by clearing
* snaps[i].parents. Sorry, this is O(n^3) - hope your
* hierarchy isn't huge. XXX Is it worth making O(n^2 log n)
* by using qsort and bsearch? */
if (start_index < 0) {
vshError(ctl, _("snapshot %s disappeared from list"), fromname);
goto cleanup;
}
for (i = 0; i < count; i++) {
if (i == start_index || !snaplist->snaps[i].parent) {
VIR_FREE(names[i]);
virshDomainSnapshotFree(snaplist->snaps[i].snap);
snaplist->snaps[i].snap = NULL;
VIR_FREE(snaplist->snaps[i].parent);
deleted++;
} else if (STREQ(snaplist->snaps[i].parent, fromname)) {
VIR_FREE(snaplist->snaps[i].parent);
changed = true;
} else {
remaining = true;
}
}
if (!changed) {
ret = vshMalloc(ctl, sizeof(*snaplist));
goto cleanup;
}
while (changed && remaining) {
changed = remaining = false;
for (i = 0; i < count; i++) {
bool found_parent = false;
size_t j;
if (!names[i] || !snaplist->snaps[i].parent)
continue;
for (j = 0; j < count; j++) {
if (!names[j] || i == j)
continue;
if (STREQ(snaplist->snaps[i].parent, names[j])) {
found_parent = true;
if (!snaplist->snaps[j].parent)
VIR_FREE(snaplist->snaps[i].parent);
else
remaining = true;
break;
}
}
if (!found_parent) {
changed = true;
VIR_FREE(names[i]);
virshDomainSnapshotFree(snaplist->snaps[i].snap);
snaplist->snaps[i].snap = NULL;
VIR_FREE(snaplist->snaps[i].parent);
deleted++;
}
}
}
}
success:
if (filter_fallback) {
/* Older API didn't filter on status or location, but the
* information is available in domain XML. */
if (!(orig_flags & VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS))
orig_flags |= VIR_DOMAIN_SNAPSHOT_FILTERS_STATUS;
if (!(orig_flags & VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION))
orig_flags |= VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION;
for (i = 0; i < snaplist->nsnaps; i++) {
switch (virshSnapshotFilter(ctl, snaplist->snaps[i].snap,
orig_flags)) {
case 1:
break;
case 0:
virshDomainSnapshotFree(snaplist->snaps[i].snap);
snaplist->snaps[i].snap = NULL;
VIR_FREE(snaplist->snaps[i].parent);
deleted++;
break;
default:
goto cleanup;
}
}
}
qsort(snaplist->snaps, snaplist->nsnaps, sizeof(*snaplist->snaps),
virshSnapSorter);
snaplist->nsnaps -= deleted;
VIR_STEAL_PTR(ret, snaplist);
cleanup:
virshSnapshotListFree(snaplist);
if (names && count > 0)
for (i = 0; i < count; i++)
VIR_FREE(names[i]);
VIR_FREE(names);
return ret;
}
--
2.19.2
5 years, 8 months
[libvirt] [PATCH 00/10] domcaps: use virTristateBool
by Cole Robinson
Extending domaincapabilities with new XML schema is currently a bit of
a maintenance pain. Consider the case of adding a new enum for listing
<sound> models. I want to output this info for the qemu driver.
Internally in the domaincapabilities plumbing, whether a <device> is
supported= is tracked with boolean true/false. If I extend that
pattern for <sound> devices and fill in data for the qemu driver, the
other domcaps implementations will now automatically output a new XML
element:
<sound supported='no'>
Now, for bhyve I can 'git grep' confirm that it doesn't have any
<sound> support, but for xen/libxl it _is_ supported. So if I don't
fill in accurate support in the xen driver, I've just made their
domcaps report blatantly incorrect info.
Ideally I would make these <sound> changes and the other drivers output
would _not_ change. xen output would now be incomplete, but not
obviously wrong, which is easier on me the developer, and safer for the
API consumer.
This moves domcaps plumbing in that direction. It switches most
internal 'supported' fields to virTristateBool so we can track an
ABSENT state and map that to outputting no XML. Explicit supported='no'
values are filled in where needed to ensure existing driver XML doesn't
change. cpu and sev supported= values are left unconverted, but they
require semi-special handling anyways so aren't really affected by the
problem I laid out above.
Cole Robinson (10):
tests: domcaps: Add a default 'empty' test
tests: domcaps: Remove unused typedef
tests: domcaps: Remove 'full' test
conf: domcaps: Add single line formatting macro
conf: domcaps: use virTristateBool for 'supported'
qemu: domcaps: fill in explicit supported BOOL_NO
libxl: domcaps: fill in explicit supported BOOL_NO
bhyve: domcaps: fill in explicit supported BOOL_NO
schemas: domcaps: Make more elements optional
conf: domcaps: Don't output XML on tristate ABSENT
docs/schemas/domaincaps.rng | 20 +++++--
src/bhyve/bhyve_capabilities.c | 20 +++++--
src/conf/domain_capabilities.c | 26 ++++++----
src/conf/domain_capabilities.h | 20 +++----
src/libxl/libxl_capabilities.c | 18 ++++---
src/qemu/qemu_capabilities.c | 26 ++++++----
tests/domaincapsschemadata/empty.xml | 16 ++++++
tests/domaincapstest.c | 78 ++--------------------------
8 files changed, 103 insertions(+), 121 deletions(-)
create mode 100644 tests/domaincapsschemadata/empty.xml
--
2.20.1
5 years, 8 months
[libvirt] [PATCH v2 00/17] Add support to list Storage Driver backend capabilities
by John Ferlan
v1: https://www.redhat.com/archives/libvir-list/2019-January/msg00479.html
Changes since v1:
* The first 4 patches were already R-by'd and pushed.
* From v1, rework patch 5 & 6 into what now is patches 8 & 9. The
format of the output for what results in the output for the
connectGetCapabilities (virConnectGetCapabilities).
* From v1, drop patch 7
* In v2, patches 1-7 are new as a result of work done for patches 10-17.
patches 1-5 were posted upstream, but left unreviewed:
https://www.redhat.com/archives/libvir-list/2019-February/msg00333.html
These essentially ensure the volOptions and poolOptions don't list
or use something unexpected per documentation. The doc patch is a
simple update to add some missing text and fix an entry
* Patches 10-17 are new to implement the ability to get/format the
Storage Driver backend capabilities via:
storageConnectGetStoragePoolCapabilities
virConnectGetStoragePoolCapabilities
similar to how virConnectGetDomainCapabilities returns domain specific
output. The output is essentially what is provided in the poolOptions
and volOptions from storage_conf as valid values for format type fields
for pool and/or volume as well as an enumerated list for the required
source elements for creation. Whether the latter is useful or not was
not clear, but since it is something that can cause a creation error
when missing, I figured it'd be useful. The new virsh command follows
then domcapabilities nomenclature.
John Ferlan (17):
conf: Remove volOptions for VIR_STORAGE_POOL_SHEEPDOG
conf: Remove volOptions for VIR_STORAGE_POOL_RBD
conf: Remove volOptions for VIR_STORAGE_POOL_SCSI
conf: Remove volOptions for VIR_STORAGE_POOL_ISCSI[_DIRECT]
conf: Remove volOptions for VIR_STORAGE_POOL_MPATH
conf: Remove defaultFormat from VIR_STORAGE_POOL_ZFS
docs: Fix a few storage.html.in typos
conf: Introduce storage pool functions into capabilities
storage: Process storage pool capabilities
docs: Add schema for storage pool capabilities
conf: Add storage pool capability formatting
tests: Introduce storage pool capabilites test
docs: Add description for Storage Pool Capabilities
libvirt: Introduce virConnectGetStoragePoolCapabilities
storage: Introduce storageConnectGetStoragePoolCapabilities
virsh: Expose virConnectGetStoragePoolCapabilities
docs: Add news article
docs/docs.html.in | 1 +
docs/format.html.in | 1 +
docs/formatstoragecaps.html.in | 108 +++++++
docs/index.html.in | 1 +
docs/news.xml | 12 +
docs/schemas/storagepoolcaps.rng | 88 ++++++
docs/storage.html.in | 8 +-
include/libvirt/libvirt-storage.h | 4 +
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 2 +
src/conf/Makefile.inc.am | 2 +
src/conf/capabilities.c | 74 +++++
src/conf/capabilities.h | 15 +
src/conf/storage_capabilities.c | 135 +++++++++
src/conf/storage_capabilities.h | 41 +++
src/conf/storage_conf.c | 131 +++++++--
src/conf/storage_conf.h | 7 +
src/conf/virstorageobj.h | 5 +
src/driver-storage.h | 5 +
src/libvirt-storage.c | 40 +++
src/libvirt_private.syms | 8 +
src/libvirt_public.syms | 5 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 15 +-
src/remote_protocol-structs | 7 +
src/storage/storage_backend.c | 16 ++
src/storage/storage_backend.h | 3 +
src/storage/storage_driver.c | 44 +++
tests/Makefile.am | 7 +
.../storagepoolcapsschemadata/poolcaps-fs.xml | 268 ++++++++++++++++++
.../poolcaps-full.xml | 268 ++++++++++++++++++
tests/storagepoolcapstest.c | 124 ++++++++
tests/storagevolxml2xmlout/vol-sheepdog.xml | 1 -
tests/virschematest.c | 1 +
tools/virsh-pool.c | 42 +++
tools/virsh.pod | 7 +
36 files changed, 1473 insertions(+), 25 deletions(-)
create mode 100644 docs/formatstoragecaps.html.in
create mode 100644 docs/schemas/storagepoolcaps.rng
create mode 100644 src/conf/storage_capabilities.c
create mode 100644 src/conf/storage_capabilities.h
create mode 100644 tests/storagepoolcapsschemadata/poolcaps-fs.xml
create mode 100644 tests/storagepoolcapsschemadata/poolcaps-full.xml
create mode 100644 tests/storagepoolcapstest.c
--
2.20.1
5 years, 8 months
[libvirt] [PATCH for-4.0 v4 0/2] virtio: Provide version-specific variants of virtio PCI devices
by Eduardo Habkost
Existing modern-only device types are not being touched by v3, as
they don't need separate variants. However, I plan to implement
separate cleanups in the code that calls virtio_pci_force_virtio_1(),
first, and then propose additional changes (e.g. deprecating
disable-legacy and disable-modern in those device types).
Changes v3 -> v4:
* Trivial comment fixes (Cornelia Huck)
* Test code update (Caio Carrara)
Changes v2 -> v3:
* Split into two separate patches (type registration helper
and introduction of new types)
* Rewrote virtio_pci_types_register() completely:
* Replaced magic generation of type names with explicit fields in
VirtioPCIDeviceTypeInfo
* Removed modern_only field (not necessary anymore)
* Don't register a separate base type unless necessary
Changes v1 -> v2:
* Removed *-0.9 devices. Nobody will want to use them, if
transitional devices work with legacy drivers
(Gerd Hoffmann, Michael S. Tsirkin)
* Drop virtio version from name: rename -1.0-transitional to
-transitional (Michael S. Tsirkin)
* Renamed -1.0 to -non-transitional
* Don't add any extra variants to modern-only device types
(they don't need it)
* Fix typo on TYPE_VIRTIO_INPUT_HOST_PCI (crash reported by
Cornelia Huck)
* No need to change cast macros for modern-only devices
* Rename virtio_register_types() to virtio_pci_types_register()
Original patch description:
Many of the current virtio-*-pci device types actually represent
3 different types of devices:
* virtio 1.0 non-transitional devices
* virtio 1.0 transitional devices
* virtio 0.9 ("legacy device" in virtio 1.0 terminology)
That would be just an annoyance if it didn't break our device/bus
compatibility QMP interfaces. With this multi-purpose device
type, there's no way to tell management software that
transitional devices and legacy devices require a Conventional
PCI bus.
The multi-purpose device types would also prevent us from telling
management software what's the PCI vendor/device ID for them,
because their PCI IDs change at runtime depending on the bus
where they were plugged.
This patch adds separate device types for each of those virtio
device flavors:
* virtio-*-pci: the existing multi-purpose device types
* virtio-*-pci-transitional: virtio-1.0 device supporting legacy drivers
* virtio-*-pci-non-transitional: modern-only
Reference to previous discussion that originated this idea:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg558389.html
Eduardo Habkost (2):
virtio: Helper for registering virtio device types
virtio: Provide version-specific variants of virtio PCI devices
hw/virtio/virtio-pci.h | 78 +++++++--
hw/display/virtio-gpu-pci.c | 7 +-
hw/display/virtio-vga.c | 7 +-
hw/virtio/virtio-crypto-pci.c | 7 +-
hw/virtio/virtio-pci.c | 267 ++++++++++++++++++++++-------
tests/acceptance/virtio_version.py | 176 +++++++++++++++++++
6 files changed, 452 insertions(+), 90 deletions(-)
create mode 100644 tests/acceptance/virtio_version.py
--
2.18.0.rc1.1.g3f1ff2140
5 years, 8 months