[libvirt] Supporting vhost-net and macvtap in libvirt for QEMU
by Anthony Liguori
Disclaimer: I am neither an SR-IOV nor a vhost-net expert, but I've CC'd
people that are who can throw tomatoes at me for getting bits wrong :-)
I wanted to start a discussion about supporting vhost-net in libvirt.
vhost-net has not yet been merged into qemu but I expect it will be soon
so it's a good time to start this discussion.
There are two modes worth supporting for vhost-net in libvirt. The
first mode is where vhost-net backs to a tun/tap device. This is
behaves in very much the same way that -net tap behaves in qemu today.
Basically, the difference is that the virtio backend is in the kernel
instead of in qemu so there should be some performance improvement.
Current, libvirt invokes qemu with -net tap,fd=X where X is an already
open fd to a tun/tap device. I suspect that after we merge vhost-net,
libvirt could support vhost-net in this mode by just doing -net
vhost,fd=X. I think the only real question for libvirt is whether to
provide a user visible switch to use vhost or to just always use vhost
when it's available and it makes sense. Personally, I think the later
makes sense.
The more interesting invocation of vhost-net though is one where the
vhost-net device backs directly to a physical network card. In this
mode, vhost should get considerably better performance than the current
implementation. I don't know the syntax yet, but I think it's
reasonable to assume that it will look something like -net
tap,dev=eth0. The effect will be that eth0 is dedicated to the guest.
On most modern systems, there is a small number of network devices so
this model is not all that useful except when dealing with SR-IOV
adapters. In that case, each physical device can be exposed as many
virtual devices (VFs). There are a few restrictions here though. The
biggest is that currently, you can only change the number of VFs by
reloading a kernel module so it's really a parameter that must be set at
startup time.
I think there are a few ways libvirt could support vhost-net in this
second mode. The simplest would be to introduce a new tag similar to
<source network='br0'>. In fact, if you probed the device type for the
network parameter, you could probably do something like <source
network='eth0'> and have it Just Work.
Another model would be to have libvirt see an SR-IOV adapter as a
network pool whereas it handled all of the VF management. Considering
how inflexible SR-IOV is today, I'm not sure whether this is the best model.
Has anyone put any more thought into this problem or how this should be
modeled in libvirt? Michael, could you share your current thinking for
-net syntax?
--
Regards,
Anthony Liguori
1 year, 1 month
[libvirt] Libvirt multi queue support
by Naor Shlomo
Hello experts,
Could anyone please tell me if Multi Queue it fully supported in Libvirt and if so what version contains it?
Thanks,
Naor
8 years, 6 months
[libvirt] [libvirt-java] [PATCH 00/65]
by Claudio Bley
Hi.
Here are a few patches that piled up in my local branch. Some of them
I already submitted to this list, but there has been no reponse to
them.
Included are a few trivial fixes as well as memory leak fixes and
additions to the public API.
There had been some minor interest in my first version of domain event
support in the Java wrapper[1], which I have reworked almost entirely.
If nobody objects, say, within the next two weeks or so, I'll go ahead
and push the whole series as was suggested to me by Daniel P. Berrange
on this list[2].
I've made sure that all JUnit tests pass after every commit with JNA
versions 3.4.1, 3.4.2, 3.5.0, 3.5.1, 3.5.2 and 4.0.0.
I'd really appreciate your comments or suggestions.
Thanks!
[1]: https://www.redhat.com/archives/libvir-list/2013-January/msg01236.html
[2]: https://www.redhat.com/archives/libvir-list/2014-January/msg01091.html
Claudio Bley (65):
Fix warnings about using raw types
Fix warnings about accessing static methods
Fix typos in Error.java
test: fix typo in testConnection()
test: ensure that exceptions are thrown when expected
Make comments proper javadoc comments for enum constants
Ignore editor backup files
Depend on JNA versions 3.4.1 to 4.0.0
jna: load virt-0 or virt library depending on the platform
Fix wrapping of native size_t data type
Use virFree in order to release memory acquired from libvirt
tests: remove obsolete test driver
Make Device.listCapabilities return only valid array elements
test: ensure the Device.listCapabilities method works
Start refactoring of error handling
Remove processError from Device class
Remove processError from Domain class
Remove processError from DomainSnapshot class
Remove processError from Interface class
Remove processError method from Network class
Remove processError method from NetworkFilter class
Remove processError method from Secret class
Remove processError method from StoragePool class
Remove processError method from StorageVol class
Remove processError method from Stream class
Remove processError method from Connect class
Call processError only when virInitialize signalled an error
Remove ErrorHandler.processError(Libvirt) method
Implement equals and hashCode methods for Connect and Domain
Fix Domain.getSchedulerParameters / getSchedulerType
Fix memleak in Domain.snapshotListNames
Fix memleak in StoragePool.listVolumes
Fix memleak in DomainSnapshot.getXMLDesc
Fix memleak in StorageVol.getPath
Fix memleak in StorageVol.getXMLDesc
jna: Wrap the virEvent(Add,Remove)Timeout libvirt functions
Implement Connect.isAlive
Implement Connect.setKeepAlive
Introduce event loop support
Add constants for enum virDomainEventID
Prepare to define proper domain event callback support
Add constructIncRef factory method to Domain class
events: handle registration for IOError events
events: handle registration for Reboot events
events: handle registration of domain lifecycle events
test: add unit test for domain lifecycle events
events: handle registration for PMWakeup events
events: add support for PMSuspend events
Implement connection close callback support
Implement Connect.getSysinfo
Implement Domain.blockPeek
Implement Domain.memoryPeek
Implement Secret.getUsageType
Implement Domain.isUpdated
Implement Domain.reset
Implement Domain.PMwakeup
Implement Domain.sendKey
Implement interface ByteChannel for Stream class
Implement Domain.screenshot
test: add testDomainScreenshot JUnit test
Add helper for handling bit-flags
Connect: add constructors using java.net.URI params
Replace Connect.getLibVirVersion method with Library.getVersion
Replace static connectionVersion method with getLibVersion
Deprecate Connect.getHypervisorVersion
.gitignore | 2 +
pom.xml.in | 2 +-
src/main/java/org/libvirt/BitFlags.java | 18 +
src/main/java/org/libvirt/Connect.java | 731 +++++++++++++++++---
src/main/java/org/libvirt/Device.java | 57 +-
src/main/java/org/libvirt/Domain.java | 672 +++++++++++-------
src/main/java/org/libvirt/DomainSnapshot.java | 29 +-
src/main/java/org/libvirt/Error.java | 409 +++++++----
src/main/java/org/libvirt/ErrorHandler.java | 54 +-
src/main/java/org/libvirt/Interface.java | 43 +-
src/main/java/org/libvirt/KeycodeSet.java | 46 ++
src/main/java/org/libvirt/Library.java | 134 +++-
src/main/java/org/libvirt/MemoryAddressMode.java | 19 +
src/main/java/org/libvirt/Network.java | 61 +-
src/main/java/org/libvirt/NetworkFilter.java | 43 +-
src/main/java/org/libvirt/Secret.java | 72 +-
src/main/java/org/libvirt/SecretUsageType.java | 23 +
src/main/java/org/libvirt/StoragePool.java | 106 ++-
src/main/java/org/libvirt/StorageVol.java | 68 +-
src/main/java/org/libvirt/Stream.java | 232 +++++--
src/main/java/org/libvirt/SuspendTarget.java | 15 +
src/main/java/org/libvirt/event/CrashedDetail.java | 15 +
src/main/java/org/libvirt/event/DefinedDetail.java | 17 +
src/main/java/org/libvirt/event/DetailInfo.java | 5 +
src/main/java/org/libvirt/event/DomainEvent.java | 71 ++
.../java/org/libvirt/event/DomainEventDetail.java | 7 +
.../java/org/libvirt/event/DomainEventType.java | 60 ++
src/main/java/org/libvirt/event/EventListener.java | 7 +
src/main/java/org/libvirt/event/IOErrorAction.java | 39 ++
.../java/org/libvirt/event/IOErrorListener.java | 21 +
.../java/org/libvirt/event/LifecycleListener.java | 24 +
.../java/org/libvirt/event/PMSuspendListener.java | 17 +
.../java/org/libvirt/event/PMSuspendReason.java | 5 +
.../java/org/libvirt/event/PMSuspendedDetail.java | 15 +
.../java/org/libvirt/event/PMWakeupListener.java | 17 +
.../java/org/libvirt/event/PMWakeupReason.java | 5 +
.../java/org/libvirt/event/RebootListener.java | 15 +
src/main/java/org/libvirt/event/ResumedDetail.java | 20 +
.../java/org/libvirt/event/ShutdownDetail.java | 12 +
src/main/java/org/libvirt/event/StartedDetail.java | 30 +
src/main/java/org/libvirt/event/StoppedDetail.java | 40 ++
.../java/org/libvirt/event/SuspendedDetail.java | 40 ++
.../java/org/libvirt/event/UndefinedDetail.java | 7 +
src/main/java/org/libvirt/jna/Libvirt.java | 121 +++-
src/main/java/org/libvirt/jna/SizeT.java | 19 +
.../java/org/libvirt/jna/SizeTByReference.java | 50 ++
src/main/java/org/libvirt/jna/virConnectAuth.java | 4 +-
.../java/org/libvirt/jna/virConnectCredential.java | 4 +-
.../java/org/libvirt/jna/virDomainBlockInfo.java | 4 +-
.../java/org/libvirt/jna/virDomainBlockStats.java | 4 +-
src/main/java/org/libvirt/jna/virDomainInfo.java | 4 +-
.../org/libvirt/jna/virDomainInterfaceStats.java | 4 +-
.../java/org/libvirt/jna/virDomainJobInfo.java | 4 +-
.../java/org/libvirt/jna/virDomainMemoryStats.java | 4 +-
src/main/java/org/libvirt/jna/virError.java | 4 +-
src/main/java/org/libvirt/jna/virNodeInfo.java | 4 +-
.../java/org/libvirt/jna/virSchedParameter.java | 4 +-
.../java/org/libvirt/jna/virStoragePoolInfo.java | 4 +-
.../java/org/libvirt/jna/virStorageVolInfo.java | 4 +-
src/main/java/org/libvirt/jna/virVcpuInfo.java | 4 +-
src/test/java/org/libvirt/TestJavaBindings.java | 139 +++-
src/test/java/org/libvirt/TestLibvirtGlobals.java | 4 +
src/test/java/test.java | 280 --------
63 files changed, 2807 insertions(+), 1187 deletions(-)
create mode 100644 src/main/java/org/libvirt/BitFlags.java
create mode 100644 src/main/java/org/libvirt/KeycodeSet.java
create mode 100644 src/main/java/org/libvirt/MemoryAddressMode.java
create mode 100644 src/main/java/org/libvirt/SecretUsageType.java
create mode 100644 src/main/java/org/libvirt/SuspendTarget.java
create mode 100644 src/main/java/org/libvirt/event/CrashedDetail.java
create mode 100644 src/main/java/org/libvirt/event/DefinedDetail.java
create mode 100644 src/main/java/org/libvirt/event/DetailInfo.java
create mode 100644 src/main/java/org/libvirt/event/DomainEvent.java
create mode 100644 src/main/java/org/libvirt/event/DomainEventDetail.java
create mode 100644 src/main/java/org/libvirt/event/DomainEventType.java
create mode 100644 src/main/java/org/libvirt/event/EventListener.java
create mode 100644 src/main/java/org/libvirt/event/IOErrorAction.java
create mode 100644 src/main/java/org/libvirt/event/IOErrorListener.java
create mode 100644 src/main/java/org/libvirt/event/LifecycleListener.java
create mode 100644 src/main/java/org/libvirt/event/PMSuspendListener.java
create mode 100644 src/main/java/org/libvirt/event/PMSuspendReason.java
create mode 100644 src/main/java/org/libvirt/event/PMSuspendedDetail.java
create mode 100644 src/main/java/org/libvirt/event/PMWakeupListener.java
create mode 100644 src/main/java/org/libvirt/event/PMWakeupReason.java
create mode 100644 src/main/java/org/libvirt/event/RebootListener.java
create mode 100644 src/main/java/org/libvirt/event/ResumedDetail.java
create mode 100644 src/main/java/org/libvirt/event/ShutdownDetail.java
create mode 100644 src/main/java/org/libvirt/event/StartedDetail.java
create mode 100644 src/main/java/org/libvirt/event/StoppedDetail.java
create mode 100644 src/main/java/org/libvirt/event/SuspendedDetail.java
create mode 100644 src/main/java/org/libvirt/event/UndefinedDetail.java
create mode 100644 src/main/java/org/libvirt/jna/SizeT.java
create mode 100644 src/main/java/org/libvirt/jna/SizeTByReference.java
delete mode 100644 src/test/java/test.java
--
1.7.9.5
10 years, 1 month
[libvirt] [RFC PATCH v2 0/3] qemu: RDMA live migration support
by mrhines@linux.vnet.ibm.com
From: "Michael R. Hines" <mrhines(a)us.ibm.com>
Changes since v1:
1. This series uses 'rdma' instead of 'x-rdma', even though QEMU
has has not yet renamed URI for live migraiton yet, but this
series is just an RFC, so at least we can get some agreement.
2. We've fixed the job stats to be in the right place instead
of breaking the hard-coded api.
Michael R. Hines (3):
qemu: Expose additional timing metrics for 'setup' and 'mbps'
qemu: RDMA migration support using 'rdma' URI
qemu: memory pre-pinning support for RDMA migration
include/libvirt/libvirt.h.in | 16 ++++
src/qemu/qemu_capabilities.c | 13 ++++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 8 ++
src/qemu/qemu_driver.c | 14 ++++
src/qemu/qemu_migration.c | 174 +++++++++++++++++++++++++++++++++++++------
src/qemu/qemu_migration.h | 3 +-
src/qemu/qemu_monitor.c | 5 +-
src/qemu/qemu_monitor.h | 14 ++++
src/qemu/qemu_monitor_json.c | 8 ++
src/util/viruri.c | 7 +-
tools/virsh-domain.c | 7 ++
12 files changed, 244 insertions(+), 26 deletions(-)
--
1.8.1.2
10 years, 8 months
[libvirt] [PATCH] add flag to enforce hugepage backing of guest RAM
by Marcelo Tosatti
Add an element named "strict-hugepages" to control whether to
refuse guest initialization in case hugepage allocation cannot
be performed.
Signed-off-by: Marcelo Tosatti <mtosatti(a)redhat.com>
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index ff50214..e79f5e6 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -632,6 +632,9 @@
<dt><code>hugepages</code></dt>
<dd>This tells the hypervisor that the guest should have its memory
allocated using hugepages instead of the normal native page size.</dd>
+ <dt><code>strict-hugepages</code></dt>
+ <dd>This tells the hypervisor that the guest should refuse to start
+ in case of failure to allocate guest memory with hugepages</dd>
<dt><code>nosharepages</code></dt>
<dd>Instructs hypervisor to disable shared pages (memory merge, KSM) for
this domain. <span class="since">Since 1.0.6</span></dd>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 28e24f9..f16ef0b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -11226,6 +11226,9 @@ virDomainDefParseXML(xmlDocPtr xml,
if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt))
def->mem.locked = true;
+ if ((node = virXPathNode("./memoryBacking/stricthugepages", ctxt)))
+ def->mem.strict_hugepages = true;
+
/* Extract blkio cgroup tunables */
if (virXPathUInt("string(./blkiotune/weight)", ctxt,
&def->blkio.weight) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d8f2e49..8ea5cf0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1977,6 +1977,7 @@ struct _virDomainDef {
unsigned long long max_balloon; /* in kibibytes */
unsigned long long cur_balloon; /* in kibibytes */
bool hugepage_backed;
+ bool strict_hugepages;
bool nosharepages;
bool locked;
int dump_core; /* enum virDomainMemDump */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 96b8825..3f8d0a4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -12133,10 +12133,9 @@ cleanup:
return def;
}
-
-static int qemuParseProcFileStrings(int pid_value,
- const char *name,
- char ***list)
+int qemuParseProcFileStrings(int pid_value,
+ const char *name,
+ char ***list)
{
char *path = NULL;
int ret = -1;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index de7683d..bcdfefa 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -226,7 +226,9 @@ virDomainDefPtr qemuParseCommandLinePid(virCapsPtr qemuCaps,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON);
-
+int qemuParseProcFileStrings(int pid_value,
+ const char *name,
+ char ***list);
int qemuDomainAssignAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
virDomainObjPtr obj)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 8bcd98e..cb8298e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
+#include <stdlib.h>
#if defined(__linux__)
# include <linux/capability.h>
#elif defined(__FreeBSD__)
@@ -3507,6 +3508,95 @@ error:
}
+/*
+ * Returns bool: whether to fail guest initialization.
+ *
+ */
+static bool qemuValidateStrictHugepage(virDomainObjPtr vm, virQEMUDriverConfigPtr cfg)
+{
+ bool ret = false;
+ char **maps = NULL;
+ int i;
+ char *buf;
+
+ if (!vm->def->mem.strict_hugepages)
+ return ret;
+
+ ret = true;
+
+ if (!vm->def->mem.hugepage_backed || !cfg->hugepagePath) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("strict huge pages depends on huge pages"));
+ return ret;
+ }
+
+ buf = malloc(strlen(cfg->hugepagePath) + 50);
+
+ /* The parser requires /proc/pid, which only exists on platforms
+ * like Linux where pid_t fits in int. */
+ if ((int) vm->pid != vm->pid ||
+ qemuParseProcFileStrings(vm->pid, "maps", &maps) < 0)
+ goto cleanup;
+
+ for (i = 0; maps && maps[i]; i++) {
+ char *endptr;
+ unsigned long start, end;
+ const char *map = maps[i];
+ bool found = false;
+
+ sprintf(buf, "%s/qemu_back_mem.pc.ram.", cfg->hugepagePath);
+ if (strstr(map,buf) != NULL)
+ found = true;
+
+ sprintf(buf, "%s/kvm.", cfg->hugepagePath);
+ if (strstr(map,buf) != NULL)
+ found = true;
+
+ if (!found)
+ continue;
+
+ errno = 0;
+ start = strtol(map, &endptr, 16);
+ if ((errno == ERANGE && (start == LONG_MAX || start == LONG_MIN))
+ || (errno != 0 && start == 0)) {
+ continue;
+ }
+
+ if (endptr && *endptr == '-')
+ endptr++;
+
+ if (!*endptr)
+ continue;
+
+ errno = 0;
+ end = strtol(endptr, NULL, 16);
+ if ((errno == ERANGE && (end == LONG_MAX || end == LONG_MIN))
+ || (errno != 0 && end == 0)) {
+ continue;
+ }
+
+ if (end-start >= vm->def->mem.max_balloon * 1024) {
+ ret = false;
+ break;
+ }
+ }
+
+ if (ret) {
+ /* FIXME: is VIR_ERR_NO_MEMORY to be used exclusively
+ * to reference libvirt allocation failures?
+ */
+ virReportError(VIR_ERR_NO_MEMORY, "%s",
+ _("guest memory not hugetlbfs backed"));
+ }
+
+cleanup:
+ for (i = 0; maps && maps[i]; i++)
+ VIR_FREE(maps[i]);
+ free(buf);
+ return ret;
+}
+
+
static bool
qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
{
@@ -4071,6 +4161,13 @@ int qemuProcessStart(virConnectPtr conn,
goto cleanup;
}
+ /* enforce strict hugepage */
+ if (qemuValidateStrictHugepage(vm, cfg)) {
+ VIR_WARN("Failure to allocate hugepage backing for %s, exiting",
+ vm->def->name);
+ goto cleanup;
+ }
+
/* set default link states */
/* qemu doesn't support setting this on the command line, so
* enter the monitor */
10 years, 8 months
[libvirt] [PATCH] maint: use $(SED) instead of sed for syntax-check
by Roman Bogorodskiy
Some syntax-check rules use GNU sed specific regexps, so allow
to override which sed would be used to fix 'syntax-check' for
non GNU-userland systems.
---
cfg.mk | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index 207dfeb..bd984bd 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -614,7 +614,7 @@ sc_libvirt_unmarked_diagnostics:
$(_sc_search_regexp)
@{ grep -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT)); \
grep -A1 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \
- | sed 's/_("\([^\"]\|\\.\)\+"//;s/[ ]"%s"//' \
+ | $(SED) 's/_("\([^\"]\|\\.\)\+"//;s/[ ]"%s"//' \
| grep '[ ]"' && \
{ echo '$(ME): found unmarked diagnostic(s)' 1>&2; \
exit 1; } || :
@@ -639,7 +639,7 @@ sc_prohibit_newline_at_end_of_diagnostic:
sc_prohibit_diagnostic_without_format:
@{ grep -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT)); \
grep -A2 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \
- | sed -rn -e ':l; /[,"]$$/ {N;b l;}' \
+ | $(SED) -rn -e ':l; /[,"]$$/ {N;b l;}' \
-e '/(xenapiSessionErrorHandler|vah_(error|warning))/d' \
-e '/\<$(func_re) *\([^"]*"([^%"]|"\n[^"]*")*"[,)]/p' \
| grep -vE 'VIR_ERROR' && \
@@ -661,7 +661,7 @@ sc_prohibit_useless_translation:
# or \n on one side of the split.
sc_require_whitespace_in_translation:
@grep -n -A1 '"$$' $$($(VC_LIST_EXCEPT)) \
- | sed -ne ':l; /"$$/ {N;b l;}; s/"\n[^"]*"/""/g; s/\\n/ /g' \
+ | $(SED) -ne ':l; /"$$/ {N;b l;}; s/"\n[^"]*"/""/g; s/\\n/ /g' \
-e '/_(.*[^\ ]""[^\ ]/p' | grep . && \
{ echo '$(ME): missing whitespace at line split' 1>&2; \
exit 1; } || :
@@ -681,11 +681,11 @@ sc_preprocessor_indentation:
sc_spec_indentation:
@if cppi --version >/dev/null 2>&1; then \
for f in $$($(VC_LIST_EXCEPT) | grep '\.spec\.in$$'); do \
- sed -e 's|#|// #|; s|%ifn*\(arch\)* |#if a // |' \
+ $(SED) -e 's|#|// #|; s|%ifn*\(arch\)* |#if a // |' \
-e 's/%\(else\|endif\|define\)/#\1/' \
-e 's/^\( *\)\1\1\1#/#\1/' \
-e 's|^\( *[^#/ ]\)|// \1|; s|^\( */[^/]\)|// \1|' $$f \
- | cppi -a -c 2>&1 | sed "s|standard input|$$f|"; \
+ | cppi -a -c 2>&1 | $(SED) "s|standard input|$$f|"; \
done | { if grep . >&2; then false; else :; fi; } \
|| { echo '$(ME): incorrect preprocessor indentation' 1>&2; \
exit 1; }; \
@@ -777,7 +777,7 @@ sc_prohibit_cross_inclusion:
# elements added to the enum by using a _LAST marker.
sc_require_enum_last_marker:
@grep -A1 -nE '^[^#]*VIR_ENUM_IMPL *\(' $$($(VC_LIST_EXCEPT)) \
- | sed -ne '/VIR_ENUM_IMPL[^,]*,$$/N' \
+ | $(SED) -ne '/VIR_ENUM_IMPL[^,]*,$$/N' \
-e '/VIR_ENUM_IMPL[^,]*,[^,]*[^_,][^L,][^A,][^S,][^T,],/p' \
-e '/VIR_ENUM_IMPL[^,]*,[^,]\{0,4\},/p' \
| grep . && \
@@ -878,7 +878,7 @@ ifeq (0,$(MAKELEVEL))
# b653eda3ac4864de205419d9f41eec267cb89eeb
#
# Keep this logic in sync with autogen.sh.
- _submodule_hash = sed 's/^[ +-]//;s/ .*//'
+ _submodule_hash = $(SED) 's/^[ +-]//;s/ .*//'
_update_required := $(shell \
cd '$(srcdir)'; \
test -d .git || { echo 0; exit; }; \
--
1.8.4.3
10 years, 9 months
[libvirt] [python PATCH 1/2] qemu: support arbitrary monitor events
by Eric Blake
Wrap the new virConnectDomainQemuMonitorEventRegister function
being added in libvirt 1.2.2. This patch copies heavily from
network events (commit 6ea5be0) and from event loop callbacks
in libvirt-override.c, since in the libvirt_qemu module, we
must expose top-level functions rather than class members.
* generator.py (qemu_skip_function): Don't generate event code.
(qemuBuildWrappers): Delay manual portion until after imports.
* libvirt-qemu-override.py (qemuMonitorEventRegister)
(qemuMonitorEventDeregister): New file.
* libvirt-qemu-override.c
(libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc)
(libvirt_qemu_virConnectDomainQemuMonitorEventCallback)
(libvirt_qemu_virConnectDomainQemuMonitorEventRegister)
(libvirt_qemu_virConnectDomainQemuMonitorEventDeregister)
(libvirt_qemu_lookupPythonFunc, getLibvirtQemuDictObject)
(getLibvirtQemuModuleObject): New functions.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
generator.py | 20 +++--
libvirt-qemu-override.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++-
libvirt-qemu-override.py | 36 ++++++++
3 files changed, 268 insertions(+), 9 deletions(-)
create mode 100644 libvirt-qemu-override.py
diff --git a/generator.py b/generator.py
index 42f3913..e2325b0 100755
--- a/generator.py
+++ b/generator.py
@@ -570,6 +570,8 @@ lxc_skip_function = (
)
qemu_skip_function = (
#"virDomainQemuAttach",
+ 'virConnectDomainQemuMonitorEventRegister', # overridden in -qemu.py
+ 'virConnectDomainQemuMonitorEventDeregister', # overridden in -qemu.py
)
# Generate C code, but skip python impl
@@ -1803,16 +1805,8 @@ def qemuBuildWrappers(module):
fd.write("#\n")
fd.write("# WARNING WARNING WARNING WARNING\n")
fd.write("#\n")
- if extra is not None:
- fd.writelines(extra.readlines())
- fd.write("#\n")
- fd.write("# WARNING WARNING WARNING WARNING\n")
- fd.write("#\n")
fd.write("# Automatically written part of python bindings for libvirt\n")
fd.write("#\n")
- fd.write("# WARNING WARNING WARNING WARNING\n")
- if extra is not None:
- extra.close()
fd.write("try:\n")
fd.write(" import libvirtmod_qemu\n")
@@ -1826,6 +1820,16 @@ def qemuBuildWrappers(module):
fd.write(" raise lib_e\n\n")
fd.write("import libvirt\n\n")
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ fd.write("#\n")
+ if extra is not None:
+ fd.writelines(extra.readlines())
+ fd.write("#\n")
+ if extra is not None:
+ extra.close()
+
+ fd.write("# WARNING WARNING WARNING WARNING\n")
+ fd.write("#\n")
fd.write("#\n# Functions from module %s\n#\n\n" % module)
#
# Generate functions directly, no classes
diff --git a/libvirt-qemu-override.c b/libvirt-qemu-override.c
index 480a7d3..0abcd3f 100644
--- a/libvirt-qemu-override.c
+++ b/libvirt-qemu-override.c
@@ -4,7 +4,7 @@
* entry points where an automatically generated stub is
* unpractical
*
- * Copyright (C) 2011-2012 Red Hat, Inc.
+ * Copyright (C) 2011-2014 Red Hat, Inc.
*
* Daniel Veillard <veillard(a)redhat.com>
*/
@@ -54,6 +54,76 @@ extern void initcygvirtmod_qemu(void);
#define VIR_PY_INT_FAIL (libvirt_intWrap(-1))
#define VIR_PY_INT_SUCCESS (libvirt_intWrap(0))
+/*******************************************
+ * Helper functions to avoid importing modules
+ * for every callback
+ *******************************************/
+#if LIBVIR_CHECK_VERSION(1, 2, 2)
+static PyObject *libvirt_qemu_module;
+static PyObject *libvirt_qemu_dict;
+
+static PyObject *
+getLibvirtQemuModuleObject(void)
+{
+ if (libvirt_qemu_module)
+ return libvirt_qemu_module;
+
+ // PyImport_ImportModule returns a new reference
+ /* Bogus (char *) cast for RHEL-5 python API brokenness */
+ libvirt_qemu_module = PyImport_ImportModule((char *)"libvirt_qemu");
+ if (!libvirt_qemu_module) {
+ DEBUG("%s Error importing libvirt_qemu module\n", __FUNCTION__);
+ PyErr_Print();
+ return NULL;
+ }
+
+ return libvirt_qemu_module;
+}
+
+static PyObject *
+getLibvirtQemuDictObject(void)
+{
+ if (libvirt_qemu_dict)
+ return libvirt_qemu_dict;
+
+ // PyModule_GetDict returns a borrowed reference
+ libvirt_qemu_dict = PyModule_GetDict(getLibvirtQemuModuleObject());
+ if (!libvirt_qemu_dict) {
+ DEBUG("%s Error importing libvirt_qemu dictionary\n", __FUNCTION__);
+ PyErr_Print();
+ return NULL;
+ }
+
+ Py_INCREF(libvirt_qemu_dict);
+ return libvirt_qemu_dict;
+}
+
+
+static PyObject *
+libvirt_qemu_lookupPythonFunc(const char *funcname)
+{
+ PyObject *python_cb;
+
+ /* Lookup the python callback */
+ python_cb = PyDict_GetItemString(getLibvirtQemuDictObject(), funcname);
+
+ if (!python_cb) {
+ DEBUG("%s: Error finding %s\n", __FUNCTION__, funcname);
+ PyErr_Print();
+ PyErr_Clear();
+ return NULL;
+ }
+
+ if (!PyCallable_Check(python_cb)) {
+ DEBUG("%s: %s is not callable\n", __FUNCTION__, funcname);
+ return NULL;
+ }
+
+ return python_cb;
+}
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 2) */
+
+
/************************************************************************
* *
* Statistics *
@@ -122,6 +192,151 @@ libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject
}
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
+
+#if LIBVIR_CHECK_VERSION(1, 2, 2)
+static void
+libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc(void *opaque)
+{
+ PyObject *pyobj_conn = (PyObject*)opaque;
+ LIBVIRT_ENSURE_THREAD_STATE;
+ Py_DECREF(pyobj_conn);
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+static void
+libvirt_qemu_virConnectDomainQemuMonitorEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ const char *event,
+ long long seconds,
+ unsigned int micros,
+ const char *details,
+ void *opaque)
+{
+ PyObject *pyobj_cbData = (PyObject*)opaque;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_ret;
+ PyObject *pyobj_conn;
+ PyObject *dictKey;
+ PyObject *pyobj_cb;
+
+ LIBVIRT_ENSURE_THREAD_STATE;
+
+ pyobj_cb = libvirt_qemu_lookupPythonFunc("_dispatchQemuMonitorEventCallback");
+ if (!pyobj_cb) {
+ goto cleanup;
+ }
+
+ dictKey = libvirt_constcharPtrWrap("conn");
+ if (!dictKey)
+ return;
+ pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+ Py_DECREF(dictKey);
+
+ /* Create a python instance of this virDomainPtr */
+ virDomainRef(dom);
+ pyobj_dom = libvirt_virDomainPtrWrap(dom);
+ Py_INCREF(pyobj_cbData);
+
+ /* Call the Callback Dispatcher */
+ pyobj_ret = PyObject_CallFunction(pyobj_cb,
+ (char *)"OOsLIsO",
+ pyobj_conn, pyobj_dom, event, seconds,
+ micros, details, pyobj_cbData);
+
+ Py_DECREF(pyobj_cbData);
+ Py_DECREF(pyobj_dom);
+
+ if (!pyobj_ret) {
+ DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+ PyErr_Print();
+ } else {
+ Py_DECREF(pyobj_ret);
+ }
+
+cleanup:
+ LIBVIRT_RELEASE_THREAD_STATE;
+}
+
+
+static PyObject *
+libvirt_qemu_virConnectDomainQemuMonitorEventRegister(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ PyObject *pyobj_dom;
+ PyObject *pyobj_cbData;
+ const char *event;
+ virConnectPtr conn;
+ int ret = 0;
+ virConnectDomainQemuMonitorEventCallback cb = NULL;
+ virDomainPtr dom;
+ unsigned int flags;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "OOzOI",
+ &pyobj_conn, &pyobj_dom, &event, &pyobj_cbData, &flags)) {
+ DEBUG("%s failed parsing tuple\n", __FUNCTION__);
+ return VIR_PY_INT_FAIL;
+ }
+
+ DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventRegister(%p %p %s %p %x) called\n",
+ pyobj_conn, pyobj_dom, NULLSTR(event), pyobj_cbData, flags);
+ conn = PyvirConnect_Get(pyobj_conn);
+ if (pyobj_dom == Py_None)
+ dom = NULL;
+ else
+ dom = PyvirDomain_Get(pyobj_dom);
+
+ cb = libvirt_qemu_virConnectDomainQemuMonitorEventCallback;
+
+ Py_INCREF(pyobj_cbData);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ret = virConnectDomainQemuMonitorEventRegister(conn, dom, event,
+ cb, pyobj_cbData,
+ libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc,
+ flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (ret < 0)
+ Py_DECREF(pyobj_cbData);
+
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+
+
+static PyObject *
+libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_conn;
+ int callbackID;
+ virConnectPtr conn;
+ int ret = 0;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "Oi:virConnectDomainQemuMonitorEventDeregister",
+ &pyobj_conn, &callbackID))
+ return NULL;
+
+ DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(%p) called\n",
+ pyobj_conn);
+
+ conn = PyvirConnect_Get(pyobj_conn);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+
+ ret = virConnectDomainQemuMonitorEventDeregister(conn, callbackID);
+
+ LIBVIRT_END_ALLOW_THREADS;
+ py_retval = libvirt_intWrap(ret);
+ return py_retval;
+}
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 2) */
+
/************************************************************************
* *
* The registration stuff *
@@ -133,6 +348,10 @@ static PyMethodDef libvirtQemuMethods[] = {
#if LIBVIR_CHECK_VERSION(0, 10, 0)
{(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL},
#endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */
+#if LIBVIR_CHECK_VERSION(1, 2, 2)
+ {(char *) "virConnectDomainQemuMonitorEventRegister", libvirt_qemu_virConnectDomainQemuMonitorEventRegister, METH_VARARGS, NULL},
+ {(char *) "virConnectDomainQemuMonitorEventDeregister", libvirt_qemu_virConnectDomainQemuMonitorEventDeregister, METH_VARARGS, NULL},
+#endif /* LIBVIR_CHECK_VERSION(1, 2, 2) */
{NULL, NULL, 0, NULL}
};
diff --git a/libvirt-qemu-override.py b/libvirt-qemu-override.py
new file mode 100644
index 0000000..ab48bec
--- /dev/null
+++ b/libvirt-qemu-override.py
@@ -0,0 +1,36 @@
+# Manually written part of python bindings for libvirt-qemu
+
+def _dispatchQemuMonitorEventCallback(conn, dom, event, seconds, micros, details, cbData):
+ """Dispatches events to python user qemu monitor event callbacks
+ """
+ cb = cbData["cb"]
+ opaque = cbData["opaque"]
+
+ cb(conn, libvirt.virDomain(conn, _obj=dom), event, seconds, micros, details, opaque)
+ return 0
+
+def qemuMonitorEventDeregister(conn, callbackID):
+ """Removes a qemu monitor event callback. De-registering for a callback
+ will disable delivery of this event type"""
+ try:
+ ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventDeregister(conn._o, callbackID)
+ if ret == -1: raise libvirt.libvirtError ('virConnectDomainQemuMonitorEventDeregister() failed')
+ del conn.qemuMonitorEventCallbackID[callbackID]
+ except AttributeError:
+ pass
+
+def qemuMonitorEventRegister(conn, dom, event, cb, opaque, flags=0):
+ """Adds a qemu monitor event callback. Registering for a monitor
+ callback will enable delivery of the events"""
+ if not hasattr(conn, 'qemuMonitorEventCallbackID'):
+ conn.qemuMonitorEventCallbackID = {}
+ cbData = { "cb": cb, "conn": conn, "opaque": opaque }
+ if dom is None:
+ ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, None, event, cbData, flags)
+ else:
+ ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, dom._o, event, cbData, flags)
+ if ret == -1:
+ raise libvirt.libvirtError ('virConnectDomainQemuMonitorEventRegister() failed')
+ conn.qemuMonitorEventCallbackID[ret] = opaque
+ return ret
+
--
1.8.5.3
10 years, 9 months
[libvirt] [libvirt-python PATCH] setup: Make libvirt API XML path configurable
by Martin Kletzander
Adding a support for LIBVIRT_API_PATH evironment variable, which can
control where the script should look for the 'libvirt-api.xml' file.
This allows building libvirt-python against different libvirt than the
one installed in the system. This may be used for example in autotest
or by packagers without the need to install libvirt into the system.
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
setup.py | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index 17b4722..566c210 100755
--- a/setup.py
+++ b/setup.py
@@ -109,7 +109,17 @@ class my_build(build):
"""Check with pkg-config that libvirt is present and extract
the API XML file paths we need from it"""
- libvirt_api = get_pkgconfig_data(["--variable", "libvirt_api"], "libvirt")
+ libvirt_api = os.getenv("LIBVIRT_API_PATH")
+
+ if libvirt_api:
+ if not libvirt_api.endswith("-api.xml"):
+ raise ValueError("Invalid path '%s' for API XML" % libvirt_api)
+ if not os.path.exists(libvirt_api):
+ raise ValueError("API XML '%s' does not exist, "
+ "have you built libvirt?" % libvirt_api)
+ else:
+ libvirt_api = get_pkgconfig_data(["--variable", "libvirt_api"],
+ "libvirt")
offset = libvirt_api.index("-api.xml")
libvirt_qemu_api = libvirt_api[0:offset] + "-qemu-api.xml"
--
1.8.4.3
10 years, 9 months