[libvirt] Is there a way to get host uptime in remote libvirt
by coffeeball
We manage hypervisors (VMWare ESXi/vCenter, KVM, XEN, Hyper-V) by remote Libvirt API, in our case we need to get the host uptime via the same libvirt interface. Is there a way get this info now for all the aforementioned hypervisor types?
The APIs virConnectGetSysinfo(), virNodeGetInfo() provide host info but it doesn't include the system uptime.
The virNodeGetCPUStats() can returns CPU usage in nanosecond, can we add the user + system + idle + iowait to calculate the system uptime? Looks like the sum value has a huge gap with the real uptime value returned by "uptime" CLI.
virsh # nodecpustats
user: 2985046540000000
system: 1368209710000000
idle: 388018933920000000
iowait: 43371960000000
10 years, 5 months
[libvirt] [PATCH] Don't use AI_ADDRCONFIG when binding to wildcard addresses
by Ján Tomko
https://bugzilla.redhat.com/show_bug.cgi?id=1098659
With parallel boot, network addresses might not yet be assigned [1],
but binding to wildcard addresses should work.
For non-wildcard addresses, ADDRCONFIG is still used. Document this
in libvirtd.conf.
[1] http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
---
daemon/libvirtd.conf | 4 ++++
src/rpc/virnetsocket.c | 28 ++++++++++++++++++++++++++--
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf
index aeba11d..e5856d4 100644
--- a/daemon/libvirtd.conf
+++ b/daemon/libvirtd.conf
@@ -48,6 +48,10 @@
# Override the default configuration which binds to all network
# interfaces. This can be a numeric IPv4/6 address, or hostname
#
+# If the libvirtd service is started in parallel with network
+# startup (e.g. with systemd), binding to addresses other than
+# the wildcards (0.0.0.0/::) might not be available yet.
+#
#listen_addr = "192.168.0.1"
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index a7e1783..87b39f2 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -226,15 +226,29 @@ int virNetSocketNewListenTCP(const char *nodename,
struct addrinfo hints;
int fd = -1;
size_t i;
- int addrInUse = false;
+ bool addrInUse = false;
+ bool familyNotSupported = false;
+ virSocketAddr tmp_addr;
*retsocks = NULL;
*nretsocks = 0;
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+ hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
+ /* Don't use ADDRCONFIG for binding to the wildcard address.
+ * Just catch the error returned by socket() if the system has
+ * no IPv6 support.
+ *
+ * This allows libvirtd to be started in parallel with the network
+ * startup in most cases.
+ */
+ if (nodename &&
+ !(virSocketAddrParse(&tmp_addr, nodename, AF_UNSPEC) > 0 &&
+ virSocketAddrIsWildcard(&tmp_addr)))
+ hints.ai_flags = AI_ADDRCONFIG;
+
int e = getaddrinfo(nodename, service, &hints, &ai);
if (e != 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
@@ -251,6 +265,11 @@ int virNetSocketNewListenTCP(const char *nodename,
if ((fd = socket(runp->ai_family, runp->ai_socktype,
runp->ai_protocol)) < 0) {
+ if (errno == EAFNOSUPPORT) {
+ familyNotSupported = true;
+ runp = runp->ai_next;
+ continue;
+ }
virReportSystemError(errno, "%s", _("Unable to create socket"));
goto error;
}
@@ -307,6 +326,11 @@ int virNetSocketNewListenTCP(const char *nodename,
fd = -1;
}
+ if (nsocks == 0 && familyNotSupported) {
+ virReportSystemError(EAFNOSUPPORT, "%s", _("Unable to bind to port"));
+ goto error;
+ }
+
if (nsocks == 0 &&
addrInUse) {
virReportSystemError(EADDRINUSE, "%s", _("Unable to bind to port"));
--
1.8.3.2
10 years, 5 months
[libvirt] [PATCH 0/4] qemu: Some more device unplug fixes
by Jiri Denemark
This series depends on "qemu: Process DEVICE_DELETED event in a separate
thread" series I sent yesterday.
Jiri Denemark (4):
qemu: Unref cfg when detaching hostdev interface
qemu: Remove interface backend only after frontend is gone
qemu: Remove disk backend only after frontend is gone
qemu: Remove character device backend only after frontend is gone
src/qemu/qemu_hotplug.c | 122 ++++++++++++++++++++++++------------------------
1 file changed, 60 insertions(+), 62 deletions(-)
--
1.9.3
10 years, 5 months
[libvirt] [PATCH 0/2] qemu: Process DEVICE_DELETED event in a separate thread
by Jiri Denemark
Jiri Denemark (2):
qemu: Finish device removal in the original thread
qemu: Process DEVICE_DELETED event in a separate thread
src/qemu/qemu_domain.h | 2 ++
src/qemu/qemu_driver.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_hotplug.c | 44 +++++++++++++++++++++++++++++++++-----------
src/qemu/qemu_hotplug.h | 2 +-
src/qemu/qemu_process.c | 30 +++++++++++++++++++++---------
5 files changed, 103 insertions(+), 23 deletions(-)
--
1.9.3
10 years, 5 months
[libvirt] Bug: iohelper drops I/O error messages
by Jason J. Herne
During a recent managed save operation I received the following error
message:
error: operation failed: domain save job: unexpectedly failed.
It turns out that I had run out of disk space. After a brief investigation I
discovered that libvirt_iohelper is exec'ed and is used to handle all
I/O during
a (Qemu) managed save operation. While iohelper appears to be set up to log
error conditions when they occur, for some reason the logging is getting
lost.
I'm hoping someone can help figure out why these errors are getting lost. It
would be nice to present a useful error message to the user when a
managed save
fails because of an I/O error.
--
-- Jason J. Herne (jjherne(a)linux.vnet.ibm.com)
10 years, 5 months
[libvirt] [PATCH v5] Add helper program to create custom leases
by Nehal J Wani
Introduce helper program to catch events from dnsmasq and maintain a custom
lease file per network. It supports dhcpv4 and dhcpv6. The file is saved as
"<interface-name>.status".
Each lease contains the following info:
<expiry-time (epoch time)> <mac> <iaid> <ip-address> <hostname> <clientid>
Example of custom leases file content:
[
{
"iaid": "1221229",
"ip-address": "2001:db8:ca2:2:1::95",
"mac-address": "52:54:00:12:a2:6d",
"hostname": "Fedora20",
"client-id": "00:04:1a:c1:d9:6b:5a:0a:e2:bc:f8:4b:1e:37:2e:38:22:55",
"expiry-time": 1393244216
},
{
"ip-address": "192.168.150.208",
"mac-address": "52:54:00:11:56:b3",
"hostname": "Wani-PC",
"client-id": "01:52:54:00:11:56:b3",
"expiry-time": 1393244248
}
]
src/Makefile.am:
* Add options to compile the helper program
src/network/bridge_driver.c:
* Introduce networkDnsmasqLeaseFileNameCustom()
* Invoke helper program along with dnsmasq
* Delete the .status file when corresponding n/w is destroyed.
src/network/leaseshelper.c
* Helper program to create the custom lease file
---
v5:
* More comments added, for better explanation
* Use of virFileFindResource() to identify proper path to helper binary
* Use of VIR_ENUM_IMPL for handling action events added
v4:
* Addition of pidfile and a corresponding lock for it
* Make correction for dnsmasq < 2.52 (Only IPv4)
* Move helper file from src/util to src/network
* Increase limit on max size of leases file
* Refer: https://www.redhat.com/archives/libvir-list/2014-March/msg01038.html
v3:
* Improved file handling, removed redundant copying, introduced --help and --version
* Refer: https://www.redhat.com/archives/libvir-list/2014-February/msg01431.html
v2:
* Changed format to JSON
* Refer: https://www.redhat.com/archives/libvir-list/2014-January/msg01234.html
v1:
* Refer: https://www.redhat.com/archives/libvir-list/2014-January/msg00626.html
src/Makefile.am | 22 +++
src/network/bridge_driver.c | 27 ++++
src/network/leaseshelper.c | 360 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 409 insertions(+), 0 deletions(-)
create mode 100644 src/network/leaseshelper.c
diff --git a/src/Makefile.am b/src/Makefile.am
index dd0abe7..fbe72c4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -859,6 +859,9 @@ STORAGE_HELPER_DISK_SOURCES = \
UTIL_IO_HELPER_SOURCES = \
util/iohelper.c
+NETWORK_LEASES_HELPER_SOURCES = \
+ network/leaseshelper.c
+
# Network filters
NWFILTER_DRIVER_SOURCES = \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
@@ -2466,6 +2469,25 @@ libvirt_iohelper_CFLAGS = \
$(AM_CFLAGS) \
$(PIE_CFLAGS) \
$(NULL)
+
+if WITH_NETWORK
+libexec_PROGRAMS += libvirt_leaseshelper
+libvirt_leaseshelper_SOURCES = $(NETWORK_LEASES_HELPER_SOURCES)
+libvirt_leaseshelper_LDADD = \
+ libvirt_util.la \
+ ../gnulib/lib/libgnu.la
+if WITH_DTRACE_PROBES
+libvirt_leaseshelper_LDADD += libvirt_probes.lo
+endif WITH_DTRACE_PROBES
+
+libvirt_leaseshelper_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(PIE_CFLAGS) \
+ $(NULL)
+else ! WITH_NETWORK
+EXTRA_DIST += $(NETWORK_LEASES_HELPER_SOURCES)
+endif ! WITH_NETWORK
+
endif WITH_LIBVIRTD
if WITH_STORAGE_DISK
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 201b22f..ade664d 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -210,6 +210,16 @@ networkDnsmasqLeaseFileNameFunc networkDnsmasqLeaseFileName =
networkDnsmasqLeaseFileNameDefault;
static char *
+networkDnsmasqLeaseFileNameCustom(const char *bridge)
+{
+ char *leasefile;
+
+ ignore_value(virAsprintf(&leasefile, "%s/%s.status",
+ driverState->dnsmasqStateDir, bridge));
+ return leasefile;
+}
+
+static char *
networkDnsmasqConfigFileName(const char *netname)
{
char *conffile;
@@ -245,6 +255,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
virNetworkObjPtr net)
{
char *leasefile = NULL;
+ char *customleasefile = NULL;
char *radvdconfigfile = NULL;
char *configfile = NULL;
char *radvdpidbase = NULL;
@@ -263,6 +274,9 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
if (!(leasefile = networkDnsmasqLeaseFileName(def->name)))
goto cleanup;
+ if (!(customleasefile = networkDnsmasqLeaseFileNameCustom(def->bridge)))
+ goto cleanup;
+
if (!(radvdconfigfile = networkRadvdConfigFileName(def->name)))
goto cleanup;
@@ -279,6 +293,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
/* dnsmasq */
dnsmasqDelete(dctx);
unlink(leasefile);
+ unlink(customleasefile);
unlink(configfile);
/* radvd */
@@ -296,6 +311,7 @@ networkRemoveInactive(virNetworkDriverStatePtr driver,
cleanup:
VIR_FREE(leasefile);
VIR_FREE(configfile);
+ VIR_FREE(customleasefile);
VIR_FREE(radvdconfigfile);
VIR_FREE(radvdpidbase);
VIR_FREE(statusfile);
@@ -1120,6 +1136,7 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
int ret = -1;
char *configfile = NULL;
char *configstr = NULL;
+ char *leaseshelper_path;
network->dnsmasqPid = -1;
@@ -1142,11 +1159,21 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps));
virCommandAddArgFormat(cmd, "--conf-file=%s", configfile);
+
+ /* This helper is used to create custom leases file for libvirt */
+ if (!(leaseshelper_path = virFileFindResource("libvirt_leaseshelper",
+ "src",
+ LIBEXECDIR)))
+ goto cleanup;
+
+ virCommandAddArgFormat(cmd, "--dhcp-script=%s", leaseshelper_path);
+
*cmdout = cmd;
ret = 0;
cleanup:
VIR_FREE(configfile);
VIR_FREE(configstr);
+ VIR_FREE(leaseshelper_path);
return ret;
}
diff --git a/src/network/leaseshelper.c b/src/network/leaseshelper.c
new file mode 100644
index 0000000..d580369
--- /dev/null
+++ b/src/network/leaseshelper.c
@@ -0,0 +1,360 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ * Copyright (C) 2014 Nehal J Wani
+ *
+ * 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: Nehal J Wani <nehaljw.kkd1(a)gmail.com>
+ *
+ * For IPv6 support, use dnsmasq >= 2.67
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "virutil.h"
+#include "virthread.h"
+#include "virfile.h"
+#include "virpidfile.h"
+#include "virbuffer.h"
+#include "virstring.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "virjson.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX:
+ *
+ * Macro providing the upper limit on the size of leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX (32 * 1024 * 1024)
+
+static const char *program_name;
+
+/* Display version information. */
+static void
+helperVersion(const char *argv0)
+{
+ printf("%s (%s) %s\n", argv0, PACKAGE_NAME, PACKAGE_VERSION);
+}
+
+ATTRIBUTE_NORETURN static void
+usage(int status)
+{
+ if (status) {
+ fprintf(stderr, _("%s: try --help for more details\n"), program_name);
+ } else {
+ printf(_("Usage: %s add|old|del mac|clientid ip [hostname]\n"
+ "Designed for use with 'dnsmasq --dhcp-script'\n"
+ "Refer to man page of dnsmasq for more details'\n"),
+ program_name);
+ }
+ exit(status);
+}
+
+static int
+customLeaseRewriteFile(int fd, void *opaque)
+{
+ char **data = opaque;
+
+ if (safewrite(fd, *data, strlen(*data)) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Flags denoting actions for a lease */
+enum virLeaseActionFlags {
+ VIR_LEASE_ACTION_ADD, /* Create new lease */
+ VIR_LEASE_ACTION_OLD, /* Lease already exists, renew it */
+ VIR_LEASE_ACTION_DEL, /* Delete the lease */
+
+ VIR_LEASE_ACTION_LAST
+};
+
+VIR_ENUM_DECL(virLeaseAction);
+
+VIR_ENUM_IMPL(virLeaseAction, VIR_LEASE_ACTION_LAST,
+ "add", "old", "del");
+
+int
+main(int argc, char **argv)
+{
+ char *exptime = NULL;
+ char *pid_file = NULL;
+ char *lease_entries = NULL;
+ char *custom_lease_file = NULL;
+ const char *ip = NULL;
+ const char *mac = NULL;
+ const char *iaid = virGetEnvAllowSUID("DNSMASQ_IAID");
+ const char *clientid = virGetEnvAllowSUID("DNSMASQ_CLIENT_ID");
+ const char *interface = virGetEnvAllowSUID("DNSMASQ_INTERFACE");
+ const char *exptime_tmp = virGetEnvAllowSUID("DNSMASQ_LEASE_EXPIRES");
+ const char *hostname = virGetEnvAllowSUID("DNSMASQ_SUPPLIED_HOSTNAME");
+ const char *leases_str = NULL;
+ long long currtime = 0;
+ long long expirytime = 0;
+ size_t i = 0;
+ int size = 0;
+ int action = -1;
+ int pid_file_fd = -1;
+ int rv = EXIT_FAILURE;
+ int custom_lease_file_len = 0;
+ bool add = false;
+ bool delete = false;
+ virJSONValuePtr lease_new = NULL;
+ virJSONValuePtr lease_tmp = NULL;
+ virJSONValuePtr leases_array = NULL;
+ virJSONValuePtr leases_array_new = NULL;
+
+ virSetErrorFunc(NULL, NULL);
+ virSetErrorLogPriorityFunc(NULL);
+
+ program_name = argv[0];
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+ textdomain(PACKAGE) == NULL) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ if (virThreadInitialize() < 0 ||
+ virErrorInitialize() < 0) {
+ fprintf(stderr, _("%s: initialization failed\n"), program_name);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Doesn't hurt to check */
+ if (argc > 1) {
+ if(STREQ(argv[1], "--help"))
+ usage(EXIT_SUCCESS);
+
+ if (STREQ(argv[1], "--version")) {
+ helperVersion(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ if (argc != 4 && argc != 5) {
+ /* Refer man page of dnsmasq --dhcp-script for more details */
+ usage(EXIT_FAILURE);
+ }
+
+ /* Make sure dnsmasq knows the interface. The interface name is not known
+ * when dnsmasq (re)starts and throws 'del' events for expired leases.
+ * So, if any old lease has expired, it will be automatically removed the
+ * next time this program is invoked */
+ if (!interface)
+ goto cleanup;
+
+ ip = argv[3];
+ mac = argv[2];
+ action = virLeaseActionTypeFromString(argv[1]);
+
+ /* In case hostname is known, it is the 5th argument */
+ if (argc == 5)
+ hostname = argv[4];
+
+ if (VIR_STRDUP(exptime, exptime_tmp) < 0)
+ goto cleanup;
+
+ /* Removed extraneous trailing space in DNSMASQ_LEASE_EXPIRES (dnsmasq < 2.52) */
+ if (exptime[strlen(exptime) - 1] == ' ')
+ exptime[strlen(exptime) - 1] = '\0';
+
+ /* Check if it is an IPv6 lease */
+ if (virGetEnvAllowSUID("DNSMASQ_IAID")) {
+ mac = virGetEnvAllowSUID("DNSMASQ_MAC");
+ clientid = argv[2];
+ }
+
+ if (virAsprintf(&custom_lease_file,
+ LOCALSTATEDIR "/lib/libvirt/dnsmasq/%s.status",
+ interface) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(pid_file, LOCALSTATEDIR "/run/leaseshelper.pid") < 0)
+ goto cleanup;
+
+ /* Try to claim the pidfile, exiting if we can't */
+ if ((pid_file_fd = virPidFileAcquirePath(pid_file, true, getpid())) < 0)
+ goto cleanup;
+
+ /* Since interfaces can be hot plugged, we need to make sure that the
+ * corresponding custom lease file exists. If not, 'touch' it */
+ if (virFileTouch(custom_lease_file, 0644) < 0)
+ goto cleanup;
+
+ /* Read entire contents */
+ if ((custom_lease_file_len = virFileReadAll(custom_lease_file,
+ VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+ &lease_entries)) < 0) {
+ goto cleanup;
+ }
+
+ if (action == VIR_LEASE_ACTION_ADD ||
+ action == VIR_LEASE_ACTION_OLD ||
+ action == VIR_LEASE_ACTION_DEL) {
+ /* Custom ipv6 leases *will not* be created if the env-var DNSMASQ_MAC
+ * is not set. In the special case, when the $(interface).status file
+ * is not already present and dnsmasq is (re)started, the corresponding
+ * ipv6 custom lease will be created only when the guest sends the
+ * 'old' action for its existing ipv6 interfaces.
+ *
+ * According to rfc3315, the combination of DUID and IAID can be used
+ * to uniquely identify each ipv6 guest interface. So, in future, if
+ * we introduce virNetworkGetDHCPLeaseBy(IAID|DUID|IAID+DUID) for ipv6
+ * interfaces, then, the following if condition won't be required, as
+ * the new lease will be created irrespective of whether the MACID is
+ * known or not.
+ */
+ if (mac || action == VIR_LEASE_ACTION_DEL) {
+ /* Delete the corresponding lease, if it already exists */
+ delete = true;
+ if (action == VIR_LEASE_ACTION_ADD ||
+ action == VIR_LEASE_ACTION_OLD) {
+ add = true;
+ /* Create new lease */
+ if (!(lease_new = virJSONValueNewObject())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+
+ if (virStrToLong_ll(exptime, NULL, 10, &expirytime) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to convert lease expiry time to long long: %s"),
+ exptime);
+ goto cleanup;
+ }
+
+ if (iaid && virJSONValueObjectAppendString(lease_new, "iaid", iaid) < 0)
+ goto cleanup;
+ if (ip && virJSONValueObjectAppendString(lease_new, "ip-address", ip) < 0)
+ goto cleanup;
+ if (mac && virJSONValueObjectAppendString(lease_new, "mac-address", mac) < 0)
+ goto cleanup;
+ if (hostname && virJSONValueObjectAppendString(lease_new, "hostname", hostname) < 0)
+ goto cleanup;
+ if (clientid && virJSONValueObjectAppendString(lease_new, "client-id", clientid) < 0)
+ goto cleanup;
+ if (expirytime && virJSONValueObjectAppendNumberLong(lease_new, "expiry-time", expirytime) < 0)
+ goto cleanup;
+ }
+ }
+ } else {
+ fprintf(stderr, _("Unsupported action: %s\n"),
+ virLeaseActionTypeToString(action));
+ exit(EXIT_FAILURE);
+ }
+ /* Check for previous leases */
+ if (custom_lease_file_len) {
+ if (!(leases_array = virJSONValueFromString(lease_entries))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid json in file: %s"), custom_lease_file);
+ goto cleanup;
+ }
+
+ if ((size = virJSONValueArraySize(leases_array)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("couldn't fetch array of leases"));
+ goto cleanup;
+ }
+ }
+
+ if (!(leases_array_new = virJSONValueNewArray())) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+
+ currtime = (long long) time(NULL);
+
+ for (i = 0; i < size; i++) {
+ const char *ip_tmp = NULL;
+ long long expirytime_tmp = -1;
+
+ if (!(lease_tmp = virJSONValueArrayGet(leases_array, i))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse json"));
+ goto cleanup;
+ }
+
+ if (!(ip_tmp = virJSONValueObjectGetString(lease_tmp, "ip-address")) ||
+ (virJSONValueObjectGetNumberLong(lease_tmp, "expiry-time", &expirytime_tmp) < 0)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse json"));
+ goto cleanup;
+ }
+
+ /* Check whether lease has expired or not */
+ if (expirytime_tmp < currtime)
+ continue;
+
+ /* Check whether lease has to be included or not */
+ if (delete && STREQ(ip_tmp, ip))
+ continue;
+
+ /* Add old lease to new array */
+ if (virJSONValueArrayAppend(leases_array_new, lease_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ }
+
+ if (add) {
+ if (virJSONValueArrayAppend(leases_array_new, lease_new) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to create json"));
+ goto cleanup;
+ }
+ }
+
+ if (!(leases_str = virJSONValueToString(leases_array_new, true))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("empty json array"));
+ goto cleanup;
+ }
+
+ /* Write to file */
+ if (virFileRewrite(custom_lease_file, 0644,
+ customLeaseRewriteFile, &leases_str) < 0)
+ goto cleanup;
+
+ rv = EXIT_SUCCESS;
+
+cleanup:
+ if (pid_file_fd != -1)
+ virPidFileReleasePath(pid_file, pid_file_fd);
+
+ VIR_FREE(pid_file);
+ VIR_FREE(exptime_tmp);
+ VIR_FREE(custom_lease_file);
+ virJSONValueFree(lease_new);
+ virJSONValueFree(leases_array);
+ virJSONValueFree(leases_array_new);
+
+ return rv;
+}
--
1.7.1
10 years, 5 months
[libvirt] [PATCH v2] qemu: Properly label FDs when restoring domain with static label
by Shivaprasad G Bhat
The restore of a saved image file fails when the selinux context is static.
The libvirt has to set the conext of save image file handle to that of
the guest before handing off the FD to qemu.
Signed-off-by: Shivaprasad G Bhat <shivaprasadbhat(a)gmail.com>
---
src/qemu/qemu_process.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 124fe28..47d1f7d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4052,14 +4052,14 @@ int qemuProcessStart(virConnectPtr conn,
*/
struct stat stdin_sb;
- VIR_DEBUG("setting security label on pipe used for migration");
+ VIR_DEBUG("setting security label on fd used for migration or restore");
if (fstat(stdin_fd, &stdin_sb) < 0) {
virReportSystemError(errno,
_("cannot stat fd %d"), stdin_fd);
goto cleanup;
}
- if (S_ISFIFO(stdin_sb.st_mode) &&
+ if ((S_ISFIFO(stdin_sb.st_mode) || S_ISREG(stdin_sb.st_mode)) &&
virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def, stdin_fd) < 0)
goto cleanup;
}
10 years, 5 months
[libvirt] [PATCH] virsh: Check wether found volume is member of the specified storage pool
by Peter Krempa
When looking up storage volumes virsh uses multiple lookup steps. Some
of the steps don't require a pool name specified. This resulted into a
possibility that a volume would be part of a different pool than the
user specified:
Let's have a /var/lib/libvirt/images/test.qcow image in the 'default'
pool and a second pool 'emptypool':
Currently we'd return:
$ virsh vol-info --pool emptypool /var/lib/libvirt/images/test.qcow
Name: test.qcow
Type: file
Capacity: 100.00 MiB
Allocation: 212.00 KiB
After the fix:
$ tools/virsh vol-info --pool emptypool /var/lib/libvirt/images/test.qcow
error: Requested volume '/var/lib/libvirt/images/test.qcow' found in a different pool (default) than specified
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1088667
---
tools/virsh-volume.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tools/virsh-volume.c b/tools/virsh-volume.c
index 55bf6f0..6416ba6 100644
--- a/tools/virsh-volume.c
+++ b/tools/virsh-volume.c
@@ -104,6 +104,26 @@ vshCommandOptVolBy(vshControl *ctl, const vshCmd *cmd,
"might help"), n, pooloptname);
}
+ /* If the pool was specified, then make sure that the returned
+ * volume is from the given pool */
+ if (pool && vol) {
+ virStoragePoolPtr volpool = NULL;
+
+ if ((volpool = virStoragePoolLookupByVolume(vol))) {
+ if (STRNEQ(virStoragePoolGetName(volpool),
+ virStoragePoolGetName(pool))) {
+ vshResetLibvirtError();
+ vshError(ctl,
+ _("Requested volume '%s' found in a different "
+ "pool (%s) than specified"),
+ n, virStoragePoolGetName(volpool));
+ virStorageVolFree(vol);
+ vol = NULL;
+ }
+ virStoragePoolFree(volpool);
+ }
+ }
+
if (pool)
virStoragePoolFree(pool);
--
1.9.3
10 years, 5 months
[libvirt] [PATCH v5] bhyve: implement PCI address allocation
by Roman Bogorodskiy
Changes from v4:
- Qemu-related part of sharing the common code is complete and
pushed, so patch lives on its own now
- virBhyveProcessBuildBhyveCmd() modified to loop over disks and nets
and call bhyveBuildDiskArgStr() and bhyveBuildNetArgStr() for an
individual device to make the latter more readable
- Fix double assing / double semicolon typo
- Fix spelling in virReportError() for disks
- Make bhyveAssignDevicePCISlots() assign nets before disks to reproduce
the old behaviour when one net and one disk were supported
- Make persistentAddrs of _bhyveDomainObjPrivate bool.
Roman Bogorodskiy (1):
bhyve: implement PCI address allocation
po/POTFILES.in | 1 +
src/Makefile.am | 4 +
src/bhyve/bhyve_command.c | 112 +++++++------
src/bhyve/bhyve_device.c | 174 +++++++++++++++++++++
src/bhyve/bhyve_device.h | 38 +++++
src/bhyve/bhyve_domain.c | 75 +++++++++
src/bhyve/bhyve_domain.h | 39 +++++
src/bhyve/bhyve_driver.c | 12 +-
.../bhyvexml2argvdata/bhyvexml2argv-acpiapic.args | 2 +-
tests/bhyvexml2argvdata/bhyvexml2argv-acpiapic.xml | 2 +
tests/bhyvexml2argvdata/bhyvexml2argv-base.args | 2 +-
tests/bhyvexml2argvdata/bhyvexml2argv-base.xml | 2 +
tests/bhyvexml2argvdata/bhyvexml2argv-console.args | 4 +-
tests/bhyvexml2argvdata/bhyvexml2argv-console.xml | 2 +
.../bhyvexml2argv-disk-virtio.args | 2 +-
.../bhyvexml2argv-disk-virtio.xml | 2 +
tests/bhyvexml2argvdata/bhyvexml2argv-macaddr.args | 2 +-
tests/bhyvexml2argvdata/bhyvexml2argv-macaddr.xml | 2 +
tests/bhyvexml2argvdata/bhyvexml2argv-serial.args | 4 +-
tests/bhyvexml2argvdata/bhyvexml2argv-serial.xml | 2 +
20 files changed, 416 insertions(+), 67 deletions(-)
create mode 100644 src/bhyve/bhyve_device.c
create mode 100644 src/bhyve/bhyve_device.h
create mode 100644 src/bhyve/bhyve_domain.c
create mode 100644 src/bhyve/bhyve_domain.h
--
1.9.0
10 years, 5 months
[libvirt] [PATCH] docs: bhyve driver documentation improvements
by Roman Bogorodskiy
- Document 'domxml-to-native' command
- Mention that the nmdm console support needs an appropriate
kernel module loaded
---
docs/drvbhyve.html.in | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/docs/drvbhyve.html.in b/docs/drvbhyve.html.in
index 603be80..ecd7c0c 100644
--- a/docs/drvbhyve.html.in
+++ b/docs/drvbhyve.html.in
@@ -98,6 +98,9 @@ the following to the domain XML (<span class="since">Since 1.2.4</span>):
</devices>
...</pre>
+
+<p>Make sure to load the <code>nmdm</code> kernel module if you plan to use that.</p>
+
<p>
Then <code>virsh console</code> command can be used to connect to the text console
of a guest.</p>
@@ -110,6 +113,24 @@ to let a guest boot or start a guest using:</p>
<pre>start --console domname</pre>
+<h3><a name="xmltonative">Converting from domain XML to Bhyve args</a></h3>
+
+<p>
+The <code>virsh domxml-to-native</code> command allows to preview the actual <code>bhyve</code> commands
+that will be executed for a given domain. It outputs two lines, the first line is a <code>bhyveload</code>
+command and the second is a <code>bhyve</code> command.
+</p>
+
+<p>Please note that the <code>virsh domxml-to-native</code> doesn't do any real actions but printing the command,
+for example, it doesn't try to find a proper TAP interface and create it, like it's done when starting a domain, and
+always returns <code>tap0</code> for the network interface. So if you're going to run these commands manually, most likely
+you might want to tweak them.</p>
+
+<pre>
+# virsh -c "bhyve:///system" domxml-to-native --format bhyve-argv --xml /path/to/bhyve.xml
+/usr/sbin/bhyveload -m 214 -d /home/user/vm1.img vm1
+/usr/sbin/bhyve -c 2 -m 214 -A -I -H -P -s 0:0,hostbridge -s 3:0,virtio-net,tap0,mac=52:54:00:5d:74:e3 -s 2:0,virtio-blk,/home/user/vm1.img -s 1,lpc -l com1,/dev/nmdm0A vm1
+</pre>
</body>
</html>
--
1.9.0
10 years, 5 months