[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEND] Make XMLRPC Server shutdown cleanly.



# HG changeset patch
# User Alastair Tse <atse@xxxxxxxxxxxxx>
# Node ID 5fe8e9ebcf5c1da30e0da4e7f66a81de37406dc1
# Parent  52bf7bbb0f363a5d36004c78f501d1dd3270670d
[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@xxxxxxxxxxxxx>
---
 tools/python/xen/xend/server/SrvDaemon.py    |    4 +
 tools/python/xen/xend/server/SrvServer.py    |   30 +++++++++++++-
 tools/python/xen/xend/server/XMLRPCServer.py |   55 +++++++++++++++++++--------
 3 files changed, 70 insertions(+), 19 deletions(-)

diff -r 52bf7bbb0f36 -r 5fe8e9ebcf5c tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Thu Oct 05 17:29:19 2006 +0100
+++ b/tools/python/xen/xend/server/SrvDaemon.py Thu Oct 05 17:29:19 2006 +0100
@@ -195,6 +195,8 @@ class Daemon:
                                 sig)
                 else:
                     self.run(w and os.fdopen(w, 'w') or None)
+                    # if we reach here, the child should quit.
+                    os._exit(0)
 
         return ret
 
@@ -290,6 +292,8 @@ class Daemon:
             relocate.listenRelocation()
             servers = SrvServer.create()
             servers.start(status)
+            del servers
+            
         except Exception, ex:
             print >>sys.stderr, 'Exception starting xend:', ex
             if XEND_DEBUG:
diff -r 52bf7bbb0f36 -r 5fe8e9ebcf5c tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Thu Oct 05 17:29:19 2006 +0100
+++ b/tools/python/xen/xend/server/SrvServer.py Thu Oct 05 17:29:19 2006 +0100
@@ -42,6 +42,7 @@
 
 import fcntl
 import time
+import signal
 from threading import Thread
 
 from xen.web.httpserver import HttpServer, UnixHttpServer
@@ -54,7 +55,6 @@ from SrvRoot import SrvRoot
 from SrvRoot import SrvRoot
 from XMLRPCServer import XMLRPCServer
 
-
 xroot = XendRoot.instance()
 
 
@@ -65,6 +65,14 @@ class XendServers:
 
     def add(self, server):
         self.servers.append(server)
+
+    def cleanup(self, signum = 0, frame = None):
+        log.debug("SrvServer.cleanup()")
+        for server in self.servers:
+            try:
+                server.shutdown()
+            except:
+                pass
 
     def start(self, status):
         # Running the network script will spawn another process, which takes
@@ -100,8 +108,24 @@ class XendServers:
             status.write('0')
             status.close()
 
-        for t in threads:
-            t.join()
+        # Prepare to catch SIGTERM (received when 'xend stop' is executed)
+        # and call each server's cleanup if possible
+        signal.signal(signal.SIGTERM, self.cleanup)
+
+        # Interruptible Thread.join - Python Bug #1167930
+        #   Replaces: for t in threads: t.join()
+        #   Reason:   The above will cause python signal handlers to be
+        #             blocked so we're not able to catch SIGTERM in any
+        #             way for cleanup
+        runningThreads = len([t for t in threads if t.isAlive()])
+        while runningThreads > 0:
+            try:
+                for t in threads:
+                    t.join(1.0)
+                runningThreads = len([t for t in threads if t.isAlive()])
+            except:
+                pass
+
 
 def create():
     root = SrvDir()
diff -r 52bf7bbb0f36 -r 5fe8e9ebcf5c 
tools/python/xen/xend/server/XMLRPCServer.py
--- a/tools/python/xen/xend/server/XMLRPCServer.py      Thu Oct 05 17:29:19 
2006 +0100
+++ b/tools/python/xen/xend/server/XMLRPCServer.py      Thu Oct 05 17:29:19 
2006 +0100
@@ -16,16 +16,15 @@
 # Copyright (C) 2006 XenSource Ltd.
 #============================================================================
 
+from types import ListType
 import xmlrpclib
-
-from xen.xend import XendDomain, XendDomainInfo, XendNode, \
-                     XendLogging, XendDmesg
 from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
 
-from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN
-from xen.xend.XendError import *
+from xen.xend import XendDomain, XendDomainInfo, XendNode
+from xen.xend import XendLogging, XendDmesg
+from xen.xend.XendClient import XML_RPC_SOCKET
 from xen.xend.XendLogging import log
-from types import ListType
+from xen.xend.XendError import XendInvalidDomain
 
 def lookup(domid):
     info = XendDomain.instance().domain_lookup_by_name_or_id(domid)
@@ -75,8 +74,8 @@ def get_log():
     finally:
         f.close()
 
-methods = ['device_create', 'device_configure', 'destroyDevice',
-           'getDeviceSxprs',
+methods = ['device_create', 'device_configure',
+           'destroyDevice','getDeviceSxprs',
            'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown',
            'send_sysrq', 'getVCPUInfo', 'waitForDevices',
            'getRestartCount']
@@ -84,25 +83,33 @@ exclude = ['domain_create', 'domain_rest
 exclude = ['domain_create', 'domain_restore']
 
 class XMLRPCServer:
-    def __init__(self, use_tcp=False):
-        self.ready = False
+    def __init__(self, use_tcp=False, host = "localhost", port = 8006,
+                 path = XML_RPC_SOCKET):
         self.use_tcp = use_tcp
+        self.port = port
+        self.host = host
+        self.path = path
+        
+        self.ready = False        
+        self.running = True
         
     def run(self):
         if self.use_tcp:
-            # bind to something fixed for now as we may eliminate
-            # tcp support completely.
-            self.server = TCPXMLRPCServer(("localhost", 8005), 
logRequests=False)
+            self.server = TCPXMLRPCServer((self.host, self.port),
+                                          logRequests = False)
         else:
-            self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False)
+            self.server = UnixXMLRPCServer(self.path, logRequests = False)
+
+        # Legacy deprecated xm xmlrpc api
+        # --------------------------------------------------------------------
 
         # Functions in XendDomainInfo
         for name in methods:
             fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name)
             self.server.register_function(fn, "xend.domain.%s" % name)
 
-        # Functions in XendDomain
         inst = XendDomain.instance()
+
         for name in dir(inst):
             fn = getattr(inst, name)
             if name.startswith("domain_") and callable(fn):
@@ -126,4 +133,20 @@ class XMLRPCServer:
 
         self.server.register_introspection_functions()
         self.ready = True
-        self.server.serve_forever()
+
+        # Custom runloop so we can cleanup when exiting.
+        # -----------------------------------------------------------------
+        try:
+            self.server.socket.settimeout(1.0)
+            while self.running:
+                self.server.handle_request()
+        finally:
+            self.cleanup()
+
+    def cleanup(self):
+        log.debug("XMLRPCServer.cleanup()")
+
+    def shutdown(self):
+        self.running = False
+        self.ready = False
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.