[libvirt] [PATCH] Replace hashing algorithm with murmurhash
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Recent discussions have illustrated the potential for DOS attacks
with the hash table implementations used by most languages and
libraries.
https://lwn.net/Articles/474912/
libvirt has an internal hash table impl, and uses hash tables for
a variety of purposes. The hash key generation code is pretty
simple and thus not strongly collision resistant.
This patch replaces the current libvirt hash key generator with
the (public domain) Murmurhash3 code. In addition every hash
table now gets a random seed value which is used to perturb the
hashing code. This should make it impossible to mount any
practical attack against libvirt hashing code.
* src/Makefile.am: Add virhashcode.[ch]
* src/util/util.c: Make virRandom() return a fixed 32 bit
integer value.
* src/util/hash.c, src/util/hash.h, src/util/cgroup.c: Replace
hash code generation with a call to virHashCodeGen()
* src/util/virhashcode.h, src/util/virhashcode.c: Add a new
virHashCodeGen() API using the Murmurhash3 algorithm.
---
src/Makefile.am | 1 +
src/util/cgroup.c | 6 ++-
src/util/hash.c | 24 ++++------
src/util/hash.h | 7 ++-
src/util/util.c | 4 +-
src/util/virhashcode.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virhashcode.h | 35 +++++++++++++
7 files changed, 181 insertions(+), 21 deletions(-)
create mode 100644 src/util/virhashcode.c
create mode 100644 src/util/virhashcode.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 0a1221a..dd5acc4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,7 @@ UTIL_SOURCES = \
util/virpidfile.c util/virpidfile.h \
util/xml.c util/xml.h \
util/virterror.c util/virterror_internal.h \
+ util/virhashcode.c util/virhashcode.h \
util/virkeycode.c util/virkeycode.h \
util/virkeymaps.h \
util/virnetdev.h util/virnetdev.c \
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 25f2691..7623264 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -33,6 +33,7 @@
#include "logging.h"
#include "virfile.h"
#include "hash.h"
+#include "virhashcode.h"
#define CGROUP_MAX_VAL 512
@@ -1636,9 +1637,10 @@ cleanup:
}
-static unsigned long virCgroupPidCode(const void *name)
+static int32_t virCgroupPidCode(const void *name, int32_t seed)
{
- return (unsigned long)name;
+ unsigned long pid = (unsigned long)name;
+ return virHashCodeGen(&pid, sizeof(pid), seed);
}
static bool virCgroupPidEqual(const void *namea, const void *nameb)
{
diff --git a/src/util/hash.c b/src/util/hash.c
index 665bcce..e765a6c 100644
--- a/src/util/hash.c
+++ b/src/util/hash.c
@@ -28,6 +28,8 @@
#include "hash.h"
#include "memory.h"
#include "logging.h"
+#include "virhashcode.h"
+#include "util.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -57,6 +59,7 @@ struct _virHashEntry {
*/
struct _virHashTable {
virHashEntryPtr *table;
+ uint32_t seed;
int size;
int nbElems;
/* True iff we are iterating over hash entries. */
@@ -70,20 +73,11 @@ struct _virHashTable {
virHashKeyFree keyFree;
};
-static unsigned long virHashStrCode(const void *name)
+
+
+static int32_t virHashStrCode(const void *name, int32_t seed)
{
- const char *str = name;
- unsigned long value = 0L;
- char ch;
-
- if (str != NULL) {
- value += 30 * (*str);
- while ((ch = *str++) != 0) {
- value =
- value ^ ((value << 5) + (value >> 3) + (unsigned long) ch);
- }
- }
- return value;
+ return virHashCodeGen(name, strlen(name), seed);
}
static bool virHashStrEqual(const void *namea, const void *nameb)
@@ -101,11 +95,10 @@ static void virHashStrFree(void *name)
VIR_FREE(name);
}
-
static unsigned long
virHashComputeKey(virHashTablePtr table, const void *name)
{
- unsigned long value = table->keyCode(name);
+ uint32_t value = table->keyCode(name, table->seed);
return (value % table->size);
}
@@ -139,6 +132,7 @@ virHashTablePtr virHashCreateFull(int size,
return NULL;
}
+ table->seed = virRandom(INT32_MAX);
table->size = size;
table->nbElems = 0;
table->dataFree = dataFree;
diff --git a/src/util/hash.h b/src/util/hash.h
index 1ba12b9..c415844 100644
--- a/src/util/hash.h
+++ b/src/util/hash.h
@@ -55,12 +55,15 @@ typedef int (*virHashSearcher) (const void *payload, const void *name,
/**
* virHashKeyCode:
* @name: the hash key
+ * @seed: random seed
*
- * Compute the hash code corresponding to the key @name
+ * Compute the hash code corresponding to the key @name, using
+ * @seed to perturb the hashing algorithm
*
* Returns the hash code
*/
-typedef unsigned long (*virHashKeyCode)(const void *name);
+typedef int32_t (*virHashKeyCode)(const void *name,
+ int32_t seed);
/**
* virHashKeyEqual:
* @namea: the first hash key
diff --git a/src/util/util.c b/src/util/util.c
index 8663c4d..c8588b5 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2115,7 +2115,7 @@ int virRandomInitialize(unsigned int seed)
return 0;
}
-int virRandom(int max)
+int32_t virRandom(int32_t max)
{
int32_t ret;
@@ -2123,7 +2123,7 @@ int virRandom(int max)
random_r(&randomData, &ret);
virMutexUnlock(&randomLock);
- return (int) ((double)max * ((double)ret / (double)RAND_MAX));
+ return (int32_t) ((double)max * ((double)ret / (double)RAND_MAX));
}
diff --git a/src/util/virhashcode.c b/src/util/virhashcode.c
new file mode 100644
index 0000000..50b46f4
--- /dev/null
+++ b/src/util/virhashcode.c
@@ -0,0 +1,125 @@
+/*
+ * virhashcode.c: hash code generation
+ *
+ * Copyright (C) 2012 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The hash code generation is based on the public domain MurmurHash3 from Austin Appleby:
+ * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ *
+ * We use only the 32 bit variant because the 2 produce different result while
+ * we need to produce the same result regardless of the architecture as
+ * clients can be both 64 or 32 bit at the same time.
+ */
+
+#include <config.h>
+
+#include "virhashcode.h"
+
+static uint32_t rotl(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+/* slower than original but is endian neutral and handles platforms that
+ * do only aligned reads */
+__attribute__((always_inline))
+static uint32_t getblock(const uint8_t *p, int i)
+{
+ uint32_t r;
+ size_t size = sizeof(uint32_t);
+
+ memcpy(&r, &p[i * size], size);
+
+ return le32toh(r);
+}
+
+/*
+ * Finalization mix - force all bits of a hash block to avalanche
+ */
+__attribute__((always_inline))
+static uint32_t fmix(uint32_t h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+
+uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed)
+{
+ const uint8_t *blocks;
+ const uint8_t *tail;
+ size_t nblocks;
+ uint32_t h1;
+ uint32_t k1;
+ uint32_t c1;
+ uint32_t c2;
+ size_t i;
+
+ blocks = (const uint8_t *)key;
+ nblocks = len / 4;
+ h1 = seed;
+ c1 = 0xcc9e2d51;
+ c2 = 0x1b873593;
+
+ /* body */
+
+ for (i = 0; i < nblocks; i++) {
+
+ k1 = getblock(blocks, i);
+
+ k1 *= c1;
+ k1 = rotl(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = rotl(h1, 13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ /* tail */
+
+ tail = (const uint8_t *)key + nblocks * 4;
+
+ k1 = 0;
+
+ switch (len & 3) {
+ case 3:
+ k1 ^= tail[2] << 16;
+ case 2:
+ k1 ^= tail[1] << 8;
+ case 1:
+ k1 ^= tail[0];
+ k1 *= c1;
+ k1 = rotl(k1, 15);
+ k1 *= c2;
+ h1 ^= k1;
+ default:
+ break;
+ }
+
+ /* finalization */
+
+ h1 ^= len;
+ h1 = fmix(h1);
+
+ return h1;
+}
diff --git a/src/util/virhashcode.h b/src/util/virhashcode.h
new file mode 100644
index 0000000..867e04e
--- /dev/null
+++ b/src/util/virhashcode.h
@@ -0,0 +1,35 @@
+/*
+ * virhashcode.h: hash code generation
+ *
+ * Copyright (C) 2012 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The hash code generation is based on the public domain MurmurHash3 from Austin Appleby:
+ * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ *
+ * We use only the 32 bit variant because the 2 produce different result while
+ * we need to produce the same result regardless of the architecture as
+ * clients can be both 64 or 32 bit at the same time.
+ */
+
+#ifndef __VIR_HASH_CODE_H__
+# define __VIR_HASH_CODE_H__
+
+# include "internal.h"
+
+extern uint32_t virHashCodeGen(const void *key, size_t len, uint32_t seed);
+
+#endif /* __VIR_HASH_CODE_H__ */
--
1.7.7.5
13 years, 1 month
[libvirt] [PATCH] lxc: export container=lxc-libvirt for systemd
by Eric Blake
Systemd detects containers based on whether they have
an environment variable starting with 'container=lxc';
using a longer name fits the expectations, while also
allowing detection of who created the container.
Requested by Lennart Poettering, in response to
https://bugs.freedesktop.org/show_bug.cgi?id=45175
* src/lxc/lxc_container.c (lxcContainerBuildInitCmd): Add another
env-var.
---
src/lxc/lxc_container.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index c1ec9c4..70f6908 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Red Hat, Inc.
+ * Copyright (C) 2008-2012 Red Hat, Inc.
* Copyright (C) 2008 IBM Corp.
*
* lxc_container.c: file description
@@ -124,6 +124,7 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef)
virCommandAddEnvString(cmd, "PATH=/bin:/sbin");
virCommandAddEnvString(cmd, "TERM=linux");
+ virCommandAddEnvString(cmd, "container=lxc-libvirt");
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_UUID", uuidstr);
virCommandAddEnvPair(cmd, "LIBVIRT_LXC_NAME", vmDef->name);
if (vmDef->os.cmdline)
--
1.7.7.5
13 years, 1 month
[libvirt] [PATCH] schema: Relax schema for domain name
by Peter Krempa
The domain schema enforced restrictions on the domain name string that
the code doesn't. This patch relaxes the check, leaving the restrictions
on the driver or hypervisor.
---
And maybe we should consider adding some restrictions on the qemu driver, as the daemon
is competely fine with creating a domain with the name "../../../../../../../test" that
has its configuration stored in "/test.xml" then.
docs/schemas/domaincommon.rng | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 2041dfb..1922cd6 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3003,9 +3003,7 @@
</data>
</define>
<define name="domainName">
- <data type="string">
- <param name="pattern">[A-Za-z0-9_\.\+\-&:/]+</param>
- </data>
+ <data type="string" />
</define>
<define name="diskSerial">
<data type="string">
--
1.7.3.4
13 years, 1 month
[libvirt] [PATCH] Add support for forcing a private network namespace for LXC guests
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
If no <interface> elements are included in an LXC guest XML
description, then the LXC guest will just see the host's
network interfaces. It is desirable to be able to hide the
host interfaces, without having to define any guest interfaces.
This patch introduces a new feature flag <privnet/> to allow
forcing of a private network namespace for LXC. In the future
I also anticipate that we will add <privuser/> to force a
private user ID namespace.
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add support
for <privnet/> feature. Auto-set <privnet> if any <interface>
devices are defined
* src/lxc/lxc_container.c: Honour request for private network
namespace
---
docs/formatdomain.html.in | 7 +++++++
docs/schemas/domaincommon.rng | 5 +++++
src/conf/domain_conf.c | 3 ++-
src/conf/domain_conf.h | 1 +
src/lxc/lxc_container.c | 11 +++++++----
5 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 1d0211d..b7ad638 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -843,6 +843,7 @@
<acpi/>
<apic/>
<hap/>
+ <privnet/>
</features>
...</pre>
@@ -870,6 +871,12 @@
<dd>Enable Viridian hypervisor extensions for paravirtualizing
guest operating systems
</dd>
+ <dt><code>privnet</code></dt>
+ <dd>Always create a private network namespace. This is
+ automatically set if any interface devices are defined.
+ This feature is only relevant for container based
+ virtualization drivers eg LXC.
+ </dd>
</dl>
<h3><a name="elementsTime">Time keeping</a></h3>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 2f655a9..9f12a6d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2530,6 +2530,11 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="privnet">
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e872396..66d7f39 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -103,7 +103,8 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"apic",
"pae",
"hap",
- "viridian")
+ "viridian",
+ "privnet")
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
"destroy",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3b522a9..2131ff9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1221,6 +1221,7 @@ enum virDomainFeature {
VIR_DOMAIN_FEATURE_PAE,
VIR_DOMAIN_FEATURE_HAP,
VIR_DOMAIN_FEATURE_VIRIDIAN,
+ VIR_DOMAIN_FEATURE_PRIVNET,
VIR_DOMAIN_FEATURE_LAST
};
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index dcd65ef..0820a0e 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -254,7 +254,8 @@ int lxcContainerWaitForContinue(int control)
*
* Returns 0 on success or nonzero in case of error
*/
-static int lxcContainerRenameAndEnableInterfaces(unsigned int nveths,
+static int lxcContainerRenameAndEnableInterfaces(bool privNet,
+ unsigned int nveths,
char **veths)
{
int rc = 0;
@@ -282,7 +283,7 @@ static int lxcContainerRenameAndEnableInterfaces(unsigned int nveths,
}
/* enable lo device only if there were other net devices */
- if (veths)
+ if (veths || privNet)
rc = virNetDevSetOnline("lo", true);
error_out:
@@ -1277,7 +1278,8 @@ static int lxcContainerChild( void *data )
VIR_DEBUG("Received container continue message");
/* rename and enable interfaces */
- if (lxcContainerRenameAndEnableInterfaces(argv->nveths,
+ if (lxcContainerRenameAndEnableInterfaces(vmDef->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET),
+ argv->nveths,
argv->veths) < 0) {
goto cleanup;
}
@@ -1386,7 +1388,8 @@ int lxcContainerStart(virDomainDefPtr def,
cflags |= CLONE_NEWUSER;
}
- if (def->nets != NULL) {
+ if (def->nets != NULL ||
+ (def->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET))) {
VIR_DEBUG("Enable network namespaces");
cflags |= CLONE_NEWNET;
}
--
1.7.7.5
13 years, 1 month
[libvirt] [PATCH] Add missing docs for <viridian/> feature flag
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
docs/formatdomain.html.in | 4 ++++
docs/schemas/domaincommon.rng | 5 +++++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index dfb010d..1d0211d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -866,6 +866,10 @@
<dd>Enable use of Hardware Assisted Paging if available in
the hardware.
</dd>
+ <dt><code>viridian</code></dt>
+ <dd>Enable Viridian hypervisor extensions for paravirtualizing
+ guest operating systems
+ </dd>
</dl>
<h3><a name="elementsTime">Time keeping</a></h3>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4fa968d..2f655a9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2525,6 +2525,11 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="viridian">
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
--
1.7.7.5
13 years, 1 month
[libvirt] [PATCH] qemu: Emit bootindex even for direct boot
by Jiri Denemark
Direct boot (using kernel, initrd, and command line) is used by
virt-install/virt-manager for network install. While any bootindex has
no direct effect since -kernel is always first, we need it as a hint for
SeaBIOS to present disks in the same order as they will be presented
during normal boot.
---
src/qemu/qemu_command.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index aaccf62..9b69ad0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4334,8 +4334,7 @@ qemuBuildCommandLine(virConnectPtr conn,
if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) {
int bootCD = 0, bootFloppy = 0, bootDisk = 0;
- if ((qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) || emitBootindex) &&
- !def->os.kernel) {
+ if ((qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) || emitBootindex)) {
/* bootDevs will get translated into either bootindex=N or boot=on
* depending on what qemu supports */
for (i = 0 ; i < def->os.nBootDevs ; i++) {
--
1.7.8.4
13 years, 1 month
[libvirt] [PATCH v2] Add two NUMA tuning python bindings APIs
by Guannan Ren
*virDomainSetNumaParameters
*virDomainGetNumaParameters
---
python/libvirt-override-api.xml | 13 +++
python/libvirt-override.c | 186 +++++++++++++++++++++++++++++++++++++++
2 files changed, 199 insertions(+), 0 deletions(-)
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 704fee9..e09290c 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -248,6 +248,19 @@
<arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
<arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
</function>
+ <function name='virDomainSetNumaParameters' file='python'>
+ <info>Change the NUMA tunables</info>
+ <return type='int' info='-1 in case of error, 0 in case of success.'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
+ <arg name='params' type='virTypedParameterPtr' info='pointer to numa tunable objects'/>
+ <arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
+ </function>
+ <function name='virDomainGetNumaParameters' file='python'>
+ <info>Get the NUMA parameters</info>
+ <return type='virTypedParameterPtr' info='the numa tunables value or None in case of error'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
+ <arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
+ </function>
<function name='virConnectListStoragePools' file='python'>
<info>list the storage pools, stores the pointers to the names in @names</info>
<arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index d2aad0f..27ad1d8 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -1000,6 +1000,190 @@ libvirt_virDomainGetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED,
}
static PyObject *
+libvirt_virDomainSetNumaParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ int i_retval;
+ int nparams = 0, i;
+ unsigned int flags;
+ virTypedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args,
+ (char *)"OOi:virDomainSetNumaParameters",
+ &pyobj_domain, &info, &flags))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetNumaParameters(domain, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_INT_FAIL;
+
+ if ((params = malloc(sizeof(*params)*nparams)) == NULL)
+ return VIR_PY_INT_FAIL;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetNumaParameters(domain, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ free(params);
+ return VIR_PY_INT_FAIL;
+ }
+
+ /* convert to a Python tuple of long objects */
+ for (i = 0; i < nparams; i++) {
+ PyObject *key, *val;
+ key = libvirt_constcharPtrWrap(params[i].field);
+ val = PyDict_GetItem(info, key);
+ Py_DECREF(key);
+
+ if (val == NULL)
+ continue;
+
+ switch (params[i].type) {
+ case VIR_TYPED_PARAM_INT:
+ params[i].value.i = (int)PyInt_AS_LONG(val);
+ break;
+
+ case VIR_TYPED_PARAM_UINT:
+ params[i].value.ui = (unsigned int)PyInt_AS_LONG(val);
+ break;
+
+ case VIR_TYPED_PARAM_LLONG:
+ params[i].value.l = (long long)PyLong_AsLongLong(val);
+ break;
+
+ case VIR_TYPED_PARAM_ULLONG:
+ params[i].value.ul = (unsigned long long)PyLong_AsLongLong(val);
+ break;
+
+ case VIR_TYPED_PARAM_DOUBLE:
+ params[i].value.d = (double)PyFloat_AsDouble(val);
+ break;
+
+ case VIR_TYPED_PARAM_BOOLEAN:
+ {
+ /* Hack - Python's definition of Py_True breaks strict
+ * aliasing rules, so can't directly compare
+ */
+ PyObject *hacktrue = PyBool_FromLong(1);
+ params[i].value.b = hacktrue == val ? 1: 0;
+ Py_DECREF(hacktrue);
+ }
+ break;
+
+ case VIR_TYPED_PARAM_STRING:
+ params[i].value.s = PyString_AsString(val);
+ break;
+
+ default:
+ free(params);
+ return VIR_PY_INT_FAIL;
+ }
+ }
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainSetNumaParameters(domain, params, nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+ if (i_retval < 0) {
+ free(params);
+ return VIR_PY_INT_FAIL;
+ }
+
+ free(params);
+ return VIR_PY_INT_SUCCESS;
+}
+
+static PyObject *
+libvirt_virDomainGetNumaParameters(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *info;
+ int i_retval;
+ int nparams = 0, i;
+ unsigned int flags;
+ virTypedParameterPtr params;
+
+ if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainGetNumaParameters",
+ &pyobj_domain, &flags))
+ return(NULL);
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetNumaParameters(domain, NULL, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ return VIR_PY_NONE;
+
+ if ((params = malloc(sizeof(*params)*nparams)) == NULL)
+ return VIR_PY_NONE;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainGetNumaParameters(domain, params, &nparams, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+
+ /* convert to a Python tuple of long objects */
+ if ((info = PyDict_New()) == NULL) {
+ free(params);
+ return VIR_PY_NONE;
+ }
+
+ for (i = 0 ; i < nparams ; i++) {
+ PyObject *key, *val;
+
+ switch (params[i].type) {
+ case VIR_TYPED_PARAM_INT:
+ val = PyInt_FromLong((long)params[i].value.i);
+ break;
+
+ case VIR_TYPED_PARAM_UINT:
+ val = PyInt_FromLong((long)params[i].value.ui);
+ break;
+
+ case VIR_TYPED_PARAM_LLONG:
+ val = PyLong_FromLongLong((long long)params[i].value.l);
+ break;
+
+ case VIR_TYPED_PARAM_ULLONG:
+ val = PyLong_FromLongLong((long long)params[i].value.ul);
+ break;
+
+ case VIR_TYPED_PARAM_DOUBLE:
+ val = PyFloat_FromDouble((double)params[i].value.d);
+ break;
+
+ case VIR_TYPED_PARAM_BOOLEAN:
+ val = PyBool_FromLong((long)params[i].value.b);
+ break;
+
+ case VIR_TYPED_PARAM_STRING:
+ val = libvirt_constcharPtrWrap(params[i].value.s);
+ break;
+
+ default:
+ free(params);
+ Py_DECREF(info);
+ return VIR_PY_NONE;
+ }
+
+ key = libvirt_constcharPtrWrap(params[i].field);
+ PyDict_SetItem(info, key, val);
+ }
+ free(params);
+ return(info);
+}
+
+static PyObject *
libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED,
PyObject *args) {
virDomainPtr domain;
@@ -5162,6 +5346,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainGetBlkioParameters", libvirt_virDomainGetBlkioParameters, METH_VARARGS, NULL},
{(char *) "virDomainSetMemoryParameters", libvirt_virDomainSetMemoryParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetMemoryParameters", libvirt_virDomainGetMemoryParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainGetNumaParameters", libvirt_virDomainGetNumaParameters, METH_VARARGS, NULL},
+ {(char *) "virDomainSetNumaParameters", libvirt_virDomainSetNumaParameters, METH_VARARGS, NULL},
{(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpuFlags", libvirt_virDomainPinVcpuFlags, METH_VARARGS, NULL},
--
1.7.7.5
13 years, 1 month
[libvirt] [PATCH][RFC] adding a title to the domain description informations
by Daniel Veillard
The idea is that currently we have only the domain name usable as
a description for the domain. It is not really a good human readable
identifier, as the kind of string allowed is limited (no space for
example). The idea would then be to extend the existing <description>
field in the domain XML to keep 40 or less character string to describe
a domain and provide that information later for example in an extended
virsh list command or for other interfaces.
While the idea is simple, see attached patch for this, it becomes more
complex when one tries to make accessors to set/get that title for a
domain, since it's mutable and possibly could be coming from the
hypervisor itself (is there anything like this in VMWare or VirtualBox?)
it should to be implemented down at the driver level. Is that worth the
effort ? If we go that route should we do this for other objects
(network, storage, etc ...) too in the end ?
here is a basic patch for just the XML side to give an idea, but
adding APIs is far more work.
Opinions ?
Daniel
Provide a title attribute on domain descriptions
Allow to provide a title attribute to domain descriptions
useful when presenting the domain in an user interface.
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index de9b480..ad5ffb0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -58,7 +58,13 @@
<dd>The content of the <code>description</code> element provides a
human readable description of the virtual machine. This data is not
used by libvirt in any way, it can contain any information the user
- wants. <span class="since">Since 0.7.2</span></dd>
+ wants. <span class="since">Since 0.7.2</span>. It is also possible
+ to provide an human readable title for the virtual machine, by
+ providing it as a <code>title<code> attribute on the
+ <code>description</code> element, this can be useful to provide an
+ human description when listing virtual machines (<span class="since"
+ >Since 0.9.10</span>)</dd>
+
</dl>
<h3><a name="elementsOS">Operating system booting</a></h3>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 2041dfb..78ba67c 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -10,6 +10,11 @@
-->
<define name="description">
<element name="description">
+ <optional>
+ <attribute name="title">
+ <ref name="title-value"/>
+ </attribute>
+ </optional>
<text/>
</element>
</define>
@@ -3115,4 +3120,9 @@
</element>
<empty/>
</define>
+ <define name="title-value">
+ <data type="string">
+ <param name="pattern">.{0,40}</param>
+ </data>
+ </define>
</grammar>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f97014e..0e1ff44 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1478,6 +1478,7 @@ void virDomainDefFree(virDomainDefPtr def)
VIR_FREE(def->cpumask);
VIR_FREE(def->emulator);
VIR_FREE(def->description);
+ VIR_FREE(def->title);
virBlkioDeviceWeightArrayClear(def->blkio.devices,
def->blkio.ndevices);
@@ -7092,6 +7093,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
/* Extract documentation if present */
def->description = virXPathString("string(./description[1])", ctxt);
+ def->title = virXPathString("string(./description[1]/@title)", ctxt);
/* analysis of security label, done early even though we format it
* late, so devices can refer to this for defaults */
@@ -11417,8 +11419,16 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virUUIDFormat(uuid, uuidstr);
virBufferAsprintf(buf, " <uuid>%s</uuid>\n", uuidstr);
- virBufferEscapeString(buf, " <description>%s</description>\n",
- def->description);
+ if (def->title || def->description) {
+ virBufferAddLit(buf, " <description");
+ if (def->title)
+ virBufferEscapeString(buf, " title='%s'", def->title);
+ if (def->description)
+ virBufferEscapeString(buf, ">%s</description>\n",
+ def->description);
+ else
+ virBufferAddLit(buf, "/>");
+ }
virBufferAsprintf(buf, " <memory>%lu</memory>\n", def->mem.max_balloon);
virBufferAsprintf(buf, " <currentMemory>%lu</currentMemory>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b121f9c..45d70e6 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1421,6 +1421,7 @@ struct _virDomainDef {
unsigned char uuid[VIR_UUID_BUFLEN];
char *name;
char *description;
+ char *title;
struct {
unsigned int weight;
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
13 years, 1 month
[libvirt] [PATCH] docs: fix a few small typos in formatdomain.html.in
by Laine Stump
---
Pushed under the trivial rule.
docs/formatdomain.html.in | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index dca9a81..dfb010d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2275,8 +2275,8 @@
<pre>
...
<devices>
- <mac address='52:54:00:6d:90:01'>
<interface type='mcast'>
+ <mac address='52:54:00:6d:90:01'>
<source address='230.0.0.1' port='5558'/>
</interface>
</devices>
@@ -2297,13 +2297,13 @@
...
<devices>
<interface type='server'>
- <mac address='52:54:00:22:c9:42'>
+ <mac address='52:54:00:22:c9:42'>
<source address='192.168.0.1' port='5558'/>
</interface>
...
<interface type='client'>
- <mac address='52:54:00:8b:c9:51'>
- <source address='192.168.0.1' port='5558'/>
+ <mac address='52:54:00:8b:c9:51'>
+ <source address='192.168.0.1' port='5558'/>
</interface>
</devices>
...</pre>
@@ -2470,7 +2470,7 @@ qemu-kvm -net nic,model=? /dev/null
...</pre>
<p>
- For hypervisors which support this, you can set exact NIC which should
+ For hypervisors which support this, you can set a specific NIC to
be used for network boot. The <code>order</code> attribute determines
the order in which devices will be tried during boot sequence. The
per-device <code>boot</code> elements cannot be used together with
--
1.7.7.5
13 years, 1 month