ia64/xen-unstable

view tools/python/xen/xend/XendCheckpoint.py @ 6835:5cbb2ecce16a

Move id back into main domain dir and rename to domid.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 14 15:10:22 2005 +0000 (2005-09-14)
parents 72e4e2aab342
children 9af349b055e5 3233e7ecfa9f
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()
16 from xen.xend.xenstore.xsutil import IntroduceDomain
18 from XendError import XendError
19 from XendLogging import log
21 SIGNATURE = "LinuxGuestRecord"
22 PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
23 PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
25 sizeof_int = calcsize("i")
26 sizeof_unsigned_long = calcsize("L")
28 def write_exact(fd, buf, errmsg):
29 if os.write(fd, buf) != len(buf):
30 raise XendError(errmsg)
32 def read_exact(fd, size, errmsg):
33 buf = os.read(fd, size)
34 if len(buf) != size:
35 raise XendError(errmsg)
36 return buf
38 def save(xd, fd, dominfo, live):
39 write_exact(fd, SIGNATURE, "could not write guest state file: signature")
41 config = sxp.to_string(dominfo.sxpr())
42 write_exact(fd, pack("!i", len(config)),
43 "could not write guest state file: config len")
44 write_exact(fd, config, "could not write guest state file: config")
46 # xc_save takes three customization parameters: maxit, max_f, and flags
47 # the last controls whether or not save is 'live', while the first two
48 # further customize behaviour when 'live' save is enabled. Passing "0"
49 # simply uses the defaults compiled into libxenguest; see the comments
50 # and/or code in xc_linux_save() for more information.
51 cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
52 str(dominfo.domid), "0", "0", str(int(live)) ]
53 log.info("[xc_save] " + join(cmd))
54 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
56 lasterr = ""
57 p = select.poll()
58 p.register(child.fromchild.fileno())
59 p.register(child.childerr.fileno())
60 while True:
61 r = p.poll()
62 for (fd, event) in r:
63 if not event & select.POLLIN:
64 continue
65 if fd == child.childerr.fileno():
66 l = child.childerr.readline()
67 log.error(l.rstrip())
68 lasterr = l.rstrip()
69 if fd == child.fromchild.fileno():
70 l = child.fromchild.readline()
71 if l.rstrip() == "suspend":
72 log.info("suspending %d" % dominfo.domid)
73 xd.domain_shutdown(dominfo.domid, reason='suspend')
74 dominfo.state_wait("suspended")
75 log.info("suspend %d done" % dominfo.domid)
76 child.tochild.write("done\n")
77 child.tochild.flush()
78 if filter(lambda (fd, event): event & select.POLLHUP, r):
79 break
81 if child.wait() >> 8 == 127:
82 lasterr = "popen %s failed" % PATH_XC_SAVE
83 if child.wait() != 0:
84 raise XendError("xc_save failed: %s" % lasterr)
86 dominfo.setStoreChannel(None)
87 xd.domain_destroy(dominfo.domid)
88 return None
90 def restore(xd, fd):
91 signature = read_exact(fd, len(SIGNATURE),
92 "not a valid guest state file: signature read")
93 if signature != SIGNATURE:
94 raise XendError("not a valid guest state file: found '%s'" %
95 signature)
97 l = read_exact(fd, sizeof_int,
98 "not a valid guest state file: config size read")
99 vmconfig_size = unpack("!i", l)[0]
100 vmconfig_buf = read_exact(fd, vmconfig_size,
101 "not a valid guest state file: config read")
103 p = sxp.Parser()
104 p.input(vmconfig_buf)
105 if not p.ready:
106 raise XendError("not a valid guest state file: config parse")
108 vmconfig = p.get_val()
109 dominfo = xd.domain_configure(vmconfig)
111 l = read_exact(fd, sizeof_unsigned_long,
112 "not a valid guest state file: pfn count read")
113 nr_pfns = unpack("=L", l)[0] # XXX endianess
114 if nr_pfns > 1024*1024: # XXX
115 raise XendError(
116 "not a valid guest state file: pfn count out of range")
118 if dominfo.store_channel:
119 store_evtchn = dominfo.store_channel.port2
120 else:
121 store_evtchn = 0
123 if dominfo.console_channel:
124 console_evtchn = dominfo.console_channel.port2
125 else:
126 console_evtchn = 0
128 cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
129 str(dominfo.domid), str(nr_pfns),
130 str(store_evtchn), str(console_evtchn)]
131 log.info("[xc_restore] " + join(cmd))
132 child = xPopen3(cmd, True, -1, [fd, xc.handle()])
133 child.tochild.close()
135 lasterr = ""
136 p = select.poll()
137 p.register(child.fromchild.fileno())
138 p.register(child.childerr.fileno())
139 while True:
140 r = p.poll()
141 for (fd, event) in r:
142 if not event & select.POLLIN:
143 continue
144 if fd == child.childerr.fileno():
145 l = child.childerr.readline()
146 log.error(l.rstrip())
147 lasterr = l.rstrip()
148 if fd == child.fromchild.fileno():
149 l = child.fromchild.readline()
150 while l:
151 log.info(l.rstrip())
152 m = re.match(r"^(store-mfn) (\d+)\n$", l)
153 if m:
154 if dominfo.store_channel:
155 dominfo.setStoreRef(int(m.group(2)))
156 if dominfo.store_mfn >= 0:
157 IntroduceDomain(dominfo.domid,
158 dominfo.store_mfn,
159 dominfo.store_channel.port1,
160 dominfo.path)
161 m = re.match(r"^(console-mfn) (\d+)\n$", l)
162 if m:
163 dominfo.setConsoleRef(int(m.group(2)))
164 try:
165 l = child.fromchild.readline()
166 except:
167 l = None
168 if filter(lambda (fd, event): event & select.POLLHUP, r):
169 break
171 if child.wait() >> 8 == 127:
172 lasterr = "popen %s failed" % PATH_XC_RESTORE
173 if child.wait() != 0:
174 raise XendError("xc_restore failed: %s" % lasterr)
176 return dominfo