ia64/xen-unstable

view tools/xm-test/lib/XmTestLib/XenDomain.py @ 13801:2e80cd715047

Copy the definition of DOM0_UUID into XenDomain so that we don't need to import
large swathes of the server to run the Xen-API tests.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Feb 01 11:42:50 2007 +0000 (2007-02-01)
parents 56e2341f02c4
children
line source
1 #!/usr/bin/python
2 """
3 Copyright (C) International Business Machines Corp., 2005
4 Author: Dan Smith <danms@us.ibm.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; under version 2 of the License.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 """
21 import sys
22 import commands
23 import re
24 import time
26 from Xm import *
27 from arch import *
28 from Test import *
29 from config import *
30 from Console import *
31 from XenDevice import *
32 from DomainTracking import *
33 from acm import *
36 DOM0_UUID = "00000000-0000-0000-0000-000000000000"
39 def getDefaultKernel():
40 return arch.getDefaultKernel()
42 def getRdPath():
43 return arch.getRdPath()
45 def getUniqueName():
46 """Get a uniqueish name for use in a domain"""
47 unixtime = int(time.time())
48 test_name = sys.argv[0]
49 test_name = re.sub("\.test", "", test_name)
50 test_name = re.sub("[\/\.]", "", test_name)
51 name = "%s-%i" % (test_name, unixtime)
53 return name
55 class XenConfig:
56 """An object to help create a xen-compliant config file"""
57 def __init__(self):
58 self.defaultOpts = {}
60 # These options need to be lists
61 self.defaultOpts["disk"] = []
62 self.defaultOpts["vif"] = []
63 self.defaultOpts["vtpm"] = []
64 if isACMEnabled():
65 #A default so every VM can start with ACM enabled
66 self.defaultOpts["access_control"] = ['policy=xm-test,label=red']
68 self.opts = self.defaultOpts
70 def toString(self):
71 """Convert this config to a string for writing out
72 to a file"""
73 string = "# Xen configuration generated by xm-test\n"
74 for k, v in self.opts.items():
75 if isinstance(v, int):
76 piece = "%s = %i" % (k, v)
77 elif isinstance(v, list) and v:
78 piece = "%s = %s" % (k, v)
79 elif isinstance(v, str) and v:
80 piece = "%s = \"%s\"" % (k, v)
81 else:
82 piece = None
84 if piece:
85 string += "%s\n" % piece
87 return string
89 def write(self, filename):
90 """Write this config out to filename"""
91 output = file(filename, "w")
92 output.write(self.toString())
93 output.close()
94 ACMPrepareSystem(self.opts)
96 def __str__(self):
97 """When used as a string, we represent ourself by a config
98 filename, which points to a temporary config that we write
99 out ahead of time"""
100 filename = "/tmp/xm-test.conf"
101 self.write(filename)
102 return filename
104 def setOpt(self, name, value):
105 """Set an option in the config"""
106 if name in self.opts.keys() and isinstance(self.opts[name] ,
107 list) and not isinstance(value, list):
108 self.opts[name] = [value]
109 # "extra" is special so append to it.
110 elif name == "extra" and name in self.opts.keys():
111 self.opts[name] += " %s" % (value)
112 else:
113 self.opts[name] = value
115 def appOpt(self, name, value):
116 """Append a value to a list option"""
117 if name in self.opts.keys() and isinstance(self.opts[name], list):
118 self.opts[name].append(value)
120 def getOpt(self, name):
121 """Return the value of a config option"""
122 if name in self.opts.keys():
123 return self.opts[name]
124 else:
125 return None
127 def setOpts(self, opts):
128 """Batch-set options from a dictionary"""
129 for k, v in opts.items():
130 self.setOpt(k, v)
132 def clearOpts(self, name=None):
133 """Clear one or all config options"""
134 if name:
135 self.opts[name] = self.defaultOpts[name]
136 else:
137 self.opts = self.defaultOpts
139 class DomainError(Exception):
140 def __init__(self, msg, extra="", errorcode=0):
141 self.msg = msg
142 self.extra = extra
143 try:
144 self.errorcode = int(errorcode)
145 except Exception, e:
146 self.errorcode = -1
148 def __str__(self):
149 return str(self.msg)
152 class XenDomain:
154 def __init__(self, name=None, config=None, isManaged=False):
155 """Create a domain object.
156 @param config: String filename of config file
157 """
159 if name:
160 self.name = name
161 else:
162 self.name = getUniqueName()
164 self.config = config
165 self.console = None
166 self.devices = {}
167 self.netEnv = "bridge"
169 if os.getenv("XM_MANAGED_DOMAINS"):
170 isManaged = True
171 self.isManaged = isManaged
173 # Set domain type, either PV for ParaVirt domU or HVM for
174 # FullVirt domain
175 if ENABLE_HVM_SUPPORT:
176 self.type = "HVM"
177 else:
178 self.type = "PV"
180 def start(self, noConsole=False):
182 if not self.isManaged:
183 ret, output = traceCommand("xm create %s" % self.config)
184 else:
185 ret, output = traceCommand("xm new %s" % self.config)
186 if ret != 0:
187 _ret, output = traceCommand("xm delete " +
188 self.config.getOpt("name"))
189 else:
190 ret, output = traceCommand("xm start " +
191 self.config.getOpt("name"))
192 addManagedDomain(self.config.getOpt("name"))
194 if ret != 0:
195 raise DomainError("Failed to create domain",
196 extra=output,
197 errorcode=ret)
199 # HVM domains require waiting for boot
200 if self.getDomainType() == "HVM":
201 waitForBoot()
203 # Go through device list and run console cmds
204 for dev in self.devices.keys():
205 self.devices[dev].execAddCmds()
207 if self.console and noConsole == True:
208 self.closeConsole()
210 elif self.console and noConsole == False:
211 return self.console
213 elif not self.console and noConsole == False:
214 return self.getConsole()
216 def stop(self):
217 prog = "xm"
218 cmd = " shutdown "
220 self.removeAllDevices()
222 if self.console:
223 self.closeConsole()
225 ret, output = traceCommand(prog + cmd + self.config.getOpt("name"))
227 return ret
229 def destroy(self):
230 prog = "xm"
231 cmd = " destroy "
233 self.removeAllDevices()
235 if self.console:
236 self.closeConsole()
238 ret, output = traceCommand(prog + cmd + self.config.getOpt("name"))
239 if self.isManaged:
240 ret, output = traceCommand(prog + " delete " +
241 self.config.getOpt("name"))
242 delManagedDomain(self.config.getOpt("name"))
244 return ret
246 def getName(self):
247 return self.name
249 def getId(self):
250 return domid(self.getName());
252 def getDomainType(self):
253 return self.type
255 def closeConsole(self):
256 # The domain closeConsole command must be called by tests, not the
257 # console's close command. Once close is called, the console is
258 # gone. You can't get history or anything else from it.
259 if self.console:
260 self.console._XmConsole__closeConsole()
261 self.console = None
263 def getConsole(self):
264 if self.console:
265 self.closeConsole()
267 self.console = XmConsole(self.getName())
268 # Activate the console
269 self.console.sendInput("input")
271 return self.console
273 def newDevice(self, Device, *args):
274 """Device Factory: Generic factory for creating new XenDevices.
275 All device creation should be done through the XenDomain
276 factory. Supply a XenDevice instance and its args and the
277 constructor will be called."""
278 # Make sure device with id hasn't already been added
279 if self.devices.has_key(args[0]):
280 raise DeviceError("Error: Domain already has device %s" % args[0])
282 # Call constructor for supplied Device instance
283 dargs = (self,)
284 dargs += args
285 dev = apply(Device, dargs)
287 if self.isRunning():
288 # Note: This needs to be done, XenDevice should have an attach
289 # method.
290 print "Domain is running, need to attach new device to domain."
292 self.devices[dev.id] = dev
293 self.config.appOpt(dev.configNode, str(dev))
294 return dev
296 def removeDevice(self, id):
297 if self.devices.has_key(id):
298 self.devices[id].removeDevice()
300 def removeAllDevices(self):
301 for k in self.devices.keys():
302 self.removeDevice(k)
304 def isRunning(self):
305 return isDomainRunning(self.name)
307 def getNetEnv(self):
308 # We need to know the network environment: bridge, NAT, or routed.
309 return self.netEnv
311 def getDevice(self, id):
312 dev = self.devices[id]
313 if dev:
314 return dev
315 print "Device %s not found for domain %s" % (id, self.getName())
318 class XmTestDomain(XenDomain):
320 def __init__(self, name=None, extraConfig=None,
321 baseConfig=arch.configDefaults, isManaged=False):
322 """Create a new xm-test domain
323 @param name: The requested domain name
324 @param extraConfig: Additional configuration options
325 @param baseConfig: The initial configuration defaults to use
326 """
327 config = XenConfig()
328 config.setOpts(baseConfig)
329 if extraConfig:
330 config.setOpts(extraConfig)
332 if name:
333 config.setOpt("name", name)
334 elif not config.getOpt("name"):
335 config.setOpt("name", getUniqueName())
337 XenDomain.__init__(self, config.getOpt("name"), config=config,
338 isManaged=isManaged)
340 def minSafeMem(self):
341 return arch.minSafeMem
343 class XmTestNetDomain(XmTestDomain):
345 def __init__(self, name=None, extraConfig=None,
346 baseConfig=arch.configDefaults):
347 """Create a new xm-test domain with one network device
348 @param name: The requested domain name
349 @param extraConfig: Additional configuration options
350 @param baseConfig: The initial configuration defaults to use
351 """
352 config = XenConfig()
353 config.setOpts(baseConfig)
354 if extraConfig:
355 config.setOpts(extraConfig)
357 if name:
358 config.setOpt("name", name)
359 elif not config.getOpt("name"):
360 config.setOpt("name", getUniqueName())
362 XenDomain.__init__(self, config.getOpt("name"), config=config)
364 # Add one network devices to domain
365 self.newDevice(XenNetDevice, "eth0")
368 if __name__ == "__main__":
370 c = XenConfig()
372 c.setOpt("foo", "bar")
373 c.setOpt("foob", 1)
374 opts = {"opt1" : 19,
375 "opt2" : "blah"}
376 c.setOpts(opts)
378 c.setOpt("disk", "phy:/dev/ram0,hda1,w")
379 c.appOpt("disk", "phy:/dev/ram1,hdb1,w")
381 print str(c)
385 # c.write("/tmp/foo.conf")
387 # d = XmTestDomain();
388 #
389 # d.start();