[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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 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, 3 months
[libvirt] mass create vm errors
by Vasiliy Tolstov
Hi again =). I have another problem then testing libvirt with massive vm start:
2015-07-18 08:25:21.687+0000: 36893: error : qemuMonitorIO:750 :
internal error: early end of file from monitor: possible problem:
2015-07-18T08:25:21.586487Z qemu-system-x86_64: -vnc [::]:4,password:
Failed to start VNC server: Failed to bind socket: Address already in
use
As i understand, when libvirt try to detect free port for vnc it
fails, because another process already binds to it. How can i avoid
this errors? Does it fixed in never libvirt releases?
libvirt 1.216
qemu 2.4.0-rc0
--
Vasiliy Tolstov,
e-mail: v.tolstov(a)selfip.ru
9 years, 3 months