[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>
This commit is contained in:
Alastair Tse committed 2006-10-05 17:29:19 +01:00
1 parent d03a635aec
commit ef46d763af
3 files changed
+70 -19

No files matched your search

@@ -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:
+27 -3
View File
@@ -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 xen.web.SrvDir import SrvDir
from SrvRoot import SrvRoot
from XMLRPCServer import XMLRPCServer
xroot = XendRoot.instance()
@@ -66,6 +66,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
# the status fd with it unless we set FD_CLOEXEC. Failing to do this
@@ -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()
+39 -16
View File
@@ -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 @@ methods = ['device_create', 'device_configure', 'destroyDevice',
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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.