direct-io.hg

view tools/python/xen/xend/XendPIF.py @ 13678:4651595d9502

Fix interface_name() after change of definition for the vlan field.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Sun Jan 28 15:55:55 2007 +0000 (2007-01-28)
parents 5e1c7022d4ad
children 7261e0d4b7df
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (c) 2006 Xensource Inc.
16 #============================================================================
18 import commands
19 import logging
20 import os
21 import re
24 log = logging.getLogger("xend.XendPIF")
25 log.setLevel(logging.TRACE)
28 MAC_RE = re.compile(':'.join(['[0-9a-f]{2}'] * 6))
29 IP_IFACE_RE = re.compile(r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)')
31 def linux_phy_to_virt(pif_name):
32 return 'eth' + re.sub(r'^[a-z]+', '', pif_name)
34 def linux_get_phy_ifaces():
35 """Returns a list of physical interfaces.
37 Identifies PIFs as those that have a interface name starting with 'p'
38 and have the fake 'fe:ff:ff:ff:ff:ff' MAC address.
40 See /etc/xen/scripts/network-bridge for how the devices are renamed.
42 @rtype: array of 3-element tuple (name, mtu, mac)
43 """
45 ip_cmd = 'ip -o link show'
46 rc, output = commands.getstatusoutput(ip_cmd)
47 ifaces = {}
48 phy_ifaces = []
49 if rc == 0:
50 # parse all interfaces into (name, mtu, mac)
51 for line in output.split('\n'):
52 has_if = re.search(IP_IFACE_RE, line)
53 if has_if:
54 ifaces[has_if.group(1)] = has_if.groups()
56 # resolve pifs' mac addresses
57 for name, mtu, mac in ifaces.values():
58 if name[0] == 'p' and mac == 'fe:ff:ff:ff:ff:ff':
59 bridged_ifname = linux_phy_to_virt(name)
60 bridged_if = ifaces.get(bridged_ifname)
61 if bridged_if:
62 bridged_mac = bridged_if[2]
63 phy_ifaces.append((name, int(mtu), bridged_mac))
65 return phy_ifaces
67 def linux_set_mac(iface, mac):
68 if not re.search(MAC_RE, mac):
69 return False
71 ip_mac_cmd = 'ip link set %s addr %s' % \
72 (linux_phy_to_virt(iface), mac)
73 rc, output = commands.getstatusoutput(ip_mac_cmd)
74 if rc == 0:
75 return True
77 return False
79 def linux_set_mtu(iface, mtu):
80 try:
81 ip_mtu_cmd = 'ip link set %s mtu %d' % \
82 (linux_phy_to_virt(iface), int(mtu))
83 rc, output = commands.getstatusoutput(ip_mtu_cmd)
84 if rc == 0:
85 return True
86 return False
87 except ValueError:
88 return False
90 class XendPIF:
91 """Representation of a Physical Network Interface."""
93 def __init__(self, uuid, device, mtu, vlan, mac, network, host):
94 self.uuid = uuid
95 self.device = device
96 self.mac = mac
97 self.mtu = mtu
98 self.vlan = vlan
99 self.network = network
100 self.host = host
102 def set_device(self, new_device):
103 self.device = new_device
105 def set_mac(self, new_mac):
106 success = linux_set_mac(new_mac)
107 if success:
108 self.mac = new_mac
109 return success
111 def set_mtu(self, new_mtu):
112 success = linux_set_mtu(new_mtu)
113 if success:
114 self.mtu = new_mtu
115 return success
117 def get_io_read_kbs(self):
118 from xen.xend.XendNode import instance as xennode
119 return xennode().get_pif_util(self.device)[0]
121 def get_io_write_kbs(self):
122 from xen.xend.XendNode import instance as xennode
123 return xennode().get_pif_util(self.device)[1]
125 def get_record(self, transient = True):
126 result = {'device': self.device,
127 'MAC': self.mac,
128 'MTU': self.mtu,
129 'VLAN': self.vlan,
130 'host': self.host.uuid,
131 'network': self.network.uuid}
132 if transient:
133 result['io_read_kbs'] = self.get_io_read_kbs()
134 result['io_write_kbs'] = self.get_io_write_kbs()
135 return result
138 def refresh(self, bridges):
139 ifname = self.interface_name()
140 rc, _ = _cmd('ip link show %s', ifname)
141 if rc != 0:
142 # Interface does not exist. If it's a physical interface, then
143 # there's nothing we can do -- this should have been set up with
144 # the network script. Otherwise, we can use vconfig to derive
145 # a subinterface.
146 if self.vlan == -1:
147 return
149 rc, _ = _cmd('vconfig add %s %d', self.device, self.vlan)
150 if rc != 0:
151 log.error('Could not refresh %s', ifname)
152 return
153 log.info('Created network interface %s', ifname)
155 for brname, nics in bridges.items():
156 if ifname in nics:
157 log.debug('%s is already attached to %s', ifname, brname)
158 return
160 # The interface is not attached to a bridge. Create one, and attach
161 # the interface to it.
162 brname = _new_bridge_name(bridges)
163 rc, _ = _cmd('brctl addbr %s', brname)
164 if rc != 0:
165 log.error('Could not create bridge %s for interface %s', brname,
166 ifname)
167 return
168 log.info('Created network bridge %s', brname)
170 rc, _ = _cmd('brctl addif %s %s', brname, ifname)
171 if rc != 0:
172 log.error('Could not add %s to %s', ifname, brname)
173 return
174 log.info('Added network interface %s to bridge %s', ifname, brname)
177 def interface_name(self):
178 if self.vlan != -1:
179 return '%s.%d' % (self.device, self.vlan)
180 else:
181 return self.device
184 def _cmd(cmd, *args):
185 if len(args) > 0:
186 cmd = cmd % args
187 rc, output = commands.getstatusoutput(cmd)
188 if rc != 0:
189 log.debug('%s failed with code %d' % (cmd, rc))
190 log.trace('%s: %s' % (cmd, output))
191 return rc, output
194 def _new_bridge_name(bridges):
195 n = 0
196 while True:
197 brname = 'xenbr%d' % n
198 if brname not in bridges:
199 return brname
200 n += 1