[libvirt] [PATCH v3] qemu: Pass file descriptor when using TPM passthrough
by Stefan Berger
Pass the TPM file descriptor to QEMU via command line.
Instead of passing /dev/tpm0 we now pass /dev/fdset/10 and the additional
parameters -add-fd set=10,fd=20.
This addresses the use case when QEMU is started with non-root privileges
and QEMU cannot open /dev/tpm0 for example.
One problem is that for the passing of the file descriptor set to work,
virCommandReorderFDs must not be called on the virCommand. This is prevented
by setting a flag in the virCommandPassFDGetFDIndex that is checked …
[View More]to be
clear when virCommandReorderFDs is run.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
v2->v3: Fixed some memory leaks
---
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 136 ++++++++++++++++++++++++++++++++++++++++++++---
src/util/vircommand.c | 33 ++++++++++++
src/util/vircommand.h | 3 ++
4 files changed, 166 insertions(+), 7 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index aeec440..3194e8b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1164,6 +1164,7 @@ virCommandNewArgList;
virCommandNewArgs;
virCommandNonblockingFDs;
virCommandPassFD;
+virCommandPassFDGetFDIndex;
virCommandPassListenFDs;
virCommandRawStatus;
virCommandRequireHandshake;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8ed7934..17debba 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -159,6 +159,58 @@ VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
"interleave");
/**
+ * qemuVirCommandGetFDSet:
+ * @cmd: the command to modify
+ * @fd: fd to reassign to the child
+ *
+ * Get the parameters for the QEMU -add-fd command line option
+ * for the given file descriptor. The file descriptor must previously
+ * have been 'transferred' in a virCommandPassFD() call.
+ * This function for example returns "set=10,fd=20".
+ */
+static char *
+qemuVirCommandGetFDSet(virCommandPtr cmd, int fd)
+{
+ char *result = NULL;
+ int idx = virCommandPassFDGetFDIndex(cmd, fd);
+
+ if (idx >= 0) {
+ ignore_value(virAsprintf(&result, "set=%d,fd=%d", idx, fd) < 0);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("file descriptor %d has not been transferred"), fd);
+ }
+
+ return result;
+}
+
+/**
+ * qemuVirCommandGetDevSet:
+ * @cmd: the command to modify
+ * @fd: fd to reassign to the child
+ *
+ * Get the parameters for the QEMU path= parameter where a file
+ * descriptor is accessed via a file descriptor set, for example
+ * /dev/fdset/10. The file descriptor must previously have been
+ * 'transferred' in a virCommandPassFD() call.
+ */
+static char *
+qemuVirCommandGetDevSet(virCommandPtr cmd, int fd)
+{
+ char *result = NULL;
+ int idx = virCommandPassFDGetFDIndex(cmd, fd);
+
+ if (idx >= 0) {
+ ignore_value(virAsprintf(&result, "/dev/fdset/%d", idx) < 0);
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("file descriptor %d has not been transferred"), fd);
+ }
+ return result;
+}
+
+
+/**
* qemuPhysIfaceConnect:
* @def: the definition of the VM (needed by 802.1Qbh and audit)
* @driver: pointer to the driver instance
@@ -5926,14 +5978,20 @@ qemuBuildRNGDeviceArgs(virCommandPtr cmd,
static char *qemuBuildTPMBackendStr(const virDomainDef *def,
+ virCommandPtr cmd,
virQEMUCapsPtr qemuCaps,
- const char *emulator)
+ const char *emulator,
+ int *tpmfd, int *cancelfd)
{
const virDomainTPMDef *tpm = def->tpm;
virBuffer buf = VIR_BUFFER_INITIALIZER;
const char *type = virDomainTPMBackendTypeToString(tpm->type);
- char *cancel_path;
+ char *cancel_path = NULL;
const char *tpmdev;
+ char *devset = NULL, *cancel_devset = NULL;
+
+ *tpmfd = -1;
+ *cancelfd = -1;
virBufferAsprintf(&buf, "%s,id=tpm-%s", type, tpm->info.alias);
@@ -5946,11 +6004,49 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
if (!(cancel_path = virTPMCreateCancelPath(tpmdev)))
goto error;
- virBufferAddLit(&buf, ",path=");
- virBufferEscape(&buf, ',', ",", "%s", tpmdev);
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ADD_FD)) {
+ *tpmfd = open(tpmdev, O_RDWR);
+ if (*tpmfd < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not open TPM device %s"), tpmdev);
+ goto error;
+ }
+
+ virCommandPassFD(cmd, *tpmfd,
+ VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ devset = qemuVirCommandGetDevSet(cmd, *tpmfd);
+ if (devset == NULL)
+ goto error;
+
+ *cancelfd = open(cancel_path, O_WRONLY);
+ if (*cancelfd < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not open TPM device's cancel path "
+ "%s"), cancel_path);
+ goto error;
+ }
+
+ virCommandPassFD(cmd, *cancelfd,
+ VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ cancel_devset = qemuVirCommandGetDevSet(cmd, *cancelfd);
+ if (cancel_devset == NULL)
+ goto error;
+
+ virBufferAddLit(&buf, ",path=");
+ virBufferEscape(&buf, ',', ",", "%s", devset);
+ VIR_FREE(devset);
- virBufferAddLit(&buf, ",cancel-path=");
- virBufferEscape(&buf, ',', ",", "%s", cancel_path);
+ virBufferAddLit(&buf, ",cancel-path=");
+ virBufferEscape(&buf, ',', ",", "%s", cancel_devset);
+ VIR_FREE(cancel_devset);
+ } else {
+ /* all test cases will use this path */
+ virBufferAddLit(&buf, ",path=");
+ virBufferEscape(&buf, ',', ",", "%s", tpmdev);
+
+ virBufferAddLit(&buf, ",cancel-path=");
+ virBufferEscape(&buf, ',', ",", "%s", cancel_path);
+ }
VIR_FREE(cancel_path);
break;
@@ -5970,6 +6066,10 @@ static char *qemuBuildTPMBackendStr(const virDomainDef *def,
emulator, type);
error:
+ VIR_FREE(devset);
+ VIR_FREE(cancel_devset);
+ VIR_FREE(cancel_path);
+
virBufferFreeAndReset(&buf);
return NULL;
}
@@ -9223,13 +9323,35 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->tpm) {
char *optstr;
+ int tpmfd = -1;
+ int cancelfd = -1;
+ char *fdset;
- if (!(optstr = qemuBuildTPMBackendStr(def, qemuCaps, emulator)))
+ if (!(optstr = qemuBuildTPMBackendStr(def, cmd, qemuCaps, emulator,
+ &tpmfd, &cancelfd)))
goto error;
virCommandAddArgList(cmd, "-tpmdev", optstr, NULL);
VIR_FREE(optstr);
+ if (tpmfd >= 0) {
+ fdset = qemuVirCommandGetFDSet(cmd, tpmfd);
+ if (!fdset)
+ goto error;
+
+ virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
+ VIR_FREE(fdset);
+ }
+
+ if (cancelfd >= 0) {
+ fdset = qemuVirCommandGetFDSet(cmd, cancelfd);
+ if (!fdset)
+ goto error;
+
+ virCommandAddArgList(cmd, "-add-fd", fdset, NULL);
+ VIR_FREE(fdset);
+ }
+
if (!(optstr = qemuBuildTPMDevStr(def, qemuCaps, emulator)))
goto error;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 6527d85..2616446 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -67,6 +67,7 @@ enum {
VIR_EXEC_RUN_SYNC = (1 << 3),
VIR_EXEC_ASYNC_IO = (1 << 4),
VIR_EXEC_LISTEN_FDS = (1 << 5),
+ VIR_EXEC_FIXED_FDS = (1 << 6),
};
typedef struct _virCommandFD virCommandFD;
@@ -214,6 +215,12 @@ virCommandReorderFDs(virCommandPtr cmd)
if (!cmd || cmd->has_error || !cmd->npassfd)
return;
+ if ((cmd->flags & VIR_EXEC_FIXED_FDS)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("The fds are fixed and cannot be reordered"));
+ goto error;
+ }
+
for (i = 0; i < cmd->npassfd; i++)
maxfd = MAX(cmd->passfd[i].fd, maxfd);
@@ -1019,6 +1026,32 @@ virCommandPassListenFDs(virCommandPtr cmd)
cmd->flags |= VIR_EXEC_LISTEN_FDS;
}
+/*
+ * virCommandPassFDGetFDIndex:
+ * @cmd: pointer to virCommand
+ * @fd: FD to get index of
+ *
+ * Determine the index of the FD in the transfer set.
+ *
+ * Returns index >= 0 if @set contains @fd,
+ * -1 otherwise.
+ */
+int
+virCommandPassFDGetFDIndex(virCommandPtr cmd, int fd)
+{
+ size_t i = 0;
+
+ while (i < cmd->npassfd) {
+ if (cmd->passfd[i].fd == fd) {
+ cmd->flags |= VIR_EXEC_FIXED_FDS;
+ return i;
+ }
+ i++;
+ }
+
+ return -1;
+}
+
/**
* virCommandSetPidFile:
* @cmd: the command to modify
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index bf65de4..198da2f 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -62,6 +62,9 @@ void virCommandPassFD(virCommandPtr cmd,
void virCommandPassListenFDs(virCommandPtr cmd);
+int virCommandPassFDGetFDIndex(virCommandPtr cmd,
+ int fd);
+
void virCommandSetPidFile(virCommandPtr cmd,
const char *pidfile) ATTRIBUTE_NONNULL(2);
--
1.9.3
[View Less]
10 years, 1 month
[libvirt] [PATCH] Add rlimits to lxc
by Ryan Cleere
---
src/conf/domain_conf.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 12 +++++
src/lxc/lxc_controller.c | 12 +++++
src/util/virprocess.c | 4 +-
src/util/virprocess.h | 3 ++
5 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2d81c37..a673dc2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include <fcntl.h&…
[View More]gt;
#include <strings.h>
+#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -1003,7 +1004,86 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
return -1;
}
+static virDomainRLimitsPtr
+virDomainRLimitsNew(void)
+{
+ virDomainRLimitsPtr def = NULL;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ return def;
+}
+
+static virDomainRLimitsPtr
+virDomainRLimitParseXML(xmlNodePtr node)
+{
+ char *c = NULL;
+ long long val;
+ virDomainRLimitsPtr def;
+ if (!(def = virDomainRLimitsNew()))
+ return NULL;
+
+ if (node->type == XML_ELEMENT_NODE) {
+ c = (char *)xmlNodeGetContent(node);
+ if (virStrToLong_ll(c, NULL, 10, &val) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not parse rlimit value of %s"),
+ c);
+ goto error;
+ }
+ VIR_FREE(c);
+
+ def->limit = val;
+ if (VIR_STRDUP(def->name, (char *)node->name) < 0)
+ goto error;
+
+ if (xmlStrEqual(node->name, BAD_CAST "as")) {
+ def->resource = RLIMIT_AS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "core")) {
+ def->resource = RLIMIT_CORE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "cpu")) {
+ def->resource = RLIMIT_CPU;
+ } else if (xmlStrEqual(node->name, BAD_CAST "data")) {
+ def->resource = RLIMIT_DATA;
+ } else if (xmlStrEqual(node->name, BAD_CAST "fsize")) {
+ def->resource = RLIMIT_FSIZE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "locks")) {
+ def->resource = RLIMIT_LOCKS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "memlock")) {
+ def->resource = RLIMIT_MEMLOCK;
+ } else if (xmlStrEqual(node->name, BAD_CAST "msgqueue")) {
+ def->resource = RLIMIT_MSGQUEUE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nice")) {
+ def->resource = RLIMIT_NICE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nofile")) {
+ def->resource = RLIMIT_NOFILE;
+ } else if (xmlStrEqual(node->name, BAD_CAST "nproc")) {
+ def->resource = RLIMIT_NPROC;
+ } else if (xmlStrEqual(node->name, BAD_CAST "rss")) {
+ def->resource = RLIMIT_RSS;
+ } else if (xmlStrEqual(node->name, BAD_CAST "rtprio")) {
+ def->resource = RLIMIT_RTPRIO;
+ } else if (xmlStrEqual(node->name, BAD_CAST "sigpending")) {
+ def->resource = RLIMIT_SIGPENDING;
+ } else if (xmlStrEqual(node->name, BAD_CAST "stack")) {
+ def->resource = RLIMIT_STACK;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not determine resource type of '%s'"),
+ node->name);
+ goto error;
+ }
+ }
+
+ return def;
+
+ error:
+ VIR_FREE(c);
+ VIR_FREE(def);
+ return NULL;
+}
static void
virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@@ -14180,6 +14260,28 @@ virDomainDefParseXML(xmlDocPtr xml,
virHashFree(bootHash);
+ if ((node = virXPathNode("./rlimits[1]", ctxt)) != NULL && (n = virXMLChildElementCount(node)) > 0) {
+ xmlNodePtr cur = node->children;
+ if (n && VIR_ALLOC_N(def->rlimits, n) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ if (!(def->rlimits[i] = virDomainRLimitParseXML(cur)))
+ goto error;
+ def->nrlimits++;
+ for (j = 0; j < i; j++) {
+ if (def->rlimits[j]->resource == def->rlimits[i]->resource) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("duplicate rlimit resources '%s'"),
+ def->rlimits[j]->name);
+ goto error;
+ }
+ }
+ cur = cur->next;
+ }
+ }
+ VIR_FREE(node);
+
return def;
error:
@@ -19759,6 +19861,19 @@ virDomainDefFormatInternal(virDomainDefPtr def,
goto error;
}
+ if (def->nrlimits > 0) {
+ virBufferAddLit(buf, "<rlimits>\n");
+ virBufferAdjustIndent(buf, 2);
+ for (n = 0; n < def->nrlimits; n++) {
+ virBufferAsprintf(buf, "<%s>%lld</%s>\n",
+ def->rlimits[n]->name,
+ def->rlimits[n]->limit,
+ def->rlimits[n]->name);
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</rlimits>\n");
+ }
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</domain>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 439f3c0..abad30e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2021,6 +2021,15 @@ struct _virDomainPowerManagement {
int s4;
};
+typedef struct _virDomainRLimits virDomainRLimits;
+typedef virDomainRLimits *virDomainRLimitsPtr;
+
+struct _virDomainRLimits {
+ char *name;
+ int resource;
+ long long limit;
+};
+
/*
* Guest VM main configuration
*
@@ -2138,6 +2147,9 @@ struct _virDomainDef {
size_t nshmems;
virDomainShmemDefPtr *shmems;
+ size_t nrlimits;
+ virDomainRLimitsPtr *rlimits;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 53a2c8d..ef5551e 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -2490,6 +2490,18 @@ int main(int argc, char *argv[])
}
}
+ VIR_INFO("nrlimits = %d", (int)ctrl->def->nrlimits);
+ if (ctrl->def->nrlimits > 0) {
+ struct rlimit rlim;
+ int n;
+ for (i = 0; i < ctrl->def->nrlimits; i++) {
+ rlim.rlim_max = rlim.rlim_cur = ctrl->def->rlimits[i]->limit;
+ n = virProcessPrLimit(0, ctrl->def->rlimits[i]->resource, &rlim);
+ if (n < 0)
+ goto cleanup;
+ }
+ }
+
rc = virLXCControllerRun(ctrl);
cleanup:
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 0c8a32f..9bb5370 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -675,13 +675,13 @@ int virProcessSetNamespaces(size_t nfdlist,
}
#if HAVE_PRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim)
{
return prlimit(pid, resource, rlim, NULL);
}
#elif HAVE_SETRLIMIT
-static int
+int
virProcessPrLimit(pid_t pid ATTRIBUTE_UNUSED,
int resource ATTRIBUTE_UNUSED,
struct rlimit *rlim ATTRIBUTE_UNUSED)
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index bcaede5..045f8d4 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -22,6 +22,7 @@
#ifndef __VIR_PROCESS_H__
# define __VIR_PROCESS_H__
+# include <sys/resource.h>
# include <sys/types.h>
# include "internal.h"
@@ -73,4 +74,6 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque);
int virProcessRunInMountNamespace(pid_t pid,
virProcessNamespaceCallback cb,
void *opaque);
+
+int virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim);
#endif /* __VIR_PROCESS_H__ */
--
1.9.3 (Apple Git-50)
[View Less]
10 years, 2 months
[libvirt] [PATCH 0/2]qemu: output error when try to hotplug/coldplug a unsupported device
by Luyao Huang
When use attach-device to hotplug a qemu unsupported console, command
will success and add a XML to the running guest, but donnot do anything
in qemu side. Add a check in qemuBuildConsoleChrDeviceStr, and output a
error when try to attach a qemu unsupport console.
About report error for qemu unsupported Chr device when cold-plug,
I think this maybe unnessary in this place, because we will check it
when we start the guest and it will report a clear error.But if we
use qemu* header func add a …
[View More]qemu unsupported things to qemu guest, it seems
strange.
Luyao Huang (2):
qemu: output error when try to hotplug unsupport console
qemu: add a check when cold-plug a Chr device
src/qemu/qemu_command.c | 6 ++++-
src/qemu/qemu_hotplug.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+), 1 deletion(-)
--
1.8.3.1
[View Less]
10 years, 2 months
[libvirt] [PATCH v2] network: Let domains be restricted to local DNS
by Josh Stone
This adds a new "localOnly" attribute on the domain element of the
network xml. With this set to "yes", DNS requests under that domain
will only be resolved by libvirt's dnsmasq, never forwarded upstream.
This was how it worked before commit f69a6b987d616, and I found that
functionality useful. For example, I have my host's NetworkManager
dnsmasq configured to forward that domain to libvirt's dnsmasq, so I can
easily resolve guest names from outside. But if libvirt's dnsmasq
doesn't know a …
[View More]name and forwards it to the host, I'd get an endless
forwarding loop. Now I can set localOnly="yes" to prevent the loop.
Signed-off-by: Josh Stone <jistone(a)redhat.com>
Cc: Laine Stump <laine(a)laine.org>
---
docs/formatnetwork.html.in | 12 +++++++-
docs/schemas/network.rng | 3 ++
src/conf/network_conf.c | 32 ++++++++++++++++++++--
src/conf/network_conf.h | 1 +
src/network/bridge_driver.c | 5 ++++
.../nat-network-dns-local-domain.conf | 14 ++++++++++
.../nat-network-dns-local-domain.xml | 9 ++++++
tests/networkxml2conftest.c | 1 +
8 files changed, 74 insertions(+), 3 deletions(-)
create mode 100644 tests/networkxml2confdata/nat-network-dns-local-domain.conf
create mode 100644 tests/networkxml2confdata/nat-network-dns-local-domain.xml
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index dc438aee8622..defcdba00930 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -82,7 +82,7 @@
<pre>
...
<bridge name="virbr0" stp="on" delay="5"/>
- <domain name="example.com"/>
+ <domain name="example.com" localOnly="no"/>
<forward mode="nat" dev="eth0"/>
...</pre>
@@ -113,6 +113,16 @@
a <code><forward></code> mode of "nat" or "route" (or an
isolated network with no <code><forward></code>
element). <span class="since">Since 0.4.5</span>
+
+ <p>
+ If the optional <code>localOnly</code> attribute on the
+ <code>domain</code> element is "yes", then DNS requests under
+ this domain will only be resolved by the virtual network's own
+ DNS server - they will not be forwarded to the host's upstream
+ DNS server. If <code>localOnly</code> is "no", and by
+ default, unresolved requests <b>will</b> be forwarded.
+ <span class="since">Since 1.2.11</span>
+ </p>
</dd>
<dt><code>forward</code></dt>
<dd>Inclusion of the <code>forward</code> element indicates that
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 4546f8037580..a1da28092375 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -225,6 +225,9 @@
<optional>
<element name="domain">
<attribute name="name"><ref name="dnsName"/></attribute>
+ <optional>
+ <attribute name="localOnly"><ref name="virYesNo"/></attribute>
+ </optional>
</element>
</optional>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 97719ed536de..31b765ff2c51 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2083,6 +2083,18 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
/* Parse network domain information */
def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
+ tmp = virXPathString("string(./domain[1]/@localOnly)", ctxt);
+ if (tmp) {
+ def->domain_local = virTristateBoolTypeFromString(tmp);
+ if (def->domain_local <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid domain localOnly setting '%s' "
+ "in network '%s'"),
+ tmp, def->name);
+ goto error;
+ }
+ VIR_FREE(tmp);
+ }
if ((bandwidthNode = virXPathNode("./bandwidth", ctxt)) != NULL &&
(def->bandwidth = virNetDevBandwidthParse(bandwidthNode, -1)) == NULL)
@@ -2805,8 +2817,24 @@ virNetworkDefFormatBuf(virBufferPtr buf,
virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr);
}
- if (def->domain)
- virBufferAsprintf(buf, "<domain name='%s'/>\n", def->domain);
+ if (def->domain) {
+ virBufferAsprintf(buf, "<domain name='%s'", def->domain);
+
+ /* default to "no", but don't format it in the XML */
+ if (def->domain_local) {
+ const char *local = virTristateBoolTypeToString(def->domain_local);
+
+ if (!local) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown localOnly type %d in network"),
+ def->domain_local);
+ return -1;
+ }
+ virBufferAsprintf(buf, " localOnly='%s'", local);
+ }
+
+ virBufferAddLit(buf, "/>\n");
+ }
if (virNetworkDNSDefFormat(buf, &def->dns) < 0)
goto error;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 660cd2d10cd1..bb9724fddbb8 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -232,6 +232,7 @@ struct _virNetworkDef {
char *bridge; /* Name of bridge device */
char *domain;
+ int domain_local; /* enum virTristateBool: yes disables dns forwarding */
unsigned long delay; /* Bridge forward delay (ms) */
bool stp; /* Spanning tree protocol */
virMacAddr mac; /* mac address of bridge device */
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 9ccc9f8f8de6..f4158517c573 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -928,6 +928,11 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
}
if (network->def->domain) {
+ if (network->def->domain_local == VIR_TRISTATE_BOOL_YES) {
+ virBufferAsprintf(&configbuf,
+ "local=/%s/\n",
+ network->def->domain);
+ }
virBufferAsprintf(&configbuf,
"domain=%s\n"
"expand-hosts\n",
diff --git a/tests/networkxml2confdata/nat-network-dns-local-domain.conf b/tests/networkxml2confdata/nat-network-dns-local-domain.conf
new file mode 100644
index 000000000000..5f41b9186cbc
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-local-domain.conf
@@ -0,0 +1,14 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+local=/example.com/
+domain=example.com
+expand-hosts
+except-interface=lo
+bind-dynamic
+interface=virbr0
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
diff --git a/tests/networkxml2confdata/nat-network-dns-local-domain.xml b/tests/networkxml2confdata/nat-network-dns-local-domain.xml
new file mode 100644
index 000000000000..a92d71f1f2f6
--- /dev/null
+++ b/tests/networkxml2confdata/nat-network-dns-local-domain.xml
@@ -0,0 +1,9 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+ <forward dev='eth0' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <domain name='example.com' localOnly='yes'/>
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ </ip>
+</network>
diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c
index 267513f6372c..280db306b6d6 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -134,6 +134,7 @@ mymain(void)
DO_TEST("nat-network-dns-hosts", full);
DO_TEST("nat-network-dns-forward-plain", full);
DO_TEST("nat-network-dns-forwarders", full);
+ DO_TEST("nat-network-dns-local-domain", full);
DO_TEST("dhcp6-network", dhcpv6);
DO_TEST("dhcp6-nat-network", dhcpv6);
DO_TEST("dhcp6host-routed-network", dhcpv6);
--
2.1.0
[View Less]
10 years, 2 months
[libvirt] [PATCH] qemu: snapshot: inactive external snapshot can't work after libvirtd restart
by Shanzhi Yu
When create inactive external snapshot, after update disk definitions,
virDomainSaveConfig is needed, if not after restart libvirtd the new snapshot
file definitions in xml will be lost.
Reproduce steps:
1. prepare a shut off guest
$ virsh domstate rhel7 && virsh domblklist rhel7
shut off
Target Source
------------------------------------------------
vda /var/lib/libvirt/images/rhel7.img
2. create external disk snapshot
$ virsh snapshot-create rhel7 --disk-only && …
[View More]virsh domblklist rhel7
Domain snapshot 1417882967 created
Target Source
------------------------------------------------
vda /var/lib/libvirt/images/rhel7.1417882967
3. restart libvirtd then check guest source file
$ service libvirtd restart && virsh domblklist rhel7
Redirecting to /bin/systemctl restart libvirtd.service
Target Source
------------------------------------------------
vda /var/lib/libvirt/images/rhel7.img
This was first reported by Eric Blake
http://www.redhat.com/archives/libvir-list/2014-December/msg00369.html
Signed-off-by: Shanzhi Yu <shyu(a)redhat.com>
---
src/qemu/qemu_driver.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9152cf5..9f8ea0a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -12847,6 +12847,9 @@ qemuDomainSnapshotCreateInactiveExternal(virQEMUDriverPtr driver,
goto cleanup;
}
defdisk->src->format = snapdisk->src->format;
+
+ if (virDomainSaveConfig(cfg->configDir, vm->def) < 0)
+ goto cleanup;
}
}
--
2.1.0
[View Less]
10 years, 2 months
[libvirt] [PATCH 0/2] check IOMMU group devices usage during vfio device passthrough
by Shivaprasad G Bhat
Problem:
====================================================================
If a device in the same iommu group is in use by a different vm, the guest boot
fails with the below error during vfio passthrough.
bash-4.2$ virsh start demo
error: Failed to start domain demo
error: internal error: process exited while connecting to monitor:
2014-12-02T13:43:52.020136Z qemu-system-x86_64: -device vfio-pci,host=00:1c.3,id=hostdev0,bus=pci.0,addr=0x5: vfio: error opening /dev/vfio/7: Device or …
[View More]resource busy
Solution:
=====================================================================
The patch iterates through the iommu group devices and errors out cleanly
mentioning the device and the guest which is using the device.
With Patch
bash-4.2$ virsh start demo
error: Failed to start domain demo
error: Requested operation is not valid: PCI device 0000:0d:00.0 is in use by driver QEMU, domain vm10
---
Shivaprasad G Bhat (2):
Move struct _virPCIDevice definition from virpci.c to virpci.h
check IOMMU group devices usage when preparing device for vfio passthrough
src/util/virhostdev.c | 87 +++++++++++++++++++++++++++++--------------------
src/util/virpci.c | 29 ----------------
src/util/virpci.h | 30 +++++++++++++++++
3 files changed, 82 insertions(+), 64 deletions(-)
--
Signature
[View Less]
10 years, 2 months
[libvirt] [PATCHv7 0/4] Introduce API to query IP addresses for given domain
by Nehal J Wani
This feature has been requested for a very long time. Since qemu guest
agent gives us reliable results, now the wait is over.
The RFC was first proposed by Michal Privoznik:
http://www.redhat.com/archives/libvir-list/2012-February/msg00437.html
A patch was submitted, using structs:
https://www.redhat.com/archives/libvir-list/2012-June/msg00220.html
Another patch was submitted, using XML:
https://www.redhat.com/archives/libvir-list/2012-June/msg00904.html
Neither of the …
[View More]patches were accepted, probably due to lack of extensibility
and usability. Hence, we thought of using virTypedParameters for reporting
list of interfaces along with their MAC address and IP addresses. The RFC
can be found here:
https://www.redhat.com/archives/libvir-list/2013-July/msg00084.html
The idea of extensibility was rejected and rendered out of scope of
libvirt. Hence, we were back to structs.
This API is called virDomainInterfaceAddresses which returns a dynamically
allocated array of virDomainInterface struct. The great disadvantage is
once this gets released, it's written in stone and we cannot change
or add an item into it.
The virsh CLI supports two methods:
* Return information (list of all associated interfaces with MAC address
and IP addresses) of all of the domain interfaces by default (if
no interface name is provided)
* Return information for the specified interface (if an interface name
is provided)
v7:
* Enable support for DHCP lease file parsing method
v6:
* Inclusion of flags, readonly check for guest agent connection
* Correction of memory leaks, other small nits.
* https://www.redhat.com/archives/libvir-list/2013-September/msg00350.html
v5:
* s/virDomainInterfacesAddresses/virDomainInterfaceAddresses.
* Case for IP aliasing handled using virHashTable.
* New test cases added, involving multiple and 0 IP addresse(s)
per interface.
* IP prefix changed from int to unsigned int.
* Changes to practice libvirt habits.
* https://www.redhat.com/archives/libvir-list/2013-September/msg00003.html
v4:
* Various style nits, indentation errors, memory leaks fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01265.html
v3:
* Upper bounds to number of interfaces and addresses per interface
introduced.
* Change from array of structs to array of pointers
* ifaces_count moved from function argument to return value
* Changes in variable names
* Test cases added for qemuAgentGetInterfaces.
* https://www.redhat.com/archives/libvir-list/2013-August/msg01215.html
v2:
* Logical errors, memory leaks and few other errors fixed.
* https://www.redhat.com/archives/libvir-list/2013-August/msg00631.html
v1:
* http://www.redhat.com/archives/libvir-list/2013-July/msg01553.html
Nehal J Wani (4):
domifaddr: Implement the public APIs
domifaddr: Implement the remote protocol
domifaddr: Implement the API for qemu
domifaddr: Add virsh support
daemon/remote.c | 134 +++++++++++++++++++++++++
include/libvirt/libvirt-domain.h | 27 +++++
src/driver-hypervisor.h | 5 +
src/libvirt-domain.c | 129 ++++++++++++++++++++++++
src/libvirt_public.syms | 2 +
src/qemu/qemu_agent.c | 202 ++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 4 +
src/qemu/qemu_driver.c | 153 +++++++++++++++++++++++++++++
src/remote/remote_driver.c | 100 +++++++++++++++++++
src/remote/remote_protocol.x | 42 +++++++-
src/remote_protocol-structs | 24 +++++
tests/qemuagenttest.c | 188 +++++++++++++++++++++++++++++++++++
tools/virsh-domain-monitor.c | 141 ++++++++++++++++++++++++++
tools/virsh.pod | 16 +++
14 files changed, 1166 insertions(+), 1 deletion(-)
--
1.7.10.4
[View Less]
10 years, 2 months
[libvirt] [PATCH 0/9] qemu: Add quorum support to libvirt
by Matthias Gatto
The purpose of these patches is to introduce quorum for libvirt
I've try to follow this proposal:
http://www.redhat.com/archives/libvir-list/2014-May/msg00533.html
This feature ask for 6 task:
1) Allow a _virStorageSource
to contain more than one backing store.
Therefore we have to treat the field virStorageSourcePtr backingStores
as an array instead of a pointer.
But doing that, most of the backingStore field would be an array contening
only one element.
So I've decide to allocate the array …
[View More]only if there is more than 1
backing store in a _virStorageSource.
Because all the actual libvirt code use the backingStore field
as a pointer and we needs want to change that, I've decide to encapsulate
the backingStore field to simplifie the array manipulation.
2) Add the missing field a quorum need in _virStorageSource and
the VIR_STORAGE_TYPE_QUORUM and VIR_STORAGE_FILE_QUORUM in
their respectives enums.
3) Parse and format the xml
Because a quorum allows to have more than one backing store at the same level
we need to change virDomainDiskDefFormat and virDomainDiskDefParseXML
to call virDomainDiskBackingStoreFormat and virDomainDiskBackingStoreParse
in a loop.
virDomainDiskBackingStoreFormat and virDomainDiskBackingStoreParse can
call themself recursively in a loop because a quorum can contain another
quorum
4) Add nodename
We need to add nodename support in _virStorageSource because qemu
use them for their child.
5) Build qemu string
As for the xml, we have to call the function which create quorum recursively.
But this task have the problem explained here:
http://www.redhat.com/archives/libvir-list/2014-October/msg00529.html
The _virStorageSource missing some informations that can be passed to
a child, and therefore this version of quorum is incomplet.
6) Allow to hotplug/change a disk in a quorum
This part is not present in these patches because for this task
we have to use blockdev-add, and currently libvirt use
device_add for hotpluging that doesn't allow to hotplug quorum childs.
There is 3 way to handle this problem:
1) create a virDomainBlockDevAdd function in libvirt witch call
blockdev-add.
2) use blockdev-add instead of device_add in qemuMonitorJSONAddDevice
3) write a hack which uses blockdev-add when only attaching quorum
(but i'm pretty sure this solution is not the good one)
Matthias Gatto (9):
virstoragefile: Add virStorageSourceGetBackingStore
virstoragefile: Always use virStorageSourceGetBackingStore to get
backing store
virstoragefile: Add virStorageSourceSetBackingStore
virstoragefile: Always use virStorageSourceSetBackingStore to set
backing store
virstoragefile: Treat backingStore as a pointer or an array
virstoragefile: Add quorum in virstoragefile
domain_conf: Read and Write quorum config
qemu: Add quorum support in qemuBuildDriveDevStr
virstoragefile: Add node-name
src/conf/domain_conf.c | 193 ++++++++++++++++++++++++++--------
src/conf/storage_conf.c | 7 +-
src/libvirt_private.syms | 3 +
src/qemu/qemu_cgroup.c | 4 +-
src/qemu/qemu_command.c | 114 ++++++++++++++++++++
src/qemu/qemu_domain.c | 3 +-
src/qemu/qemu_driver.c | 20 ++--
src/security/security_dac.c | 2 +-
src/security/security_selinux.c | 4 +-
src/security/virt-aa-helper.c | 2 +-
src/storage/storage_backend.c | 12 +--
src/storage/storage_backend_fs.c | 12 +--
src/storage/storage_backend_logical.c | 4 +-
src/storage/storage_driver.c | 2 +-
src/util/virstoragefile.c | 136 +++++++++++++++++++++---
src/util/virstoragefile.h | 12 +++
tests/virstoragetest.c | 18 ++--
17 files changed, 445 insertions(+), 103 deletions(-)
--
1.8.3.1
[View Less]
10 years, 2 months
[libvirt] [PATCH 0/5] parallels: manage container's filesystems
by Dmitry Guryanov
This patch series adds ability to manage container's
filesystems: you can add or remove fs from existing
container or create new one, based on existing
disk image.
Dmitry Guryanov (5):
add ploop fs driver type
parallels: dump info about container filesystems
parallels: commit with PVCF_DETACH_HDD_BUNDLE flag
parallels: allow to add filesystems to container
parallels: create container from existing image
src/conf/domain_conf.c | 3 +-
src/conf/domain_conf.h | 1 +
…
[View More]src/parallels/parallels_sdk.c | 209 ++++++++++++++++++++++++++++++++++++++----
src/qemu/qemu_command.c | 1 +
4 files changed, 196 insertions(+), 18 deletions(-)
--
2.1.0
[View Less]
10 years, 2 months
[libvirt] [PATCH 1/2] lxc: Move setting ifname_guest_actual to virLXCSetupInterfaces
by Guido Günther
so it applies to interfaces of type 'direct' too.
Reported and patch provided by Bastian Blank at
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=769600
---
src/lxc/lxc_process.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 1c0d4e5..c3818a5 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -260,8 +260,6 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
if (…
[View More]virNetDevSetMAC(containerVeth, &net->mac) < 0)
goto cleanup;
- if (VIR_STRDUP(net->ifname_guest_actual, containerVeth) < 0)
- goto cleanup;
if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
@@ -432,6 +430,9 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
(*veths)[(*nveths)-1] = veth;
+ if (VIR_STRDUP(def->nets[i]->ifname_guest_actual, veth) < 0)
+ goto cleanup;
+
/* Make sure all net definitions will have a name in the container */
if (!net->ifname_guest) {
if (virAsprintf(&net->ifname_guest, "eth%zu", niface) < 0)
--
2.1.3
[View Less]
10 years, 2 months