Add -netdev bridge support

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@linux.vnet.ibm.com>
Signed-off-by: Corey Bryant<coreyb@linux.vnet.ibm.com>
This commit is contained in:
Richa Marwaha 2012-08-03 16:33:06 -04:00 committed by Michal Privoznik
parent 756fe7868b
commit e060f86495
3 changed files with 65 additions and 25 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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;
}