diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 50b7afad41..b94175cd47 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -957,6 +957,7 @@ class XendConfig(dict): _set_cfg_if_exists('on_xend_stop') _set_cfg_if_exists('on_xend_start') _set_cfg_if_exists('vcpu_avail') + _set_cfg_if_exists('change_home_server') # Parse and store runtime configuration _set_cfg_if_exists('start_time') @@ -1158,6 +1159,9 @@ class XendConfig(dict): if 'cpuid_check' in self: self.cpuid_to_sxp(sxpr, 'cpuid_check') + if self.has_key('change_home_server'): + sxpr.append(['change_home_server', self['change_home_server']]) + log.debug(sxpr) return sxpr diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 336e5bc8b2..9c8516de27 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -1156,7 +1156,21 @@ class XendDomain: self.policy_lock.acquire_reader() try: - return XendCheckpoint.restore(self, fd, paused=paused, relocating=relocating) + dominfo = XendCheckpoint.restore(self, fd, paused=paused, relocating=relocating) + if relocating and \ + dominfo.info.has_key("change_home_server"): + chs = (dominfo.info["change_home_server"] == "True") + dominfo.setChangeHomeServer(None) + if chs: + self.domains_lock.acquire() + try: + log.debug("Migrating new managed domain: %s: %s" % + (dominfo.getName(), dominfo.get_uuid())) + self._managed_domain_register(dominfo) + self.managed_config_save(dominfo) + finally: + self.domains_lock.release() + return dominfo except XendError, e: log.exception("Restore failed") raise @@ -1298,7 +1312,8 @@ class XendDomain: return val - def domain_migrate(self, domid, dst, live=False, port=0, node=-1, ssl=None): + def domain_migrate(self, domid, dst, live=False, port=0, node=-1, ssl=None,\ + chs=False): """Start domain migration. @param domid: Domain ID or Name @@ -1313,6 +1328,8 @@ class XendDomain: @type node: int @keyword ssl: use ssl connection @type ssl: bool + @keyword chs: change home server for managed domain + @type chs: bool @rtype: None @raise XendError: Failed to migrate @raise XendInvalidDomain: Domain is not valid @@ -1328,6 +1345,8 @@ class XendDomain: raise VMBadState("Domain is not running", POWER_STATE_NAMES[DOM_STATE_RUNNING], POWER_STATE_NAMES[dominfo._stateGet()]) + if chs and not self.is_domain_managed(dominfo): + raise XendError("Domain is not a managed domain") """ The following call may raise a XendError exception """ dominfo.testMigrateDevices(True, dst) @@ -1339,120 +1358,131 @@ class XendDomain: if ssl is None: ssl = xoptions.get_xend_relocation_ssl() - if ssl: - from OpenSSL import SSL - from xen.web import connection - if port == 0: - port = xoptions.get_xend_relocation_ssl_port() - try: - ctx = SSL.Context(SSL.SSLv23_METHOD) - sock = SSL.Connection(ctx, - socket.socket(socket.AF_INET, socket.SOCK_STREAM)) - sock.set_connect_state() - sock.connect((dst, port)) - sock.send("sslreceive\n") - sock.recv(80) - except SSL.Error, err: - raise XendError("SSL error: %s" % err) - except socket.error, err: - raise XendError("can't connect: %s" % err) - - p2cread, p2cwrite = os.pipe() - threading.Thread(target=connection.SSLSocketServerConnection.fd2send, - args=(sock, p2cread)).start() - + try: + dominfo.setChangeHomeServer(chs) + if ssl: + self._domain_migrate_by_ssl(dominfo, dst, live, port, node) + else: + self._domain_migrate(dominfo, dst, live, port, node) + except: + dominfo.setChangeHomeServer(None) + raise + + def _domain_migrate_by_ssl(self, dominfo, dst, live, port, node): + from OpenSSL import SSL + from xen.web import connection + if port == 0: + port = xoptions.get_xend_relocation_ssl_port() + try: + ctx = SSL.Context(SSL.SSLv23_METHOD) + sock = SSL.Connection(ctx, + socket.socket(socket.AF_INET, socket.SOCK_STREAM)) + sock.set_connect_state() + sock.connect((dst, port)) + sock.send("sslreceive\n") + sock.recv(80) + except SSL.Error, err: + raise XendError("SSL error: %s" % err) + except socket.error, err: + raise XendError("can't connect: %s" % err) + + p2cread, p2cwrite = os.pipe() + threading.Thread(target=connection.SSLSocketServerConnection.fd2send, + args=(sock, p2cread)).start() + + try: try: + XendCheckpoint.save(p2cwrite, dominfo, True, live, dst, + node=node) + except Exception, ex: + m_dsterr = None try: - XendCheckpoint.save(p2cwrite, dominfo, True, live, dst, - node=node) - except Exception, ex: - m_dsterr = None - try: - sock.settimeout(3.0) - dsterr = sock.recv(1024) - sock.settimeout(None) - if dsterr: - # See send_error@relocate.py. If an error occurred - # in a destination side, an error message with the - # following form is returned from the destination - # side. - m_dsterr = \ - re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) - except: - # Probably socket.timeout exception occurred. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - - if m_dsterr: - raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) - raise - finally: - try: - sock.shutdown(2) + sock.settimeout(3.0) + dsterr = sock.recv(1024) + sock.settimeout(None) + if dsterr: + # See send_error@relocate.py. If an error occurred + # in a destination side, an error message with the + # following form is returned from the destination + # side. + m_dsterr = \ + re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) except: - # Probably the socket is already disconnected by sock.close - # in the destination side. + # Probably socket.timeout exception occurred. # Ignore the exception because it has nothing to do with # an exception of XendCheckpoint.save. pass - sock.close() - os.close(p2cread) - os.close(p2cwrite) - else: - if port == 0: - port = xoptions.get_xend_relocation_port() + if m_dsterr: + raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) + raise + finally: try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # When connecting to our ssl enabled relocation server using a - # plain socket, send will success but recv will block. Add a - # 30 seconds timeout to raise a socket.timeout exception to - # inform the client. - sock.settimeout(30.0) - sock.connect((dst, port)) - sock.send("receive\n") - sock.recv(80) - sock.settimeout(None) - except socket.error, err: - raise XendError("can't connect: %s" % err) + sock.shutdown(2) + except: + # Probably the socket is already disconnected by sock.close + # in the destination side. + # Ignore the exception because it has nothing to do with + # an exception of XendCheckpoint.save. + pass + sock.close() + os.close(p2cread) + os.close(p2cwrite) + + def _domain_migrate(self, dominfo, dst, live, port, node): + if port == 0: + port = xoptions.get_xend_relocation_port() + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # When connecting to our ssl enabled relocation server using a + # plain socket, send will success but recv will block. Add a + # 30 seconds timeout to raise a socket.timeout exception to + # inform the client. + sock.settimeout(30.0) + sock.connect((dst, port)) + sock.send("receive\n") + sock.recv(80) + sock.settimeout(None) + except socket.error, err: + raise XendError("can't connect: %s" % err) + + try: try: + XendCheckpoint.save(sock.fileno(), dominfo, True, live, + dst, node=node) + except Exception, ex: + m_dsterr = None try: - XendCheckpoint.save(sock.fileno(), dominfo, True, live, - dst, node=node) - except Exception, ex: - m_dsterr = None - try: - sock.settimeout(3.0) - dsterr = sock.recv(1024) - sock.settimeout(None) - if dsterr: - # See send_error@relocate.py. If an error occurred - # in a destination side, an error message with the - # following form is returned from the destination - # side. - m_dsterr = \ - re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) - except: - # Probably socket.timeout exception occurred. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - - if m_dsterr: - raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) - raise - finally: - try: - sock.shutdown(2) + sock.settimeout(3.0) + dsterr = sock.recv(1024) + sock.settimeout(None) + if dsterr: + # See send_error@relocate.py. If an error occurred + # in a destination side, an error message with the + # following form is returned from the destination + # side. + m_dsterr = \ + re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) except: - # Probably the socket is already disconnected by sock.close - # in the destination side. + # Probably socket.timeout exception occurred. # Ignore the exception because it has nothing to do with # an exception of XendCheckpoint.save. pass - sock.close() + + if m_dsterr: + raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) + raise + finally: + try: + sock.shutdown(2) + except: + # Probably the socket is already disconnected by sock.close + # in the destination side. + # Ignore the exception because it has nothing to do with + # an exception of XendCheckpoint.save. + pass + sock.close() def domain_save(self, domid, dst, checkpoint=False): """Start saving a domain to file. diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index fb76b47ca6..5e9f0fe6e1 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2364,6 +2364,13 @@ class XendDomainInfo: return self.getDeviceController(deviceClass).recover_migrate( deviceConfig, network, dst, step, domName) + def setChangeHomeServer(self, chs): + if chs is not None: + self.info['change_home_server'] = bool(chs) + else: + if self.info.has_key('change_home_server'): + del self.info['change_home_server'] + ## private: @@ -2870,8 +2877,10 @@ class XendDomainInfo: self._cleanup_phantom_devs(paths) self._cleanupVm() - if "transient" in self.info["other_config"] \ - and bool(self.info["other_config"]["transient"]): + if ("transient" in self.info["other_config"] and \ + bool(self.info["other_config"]["transient"])) or \ + ("change_home_server" in self.info and \ + bool(self.info["change_home_server"])): XendDomain.instance().domain_delete_by_dominfo(self) diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index ee990e0b4d..220f09198a 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -51,6 +51,10 @@ gopts.opt('ssl', short='s', fn=set_true, default=None, use="Use ssl connection for migration.") +gopts.opt('change_home_server', short='c', + fn=set_true, default=0, + use="Change home server for managed domains.") + def help(): return str(gopts) @@ -78,4 +82,5 @@ def main(argv): server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.port, opts.vals.node, - opts.vals.ssl) + opts.vals.ssl, + opts.vals.change_home_server)