ia64/xen-unstable

changeset 12076:5fe8e9ebcf5c

[XEND] Make XMLRPC Server shutdown cleanly.

We can now catch the end of Xend and clean up domains accordingly.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Thu Oct 05 17:29:19 2006 +0100 (2006-10-05)
parents 52bf7bbb0f36
children 48c5a79c4fbf
files tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvServer.py tools/python/xen/xend/server/XMLRPCServer.py
line diff
     1.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Thu Oct 05 17:29:19 2006 +0100
     1.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Thu Oct 05 17:29:19 2006 +0100
     1.3 @@ -195,6 +195,8 @@ class Daemon:
     1.4                                  sig)
     1.5                  else:
     1.6                      self.run(w and os.fdopen(w, 'w') or None)
     1.7 +                    # if we reach here, the child should quit.
     1.8 +                    os._exit(0)
     1.9  
    1.10          return ret
    1.11  
    1.12 @@ -290,6 +292,8 @@ class Daemon:
    1.13              relocate.listenRelocation()
    1.14              servers = SrvServer.create()
    1.15              servers.start(status)
    1.16 +            del servers
    1.17 +            
    1.18          except Exception, ex:
    1.19              print >>sys.stderr, 'Exception starting xend:', ex
    1.20              if XEND_DEBUG:
     2.1 --- a/tools/python/xen/xend/server/SrvServer.py	Thu Oct 05 17:29:19 2006 +0100
     2.2 +++ b/tools/python/xen/xend/server/SrvServer.py	Thu Oct 05 17:29:19 2006 +0100
     2.3 @@ -42,6 +42,7 @@
     2.4  
     2.5  import fcntl
     2.6  import time
     2.7 +import signal
     2.8  from threading import Thread
     2.9  
    2.10  from xen.web.httpserver import HttpServer, UnixHttpServer
    2.11 @@ -54,7 +55,6 @@ from xen.web.SrvDir import SrvDir
    2.12  from SrvRoot import SrvRoot
    2.13  from XMLRPCServer import XMLRPCServer
    2.14  
    2.15 -
    2.16  xroot = XendRoot.instance()
    2.17  
    2.18  
    2.19 @@ -66,6 +66,14 @@ class XendServers:
    2.20      def add(self, server):
    2.21          self.servers.append(server)
    2.22  
    2.23 +    def cleanup(self, signum = 0, frame = None):
    2.24 +        log.debug("SrvServer.cleanup()")
    2.25 +        for server in self.servers:
    2.26 +            try:
    2.27 +                server.shutdown()
    2.28 +            except:
    2.29 +                pass
    2.30 +
    2.31      def start(self, status):
    2.32          # Running the network script will spawn another process, which takes
    2.33          # the status fd with it unless we set FD_CLOEXEC.  Failing to do this
    2.34 @@ -100,8 +108,24 @@ class XendServers:
    2.35              status.write('0')
    2.36              status.close()
    2.37  
    2.38 -        for t in threads:
    2.39 -            t.join()
    2.40 +        # Prepare to catch SIGTERM (received when 'xend stop' is executed)
    2.41 +        # and call each server's cleanup if possible
    2.42 +        signal.signal(signal.SIGTERM, self.cleanup)
    2.43 +
    2.44 +        # Interruptible Thread.join - Python Bug #1167930
    2.45 +        #   Replaces: for t in threads: t.join()
    2.46 +        #   Reason:   The above will cause python signal handlers to be
    2.47 +        #             blocked so we're not able to catch SIGTERM in any
    2.48 +        #             way for cleanup
    2.49 +        runningThreads = len([t for t in threads if t.isAlive()])
    2.50 +        while runningThreads > 0:
    2.51 +            try:
    2.52 +                for t in threads:
    2.53 +                    t.join(1.0)
    2.54 +                runningThreads = len([t for t in threads if t.isAlive()])
    2.55 +            except:
    2.56 +                pass
    2.57 +
    2.58  
    2.59  def create():
    2.60      root = SrvDir()
     3.1 --- a/tools/python/xen/xend/server/XMLRPCServer.py	Thu Oct 05 17:29:19 2006 +0100
     3.2 +++ b/tools/python/xen/xend/server/XMLRPCServer.py	Thu Oct 05 17:29:19 2006 +0100
     3.3 @@ -16,16 +16,15 @@
     3.4  # Copyright (C) 2006 XenSource Ltd.
     3.5  #============================================================================
     3.6  
     3.7 +from types import ListType
     3.8  import xmlrpclib
     3.9 -
    3.10 -from xen.xend import XendDomain, XendDomainInfo, XendNode, \
    3.11 -                     XendLogging, XendDmesg
    3.12  from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
    3.13  
    3.14 -from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN
    3.15 -from xen.xend.XendError import *
    3.16 +from xen.xend import XendDomain, XendDomainInfo, XendNode
    3.17 +from xen.xend import XendLogging, XendDmesg
    3.18 +from xen.xend.XendClient import XML_RPC_SOCKET
    3.19  from xen.xend.XendLogging import log
    3.20 -from types import ListType
    3.21 +from xen.xend.XendError import XendInvalidDomain
    3.22  
    3.23  def lookup(domid):
    3.24      info = XendDomain.instance().domain_lookup_by_name_or_id(domid)
    3.25 @@ -75,8 +74,8 @@ def get_log():
    3.26      finally:
    3.27          f.close()
    3.28  
    3.29 -methods = ['device_create', 'device_configure', 'destroyDevice',
    3.30 -           'getDeviceSxprs',
    3.31 +methods = ['device_create', 'device_configure',
    3.32 +           'destroyDevice','getDeviceSxprs',
    3.33             'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
    3.34             'send_sysrq', 'getVCPUInfo', 'waitForDevices',
    3.35             'getRestartCount']
    3.36 @@ -84,25 +83,33 @@ methods = ['device_create', 'device_conf
    3.37  exclude = ['domain_create', 'domain_restore']
    3.38  
    3.39  class XMLRPCServer:
    3.40 -    def __init__(self, use_tcp=False):
    3.41 -        self.ready = False
    3.42 +    def __init__(self, use_tcp=False, host = "localhost", port = 8006,
    3.43 +                 path = XML_RPC_SOCKET):
    3.44          self.use_tcp = use_tcp
    3.45 +        self.port = port
    3.46 +        self.host = host
    3.47 +        self.path = path
    3.48 +        
    3.49 +        self.ready = False        
    3.50 +        self.running = True
    3.51          
    3.52      def run(self):
    3.53          if self.use_tcp:
    3.54 -            # bind to something fixed for now as we may eliminate
    3.55 -            # tcp support completely.
    3.56 -            self.server = TCPXMLRPCServer(("localhost", 8005), logRequests=False)
    3.57 +            self.server = TCPXMLRPCServer((self.host, self.port),
    3.58 +                                          logRequests = False)
    3.59          else:
    3.60 -            self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False)
    3.61 +            self.server = UnixXMLRPCServer(self.path, logRequests = False)
    3.62 +
    3.63 +        # Legacy deprecated xm xmlrpc api
    3.64 +        # --------------------------------------------------------------------
    3.65  
    3.66          # Functions in XendDomainInfo
    3.67          for name in methods:
    3.68              fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
    3.69              self.server.register_function(fn, "xend.domain.%s" % name)
    3.70  
    3.71 -        # Functions in XendDomain
    3.72          inst = XendDomain.instance()
    3.73 +
    3.74          for name in dir(inst):
    3.75              fn = getattr(inst, name)
    3.76              if name.startswith("domain_") and callable(fn):
    3.77 @@ -126,4 +133,20 @@ class XMLRPCServer:
    3.78  
    3.79          self.server.register_introspection_functions()
    3.80          self.ready = True
    3.81 -        self.server.serve_forever()
    3.82 +
    3.83 +        # Custom runloop so we can cleanup when exiting.
    3.84 +        # -----------------------------------------------------------------
    3.85 +        try:
    3.86 +            self.server.socket.settimeout(1.0)
    3.87 +            while self.running:
    3.88 +                self.server.handle_request()
    3.89 +        finally:
    3.90 +            self.cleanup()
    3.91 +
    3.92 +    def cleanup(self):
    3.93 +        log.debug("XMLRPCServer.cleanup()")
    3.94 +
    3.95 +    def shutdown(self):
    3.96 +        self.running = False
    3.97 +        self.ready = False
    3.98 +