[libvirt] [PATCHv2] conf: more useful error message when pci function is out of range
by Laine Stump
If a pci address had a function number out of range, the error message
would be:
Insufficient specification for PCI address
which is logged by virDevicePCIAddressParseXML() after
virDevicePCIAddressIsValid returns a failure.
This patch enhances virDevicePCIAddressIsValid() to optionally report
the error itself (since it is the place that decides which part of the
address is "invalid"), and uses that feature when calling from
virDevicePCIAddressParseXML(), so that the error will be more useful,
e.g.:
Invalid PCI address function=0x8, must be <= 7
Previously, virDevicePCIAddressIsValid didn't check for the
theoretical limits of domain or bus, only for slot or function. While
adding log messages, we also correct that ommission. (The RNG for PCI
addresses already enforces this limit, which by the way means that we
can't add any negative tests for this - as far as I know our
domainschematest has no provisions for passing XML that is supposed to
fail).
Note that virDevicePCIAddressIsValid() can only check against the
absolute maximum attribute values for *any* possible PCI controller,
not for the actual maximums of the specific controller that this
device is attaching to; fortunately there is later more specific
validation for guest-side PCI addresses when building the set of
assigned PCI addresses. For host-side PCI addresses (e.g. for
<hostdev> and for network device pools), we rely on the error that
will be logged when it is found that the device doesn't actually
exist.
This resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1004596
---
Change from V1:
V1 simply removed the validation from virDevicePCIAddressParseXML() in
favor of allowing things later in the parse process to figure out the
out-of-bounds conditions, but jtomko pointed out that there are other
uses of virDevicePCIAddressParseXML() aside from the guest-side PCI
addresses of devices, and that the other uses relied on the one
validation check in virDevicePCIAddressParseXML() to make sure the
address was sensible. So instead of simply removing the check, I had
to make it smarter about what it logged. In the process, I added
checks for max domain and bus.
src/conf/device_conf.c | 52 +++++++++++++++++++++++++++++++++++++++++---------
src/conf/device_conf.h | 5 +++--
src/conf/domain_conf.c | 2 +-
3 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index e7b7957..4e15d38 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -1,7 +1,7 @@
/*
* device_conf.c: device XML handling
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2015 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
@@ -55,12 +55,49 @@ VIR_ENUM_IMPL(virNetDevFeature,
"rdma",
"txudptnl")
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
+ bool report)
{
- /* PCI bus has 32 slots and 8 functions per slot */
- if (addr->slot >= 32 || addr->function >= 8)
+ if (addr->domain > 0xFFFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address domain='0x%x', "
+ "must be <= 0xFFFF"),
+ addr->domain);
+ return 0;
+ }
+ if (addr->bus > 0xFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address bus='0x%x', "
+ "must be <= 0xFF"),
+ addr->bus);
return 0;
- return addr->domain || addr->bus || addr->slot;
+ }
+ if (addr->slot > 0x1F) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address slot='0x%x', "
+ "must be <= 0x1F"),
+ addr->slot);
+ return 0;
+ }
+ if (addr->function > 7) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address function=0x%x, "
+ "must be <= 7"),
+ addr->function);
+ return 0;
+ }
+ if (!(addr->domain || addr->bus || addr->slot)) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid PCI address 0000:00:00, at least "
+ "one of domain, bus, or slot must be > 0"));
+ return 0;
+ }
+ return 1;
}
@@ -115,11 +152,8 @@ virDevicePCIAddressParseXML(xmlNodePtr node,
goto cleanup;
}
- if (!virDevicePCIAddressIsValid(addr)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Insufficient specification for PCI address"));
+ if (!virDevicePCIAddressIsValid(addr, true))
goto cleanup;
- }
ret = 0;
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 40a2b3d..85ce40f 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -1,7 +1,7 @@
/*
* device_conf.h: device XML handling entry points
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2012, 2014-2015 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
@@ -81,7 +81,8 @@ typedef enum {
VIR_ENUM_DECL(virNetDevFeature)
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr);
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
+ bool report);
int virDevicePCIAddressParseXML(xmlNodePtr node,
virDevicePCIAddressPtr addr);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8a89b9a..5142201 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3133,7 +3133,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
switch (info->type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
- return virDevicePCIAddressIsValid(&info->addr.pci);
+ return virDevicePCIAddressIsValid(&info->addr.pci, false);
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
return 1;
--
2.1.0
9 years, 8 months
[libvirt] [PATCH] Inherit namespace feature
by ik.nitk
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what
lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as
[ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing namespace.
>From this patch you can add extra libvirt option to share namespace in following way.
<lxc:namespace>
<lxc:sharenet type='netns' value='red'/>
<lxc:shareipc type='pid' value='12345'/>
<lxc:shareuts type='name' value='container1'/>
</lxc:namespace>
---
docs/drvlxc.html.in | 18 +++
docs/schemas/domaincommon.rng | 42 ++++++
src/Makefile.am | 4 +-
src/lxc/lxc_conf.c | 2 +-
src/lxc/lxc_conf.h | 15 +++
src/lxc/lxc_container.c | 236 +++++++++++++++++++++++++++++++++-
src/lxc/lxc_domain.c | 164 ++++++++++++++++++++++-
src/lxc/lxc_domain.h | 1 +
tests/lxcxml2xmldata/lxc-sharenet.xml | 33 +++++
tests/lxcxml2xmltest.c | 1 +
10 files changed, 507 insertions(+), 9 deletions(-)
create mode 100644 tests/lxcxml2xmldata/lxc-sharenet.xml
diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in
index a094bd9..d14d4c7 100644
--- a/docs/drvlxc.html.in
+++ b/docs/drvlxc.html.in
@@ -590,6 +590,24 @@ Note that allowing capabilities that are normally dropped by default can serious
affect the security of the container and the host.
</p>
+<h2><a name="share">Inherit namespaces</a></h2>
+
+<p>
+Libvirt allows you to inherit the namespace from container/process just like lxc tools
+or docker provides to share the network namespace. The following can be used to share
+required namespaces. If we want to share only one then the other namespaces can be ignored.
+</p>
+<pre>
+<domain type='lxc' xmlns:lxc='http://libvirt.org/schemas/domain/lxc/1.0'>
+...
+<lxc:namespace>
+ <lxc:sharenet type='netns' value='red'/>
+ <lxc:shareuts type='name' value='container1'/>
+ <lxc:shareipc type='pid' value='12345'/>
+</lxc:namespace>
+</domain>
+</pre>
+
<h2><a name="usage">Container usage / management</a></h2>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 1120003..803b327 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -68,6 +68,9 @@
<ref name='qemucmdline'/>
</optional>
<optional>
+ <ref name='lxcsharens'/>
+ </optional>
+ <optional>
<ref name='keywrap'/>
</optional>
</interleave>
@@ -5012,6 +5015,45 @@
</element>
</define>
+ <!--
+ Optional hypervisor extensions in their own namespace:
+ LXC
+ -->
+ <define name="lxcsharens">
+ <element name="namespace" ns="http://libvirt.org/schemas/domain/lxc/1.0">
+ <zeroOrMore>
+ <element name="sharenet">
+ <attribute name="type">
+ <choice>
+ <value>netns</value>
+ <value>name</value>
+ <value>pid</value>
+ </choice>
+ </attribute>
+ <attribute name='value'/>
+ </element>
+ <element name="shareipc">
+ <attribute name="type">
+ <choice>
+ <value>name</value>
+ <value>pid</value>
+ </choice>
+ </attribute>
+ <attribute name='value'/>
+ </element>
+ <element name="shareuts">
+ <attribute name="type">
+ <choice>
+ <value>name</value>
+ <value>pid</value>
+ </choice>
+ </attribute>
+ <attribute name='value'/>
+ </element>
+ </zeroOrMore>
+ </element>
+ </define>
+
<define name="metadata">
<element name="metadata">
<zeroOrMore>
diff --git a/src/Makefile.am b/src/Makefile.am
index be63e26..ef96a5a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1319,7 +1319,7 @@ libvirt_driver_lxc_impl_la_CFLAGS = \
-I$(srcdir)/access \
-I$(srcdir)/conf \
$(AM_CFLAGS)
-libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(FUSE_LIBS)
+libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(LIBXML_LIBS) libvirt-lxc.la $(FUSE_LIBS)
if WITH_BLKID
libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
@@ -2709,6 +2709,8 @@ libvirt_lxc_LDADD = \
libvirt-net-rpc.la \
libvirt_security_manager.la \
libvirt_conf.la \
+ libvirt.la \
+ libvirt-lxc.la \
libvirt_util.la \
../gnulib/lib/libgnu.la
if WITH_DTRACE_PROBES
diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index c393cb5..96a0f47 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -213,7 +213,7 @@ lxcDomainXMLConfInit(void)
{
return virDomainXMLOptionNew(&virLXCDriverDomainDefParserConfig,
&virLXCDriverPrivateDataCallbacks,
- NULL);
+ &virLXCDriverDomainXMLNamespace);
}
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index 8340b1f..72b1d44 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -67,6 +67,21 @@ struct _virLXCDriverConfig {
bool securityRequireConfined;
};
+
+typedef enum {
+ VIR_DOMAIN_NAMESPACE_SHARENET = 0,
+ VIR_DOMAIN_NAMESPACE_SHAREIPC,
+ VIR_DOMAIN_NAMESPACE_SHAREUTS,
+ VIR_DOMAIN_NAMESPACE_LAST,
+} virDomainNamespace;
+
+typedef struct _lxcDomainDef lxcDomainDef;
+typedef lxcDomainDef *lxcDomainDefPtr;
+struct _lxcDomainDef {
+ char *ns_type[VIR_DOMAIN_NAMESPACE_LAST];
+ char *ns_val[VIR_DOMAIN_NAMESPACE_LAST];
+};
+
struct _virLXCDriver {
virMutex lock;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 11e9514..d8362ab 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -27,6 +27,7 @@
#include <config.h>
#include <fcntl.h>
+#include <sched.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
@@ -38,7 +39,6 @@
#include <mntent.h>
#include <sys/reboot.h>
#include <linux/reboot.h>
-
/* Yes, we want linux private one, for _syscall2() macro */
#include <linux/unistd.h>
@@ -2321,6 +2321,181 @@ virArch lxcContainerGetAlt32bitArch(virArch arch)
return VIR_ARCH_NONE;
}
+struct ns_info {
+ const char *proc_name;
+ int clone_flag;
+}ns_info_local[VIR_DOMAIN_NAMESPACE_LAST] = {
+ [VIR_DOMAIN_NAMESPACE_SHARENET] = {"net", CLONE_NEWNET},
+ [VIR_DOMAIN_NAMESPACE_SHAREIPC] = {"ipc", CLONE_NEWIPC},
+ [VIR_DOMAIN_NAMESPACE_SHAREUTS] = {"uts", CLONE_NEWUTS}
+};
+
+static int lxcOpen_ns(lxcDomainDefPtr lxcDef, int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
+{
+ int i, n, rc = 0;
+ virDomainPtr dom = NULL;
+ virConnectPtr conn = NULL;
+ pid_t pid;
+ int nfdlist;
+ int *fdlist;
+ char *path = NULL;
+ char *eptr;
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+ ns_fd[i] = -1;
+
+ if (STREQ_NULLABLE("netns", lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET])) {
+ if (virAsprintf(&path, "/var/run/netns/%s", lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]) < 0)
+ return -1;
+ ns_fd[VIR_DOMAIN_NAMESPACE_SHARENET] = open(path, O_RDONLY);
+ VIR_FREE(path);
+ if (ns_fd[VIR_DOMAIN_NAMESPACE_SHARENET] < 0) {
+ virReportSystemError(errno,
+ _("failed to open netns %s"), lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]);
+ return -1;
+ }
+ }
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ /* If not yet intialized by above: netns*/
+ if (lxcDef->ns_type[i] && ns_fd[i] == -1) {
+ pid = strtol(lxcDef->ns_val[i], &eptr, 10);
+ if (*eptr != '\0' || pid < 1) {
+ /* check if the domain is running, then set the namespaces
+ * to that container
+ */
+ const char *ns[] = { "user", "ipc", "uts", "net", "pid", "mnt" };
+ conn = virConnectOpen("lxc:///");
+ if (!conn) {
+ virReportError(virGetLastError()->code,
+ _("unable to get connect to lxc %s"), lxcDef->ns_val[i]);
+ rc = -1;
+ goto cleanup;
+ }
+ dom = virDomainLookupByName(conn, lxcDef->ns_val[i]);
+ if (!dom) {
+ virReportError(virGetLastError()->code,
+ _("Unable to lookup peer containeri %s"),
+ lxcDef->ns_val[i]);
+ rc = -1;
+ goto cleanup;
+ }
+ if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) {
+ virReportError(virGetLastError()->code,
+ _("Unable to open %s"), lxcDef->ns_val[i]);
+ rc = -1;
+ goto cleanup;
+ }
+ for (n = 0; n < ARRAY_CARDINALITY(ns); n++) {
+ if (STREQ(ns[n], ns_info_local[i].proc_name)) {
+ ns_fd[i] = fdlist[n];
+ } else {
+ if (VIR_CLOSE(fdlist[n]) < 0)
+ VIR_ERROR(_("failed to close fd. ignoring.."));
+ }
+ }
+ if (nfdlist > 0)
+ VIR_FREE(fdlist);
+ } else {
+ if (virAsprintf(&path, "/proc/%d/ns/%s", pid, ns_info_local[i].proc_name) < 0)
+ return -1;
+ ns_fd[i] = open(path, O_RDONLY);
+ VIR_FREE(path);
+ if (ns_fd[i] < 0) {
+ virReportSystemError(errno,
+ _("failed to open ns %s"), lxcDef->ns_val[i]);
+ return -1;
+ }
+ }
+ }
+ }
+ cleanup:
+ if (dom)
+ virDomainFree(dom);
+ if (conn)
+ virConnectClose(conn);
+ return rc;
+}
+
+
+static void lxcClose_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
+{
+ int i;
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if (ns_fd[i] > -1) {
+ if (VIR_CLOSE(ns_fd[i]) < 0)
+ virReportSystemError(errno, "%s", _("failed to close file"));
+ ns_fd[i] = -1;
+ }
+ }
+}
+
+
+/**
+ * lxcPreserve_ns:
+ * @ns_fd: array to store current namespace
+ * @clone_flags: namespaces that need to be preserved
+ */
+static int lxcPreserve_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST], int clone_flags)
+{
+ int i, saved_errno;
+ char *path = NULL;
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+ ns_fd[i] = -1;
+
+ if (!virFileExists("/proc/self/ns")) {
+ virReportSystemError(errno, "%s",
+ _("Kernel does not support attach; preserve_ns ignored"));
+ return -1;
+ }
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if ((clone_flags & ns_info_local[i].clone_flag) == 0)
+ continue;
+ if (virAsprintf(&path, "/proc/self/ns/%s",
+ ns_info_local[i].proc_name) < 0)
+ goto error;
+ ns_fd[i] = open(path, O_RDONLY | O_CLOEXEC);
+ if (ns_fd[i] < 0)
+ goto error;
+ VIR_FREE(path);
+ }
+ return 0;
+ error:
+ saved_errno = errno;
+ lxcClose_ns(ns_fd);
+ errno = saved_errno;
+ virReportSystemError(errno, _("lxcPreserve_ns failed for '%s'"), path);
+ VIR_FREE(path);
+ return -1;
+}
+
+/**
+ * lxcAttach_ns:
+ * @ns_fd: array of namespaces to attach
+ */
+static int lxcAttach_ns(const int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
+{
+ int i;
+
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ if (ns_fd[i] < 0)
+ continue;
+ VIR_DEBUG("Setting into namespace\n");
+ /* We get EINVAL if new NS is same as the current
+ * NS, or if the fd namespace doesn't match the
+ * type passed to setns()'s second param. Since we
+ * pass 0, we know the EINVAL is harmless
+ */
+ if (setns(ns_fd[i], 0) < 0 &&
+ errno != EINVAL) {
+ virReportSystemError(errno, _("failed to set namespace '%s'")
+ , ns_info_local[i].proc_name);
+ return -1;
+ }
+ }
+ return 0;
+}
+
/**
* lxcContainerStart:
@@ -2346,9 +2521,13 @@ int lxcContainerStart(virDomainDefPtr def,
char **ttyPaths)
{
pid_t pid;
- int cflags;
+ int cflags, i;
int stacksize = getpagesize() * 4;
char *stack, *stacktop;
+ int saved_ns_fd[VIR_DOMAIN_NAMESPACE_LAST];
+ int ns_inherit_fd[VIR_DOMAIN_NAMESPACE_LAST];
+ int preserve_mask = 0;
+ lxcDomainDefPtr lxcDef;
lxc_child_argv_t args = {
.config = def,
.securityDriver = securityDriver,
@@ -2368,7 +2547,12 @@ int lxcContainerStart(virDomainDefPtr def,
stacktop = stack + stacksize;
- cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD;
+ lxcDef = def->namespaceData;
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+ if (lxcDef && lxcDef->ns_type[i])
+ preserve_mask |= ns_info_local[i].clone_flag;
+
+ cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD;
if (userns_required(def)) {
if (userns_supported()) {
@@ -2381,10 +2565,43 @@ int lxcContainerStart(virDomainDefPtr def,
return -1;
}
}
+ if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET]) {
+ if (lxcNeedNetworkNamespace(def)) {
+ VIR_DEBUG("Enable network namespaces");
+ cflags |= CLONE_NEWNET;
+ }
+ } else {
+ VIR_DEBUG("Inheriting a net namespace");
+ }
+
+ if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREIPC]) {
+ cflags |= CLONE_NEWIPC;
+ } else {
+ VIR_DEBUG("Inheriting an IPC namespace");
+ }
+
+ if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREUTS]) {
+ cflags |= CLONE_NEWUTS;
+ } else {
+ VIR_DEBUG("Inheriting a UTS namespace");
+ }
+
+ if (lxcDef && lxcPreserve_ns(saved_ns_fd, preserve_mask) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to preserve the namespace"));
+ return -1;
+ }
- if (lxcNeedNetworkNamespace(def)) {
- VIR_DEBUG("Enable network namespaces");
- cflags |= CLONE_NEWNET;
+ if (lxcDef && lxcOpen_ns(lxcDef, ns_inherit_fd)) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to open the namespace"));
+ return -1;
+ }
+
+ if (lxcDef && lxcAttach_ns(ns_inherit_fd) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to attach the namespace"));
+ return -1;
}
VIR_DEBUG("Cloning container init process");
@@ -2397,7 +2614,14 @@ int lxcContainerStart(virDomainDefPtr def,
_("Failed to run clone container"));
return -1;
}
+ if (lxcDef && lxcAttach_ns(saved_ns_fd)) {
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to restore saved namespaces"));
+ }
+ /* clean up */
+ if (lxcDef)
+ lxcClose_ns(ns_inherit_fd);
return pid;
}
diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
index 70606f3..5e63969 100644
--- a/src/lxc/lxc_domain.c
+++ b/src/lxc/lxc_domain.c
@@ -26,8 +26,14 @@
#include "viralloc.h"
#include "virlog.h"
#include "virerror.h"
+#include <fcntl.h>
+#include <libxml/xpathInternals.h>
+#include "virstring.h"
+#include "virutil.h"
+#include "virfile.h"
#define VIR_FROM_THIS VIR_FROM_LXC
+#define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0"
VIR_LOG_INIT("lxc.lxc_domain");
@@ -41,6 +47,163 @@ static void *virLXCDomainObjPrivateAlloc(void)
return priv;
}
+VIR_ENUM_DECL(virDomainNamespace)
+VIR_ENUM_IMPL(virDomainNamespace, VIR_DOMAIN_NAMESPACE_LAST,
+ N_("sharenet"),
+ N_("shareipc"),
+ N_("shareuts"))
+
+static void
+lxcDomainDefNamespaceFree(void *nsdata)
+{
+ int j;
+ lxcDomainDefPtr lxcDef = nsdata;
+ for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
+ VIR_FREE(lxcDef->ns_type[j]);
+ VIR_FREE(lxcDef->ns_val[j]);
+ }
+ VIR_FREE(nsdata);
+}
+
+static int
+lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
+ xmlNodePtr root ATTRIBUTE_UNUSED,
+ xmlXPathContextPtr ctxt,
+ void **data)
+{
+ lxcDomainDefPtr lxcDef = NULL;
+ xmlNodePtr *nodes = NULL;
+ bool uses_lxc_ns = false;
+ xmlNodePtr node;
+ int feature;
+ int n;
+ char *tmp = NULL;
+ size_t i;
+
+ if (xmlXPathRegisterNs(ctxt, BAD_CAST "lxc", BAD_CAST LXC_NAMESPACE_HREF) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to register xml namespace '%s'"),
+ LXC_NAMESPACE_HREF);
+ return -1;
+ }
+
+ if (VIR_ALLOC(lxcDef) < 0)
+ return -1;
+ /* Init ns_herit_fd for namespaces */
+ for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+ lxcDef->ns_type[i] = NULL;
+ lxcDef->ns_val[i] = NULL;
+ }
+
+ node = ctxt->node;
+ if ((n = virXPathNodeSet("./lxc:namespace/*", ctxt, &nodes)) < 0)
+ goto error;
+ uses_lxc_ns |= n > 0;
+
+ for (i = 0; i < n; i++) {
+ feature =
+ virDomainNamespaceTypeFromString((const char *) nodes[i]->name);
+ if (feature < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unsupported Namespace feature: %s"),
+ nodes[i]->name);
+ goto error;
+ }
+
+ ctxt->node = nodes[i];
+
+ switch ((virDomainNamespace) feature) {
+ case VIR_DOMAIN_NAMESPACE_SHARENET:
+ case VIR_DOMAIN_NAMESPACE_SHAREIPC:
+ case VIR_DOMAIN_NAMESPACE_SHAREUTS:
+ {
+ tmp = virXMLPropString(nodes[i], "type");
+ if (tmp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No lxc environment type specified"));
+ goto error;
+ }
+ /* save the tmp so that its needed while writing to xml */
+ lxcDef->ns_type[feature] = tmp;
+ tmp = virXMLPropString(nodes[i], "value");
+ if (tmp == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("No lxc environment type specified"));
+ goto error;
+ }
+ lxcDef->ns_val[feature] = tmp;
+ }
+ break;
+ case VIR_DOMAIN_NAMESPACE_LAST:
+ break;
+ }
+ }
+ VIR_FREE(nodes);
+ ctxt->node = node;
+ if (uses_lxc_ns)
+ *data = lxcDef;
+ else
+ VIR_FREE(lxcDef);
+ return 0;
+ error:
+ VIR_FREE(nodes);
+ lxcDomainDefNamespaceFree(lxcDef);
+ return -1;
+}
+
+
+static int
+lxcDomainDefNamespaceFormatXML(virBufferPtr buf,
+ void *nsdata)
+{
+ lxcDomainDefPtr lxcDef = nsdata;
+ size_t j;
+
+ if (!lxcDef)
+ return 0;
+
+ virBufferAddLit(buf, "<lxc:namespace>\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
+ switch ((virDomainNamespace) j) {
+ case VIR_DOMAIN_NAMESPACE_SHAREIPC:
+ case VIR_DOMAIN_NAMESPACE_SHAREUTS:
+ case VIR_DOMAIN_NAMESPACE_SHARENET:
+ {
+ if (lxcDef->ns_type[j]) {
+ virBufferAsprintf(buf, "<lxc:%s type='%s' value='%s'/>\n",
+ virDomainNamespaceTypeToString(j),
+ lxcDef->ns_type[j],
+ lxcDef->ns_val[j]);
+ }
+ }
+ break;
+ case VIR_DOMAIN_NAMESPACE_LAST:
+ break;
+ }
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</lxc:namespace>\n");
+ return 0;
+}
+
+static const char *
+lxcDomainDefNamespaceHref(void)
+{
+ return "xmlns:lxc='" LXC_NAMESPACE_HREF "'";
+}
+
+
+virDomainXMLNamespace virLXCDriverDomainXMLNamespace = {
+ .parse = lxcDomainDefNamespaceParse,
+ .free = lxcDomainDefNamespaceFree,
+ .format = lxcDomainDefNamespaceFormatXML,
+ .href = lxcDomainDefNamespaceHref,
+};
+
+
static void virLXCDomainObjPrivateFree(void *data)
{
virLXCDomainObjPrivatePtr priv = data;
@@ -77,7 +240,6 @@ virLXCDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
} else {
priv->initpid = thepid;
}
-
return 0;
}
diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h
index 751aece..25df999 100644
--- a/src/lxc/lxc_domain.h
+++ b/src/lxc/lxc_domain.h
@@ -41,6 +41,7 @@ struct _virLXCDomainObjPrivate {
virCgroupPtr cgroup;
};
+extern virDomainXMLNamespace virLXCDriverDomainXMLNamespace;
extern virDomainXMLPrivateDataCallbacks virLXCDriverPrivateDataCallbacks;
extern virDomainDefParserConfig virLXCDriverDomainDefParserConfig;
diff --git a/tests/lxcxml2xmldata/lxc-sharenet.xml b/tests/lxcxml2xmldata/lxc-sharenet.xml
new file mode 100644
index 0000000..a2b8d1b
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-sharenet.xml
@@ -0,0 +1,33 @@
+<domain type='lxc' xmlns:lxc='http://libvirt.org/schemas/domain/lxc/1.0'>
+ <name>jessie</name>
+ <uuid>e21987a5-e98e-9c99-0e35-803e4d9ad1fe</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <resource>
+ <partition>/machine</partition>
+ </resource>
+ <os>
+ <type arch='x86_64'>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/libexec/libvirt_lxc</emulator>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/mach/jessie'/>
+ <target dir='/'/>
+ </filesystem>
+ <console type='pty'>
+ <target type='lxc' port='0'/>
+ </console>
+ </devices>
+ <lxc:namespace>
+ <lxc:sharenet type='netns' value='red'/>
+ <lxc:shareipc type='pid' value='12345'/>
+ <lxc:shareuts type='name' value='container1'/>
+ </lxc:namespace>
+</domain>
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index 3e00347..8d824b9 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -133,6 +133,7 @@ mymain(void)
DO_TEST("filesystem-root");
DO_TEST("idmap");
DO_TEST("capabilities");
+ DO_TEST("sharenet");
virObjectUnref(caps);
virObjectUnref(xmlopt);
--
1.9.1
9 years, 8 months
[libvirt] [PATCH 0/3] qemu: Return true pinning info
by Martin Kletzander
First two patches just prepare the ground for the third one that
explains what needs to be fixed and ho it's done.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1162947
Martin Kletzander (3):
conf: Pass private data to Parse function of XML options
qemu: Keep numad hint after reboot
qemu: Return true pining info when using numad
src/conf/domain_conf.c | 2 +-
src/conf/domain_conf.h | 17 +++++++++--------
src/libxl/libxl_domain.c | 3 ++-
src/lxc/lxc_domain.c | 3 ++-
src/qemu/qemu_domain.c | 33 ++++++++++++++++++++++++++++++++-
src/qemu/qemu_driver.c | 11 +++++++++++
6 files changed, 57 insertions(+), 12 deletions(-)
--
2.4.6
9 years, 8 months
[libvirt] unsupported configuration: unknown video model 'virtio' - virtio-vga
by poma
$ qemu-system-x86_64 ... -device virtio-vga
# lspci -d 1af4:1050 -knn
00:03.0 VGA compatible controller [0300]: Red Hat, Inc Device [1af4:1050] (rev 01)
Subsystem: Red Hat, Inc Device [1af4:1100]
Kernel driver in use: virtio-pci
Kernel modules: virtio_pci
# dmesg | grep virtio
[ 1.727390] [drm] pci: virtio-vga detected
[ 1.729315] [drm] virtio vbuffers: 80 bufs, 192B each, 15kB total.
[ 2.023845] virtio_gpu virtio0: fb0: virtiodrmfb frame buffer device
[ 2.023846] virtio_gpu virtio0: registered panic notifier
[ 2.043135] [drm] Initialized virtio_gpu 0.0.1 0 on minor 0
# journalctl -b -u libvirtd.service -o cat
Starting Virtualization daemon...
Started Virtualization daemon.
libvirt version: 1.2.17, package: 1.fc23 (Fedora Project, 2015-07-14-18:18:48, buildvm-03.phx2.fedoraproject.org)
unsupported configuration: unknown video model 'virtio'
Soonish?
9 years, 8 months
[libvirt] [PATCH] Allow vfio hotplug of a device to the domain which owns the iommu
by Shivaprasad G Bhat
The commit 7e72de4 didn't consider the hotplug scenarios. The patch addresses
the hotplug case whereby if atleast one of the pci function is owned by a
guest, the hotplug of other functions/devices in the same iommu group to the
same guest goes through successfully.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/util/virhostdev.c | 34 +++++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 809caed..529753c 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -54,23 +54,35 @@ static virClassPtr virHostdevManagerClass;
static void virHostdevManagerDispose(void *obj);
static virHostdevManagerPtr virHostdevManagerNew(void);
+struct virHostdevIsPCINodeDeviceUsedData {
+ virHostdevManagerPtr hostdev_mgr;
+ const char *domainName;
+ const bool usesVfio;
+};
+
static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *opaque)
{
virPCIDevicePtr other;
int ret = -1;
virPCIDevicePtr pci = NULL;
- virHostdevManagerPtr hostdev_mgr = opaque;
+ struct virHostdevIsPCINodeDeviceUsedData *helperData = opaque;
if (!(pci = virPCIDeviceNew(devAddr->domain, devAddr->bus,
devAddr->slot, devAddr->function)))
goto cleanup;
- other = virPCIDeviceListFind(hostdev_mgr->activePCIHostdevs, pci);
+ other = virPCIDeviceListFind(helperData->hostdev_mgr->activePCIHostdevs,
+ pci);
if (other) {
const char *other_drvname = NULL;
const char *other_domname = NULL;
virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname);
+ if (helperData->usesVfio &&
+ (other_domname && helperData->domainName) &&
+ (STREQ(other_domname, helperData->domainName)))
+ goto iommu_owner;
+
if (other_drvname && other_domname)
virReportError(VIR_ERR_OPERATION_INVALID,
_("PCI device %s is in use by "
@@ -83,6 +95,7 @@ static int virHostdevIsPCINodeDeviceUsed(virPCIDeviceAddressPtr devAddr, void *o
virPCIDeviceGetName(pci));
goto cleanup;
}
+ iommu_owner:
ret = 0;
cleanup:
virPCIDeviceFree(pci);
@@ -562,6 +575,9 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
bool strict_acs_check = !!(flags & VIR_HOSTDEV_STRICT_ACS_CHECK);
+ bool usesVfio = STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci");
+ struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, dom_name,
+ usesVfio};
if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) {
virReportError(VIR_ERR_OPERATION_INVALID,
@@ -579,12 +595,12 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr hostdev_mgr,
* belonging to same iommu group can't be shared
* across guests.
*/
- if (STREQ(virPCIDeviceGetStubDriver(dev), "vfio-pci")) {
+ if (usesVfio) {
if (virPCIDeviceAddressIOMMUGroupIterate(devAddr,
virHostdevIsPCINodeDeviceUsed,
- hostdev_mgr) < 0)
+ &data) < 0)
goto cleanup;
- } else if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr)) {
+ } else if (virHostdevIsPCINodeDeviceUsed(devAddr, &data)) {
goto cleanup;
}
}
@@ -1544,6 +1560,8 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
virPCIDevicePtr pci)
{
virPCIDeviceAddressPtr devAddr = NULL;
+ struct virHostdevIsPCINodeDeviceUsedData data = { hostdev_mgr, NULL,
+ false };
int ret = -1;
virObjectLock(hostdev_mgr->activePCIHostdevs);
@@ -1552,7 +1570,7 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
if (!(devAddr = virPCIDeviceGetAddress(pci)))
goto out;
- if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
+ if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
goto out;
if (virPCIDeviceDetach(pci, hostdev_mgr->activePCIHostdevs,
@@ -1573,6 +1591,8 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
virPCIDevicePtr pci)
{
virPCIDeviceAddressPtr devAddr = NULL;
+ struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, NULL,
+ false};
int ret = -1;
virObjectLock(hostdev_mgr->activePCIHostdevs);
@@ -1581,7 +1601,7 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
if (!(devAddr = virPCIDeviceGetAddress(pci)))
goto out;
- if (virHostdevIsPCINodeDeviceUsed(devAddr, hostdev_mgr))
+ if (virHostdevIsPCINodeDeviceUsed(devAddr, &data))
goto out;
virPCIDeviceReattachInit(pci);
9 years, 8 months
[libvirt] [PATCH] bootstrap: Don't require python-config
by Michal Privoznik
We've split the python bindings a long time ago. However,
we are still requiring python-config (as an obfuscation to
python-devel). This does not make any sense. The only thing
we need is python, not python-devel.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
bootstrap.conf | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/bootstrap.conf b/bootstrap.conf
index c06ee4c..783b3a3 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -196,10 +196,7 @@ local_gl_dir=gnulib/local
# Build prerequisites
# Note that some of these programs are only required for 'make dist' to
# succeed from a fresh git checkout; not all of these programs are
-# required to run 'make dist' on a tarball. As a special case, we want
-# to require the equivalent of the Fedora python-devel package, but
-# RHEL 5 lacks the witness python-config package; we hack around that
-# old environment below.
+# required to run 'make dist' on a tarball.
buildreq="\
autoconf 2.59
automake 1.9.6
@@ -212,19 +209,11 @@ patch -
perl 5.5
perl::XML::XPath -
pkg-config -
-python-config -
rpcgen -
tar -
xmllint -
xsltproc -
"
-# Use rpm as a fallback to bypass the bootstrap probe for python-config,
-# for the sake of RHEL 5; without requiring it on newer systems that
-# have python-config to begin with.
-if `(${PYTHON_CONFIG-python-config} --version;
- test $? -lt 126 || rpm -q python-devel) >/dev/null 2>&1`; then
- PYTHON_CONFIG=true
-fi
# Automake requires that ChangeLog and AUTHORS exist.
touch AUTHORS ChangeLog || exit 1
--
2.3.6
9 years, 8 months
[libvirt] [libvirt-php][PATCH v1] snapshot flags
by Vasiliy Tolstov
* add more snapshot flag constants
* add flags support to snapshot functions
Signed-off-by: Vasiliy Tolstov <v.tolstov(a)selfip.ru>
---
src/libvirt-php.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 49 insertions(+), 12 deletions(-)
diff --git a/src/libvirt-php.c b/src/libvirt-php.c
index d13e5b4..a2949f1 100644
--- a/src/libvirt-php.c
+++ b/src/libvirt-php.c
@@ -1240,6 +1240,31 @@ PHP_MINIT_FUNCTION(libvirt)
/* Domain snapshot constants */
REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_CHILDREN", VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_METADATA_ONLY", VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_DELETE_CHILDREN_ONLY", VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_REDEFINE", VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_CURRENT", VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_NO_METADATA", VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_HALT", VIR_DOMAIN_SNAPSHOT_CREATE_HALT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_DISK_ONLY", VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_REUSE_EXT", VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_QUIESCE", VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_ATOMIC", VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_CREATE_LIVE", VIR_DOMAIN_SNAPSHOT_CREATE_LIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_DESCENDANTS", VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_ROOTS", VIR_DOMAIN_SNAPSHOT_LIST_ROOTS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_METADATA", VIR_DOMAIN_SNAPSHOT_LIST_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_LEAVES", VIR_DOMAIN_SNAPSHOT_LIST_LEAVES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_NO_LEAVES", VIR_DOMAIN_SNAPSHOT_LIST_NO_LEAVES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_NO_METADATA", VIR_DOMAIN_SNAPSHOT_LIST_NO_METADATA, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_INACTIVE", VIR_DOMAIN_SNAPSHOT_LIST_INACTIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_ACTIVE", VIR_DOMAIN_SNAPSHOT_LIST_ACTIVE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_DISK_ONLY", VIR_DOMAIN_SNAPSHOT_LIST_DISK_ONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_INTERNAL", VIR_DOMAIN_SNAPSHOT_LIST_INTERNAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_LIST_EXTERNAL", VIR_DOMAIN_SNAPSHOT_LIST_EXTERNAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_RUNNING", VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_PAUSED", VIR_DOMAIN_SNAPSHOT_REVERT_PAUSED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("VIR_SNAPSHOT_REVERT_FORCE", VIR_DOMAIN_SNAPSHOT_REVERT_FORCE, CONST_CS | CONST_PERSISTENT);
/* Memory constants */
REGISTER_LONG_CONSTANT("VIR_MEMORY_VIRTUAL", 1, CONST_CS | CONST_PERSISTENT);
@@ -6568,6 +6593,7 @@ PHP_FUNCTION(libvirt_domain_get_job_info)
* Since version: 0.4.1(-2)
* Description: Function is used to get the information whether domain has the current snapshot
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: TRUE is domain has the current snapshot, otherwise FALSE (you may need to check for error using libvirt_get_last_error())
*/
PHP_FUNCTION(libvirt_domain_has_current_snapshot)
@@ -6575,10 +6601,11 @@ PHP_FUNCTION(libvirt_domain_has_current_snapshot)
php_libvirt_domain *domain=NULL;
zval *zdomain;
int retval;
+ long flags = 0;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- retval=virDomainHasCurrentSnapshot(domain->domain, 0);
+ retval=virDomainHasCurrentSnapshot(domain->domain, flags);
if (retval <= 0) RETURN_FALSE;
RETURN_TRUE;
}
@@ -6589,6 +6616,7 @@ PHP_FUNCTION(libvirt_domain_has_current_snapshot)
* Description: This functions is used to lookup for the snapshot by it's name
* Arguments: @res [resource]: libvirt domain resource
* @name [string]: name of the snapshot to get the resource
+ * @flags [int]: libvirt snapshot flags
* Returns: domain snapshot resource
*/
PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
@@ -6597,13 +6625,14 @@ PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
zval *zdomain;
int name_len;
char *name=NULL;
+ long flags = 0;
php_libvirt_snapshot *res_snapshot;
virDomainSnapshotPtr snapshot = NULL;
- GET_DOMAIN_FROM_ARGS("rs",&zdomain,&name,&name_len);
+ GET_DOMAIN_FROM_ARGS("rs|l",&zdomain,&name,&name_len,&flags);
if ( (name == NULL) || (name_len<1)) RETURN_FALSE;
- snapshot=virDomainSnapshotLookupByName(domain->domain, name, 0);
+ snapshot=virDomainSnapshotLookupByName(domain->domain, name, flags);
if (snapshot==NULL) RETURN_FALSE;
res_snapshot = (php_libvirt_snapshot *)emalloc(sizeof(php_libvirt_snapshot));
@@ -6620,6 +6649,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_lookup_by_name)
* Since version: 0.4.1(-2)
* Description: This function creates the domain snapshot for the domain identified by it's resource
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: domain snapshot resource
*/
PHP_FUNCTION(libvirt_domain_snapshot_create)
@@ -6628,10 +6658,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_create)
php_libvirt_snapshot *res_snapshot;
zval *zdomain;
virDomainSnapshotPtr snapshot = NULL;
+ long flags = 0;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- snapshot=virDomainSnapshotCreateXML(domain->domain, "<domainsnapshot/>", 0);
+ snapshot=virDomainSnapshotCreateXML(domain->domain, "<domainsnapshot/>", flags);
DPRINTF("%s: virDomainSnapshotCreateXML(%p, <xml>) returned %p\n", PHPFUNC, domain->domain, snapshot);
if (snapshot == NULL) RETURN_FALSE;
@@ -6649,6 +6680,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_create)
* Since version: 0.4.1(-2)
* Description: Function is used to get the XML description of the snapshot identified by it's resource
* Arguments: @res [resource]: libvirt snapshot resource
+ * @flags [int]: libvirt snapshot flags
* Returns: XML description string for the snapshot
*/
PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
@@ -6657,10 +6689,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
char *xml_out;
zval *zsnapshot;
php_libvirt_snapshot *snapshot;
+ long flags = 0;
- GET_SNAPSHOT_FROM_ARGS("r",&zsnapshot);
+ GET_SNAPSHOT_FROM_ARGS("r|l",&zsnapshot, &flags);
- xml = virDomainSnapshotGetXMLDesc(snapshot->snapshot, 0);
+ xml = virDomainSnapshotGetXMLDesc(snapshot->snapshot, flags);
if (xml==NULL) RETURN_FALSE;
RECREATE_STRING_WITH_E(xml_out,xml);
@@ -6673,6 +6706,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_get_xml)
* Since version: 0.4.1(-2)
* Description: Function is used to revert the domain state to the state identified by the snapshot
* Arguments: @res [resource]: libvirt snapshot resource
+ * @flags [int]: libvirt snapshot flags
* Returns: TRUE on success, FALSE on error
*/
PHP_FUNCTION(libvirt_domain_snapshot_revert)
@@ -6680,10 +6714,11 @@ PHP_FUNCTION(libvirt_domain_snapshot_revert)
zval *zsnapshot;
php_libvirt_snapshot *snapshot;
int ret;
+ long flags = 0;
- GET_SNAPSHOT_FROM_ARGS("r",&zsnapshot);
+ GET_SNAPSHOT_FROM_ARGS("r|l",&zsnapshot, &flags);
- ret = virDomainRevertToSnapshot(snapshot->snapshot, 0);
+ ret = virDomainRevertToSnapshot(snapshot->snapshot, flags);
DPRINTF("%s: virDomainRevertToSnapshot(%p, 0) returned %d\n", PHPFUNC, snapshot->snapshot, ret);
if (ret == -1) RETURN_FALSE;
RETURN_TRUE;
@@ -6717,6 +6752,7 @@ PHP_FUNCTION(libvirt_domain_snapshot_delete)
* Since version: 0.4.1(-2)
* Description: Function is used to list domain snapshots for the domain specified by it's resource
* Arguments: @res [resource]: libvirt domain resource
+ * @flags [int]: libvirt snapshot flags
* Returns: libvirt domain snapshot names array
*/
PHP_FUNCTION(libvirt_list_domain_snapshots)
@@ -6726,11 +6762,12 @@ PHP_FUNCTION(libvirt_list_domain_snapshots)
int count=-1;
int expectedcount=-1;
char **names;
+ long flags = 0;
int i;
- GET_DOMAIN_FROM_ARGS("r",&zdomain);
+ GET_DOMAIN_FROM_ARGS("r|l",&zdomain, &flags);
- expectedcount=virDomainSnapshotNum(domain->domain, 0);
+ expectedcount=virDomainSnapshotNum(domain->domain, flags);
DPRINTF("%s: virDomainSnapshotNum(%p, 0) returned %d\n", PHPFUNC, domain->domain, expectedcount);
if (expectedcount != -1 ) {
--
2.3.3
9 years, 8 months
[libvirt] tc ingress rule of VM B disappear when reboot VM A
by ychen
hi:
when I use openstack devstack to test QOS, wired phenomenon appeared,
I set qos ingress rule in tapB, but when I reboot tapA, the ingress rule of tapB automatically removed, but the egress rule is still exist.
Test enviroment:
Linux: ubuntu 14.04.1 LTS
kernel: 3.13.0-32-generic
libvirt: 1.2.2
openstack: havana
1. use nova to create vm A and vm B. for the configuration of the libvirt xml, see the last paragraph in the end.
2. use tc cmd to create qos rule for vm A and vm B
tc qdisc add dev tap3d0d2c4a-0b ingress //vmA
tc qdisc add dev tap896d5066-69 ingress //vmB
3. then use cmd
"sudo virsh destory 142a08db-6e25-4a03-be13-7073104b0745 " to first shutdown vm1
then I see ingress rule of vmB disappeared :(
configurations:
vmA:-------------------------------------------
<domain type='qemu' id='15'>
<name>instance-00000001</name>
<uuid>142a08db-6e25-4a03-be13-7073104b0745</uuid>
<memory unit='KiB'>524288</memory>
<currentMemory unit='KiB'>524288</currentMemory>
<vcpu placement='static'>1</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<sysinfo type='smbios'>
<system>
<entry name='manufacturer'>OpenStack Foundation</entry>
<entry name='product'>OpenStack Nova</entry>
<entry name='version'>2013.2.3</entry>
<entry name='serial'>5fd079ed-5bc3-45ed-8de5-8bf9b8533d82</entry>
<entry name='uuid'>142a08db-6e25-4a03-be13-7073104b0745</entry>
</system>
</sysinfo>
<os>
<type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type>
<boot dev='hd'/>
<smbios mode='sysinfo'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/opt/stack/data/nova/instances/142a08db-6e25-4a03-be13-7073104b0745/disk'/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</disk>
<controller type='usb' index='0'>
<alias name='usb0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<interface type='bridge'>
<mac address='fa:16:3e:22:68:6a'/>
<source bridge='br-int'/>
<virtualport type='openvswitch'>
<parameters interfaceid='3d0d2c4a-0b72-4f91-b393-413e0c5a335b'/>
</virtualport>
<target dev='tap3d0d2c4a-0b'/>
<model type='virtio'/>
<driver name='qemu'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='file'>
<source path='/opt/stack/data/nova/instances/142a08db-6e25-4a03-be13-7073104b0745/console.log'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<serial type='pty'>
<source path='/dev/pts/31'/>
<target port='1'/>
<alias name='serial1'/>
</serial>
<console type='file'>
<source path='/opt/stack/data/nova/instances/142a08db-6e25-4a03-be13-7073104b0745/console.log'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='tablet' bus='usb'>
<alias name='input0'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='apparmor' relabel='yes'>
<label>libvirt-142a08db-6e25-4a03-be13-7073104b0745</label>
<imagelabel>libvirt-142a08db-6e25-4a03-be13-7073104b0745</imagelabel>
</seclabel>
</domain>
vmB:-------------------------------------------
<domain type='qemu' id='13'>
<name>instance-00000002</name>
<uuid>fbd69f7b-83f1-45fe-818b-2021d5cb2e61</uuid>
<memory unit='KiB'>524288</memory>
<currentMemory unit='KiB'>524288</currentMemory>
<vcpu placement='static'>1</vcpu>
<resource>
<partition>/machine</partition>
</resource>
<sysinfo type='smbios'>
<system>
<entry name='manufacturer'>OpenStack Foundation</entry>
<entry name='product'>OpenStack Nova</entry>
<entry name='version'>2013.2.3</entry>
<entry name='serial'>5fd079ed-5bc3-45ed-8de5-8bf9b8533d82</entry>
<entry name='uuid'>fbd69f7b-83f1-45fe-818b-2021d5cb2e61</entry>
</system>
</sysinfo>
<os>
<type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type>
<boot dev='hd'/>
<smbios mode='sysinfo'/>
</os>
<features>
<acpi/>
<apic/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/opt/stack/data/nova/instances/fbd69f7b-83f1-45fe-818b-2021d5cb2e61/disk'/>
<target dev='vda' bus='virtio'/>
<alias name='virtio-disk0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</disk>
<controller type='usb' index='0'>
<alias name='usb0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'>
<alias name='pci.0'/>
</controller>
<interface type='bridge'>
<mac address='fa:16:3e:c0:43:88'/>
<source bridge='br-int'/>
<virtualport type='openvswitch'>
<parameters interfaceid='896d5066-694d-4f15-9abe-f587439f279b'/>
</virtualport>
<target dev='tap896d5066-69'/>
<model type='virtio'/>
<driver name='qemu'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='file'>
<source path='/opt/stack/data/nova/instances/fbd69f7b-83f1-45fe-818b-2021d5cb2e61/console.log'/>
<target port='0'/>
<alias name='serial0'/>
</serial>
<serial type='pty'>
<source path='/dev/pts/32'/>
<target port='1'/>
<alias name='serial1'/>
</serial>
<console type='file'>
<source path='/opt/stack/data/nova/instances/fbd69f7b-83f1-45fe-818b-2021d5cb2e61/console.log'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
</console>
<input type='tablet' bus='usb'>
<alias name='input0'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='5901' autoport='yes' listen='127.0.0.1' keymap='en-us'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<alias name='video0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<alias name='balloon0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</memballoon>
</devices>
<seclabel type='dynamic' model='apparmor' relabel='yes'>
<label>libvirt-fbd69f7b-83f1-45fe-818b-2021d5cb2e61</label>
<imagelabel>libvirt-fbd69f7b-83f1-45fe-818b-2021d5cb2e61</imagelabel>
</seclabel>
</domain>
9 years, 8 months
[libvirt] Libvirt error in Openstack Tempest attaching disk on arm64 system
by Clark Laughlin
I am running Openstack Tempest on an arm64 platform and am seeing some
test failures related to attaching volumes to an instance. This is an
example of the disk XML generated by one of the tests:
<disk type="block" device="disk"><driver name="qemu" type="raw"
cache="none"/<source
dev="/dev/disk/by-path/ip-10.7.1.2:3260-iscsi-iqn.2010-10.org.openstack:volume-5a204339-80cb-4d06-aecf-2a8a2c970b0e-lun-1"/><target
bus="virtio" dev="vdb"/><serial>5a204339-80cb-4d06-aecf-2a8a2c970b0e</serial></disk>
The test is failing with the error "XML error: No PCI buses
available". I am trying to find the relevent source locations for
this functionality in either in the nova libvirt driver or in the
libvirt source itself. I am not sure why I am getting an error about
no PCI buses when the bus specified in the XML is "virtio".
I would appreciate any pointers / help.
Thank you,
Clark L
9 years, 8 months
[libvirt] [PATCH] qemuProcessStart: Be tolerant to relabel errors for session mode
by Michal Privoznik
https://bugzilla.redhat.com/show_bug.cgi?id=1124841
When the daemon is running under unprivileged user, that is under
qemu:///session, there are plenty of operations we can't do. What
we can do is to go with best effort. One of such cases is
relabeling domain resources (be it disks, sockets, regular files,
etc.) during domain startup process. While we may successfully set
DAC labels, we can be fairly certain that any attempt to change
SELinux labels will fail. Therefore we should tolerate relabelling
errors and just let qemu to try access the resources. If it fails,
our error reporting system is strong enough to articulate the
exact error to the user anyway.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_process.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1c0c734..58ed631 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4856,8 +4856,13 @@ int qemuProcessStart(virConnectPtr conn,
VIR_DEBUG("Setting domain security labels");
if (virSecurityManagerSetAllLabel(driver->securityManager,
- vm->def, stdin_path) < 0)
- goto cleanup;
+ vm->def, stdin_path) < 0) {
+ /* Be tolerant to relabel errors if we are running unprivileged. */
+ if (virQEMUDriverIsPrivileged(driver))
+ goto cleanup;
+ else
+ VIR_DEBUG("Ignoring relabel errors for unprivileged daemon");
+ }
/* Security manager labeled all devices, therefore
* if any operation from now on fails and we goto cleanup,
--
2.3.6
9 years, 8 months