debuggers.hg

view tools/python/xen/xend/XendCheckpoint.py @ 6641:f27205ea60ef

merge?
author cl349@firebug.cl.cam.ac.uk
date Sat Sep 03 16:58:50 2005 +0000 (2005-09-03)
parents dd668f7527cb a1de77c1486c
children 29808fef9148 2e2611af05c6
line source
1 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
3 # This file is subject to the terms and conditions of the GNU General
4 # Public License. See the file "COPYING" in the main directory of
5 # this archive for more details.
7 import errno
8 import os
9 import re
10 import select
11 import sxp
12 from string import join
13 from struct import pack, unpack, calcsize
14 from xen.util.xpopen import xPopen3
15 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
17 from XendError import XendError
18 from XendLogging import log
20 SIGNATURE = "LinuxGuestRecord"
21 PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
22 PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
24 sizeof_int = calcsize("i")
25 sizeof_unsigned_long = calcsize("L")
27 def write_exact(fd, buf, errmsg):
28 if os.write(fd, buf) != len(buf):
29 raise XendError(errmsg)
31 def read_exact(fd, size, errmsg):
32 buf = os.read(fd, size)
33 if len(buf) != size:
34 raise XendError(errmsg)
35 return buf
37 def save(xd, fd, dominfo, live):
38 write_exact(fd, SIGNATURE, "could not write guest state file: signature")
40 config = sxp.to_string(dominfo.sxpr())
41 write_exact(fd, pack("!i", len(config)),
42 "could not write guest state file: config len")
43 write_exact(fd, config, "could not write guest state file: config")
45 # xc_save takes three customization parameters: maxit, max_f, and flags
46 # the last controls whether or not save is 'live', while the first two
47 # further customize behaviour when 'live' save is enabled. Passing "0"
48 # simply uses the defaults compiled into libxenguest; see the comments
49 # and/or code in xc_linux_save() for more information.
50 cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
51 str(dominfo.id), "0", "0", str(live) ]
52 log.info("[xc_save] " + join(cmd))
53 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
55 lasterr = ""
56 p = select.poll()
57 p.register(child.fromchild.fileno())
58 p.register(child.childerr.fileno())
59 while True:
60 r = p.poll()
61 for (fd, event) in r:
62 if not event & select.POLLIN:
63 continue
64 if fd == child.childerr.fileno():
65 l = child.childerr.readline()
66 log.error(l.rstrip())
67 lasterr = l.rstrip()
68 if fd == child.fromchild.fileno():
69 l = child.fromchild.readline()
70 if l.rstrip() == "suspend":
71 log.info("suspending %d" % dominfo.id)
72 xd.domain_shutdown(dominfo.id, reason='suspend')
73 if dominfo.store_channel:
74 try:
75 dominfo.db.releaseDomain(dominfo.id)
76 except Exception, ex:
77 log.warning(
78 "error in domain release on xenstore: %s",
79 ex)
80 pass
81 dominfo.state_wait("suspended")
82 log.info("suspend %d done" % dominfo.id)
83 child.tochild.write("done\n")
84 child.tochild.flush()
85 if filter(lambda (fd, event): event & select.POLLHUP, r):
86 break
88 if child.wait() >> 8 == 127:
89 lasterr = "popen %s failed" % PATH_XC_SAVE
90 if child.wait() != 0:
91 raise XendError("xc_save failed: %s" % lasterr)
93 if dominfo.store_channel:
94 dominfo.store_channel.close()
95 dominfo.db['store_channel'].delete()
96 dominfo.db.saveDB(save=True)
97 dominfo.store_channel = None
98 xd.domain_destroy(dominfo.id)
99 return None
101 def restore(xd, fd):
102 signature = read_exact(fd, len(SIGNATURE),
103 "not a valid guest state file: signature read")
104 if signature != SIGNATURE:
105 raise XendError("not a valid guest state file: found '%s'" %
106 signature)
108 l = read_exact(fd, sizeof_int,
109 "not a valid guest state file: config size read")
110 vmconfig_size = unpack("!i", l)[0]
111 vmconfig_buf = read_exact(fd, vmconfig_size,
112 "not a valid guest state file: config read")
114 p = sxp.Parser()
115 p.input(vmconfig_buf)
116 if not p.ready:
117 raise XendError("not a valid guest state file: config parse")
119 vmconfig = p.get_val()
120 dominfo = xd.domain_configure(vmconfig)
122 l = read_exact(fd, sizeof_unsigned_long,
123 "not a valid guest state file: pfn count read")
124 nr_pfns = unpack("=L", l)[0] # XXX endianess
125 if nr_pfns > 1024*1024: # XXX
126 raise XendError(
127 "not a valid guest state file: pfn count out of range")
129 if dominfo.store_channel:
130 evtchn = dominfo.store_channel.port2
131 else:
132 evtchn = 0
134 cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
135 str(dominfo.id), str(nr_pfns), str(evtchn)]
136 log.info("[xc_restore] " + join(cmd))
137 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
138 child.tochild.close()
140 lasterr = ""
141 p = select.poll()
142 p.register(child.fromchild.fileno())
143 p.register(child.childerr.fileno())
144 while True:
145 r = p.poll()
146 for (fd, event) in r:
147 if not event & select.POLLIN:
148 continue
149 if fd == child.childerr.fileno():
150 l = child.childerr.readline()
151 log.error(l.rstrip())
152 lasterr = l.rstrip()
153 if fd == child.fromchild.fileno():
154 l = child.fromchild.readline()
155 while l:
156 m = re.match(r"^(store-mfn) (\d+)\n$", l)
157 if m:
158 if dominfo.store_channel:
159 dominfo.store_mfn = int(m.group(2))
160 if dominfo.store_mfn >= 0:
161 dominfo.db.introduceDomain(dominfo.id,
162 dominfo.store_mfn,
163 dominfo.store_channel)
164 dominfo.exportToDB(save=True, sync=True)
165 log.info(l.rstrip())
166 try:
167 l = child.fromchild.readline()
168 except:
169 l = None
170 if filter(lambda (fd, event): event & select.POLLHUP, r):
171 break
173 if child.wait() >> 8 == 127:
174 lasterr = "popen %s failed" % PATH_XC_RESTORE
175 if child.wait() != 0:
176 raise XendError("xc_restore failed: %s" % lasterr)
178 return dominfo