[libvirt] [PATCH] drvbhyve: Automatically tear down guest domains on shutdown
by Conrad Meyer
Reboot requires more sophistication and is left as a future work item --
but at least part of the plumbing is in place.
---
src/Makefile.am | 2 +
src/bhyve/bhyve_monitor.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++
src/bhyve/bhyve_monitor.h | 36 +++++++++
src/bhyve/bhyve_process.c | 14 +++-
4 files changed, 233 insertions(+), 3 deletions(-)
create mode 100644 src/bhyve/bhyve_monitor.c
create mode 100644 src/bhyve/bhyve_monitor.h
diff --git a/src/Makefile.am b/src/Makefile.am
index d8fe624..b6c1701 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -833,6 +833,8 @@ BHYVE_DRIVER_SOURCES = \
bhyve/bhyve_domain.h \
bhyve/bhyve_driver.h \
bhyve/bhyve_driver.c \
+ bhyve/bhyve_monitor.c \
+ bhyve/bhyve_monitor.h \
bhyve/bhyve_process.c \
bhyve/bhyve_process.h \
bhyve/bhyve_utils.h \
diff --git a/src/bhyve/bhyve_monitor.c b/src/bhyve/bhyve_monitor.c
new file mode 100644
index 0000000..cd3cf6e
--- /dev/null
+++ b/src/bhyve/bhyve_monitor.c
@@ -0,0 +1,184 @@
+/*
+ * bhyve_monitor.c: Tear-down or reboot bhyve domains on guest shutdown
+ *
+ * Copyright (C) 2014 Conrad Meyer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Conrad Meyer <cse.cem(a)gmail.com>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include "bhyve_monitor.h"
+#include "bhyve_process.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_BHYVE
+
+VIR_LOG_INIT("bhyve.bhyve_monitor");
+
+struct _bhyveMonitor {
+ int kq;
+ int watch;
+ virDomainObjPtr vm;
+ bhyveConnPtr driver;
+};
+
+static void
+bhyveMonitorIO(int watch, int kq, int events ATTRIBUTE_UNUSED, void *opaque)
+{
+ const struct timespec zerowait = {};
+ bhyveMonitorPtr mon = opaque;
+ struct kevent kev;
+ int rc, status;
+
+ if (watch != mon->watch || kq != mon->kq) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("event from unexpected fd %d!=%d / watch %d!=%d"),
+ mon->kq, kq, mon->watch, watch);
+ return;
+ }
+
+ rc = kevent(kq, NULL, 0, &kev, 1, &zerowait);
+ if (rc < 0) {
+ virReportSystemError(errno, "%s", _("Unable to query kqueue"));
+ return;
+ }
+
+ if (rc == 0)
+ return;
+
+ if ((kev.flags & EV_ERROR) != 0) {
+ virReportSystemError(kev.data, "%s", _("Unable to query kqueue"));
+ return;
+ }
+
+ if (kev.filter == EVFILT_PROC && (kev.fflags & NOTE_EXIT) != 0) {
+ if ((pid_t)kev.ident != mon->vm->pid) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("event from unexpected proc %ju!=%ju"),
+ (uintmax_t)mon->vm->pid, (uintmax_t)kev.ident);
+ return;
+ }
+
+ status = kev.data;
+ if (WIFSIGNALED(status) && WCOREDUMP(status)) {
+ VIR_ERROR("Guest %s got signal %d and crashed", mon->vm->def->name,
+ WTERMSIG(status));
+ virBhyveProcessStop(mon->driver, mon->vm,
+ VIR_DOMAIN_SHUTOFF_CRASHED);
+ } else if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ /* 0 - reboot */
+ /* TODO: Implementing reboot is a little more complicated. */
+ VIR_INFO("Guest %s rebooted; destroying domain.",
+ mon->vm->def->name);
+ virBhyveProcessStop(mon->driver, mon->vm,
+ VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ } else if (WEXITSTATUS(status) < 3) {
+ /* 1 - shutdown, 2 - halt, 3 - triple fault. others - error */
+ VIR_INFO("Guest %s shut itself down; destroying domain.",
+ mon->vm->def->name);
+ virBhyveProcessStop(mon->driver, mon->vm,
+ VIR_DOMAIN_SHUTOFF_SHUTDOWN);
+ } else {
+ VIR_INFO("Guest %s had an error and exited with status %d; destroying domain.",
+ mon->vm->def->name, WEXITSTATUS(status));
+ virBhyveProcessStop(mon->driver, mon->vm,
+ VIR_DOMAIN_SHUTOFF_UNKNOWN);
+ }
+ }
+ }
+}
+
+static void
+bhyveMonitorRelease(void *opaque)
+{
+ bhyveMonitorPtr mon = opaque;
+
+ VIR_FORCE_CLOSE(mon->kq);
+ virObjectUnref(mon->vm);
+ VIR_FREE(mon);
+}
+
+bhyveMonitorPtr
+bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver)
+{
+ bhyveMonitorPtr mon;
+ struct kevent kev;
+ int rc;
+
+ if (VIR_ALLOC(mon) < 0)
+ return NULL;
+
+ mon->vm = virObjectRef(vm);
+ mon->driver = driver;
+
+ mon->kq = kqueue();
+ if (mon->kq < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("Unable to create kqueue"));
+ goto cleanup;
+ }
+
+ EV_SET(&kev, vm->pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, mon);
+ rc = kevent(mon->kq, &kev, 1, NULL, 0, NULL);
+ if (rc < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("Unable to register process kevent"));
+ goto cleanup;
+ }
+
+ mon->watch = virEventAddHandle(mon->kq,
+ VIR_EVENT_HANDLE_READABLE |
+ VIR_EVENT_HANDLE_ERROR |
+ VIR_EVENT_HANDLE_HANGUP,
+ bhyveMonitorIO,
+ mon,
+ bhyveMonitorRelease);
+ if (mon->watch < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unable to register monitor events"));
+ goto cleanup;
+ }
+
+ return mon;
+
+ cleanup:
+ bhyveMonitorRelease(mon);
+ return NULL;
+}
+
+void
+bhyveMonitorClose(bhyveMonitorPtr mon)
+{
+
+ if (mon == NULL)
+ return;
+
+ if (mon->watch > 0)
+ virEventRemoveHandle(mon->watch);
+ else
+ bhyveMonitorRelease(mon);
+}
diff --git a/src/bhyve/bhyve_monitor.h b/src/bhyve/bhyve_monitor.h
new file mode 100644
index 0000000..226d878
--- /dev/null
+++ b/src/bhyve/bhyve_monitor.h
@@ -0,0 +1,36 @@
+/*
+ * bhyve_monitor.h: Tear-down or reboot bhyve domains on guest shutdown
+ *
+ * Copyright (C) 2014 Conrad Meyer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Conrad Meyer <cse.cem(a)gmail.com>
+ */
+
+#ifndef BHYVE_MONITOR_H
+# define BHYVE_MONITOR_H
+
+# include "internal.h"
+# include "domain_conf.h"
+# include "bhyve_utils.h"
+
+typedef struct _bhyveMonitor bhyveMonitor;
+typedef bhyveMonitor *bhyveMonitorPtr;
+
+bhyveMonitorPtr bhyveMonitorOpen(virDomainObjPtr vm, bhyveConnPtr driver);
+void bhyveMonitorClose(bhyveMonitorPtr mon);
+
+#endif /* BHYVE_MONITOR_H */
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index a30e36a..284641a 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -32,8 +32,9 @@
#include <net/if_tap.h>
#include "bhyve_device.h"
-#include "bhyve_process.h"
#include "bhyve_command.h"
+#include "bhyve_monitor.h"
+#include "bhyve_process.h"
#include "datatypes.h"
#include "virerror.h"
#include "virlog.h"
@@ -209,6 +210,7 @@ virBhyveProcessStart(virConnectPtr conn,
vm->def->id = vm->pid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
+ vm->privateData = bhyveMonitorOpen(vm, driver);
if (virDomainSaveStatus(driver->xmlopt,
BHYVE_STATE_DIR,
@@ -268,6 +270,9 @@ virBhyveProcessStop(bhyveConnPtr driver,
return -1;
}
+ if (vm->privateData != NULL)
+ bhyveMonitorClose((bhyveMonitorPtr)vm->privateData);
+
/* First, try to kill 'bhyve' process */
if (virProcessKillPainfully(vm->pid, true) != 0)
VIR_WARN("Failed to gracefully stop bhyve VM '%s' (pid: %d)",
@@ -371,9 +376,12 @@ virBhyveProcessReconnect(virDomainObjPtr vm,
goto cleanup;
proc_argv = kvm_getargv(data->kd, kp, 0);
- if (proc_argv && proc_argv[0])
- if (STREQ(expected_proctitle, proc_argv[0]))
+ if (proc_argv && proc_argv[0]) {
+ if (STREQ(expected_proctitle, proc_argv[0])) {
ret = 0;
+ vm->privateData = bhyveMonitorOpen(vm, data->driver);
+ }
+ }
cleanup:
if (ret < 0) {
--
1.9.3
10 years
[libvirt] [PATCH 0/2] Fix fc_host SCSI pool refresh issues
by John Ferlan
https://bugzilla.redhat.com/show_bug.cgi?id=1152382
Fix a couple of fc_host SCSI refresh pool issues. The first patch I found
while working on the second.
It turns out the existing logic to handle 'retval' wasn't correct. Using
a default of zero, resulted in a couple of cases where success was returned
when it shouldn't have been. The one that caused the issues was when the
search of the /sys/bus/scsi/devices/ tree found a new vHBA related device
and then "assumed" that the 'block' device would be found in the directory.
That assumption resulted in a 10 second pause in virStorageBackendStablePath
failing to find a stable path to the device "/dev/(null)" because the
getBlockDevice returned zero and a NULL block_device and the processLU
code only failed when the return was < 0. The processLU code had similar
issues with retval processing which are also fixed.
The second patch provides a mechanism to attempt to fill the pool of a
libvirt created VPORT_CREATE'd vHBA. The creation takes some time for the
udev callback mechanism to find and configure. By adding a thread to
attempt to retry to find the LU's (with any luck) after the udev processing
has had time to do something means a subsequent 'vol-list' on the pool may
actually find a volume without needing to attempt a 'pool-refresh' again.
It's too bad the udev mechanism didn't provide a way to indicate it has
completed setting up a specific device.
John Ferlan (2):
storage: Fix issue finding LU's when block doesn't exist
storage: Add thread to refresh for createVport
src/storage/storage_backend_scsi.c | 147 ++++++++++++++++++++++++++++++++-----
1 file changed, 128 insertions(+), 19 deletions(-)
--
1.9.3
10 years
[libvirt] [PATCH] Fix API docs for header file re-organization
by Daniel P. Berrange
The API docs generators were broken by the header file
re-organization. Specifically
* html/libvirt-libvirt.html was empty (and should be deleted)
* Makefile.am didn't install html/libvirt-libvirt-*.html
* hvsupport.html was mostly empty
* sitemap.html.in didn't list the new html/*.html files
---
docs/Makefile.am | 17 +++++++--
docs/apibuild.py | 1 -
docs/hvsupport.pl | 101 +++++++++++++++++++++++++++++----------------------
docs/sitemap.html.in | 48 ++++++++++++++++++++++--
4 files changed, 115 insertions(+), 52 deletions(-)
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 9de3406..910bfef 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -25,9 +25,20 @@ DOC_SOURCE_DIR=../src
DEVHELP_DIR=$(datadir)/gtk-doc/html/libvirt
-apihtml = \
- html/index.html \
- html/libvirt-libvirt.html \
+apihtml = \
+ html/index.html \
+ html/libvirt-libvirt-domain.html \
+ html/libvirt-libvirt-domain-snapshot.html \
+ html/libvirt-libvirt-event.html \
+ html/libvirt-libvirt-host.html \
+ html/libvirt-libvirt.html \
+ html/libvirt-libvirt-interface.html \
+ html/libvirt-libvirt-network.html \
+ html/libvirt-libvirt-nodedev.html \
+ html/libvirt-libvirt-nwfilter.html \
+ html/libvirt-libvirt-secret.html \
+ html/libvirt-libvirt-storage.html \
+ html/libvirt-libvirt-stream.html \
html/libvirt-virterror.html
apipng = \
diff --git a/docs/apibuild.py b/docs/apibuild.py
index 797a7a5..7549a63 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -21,7 +21,6 @@ debugsym=None
# C parser analysis code
#
included_files = {
- "libvirt.h": "header with general libvirt API definitions",
"libvirt-domain.h": "header with general libvirt API definitions",
"libvirt-domain-snapshot.h": "header with general libvirt API definitions",
"libvirt-event.h": "header with general libvirt API definitions",
diff --git a/docs/hvsupport.pl b/docs/hvsupport.pl
index 6d8ed9c..96720eb 100755
--- a/docs/hvsupport.pl
+++ b/docs/hvsupport.pl
@@ -12,7 +12,17 @@ my $srcdir = shift @ARGV;
my $symslibvirt = "$srcdir/libvirt_public.syms";
my $symsqemu = "$srcdir/libvirt_qemu.syms";
my $symslxc = "$srcdir/libvirt_lxc.syms";
-my $drivertable = "$srcdir/driver.h";
+my @drivertable = (
+ "$srcdir/driver-hypervisor.h",
+ "$srcdir/driver-interface.h",
+ "$srcdir/driver-network.h",
+ "$srcdir/driver-nodedev.h",
+ "$srcdir/driver-nwfilter.h",
+ "$srcdir/driver-secret.h",
+ "$srcdir/driver-state.h",
+ "$srcdir/driver-storage.h",
+ "$srcdir/driver-stream.h",
+ );
my %groupheaders = (
"virHypervisorDriver" => "Hypervisor APIs",
@@ -182,41 +192,44 @@ $apis{virDomainMigrateConfirm3Params} = "1.1.0";
# and driver struct fields. This lets us later match
# update the driver impls with the public APis.
-open FILE, "<$drivertable"
- or die "cannot read $drivertable: $!";
-
# Group name -> hash of APIs { fields -> api name }
my %groups;
my $ingrp;
-while (defined($line = <FILE>)) {
- if ($line =~ /struct _(vir\w*Driver)/) {
- my $grp = $1;
- if ($grp ne "virStateDriver" &&
- $grp ne "virStreamDriver") {
- $ingrp = $grp;
- $groups{$ingrp} = { apis => {}, drivers => {} };
- }
- } elsif ($ingrp) {
- if ($line =~ /^\s*vir(?:Drv)(\w+)\s+(\w+);\s*$/) {
- my $field = $2;
- my $name = $1;
-
- my $api;
- if (exists $apis{"vir$name"}) {
- $api = "vir$name";
- } elsif ($name =~ /\w+(Open|Close)/) {
- next;
- } else {
- die "driver $name does not have a public API";
+foreach my $drivertable (@drivertable) {
+ open FILE, "<$drivertable"
+ or die "cannot read $drivertable: $!";
+
+ while (defined($line = <FILE>)) {
+ if ($line =~ /struct _(vir\w*Driver)/) {
+ my $grp = $1;
+ if ($grp ne "virStateDriver" &&
+ $grp ne "virStreamDriver") {
+ $ingrp = $grp;
+ warn "[$ingrp]";
+ $groups{$ingrp} = { apis => {}, drivers => {} };
+ }
+ } elsif ($ingrp) {
+ if ($line =~ /^\s*vir(?:Drv)(\w+)\s+(\w+);\s*$/) {
+ my $field = $2;
+ my $name = $1;
+
+ my $api;
+ if (exists $apis{"vir$name"}) {
+ $api = "vir$name";
+ } elsif ($name =~ /\w+(Open|Close)/) {
+ next;
+ } else {
+ die "driver $name does not have a public API";
+ }
+ $groups{$ingrp}->{apis}->{$field} = $api;
+ } elsif ($line =~ /};/) {
+ $ingrp = undef;
}
- $groups{$ingrp}->{apis}->{$field} = $api;
- } elsif ($line =~ /};/) {
- $ingrp = undef;
}
}
-}
-close FILE;
+ close FILE;
+}
# Finally, we read all the primary driver files and extract
@@ -290,43 +303,43 @@ foreach my $src (@srcs) {
# have a bit of manual fixup todo with the per-driver versioning
# and support matrix
-$groups{virDriver}->{apis}->{"openAuth"} = "virConnectOpenAuth";
-$groups{virDriver}->{apis}->{"openReadOnly"} = "virConnectOpenReadOnly";
-$groups{virDriver}->{apis}->{"domainMigrate"} = "virDomainMigrate";
+$groups{virHypervisorDriver}->{apis}->{"openAuth"} = "virConnectOpenAuth";
+$groups{virHypervisorDriver}->{apis}->{"openReadOnly"} = "virConnectOpenReadOnly";
+$groups{virHypervisorDriver}->{apis}->{"domainMigrate"} = "virDomainMigrate";
my $openAuthVers = (0 * 1000 * 1000) + (4 * 1000) + 0;
-foreach my $drv (keys %{$groups{"virDriver"}->{drivers}}) {
- my $openVersStr = $groups{"virDriver"}->{drivers}->{$drv}->{"connectOpen"};
+foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
+ my $openVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"};
my $openVers;
if ($openVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
$openVers = ($1 * 1000 * 1000) + ($2 * 1000) + $3;
}
# virConnectOpenReadOnly always matches virConnectOpen version
- $groups{"virDriver"}->{drivers}->{$drv}->{"connectOpenReadOnly"} =
- $groups{"virDriver"}->{drivers}->{$drv}->{"connectOpen"};
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenReadOnly"} =
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpen"};
# virConnectOpenAuth is always 0.4.0 if the driver existed
# before this time, otherwise it matches the version of
# the driver's virConnectOpen entry
if ($openVersStr eq "Y" ||
$openVers >= $openAuthVers) {
- $groups{"virDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = $openVersStr;
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = $openVersStr;
} else {
- $groups{"virDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = "0.4.0";
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"connectOpenAuth"} = "0.4.0";
}
}
# Another special case for the virDomainCreateLinux which was replaced
# with virDomainCreateXML
-$groups{virDriver}->{apis}->{"domainCreateLinux"} = "virDomainCreateLinux";
+$groups{virHypervisorDriver}->{apis}->{"domainCreateLinux"} = "virDomainCreateLinux";
my $createAPIVers = (0 * 1000 * 1000) + (0 * 1000) + 3;
-foreach my $drv (keys %{$groups{"virDriver"}->{drivers}}) {
- my $createVersStr = $groups{"virDriver"}->{drivers}->{$drv}->{"domainCreateXML"};
+foreach my $drv (keys %{$groups{"virHypervisorDriver"}->{drivers}}) {
+ my $createVersStr = $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateXML"};
next unless defined $createVersStr;
my $createVers;
if ($createVersStr =~ /(\d+)\.(\d+)\.(\d+)/) {
@@ -338,9 +351,9 @@ foreach my $drv (keys %{$groups{"virDriver"}->{drivers}}) {
# the driver's virCreateXML entry
if ($createVersStr eq "Y" ||
$createVers >= $createAPIVers) {
- $groups{"virDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = $createVersStr;
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = $createVersStr;
} else {
- $groups{"virDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = "0.0.3";
+ $groups{"virHypervisorDriver"}->{drivers}->{$drv}->{"domainCreateLinux"} = "0.0.3";
}
}
@@ -367,7 +380,7 @@ in.
EOF
-foreach my $grp (sort { $a cmp $b } keys %groups) {
+ foreach my $grp (sort { $a cmp $b } keys %groups) {
print "<h2><a name=\"$grp\">", $groupheaders{$grp}, "</a></h2>\n";
print <<EOF;
<table class="top_table">
diff --git a/docs/sitemap.html.in b/docs/sitemap.html.in
index 1e91869..fad5358 100644
--- a/docs/sitemap.html.in
+++ b/docs/sitemap.html.in
@@ -291,12 +291,52 @@
-->
<ul>
<li>
- <a href="html/libvirt-libvirt.html">libvirt</a>
- <span>core interfaces for the libvirt library</span>
+ <a href="html/libvirt-libvirt-domain.html">Domain</a>
+ <span>domain APIs for the libvirt library</span>
</li>
<li>
- <a href="html/libvirt-virterror.html">virterror</a>
- <span>error handling interfaces for the libvirt library</span>
+ <a href="html/libvirt-libvirt-domain-snapshot.html">Domain snapshot</a>
+ <span>domain snapshot APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-virterror.html">Error</a>
+ <span>error handling APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-event.html">Event</a>
+ <span>event APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-host.html">Host</a>
+ <span>host APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-interface.html">Interface</a>
+ <span>interface APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-network.html">Network</a>
+ <span>network APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-nodedev.html">Node device</a>
+ <span>node device APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-nwfilter.html">Network filter</a>
+ <span>network filter APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-secret.html">Secret</a>
+ <span>secret APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-storage.html">Storage</a>
+ <span>storage APIs for the libvirt library</span>
+ </li>
+ <li>
+ <a href="html/libvirt-libvirt-stream.html">Stream</a>
+ <span>stream APIs for the libvirt library</span>
</li>
<li>
<a href="hvsupport.html">Driver support</a>
--
2.1.0
10 years
[libvirt] [PATCH] build: fix build with older dbus headers
by Eric Blake
Compilation on a RHEL 5 host failed, due to the older dbus headers
present on that machine, and triggered by commit 2aa167ca:
util/virdbus.c: In function 'virDBusMessageIterDecode':
util/virdbus.c:952: error: 'DBusBasicValue' undeclared (first use in this function)
* m4/virt-dbus.m4 (LIBVIRT_CHECK_DBUS): Check for DBusBasicValue.
* src/util/virdbuspriv.h (DBusBasicValue): Provide fallback.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the build-breaker rule.
m4/virt-dbus.m4 | 3 ++-
src/util/virdbuspriv.h | 17 ++++++++++++++++-
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/m4/virt-dbus.m4 b/m4/virt-dbus.m4
index 4ef0c82..3f9b306 100644
--- a/m4/virt-dbus.m4
+++ b/m4/virt-dbus.m4
@@ -1,6 +1,6 @@
dnl The libdbus.so library
dnl
-dnl Copyright (C) 2012-2013 Red Hat, Inc.
+dnl Copyright (C) 2012-2014 Red Hat, Inc.
dnl
dnl This library is free software; you can redistribute it and/or
dnl modify it under the terms of the GNU Lesser General Public
@@ -26,6 +26,7 @@ AC_DEFUN([LIBVIRT_CHECK_DBUS],[
CFLAGS="$CFLAGS $DBUS_CFLAGS"
LIBS="$LIBS $DBUS_LIBS"
AC_CHECK_FUNCS([dbus_watch_get_unix_fd])
+ AC_CHECK_TYPES([DBusBasicValue], [], [], [[#include <dbus/dbus.h>]])
CFLAGS="$old_CFLAGS"
LIBS="$old_LIBS"
fi
diff --git a/src/util/virdbuspriv.h b/src/util/virdbuspriv.h
index d45fb25..4247746 100644
--- a/src/util/virdbuspriv.h
+++ b/src/util/virdbuspriv.h
@@ -1,7 +1,7 @@
/*
* virdbuspriv.h: internal APIs for testing DBus code
*
- * Copyright (C) 2012-2013 Red Hat, Inc.
+ * Copyright (C) 2012-2014 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
@@ -24,6 +24,21 @@
# include "virdbus.h"
+# if !HAVE_DBUSBASICVALUE
+/* Copied (and simplified) from dbus 1.6.12, for use with older dbus headers */
+typedef union
+{
+ dbus_int16_t i16; /**< as int16 */
+ dbus_uint16_t u16; /**< as int16 */
+ dbus_int32_t i32; /**< as int32 */
+ dbus_uint32_t u32; /**< as int32 */
+ dbus_bool_t bool_val; /**< as boolean */
+ dbus_int64_t i64; /**< as int64 */
+ dbus_uint64_t u64; /**< as int64 */
+ double dbl; /**< as double */
+ unsigned char byt; /**< as byte */
+} DBusBasicValue;
+# endif
int virDBusMessageEncodeArgs(DBusMessage* msg,
const char *types,
--
1.9.3
10 years
[libvirt] [libvirt PATCH] rpc: do not fail if the pid of the connecting process is not set
by Giuseppe Scrivano
getsockopt(sock->fd, SOL_SOCKET, SO_PEERCRED, ...) sets the pid to 0
when the process that opens the connection is in another container.
Signed-off-by: Giuseppe Scrivano <gscrivan(a)redhat.com>
---
src/rpc/virnetsocket.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 882fbec..6b019cc 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -1251,10 +1251,14 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock,
goto cleanup;
}
- if (virProcessGetStartTime(cr.pid, timestamp) < 0)
+ *timestamp = -1;
+ if (cr.pid && virProcessGetStartTime(cr.pid, timestamp) < 0)
goto cleanup;
- *pid = cr.pid;
+ if (cr.pid)
+ *pid = cr.pid;
+ else
+ *pid = -1;
*uid = cr.uid;
*gid = cr.gid;
--
1.9.3
10 years
[libvirt] [PATCH] util: don't log failure when older iptables lacks -w
by Eric Blake
Commit dc33e6e4 caused older platforms like Fedora 20 to emit
scary log messages at startup:
2014-11-19 23:12:58.800+0000: 28906: error : virCommandWait:2532 : internal error: Child process (/usr/sbin/iptables -w -L -n) unexpected exit status 2: iptables v1.4.19.1: unknown option "-w"
Try `iptables -h' or 'iptables --help' for more information.
Since we are probing and expect to handle the case where -w is not
supported, we should not let virCommand log it as an error.
* src/util/virfirewall.c (virFirewallCheckUpdateLock): Handle
non-zero status ourselves.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/util/virfirewall.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
index e82fdc3..8496062 100644
--- a/src/util/virfirewall.c
+++ b/src/util/virfirewall.c
@@ -112,8 +112,9 @@ static void
virFirewallCheckUpdateLock(bool *lockflag,
const char *const*args)
{
+ int status; /* Ignore failed commands without logging them */
virCommandPtr cmd = virCommandNewArgs(args);
- if (virCommandRun(cmd, NULL) < 0) {
+ if (virCommandRun(cmd, &status) < 0 || status) {
VIR_INFO("locking not supported by %s", args[0]);
} else {
VIR_INFO("using locking for %s", args[0]);
--
1.9.3
10 years
[libvirt] [PATCH] qemu: Really fix crash in tunnelled migration
by Jiri Denemark
Oops, I forgot to squash one more instance of the same check into the
previous commit (v1.2.10-144-g52691f9).
https://bugzilla.redhat.com/show_bug.cgi?id=1147331
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_migration.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 89313df..a1b1458 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2757,7 +2757,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
goto stop;
- if (STREQ(protocol, "rdma") &&
+ if (STREQ_NULLABLE(protocol, "rdma") &&
virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
goto stop;
}
--
2.1.3
10 years
[libvirt] [PATCHv3] virsh: Fix msg: blockjob is aborted from another client
by Erik Skultety
When a block{pull, copy, commit} is aborted via keyboard interrupt,
the job is properly canceled followed by proper error message.
However, when the job receives an abort from another client connected
to the same domain, the error message incorrectly indicates that
a blockjob has been finished successfully, though the abort request
took effect. This patch introduces a new blockjob abort handler, which
is registered when the client calls block{copy,commit,pull} routine,
providing its caller the status of the finished blockjob.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1135442
---
tools/virsh-domain.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 68 insertions(+), 3 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index a7e9151..0891821 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1709,6 +1709,17 @@ static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
intCaught = 1;
}
+static void
+vshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom ATTRIBUTE_UNUSED,
+ const char *disk ATTRIBUTE_UNUSED,
+ int type ATTRIBUTE_UNUSED,
+ int status,
+ void *opaque)
+{
+ *(int *) opaque = status;
+}
+
/*
* "blockcommit" command
*/
@@ -1808,6 +1819,8 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
const char *path = NULL;
bool quit = false;
int abort_flags = 0;
+ int status = -1;
+ int cb_id = -1;
blocking |= vshCommandOptBool(cmd, "timeout") || pivot || finish;
if (blocking) {
@@ -1837,6 +1850,17 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
return false;
}
+ virConnectDomainEventGenericCallback cb =
+ VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
+
+ if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn,
+ dom,
+ VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
+ cb,
+ &status,
+ NULL)) < 0)
+ vshResetLibvirtError();
+
if (!blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_COMMIT, &dom))
goto cleanup;
@@ -1878,7 +1902,7 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
intCaught ? "interrupted" : "timeout");
intCaught = 0;
timeout = 0;
- quit = true;
+ status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
vshError(ctl, _("failed to abort job for disk %s"), path);
goto cleanup;
@@ -1890,6 +1914,9 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
}
}
+ if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
+ quit = true;
+
if (verbose && !quit) {
/* printf [100 %] */
vshPrintJobProgress(_("Block Commit"), 0, 1);
@@ -1920,6 +1947,8 @@ cmdBlockCommit(vshControl *ctl, const vshCmd *cmd)
virDomainFree(dom);
if (blocking)
sigaction(SIGINT, &old_sig_action, NULL);
+ if (cb_id >= 0)
+ virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
return ret;
}
@@ -2043,6 +2072,8 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
char *xmlstr = NULL;
virTypedParameterPtr params = NULL;
int nparams = 0;
+ int status = -1;
+ int cb_id = -1;
if (vshCommandOptStringReq(ctl, cmd, "path", &path) < 0)
return false;
@@ -2083,6 +2114,17 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
return false;
}
+ virConnectDomainEventGenericCallback cb =
+ VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
+
+ if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn,
+ dom,
+ VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
+ cb,
+ &status,
+ NULL)) < 0)
+ vshResetLibvirtError();
+
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
goto cleanup;
@@ -2216,7 +2258,7 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
intCaught ? "interrupted" : "timeout");
intCaught = 0;
timeout = 0;
- quit = true;
+ status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
vshError(ctl, _("failed to abort job for disk %s"), path);
goto cleanup;
@@ -2228,6 +2270,9 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
}
}
+ if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
+ quit = true;
+
if (!quit && pivot) {
abort_flags |= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT;
if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
@@ -2256,6 +2301,8 @@ cmdBlockCopy(vshControl *ctl, const vshCmd *cmd)
virDomainFree(dom);
if (blocking)
sigaction(SIGINT, &old_sig_action, NULL);
+ if (cb_id >= 0)
+ virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
return ret;
}
@@ -2513,6 +2560,8 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
const char *path = NULL;
bool quit = false;
int abort_flags = 0;
+ int status = -1;
+ int cb_id = -1;
if (blocking) {
if (vshCommandOptTimeoutToMs(ctl, cmd, &timeout) < 0)
@@ -2538,6 +2587,17 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
return false;
}
+ virConnectDomainEventGenericCallback cb =
+ VIR_DOMAIN_EVENT_CALLBACK(vshBlockJobStatusHandler);
+
+ if ((cb_id = virConnectDomainEventRegisterAny(ctl->conn,
+ dom,
+ VIR_DOMAIN_EVENT_ID_BLOCK_JOB,
+ cb,
+ &status,
+ NULL)) < 0)
+ vshResetLibvirtError();
+
if (!blockJobImpl(ctl, cmd, VSH_CMD_BLOCK_JOB_PULL, &dom))
goto cleanup;
@@ -2574,7 +2634,7 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
intCaught ? "interrupted" : "timeout");
intCaught = 0;
timeout = 0;
- quit = true;
+ status = VIR_DOMAIN_BLOCK_JOB_CANCELED;
if (virDomainBlockJobAbort(dom, path, abort_flags) < 0) {
vshError(ctl, _("failed to abort job for disk %s"), path);
goto cleanup;
@@ -2586,6 +2646,9 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
}
}
+ if (status == VIR_DOMAIN_BLOCK_JOB_CANCELED)
+ quit = true;
+
if (verbose && !quit) {
/* printf [100 %] */
vshPrintJobProgress(_("Block Pull"), 0, 1);
@@ -2598,6 +2661,8 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
virDomainFree(dom);
if (blocking)
sigaction(SIGINT, &old_sig_action, NULL);
+ if (cb_id >= 0)
+ virConnectDomainEventDeregisterAny(ctl->conn, cb_id);
return ret;
}
--
1.9.3
10 years
[libvirt] [PATCH] qemu: Fix crash in tunnelled migration
by Jiri Denemark
Any attempt to start a tunnelled migration with libvirtd that supports
RDMA migration (specifically commit v1.2.8-226-ged22a47) crashes
libvirtd on the destination host.
The crash is inevitable because qemuMigrationPrepareAny is always called
with NULL protocol in case of tunnelled migration.
https://bugzilla.redhat.com/show_bug.cgi?id=1147331
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_migration.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 100600e..89313df 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2707,7 +2707,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
QEMU_MIGRATION_COOKIE_NBD)))
goto cleanup;
- if (STREQ(protocol, "rdma") && !vm->def->mem.hard_limit) {
+ if (STREQ_NULLABLE(protocol, "rdma") && !vm->def->mem.hard_limit) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot start RDMA migration with no memory hard "
"limit set"));
--
2.1.3
10 years
[libvirt] Libvirt Live Migration
by Dhia Abbassi
I'm trying to implement a virtualization API. I was testing migration with
libvirt I got some problems.
When I use the following command :
*virsh migrate --live --persistent --copy-storage-all vm-clone1
qemu+ssh://server_ip/system*
the migration works fine but in the destination host the migrated vm is
paused and I can't unpause it and I need to reboot the vm to be able use it
in the new host. When I try to unoause it Igot the following error message:
<< *Error unpausing domain: internal error: unable to execute QEMU command
'cont': Resetting the Virtual Machine is required *>>
How can I solve this problem, or is there an other way to make a live
migration with libvirt??
Thank you for you consideration.
--
Best regards
*Dhia Abbassi*
Full Stack Engineer | Rosafi Holding
<http://tn.linkedin.com/in/dhiaabbassi> <https://github.com/DhiaTN>
<https://plus.google.com/u/0/+DhiaAbbassi> <https://twitter.com/DhiaTN>
10 years