aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xend
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-03-15 13:20:33 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-03-15 13:20:33 +0000
commit74851d00abd8170a7b8482f7075ea3f6ea7c49b6 (patch)
tree90c0905891f4ca857f9cda5b31163646b5ef94e7 /tools/xend
parent0b9d367cf8677be6d54c6d80e393499c99398d2f (diff)
downloadxen-74851d00abd8170a7b8482f7075ea3f6ea7c49b6.tar.gz
xen-74851d00abd8170a7b8482f7075ea3f6ea7c49b6.tar.bz2
xen-74851d00abd8170a7b8482f7075ea3f6ea7c49b6.zip
bitkeeper revision 1.796 (4055ada1c5nV7AgvKi2Y_vrxKyA7CA)
manager.py, console.py, __init__.py: new file setup.py, utils.c, main.py, Makefile: Refactor the Xen daemon. main.py: Rename: tools/xend/xend.py -> tools/xend/lib/main.py utils.c: Rename: tools/xend/xend_utils.c -> tools/xend/lib/utils.c
Diffstat (limited to 'tools/xend')
-rw-r--r--tools/xend/Makefile6
-rw-r--r--tools/xend/lib/__init__.py0
-rw-r--r--tools/xend/lib/console.py114
-rwxr-xr-xtools/xend/lib/main.py (renamed from tools/xend/xend.py)194
-rw-r--r--tools/xend/lib/manager.py39
-rw-r--r--tools/xend/lib/utils.c (renamed from tools/xend/xend_utils.c)12
-rw-r--r--tools/xend/setup.py20
7 files changed, 191 insertions, 194 deletions
diff --git a/tools/xend/Makefile b/tools/xend/Makefile
index de6aeb3982..1ea271e80e 100644
--- a/tools/xend/Makefile
+++ b/tools/xend/Makefile
@@ -5,8 +5,7 @@ all:
install: all
if [ "$(prefix)" = "" ]; then python setup.py install; \
else python setup.py install --root "$(prefix)"; fi
- install --mode=755 xend.py $(prefix)/usr/sbin
- ln -sf xend.py $(prefix)/usr/sbin/xend
+ install --mode=755 xend $(prefix)/usr/sbin
dist: all
mkdir -p ../../../../install/lib/python
@@ -14,8 +13,7 @@ dist: all
install --mode=755 $$i ../../../../install/lib/python/`basename $$i` ; \
done
python -c 'import py_compile, sys; py_compile.compile("XenoUtil.py")'
- install --mode=755 xend.py ../../../../install/sbin
- ln -sf xend.py ../../../../install/sbin/xend
+ install --mode=755 xend ../../../../install/sbin
clean:
rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm
diff --git a/tools/xend/lib/__init__.py b/tools/xend/lib/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/xend/lib/__init__.py
diff --git a/tools/xend/lib/console.py b/tools/xend/lib/console.py
new file mode 100644
index 0000000000..1b2874c696
--- /dev/null
+++ b/tools/xend/lib/console.py
@@ -0,0 +1,114 @@
+
+#############################################################
+## xend/console.py -- Console-management functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+#############################################################
+
+import errno, re, os, select, signal, socket, struct, sys
+
+
+##
+## interface:
+## Each control interface owns an instance of this class, which manages
+## the current state of the console interface. Normally a console interface
+## will be one of two state:
+## LISTENING: listening for a connection on TCP port 'self.port'
+## CONNECTED: sending/receiving console data on TCP port 'self.port'
+##
+## A dictionary of all active interfaces, indexed by TCP socket descriptor,
+## is accessible as 'interface.interface_list'.
+##
+## NB. When a class instance is to be destroyed you *must* call the 'close'
+## method. Otherwise a stale reference will eb left in the interface list.
+##
+class interface:
+
+ # The various states that a console interface may be in.
+ CLOSED = 0 # No console activity
+ LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
+ CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
+
+
+ # Dictionary of all active (non-closed) console interfaces.
+ interface_list = {}
+
+
+ # NB. 'key' is an opaque value that has no meaning in this class.
+ def __init__(self, port, key):
+ self.status = interface.CLOSED
+ self.port = port
+ self.key = key
+
+
+ # Is this interface closed (inactive)?
+ def closed(self):
+ return self.status == interface.CLOSED
+
+
+ # Is this interface listening?
+ def listening(self):
+ return self.status == interface.LISTENING
+
+
+ # Is this interface active and connected?
+ def connected(self):
+ return self.status == interface.CONNECTED
+
+
+ # Close the interface, if it is not closed already.
+ def close(self):
+ if not self.closed():
+ del interface.interface_list[self.sock.fileno()]
+ self.sock.close()
+ del self.sock
+ self.status = interface.CLOSED
+
+
+ # Move the interface into the 'listening' state. Opens a new listening
+ # socket and updates 'interface_list'.
+ def listen(self):
+ # Close old socket (if any), and create a fresh one.
+ self.close()
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+
+ try:
+ # Turn the new socket into a non-blocking listener.
+ self.sock.setblocking(False)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+ struct.pack('ii', 0, 0))
+ self.sock.bind(('', self.port))
+ self.sock.listen(1)
+
+ # Announce the new status of thsi interface.
+ self.status = interface.LISTENING
+ interface.interface_list[self.sock.fileno()] = self
+
+ except:
+ # In case of trouble ensure we get rid of dangling socket reference
+ self.sock.close()
+ del self.sock
+ raise
+
+
+ # Move a listening interface into the 'connected' state.
+ def connect(self):
+ # Pick up a new connection, if one is available.
+ try:
+ (sock, addr) = self.sock.accept()
+ except:
+ return 0
+ sock.setblocking(False)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+ struct.pack('ii', 0, 0))
+
+ # Close the listening socket.
+ self.sock.close()
+
+ # Publish the new socket and the new interface state.
+ self.sock = sock
+ self.status = interface.CONNECTED
+ interface.interface_list[self.sock.fileno()] = self
+ return 1
+
+
diff --git a/tools/xend/xend.py b/tools/xend/lib/main.py
index 313dc06575..2bf1ed246d 100755
--- a/tools/xend/xend.py
+++ b/tools/xend/lib/main.py
@@ -1,15 +1,11 @@
-#!/usr/bin/env python
-
###########################################################
## xend.py -- Xen controller daemon
## Copyright (c) 2004, K A Fraser (University of Cambridge)
###########################################################
-
import errno, re, os, pwd, select, signal, socket, struct, sys, tempfile, time
-import xend_utils, Xc
-
+import xend.console, xend.manager, xend.utils, Xc
# The following parameters could be placed in a configuration file.
@@ -20,152 +16,16 @@ CONTROL_DIR = '/var/run/xend'
UNIX_SOCK = 'management_sock' # relative to CONTROL_DIR
-
-##
-## console_interface:
-## Each control interface owns an instance of this class, which manages
-## the current state of the console interface. Normally a console interface
-## will be one of two state:
-## LISTENING: listening for a connection on TCP port 'self.port'
-## CONNECTED: sending/receiving console data on TCP port 'self.port'
-##
-## A dictionary of all active interfaces, indexed by TCP socket descriptor,
-## is accessible as 'console_interface.interface_list'.
-##
-## NB. When a class instance is to be destroyed you *must* call the 'close'
-## method. Otherwise a stale reference will eb left in the interface list.
-##
-class console_interface:
-
- # The various states that a console interface may be in.
- CLOSED = 0 # No console activity
- LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
- CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
-
-
- # Dictionary of all active (non-closed) console interfaces.
- interface_list = {}
-
-
- # NB. 'key' is an opaque value that has no meaning in this class.
- def __init__(self, port, key):
- self.status = console_interface.CLOSED
- self.port = port
- self.key = key
-
-
- # Is this interface closed (inactive)?
- def closed(self):
- return self.status == console_interface.CLOSED
-
-
- # Is this interface listening?
- def listening(self):
- return self.status == console_interface.LISTENING
-
-
- # Is this interface active and connected?
- def connected(self):
- return self.status == console_interface.CONNECTED
-
-
- # Close the interface, if it is not closed already.
- def close(self):
- if not self.closed():
- del console_interface.interface_list[self.sock.fileno()]
- self.sock.close()
- del self.sock
- self.status = console_interface.CLOSED
-
-
- # Move the interface into the 'listening' state. Opens a new listening
- # socket and updates 'interface_list'.
- def listen(self):
- # Close old socket (if any), and create a fresh one.
- self.close()
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
-
- try:
- # Turn the new socket into a non-blocking listener.
- self.sock.setblocking(False)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
- struct.pack('ii', 0, 0))
- self.sock.bind(('', self.port))
- self.sock.listen(1)
-
- # Announce the new status of thsi interface.
- self.status = console_interface.LISTENING
- console_interface.interface_list[self.sock.fileno()] = self
-
- except:
- # In case of trouble ensure we get rid of dangling socket reference
- self.sock.close()
- del self.sock
- raise
-
-
- # Move a listening interface into the 'connected' state.
- def connect(self):
- # Pick up a new connection, if one is available.
- try:
- (sock, addr) = self.sock.accept()
- except:
- return 0
- sock.setblocking(False)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
- struct.pack('ii', 0, 0))
-
- # Close the listening socket.
- self.sock.close()
-
- # Publish the new socket and the new interface state.
- self.sock = sock
- self.status = console_interface.CONNECTED
- console_interface.interface_list[self.sock.fileno()] = self
- return 1
-
-
-
-##
-## new_control_interface:
-## Create a new control interface with the specified domain 'dom'.
-## The console port may also be specified; otehrwise a suitable port is
-## automatically allocated.
-##
-def new_control_interface(dom, console_port=-1):
- # Allocate an event channel. Clear pending notifications.
- port = xend_utils.port(dom)
- notifier.clear(port.local_port, notifier.NORMAL)
- notifier.clear(port.local_port, notifier.DISCONNECT)
-
- # If necessary, compute a suitable TCP port for console I/O.
- if console_port < 0:
- console_port = 9600 + port.local_port
-
- # Create a listenign console interface.
- con_if = console_interface(console_port, port.local_port)
- con_if.listen()
-
- # Add control state to the master list.
- control_list[port.local_port] = \
- (port, xend_utils.buffer(), xend_utils.buffer(), con_if)
-
- # Construct the successful response to be returned to the requester.
- response = { 'success': True }
- response['local_port'] = port.local_port
- response['remote_port'] = port.remote_port
- response['console_port'] = console_port
- return response
-
-
-
def daemon_loop():
+ # Could we do this more nicely? The xend.manager functions need access
+ # to this global state to do their work.
global control_list, notifier
- xc = Xc.new()
+ # List of all control interfaces, indexed by local event-channel port.
control_list = {}
+ xc = Xc.new()
+
# Ignore writes to disconnected sockets. We clean up differently.
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
@@ -179,7 +39,11 @@ def daemon_loop():
management_interface.setblocking(False)
management_interface.bind(CONTROL_DIR+'/'+UNIX_SOCK)
- notifier = xend_utils.notifier()
+ # Interface via which we receive event notifications from other guest
+ # OSes. This interface also allows us to clear/acknowledge outstanding
+ # notifications --- successive notifications for the same channel are
+ # dropped until the first notification is cleared.
+ notifier = xend.utils.notifier()
##
## MAIN LOOP
@@ -218,7 +82,7 @@ def daemon_loop():
# Evaluate the request in an exception-trapping sandbox.
try:
print "Mgmt_req[%s]: %s" % (addr, data)
- response = str(eval(data))
+ response = str(eval('xend.manager.'+data))
except:
# Catch all exceptions and turn into an error response:
@@ -242,9 +106,9 @@ def daemon_loop():
# Do work for every console interface that hit in the poll set.
for (fd, events) in fdset:
- if not console_interface.interface_list.has_key(fd):
+ if not xend.console.interface.interface_list.has_key(fd):
continue
- con_if = console_interface.interface_list[fd]
+ con_if = xend.console.interface.interface_list[fd]
# If the interface is listening, check for pending connections.
if con_if.listening():
@@ -290,7 +154,7 @@ def daemon_loop():
# and notify the remote end.
work_done = False
while not wbuf.empty() and port.space_to_write_request():
- msg = xend_utils.message(0, 0, 0)
+ msg = xend.utils.message(0, 0, 0)
msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
port.write_request(msg)
work_done = True
@@ -347,7 +211,7 @@ def daemon_loop():
# Send as much pending console data as there is room for.
while not wbuf.empty() and port.space_to_write_request():
- msg = xend_utils.message(0, 0, 0)
+ msg = xend.utils.message(0, 0, 0)
msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
port.write_request(msg)
work_done = True
@@ -401,7 +265,7 @@ def start_daemon():
return 1
# Ensure that zombie children are automatically reaped.
- xend_utils.autoreap()
+ xend.utils.autoreap()
# Fork -- parent writes the PID file and exits.
pid = os.fork()
@@ -428,27 +292,3 @@ def start_daemon():
def stop_daemon():
return cleanup_daemon(kill=True)
-
-
-
-def main():
- xend_utils.autoreap()
- if not sys.argv[1:]:
- print 'usage: %s {start|stop|restart}' % sys.argv[0]
- elif os.fork():
- pid, status = os.wait()
- return status >> 8
- elif sys.argv[1] == 'start':
- return start_daemon()
- elif sys.argv[1] == 'stop':
- return stop_daemon()
- elif sys.argv[1] == 'restart':
- return stop_daemon() or start_daemon()
- else:
- print 'not an option:', sys.argv[1]
- return 1
-
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/xend/lib/manager.py b/tools/xend/lib/manager.py
new file mode 100644
index 0000000000..092caa02fc
--- /dev/null
+++ b/tools/xend/lib/manager.py
@@ -0,0 +1,39 @@
+
+#############################################################
+## xend/manager.py -- Management-interface functions for Xend
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+#############################################################
+
+import xend.console, xend.main, xend.utils
+
+
+##
+## new_control_interface:
+## Create a new control interface with the specified domain 'dom'.
+## The console port may also be specified; otehrwise a suitable port is
+## automatically allocated.
+##
+def new_control_interface(dom, console_port=-1):
+ # Allocate an event channel. Clear pending notifications.
+ port = xend.utils.port(dom)
+ xend.main.notifier.clear(port.local_port, xend.main.notifier.NORMAL)
+ xend.main.notifier.clear(port.local_port, xend.main.notifier.DISCONNECT)
+
+ # If necessary, compute a suitable TCP port for console I/O.
+ if console_port < 0:
+ console_port = 9600 + port.local_port
+
+ # Create a listenign console interface.
+ con_if = xend.console.interface(console_port, port.local_port)
+ con_if.listen()
+
+ # Add control state to the master list.
+ xend.main.control_list[port.local_port] = \
+ (port, xend.utils.buffer(), xend.utils.buffer(), con_if)
+
+ # Construct the successful response to be returned to the requester.
+ response = { 'success': True }
+ response['local_port'] = port.local_port
+ response['remote_port'] = port.remote_port
+ response['console_port'] = console_port
+ return response
diff --git a/tools/xend/xend_utils.c b/tools/xend/lib/utils.c
index 81b101e5c8..de832a1761 100644
--- a/tools/xend/xend_utils.c
+++ b/tools/xend/lib/utils.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * xend_utils.c
+ * utils.c
*
* Copyright (c) 2004, K A Fraser
*/
@@ -409,7 +409,7 @@ static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
{
- PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
+ PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
return NULL;
}
@@ -467,7 +467,7 @@ static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
{
- PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
+ PyErr_SetString(PyExc_TypeError, "expected a xend.utils.message");
return NULL;
}
@@ -994,13 +994,13 @@ static PyMethodDef xu_methods[] = {
{ NULL, NULL, 0, NULL }
};
-PyMODINIT_FUNC initxend_utils(void)
+PyMODINIT_FUNC initutils(void)
{
PyObject *m, *d;
- m = Py_InitModule("xend_utils", xu_methods);
+ m = Py_InitModule("xend.utils", xu_methods);
d = PyModule_GetDict(m);
- port_error = PyErr_NewException("xend_utils.PortError", NULL, NULL);
+ port_error = PyErr_NewException("xend.utils.PortError", NULL, NULL);
PyDict_SetItemString(d, "PortError", port_error);
}
diff --git a/tools/xend/setup.py b/tools/xend/setup.py
index 9bc967785f..3dc84d61fa 100644
--- a/tools/xend/setup.py
+++ b/tools/xend/setup.py
@@ -1,11 +1,17 @@
from distutils.core import setup, Extension
-module = Extension("xend_utils",
- include_dirs = ["../xc/lib",
- "../../xenolinux-sparse/include"],
- library_dirs = ["../xc/lib"],
- libraries = ["xc"],
- sources = ["xend_utils.c"])
+utils = Extension("utils",
+ include_dirs = ["../xc/lib",
+ "../../xenolinux-sparse/include"],
+ library_dirs = ["../xc/lib"],
+ libraries = ["xc"],
+ sources = ["lib/utils.c"])
-setup(name = "xend_utils", version = "1.0", ext_modules = [module])
+setup(name = "xend",
+ version = "1.0",
+ packages = ["xend"],
+ package_dir = { "xend" : "lib" },
+ ext_package = "xend",
+ ext_modules = [ utils ]
+ )