ia64/xen-unstable

view tools/python/xen/xend/XendCheckpoint.py @ 7155:468ad17f9970

Minor tidy.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Fri Sep 30 17:05:08 2005 +0100 (2005-09-30)
parents 4a2c162d3e7c
children 9c6b39746b78 5a3d5f9ef44e
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 os
8 import re
9 import select
10 import sxp
11 from string import join
12 from struct import pack, unpack, calcsize
14 from xen.util.xpopen import xPopen3
16 import xen.lowlevel.xc
18 import XendDomainInfo
19 from xen.xend.xenstore.xsutil import IntroduceDomain
21 from XendError import XendError
22 from XendLogging import log
24 SIGNATURE = "LinuxGuestRecord"
25 PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
26 PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
28 sizeof_int = calcsize("i")
29 sizeof_unsigned_long = calcsize("L")
32 xc = xen.lowlevel.xc.new()
35 def write_exact(fd, buf, errmsg):
36 if os.write(fd, buf) != len(buf):
37 raise XendError(errmsg)
39 def read_exact(fd, size, errmsg):
40 buf = os.read(fd, size)
41 if len(buf) != size:
42 raise XendError(errmsg)
43 return buf
45 def save(xd, fd, dominfo, live):
46 write_exact(fd, SIGNATURE, "could not write guest state file: signature")
48 config = sxp.to_string(dominfo.sxpr())
49 write_exact(fd, pack("!i", len(config)),
50 "could not write guest state file: config len")
51 write_exact(fd, config, "could not write guest state file: config")
53 # xc_save takes three customization parameters: maxit, max_f, and flags
54 # the last controls whether or not save is 'live', while the first two
55 # further customize behaviour when 'live' save is enabled. Passing "0"
56 # simply uses the defaults compiled into libxenguest; see the comments
57 # and/or code in xc_linux_save() for more information.
58 cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
59 str(dominfo.getDomid()), "0", "0", str(int(live)) ]
60 log.info("[xc_save] " + join(cmd))
61 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
63 lasterr = ""
64 p = select.poll()
65 p.register(child.fromchild.fileno())
66 p.register(child.childerr.fileno())
67 while True:
68 r = p.poll()
69 for (fd, event) in r:
70 if not event & select.POLLIN:
71 continue
72 if fd == child.childerr.fileno():
73 l = child.childerr.readline()
74 log.error(l.rstrip())
75 lasterr = l.rstrip()
76 if fd == child.fromchild.fileno():
77 l = child.fromchild.readline()
78 if l.rstrip() == "suspend":
79 log.info("suspending %d" % dominfo.getDomid())
80 xd.domain_shutdown(dominfo.getDomid(), reason='suspend')
81 dominfo.state_wait(XendDomainInfo.STATE_VM_SUSPENDED)
82 log.info("suspend %d done" % dominfo.getDomid())
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 dominfo.destroy()
94 return None
96 def restore(fd):
97 signature = read_exact(fd, len(SIGNATURE),
98 "not a valid guest state file: signature read")
99 if signature != SIGNATURE:
100 raise XendError("not a valid guest state file: found '%s'" %
101 signature)
103 l = read_exact(fd, sizeof_int,
104 "not a valid guest state file: config size read")
105 vmconfig_size = unpack("!i", l)[0]
106 vmconfig_buf = read_exact(fd, vmconfig_size,
107 "not a valid guest state file: config read")
109 p = sxp.Parser()
110 p.input(vmconfig_buf)
111 if not p.ready:
112 raise XendError("not a valid guest state file: config parse")
114 vmconfig = p.get_val()
115 dominfo = XendDomainInfo.restore(vmconfig)
117 l = read_exact(fd, sizeof_unsigned_long,
118 "not a valid guest state file: pfn count read")
119 nr_pfns = unpack("=L", l)[0] # XXX endianess
120 if nr_pfns > 1024*1024: # XXX
121 raise XendError(
122 "not a valid guest state file: pfn count out of range")
124 if dominfo.store_channel:
125 store_evtchn = dominfo.store_channel.port2
126 else:
127 store_evtchn = 0
129 if dominfo.console_channel:
130 console_evtchn = dominfo.console_channel.port2
131 else:
132 console_evtchn = 0
134 cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
135 str(dominfo.getDomid()), str(nr_pfns),
136 str(store_evtchn), str(console_evtchn)]
137 log.info("[xc_restore] " + join(cmd))
138 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
139 child.tochild.close()
141 lasterr = ""
142 p = select.poll()
143 p.register(child.fromchild.fileno())
144 p.register(child.childerr.fileno())
145 while True:
146 r = p.poll()
147 for (fd, event) in r:
148 if not event & select.POLLIN:
149 continue
150 if fd == child.childerr.fileno():
151 l = child.childerr.readline()
152 log.error(l.rstrip())
153 lasterr = l.rstrip()
154 if fd == child.fromchild.fileno():
155 l = child.fromchild.readline()
156 while l:
157 log.info(l.rstrip())
158 m = re.match(r"^(store-mfn) (\d+)\n$", l)
159 if m:
160 if dominfo.store_channel:
161 store_mfn = int(m.group(2))
162 dominfo.setStoreRef(store_mfn)
163 IntroduceDomain(dominfo.getDomid(),
164 store_mfn,
165 dominfo.store_channel.port1,
166 dominfo.getDomainPath())
167 m = re.match(r"^(console-mfn) (\d+)\n$", l)
168 if m:
169 dominfo.setConsoleRef(int(m.group(2)))
170 try:
171 l = child.fromchild.readline()
172 except:
173 l = None
174 if filter(lambda (fd, event): event & select.POLLHUP, r):
175 break
177 if child.wait() >> 8 == 127:
178 lasterr = "popen %s failed" % PATH_XC_RESTORE
179 if child.wait() != 0:
180 raise XendError("xc_restore failed: %s" % lasterr)
182 return dominfo