diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/python/xen/xend/XendCheckpoint.py | 150 |
1 files changed, 73 insertions, 77 deletions
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 38e5370725..9d4b51d7a0 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -8,8 +8,8 @@ import os import re import select +import string import sxp -from string import join from struct import pack, unpack, calcsize from xen.util.xpopen import xPopen3 @@ -65,40 +65,22 @@ def save(fd, dominfo, live): # more information. cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd), str(dominfo.getDomid()), "0", "0", str(int(live)) ] - log.info("[xc_save] " + join(cmd)) - child = xPopen3(cmd, True, -1, [fd, xc.handle()]) - - lasterr = "" - p = select.poll() - p.register(child.fromchild.fileno()) - p.register(child.childerr.fileno()) - while True: - r = p.poll() - for (fd, event) in r: - if not event & select.POLLIN: - continue - if fd == child.childerr.fileno(): - l = child.childerr.readline() - log.error(l.rstrip()) - lasterr = l.rstrip() - if fd == child.fromchild.fileno(): - l = child.fromchild.readline() - if l.rstrip() == "suspend": - log.info("suspending %d", dominfo.getDomid()) - dominfo.shutdown('suspend') - dominfo.waitForShutdown() - log.info("suspend %d done", dominfo.getDomid()) - child.tochild.write("done\n") - child.tochild.flush() - if filter(lambda (fd, event): event & select.POLLHUP, r): - break - - if child.wait() >> 8 == 127: - lasterr = "popen %s failed" % PATH_XC_SAVE - if child.wait() != 0: - raise XendError("xc_save failed: %s" % lasterr) + log.debug("[xc_save]: %s", string.join(cmd)) + + def saveInputHandler(line, tochild): + log.debug("In saveInputHandler %s", line) + if line == "suspend": + log.debug("Suspending %d ...", dominfo.getDomid()) + dominfo.shutdown('suspend') + dominfo.waitForShutdown() + log.info("Domain %d suspended.", dominfo.getDomid()) + tochild.write("done\n") + tochild.flush() + + forkHelper(cmd, fd, saveInputHandler, False) dominfo.destroyDomain() + except Exception, exn: log.exception("Save failed on domain %s (%d).", domain_name, dominfo.getDomid()) @@ -149,52 +131,66 @@ def restore(xd, fd): cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd), str(dominfo.getDomid()), str(nr_pfns), str(store_evtchn), str(console_evtchn)] - log.info("[xc_restore] " + join(cmd)) - child = xPopen3(cmd, True, -1, [fd, xc.handle()]) - child.tochild.close() - - lasterr = "" - p = select.poll() - p.register(child.fromchild.fileno()) - p.register(child.childerr.fileno()) - while True: - r = p.poll() - for (fd, event) in r: - if not event & select.POLLIN: - continue - if fd == child.childerr.fileno(): - l = child.childerr.readline() - log.error(l.rstrip()) - lasterr = l.rstrip() - if fd == child.fromchild.fileno(): - l = child.fromchild.readline() - while l: - log.info(l.rstrip()) - m = re.match(r"^(store-mfn) (\d+)\n$", l) - if m: - store_mfn = int(m.group(2)) - dominfo.setStoreRef(store_mfn) - IntroduceDomain(dominfo.getDomid(), - store_mfn, - dominfo.store_channel.port1, - dominfo.getDomainPath()) - m = re.match(r"^(console-mfn) (\d+)\n$", l) - if m: - dominfo.setConsoleRef(int(m.group(2))) - try: - l = child.fromchild.readline() - except: - l = None - if filter(lambda (fd, event): event & select.POLLHUP, r): - break - - if child.wait() >> 8 == 127: - lasterr = "popen %s failed" % PATH_XC_RESTORE - if child.wait() != 0: - raise XendError("xc_restore failed: %s" % lasterr) + log.debug("[xc_restore]: %s", string.join(cmd)) + + def restoreInputHandler(line, _): + m = re.match(r"^(store-mfn) (\d+)$", line) + if m: + store_mfn = int(m.group(2)) + dominfo.setStoreRef(store_mfn) + IntroduceDomain(dominfo.getDomid(), + store_mfn, + dominfo.store_channel.port1, + dominfo.getDomainPath()) + else: + m = re.match(r"^(console-mfn) (\d+)$", line) + if m: + dominfo.setConsoleRef(int(m.group(2))) + + forkHelper(cmd, fd, restoreInputHandler, True) return dominfo except: - log.exception("Restore failed") dominfo.destroy() raise + + +def forkHelper(cmd, fd, inputHandler, closeToChild): + child = xPopen3(cmd, True, -1, [fd, xc.handle()]) + + if closeToChild: + child.tochild.close() + + fds = [child.fromchild.fileno(), + child.childerr.fileno()] + p = select.poll() + map(p.register, fds) + while len(fds) > 0: + r = p.poll() + for (fd, event) in r: + if event & select.POLLHUP or event & select.POLLERR: + fds.remove(fd) + p.unregister(fd) + continue + if not event & select.POLLIN: + continue + if fd == child.childerr.fileno(): + lasterr = child.childerr.readline().rstrip() + log.error('%s', lasterr) + else + l = child.fromchild.readline().rstrip() + while l: + log.debug('%s', l) + inputHandler(l, child.tochild) + try: + l = child.fromchild.readline().rstrip() + except: + l = None + + child.fromchild.close() + child.childerr.close() + + if child.wait() >> 8 == 127: + lasterr = "popen failed" + if child.wait() != 0: + raise XendError("%s failed: %s" % (string.join(cmd), lasterr)) |