ia64/xen-unstable

view tools/python/xen/xend/XendCheckpoint.py @ 7672:ca37f8be9426

Rename parameter to avoid shadowing builtin.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Mon Nov 07 21:22:02 2005 +0100 (2005-11-07)
parents fe487b19c379
children fe3a892b33b4
line source
1 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
2 # Copyright (C) 2005 XenSource Ltd
4 # This file is subject to the terms and conditions of the GNU General
5 # Public License. See the file "COPYING" in the main directory of
6 # this archive for more details.
8 import os
9 import re
10 import string
11 import sxp
12 import threading
13 from struct import pack, unpack, calcsize
15 from xen.util.xpopen import xPopen3
17 import xen.util.auxbin
19 import xen.lowlevel.xc
21 from xen.xend.xenstore.xsutil import IntroduceDomain
23 from XendError import XendError
24 from XendLogging import log
27 SIGNATURE = "LinuxGuestRecord"
28 XC_SAVE = "xc_save"
29 XC_RESTORE = "xc_restore"
32 sizeof_int = calcsize("i")
33 sizeof_unsigned_long = calcsize("L")
36 xc = xen.lowlevel.xc.new()
39 def write_exact(fd, buf, errmsg):
40 if os.write(fd, buf) != len(buf):
41 raise XendError(errmsg)
43 def read_exact(fd, size, errmsg):
44 buf = os.read(fd, size)
45 if len(buf) != size:
46 raise XendError(errmsg)
47 return buf
49 def save(fd, dominfo, live):
50 write_exact(fd, SIGNATURE, "could not write guest state file: signature")
52 config = sxp.to_string(dominfo.sxpr())
54 domain_name = dominfo.getName()
55 # Rename the domain temporarily, so that we don't get a name clash if this
56 # domain is migrating (live or non-live) to the local host. Doing such a
57 # thing is useful for debugging.
58 dominfo.setName('migrating-' + domain_name)
60 try:
61 write_exact(fd, pack("!i", len(config)),
62 "could not write guest state file: config len")
63 write_exact(fd, config, "could not write guest state file: config")
65 # xc_save takes three customization parameters: maxit, max_f, and
66 # flags the last controls whether or not save is 'live', while the
67 # first two further customize behaviour when 'live' save is
68 # enabled. Passing "0" simply uses the defaults compiled into
69 # libxenguest; see the comments and/or code in xc_linux_save() for
70 # more information.
71 cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(xc.handle()), str(fd),
72 str(dominfo.getDomid()), "0", "0", str(int(live)) ]
73 log.debug("[xc_save]: %s", string.join(cmd))
75 def saveInputHandler(line, tochild):
76 log.debug("In saveInputHandler %s", line)
77 if line == "suspend":
78 log.debug("Suspending %d ...", dominfo.getDomid())
79 dominfo.shutdown('suspend')
80 dominfo.waitForShutdown()
81 log.info("Domain %d suspended.", dominfo.getDomid())
82 tochild.write("done\n")
83 tochild.flush()
84 log.debug('Written done')
86 forkHelper(cmd, fd, saveInputHandler, False)
88 dominfo.destroyDomain()
90 except Exception, exn:
91 log.exception("Save failed on domain %s (%d).", domain_name,
92 dominfo.getDomid())
93 try:
94 dominfo.setName(domain_name)
95 except:
96 log.exception("Failed to reset the migrating domain's name")
97 raise Exception, exn
100 def restore(xd, fd):
101 signature = read_exact(fd, len(SIGNATURE),
102 "not a valid guest state file: signature read")
103 if signature != SIGNATURE:
104 raise XendError("not a valid guest state file: found '%s'" %
105 signature)
107 l = read_exact(fd, sizeof_int,
108 "not a valid guest state file: config size read")
109 vmconfig_size = unpack("!i", l)[0]
110 vmconfig_buf = read_exact(fd, vmconfig_size,
111 "not a valid guest state file: config read")
113 p = sxp.Parser()
114 p.input(vmconfig_buf)
115 if not p.ready:
116 raise XendError("not a valid guest state file: config parse")
118 vmconfig = p.get_val()
120 dominfo = xd.restore_(vmconfig)
122 store_port = dominfo.getStorePort()
123 console_port = dominfo.getConsolePort()
125 assert store_port
126 assert console_port
128 try:
129 l = read_exact(fd, sizeof_unsigned_long,
130 "not a valid guest state file: pfn count read")
131 nr_pfns = unpack("=L", l)[0] # XXX endianess
132 if nr_pfns > 1024*1024: # XXX
133 raise XendError(
134 "not a valid guest state file: pfn count out of range")
136 cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
137 xc.handle(), fd, dominfo.getDomid(), nr_pfns,
138 store_port, console_port])
139 log.debug("[xc_restore]: %s", string.join(cmd))
141 handler = RestoreInputHandler()
143 forkHelper(cmd, fd, handler.handler, True)
145 if handler.store_mfn is None or handler.console_mfn is None:
146 raise XendError('Could not read store/console MFN')
148 dominfo.unpause()
150 dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
152 return dominfo
153 except:
154 dominfo.destroy()
155 raise
158 class RestoreInputHandler:
159 def __init__(self):
160 self.store_mfn = None
161 self.console_mfn = None
164 def handler(self, line, _):
165 m = re.match(r"^(store-mfn) (\d+)$", line)
166 if m:
167 self.store_mfn = int(m.group(2))
168 else:
169 m = re.match(r"^(console-mfn) (\d+)$", line)
170 if m:
171 self.console_mfn = int(m.group(2))
174 def forkHelper(cmd, fd, inputHandler, closeToChild):
175 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
177 if closeToChild:
178 child.tochild.close()
180 thread = threading.Thread(target = slurp, args = (child.childerr,))
181 thread.start()
183 try:
184 try:
185 while 1:
186 line = child.fromchild.readline()
187 if line == "":
188 break
189 else:
190 line = line.rstrip()
191 log.debug('%s', line)
192 inputHandler(line, child.tochild)
194 thread.join()
196 except IOError, exn:
197 raise XendError('Error reading from child process for %s: %s' %
198 (cmd, exn))
199 finally:
200 child.fromchild.close()
201 child.childerr.close()
202 if not closeToChild:
203 child.tochild.close()
205 status = child.wait()
206 if status >> 8 == 127:
207 raise XendError("%s failed: popen failed" % string.join(cmd))
208 elif status != 0:
209 raise XendError("%s failed" % string.join(cmd))
212 def slurp(infile):
213 while 1:
214 line = infile.readline()
215 if line == "":
216 break
217 else:
218 log.error('%s', line)