# 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
|