summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlmr <lmr@592f7852-d20e-0410-864c-8624ca9c26a4>2011-06-06 17:25:05 +0000
committerlmr <lmr@592f7852-d20e-0410-864c-8624ca9c26a4>2011-06-06 17:25:05 +0000
commit08561d8add2611675ffd7fe978186052197ce0b4 (patch)
tree67e8adee77c396162796c24660b01c839d8bd069
parent2f4eb28c3f95fefc15bdcceda389d3b5bf114bd3 (diff)
KVM test: setup tap fd and pass it to qemu-kvm v3
We used to use qemu-ifup to manage the tap which have several limitations: 1) If we want to specify a bridge, we must create a customized qemu-ifup file as the default script always match the first bridge. 2) It's hard to add support for macvtap device. So this patch let kvm subtest control the tap creation and setup then pass it to qemu-kvm. User could specify the bridge he want to used in configuration file. The original autoconfiguration was changed by private bridge setup. Changes from v1: * Combine the private bridge config and TAP fd in one patchset, dropped the "auto" mode Changes from v2: * Close TAP fds on VM.destroy() (thanks to Amos Kong for finding the problem, and for Cleber and Jason for actually fixing it). Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com> git-svn-id: svn://test.kernel.org/autotest/trunk@5402 592f7852-d20e-0410-864c-8624ca9c26a4
-rwxr-xr-xclient/tests/kvm/scripts/qemu-ifup11
-rwxr-xr-xclient/tests/kvm/scripts/qemu-ifup-ipv611
-rw-r--r--client/virt/kvm_vm.py63
-rw-r--r--client/virt/virt_utils.py9
4 files changed, 50 insertions, 44 deletions
diff --git a/client/tests/kvm/scripts/qemu-ifup b/client/tests/kvm/scripts/qemu-ifup
deleted file mode 100755
index c4debf58..00000000
--- a/client/tests/kvm/scripts/qemu-ifup
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# The following expression selects the first bridge listed by 'brctl show'.
-# Modify it to suit your needs.
-switch=$(/usr/sbin/brctl show | awk 'NR==2 { print $1 }')
-
-/bin/echo 1 > /proc/sys/net/ipv6/conf/${switch}/disable_ipv6
-/sbin/ifconfig $1 0.0.0.0 up
-/usr/sbin/brctl addif ${switch} $1
-/usr/sbin/brctl setfd ${switch} 0
-/usr/sbin/brctl stp ${switch} off
diff --git a/client/tests/kvm/scripts/qemu-ifup-ipv6 b/client/tests/kvm/scripts/qemu-ifup-ipv6
deleted file mode 100755
index d4b05929..00000000
--- a/client/tests/kvm/scripts/qemu-ifup-ipv6
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-# The following expression selects the first bridge listed by 'brctl show'.
-# Modify it to suit your needs.
-switch=$(/usr/sbin/brctl show | awk 'NR==2 { print $1 }')
-
-/bin/echo 0 > /proc/sys/net/ipv6/conf/${switch}/disable_ipv6
-/sbin/ifconfig $1 0.0.0.0 up
-/usr/sbin/brctl addif ${switch} $1
-/usr/sbin/brctl setfd ${switch} 0
-/usr/sbin/brctl stp ${switch} off
diff --git a/client/virt/kvm_vm.py b/client/virt/kvm_vm.py
index 343488f9..21300f97 100644
--- a/client/virt/kvm_vm.py
+++ b/client/virt/kvm_vm.py
@@ -7,7 +7,7 @@ Utility classes and functions to handle Virtual Machine creation using qemu.
import time, os, logging, fcntl, re, commands, glob
from autotest_lib.client.common_lib import error
from autotest_lib.client.bin import utils
-import virt_utils, virt_vm, kvm_monitor, aexpect
+import virt_utils, virt_vm, virt_test_setup, kvm_monitor, aexpect
class VM(virt_vm.BaseVM):
@@ -41,6 +41,7 @@ class VM(virt_vm.BaseVM):
self.pci_assignable = None
self.netdev_id = []
self.device_id = []
+ self.tapfds = []
self.uuid = None
@@ -240,19 +241,17 @@ class VM(virt_vm.BaseVM):
cmd += ",id='%s'" % device_id
return cmd
- def add_net(help, vlan, mode, ifname=None, script=None,
- downscript=None, tftp=None, bootfile=None, hostfwd=[],
- netdev_id=None, netdev_extra_params=None):
+ def add_net(help, vlan, mode, ifname=None, tftp=None, bootfile=None,
+ hostfwd=[], netdev_id=None, netdev_extra_params=None,
+ tapfd=None):
if has_option(help, "netdev"):
cmd = " -netdev %s,id=%s" % (mode, netdev_id)
if netdev_extra_params:
cmd += ",%s" % netdev_extra_params
else:
cmd = " -net %s,vlan=%d" % (mode, vlan)
- if mode == "tap":
- if ifname: cmd += ",ifname='%s'" % ifname
- if script: cmd += ",script='%s'" % script
- cmd += ",downscript='%s'" % (downscript or "no")
+ if mode == "tap" and tapfd:
+ cmd += ",fd=%d" % tapfd
elif mode == "user":
if tftp and "[,tftp=" in help:
cmd += ",tftp='%s'" % tftp
@@ -422,20 +421,22 @@ class VM(virt_vm.BaseVM):
qemu_cmd += add_nic(help, vlan, nic_params.get("nic_model"), mac,
device_id, netdev_id, nic_params.get("nic_extra_params"))
# Handle the '-net tap' or '-net user' or '-netdev' part
- script = nic_params.get("nic_script")
- downscript = nic_params.get("nic_downscript")
tftp = nic_params.get("tftp")
- if script:
- script = virt_utils.get_path(root_dir, script)
- if downscript:
- downscript = virt_utils.get_path(root_dir, downscript)
if tftp:
tftp = virt_utils.get_path(root_dir, tftp)
- qemu_cmd += add_net(help, vlan, nic_params.get("nic_mode", "user"),
- vm.get_ifname(vlan),
- script, downscript, tftp,
+ if nic_params.get("nic_mode") == "tap":
+ try:
+ tapfd = vm.tapfds[vlan]
+ except:
+ tapfd = None
+ else:
+ tapfd = None
+ qemu_cmd += add_net(help, vlan,
+ nic_params.get("nic_mode", "user"),
+ vm.get_ifname(vlan), tftp,
nic_params.get("bootp"), redirs, netdev_id,
- nic_params.get("netdev_extra_params"))
+ nic_params.get("netdev_extra_params"),
+ tapfd)
# Proceed to next NIC
vlan += 1
@@ -558,6 +559,10 @@ class VM(virt_vm.BaseVM):
@raise VMBadPATypeError: If an unsupported PCI assignment type is
requested
@raise VMPAError: If no PCI assignable devices could be assigned
+ @raise TAPCreationError: If fail to create tap fd
+ @raise BRAddIfError: If fail to add a tap to a bridge
+ @raise TAPBringUpError: If fail to bring up a tap
+ @raise PrivateBridgeError: If fail to bring the private bridge
"""
error.context("creating '%s'" % self.name)
self.destroy(free_mac_addresses=False)
@@ -621,12 +626,24 @@ class VM(virt_vm.BaseVM):
guest_port = int(redir_params.get("guest_port"))
self.redirs[guest_port] = host_ports[i]
- # Generate netdev/device IDs for all NICs
+ # Generate netdev IDs for all NICs and create TAP fd
self.netdev_id = []
- self.device_id = []
+ self.tapfds = []
+ vlan = 0
for nic in params.objects("nics"):
self.netdev_id.append(virt_utils.generate_random_id())
self.device_id.append(virt_utils.generate_random_id())
+ nic_params = params.object_params(nic)
+ if nic_params.get("nic_mode") == "tap":
+ ifname = self.get_ifname(vlan)
+ brname = nic_params.get("bridge")
+ if brname == "private":
+ brname = virt_test_setup.PrivateBridgeConfig().brname
+ tapfd = virt_utils.open_tap("/dev/net/tun", ifname)
+ virt_utils.add_to_bridge(ifname, brname)
+ virt_utils.bring_up_ifname(ifname)
+ self.tapfds.append(tapfd)
+ vlan += 1
# Find available VNC port, if needed
if params.get("display") == "vnc":
@@ -710,6 +727,12 @@ class VM(virt_vm.BaseVM):
logging.info("Running qemu command:\n%s", qemu_command)
self.process = aexpect.run_bg(qemu_command, None,
logging.info, "(qemu) ")
+ for tapfd in self.tapfds:
+ try:
+ os.close(tapfd)
+ # File descriptor is already closed
+ except OSError:
+ pass
# Make sure the process was started successfully
if not self.process.is_alive():
diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py
index 0700509a..e3d912a6 100644
--- a/client/virt/virt_utils.py
+++ b/client/virt/virt_utils.py
@@ -56,12 +56,17 @@ class NetError(Exception):
class TAPModuleError(NetError):
- def __init__(self, devname):
+ def __init__(self, devname, action="open", details=None):
NetError.__init__(self, devname)
self.devname = devname
+ self.details = details
def __str__(self):
- return "Can't open %s" % self.devname
+ e_msg = "Can't %s %s" % (self.action, self.devname)
+ if self.details is not None:
+ e_msg += " : %s" % self.details
+ return e_msg
+
class TAPNotExistError(NetError):
def __init__(self, ifname):