Index: xen/xen-unstable.hg/tools/python/xen/xend/XendCheckpoint.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/XendCheckpoint.py +++ xen/xen-unstable.hg/tools/python/xen/xend/XendCheckpoint.py @@ -53,7 +53,7 @@ def read_exact(fd, size, errmsg): -def save(fd, dominfo, live): +def save(fd, dominfo, live, dst): write_exact(fd, SIGNATURE, "could not write guest state file: signature") config = sxp.to_string(dominfo.sxpr()) @@ -65,6 +65,8 @@ def save(fd, dominfo, live): dominfo.setName('migrating-' + domain_name) try: + dominfo.migrateDevices(live, dst, 1, domain_name) + write_exact(fd, pack("!i", len(config)), "could not write guest state file: config len") write_exact(fd, config, "could not write guest state file: config") @@ -85,7 +87,9 @@ def save(fd, dominfo, live): log.debug("Suspending %d ...", dominfo.getDomid()) dominfo.shutdown('suspend') dominfo.waitForShutdown() + dominfo.migrateDevices(live, dst, 2, domain_name) log.info("Domain %d suspended.", dominfo.getDomid()) + dominfo.migrateDevices(live, dst, 3, domain_name) tochild.write("done\n") tochild.flush() log.debug('Written done') Index: xen/xen-unstable.hg/tools/python/xen/xend/XendDomain.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/XendDomain.py +++ xen/xen-unstable.hg/tools/python/xen/xend/XendDomain.py @@ -405,6 +405,9 @@ class XendDomain: if dominfo.getDomid() == PRIV_DOMAIN: raise XendError("Cannot migrate privileged domain %i" % domid) + """ The following call may raise a XendError exception """ + dominfo.testMigrateDevices(live, dst) + if port == 0: port = xroot.get_xend_relocation_port() try: @@ -414,8 +417,8 @@ class XendDomain: raise XendError("can't connect: %s" % err[1]) sock.send("receive\n") - sock.recv(80) - XendCheckpoint.save(sock.fileno(), dominfo, live) + sock.recv(80) + XendCheckpoint.save(sock.fileno(), dominfo, live, dst) def domain_save(self, domid, dst): @@ -435,7 +438,7 @@ class XendDomain: fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) try: # For now we don't support 'live checkpoint' - return XendCheckpoint.save(fd, dominfo, False) + return XendCheckpoint.save(fd, dominfo, False, dst) finally: os.close(fd) except OSError, ex: Index: xen/xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py +++ xen/xen-unstable.hg/tools/python/xen/xend/XendDomainInfo.py @@ -1395,6 +1395,38 @@ class XendDomainInfo: if self.image: self.image.createDeviceModel() + ## public: + + def testMigrateDevices(self, live, dst): + """ Notify all device about intention of migration + @raise: XendError for a device that cannot be migrated + """ + for (n, c) in self.info['device']: + rc = self.migrateDevice(n, c, live, dst, 0) + if rc != 0: + raise XendError("Device of type '%s' refuses migration." % n) + + def migrateDevices(self, live, dst, step, domName=''): + """Notify the devices about migration + """ + ctr = 0 + try: + for (n, c) in self.info['device']: + self.migrateDevice(n, c, live, dst, step, domName) + ctr = ctr + 1 + except: + for (n, c) in self.info['device']: + if ctr == 0: + step = step - 1 + ctr = ctr - 1 + self.recoverMigrateDevice(n, c, live, dst, step, domName) + raise + + def migrateDevice(self, deviceClass, deviceConfig, live, dst, step, domName=''): + return self.getDeviceController(deviceClass).migrate(deviceConfig, live, dst, step, domName) + + def recoverMigrateDevice(self, deviceClass, deviceConfig, live, dst, step, domName=''): + return self.getDeviceController(deviceClass).recover_migrate(deviceConfig, live, dst, step, domName) def waitForDevices(self): """Wait for this domain's configured devices to connect. Index: xen/xen-unstable.hg/tools/python/xen/xend/server/DevController.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/server/DevController.py +++ xen/xen-unstable.hg/tools/python/xen/xend/server/DevController.py @@ -267,6 +267,41 @@ class DevController: raise NotImplementedError() + def migrate(self, deviceConfig, live, dst, step, domName): + """ Migration of a device. The 'live' parameter indicates + whether the device is live-migrated (live=1). 'dst' then gives + the hostname of the machine to migrate to. + This function is called for 4 steps: + If step == 0: Check whether the device is ready to be migrated + or can at all be migrated; return a '-1' if + the device is NOT ready, a '0' otherwise. If it is + not ready ( = not possible to migrate this device), + migration will not take place. + step == 1: Called immediately after step 0; migration + of the kernel has started; + step == 2: Called after the suspend has been issued + to the domain and the domain is not scheduled anymore. + Synchronize with what was started in step 1, if necessary. + Now the device should initiate its transfer to the + given target. Since there might be more than just + one device initiating a migration, this step should + put the process performing the transfer into the + background and return immediately to achieve as much + concurrency as possible. + step == 3: Synchronize with the migration of the device that + was initiated in step 2. + Make sure that the migration has finished and only + then return from the call. + """ + return 0 + + + def recover_migrate(self, deviceConfig, list, dst, step, domName): + """ Recover from device migration. The given step was the + last one that was successfully executed. + """ + return 0 + def getDomid(self): """Stub to {@link XendDomainInfo.getDomid}, for use by our Index: xen/xen-unstable.hg/tools/python/xen/xend/server/tpmif.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/server/tpmif.py +++ xen/xen-unstable.hg/tools/python/xen/xend/server/tpmif.py @@ -23,9 +23,17 @@ from xen.xend import sxp from xen.xend.XendLogging import log +from xen.xend.XendError import XendError +from xen.xend import XendRoot from xen.xend.server.DevController import DevController +import os +import re + + +xroot = XendRoot.instance() + class TPMifController(DevController): """TPM interface controller. Handles all TPM devices for a domain. @@ -61,3 +69,43 @@ class TPMifController(DevController): result.append(['instance', instance]) return result + + def migrate(self, deviceConfig, live, dst, step, domName): + """@see DevContoller.migrate""" + if live: + tool = xroot.get_external_migration_tool() + if tool != '': + log.info("Request to live-migrate device to %s. step=%d.", + dst, step) + + if step == 0: + """Assuming for now that everything is ok and migration + with the given tool can proceed. + """ + return 0 + else: + fd = os.popen("%s -type vtpm -step %d -host %s -domname %s" % + (tool, step, dst, domName), + 'r') + for line in fd.readlines(): + mo = re.search('Error', line) + if mo: + raise XendError("vtpm: Fatal error in migration step %d." % + step) + return 0 + else: + log.debug("External migration tool not in configuration.") + return -1 + return 0 + + def recover_migrate(self, deviceConfig, live, dst, step, domName): + """@see DevContoller.recover_migrate""" + if live: + tool = xroot.get_external_migration_tool() + if tool != '': + log.info("Request to recover live-migrated device. last good step=%d.", + step) + fd = os.popen("%s -type vtpm -step %d -host %s -domname %s -recover" % + (tool, step, dst, domName), + 'r') + return 0 Index: xen/xen-unstable.hg/tools/python/xen/xend/XendRoot.py =================================================================== --- xen.orig/xen-unstable.hg/tools/python/xen/xend/XendRoot.py +++ xen/xen-unstable.hg/tools/python/xen/xend/XendRoot.py @@ -86,6 +86,9 @@ class XendRoot: server (deprecated).""" xend_unix_server_default = 'no' + """Default external migration tool """ + external_migration_tool_default = '' + """Default path the unix-domain server listens at.""" xend_unix_path_default = '/var/lib/xend/xend-socket' @@ -250,6 +253,9 @@ class XendRoot: else: return None + def get_external_migration_tool(self): + """@return the name of the tool to handle virtual TPM migration.""" + return self.get_config_value('external-migration-tool', self.external_migration_tool_default) def get_enable_dump(self): return self.get_config_bool('enable-dump', 'no') Index: xen/xen-unstable.hg/tools/examples/xend-config.sxp =================================================================== --- xen.orig/xen-unstable.hg/tools/examples/xend-config.sxp +++ xen/xen-unstable.hg/tools/examples/xend-config.sxp @@ -127,3 +127,6 @@ # Whether to enable core-dumps when domains crash. #(enable-dump no) + +# The tool used for initiating virtual TPM migration +#(external-migration-tool '')