ia64/xen-unstable

view tools/xm-test/lib/XmTestLib/NetConfig.py @ 19281:6c7ae9c859f5

xm-test: Identifying the network env specified in xend config fails,
if an additional parameter is given for the network-bridge
(e.g. netdev=eth1) The patch splits the network command into the
command name and its parameters to determine the netenv (bridge,
route, nat)

Signed-off-by: juergen.gross@fujitsu-siemens.com
author Keir Fraser <keir.fraser@citrix.com>
date Fri Mar 06 18:56:28 2009 +0000 (2009-03-06)
parents 33dcf04d7715
children
line source
1 #!/usr/bin/python
2 """
3 Copyright (C) International Business Machines Corp., 2005, 2006
4 Authors: Dan Smith <danms@us.ibm.com>
5 Daniel Stekloff <dsteklof@us.ibm.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; under version 2 of the License.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 """
22 import sys
23 import commands
24 import os
25 import re
26 import time
27 import random
28 from xen.xend.sxp import Parser
30 from Xm import *
31 from Test import *
32 from config import *
34 class NetworkError(Exception):
35 def __init__(self, msg):
36 self.errMsg = msg
38 def __str__(self):
39 return str(self.errMsg)
41 def getXendNetConfig():
42 # Find out what environment we're in: bridge, nat, or route
43 xconfig = os.getenv("XEND_CONFIG")
44 if not xconfig:
45 xconfig = "/etc/xen/xend-config.sxp"
47 try:
48 configfile = open(xconfig, 'r')
49 except:
50 return "bridge"
52 S = configfile.read()
53 pin = Parser()
54 pin.input(S)
55 pin.input_eof()
56 val = pin.get_val()
57 while val[0] != 'network-script':
58 val = pin.get_val()
60 # split network command into script name and its parameters
61 sub_val = val[1].split()
62 if sub_val[0] == "network-bridge":
63 netenv = "bridge"
64 elif sub_val[0] == "network-route":
65 netenv = "route"
66 elif sub_val[0] == "network-nat":
67 netenv = "nat"
68 else:
69 raise NetworkError("Failed to get network env from xend config")
71 configfile.close()
72 return netenv
74 class NetConfig:
76 def __init__(self):
77 self.netenv = getXendNetConfig()
78 self.used_ips = {}
79 self.free_oct_ips = [ 0, 0, 0, 0 ]
80 self.total_ips = 0
82 if NETWORK_IP_RANGE == 'dhcp':
83 self.netmask = NETWORK_IP_RANGE
84 self.network = NETWORK_IP_RANGE
85 self.max_ip = NETWORK_IP_RANGE
86 self.min_ip = NETWORK_IP_RANGE
87 else:
88 self.netmask = NETMASK
89 self.network = NETWORK
90 s_ip = ''
92 # Get starting ip and max ip from configured ip range
93 s_ip = NETWORK_IP_RANGE
94 ips = s_ip.split("-")
95 self.max_ip = ips[1]
96 self.min_ip = ips[0]
98 self.__setMaxNumberIPs()
100 # Clean out any aliases in the network range for dom0's interface.
101 # If an alias exists, a test xendevice add command could fail.
102 if NETWORK_IP_RANGE != "dhcp":
103 self.__cleanDom0Aliases()
105 def __setMaxNumberIPs(self):
106 # Count the number of IPs available, to help tests know whether they
107 # have enough to run or not
108 masko = self.netmask.split('.')
109 maxo = self.max_ip.split('.')
110 mino = self.min_ip.split('.')
111 ips = 0
113 # Last octet
114 self.free_oct_ips[3] = (int(maxo[3]) - int(mino[3])) + 1
116 # 3rd octet
117 self.free_oct_ips[2] = (int(maxo[2]) - int(mino[2])) + 1
119 # 2nd octet
120 self.free_oct_ips[1] = (int(maxo[1]) - int(mino[1])) + 1
122 # 1st octet
123 self.free_oct_ips[0] = (int(maxo[0]) - int(mino[0])) + 1
125 self.total_ips = self.free_oct_ips[3]
126 if self.free_oct_ips[2] > 1:
127 self.total_ips = (self.total_ips * self.free_oct_ips[2])
128 if self.free_oct_ips[1] > 1:
129 self.total_ips = (self.total_ips * self.free_oct_ips[1])
130 if self.free_oct_ips[0] > 1:
131 self.total_ips = (self.total_ips * self.free_oct_ips[0])
133 def __cleanDom0Aliases(self):
134 # Remove any aliases within the supplied network IP range on dom0
135 scmd = 'ip addr show dev %s' % (DOM0_INTF)
137 status, output = traceCommand(scmd)
138 if status:
139 raise NetworkError("Failed to show %s aliases: %d" %
140 (DOM0_INTF, status))
142 lines = output.split("\n")
143 for line in lines:
144 ip = re.search('(\d+\.\d+\.\d+\.\d+)', line)
145 if ip and self.isIPInRange(ip.group(1)) == True:
146 dcmd = 'ip addr del %s dev %s' % (ip.group(1), DOM0_INTF)
147 dstatus, doutput = traceCommand(dcmd)
148 if dstatus:
149 raise NetworkError("Failed to remove %s aliases: %d" %
150 (DOM0_INTF, status))
152 def getNetEnv(self):
153 return self.netenv
155 def setUsedIP(self, domname, interface, ip):
156 self.used_ips['%s:%s' % (domname, interface)] = ip
158 def __findFirstOctetIP(self, prefix, min, max):
159 for i in range(min, max):
160 ip = '%s%s' % (prefix, str(i))
161 found = False
162 for k in self.used_ips.keys():
163 if self.used_ips[k] == ip:
164 found = True
165 if found == False:
166 return ip
168 if found == True:
169 return None
171 def getFreeIP(self, domname, interface):
172 # Get a free IP. It uses the starting ip octets and then the
173 # total number of allowed numbers for that octet. It only
174 # calculates ips for the last two octets, we shouldn't need more
175 start_octets = self.min_ip.split(".")
176 ip = None
178 # Only working with ips from last two octets, shouldn't need more
179 max = int(start_octets[2]) + self.free_oct_ips[2]
180 for i in range(int(start_octets[2]), max):
181 prefix = '%s.%s.%s.' % (start_octets[0], start_octets[1], str(i))
182 ip = self.__findFirstOctetIP(prefix, int(start_octets[3]), self.free_oct_ips[3])
183 if ip:
184 break
186 if not ip:
187 raise NetworkError("Ran out of configured addresses.")
189 self.setUsedIP(domname, interface, ip)
190 return ip
192 def getNetMask(self):
193 return self.netmask
195 def getNetwork(self):
196 return self.network
198 def getIP(self, domname, interface):
199 # Depending on environment, set an IP. Uses the configured range
200 # of IPs, network address, and netmask
201 if NETWORK_IP_RANGE == "dhcp":
202 return None
204 # Make sure domain and interface aren't already assigned an IP
205 if self.used_ips.has_key('%s:%s' % (domname, interface)):
206 raise NetworkError("Domain %s interface %s is already has IP"
207 % (domname, interface))
209 return self.getFreeIP(domname, interface)
211 def setIP(self, domname, interface, ip):
212 # Make sure domain and interface aren't already assigned an IP
213 if self.used_ips.has_key('%s:%s' % (domname, interface)):
214 raise NetworkError("Domain %s interface %s is already has IP"
215 % (domname, interface))
217 self.setUsedIP(domname, interface, ip)
219 def releaseIP(self, domname, interface, ip):
220 if self.used_ips.has_key('%s:%s' % (domname, interface)):
221 del self.used_ips['%s:%s' % (domname, interface)]
223 def getNumberAllowedIPs(self):
224 return self.total_ips
226 def canRunNetTest(self, ips):
227 # Check to see if a test can run, returns true or false. Input is
228 # number of ips needed.
229 if NETWORK_IP_RANGE == "dhcp":
230 return True
232 if self.total_ips >= ips:
233 return True
235 return False
237 def isIPInRange(self, ip):
238 # Checks to see if supplied ip is in the range of allowed ips
239 maxo = self.max_ip.split('.')
240 mino = self.min_ip.split('.')
241 ipo = ip.split('.')
243 if int(ipo[0]) < int(mino[0]):
244 return False
245 elif int(ipo[0]) > int(maxo[0]):
246 return False
248 if int(ipo[1]) < int(mino[1]):
249 return False
250 elif int(ipo[1]) > int(maxo[1]):
251 return False
253 if int(ipo[2]) < int(mino[2]):
254 return False
255 elif int(ipo[2]) > int(maxo[2]):
256 return False
258 if int(ipo[3]) < int(mino[3]):
259 return False
260 elif int(ipo[3]) > int(maxo[3]):
261 return False
263 return True