[libvirt] [PATCH glib] Fix event loop implementation on win32
by Daniel P. Berrange
Libvirt uses gnulib for making winsock look like POSIX
sockets. This means that in the libvirt event handle
callbacks the application will be given a file descriptor
rather than a winsock HANDLE object. The g_io_channel_unix_new
method will detect that it is an FD and delegate to the
g_io_channel_win32_new_fd method. Unfortunately the glib Win32
event loop impl is not very good at dealing with FD objects,
simulating poll() by doing a read() on the FD :-(
The API docs for g_io_channel_win32_new_fd say
"All reads from the file descriptor should be done by
this internal GLib thread. Your code should call only
g_io_channel_read()."
This isn't going to fly for libvirt, since it has zero
knowledge of glib at all, so is just doing normal read().
Fortunately we can work around this problem by turning
the FD we get from libvirt back into a HANDLE using the
_get_osfhandle() method.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
libvirt-glib/libvirt-glib-event.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libvirt-glib/libvirt-glib-event.c b/libvirt-glib/libvirt-glib-event.c
index 87019b5..826db2d 100644
--- a/libvirt-glib/libvirt-glib-event.c
+++ b/libvirt-glib/libvirt-glib-event.c
@@ -31,6 +31,10 @@
#include "libvirt-glib/libvirt-glib.h"
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
/**
* SECTION:libvirt-glib-event
* @short_description: Integrate libvirt with the GMain event framework
@@ -164,7 +168,7 @@ gvir_event_handle_add(int fd,
data->events = events;
data->cb = cb;
data->opaque = opaque;
- data->channel = g_io_channel_unix_new(fd);
+ data->channel = g_io_channel_unix_new(_get_osfhandle(fd));
data->ff = ff;
g_debug("Add handle %p %d %d %d %p\n", data, data->watch, data->fd, events, data->opaque);
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH v2] 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".
The format of each lease is:
<expiry-time (epoch time)> <mac> <iaid> <ip-address> <hostname> <clientid>
Example of custom leases file content:
1385245780 52:54:00:2f:ba:76 * 192.168.150.153 * *
1385245781 52:54:00:2f:ba:76 3127926 2001:db8:ca2:2:1::6c * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 iiit-ad885e4aa1 01:52:54:00:44:7c:d7
1385245964 52:54:00:44:7c:d7 * 192.168.150.219 * 01:52:54:00:44:7c:d7
1385246016 52:54:00:5d:99:92 * 192.168.150.212 iiit-ad885e4aa1 01:52:54:00:5d:99:92
1385246041 52:54:00:3b:16:e0 * 192.168.150.207 * *
1385246081 52:54:00:db:dd:98 * 192.168.150.234 * *
1385246088 52:54:00:db:dd:98 14409112 2001:db8:ca2:2:1::6d * 00:04:76:00:cf:ae:b3:0b:fc:cd:0e:22:2e:97:76:65:74:ec
---
As danpb suggested, I have split the previous patch into helper program & API
Refer: https://www.redhat.com/archives/libvir-list/2013-December/msg00694.html
Once this get ACKed, I'll send in the patches for the Leases API v6
src/Makefile.am | 20 ++++
src/network/bridge_driver.c | 4 +
src/util/leaseshelper.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 249 insertions(+)
create mode 100644 src/util/leaseshelper.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 57e163f..6e5b03c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -838,6 +838,9 @@ STORAGE_HELPER_DISK_SOURCES = \
UTIL_IO_HELPER_SOURCES = \
util/iohelper.c
+UTIL_LEASES_HELPER_SOURCES = \
+ util/leaseshelper.c
+
# Network filters
NWFILTER_DRIVER_SOURCES = \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
@@ -2408,6 +2411,23 @@ libvirt_iohelper_CFLAGS = \
$(NULL)
endif WITH_LIBVIRTD
+if WITH_LIBVIRTD
+libexec_PROGRAMS += libvirt_leaseshelper
+libvirt_leaseshelper_SOURCES = $(UTIL_LEASES_HELPER_SOURCES)
+libvirt_leaseshelper_LDFLAGS = \
+ $(NULL)
+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 = \
+ $(PIE_CFLAGS) \
+ $(NULL)
+endif WITH_LIBVIRTD
+
if WITH_STORAGE_DISK
if WITH_LIBVIRTD
libexec_PROGRAMS += libvirt_parthelper
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 95e4b65..2278dba 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1063,6 +1063,10 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps));
virCommandAddArgFormat(cmd, "--conf-file=%s", configfile);
+
+ /* This helper is used to create cutom leases file for libvirt */
+ virCommandAddArgFormat(cmd, "--dhcp-script=%s", LIBEXECDIR "/libvirt_leaseshelper");
+
*cmdout = cmd;
ret = 0;
cleanup:
diff --git a/src/util/leaseshelper.c b/src/util/leaseshelper.c
new file mode 100644
index 0000000..486ebe3
--- /dev/null
+++ b/src/util/leaseshelper.c
@@ -0,0 +1,225 @@
+/*
+ * leasehelper.c: Helper program to create custom leases file
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Nehal J Wani <nehaljw.kkd1(a)gmail.com>
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "virutil.h"
+#include "virthread.h"
+#include "virfile.h"
+#include "virbuffer.h"
+#include "virstring.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/**
+ * VIR_NETWORK_DHCP_LEASE_FIELDS:
+ *
+ * Macro providing the maximum number of fields in an entry in
+ * the leases file
+ */
+#define VIR_NETWORK_DHCP_LEASE_FIELDS 6
+/**
+ * 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 2097152
+
+/*
+ * Use this when passing possibly-NULL strings to printf-a-likes.
+ */
+# define EMPTY_STR(s) ((s) ? (s) : "*")
+
+int
+main(int argc, char **argv) {
+
+ /* Doesn't hurt to check */
+ if (argc < 4) {
+ /* Refer man page of dnsmasq --dhcp-script for more details */
+ fprintf(stderr, "Usage: $program $action ${mac|clientid} $ip\n");
+ return -1;
+ }
+
+ const char *program_name = argv[0];
+ const char *action = argv[1];
+ const char *interface = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_INTERFACE"));
+ const char *expirytime = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_LEASE_EXPIRES"));
+ const char *mac = argv[2];
+ const char *ip = argv[3];
+ const char *iaid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_IAID"));
+ const char *hostname = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_SUPPLIED_HOSTNAME"));
+ const char *clientid = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_CLIENT_ID"));
+ const char *leases_str = NULL;
+ char *lease_file = NULL;
+ char *lease_entries = NULL;
+ char *lease_entry = NULL;
+ char **lease_fields = NULL;
+ bool delete = false;
+ bool add = false;
+ int rv = -1;
+ int lease_file_len = 0;
+ FILE *fp = NULL;
+ long long expirytime_tmp = 0;
+ virBuffer buf_new_lease = VIR_BUFFER_INITIALIZER;
+ virBuffer buf_all_leases = VIR_BUFFER_INITIALIZER;
+
+ 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);
+ }
+
+ if (virAsprintf(&lease_file, "%s/%s.status", LOCALSTATEDIR
+ "/lib/libvirt/dnsmasq/", interface) < 0)
+ goto cleanup;
+
+ if (virGetEnvAllowSUID("DNSMASQ_IAID")) {
+ mac = EMPTY_STR(virGetEnvAllowSUID("DNSMASQ_MAC"));
+ clientid = argv[2];
+ }
+
+ /* Make sure dnsmasq knows the interface, otherwise something is wrong */
+ if (STREQ(interface, "*"))
+ goto cleanup;
+
+ /* Make sure the file exists. If not, 'touch' it */
+ if (virFileTouch(lease_file, 0644) < 0)
+ goto cleanup;
+
+ /* Read entire contents */
+ if ((lease_file_len = virFileReadAll(lease_file,
+ VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX,
+ &lease_entries)) < 0) {
+ goto cleanup;
+ }
+
+ if (STREQ(action, "add") || STREQ(action, "old") || STREQ(action, "del")) {
+ if (mac || STREQ(action, "del")) {
+ /* Delete the corresponding lease */
+ delete = true;
+ if (STREQ(action, "add") || STREQ(action, "old")) {
+ fprintf(stderr, "add|old\n");
+ add = true;
+ /* Enter new lease */
+ virBufferAsprintf(&buf_new_lease, "%s %s %s %s %s %s\n",
+ expirytime, mac, iaid, ip, hostname, clientid);
+
+ if (virBufferError(&buf_new_lease)) {
+ virBufferFreeAndReset(&buf_new_lease);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ lease_entry = lease_entries[0] == '\0' ? NULL : lease_entries;
+
+ while (lease_entry) {
+ int nfields = 0;
+
+ char *eol = strchr(lease_entry, '\n');
+ *eol = '\0';
+
+ /* Split the lease line */
+ if (!(lease_fields = virStringSplit(lease_entry, " ",
+ VIR_NETWORK_DHCP_LEASE_FIELDS)))
+ goto cleanup;
+
+ nfields = virStringListLength(lease_fields);
+
+ /* Forward lease_entry to the next lease */
+ lease_entry = strchr(lease_entry, '\0');
+ if (lease_entry - lease_entries + 1 < lease_file_len)
+ lease_entry++;
+ else
+ lease_entry = NULL;
+
+ if (nfields != VIR_NETWORK_DHCP_LEASE_FIELDS)
+ goto cleanup;
+
+ if (virStrToLong_ll(lease_fields[0], NULL, 10, &expirytime_tmp) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to convert lease expiry time to integer: %s"),
+ lease_fields[0]);
+ goto cleanup;
+ }
+
+ /* Check whether lease has expired or not */
+ if (expirytime_tmp < (long long) time(NULL))
+ continue;
+ else if (delete && STREQ(lease_fields[3], ip))
+ continue;
+ else {
+ virBufferAsprintf(&buf_all_leases, "%s %s %s %s %s %s\n",
+ lease_fields[0], lease_fields[1], lease_fields[2],
+ lease_fields[3], lease_fields[4], lease_fields[5]);
+
+ if (virBufferError(&buf_all_leases)) {
+ virBufferFreeAndReset(&buf_all_leases);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+ }
+
+ if (add) {
+ virBufferAsprintf(&buf_all_leases, "%s", virBufferContentAndReset(&buf_new_lease));
+
+ if (virBufferError(&buf_all_leases)) {
+ virBufferFreeAndReset(&buf_all_leases);
+ virReportOOMError();
+ goto cleanup;
+ }
+ }
+
+ rv = 0;
+
+ /* Write to file */
+ leases_str = virBufferContentAndReset(&buf_all_leases);
+ if (!leases_str)
+ leases_str = "";
+
+ if (virFileWriteStr(lease_file, leases_str, 0) < 0)
+ rv = -1;
+
+cleanup:
+ VIR_FREE(lease_file);
+ VIR_FREE(lease_entries);
+ if (lease_fields)
+ virStringFreeList(lease_fields);
+ return rv;
+}
--
1.8.1.4
10 years, 10 months
[libvirt] [PATCH] Sheepdog: Auto Adding volume and correct refresh volume problem.
by joel SIMOES
From: Joel SIMOES <joel.simoes(a)laposte.net>
---
src/storage/storage_backend_sheepdog.c | 91 ++++++++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 10 deletions(-)
diff --git a/src/storage/storage_backend_sheepdog.c b/src/storage/storage_backend_sheepdog.c
index a6981ce..fbed11a 100644
--- a/src/storage/storage_backend_sheepdog.c
+++ b/src/storage/storage_backend_sheepdog.c
@@ -86,7 +86,8 @@ virStorageBackendSheepdogParseNodeInfo(virStoragePoolDefPtr pool,
pool->available = pool->capacity - pool->allocation;
return 0;
- } while ((p = next));
+ }
+ while ((p = next));
return -1;
}
@@ -109,6 +110,71 @@ virStorageBackendSheepdogAddHostArg(virCommandPtr cmd,
virCommandAddArgFormat(cmd, "%d", port);
}
+static int
+virStorageBackendSheepdogRefreshAllVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool)
+{
+ int ret;
+ char *output = NULL;
+
+ virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", "-r", NULL);
+ virStorageBackendSheepdogAddHostArg(cmd, pool);
+ virCommandSetOutputBuffer(cmd, &output);
+ ret = virCommandRun(cmd, NULL);
+ char** lines;
+ char** cells;
+
+ if (ret < 0)
+ goto cleanup;
+
+ lines = virStringSplit(output, "\n", 0);
+ size_t i;
+ for (i = 0; *(lines + i); i++) {
+ char *line = *(lines + i);
+ cells = virStringSplit(line, " ", 0);
+ size_t j;
+ for (j = 0; *(cells + j); j++) {
+
+ char *cell = *(cells + j);
+ if (j == 1) {
+ virStorageVolDefPtr vol = NULL;
+ if (VIR_ALLOC(vol) < 0)
+ goto cleanup;
+
+ if (VIR_STRDUP(vol->name, cell) < 0)
+ goto cleanup;
+
+ vol->type = VIR_STORAGE_VOL_BLOCK;
+
+ if (VIR_EXPAND_N(pool->volumes.objs, pool->volumes.count, 1) < 0)
+ goto cleanup;
+ pool->volumes.objs[pool->volumes.count - 1] = vol;
+
+ if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0)
+ goto cleanup;
+
+ vol = NULL;
+ }
+
+ VIR_FREE(*(cells + j));
+ }
+
+ VIR_FREE(cells);
+ VIR_FREE(*(lines + i));
+ }
+
+
+ VIR_FREE(lines);
+
+
+
+
+cleanup:
+ virCommandFree(cmd);
+ VIR_FREE(lines);
+ VIR_FREE(cells);
+ return ret;
+}
static int
virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -122,15 +188,16 @@ virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStorageBackendSheepdogAddHostArg(cmd, pool);
virCommandSetOutputBuffer(cmd, &output);
ret = virCommandRun(cmd, NULL);
- if (ret == 0)
- ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);
+ if (ret < 0)
+ goto cleanup;
+ ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output);
+ virStorageBackendSheepdogRefreshAllVol(conn, pool);
+cleanup:
virCommandFree(cmd);
- VIR_FREE(output);
return ret;
}
-
static int
virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
@@ -143,12 +210,14 @@ virStorageBackendSheepdogDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "delete", vol->name, NULL);
virStorageBackendSheepdogAddHostArg(cmd, pool);
int ret = virCommandRun(cmd, NULL);
+ if (ret < 0)
+ goto cleanup;
+cleanup:
virCommandFree(cmd);
return ret;
}
-
static int
virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
@@ -174,7 +243,6 @@ virStorageBackendSheepdogCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
return 0;
}
-
static int
virStorageBackendSheepdogBuildVol(virConnectPtr conn,
virStoragePoolObjPtr pool,
@@ -195,12 +263,12 @@ virStorageBackendSheepdogBuildVol(virConnectPtr conn,
goto cleanup;
ret = 0;
+
cleanup:
virCommandFree(cmd);
return ret;
}
-
int
virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
char *output)
@@ -257,7 +325,8 @@ virStorageBackendSheepdogParseVdiList(virStorageVolDefPtr vol,
return -1;
return 0;
- } while ((p = next));
+ }
+ while ((p = next));
return -1;
}
@@ -295,7 +364,6 @@ cleanup:
return ret;
}
-
static int
virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
@@ -310,7 +378,10 @@ virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED,
virCommandAddArgFormat(cmd, "%llu", capacity);
virStorageBackendSheepdogAddHostArg(cmd, pool);
int ret = virCommandRun(cmd, NULL);
+ if (ret < 0)
+ goto cleanup;
+cleanup:
virCommandFree(cmd);
return ret;
--
1.8.3.2
10 years, 10 months
[libvirt] [PATCH] docs: add a permalink to html headers
by Dan Kenigsberg
Quite often, I need to cite URLs like
http://libvirt.org/formatnetwork.html#elementQoS
but it is annoying to copy them from the table of contents or the html
source.
This patch borrows from the Python documentation in order to make it
easier to cite headers on libvirt's oneline documentation.
---
docs/libvirt.css | 13 +++++++++++++
docs/page.xsl | 7 +++++++
2 files changed, 20 insertions(+)
diff --git a/docs/libvirt.css b/docs/libvirt.css
index b324ac8..1d27873 100644
--- a/docs/libvirt.css
+++ b/docs/libvirt.css
@@ -498,3 +498,16 @@ div.description pre.code {
padding: 5px 10px 5px 10px;
margin-left: 2.5em;
}
+
+a.headerlink {
+ text-decoration: none!important;
+ visibility: hidden;
+}
+
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink {
+ visibility: visible;
+}
diff --git a/docs/page.xsl b/docs/page.xsl
index a2da854..107f6e2 100644
--- a/docs/page.xsl
+++ b/docs/page.xsl
@@ -185,4 +185,11 @@
<xsl:apply-templates select="exsl:node-set($inchtml)/html:html/html:body/*" mode="content"/>
</xsl:template>
+
+ <xsl:template match="html:h2 | html:h3 | html:h4 | html:h5 | html:h6" mode="content">
+ <xsl:copy>
+ <xsl:copy-of select="./*"/>
+ <a class="headerlink" href="#{html:a/@name}" title="Permalink to this headline">¶</a>
+ </xsl:copy>
+ </xsl:template>
</xsl:stylesheet>
--
1.8.3.1
10 years, 10 months
[libvirt] Libvirt and QBG with VEB
by Padmanabhan Krishnan
Hello,
I have a setup of virtual machines and wherein my virtual switch (OVS)
takes care of switching locally and it uses the network for talking to
VM's outside the server (like a VEB scenario I guess). I want Netlink
messages to be sent to LLDPAD. I understand that i had to modify the XML files and start the VM. But, i see from the XML that it supports only
VEPA, not VEB.
But, irrespective of VEB or VEPA, those VM information should be known to
the upstream switch through VDP. 802.1QBG seem to support this (both
VEPA and VEB)
http://www.ieee802.org/1/files/private/bg-drafts/d2/802-1qbg-d2-2.pdf
But, for VEB, no net link messages are sent by libvirt. Why is that?
From the XML example, I see that:
<interface type=’direct’>
<mac address=’d0:0f:d0:0f:02:01’/>
<source dev=’eth2.20’ mode=’vepa’/>
<source network=’default’/>
<virtualport
type=’802.1Qbg’>
<parameters
managerid=’12’
typeid=’0x123456’
typeidversion=’1’
instanceid=’09b00c53-8b5c-4eeb-8f00-d847aa05191b’
/>
</virtualport>
I
tried different combinations by changing the interface type to bridge
and and trying Qbg as in below, I find that it doesn't send a Netlink
message to LLDPAD. There's no "mode=veb".
</controller>
<interface type='bridge'>
<mac
address='00:54:00:4e:46:04'/>
<source bridge='xml_br'/>
<virtualport type='802.1Qbg'>
<parameters managerid='12' typeid='1193046' typeidversion='1' instanceid='09b00c53-8b5c-4eeb-8f00-d847aa05191b'/>
</virtualport>
<target dev='tap_xml'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
How do i get this to work? Is this a limitation?
Thanks,KP
10 years, 10 months
[libvirt] [PATCH] Fix segmentation fault when accessing default qemu machine type
by Yudai Yamagishi
From: Yudai Yamagish <yummy(a)sfc.wide.ad.jp>
This patch fixes a segmentation fault when creating new virtual machines using QEMU.
The segmentation fault is caused by commit f41830680e40d3ec845cefd25419bd87414b9ccf
and commit cbb6ec42e2447d7920b30d66923b2a2b2670133b.
In virQEMUCapsProbeQMPMachineTypes, when copying machines to qemuCaps, "none" is skipped.
Therefore, the value of i and "qemuCaps->nmachineTypes - 1" do not always match.
However, defIdx value (used to call virQEMUCapsSetDefaultMachine) is set using the value in i
when the array elements are in qemuCaps->nmachineTypes - 1.
So, when libvirt tries to create virtual machines using the default machine type,
qemuCaps->machineTypes[defIdx] is accessed and since the defIdx is NULL, it results in segmentation fault.
Signed-off-by: Yudai Yamagishi <yummy(a)sfc.wide.ad.jp>
---
src/qemu/qemu_capabilities.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 5e9c65e..5def55c 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2150,7 +2150,7 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps,
machines[i]->name) < 0)
goto cleanup;
if (machines[i]->isDefault)
- defIdx = i;
+ defIdx = qemuCaps->nmachineTypes - 1;
qemuCaps->machineMaxCpus[qemuCaps->nmachineTypes - 1] =
machines[i]->maxCpus;
}
--
1.7.2.5
10 years, 10 months
[libvirt] [PATCH] qemu: Enable 'host-passthrough' cpu mode for aarch64
by Oleg Strikov
This patch allows libvirt user to specify 'host-passthrough'
cpu mode while using qemu/kvm backend on aarch64.
It uses 'host' as a CPU model name instead of some other stub
(correct CPU detection is not implemented yet) to allow libvirt
user to specify 'host-model' cpu mode as well.
Signed-off-by: Oleg Strikov <oleg.strikov(a)canonical.com>
---
src/cpu/cpu_aarch64.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/cpu/cpu_aarch64.c b/src/cpu/cpu_aarch64.c
index 3959deb..4afe9db 100644
--- a/src/cpu/cpu_aarch64.c
+++ b/src/cpu/cpu_aarch64.c
@@ -25,6 +25,7 @@
#include "viralloc.h"
#include "cpu.h"
+#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_CPU
@@ -44,16 +45,19 @@ AArch64NodeData(virArch arch)
}
static int
-AArch64Decode(virCPUDefPtr cpu ATTRIBUTE_UNUSED,
+AArch64Decode(virCPUDefPtr cpu,
const virCPUData *data ATTRIBUTE_UNUSED,
const char **models ATTRIBUTE_UNUSED,
unsigned int nmodels ATTRIBUTE_UNUSED,
const char *preferred ATTRIBUTE_UNUSED,
unsigned int flags)
{
-
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
+ if (cpu->model == NULL &&
+ VIR_STRDUP(cpu->model, "host") < 0)
+ return -1;
+
return 0;
}
@@ -63,6 +67,24 @@ AArch64DataFree(virCPUDataPtr data)
VIR_FREE(data);
}
+static int
+AArch64Update(virCPUDefPtr guest,
+ const virCPUDef *host)
+{
+ guest->match = VIR_CPU_MATCH_EXACT;
+ virCPUDefFreeModel(guest);
+ return virCPUDefCopyModel(guest, host, true);
+}
+
+static virCPUCompareResult
+AArch64GuestData(virCPUDefPtr host ATTRIBUTE_UNUSED,
+ virCPUDefPtr guest ATTRIBUTE_UNUSED,
+ virCPUDataPtr *data ATTRIBUTE_UNUSED,
+ char **message ATTRIBUTE_UNUSED)
+{
+ return VIR_CPU_COMPARE_IDENTICAL;
+}
+
struct cpuArchDriver cpuDriverAARCH64 = {
.name = "aarch64",
.arch = archs,
@@ -72,8 +94,8 @@ struct cpuArchDriver cpuDriverAARCH64 = {
.encode = NULL,
.free = AArch64DataFree,
.nodeData = AArch64NodeData,
- .guestData = NULL,
+ .guestData = AArch64GuestData,
.baseline = NULL,
- .update = NULL,
+ .update = AArch64Update,
.hasFeature = NULL,
};
--
1.7.9.5
10 years, 10 months
[libvirt] [PATCH] tests: Fix PCI test data filenames for Windows
by Matthias Bolte
Windows doesn't allow : in filenames.
Commit 21685c955e546676a5b2a01f7b788d222e0ee0f5 added files with a : in
their names. This broke git operations on Windows as git is not able to
create those files on clone or pull.
Replace : with - in the offending filenames and adapt the test case.
---
tests/virpcimock.c | 19 ++++++++++++++++++-
.../{0000:00:01.0.config => 0000-00-01.0.config} | Bin
.../{0000:00:02.0.config => 0000-00-02.0.config} | Bin
.../{0000:00:03.0.config => 0000-00-03.0.config} | Bin
.../{0001:00:00.0.config => 0001-00-00.0.config} | Bin
.../{0001:01:00.0.config => 0001-01-00.0.config} | Bin
.../{0001:01:00.1.config => 0001-01-00.1.config} | Bin
.../{0005:80:00.0.config => 0005-80-00.0.config} | Bin
.../{0005:90:01.0.config => 0005-90-01.0.config} | Bin
.../{0005:90:01.1.config => 0005-90-01.1.config} | Bin
.../{0005:90:01.2.config => 0005-90-01.2.config} | Bin
11 files changed, 18 insertions(+), 1 deletion(-)
rename tests/virpcitestdata/{0000:00:01.0.config => 0000-00-01.0.config} (100%)
rename tests/virpcitestdata/{0000:00:02.0.config => 0000-00-02.0.config} (100%)
rename tests/virpcitestdata/{0000:00:03.0.config => 0000-00-03.0.config} (100%)
rename tests/virpcitestdata/{0001:00:00.0.config => 0001-00-00.0.config} (100%)
rename tests/virpcitestdata/{0001:01:00.0.config => 0001-01-00.0.config} (100%)
rename tests/virpcitestdata/{0001:01:00.1.config => 0001-01-00.1.config} (100%)
rename tests/virpcitestdata/{0005:80:00.0.config => 0005-80-00.0.config} (100%)
rename tests/virpcitestdata/{0005:90:01.0.config => 0005-90-01.0.config} (100%)
rename tests/virpcitestdata/{0005:90:01.1.config => 0005-90-01.1.config} (100%)
rename tests/virpcitestdata/{0005:90:01.2.config => 0005-90-01.2.config} (100%)
diff --git a/tests/virpcimock.c b/tests/virpcimock.c
index 1efcd33..b42e8bf 100644
--- a/tests/virpcimock.c
+++ b/tests/virpcimock.c
@@ -320,16 +320,33 @@ pci_device_new_from_stub(const struct pciDevice *data)
{
struct pciDevice *dev;
char *devpath;
+ char *id;
+ char *c;
char *configSrc;
char tmp[32];
struct stat sb;
+ if (VIR_STRDUP_QUIET(id, data->id) < 0)
+ ABORT_OOM();
+
+ /* Replace ':' with '-' to create the config filename from the
+ * device ID. The device ID cannot be used directly as filename
+ * because it contains ':' and Windows does not allow ':' in
+ * filenames. */
+ c = strchr(id, ':');
+
+ while (c) {
+ *c = '-';
+ c = strchr(c, ':');
+ }
+
if (VIR_ALLOC_QUIET(dev) < 0 ||
virAsprintfQuiet(&configSrc, "%s/virpcitestdata/%s.config",
- abs_srcdir, data->id) < 0 ||
+ abs_srcdir, id) < 0 ||
virAsprintfQuiet(&devpath, "%s/devices/%s", fakesysfsdir, data->id) < 0)
ABORT_OOM();
+ VIR_FREE(id);
memcpy(dev, data, sizeof(*dev));
if (virFileMakePath(devpath) < 0)
diff --git a/tests/virpcitestdata/0000:00:01.0.config b/tests/virpcitestdata/0000-00-01.0.config
similarity index 100%
rename from tests/virpcitestdata/0000:00:01.0.config
rename to tests/virpcitestdata/0000-00-01.0.config
diff --git a/tests/virpcitestdata/0000:00:02.0.config b/tests/virpcitestdata/0000-00-02.0.config
similarity index 100%
rename from tests/virpcitestdata/0000:00:02.0.config
rename to tests/virpcitestdata/0000-00-02.0.config
diff --git a/tests/virpcitestdata/0000:00:03.0.config b/tests/virpcitestdata/0000-00-03.0.config
similarity index 100%
rename from tests/virpcitestdata/0000:00:03.0.config
rename to tests/virpcitestdata/0000-00-03.0.config
diff --git a/tests/virpcitestdata/0001:00:00.0.config b/tests/virpcitestdata/0001-00-00.0.config
similarity index 100%
rename from tests/virpcitestdata/0001:00:00.0.config
rename to tests/virpcitestdata/0001-00-00.0.config
diff --git a/tests/virpcitestdata/0001:01:00.0.config b/tests/virpcitestdata/0001-01-00.0.config
similarity index 100%
rename from tests/virpcitestdata/0001:01:00.0.config
rename to tests/virpcitestdata/0001-01-00.0.config
diff --git a/tests/virpcitestdata/0001:01:00.1.config b/tests/virpcitestdata/0001-01-00.1.config
similarity index 100%
rename from tests/virpcitestdata/0001:01:00.1.config
rename to tests/virpcitestdata/0001-01-00.1.config
diff --git a/tests/virpcitestdata/0005:80:00.0.config b/tests/virpcitestdata/0005-80-00.0.config
similarity index 100%
rename from tests/virpcitestdata/0005:80:00.0.config
rename to tests/virpcitestdata/0005-80-00.0.config
diff --git a/tests/virpcitestdata/0005:90:01.0.config b/tests/virpcitestdata/0005-90-01.0.config
similarity index 100%
rename from tests/virpcitestdata/0005:90:01.0.config
rename to tests/virpcitestdata/0005-90-01.0.config
diff --git a/tests/virpcitestdata/0005:90:01.1.config b/tests/virpcitestdata/0005-90-01.1.config
similarity index 100%
rename from tests/virpcitestdata/0005:90:01.1.config
rename to tests/virpcitestdata/0005-90-01.1.config
diff --git a/tests/virpcitestdata/0005:90:01.2.config b/tests/virpcitestdata/0005-90-01.2.config
similarity index 100%
rename from tests/virpcitestdata/0005:90:01.2.config
rename to tests/virpcitestdata/0005-90-01.2.config
--
1.8.1.2
10 years, 10 months
[libvirt] [RFC PATCH] Cannot set persistent config mem/vcpu above live maxmem/maxvcpu
by Geoff Franks
I submitted bug https://bugzilla.redhat.com/show_bug.cgi?id=1038363 for being unable to raise the persistent mem/vcpu values above a live domain’s maxmem/maxvcpu values (rather than the persistent maxmem/maxvcpu values). I was asked to submit my patch here for a wider review.
For memory, check the newmem value against mem.max_baloon of the live def for non-persistent changes, or mem.max_baloon of the persistent def for persistent changes. Same theory for setting vcpus/maxvcpus.
--- a/libvirt0/libvirt-1.1.1/src/qemu/qemu_driver.c
+++ b/libvirt0/libvirt-1.1.1/src/qemu/qemu_driver.c
@@ -2236,13 +2236,13 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
} else {
/* resize the current memory */
- if (newmem > vm->def->mem.max_balloon) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("cannot set memory higher than max memory"));
- goto endjob;
- }
-
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+ if (newmem > vm->def->mem.max_balloon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("cannot set memory higher than max memory"));
+ goto endjob;
+ }
+
priv = vm->privateData;
qemuDomainObjEnterMonitor(driver, vm);
r = qemuMonitorSetBalloon(priv->mon, newmem);
@@ -2262,6 +2262,12 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ if (newmem > persistentDef->mem.max_balloon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("cannot set memory higher than max memory"));
+ goto endjob;
+ }
+
sa_assert(persistentDef);
persistentDef->mem.cur_balloon = newmem;
ret = virDomainSaveConfig(cfg->configDir, persistentDef);
@@ -4160,6 +4166,7 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
virDomainDefPtr persistentDef;
int ret = -1;
bool maximum;
+ unsigned int maxvcpus;
virQEMUDriverConfigPtr cfg = NULL;
virCapsPtr caps = NULL;
qemuAgentCPUInfoPtr cpuinfo = NULL;
@@ -4207,11 +4214,12 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
goto endjob;
}
- if (!maximum && nvcpus > vm->def->maxvcpus) {
+ maxvcpus = (flags & VIR_DOMAIN_AFFECT_LIVE) ? vm->def->maxvcpus : persistentDef->maxvcpus;
+ if (!maximum && nvcpus > maxvcpus) {
virReportError(VIR_ERR_INVALID_ARG,
_("requested vcpus is greater than max allowable"
" vcpus for the domain: %d > %d"),
- nvcpus, vm->def->maxvcpus);
+ nvcpus, maxvcpus);
goto endjob;
}
10 years, 10 months