Revision 199b2053 lib/hypervisor/hv_kvm.py
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
31 | 31 |
import time |
32 | 32 |
import logging |
33 | 33 |
import pwd |
34 |
import struct |
|
35 |
import fcntl |
|
34 | 36 |
from cStringIO import StringIO |
35 | 37 |
|
36 | 38 |
from ganeti import utils |
... | ... | |
46 | 48 |
|
47 | 49 |
_KVM_NETWORK_SCRIPT = constants.SYSCONFDIR + "/ganeti/kvm-vif-bridge" |
48 | 50 |
|
51 |
# TUN/TAP driver constants, taken from <linux/if_tun.h> |
|
52 |
# They are architecture-independent and already hardcoded in qemu-kvm source, |
|
53 |
# so we can safely include them here. |
|
54 |
TUNSETIFF = 0x400454ca |
|
55 |
TUNGETIFF = 0x800454d2 |
|
56 |
TUNGETFEATURES = 0x800454cf |
|
57 |
IFF_TAP = 0x0002 |
|
58 |
IFF_NO_PI = 0x1000 |
|
59 |
IFF_VNET_HDR = 0x4000 |
|
60 |
|
|
61 |
|
|
62 |
def _ProbeTapVnetHdr(fd): |
|
63 |
"""Check whether to enable the IFF_VNET_HDR flag. |
|
64 |
|
|
65 |
To do this, _all_ of the following conditions must be met: |
|
66 |
1. TUNGETFEATURES ioctl() *must* be implemented |
|
67 |
2. TUNGETFEATURES ioctl() result *must* contain the IFF_VNET_HDR flag |
|
68 |
3. TUNGETIFF ioctl() *must* be implemented; reading the kernel code in |
|
69 |
drivers/net/tun.c there is no way to test this until after the tap device |
|
70 |
has been created using TUNSETIFF, and there is no way to change the |
|
71 |
IFF_VNET_HDR flag after creating the interface, catch-22! However both |
|
72 |
TUNGETIFF and TUNGETFEATURES were introduced in kernel version 2.6.27, |
|
73 |
thus we can expect TUNGETIFF to be present if TUNGETFEATURES is. |
|
74 |
|
|
75 |
@type fd: int |
|
76 |
@param fd: the file descriptor of /dev/net/tun |
|
77 |
|
|
78 |
""" |
|
79 |
req = struct.pack("I", 0) |
|
80 |
try: |
|
81 |
res = fcntl.ioctl(fd, TUNGETFEATURES, req) |
|
82 |
except EnvironmentError: |
|
83 |
logging.warning("TUNGETFEATURES ioctl() not implemented") |
|
84 |
return False |
|
85 |
|
|
86 |
tunflags = struct.unpack("I", res)[0] |
|
87 |
if tunflags & IFF_VNET_HDR: |
|
88 |
return True |
|
89 |
else: |
|
90 |
logging.warning("Host does not support IFF_VNET_HDR, not enabling") |
|
91 |
return False |
|
92 |
|
|
93 |
|
|
94 |
def _OpenTap(vnet_hdr=True): |
|
95 |
"""Open a new tap device and return its file descriptor. |
|
96 |
|
|
97 |
This is intended to be used by a qemu-type hypervisor together with the -net |
|
98 |
tap,fd=<fd> command line parameter. |
|
99 |
|
|
100 |
@type vnet_hdr: boolean |
|
101 |
@param vnet_hdr: Enable the VNET Header |
|
102 |
@return: (ifname, tapfd) |
|
103 |
@rtype: tuple |
|
104 |
|
|
105 |
""" |
|
106 |
try: |
|
107 |
tapfd = os.open("/dev/net/tun", os.O_RDWR) |
|
108 |
except EnvironmentError: |
|
109 |
raise errors.HypervisorError("Failed to open /dev/net/tun") |
|
110 |
|
|
111 |
flags = IFF_TAP | IFF_NO_PI |
|
112 |
|
|
113 |
if vnet_hdr and _ProbeTapVnetHdr(tapfd): |
|
114 |
flags |= IFF_VNET_HDR |
|
115 |
|
|
116 |
# The struct ifreq ioctl request (see netdevice(7)) |
|
117 |
ifr = struct.pack("16sh", "", flags) |
|
118 |
|
|
119 |
try: |
|
120 |
res = fcntl.ioctl(tapfd, TUNSETIFF, ifr) |
|
121 |
except EnvironmentError: |
|
122 |
raise errors.HypervisorError("Failed to allocate a new TAP device") |
|
123 |
|
|
124 |
# Get the interface name from the ioctl |
|
125 |
ifname = struct.unpack("16sh", res)[0].strip("\x00") |
|
126 |
return (ifname, tapfd) |
|
127 |
|
|
49 | 128 |
|
50 | 129 |
def _WriteNetScript(instance, nic, index): |
51 | 130 |
"""Write a script to connect a net interface to the proper bridge. |
Also available in: Unified diff