From: Richa Marwaha <rmarwah(a)linux.vnet.ibm.com>
This patch adds the support to run the QEMU network helper
under unprivileged user. It also adds the support for
attach-interface option in virsh to run under unprivileged
user.
Signed-off-by: Richa Marwaha <rmarwah(a)linux.vnet.ibm.com>
Signed-off-by: Corey Bryant<coreyb(a)linux.vnet.ibm.com>
---
src/qemu/qemu_command.c | 57 ++++++++++++++++++++++++++++++++++------------
src/qemu/qemu_command.h | 2 +
src/qemu/qemu_hotplug.c | 31 +++++++++++++++++--------
3 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6ad65a6..83b3d30 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2964,6 +2964,8 @@ error:
char *
qemuBuildHostNetStr(virDomainNetDefPtr net,
+ struct qemud_driver *driver,
+ virBitmapPtr qemuCaps,
char type_sep,
int vlan,
const char *tapfd,
@@ -2972,6 +2974,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
bool is_tap = false;
virBuffer buf = VIR_BUFFER_INITIALIZER;
enum virDomainNetType netType = virDomainNetGetActualType(net);
+ const char *brname = NULL;
if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -2981,8 +2984,21 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
}
switch (netType) {
- case VIR_DOMAIN_NET_TYPE_NETWORK:
+ /*
+ * If type='bridge', and we're running as privileged user
+ * or -netdev bridge is not supported then it will fall
+ * through, -net tap,fd
+ */
case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ if (!driver->privileged &&
+ qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV_BRIDGE)) {
+ brname = virDomainNetGetActualBridgeName(net);
+ virBufferAsprintf(&buf, "bridge%cbr=%s", type_sep, brname);
+ type_sep = ',';
+ is_tap = true;
+ break;
+ }
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_DIRECT:
virBufferAsprintf(&buf, "tap%cfd=%s", type_sep, tapfd);
type_sep = ',';
@@ -5125,7 +5141,7 @@ qemuBuildCommandLine(virConnectPtr conn,
for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
char *nic, *host;
- char tapfd_name[50];
+ char tapfd_name[50] = "";
char vhostfd_name[50] = "";
int vlan;
int bootindex = bootNet;
@@ -5162,17 +5178,26 @@ qemuBuildCommandLine(virConnectPtr conn,
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
- int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net,
- qemuCaps);
- if (tapfd < 0)
- goto error;
+ /*
+ * If type='bridge' then we attempt to allocate the tap fd here
only if
+ * running under a privilged user or -netdev bridge option is not
+ * supported.
+ */
+ if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ driver->privileged ||
+ (!qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV_BRIDGE))) {
+ int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net,
+ qemuCaps);
+ if (tapfd < 0)
+ goto error;
- last_good_net = i;
- virCommandTransferFD(cmd, tapfd);
+ last_good_net = i;
+ virCommandTransferFD(cmd, tapfd);
- if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
- tapfd) >= sizeof(tapfd_name))
- goto no_memory;
+ if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+ tapfd) >= sizeof(tapfd_name))
+ goto no_memory;
+ }
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
int tapfd = qemuPhysIfaceConnect(def, driver, net,
qemuCaps, vmop);
@@ -5215,8 +5240,9 @@ qemuBuildCommandLine(virConnectPtr conn,
if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
virCommandAddArg(cmd, "-netdev");
- if (!(host = qemuBuildHostNetStr(net, ',', vlan,
- tapfd_name, vhostfd_name)))
+ if (!(host = qemuBuildHostNetStr(net, driver, qemuCaps,
+ ',', vlan, tapfd_name,
+ vhostfd_name)))
goto error;
virCommandAddArg(cmd, host);
VIR_FREE(host);
@@ -5238,8 +5264,9 @@ qemuBuildCommandLine(virConnectPtr conn,
if (!(qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE))) {
virCommandAddArg(cmd, "-net");
- if (!(host = qemuBuildHostNetStr(net, ',', vlan,
- tapfd_name, vhostfd_name)))
+ if (!(host = qemuBuildHostNetStr(net, driver, qemuCaps,
+ ',', vlan, tapfd_name,
+ vhostfd_name)))
goto error;
virCommandAddArg(cmd, host);
VIR_FREE(host);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 3ccf4d7..946a7ac 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -62,6 +62,8 @@ qemuBuildChrDeviceStr (virDomainChrDefPtr serial,
/* With vlan == -1, use netdev syntax, else old hostnet */
char * qemuBuildHostNetStr(virDomainNetDefPtr net,
+ struct qemud_driver *driver,
+ virBitmapPtr qemuCaps,
char type_sep,
int vlan,
const char *tapfd,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 71ec484..e128e58 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -695,12 +695,21 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
- if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
- priv->qemuCaps)) < 0)
- goto cleanup;
- iface_connected = true;
- if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
- goto cleanup;
+ /*
+ * If type=bridge then we attempt to allocate the tap fd here only if
+ * running under a privilged user or -netdev bridge option is not
+ * supported.
+ */
+ if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ driver->privileged ||
+ (!qemuCapsGet (priv->qemuCaps, QEMU_CAPS_NETDEV_BRIDGE))) {
+ if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
+ priv->qemuCaps)) < 0)
+ goto cleanup;
+ iface_connected = true;
+ if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) <
0)
+ goto cleanup;
+ }
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net,
priv->qemuCaps,
@@ -748,12 +757,14 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
- if (!(netstr = qemuBuildHostNetStr(net, ',',
- -1, tapfd_name, vhostfd_name)))
+ if (!(netstr = qemuBuildHostNetStr(net, driver, priv->qemuCaps,
+ ',', -1, tapfd_name,
+ vhostfd_name)))
goto cleanup;
} else {
- if (!(netstr = qemuBuildHostNetStr(net, ' ',
- vlan, tapfd_name, vhostfd_name)))
+ if (!(netstr = qemuBuildHostNetStr(net, driver, priv->qemuCaps,
+ ' ', vlan, tapfd_name,
+ vhostfd_name)))
goto cleanup;
}
--
1.7.1