diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 4e76acfdbe..650a500e8f 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -24,6 +24,7 @@ import logging import os +import socket import sys import threading @@ -35,7 +36,6 @@ from xen.xend import XendRoot from xen.xend import XendCheckpoint from xen.xend.XendError import XendError from xen.xend.XendLogging import log -from xen.xend.server import relocate from xen.xend.xenstore.xswatch import xswatch @@ -54,15 +54,16 @@ class XendDomain: ## public: def __init__(self): - # Hack alert. Python does not support mutual imports, but XendDomainInfo - # needs access to the XendDomain instance to look up domains. Attempting - # to import XendDomain from XendDomainInfo causes unbounded recursion. - # So we stuff the XendDomain instance (self) into xroot's components. - xroot.add_component("xen.xend.XendDomain", self) - self.domains = {} self.domains_lock = threading.RLock() + + # This must be called only the once, by instance() below. It is separate + # from the constructor because XendDomainInfo calls back into this class + # in order to check the uniqueness of domain names. This means that + # instance() must be able to return a valid instance of this class even + # during this initialisation. + def init(self): self.domains_lock.acquire() try: self._add_domain( @@ -389,10 +390,15 @@ class XendDomain: dominfo = self.domain_lookup(domid) port = xroot.get_xend_relocation_port() - sock = relocate.setupRelocation(dst, port) + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((dst, port)) + except socket.error, err: + raise XendError("can't connect: %s" % err[1]) + sock.send("receive\n") XendCheckpoint.save(sock.fileno(), dominfo, live) - + def domain_save(self, domid, dst): """Start saving a domain to file. @@ -527,4 +533,5 @@ def instance(): inst except: inst = XendDomain() + inst.init() return inst diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index bbc7287f82..8f01f0aef0 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -33,14 +33,14 @@ import xen.lowlevel.xc from xen.util import asserts from xen.util.blkif import blkdev_uname_to_file -from xen.xend import image -from xen.xend import sxp -from xen.xend import XendRoot +import image +import sxp +import uuid +import XendDomain +import XendRoot + from xen.xend.XendBootloader import bootloader from xen.xend.XendError import XendError, VmError -from xen.xend.XendRoot import get_component - -import uuid from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain @@ -338,9 +338,8 @@ def parseConfig(config): def domain_by_name(name): - # See comment in XendDomain constructor. - xd = get_component('xen.xend.XendDomain') - return xd.domain_lookup_by_name_nr(name) + return XendDomain.instance().domain_lookup_by_name_nr(name) + def shutdown_reason(code): """Get a shutdown reason from a code. @@ -1343,8 +1342,7 @@ class XendDomainInfo: new_dom = None try: - xd = get_component('xen.xend.XendDomain') - new_dom = xd.domain_create(config) + new_dom = XendDomain.instance().domain_create(config) new_dom.unpause() new_dom.removeVm(RESTART_IN_PROGRESS) except: diff --git a/tools/python/xen/xend/XendRoot.py b/tools/python/xen/xend/XendRoot.py index 29398df901..d94f63a58d 100644 --- a/tools/python/xen/xend/XendRoot.py +++ b/tools/python/xen/xend/XendRoot.py @@ -93,24 +93,6 @@ class XendRoot: self.configure() - def add_component(self, name, val): - """Add a xend component. - - @param name: component name - @param val: component object - """ - self.components[name] = val - - def get_component(self, name): - """Get a xend component from its name. - This is used as a work-round for problems caused by mutually - recursive imports. - - @param name: component name - @return: component object (or None) - """ - return self.components.get(name) - def _logError(self, fmt, *args): """Logging function to log to stderr. We use this for XendRoot log messages because they may be logged before the logger has been @@ -277,21 +259,3 @@ def instance(): except: inst = XendRoot() return inst - -def add_component(name, val): - """Register a component with XendRoot. - This is used to work-round import cycles. - - @param name: component name - @param val: component value (often a module) - """ - return instance().add_component(name, val) - -def get_component(name): - """Get a component. - This is used to work-round import cycles. - - @param name: component name - @return component or None - """ - return instance().get_component(name) diff --git a/tools/python/xen/xend/server/relocate.py b/tools/python/xen/xend/server/relocate.py index f7cda14ec9..c179eaf6f7 100644 --- a/tools/python/xen/xend/server/relocate.py +++ b/tools/python/xen/xend/server/relocate.py @@ -23,16 +23,12 @@ import StringIO from xen.web import protocol, tcp, unix from xen.xend import sxp -from xen.xend.XendError import XendError +from xen.xend import XendDomain from xen.xend import XendRoot +from xen.xend.XendError import XendError from xen.xend.XendLogging import log -xroot = XendRoot.instance() - - -DEBUG = 0 - class RelocationProtocol(protocol.Protocol): """Asynchronous handler for a connected relocation socket. """ @@ -111,8 +107,8 @@ class RelocationProtocol(protocol.Protocol): if self.transport: self.send_reply(["ready", name]) self.transport.sock.setblocking(1) - xd = xroot.get_component("xen.xend.XendDomain") - xd.domain_restore_fd(self.transport.sock.fileno()) + XendDomain.instance().domain_restore_fd( + self.transport.sock.fileno()) self.transport.sock.setblocking(0) else: log.error(name + ": no transport") @@ -120,6 +116,7 @@ class RelocationProtocol(protocol.Protocol): def listenRelocation(): + xroot = XendRoot.instance() if xroot.get_xend_unix_server(): path = '/var/lib/xend/relocation-socket' unix.listenUNIX(path, RelocationProtocol) @@ -128,15 +125,3 @@ def listenRelocation(): interface = xroot.get_xend_relocation_address() l = tcp.listenTCP(port, RelocationProtocol, interface=interface) l.setCloExec() - -def setupRelocation(dst, port): - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((dst, port)) - except socket.error, err: - raise XendError("can't connect: %s" % err[1]) - - sock.send("receive\n") - print sock.recv(80) - - return sock