[libvirt] libvirt chowning my kernel/initrd files
by Seth Jennings
libvirt dev team,
I'm running libvirtd 0.9.8 and I notice than when I provide a kernel
path for my VM, libvirt chowns the kernel file I provide to root:root.
I see this was done in 0.7.1
http://libvirt.org/git/?p=libvirt.git;a=commit;h=c42b39784534930791d1feb3...
Why was this done? It seems to me that the kernel and initrd file
would be completely read-only from the qemu perspective, and qemu
would only need read access to the files.
For unprivileged users without sudo access, this chowning results in
kernel files that can not be removed or modified.
Thanks,
Seth
12 years, 6 months
[libvirt] [PATCH libvirt 1/2] domain: add <forward> element for user mode networking
by Marc-André Lureau
Add element <forward> to add TCP or UDP port redirection from host to
guest in user mode networking.
---
docs/formatdomain.html.in | 21 ++++
docs/schemas/domaincommon.rng | 29 +++++
src/conf/domain_conf.c | 140 ++++++++++++++++++++++
src/conf/domain_conf.h | 23 ++++
tests/qemuargv2xmltest.c | 3 +-
tests/qemuxml2argvdata/qemuxml2argv-net-user.xml | 2 +
6 files changed, 217 insertions(+), 1 deletion(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index d6e90f1..9c9bbf5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2268,6 +2268,27 @@
VMs to have outgoing access.
</p>
+ <p>
+ Port redirections from host to guest can be added by
+ providing <code>forward</code> elements that takes the
+ following attributes:
+ </p>
+
+ <dl>
+ <dt><code>type</code></dt>
+ <dd>Either <code>tcp</code> (default) or <code>udp</code>.</dd>
+
+ <dt><code>host_port</code></dt>
+ <dd>Host port to redirect.</dd>
+
+ <dt><code>guest_port</code></dt>
+ <dd>Guest port to redirect to.</dd>
+
+ <dt><code>host</code></dt>
+ <dd>IPv4 address to bound the redirection to a specific host
+ interface.</dd>
+ </dl>
+
<pre>
...
<devices>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 34f63c3..740f5af 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1408,6 +1408,35 @@
<value>user</value>
</attribute>
<interleave>
+ <zeroOrMore>
+ <element name="forward">
+ <attribute name="host_port">
+ <ref name="PortNumber"/>
+ </attribute>
+ <attribute name="guest_port">
+ <ref name="PortNumber"/>
+ </attribute>
+ <optional>
+ <attribute name="type">
+ <choice>
+ <value>tcp</value>
+ <value>udp</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="host">
+ <ref name="ipv4Addr"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="guest">
+ <ref name="ipv4Addr"/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </zeroOrMore>
<ref name="interface-options"/>
</interleave>
</group>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 51d6cb9..4b9b644 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -650,6 +650,10 @@ VIR_ENUM_IMPL(virDomainNumatuneMemPlacementMode,
"static",
"auto");
+VIR_ENUM_IMPL(virDomainNetForward, VIR_DOMAIN_NET_FORWARD_TYPE_LAST,
+ "tcp",
+ "udp")
+
#define virDomainReportError(code, ...) \
virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
@@ -1019,8 +1023,22 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
VIR_FREE(def);
}
+void
+virDomainNetForwardDefFree(virDomainNetForwardDefPtr def)
+{
+ if (!def)
+ return;
+
+ VIR_FREE(def->host_addr);
+ VIR_FREE(def->guest_addr);
+
+ VIR_FREE(def);
+}
+
void virDomainNetDefFree(virDomainNetDefPtr def)
{
+ int i;
+
if (!def)
return;
@@ -1066,6 +1084,11 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
break;
case VIR_DOMAIN_NET_TYPE_USER:
+ for (i = 0; i < def->data.user.nforward; i++)
+ virDomainNetForwardDefFree(def->data.user.forwards[i]);
+ VIR_FREE(def->data.user.forwards);
+ break;
+
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
@@ -4351,6 +4374,60 @@ error:
return ret;
}
+static virDomainNetForwardDefPtr
+virDomainNetForwardDefParseXML(const xmlNodePtr node)
+{
+ char *type = NULL;
+ char *host_port = NULL;
+ char *guest_port = NULL;
+ virDomainNetForwardDefPtr def;
+
+ if (VIR_ALLOC(def) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ type = virXMLPropString(node, "type");
+ if (type == NULL) {
+ def->type = VIR_DOMAIN_NET_FORWARD_TYPE_TCP;
+ } else if ((def->type = virDomainNetForwardTypeFromString(type)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown forward type '%s'"), type);
+ goto error;
+ }
+
+ host_port = virXMLPropString(node, "host_port");
+ if (!host_port ||
+ virStrToLong_i(host_port, NULL, 10, &def->host_port) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <forward> 'host_port' attribute"));
+ goto error;
+ }
+
+ guest_port = virXMLPropString(node, "guest_port");
+ if (!guest_port ||
+ virStrToLong_i(guest_port, NULL, 10, &def->guest_port) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Cannot parse <forward> 'guest_port' attribute"));
+ goto error;
+ }
+
+ def->host_addr = virXMLPropString(node, "host");
+ def->guest_addr = virXMLPropString(node, "guest");
+
+cleanup:
+ VIR_FREE(type);
+ VIR_FREE(host_port);
+ VIR_FREE(guest_port);
+
+ return def;
+
+error:
+ virDomainNetForwardDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
#define NET_MODEL_CHARS \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ091234567890_-"
@@ -4394,6 +4471,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
int ret;
+ int nforwards;
+ xmlNodePtr *forwardNodes = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -4683,6 +4762,28 @@ virDomainNetDefParseXML(virCapsPtr caps,
break;
case VIR_DOMAIN_NET_TYPE_USER:
+ /* parse the <forward> elements */
+ nforwards = virXPathNodeSet("./forward", ctxt, &forwardNodes);
+ if (nforwards < 0)
+ goto error;
+
+ if (nforwards > 0) {
+ int i;
+ if (VIR_ALLOC_N(def->data.user.forwards, nforwards) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ for (i = 0; i < nforwards; i++) {
+ virDomainNetForwardDefPtr fwd =
+ virDomainNetForwardDefParseXML(forwardNodes[i]);
+ if (fwd == NULL)
+ goto error;
+ def->data.user.forwards[def->data.user.nforward++] = fwd;
+ }
+ VIR_FREE(forwardNodes);
+ }
+ break;
+
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
@@ -11413,11 +11514,42 @@ error:
}
static int
+virDomainNetForwardDefFormat(virBufferPtr buf,
+ virDomainNetForwardDefPtr def)
+{
+ const char *type;
+ if (!def)
+ return 0;
+
+ type = virDomainNetForwardTypeToString(def->type);
+ if (!type) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected net type %d"), def->type);
+ return -1;
+ }
+ virBufferAsprintf(buf, "<forward type='%s'", type);
+
+ if (def->host_addr)
+ virBufferAsprintf(buf, " host='%s'", def->host_addr);
+
+ virBufferAsprintf(buf, " host_port='%d'", def->host_port);
+
+ if (def->guest_addr)
+ virBufferAsprintf(buf, " guest='%s'", def->guest_addr);
+
+ virBufferAsprintf(buf, " guest_port='%d'", def->guest_port);
+
+ virBufferAddLit(buf, "/>\n");
+ return 0;
+}
+
+static int
virDomainNetDefFormat(virBufferPtr buf,
virDomainNetDefPtr def,
unsigned int flags)
{
const char *type = virDomainNetTypeToString(def->type);
+ int i;
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -11517,6 +11649,14 @@ virDomainNetDefFormat(virBufferPtr buf,
break;
case VIR_DOMAIN_NET_TYPE_USER:
+ virBufferAdjustIndent(buf, 6);
+ for (i = 0; i < def->data.user.nforward; i++) {
+ if (virDomainNetForwardDefFormat(buf, def->data.user.forwards[i]) < 0)
+ return -1;
+ }
+ virBufferAdjustIndent(buf, -6);
+ break;
+
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 70129fe..7fde05e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -768,6 +768,23 @@ struct _virDomainActualNetDef {
virNetDevBandwidthPtr bandwidth;
};
+enum virDomainNetForwardType {
+ VIR_DOMAIN_NET_FORWARD_TYPE_TCP,
+ VIR_DOMAIN_NET_FORWARD_TYPE_UDP,
+
+ VIR_DOMAIN_NET_FORWARD_TYPE_LAST,
+};
+
+typedef struct _virDomainNetForwardDef virDomainNetForwardDef;
+typedef virDomainNetForwardDef *virDomainNetForwardDefPtr;
+struct _virDomainNetForwardDef {
+ int type; /* enum virDomainNetForwardType */
+ char *host_addr;
+ int host_port;
+ char *guest_addr;
+ int guest_port;
+};
+
/* Stores the virtual network interface configuration */
struct _virDomainNetDef {
enum virDomainNetType type;
@@ -821,6 +838,10 @@ struct _virDomainNetDef {
virDomainHostdevDef def;
virNetDevVPortProfilePtr virtPortProfile;
} hostdev;
+ struct {
+ int nforward;
+ virDomainNetForwardDefPtr *forwards;
+ } user;
} data;
struct {
bool sndbuf_specified;
@@ -1856,6 +1877,7 @@ int virDomainDiskFindControllerModel(virDomainDefPtr def,
void virDomainControllerDefFree(virDomainControllerDefPtr def);
void virDomainFSDefFree(virDomainFSDefPtr def);
void virDomainActualNetDefFree(virDomainActualNetDefPtr def);
+void virDomainNetForwardDefFree(virDomainNetForwardDefPtr def);
void virDomainNetDefFree(virDomainNetDefPtr def);
void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def);
void virDomainChrDefFree(virDomainChrDefPtr def);
@@ -2170,6 +2192,7 @@ VIR_ENUM_DECL(virDomainFSAccessMode)
VIR_ENUM_DECL(virDomainFSWrpolicy)
VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainNetBackend)
+VIR_ENUM_DECL(virDomainNetForward)
VIR_ENUM_DECL(virDomainNetVirtioTxMode)
VIR_ENUM_DECL(virDomainNetInterfaceLinkState)
VIR_ENUM_DECL(virDomainChrDevice)
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 439218e..cf2862b 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -207,7 +207,8 @@ mymain(void)
DO_TEST("misc-acpi");
DO_TEST("misc-no-reboot");
DO_TEST("misc-uuid");
- DO_TEST("net-user");
+ /* Fixed in following commit */
+ /* DO_TEST("net-user"); */
DO_TEST("net-virtio");
DO_TEST("net-eth");
DO_TEST("net-eth-ifname");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml
index 37e5edf..ecefdeb 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml
@@ -23,6 +23,8 @@
<controller type='ide' index='0'/>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
+ <forward type='tcp' host_port='2222' guest_port='22'/>
+ <forward type='udp' host='127.0.0.1' host_port='2242' guest='10.0.2.15' guest_port='42'/>
</interface>
<memballoon model='virtio'/>
</devices>
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH] nodeinfo: test more details
by Eric Blake
Make it obvious why we need Osier's patch to fix NUMA parsing
of an AMD machine with two cores sharing a socket id.
* tests/nodeinfotest.c (linuxTestCompareFiles): Enhance the test.
* tests/nodeinfodata/linux-nodeinfo-sysfs-test-*-output.txt: Update.
---
As promised here:
https://www.redhat.com/archives/libvir-list/2012-May/msg00759.html
(Hmm, I still need to add results from a machine with an offline cpu)
I can push this either before or after Osier's patch here:
https://www.redhat.com/archives/libvir-list/2012-May/msg00736.html
whoever pushes second needs a minor rebase; should be obvious
what the changes will be, since 48 online out of 24 max is clearly
wrong...
.../linux-nodeinfo-sysfs-test-1-cpu-ppc-output.txt | 2 +-
.../linux-nodeinfo-sysfs-test-1-cpu-x86-output.txt | 2 +-
.../linux-nodeinfo-sysfs-test-2-cpu-x86-output.txt | 2 +-
.../linux-nodeinfo-sysfs-test-3-cpu-x86-output.txt | 2 +-
tests/nodeinfotest.c | 9 ++++++---
5 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-ppc-output.txt b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-ppc-output.txt
index 433a81f..80df832 100644
--- a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-ppc-output.txt
+++ b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-ppc-output.txt
@@ -1 +1 @@
-CPUs: 2, MHz: 8, Nodes: 1, Cores: 2
+CPUs: 2/2, MHz: 8, Nodes: 1, Sockets: 1, Cores: 2, Threads: 1
diff --git a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-x86-output.txt b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-x86-output.txt
index 09e2946..4c86824 100644
--- a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-x86-output.txt
+++ b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-1-cpu-x86-output.txt
@@ -1 +1 @@
-CPUs: 2, MHz: 2800, Nodes: 1, Cores: 2
+CPUs: 2/2, MHz: 2800, Nodes: 1, Sockets: 1, Cores: 2, Threads: 1
diff --git a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-2-cpu-x86-output.txt b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-2-cpu-x86-output.txt
index 73300a4..33bfbf3 100644
--- a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-2-cpu-x86-output.txt
+++ b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-2-cpu-x86-output.txt
@@ -1 +1 @@
-CPUs: 2, MHz: 800, Nodes: 1, Cores: 2
+CPUs: 2/2, MHz: 800, Nodes: 1, Sockets: 1, Cores: 2, Threads: 1
diff --git a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-3-cpu-x86-output.txt b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-3-cpu-x86-output.txt
index e3c046b..ed5d6bd 100644
--- a/tests/nodeinfodata/linux-nodeinfo-sysfs-test-3-cpu-x86-output.txt
+++ b/tests/nodeinfodata/linux-nodeinfo-sysfs-test-3-cpu-x86-output.txt
@@ -1 +1 @@
-CPUs: 48, MHz: 2100, Nodes: 1, Cores: 6
+CPUs: 48/24, MHz: 2100, Nodes: 1, Sockets: 4, Cores: 6, Threads: 1
diff --git a/tests/nodeinfotest.c b/tests/nodeinfotest.c
index 2b4c3a0..a2b89dd 100644
--- a/tests/nodeinfotest.c
+++ b/tests/nodeinfotest.c
@@ -60,9 +60,12 @@ linuxTestCompareFiles(const char *cpuinfofile,
}
VIR_FORCE_FCLOSE(cpuinfo);
- if (virAsprintf(&actualData, "CPUs: %u, MHz: %u, Nodes: %u, Cores: %u\n",
- nodeinfo.cpus, nodeinfo.mhz, nodeinfo.nodes,
- nodeinfo.cores) < 0)
+ if (virAsprintf(&actualData,
+ "CPUs: %u/%u, MHz: %u, Nodes: %u, Sockets: %u, "
+ "Cores: %u, Threads: %u\n",
+ nodeinfo.cpus, VIR_NODEINFO_MAXCPUS(nodeinfo),
+ nodeinfo.mhz, nodeinfo.nodes, nodeinfo.sockets,
+ nodeinfo.cores, nodeinfo.threads) < 0)
goto fail;
if (STRNEQ(actualData, expectData)) {
--
1.7.7.6
12 years, 6 months
[libvirt] [PATCH] build: fix recent syntax-check breakage
by Eric Blake
The use of readlink() in lxc_container.c is intentional; we don't
want an absolute pathname there.
* src/util/cgroup.h (VIR_CGROUP_SYSFS_MOUNT): Indent properly.
* cfg.mk (exclude_file_name_regexp--sc_prohibit_readlink): Add
exemption.
---
Pushing under the build-breaker rule.
cfg.mk | 3 ++-
src/util/cgroup.h | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/cfg.mk b/cfg.mk
index 7f81933..07fb7b2 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -800,7 +800,8 @@ exclude_file_name_regexp--sc_prohibit_nonreentrant = \
exclude_file_name_regexp--sc_prohibit_raw_allocation = \
^(src/util/memory\.[ch]|examples/.*)$$
-exclude_file_name_regexp--sc_prohibit_readlink = ^src/util/util\.c$$
+exclude_file_name_regexp--sc_prohibit_readlink = \
+ ^(src/(util/util|lxc/lxc_container)\.c$$
exclude_file_name_regexp--sc_prohibit_setuid = ^src/util/util\.c$$
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 857945d..05325ae 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -16,7 +16,7 @@
struct virCgroup;
typedef struct virCgroup *virCgroupPtr;
-#define VIR_CGROUP_SYSFS_MOUNT "/sys/fs/cgroup"
+# define VIR_CGROUP_SYSFS_MOUNT "/sys/fs/cgroup"
enum {
VIR_CGROUP_CONTROLLER_CPU,
--
1.7.7.6
12 years, 6 months
[libvirt] F17's libvirt takes comments into LIBVIRTD_ARGS
by Dan Kenigsberg
On Tue, May 15, 2012 at 04:16:11PM +0800, Shu Ming wrote:
> On 2012-5-14 7:30, Dan Kenigsberg wrote:
> >On Sun, May 13, 2012 at 11:51:48PM +0800, Shu Ming wrote:
> >>Hi,
> >> Recently, I found that my host in engine was always in a
> >>"unassigned state" after the host node was installed. After looking
> >>into the vdsm.log, it seemed that vdsm failed to call libvirt as an
> >>error, "libvirtError: Cannot write data: Broken pipe". When I
> >>started virsh in the host node at that time, a warning was given
> >>"WARNING: no socket to connect to" and core dumped with "virsh
> >>net-list". It looks like that no right socket was created for
> >>virsh to connect to libvirtd. Any comments about this problem? The
> >>followings are my steps in the node:
> >>
> >>[root@ovirt-node1 ~]# rpm -qa |grep vdsm
> >>vdsm-cli-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-python-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-hook-vhostmd-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-4.9.6-0.183.git107644d.fc16.shuming1336622293.x86_64
> >>vdsm-reg-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-debug-plugin-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-hook-faqemu-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>vdsm-bootstrap-4.9.6-0.183.git107644d.fc16.shuming1336622293.noarch
> >>[root@ovirt-node1 ~]#
> >>[root@ovirt-node1 ~]# ps -ef |grep libvirt
> >>
> >>libvirt-daemon-0.9.11-1.fc17.x86_64
> >>libvirt-daemon-config-nwfilter-0.9.11-1.fc17.x86_64
> >>libvirt-client-0.9.11-1.fc17.x86_64
> >>libvirt-daemon-config-network-0.9.11-1.fc17.x86_64
> >>libvirt-python-0.9.11-1.fc17.x86_64
> >>
> >>[root@ovirt-node1 ~]# virsh net-list
> >>WARNING: no socket to connect to
> >>Segmentation fault
> >I think that merits a libvirt bug. please attach strace output to
> >bugzilla.
> >
> >>[root@ovirt-node1 ~]#
> >>
> >>
> >>[root@ovirt-node1 ~]# ps -ef |grep vdsm
> >>root 1299 1 0 23:10 ? 00:00:00 /usr/sbin/libvirtd
> >>--listen # by vdsm
> >The command line of libvirt process is very odd - the comment that vdsm
> >puts into /etc/sysconfig/libvirtd is somehow taken verbatim. That's bad,
> >and may be related to Fedora 17's systemd services. Try to remove the
> >comment and restart libvirtd to see if this is the case.
> The comment come from
>
> [root@ovirt-node1 ~]# cat /etc/sysconfig/libvirtd:
I know that (see my text above). However, in F16 and before, comments have been stripped
before being passed to commandline. Have you tested if all is well when
the commment is removed?
Let's see what our friends in libvir-list think.
Dan.
12 years, 6 months
[libvirt] [PATCH] qemu: Rollback on used USB devices
by Michal Privoznik
One of our latest USB device handling patches
05abd1507d66aabb6cad12eeafeb4c4d1911c585 introduced a regression.
That is, we first create a temporary list of all USB devices that
are to be used by domain just starting up. Then we iterate over and
check if a device from the list is in the global list of currently
assigned devices (activeUsbHostdevs). If not, we add it there and
continue with next iteration then. But if a device from temporary
list is either taken already or adding to the activeUsbHostdevs fails,
we remove all devices in temp list from the activeUsbHostdevs list.
Therefore, if a device is already taken we remove it from
activeUsbHostdevs even if we should not. Thus, next time we allow
the device to be assigned to another domain.
---
src/qemu/qemu_hostdev.c | 28 ++++++++++++----------------
1 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index b649ae0..ff13305 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -567,7 +567,7 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
const char *name,
usbDeviceList *list)
{
- int i;
+ int i, j;
unsigned int count;
usbDevice *tmp;
@@ -586,7 +586,7 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
qemuReportError(VIR_ERR_OPERATION_INVALID,
_("USB device %s is already in use"),
usbDeviceGetName(tmp));
- return -1;
+ goto error;
}
usbDeviceSetUsedBy(usb, name);
@@ -598,9 +598,16 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
* perform rollback on failure.
*/
if (usbDeviceListAdd(driver->activeUsbHostdevs, usb) < 0)
- return -1;
+ goto error;
}
return 0;
+
+error:
+ for (j = 0; j < i; j++) {
+ tmp = usbDeviceListGet(list, i);
+ usbDeviceListSteal(driver->activeUsbHostdevs, tmp);
+ }
+ return -1;
}
static int
@@ -621,8 +628,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
if (!(list = usbDeviceListNew()))
goto cleanup;
- /* Loop 1: build temporary list and validate no usb device
- * is already taken
+ /* Loop 1: build temporary list
*/
for (i = 0 ; i < nhostdevs ; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
@@ -678,7 +684,7 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
* wrong, perform rollback.
*/
if (qemuPrepareHostdevUSBDevices(driver, def->name, list) < 0)
- goto inactivedevs;
+ goto cleanup;
/* Loop 2: Temporary list was successfully merged with
* driver list, so steal all items to avoid freeing them
@@ -690,16 +696,6 @@ qemuPrepareHostUSBDevices(struct qemud_driver *driver,
}
ret = 0;
- goto cleanup;
-
-inactivedevs:
- /* Steal devices from driver->activeUsbHostdevs.
- * We will free them later.
- */
- for (i = 0; i < usbDeviceListCount(list); i++) {
- tmp = usbDeviceListGet(list, i);
- usbDeviceListSteal(driver->activeUsbHostdevs, tmp);
- }
cleanup:
usbDeviceListFree(list);
--
1.7.8.5
12 years, 6 months
[libvirt] [PATCH] Fix build compat with older libselinux for LXC
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Most versions of libselinux do not contain the function
selinux_lxc_contexts_path() that the security driver
recently started using for LXC. We must add a conditional
check for it in configure and then disable the LXC security
driver for builds where libselinux lacks this function.
NB although this qualifies as a build breaker fix, I'm
not pushing until it has had review
* configure.ac: Check for selinux_lxc_contexts_path
* src/security/security_selinux.c: Disable LXC security
if selinux_lxc_contexts_path() is missing
---
configure.ac | 1 +
src/security/security_selinux.c | 19 ++++++++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 9c356c9..d666736 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1360,6 +1360,7 @@ else
fail=0
AC_CHECK_FUNC([selinux_virtual_domain_context_path], [], [fail=1])
AC_CHECK_FUNC([selinux_virtual_image_context_path], [], [fail=1])
+ AC_CHECK_FUNCS([selinux_lxc_contexts_path])
CFLAGS="$old_cflags"
LIBS="$old_libs"
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index b0bb0a0..2b8ff19 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -127,6 +127,7 @@ err:
}
+#ifdef HAVE_SELINUX_LXC_CONTEXTS_PATH
static int
SELinuxLXCInitialize(virSecurityManagerPtr mgr)
{
@@ -189,6 +190,15 @@ error:
VIR_FREE(data->content_context);
return -1;
}
+#else
+static int
+SELinuxLXCInitialize(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("libselinux does not support LXC contexts path"));
+ return -1;
+}
+#endif
static int
@@ -443,9 +453,12 @@ SELinuxSecurityDriverProbe(const char *virtDriver)
if (!is_selinux_enabled())
return SECURITY_DRIVER_DISABLE;
- if (virtDriver && STREQ(virtDriver, "LXC") &&
- !virFileExists(selinux_lxc_contexts_path()))
- return SECURITY_DRIVER_DISABLE;
+ if (virtDriver && STREQ(virtDriver, "LXC")) {
+#if HAVE_SELINUX_LXC_CONTEXTS_PATH
+ if (!virFileExists(selinux_lxc_contexts_path()))
+#endif
+ return SECURITY_DRIVER_DISABLE;
+ }
return SECURITY_DRIVER_ENABLE;
}
--
1.7.7.6
12 years, 6 months
[libvirt] [PATCH libvirt] Reject any non-option command line arguments
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Due to a bug in editing /etc/sysconfig/libvirtd, VDSM was causing
libvirt processes to run with the following command line args
/usr/sbin/libvirtd --listen '#' 'by vdsm'
While it correctly rejects any invalid option flags, libvirtd
was not rejecting any non-option command line arguments
* daemon/libvirtd.c: Reject non-option argv
---
daemon/libvirtd.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 2696c54..0b5ae35 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -999,6 +999,12 @@ int main(int argc, char **argv) {
}
}
+ if (optind != argc) {
+ fprintf(stderr, "%s: unexpected, non-option, command line arguments\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
if (!(config = daemonConfigNew(privileged))) {
VIR_ERROR(_("Can't create initial configuration"));
exit(EXIT_FAILURE);
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH v4 0/3] usb devices with same vendorID, productID hotplug support
by Guannan Ren
v4 updates:
make each patch not break build
make usbDeviceSearch flags filtering code simpler
https://bugzilla.redhat.com/show_bug.cgi?id=815755
The set of patch tries to fix the issue when multiple usb devices with
same idVendor, idProduct are availible on host, the usb device with
lowest bus:device will be attached to guest if usb xml file is given like
this:
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<vendor id='0x15e1'/>
<product id='0x2007'/>
</source>
</hostdev>
The reason is that the usb hotplug function searchs usb device in system files
to match vendor and product id, the file with lowest number is always found
first.
After fix, in this case, libvirt will report an error like:
# virsh attach-device rhel6u1 /tmp/usb.xml
error: Failed to attach device from /tmp/usb.xml
error: operation failed: multiple USB devices for 15e1:2007, use <address> to specify one
At the same time, the usb part of domain initilization is also updated in patch 2/3
These patches also fix the problem when using the following xml, the usb device
could be hotplugged in two domains without raising errors
<hostdev mode='subsystem' type='usb' managed='yes'>
<source>
<address bus='6' device='7'/>
</source>
</hostdev>
# virsh attach-device rhel6u12nd /tmp/usb_by_bus.xml
error: Failed to attach device from /tmp/usb_by_bus.xml
error: Requested operation is not valid: USB device 006:007 is in use by domain rhel6u1
12 years, 6 months
[libvirt] [PATCH v2] Remount cgroups controllers after setting up new /sys in LXC
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Normal practice is for cgroups controllers to be mounted at
/sys/fs/cgroup. When setting up a container, /sys is mounted
with a new sysfs instance, thus we must re-mount all the
cgroups controllers. The complexity is that we must mount
them in the same layout as the host OS. ie if 'cpu' and 'cpuacct'
were mounted at the same location in the host we must preserve
this in the container. Also if any controllers are co-located
we must setup symlinks from the individual controller name to
the co-located mount-point
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/lxc/lxc_container.c | 243 +++++++++++++++++++++++++++++++++++++++++++++--
src/util/cgroup.h | 2 +
2 files changed, 236 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index a3ca76c..e606108 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <mntent.h>
+#include <dirent.h>
/* Yes, we want linux private one, for _syscall2() macro */
#include <linux/unistd.h>
@@ -1122,6 +1123,192 @@ cleanup:
}
+struct lxcContainerCGroup {
+ const char *dir;
+ const char *linkDest;
+};
+
+
+static void lxcContainerCGroupFree(struct lxcContainerCGroup *mounts,
+ size_t nmounts)
+{
+ size_t i;
+
+ if (!mounts)
+ return;
+
+ for (i = 0 ; i < nmounts ; i++) {
+ VIR_FREE(mounts[i].dir);
+ VIR_FREE(mounts[i].linkDest);
+ }
+ VIR_FREE(mounts);
+}
+
+
+static int lxcContainerIdentifyCGroups(struct lxcContainerCGroup **mountsret,
+ size_t *nmountsret)
+{
+ FILE *procmnt = NULL;
+ struct mntent mntent;
+ struct dirent *dent;
+ char mntbuf[1024];
+ int ret = -1;
+ struct lxcContainerCGroup *mounts = NULL;
+ size_t nmounts = 0;
+ DIR *dh = NULL;
+ char *path = NULL;
+
+ *mountsret = NULL;
+ *nmountsret = 0;
+
+ VIR_DEBUG("Finding cgroups mount points under %s", VIR_CGROUP_SYSFS_MOUNT);
+
+ if (!(procmnt = setmntent("/proc/mounts", "r"))) {
+ virReportSystemError(errno, "%s",
+ _("Failed to read /proc/mounts"));
+ return -1;
+ }
+
+ while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
+ VIR_DEBUG("Got %s", mntent.mnt_dir);
+ if (STRNEQ(mntent.mnt_type, "cgroup") ||
+ !STRPREFIX(mntent.mnt_dir, VIR_CGROUP_SYSFS_MOUNT))
+ continue;
+
+ /* Skip named mounts with no controller since they're
+ * for application use only ie systemd */
+ if (strstr(mntent.mnt_opts, "name="))
+ continue;
+
+ if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (!(mounts[nmounts-1].dir = strdup(mntent.mnt_dir))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
+ }
+
+ VIR_DEBUG("Checking for symlinks in %s", VIR_CGROUP_SYSFS_MOUNT);
+ if (!(dh = opendir(VIR_CGROUP_SYSFS_MOUNT))) {
+ virReportSystemError(errno,
+ _("Unable to read directory %s"),
+ VIR_CGROUP_SYSFS_MOUNT);
+ goto cleanup;
+ }
+
+ while ((dent = readdir(dh)) != NULL) {
+ ssize_t rv;
+ /* The cgroups links are just relative to the local
+ * dir so we don't need a large buf */
+ char linkbuf[100];
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ VIR_DEBUG("Checking entry %s", dent->d_name);
+ if (virAsprintf(&path, "%s/%s", VIR_CGROUP_SYSFS_MOUNT, dent->d_name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if ((rv = readlink(path, linkbuf, sizeof(linkbuf)-1)) < 0) {
+ if (errno != EINVAL) {
+ virReportSystemError(errno,
+ _("Unable to resolve link %s"),
+ path);
+ VIR_FREE(path);
+ goto cleanup;
+ }
+ /* Ok not a link */
+ VIR_FREE(path);
+ } else {
+ linkbuf[rv] = '\0';
+ VIR_DEBUG("Got a link %s to %s", path, linkbuf);
+ if (VIR_EXPAND_N(mounts, nmounts, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (!(mounts[nmounts-1].linkDest = strdup(linkbuf))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ mounts[nmounts-1].dir = path;
+ path = NULL;
+ }
+ }
+
+ *mountsret = mounts;
+ *nmountsret = nmounts;
+ ret = 0;
+
+cleanup:
+ closedir(dh);
+ endmntent(procmnt);
+ VIR_FREE(path);
+
+ if (ret < 0)
+ lxcContainerCGroupFree(mounts, nmounts);
+ return ret;
+}
+
+
+static int lxcContainerMountCGroups(struct lxcContainerCGroup *mounts,
+ size_t nmounts)
+{
+ size_t i;
+
+ VIR_DEBUG("Mounting cgroups at '%s'", VIR_CGROUP_SYSFS_MOUNT);
+
+ if (virFileMakePath(VIR_CGROUP_SYSFS_MOUNT) < 0) {
+ virReportSystemError(errno,
+ _("Unable to create directory %s"),
+ VIR_CGROUP_SYSFS_MOUNT);
+ return -1;
+ }
+
+ if (mount("tmpfs", VIR_CGROUP_SYSFS_MOUNT, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, "mode=755") < 0) {
+ virReportSystemError(errno,
+ _("Failed to mount %s on %s type %s"),
+ "tmpfs", VIR_CGROUP_SYSFS_MOUNT, "tmpfs");
+ return -1;
+ }
+
+ for (i = 0 ; i < nmounts ; i++) {
+ if (mounts[i].linkDest) {
+ VIR_DEBUG("Link mount point '%s' to '%s'",
+ mounts[i].dir, mounts[i].linkDest);
+ if (symlink(mounts[i].linkDest, mounts[i].dir) < 0) {
+ virReportSystemError(errno,
+ _("Unable to symlink directory %s to %s"),
+ mounts[i].dir, mounts[i].linkDest);
+ return -1;
+ }
+ } else {
+ VIR_DEBUG("Create mount point '%s'", mounts[i].dir);
+ if (virFileMakePath(mounts[i].dir) < 0) {
+ virReportSystemError(errno,
+ _("Unable to create directory %s"),
+ mounts[i].dir);
+ return -1;
+ }
+
+ if (mount("cgroup", mounts[i].dir, "cgroup",
+ 0, mounts[i].dir + strlen(VIR_CGROUP_SYSFS_MOUNT) + 1) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mount %s on %s"),
+ "cgroup", mounts[i].dir);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
/* Got a FS mapped to /, we're going the pivot_root
* approach to do a better-chroot-than-chroot
* this is based on this thread http://lkml.org/lkml/2008/3/5/29
@@ -1132,31 +1319,49 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
size_t nttyPaths,
virSecurityManagerPtr securityDriver)
{
+ struct lxcContainerCGroup *mounts = NULL;
+ size_t nmounts = 0;
+ int ret = -1;
+
+ /* Before pivoting we need to identify any
+ * cgroups controllers that are mounted */
+ if (lxcContainerIdentifyCGroups(&mounts, &nmounts) < 0)
+ goto cleanup;
+
/* Gives us a private root, leaving all parent OS mounts on /.oldroot */
if (lxcContainerPivotRoot(root) < 0)
- return -1;
+ goto cleanup;
/* Mounts the core /proc, /sys, etc filesystems */
if (lxcContainerMountBasicFS(vmDef, true, securityDriver) < 0)
- return -1;
+ goto cleanup;
+
+ /* Now we can re-mount the cgroups controllers in the
+ * same configuration as before */
+ if (lxcContainerMountCGroups(mounts, nmounts) < 0)
+ goto cleanup;
/* Mounts /dev/pts */
if (lxcContainerMountFSDevPTS(root) < 0)
- return -1;
+ goto cleanup;
/* Populates device nodes in /dev/ */
if (lxcContainerPopulateDevices(ttyPaths, nttyPaths) < 0)
- return -1;
+ goto cleanup;
/* Sets up any non-root mounts from guest config */
if (lxcContainerMountAllFS(vmDef, "/.oldroot", true) < 0)
- return -1;
+ goto cleanup;
/* Gets rid of all remaining mounts from host OS, including /.oldroot itself */
if (lxcContainerUnmountSubtree("/.oldroot", true) < 0)
- return -1;
+ goto cleanup;
- return 0;
+ ret = 0;
+
+cleanup:
+ lxcContainerCGroupFree(mounts, nmounts);
+ return ret;
}
@@ -1166,6 +1371,10 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
virDomainFSDefPtr root,
virSecurityManagerPtr securityDriver)
{
+ int ret = -1;
+ struct lxcContainerCGroup *mounts = NULL;
+ size_t nmounts = 0;
+
VIR_DEBUG("def=%p", vmDef);
/*
* This makes sure that any new filesystems in the
@@ -1190,19 +1399,35 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
if (lxcContainerMountAllFS(vmDef, "", false) < 0)
return -1;
+ /* Before replacing /sys we need to identify any
+ * cgroups controllers that are mounted */
+ if (lxcContainerIdentifyCGroups(&mounts, &nmounts) < 0)
+ goto cleanup;
+
/* Gets rid of any existing stuff under /proc, since we need new
* namespace aware versions of those. We must do /proc second
* otherwise we won't find /proc/mounts :-) */
if (lxcContainerUnmountSubtree("/sys", false) < 0 ||
lxcContainerUnmountSubtree("/proc", false) < 0)
- return -1;
+ goto cleanup;
/* Mounts the core /proc, /sys, etc filesystems */
if (lxcContainerMountBasicFS(vmDef, false, securityDriver) < 0)
- return -1;
+ goto cleanup;
+
+ /* Now we can re-mount the cgroups controllers in the
+ * same configuration as before */
+ if (lxcContainerMountCGroups(mounts, nmounts) < 0)
+ goto cleanup;
VIR_DEBUG("Mounting completed");
return 0;
+
+ ret = 0;
+
+cleanup:
+ lxcContainerCGroupFree(mounts, nmounts);
+ return ret;
}
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 8486c42..857945d 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -16,6 +16,8 @@
struct virCgroup;
typedef struct virCgroup *virCgroupPtr;
+#define VIR_CGROUP_SYSFS_MOUNT "/sys/fs/cgroup"
+
enum {
VIR_CGROUP_CONTROLLER_CPU,
VIR_CGROUP_CONTROLLER_CPUACCT,
--
1.7.10.1
12 years, 6 months