ia64/xen-unstable

view tools/python/xen/xend/XendCheckpoint.py @ 7071:299c2d5b5daf

Use constant in XendDomainInfo rather than embedding a string literal.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Tue Sep 27 12:30:13 2005 +0100 (2005-09-27)
parents 06d84bf87159
children 9ff1bea68d51
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.domid), "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.domid)
80 xd.domain_shutdown(dominfo.domid, reason='suspend')
81 dominfo.state_wait(XendDomainInfo.STATE_VM_SUSPENDED)
82 log.info("suspend %d done" % dominfo.domid)
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.closeStoreChannel()
94 xd.domain_destroy(dominfo.domid)
95 return None
97 def restore(xd, fd):
98 signature = read_exact(fd, len(SIGNATURE),
99 "not a valid guest state file: signature read")
100 if signature != SIGNATURE:
101 raise XendError("not a valid guest state file: found '%s'" %
102 signature)
104 l = read_exact(fd, sizeof_int,
105 "not a valid guest state file: config size read")
106 vmconfig_size = unpack("!i", l)[0]
107 vmconfig_buf = read_exact(fd, vmconfig_size,
108 "not a valid guest state file: config read")
110 p = sxp.Parser()
111 p.input(vmconfig_buf)
112 if not p.ready:
113 raise XendError("not a valid guest state file: config parse")
115 vmconfig = p.get_val()
116 dominfo = xd.domain_configure(vmconfig)
118 l = read_exact(fd, sizeof_unsigned_long,
119 "not a valid guest state file: pfn count read")
120 nr_pfns = unpack("=L", l)[0] # XXX endianess
121 if nr_pfns > 1024*1024: # XXX
122 raise XendError(
123 "not a valid guest state file: pfn count out of range")
125 if dominfo.store_channel:
126 store_evtchn = dominfo.store_channel.port2
127 else:
128 store_evtchn = 0
130 if dominfo.console_channel:
131 console_evtchn = dominfo.console_channel.port2
132 else:
133 console_evtchn = 0
135 cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
136 str(dominfo.domid), str(nr_pfns),
137 str(store_evtchn), str(console_evtchn)]
138 log.info("[xc_restore] " + join(cmd))
139 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
140 child.tochild.close()
142 lasterr = ""
143 p = select.poll()
144 p.register(child.fromchild.fileno())
145 p.register(child.childerr.fileno())
146 while True:
147 r = p.poll()
148 for (fd, event) in r:
149 if not event & select.POLLIN:
150 continue
151 if fd == child.childerr.fileno():
152 l = child.childerr.readline()
153 log.error(l.rstrip())
154 lasterr = l.rstrip()
155 if fd == child.fromchild.fileno():
156 l = child.fromchild.readline()
157 while l:
158 log.info(l.rstrip())
159 m = re.match(r"^(store-mfn) (\d+)\n$", l)
160 if m:
161 if dominfo.store_channel:
162 dominfo.setStoreRef(int(m.group(2)))
163 if dominfo.store_mfn >= 0:
164 IntroduceDomain(dominfo.domid,
165 dominfo.store_mfn,
166 dominfo.store_channel.port1,
167 dominfo.path)
168 m = re.match(r"^(console-mfn) (\d+)\n$", l)
169 if m:
170 dominfo.setConsoleRef(int(m.group(2)))
171 try:
172 l = child.fromchild.readline()
173 except:
174 l = None
175 if filter(lambda (fd, event): event & select.POLLHUP, r):
176 break
178 if child.wait() >> 8 == 127:
179 lasterr = "popen %s failed" % PATH_XC_RESTORE
180 if child.wait() != 0:
181 raise XendError("xc_restore failed: %s" % lasterr)
183 return dominfo