[HVM] save restore: frame work

Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>

frame work for HVM save restore in Control Panel
This commit is contained in:
Tim Deegan committed 2007-01-18 16:48:03 +00:00
1 parent ccace2b704
commit 4a13cf1b70
10 files changed
+260 -17

No files matched your search

+22
View File
@@ -160,6 +160,20 @@ static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
return dom_op(self, args, xc_domain_destroy);
}
static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
{
uint32_t dom, reason;
if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
return NULL;
if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
return pyxc_error_to_exception();
Py_INCREF(zero);
return zero;
}
static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
PyObject *args,
@@ -1029,6 +1043,14 @@ static PyMethodDef pyxc_methods[] = {
" dom [int]: Identifier of domain to be destroyed.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_shutdown",
(PyCFunction)pyxc_domain_shutdown,
METH_VARARGS, "\n"
"Shutdown a domain.\n"
" dom [int, 0]: Domain identifier to use.\n"
" reason [int, 0]: Reason for shutdown.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "vcpu_setaffinity",
(PyCFunction)pyxc_vcpu_setaffinity,
METH_VARARGS | METH_KEYWORDS, "\n"
+81 -6
View File
@@ -22,11 +22,14 @@ from xen.xend.XendConfig import XendConfig
from xen.xend.XendConstants import *
SIGNATURE = "LinuxGuestRecord"
QEMU_SIGNATURE = "QemuDeviceModelRecord"
dm_batch = 512
XC_SAVE = "xc_save"
XC_RESTORE = "xc_restore"
sizeof_int = calcsize("i")
sizeof_unsigned_int = calcsize("I")
sizeof_unsigned_long = calcsize("L")
@@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst):
"could not write guest state file: config len")
write_exact(fd, config, "could not write guest state file: config")
image_cfg = dominfo.info.get('image', {})
hvm = image_cfg.has_key('hvm')
if hvm:
log.info("save hvm domain")
# xc_save takes three customization parameters: maxit, max_f, and
# flags the last controls whether or not save is 'live', while the
# first two further customize behaviour when 'live' save is
@@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst):
# libxenguest; see the comments and/or code in xc_linux_save() for
# more information.
cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
str(dominfo.getDomid()), "0", "0", str(int(live)) ]
str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
log.debug("[xc_save]: %s", string.join(cmd))
def saveInputHandler(line, tochild):
@@ -90,12 +98,29 @@ def save(fd, dominfo, network, live, dst):
log.info("Domain %d suspended.", dominfo.getDomid())
dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
domain_name)
#send signal to device model for save
if hvm:
log.info("release_devices for hvm domain")
dominfo._releaseDevices(True)
tochild.write("done\n")
tochild.flush()
log.debug('Written done')
forkHelper(cmd, fd, saveInputHandler, False)
# put qemu device model state
if hvm:
write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(), os.O_RDONLY)
while True:
buf = os.read(qemu_fd, dm_batch)
if len(buf):
write_exact(fd, buf, "could not write device model state")
else:
break
os.close(qemu_fd)
os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
dominfo.destroyDomain()
try:
dominfo.setName(domain_name)
@@ -149,19 +174,49 @@ def restore(xd, fd, dominfo = None, paused = False):
nr_pfns = (dominfo.getMemoryTarget() + 3) / 4
# if hvm, pass mem size to calculate the store_mfn
hvm = 0
apic = 0
pae = 0
image_cfg = dominfo.info.get('image', {})
hvm = image_cfg.has_key('hvm')
if hvm:
# the 'memory' in config has been removed
hvm = dominfo.info['memory_static_min']
apic = dominfo.info['image']['hvm'].get('apic', 0)
pae = dominfo.info['image']['hvm'].get('pae', 0)
log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
dominfo.domid, hvm, apic, pae)
try:
l = read_exact(fd, sizeof_unsigned_long,
"not a valid guest state file: pfn count read")
if hvm:
l = read_exact(fd, sizeof_unsigned_int,
"not a valid hvm guest state file: pfn count read")
nr_pfns = unpack("I", l)[0] # native sizeof int
else:
l = read_exact(fd, sizeof_unsigned_long,
"not a valid guest state file: pfn count read")
max_pfn = unpack("L", l)[0] # native sizeof long
if max_pfn > 16*1024*1024: # XXX
raise XendError(
"not a valid guest state file: pfn count out of range")
balloon.free(xc.pages_to_kib(nr_pfns))
shadow = dominfo.info['shadow_memory']
log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
"nr_pfns=0x%x.", dominfo.info['shadow_memory'],
dominfo.info['memory_static_max'],
dominfo.info['memory_static_min'], nr_pfns)
balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
dominfo.info['shadow_memory'] = shadow_cur
cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
fd, dominfo.getDomid(), max_pfn,
store_port, console_port])
store_port, console_port, hvm, pae, apic])
log.debug("[xc_restore]: %s", string.join(cmd))
handler = RestoreInputHandler()
@@ -171,10 +226,30 @@ def restore(xd, fd, dominfo = None, paused = False):
if handler.store_mfn is None or handler.console_mfn is None:
raise XendError('Could not read store/console MFN')
os.read(fd, 1) # Wait for source to close connection
dominfo.waitForDevices() # Wait for backends to set up
if not paused:
dominfo.unpause()
# get qemu state and create a tmp file for dm restore
if hvm:
qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
"invalid device model signature read")
if qemu_signature != QEMU_SIGNATURE:
raise XendError("not a valid device model state: found '%s'" %
qemu_signature)
qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
while True:
buf = os.read(fd, dm_batch)
if len(buf):
write_exact(qemu_fd, buf,
"could not write dm state to tmp file")
else:
break
os.close(qemu_fd)
os.read(fd, 1) # Wait for source to close connection
dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
+25 -1
View File
@@ -451,6 +451,16 @@ class XendDomainInfo:
self._removeVm('xend/previous_restart_time')
self.storeDom("control/shutdown", reason)
## shutdown hypercall for hvm domain desides xenstore write
image_cfg = self.info.get('image', {})
hvm = image_cfg.has_key('hvm')
if hvm:
for code in DOMAIN_SHUTDOWN_REASONS.keys():
if DOMAIN_SHUTDOWN_REASONS[code] == reason:
break
xc.domain_shutdown(self.domid, code)
def pause(self):
"""Pause domain
@@ -1228,8 +1238,11 @@ class XendDomainInfo:
if self.image:
self.image.createDeviceModel()
def _releaseDevices(self):
def _releaseDevices(self, suspend = False):
"""Release all domain's devices. Nothrow guarantee."""
if suspend and self.image:
self.image.destroy(suspend)
return
while True:
t = xstransact("%s/device" % self.dompath)
@@ -1395,6 +1408,7 @@ class XendDomainInfo:
self.info['shadow_memory'] * 1024,
self.info['memory_static_max'] * 1024)
log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
# takes MiB and we must not round down and end up under-providing.
shadow = ((shadow + 1023) / 1024) * 1024
@@ -1494,6 +1508,16 @@ class XendDomainInfo:
self.console_mfn = console_mfn
self._introduceDomain()
image_cfg = self.info.get('image', {})
hvm = image_cfg.has_key('hvm')
if hvm:
self.image = image.create(self,
self.info,
self.info['image'],
self.info['devices'])
if self.image:
self.image.createDeviceModel(True)
self.image.register_shutdown_watch()
self._storeDomDetails()
self._registerWatches()
self.refreshShutdown()
+10 -4
View File
@@ -173,7 +173,7 @@ class ImageHandler:
"""Build the domain. Define in subclass."""
raise NotImplementedError()
def createDeviceModel(self):
def createDeviceModel(self, restore = False):
"""Create device model for the domain (define in subclass if needed)."""
pass
@@ -478,7 +478,7 @@ class HVMImageHandler(ImageHandler):
return ret
def createDeviceModel(self):
def createDeviceModel(self, restore = False):
if self.pid:
return
# Execute device model.
@@ -487,6 +487,8 @@ class HVMImageHandler(ImageHandler):
args = args + ([ "-d", "%d" % self.vm.getDomid(),
"-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
args = args + self.dmargs
if restore:
args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
env = dict(os.environ)
if self.display:
env['DISPLAY'] = self.display
@@ -505,12 +507,16 @@ class HVMImageHandler(ImageHandler):
self.register_reboot_feature_watch()
self.pid = self.vm.gatherDom(('image/device-model-pid', int))
def destroy(self):
def destroy(self, suspend = False):
self.unregister_shutdown_watch()
self.unregister_reboot_feature_watch();
if self.pid:
try:
os.kill(self.pid, signal.SIGKILL)
sig = signal.SIGKILL
if suspend:
log.info("use sigusr1 to signal qemu %d", self.pid)
sig = signal.SIGUSR1
os.kill(self.pid, sig)
except OSError, exn:
log.exception(exn)
try:
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.