Sorry, forgot patch.
Anthony Liguori wrote:
The attached patch removes all of the console handling code from Xend
and changes xm to simply exec /usr/libexec/xen/xc_console.
I've done a pretty good amount of testing and this seems to clear up
all of the Xend console issues in bugzilla.
This is a pretty big change to Xend though with a lot of deleted code
so I'd appreciate if people more familiar with the Xend codebase could
look through it critically.
In addition to the patch, the following files are no longer used:
tools/python/xen/util/console_client.py
tools/python/xen/xend/XendConsole.py
tools/python/xen/xend/server/SrvConsole.py
tools/python/xen/xend/server/SrvConsoleDir.py
tools/python/xen/xend/server/console.py
Regards,
Anthony Liguori
Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
diff -r 60c4cd9ebaa1 tools/Makefile
--- a/tools/Makefile Wed Aug 3 16:11:32 2005
+++ b/tools/Makefile Wed Aug 3 16:19:56 2005
@@ -13,7 +13,7 @@
#SUBDIRS += pygrub
SUBDIRS += firmware
SUBDIRS += security
-#SUBDIRS += consoled
+SUBDIRS += consoled
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
diff -r 60c4cd9ebaa1 tools/misc/xend
--- a/tools/misc/xend Wed Aug 3 16:11:32 2005
+++ b/tools/misc/xend Wed Aug 3 16:19:56 2005
@@ -130,6 +130,8 @@
return status >> 8
elif sys.argv[1] == 'start':
start_xcs()
+ if os.fork() == 0:
+ os.execvp('/usr/sbin/consoled', ['/usr/sbin/consoled']);
return daemon.start()
elif sys.argv[1] == 'trace_start':
start_xcs()
diff -r 60c4cd9ebaa1 tools/python/xen/xend/XendClient.py
--- a/tools/python/xen/xend/XendClient.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/XendClient.py Wed Aug 3 16:19:56 2005
@@ -5,9 +5,7 @@
Supports inet or unix connection to xend.
This API is the 'control-plane' for xend.
-The 'data-plane' is done separately. For example, consoles
-are accessed via sockets on xend, but the list of consoles
-is accessible via this API.
+The 'data-plane' is done separately.
"""
import os
import sys
@@ -145,9 +143,6 @@
def domainurl(self, id=''):
return self.url.relative('domain/' + str(id))
-
- def consoleurl(self, id=''):
- return self.url.relative('console/' + str(id))
def deviceurl(self, id=''):
return self.url.relative('device/' + str(id))
@@ -317,16 +312,6 @@
{'op' : 'device_configure',
'idx' : idx,
'config' : fileof(config) })
-
- def xend_consoles(self):
- return self.xendGet(self.consoleurl())
-
- def xend_console(self, id):
- return self.xendGet(self.consoleurl(id))
-
- def xend_console_disconnect(self, id):
- return self.xendPost(self.consoleurl(id),
- {'op' : 'disconnect'})
def xend_vnets(self):
return self.xendGet(self.vneturl())
diff -r 60c4cd9ebaa1 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Wed Aug 3 16:19:56 2005
@@ -268,7 +268,6 @@
self.restart_time = None
self.restart_count = 0
- self.console_port = None
self.vcpus = 1
self.bootloader = None
@@ -344,9 +343,6 @@
s += " name=" + self.name
s += " memory=" + str(self.memory)
s += " ssidref=" + str(self.ssidref)
- console = self.getConsole()
- if console:
- s += " console=" + str(console.console_port)
s += ">"
return s
@@ -443,9 +439,6 @@
sxpr.append(self.store_channel.sxpr())
if self.store_mfn:
sxpr.append(['store_mfn', self.store_mfn])
- console = self.getConsole()
- if console:
- sxpr.append(console.sxpr())
if self.restart_count:
sxpr.append(['restart_count', self.restart_count])
@@ -519,7 +512,6 @@
# Create domain devices.
self.configure_backends()
- self.configure_console()
self.configure_restart()
self.construct_image()
self.configure()
@@ -785,17 +777,6 @@
"""
self.bootloader = sxp.child_value(self.config, "bootloader")
- def configure_console(self):
- """Configure the vm console port.
- """
- x = sxp.child_value(self.config, 'console')
- if x:
- try:
- port = int(x)
- except:
- raise VmError('invalid console:' + str(x))
- self.console_port = port
-
def configure_restart(self):
"""Configure the vm restart mode.
"""
@@ -855,7 +836,7 @@
def restart(self):
"""Restart the domain after it has exited.
- Reuses the domain id and console port.
+ Reuses the domain id
"""
try:
@@ -910,24 +891,8 @@
"""
self.configure_fields()
- self.create_console()
self.create_devices()
self.create_blkif()
-
- def create_console(self):
- console = self.getConsole()
- if not console:
- config = ['console']
- if self.console_port:
- config.append(['console_port', self.console_port])
- console = self.createDevice('console', config)
- return console
-
- def getConsole(self):
- console_ctrl = self.getDeviceController("console", error=False)
- if console_ctrl:
- return console_ctrl.getDevice(0)
- return None
def create_blkif(self):
"""Create the block device interface (blkif) for the vm.
@@ -1048,7 +1013,6 @@
add_config_handler('ssidref', vm_field_ignore)
add_config_handler('cpu', vm_field_ignore)
add_config_handler('cpu_weight', vm_field_ignore)
-add_config_handler('console', vm_field_ignore)
add_config_handler('restart', vm_field_ignore)
add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
@@ -1062,9 +1026,6 @@
#============================================================================
# Register device controllers and their device config types.
-from server import console
-controller.addDevControllerClass("console", console.ConsoleController)
-
from server import blkif
controller.addDevControllerClass("vbd", blkif.BlkifController)
add_device_handler("vbd", "vbd")
diff -r 60c4cd9ebaa1 tools/python/xen/xend/XendRoot.py
--- a/tools/python/xen/xend/XendRoot.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/XendRoot.py Wed Aug 3 16:19:56 2005
@@ -69,12 +69,6 @@
"""Default path the unix-domain server listens at."""
xend_unix_path_default = '/var/lib/xend/xend-socket'
-
- """Default interface address xend listens at for consoles."""
- console_address_default = 'localhost'
-
- """Default port xend serves consoles at. """
- console_port_base_default = '9600'
dom0_min_mem_default = '0'
@@ -302,19 +296,6 @@
"""
return self.get_config_value("xend-unix-path",
self.xend_unix_path_default)
- def get_console_address(self):
- """Get the address xend listens at for its console ports.
- This defaults to 'localhost', allowing only the localhost to connect
- to the console ports. Setting this to the empty string, allows all
- hosts to connect.
- """
- return self.get_config_value('console-address',
self.console_address_default)
-
- def get_console_port_base(self):
- """Get the base port number used to generate console ports for domains.
- """
- return self.get_config_int('console-port-base',
self.console_port_base_default)
-
def get_block_script(self, type):
return self.get_config_value('block-%s' % type, '')
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/server/SrvDomain.py Wed Aug 3 16:19:56 2005
@@ -4,7 +4,6 @@
from xen.xend import sxp
from xen.xend import XendDomain
-from xen.xend import XendConsole
from xen.xend import PrettyPrint
from xen.xend.Args import FormFn
@@ -18,7 +17,6 @@
SrvDir.__init__(self)
self.dom = dom
self.xd = XendDomain.instance()
- self.xconsole = XendConsole.instance()
def op_configure(self, op, req):
"""Configure an existing domain.
@@ -208,14 +206,6 @@
self.print_path(req)
#self.ls()
req.write('<p>%s</p>' % self.dom)
- if self.dom.console:
- cinfo = self.dom.console
- cid = str(cinfo.console_port)
- #todo: Local xref: need to know server prefix.
- req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
- % (cid, cid))
- req.write('<p><a href="%s">Connect to console</a></p>'
- % cinfo.uri())
if self.dom.config:
req.write("<code><pre>")
PrettyPrint.prettyprint(self.dom.config, out=req)
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvRoot.py
--- a/tools/python/xen/xend/server/SrvRoot.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/server/SrvRoot.py Wed Aug 3 16:19:56 2005
@@ -15,7 +15,6 @@
subdirs = [
('node', 'SrvNode' ),
('domain', 'SrvDomainDir' ),
- ('console', 'SrvConsoleDir' ),
('vnet', 'SrvVnetDir' ),
]
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/server/SrvServer.py Wed Aug 3 16:19:56 2005
@@ -1,7 +1,7 @@
#!/usr/bin/python
# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
-"""Example xend HTTP and console server.
+"""Example xend HTTP
Can be accessed from a browser or from a program.
Do 'python SrvServer.py' to run the server.
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/event.py
--- a/tools/python/xen/xend/server/event.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/server/event.py Wed Aug 3 16:19:56 2005
@@ -128,16 +128,8 @@
def op_pretty(self, name, req):
self.pretty = 1
- def op_console_disconnect(self, name, req):
- id = sxp.child_value(req, 'id')
- if not id:
- raise XendError('Missing console id')
- id = int(id)
- self.daemon.console_disconnect(id)
-
def op_info(self, name, req):
val = ['info']
- #val += self.daemon.consoles()
#val += self.daemon.blkifs()
#val += self.daemon.netifs()
#val += self.daemon.usbifs()
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/messages.py
--- a/tools/python/xen/xend/server/messages.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xend/server/messages.py Wed Aug 3 16:19:56 2005
@@ -16,16 +16,6 @@
See below.
"""
msg_formats = {}
-
-#============================================================================
-# Console message types.
-#============================================================================
-
-CMSG_CONSOLE = 0
-
-console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
-
-msg_formats.update(console_formats)
#============================================================================
# Block interface message types.
diff -r 60c4cd9ebaa1 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xm/create.py Wed Aug 3 16:19:56 2005
@@ -7,6 +7,7 @@
import string
import sys
import socket
+import commands
import xen.lowlevel.xc
@@ -16,8 +17,6 @@
from xen.xend.XendBootloader import bootloader
from xen.xend import XendRoot; xroot = XendRoot.instance()
from xen.util import blkif
-
-from xen.util import console_client
from xen.xm.opts import *
@@ -144,10 +143,6 @@
fn=set_float, default=None,
use="""Set the new domain's cpu weight.
WEIGHT is a float that controls the domain's share of the cpu.""")
-
-gopts.var('console', val='PORT',
- fn=set_int, default=None,
- use="Console port to use. Default is 9600 + domain id.")
gopts.var('restart', val='onreboot|always|never',
fn=set_value, default=None,
@@ -471,8 +466,6 @@
config.append(['backend', ['netif']])
if vals.restart:
config.append(['restart', vals.restart])
- if vals.console:
- config.append(['console', vals.console])
if vals.bootloader:
run_bootloader(opts, config, vals)
@@ -620,8 +613,8 @@
@param opts: options
@param config: configuration
- @return: domain id, console port
- @rtype: (int, int)
+ @return: domain id
+ @rtype: int
"""
try:
@@ -634,19 +627,13 @@
opts.err(str(ex))
dom = sxp.child_value(dominfo, 'name')
- console_info = sxp.child(dominfo, 'console')
- if console_info:
- console_port = int(sxp.child_value(console_info, 'console_port'))
- else:
- console_port = None
if not opts.vals.paused:
if server.xend_domain_unpause(dom) < 0:
server.xend_domain_destroy(dom)
opts.err("Failed to unpause domain %s" % dom)
- opts.info("Started domain %s, console on port %d"
- % (dom, console_port))
- return (dom, console_port)
+ opts.info("Started domain %s" % (dom))
+ return int(sxp.child_value(dominfo, 'id'))
def get_dom0_alloc():
"""Return current allocation memory of dom0 (in MB). Return 0 on error"""
@@ -709,10 +696,10 @@
if dom0_min_mem != 0:
balloon_out(dom0_min_mem, opts)
- (dom, console) = make_domain(opts, config)
+ dom = make_domain(opts, config)
if opts.vals.console_autoconnect:
- path = "/var/lib/xend/console-%s" % console
- console_client.connect('localhost', console, path=path)
+ cmd = "/usr/libexec/xen/xc_console %d" % dom
+ os.execvp('/usr/libexec/xen/xc_console', cmd.split())
if __name__ == '__main__':
main(sys.argv)
diff -r 60c4cd9ebaa1 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Wed Aug 3 16:11:32 2005
+++ b/tools/python/xen/xm/main.py Wed Aug 3 16:19:56 2005
@@ -4,6 +4,7 @@
import os
import os.path
import sys
+import commands
from getopt import getopt
import socket
import warnings
@@ -390,7 +391,7 @@
self.brief_list(doms)
def brief_list(self, doms):
- print 'Name Id Mem(MB) CPU VCPU(s) State Time(s)
Console'
+ print 'Name Id Mem(MB) CPU VCPU(s) State Time(s)'
for dom in doms:
info = server.xend_domain(dom)
d = {}
@@ -401,19 +402,14 @@
d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
d['state'] = sxp.child_value(info, 'state', '??')
d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
- console = sxp.child(info, 'console')
- if console:
- d['port'] = sxp.child_value(console, 'console_port')
- else:
- d['port'] = ''
if d['vcpus'] > 1:
d['cpu'] = '-'
if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
d['ssidref1'] = int(sxp.child_value(info, 'ssidref', '0')) &
0xffff
d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >>
16) & 0xffff
- print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d
%(state)5s %(cpu_time)7.1f %(port)4s s:%(ssidref2)02x/p:%(ssidref1)02x"
% d)
+ print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d
%(state)5s %(cpu_time)7.1f %s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
else:
- print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d
%(state)5s %(cpu_time)7.1f %(port)4s" % d)
+ print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d
%(state)5s %(cpu_time)7.1f" % d)
def show_vcpus(self, doms):
print 'Name Id VCPU CPU CPUMAP'
@@ -699,29 +695,6 @@
xm.prog(ProgInfo)
-class ProgConsoles(Prog):
- group = 'console'
- name = "consoles"
- info = """Get information about domain consoles."""
-
- def main(self, args):
- l = server.xend_consoles()
- print "Dom Port Id Connection"
- for x in l:
- info = server.xend_console(x)
- d = {}
- d['dom'] = sxp.child(info, 'domain', '?')[1]
- d['port'] = sxp.child_value(info, 'console_port', '?')
- d['id'] = sxp.child_value(info, 'id', '?')
- connected = sxp.child(info, 'connected')
- if connected:
- d['conn'] = '%s:%s' % (connected[1], connected[2])
- else:
- d['conn'] = ''
- print "%(dom)3s %(port)4s %(id)3s %(conn)s" % d
-
-xm.prog(ProgConsoles)
-
class ProgConsole(Prog):
group = 'console'
name = "console"
@@ -735,13 +708,9 @@
if len(args) < 2: self.err("%s: Missing domain" % args[0])
dom = args[1]
info = server.xend_domain(dom)
- console = sxp.child(info, "console")
- if not console:
- self.err("No console information")
- port = sxp.child_value(console, "console_port")
- from xen.util import console_client
- path = "/var/lib/xend/console-%s" % port
- console_client.connect("localhost", int(port), path=path)
+ domid = int(sxp.child_value(info, 'id', '-1'))
+ cmd = "/usr/libexec/xen/xc_console %d" % domid
+ os.execvp('/usr/libexec/xen/xc_console', cmd.split())
xm.prog(ProgConsole)
diff -r 60c4cd9ebaa1 tools/python/xen/util/console_client.py
--- a/tools/python/xen/util/console_client.py Wed Aug 3 16:11:32 2005
+++ /dev/null Wed Aug 3 16:19:56 2005
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-
-##############################################
-# Console client for Xen guest OSes
-# Copyright (c) 2004, K A Fraser
-##############################################
-
-import errno, os, signal, socket, struct, sys
-
-from termios import *
-# Indexes into termios.tcgetattr() list.
-IFLAG = 0
-OFLAG = 1
-CFLAG = 2
-LFLAG = 3
-ISPEED = 4
-OSPEED = 5
-CC = 6
-
-def __child_death(signum, frame):
- global stop
- stop = True
-
-def __recv_from_sock(sock):
- global stop
- stop = False
- while not stop:
- try:
- data = sock.recv(1024)
- except socket.error, error:
- if error[0] != errno.EINTR:
- raise
- else:
- try:
- os.write(1, data)
- except os.error, error:
- if error[0] != errno.EINTR:
- raise
- os.wait()
-
-def __send_to_sock(sock):
- while 1:
- try:
- data = os.read(0,1024)
- except os.error, error:
- if error[0] != errno.EINTR:
- raise
- else:
- if ord(data[0]) == ord(']')-64:
- break
- try:
- sock.send(data)
- except socket.error, error:
- if error[0] == errno.EPIPE:
- sys.exit(0)
- if error[0] != errno.EINTR:
- raise
- sys.exit(0)
-
-def connect(host, port, path=None):
- # Try inet first. If 'path' is given and the error
- # was connection refused, try unix-domain on 'path'.
- try:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect((host, port))
- except socket.error, err:
- if (path is None) or (err[0] != errno.ECONNREFUSED):
- raise
- # Try unix-domain.
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.connect(path)
-
- oattrs = tcgetattr(0)
- nattrs = tcgetattr(0)
- nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
- nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
- nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
- nattrs[CFLAG] = nattrs[CFLAG] | CS8
- nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
- nattrs[CC][VMIN] = 1
- nattrs[CC][VTIME] = 0
-
- if os.fork():
- signal.signal(signal.SIGCHLD, __child_death)
- print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
- tcsetattr(0, TCSAFLUSH, nattrs)
- try:
- __recv_from_sock(sock)
- finally:
- tcsetattr(0, TCSAFLUSH, oattrs)
- print
- print "************ REMOTE CONSOLE EXITED *****************"
- else:
- signal.signal(signal.SIGPIPE, signal.SIG_IGN)
- __send_to_sock(sock)
-
-if __name__ == '__main__':
- argc = len(sys.argv)
- if argc < 3 or argc > 4:
- print >>sys.stderr, sys.argv[0], "<host> <port> [<path>]"
- sys.exit(1)
- host = sys.argv[1]
- port = int(sys.argv[2])
- if argc > 3:
- path = sys.argv[3]
- else:
- path = None
- connect(host, port, path=path)
diff -r 60c4cd9ebaa1 tools/python/xen/xend/XendConsole.py
--- a/tools/python/xen/xend/XendConsole.py Wed Aug 3 16:11:32 2005
+++ /dev/null Wed Aug 3 16:19:56 2005
@@ -1,44 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
-
-import XendRoot; xroot = XendRoot.instance()
-from XendError import XendError
-
-class XendConsole:
-
- def __init__(self):
- pass
-
- def console_ls(self):
- return [ c.console_port for c in self.consoles() ]
-
- def consoles(self):
- l = []
- xd = XendRoot.get_component('xen.xend.XendDomain')
- for vm in xd.list():
- ctrl = vm.getDeviceController("console", error=False)
- if (not ctrl): continue
- console = ctrl.getDevice(0)
- if (not console): continue
- l.append(console)
- return l
-
- def console_get(self, id):
- id = int(id)
- for c in self.consoles():
- if c.console_port == id:
- return c
- return None
-
- def console_disconnect(self, id):
- console = self.console_get(id)
- if not console:
- raise XendError('Invalid console id')
- console.disconnect()
-
-def instance():
- global inst
- try:
- inst
- except:
- inst = XendConsole()
- return inst
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvConsole.py
--- a/tools/python/xen/xend/server/SrvConsole.py Wed Aug 3 16:11:32 2005
+++ /dev/null Wed Aug 3 16:19:56 2005
@@ -1,41 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
-
-from xen.xend import sxp
-from xen.xend import XendConsole
-from xen.web.SrvDir import SrvDir
-
-class SrvConsole(SrvDir):
- """An individual console.
- """
-
- def __init__(self, info):
- SrvDir.__init__(self)
- self.info = info
- self.xc = XendConsole.instance()
-
- def op_disconnect(self, op, req):
- val = self.xc.console_disconnect(self.info.console_port)
- return val
-
- def render_POST(self, req):
- return self.perform(req)
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- sxp.show(self.info.sxpr(), out=req)
- else:
- req.write('<html><head></head><body>')
- self.print_path(req)
- #self.ls()
- req.write('<p>%s</p>' % self.info)
- req.write('<p><a href="%s">Connect to domain %d</a></p>'
- % (self.info.uri(), self.info.id))
- self.form(req)
- req.write('</body></html>')
-
- def form(self, req):
- req.write('<form method="post" action="%s">' % req.prePathURL())
- if self.info.connected():
- req.write('<input type="submit" name="op" value="disconnect">')
- req.write('</form>')
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvConsoleDir.py
--- a/tools/python/xen/xend/server/SrvConsoleDir.py Wed Aug 3 16:11:32 2005
+++ /dev/null Wed Aug 3 16:19:56 2005
@@ -1,59 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
-
-from xen.web.SrvDir import SrvDir
-from SrvConsole import SrvConsole
-from xen.xend import XendConsole
-from xen.xend import sxp
-
-class SrvConsoleDir(SrvDir):
- """Console directory.
- """
-
- def __init__(self):
- SrvDir.__init__(self)
- self.xconsole = XendConsole.instance()
-
- def console(self, x):
- val = None
- try:
- info = self.xconsole.console_get(x)
- val = SrvConsole(info)
- except KeyError, ex:
- print 'SrvConsoleDir>', ex
- pass
- return val
-
- def get(self, x):
- v = SrvDir.get(self, x)
- if v is not None:
- return v
- v = self.console(x)
- return v
-
- def render_GET(self, req):
- if self.use_sxp(req):
- req.setHeader("Content-Type", sxp.mime_type)
- self.ls_console(req, 1)
- else:
- req.write("<html><head></head><body>")
- self.print_path(req)
- self.ls(req)
- self.ls_console(req)
- #self.form(req.wfile)
- req.write("</body></html>")
-
- def ls_console(self, req, use_sxp=0):
- url = req.prePathURL()
- if not url.endswith('/'):
- url += '/'
- if use_sxp:
- consoles = self.xconsole.console_ls()
- sxp.show(consoles, out=req)
- else:
- consoles = self.xconsole.consoles()
- consoles.sort(lambda x, y: cmp(x.console_port, y.console_port))
- req.write('<ul>')
- for c in consoles:
- cid = str(c.console_port)
- req.write('<li><a href="%s%s"> %s</a></li>' % (url, cid, cid))
- req.write('</ul>')
diff -r 60c4cd9ebaa1 tools/python/xen/xend/server/console.py
--- a/tools/python/xen/xend/server/console.py Wed Aug 3 16:11:32 2005
+++ /dev/null Wed Aug 3 16:19:56 2005
@@ -1,391 +0,0 @@
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
-
-import socket
-import threading
-from errno import EAGAIN, EINTR, EWOULDBLOCK
-
-from xen.web import reactor, protocol
-
-from xen.lowlevel import xu
-
-from xen.xend.XendError import XendError
-from xen.xend import EventServer; eserver = EventServer.instance()
-from xen.xend.XendLogging import log
-from xen.xend import XendRoot; xroot = XendRoot.instance()
-from xen.xend import sxp
-from xen.xend.xenstore import DBVar
-
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
-from xen.xend.server.params import *
-
-class ConsoleProtocol(protocol.Protocol):
- """Asynchronous handler for a console socket.
- """
-
- def __init__(self, console, id):
- self.console = console
- self.id = id
- self.addr = None
-
- def connectionMade(self, addr=None):
- peer = self.transport.getPeer()
- self.addr = addr
- if self.console.connect(self.addr, self):
- self.transport.write("Cannot connect to console %d on domain %d\n"
- % (self.id, self.console.getDomain()))
- self.loseConnection()
- return
- else:
- if len(self.addr) == 2:
- host = str(self.addr[0])
- port = str(self.addr[1])
- else:
- host = 'localhost'
- port = str(addr)
- log.info("Console connected %s %s %s",
- self.id, host, port)
- eserver.inject('xend.console.connect',
- [self.id, host, port])
-
- def dataReceived(self, data):
- if self.console.receiveInput(self, data):
- self.loseConnection()
-
- def write(self, data):
- self.transport.write(data)
- return len(data)
-
- def connectionLost(self, reason=None):
- log.info("Console disconnected %s %s %s",
- str(self.id), str(self.addr[0]), str(self.addr[1]))
- eserver.inject('xend.console.disconnect',
- [self.id, self.addr[0], self.addr[1]])
- self.console.disconnect(conn=self)
-
- def loseConnection(self):
- self.transport.loseConnection()
-
-class ConsoleDev(Dev, protocol.ServerFactory):
- """Console device for a domain.
- Does not poll for i/o itself, but relies on the domain to post console
- output and the connected TCP sockets to post console input.
- """
-
- STATUS_NEW = 'new'
- STATUS_CLOSED = 'closed'
- STATUS_CONNECTED = 'connected'
- STATUS_LISTENING = 'listening'
-
- __exports__ = Dev.__exports__ + [
- DBVar('status', ty='str'),
- #DBVar('listening', ty='str'),
- DBVar('console_port', ty='int'),
- ]
-
- def __init__(self, controller, id, config, recreate=False):
- Dev.__init__(self, controller, id, config)
- self.lock = threading.RLock()
- self.status = self.STATUS_NEW
- self.addr = None
- self.conn = None
- self.console_port = None
- self.obuf = xu.buffer()
- self.ibuf = xu.buffer()
- self.channel = None
- self.listening = False
- self.unix_listener = None
- self.tcp_listener = None
-
- console_port = sxp.child_value(self.config, "console_port")
- if console_port is None:
- console_port = xroot.get_console_port_base() + self.getDomain()
- self.checkConsolePort(console_port)
- self.console_port = console_port
-
- log.info("Created console id=%d domain=%d port=%d",
- self.id, self.getDomain(), self.console_port)
- eserver.inject('xend.console.create',
- [self.id, self.getDomain(), self.console_port])
-
- def init(self, recreate=False, reboot=False):
- try:
- self.lock.acquire()
- self.destroyed = False
- self.channel = self.getChannel()
- self.listen()
- finally:
- self.lock.release()
-
- def checkConsolePort(self, console_port):
- """Check that a console port is not in use by another console.
- """
- xd = XendRoot.get_component('xen.xend.XendDomain')
- for vm in xd.list():
- ctrl = vm.getDeviceController(self.getType(), error=False)
- if (not ctrl): continue
- ctrl.checkConsolePort(console_port)
-
- def sxpr(self):
- try:
- self.lock.acquire()
- val = ['console',
- ['status', self.status ],
- ['id', self.id ],
- ['domain', self.getDomain() ] ]
- val.append(['local_port', self.getLocalPort() ])
- val.append(['remote_port', self.getRemotePort() ])
- val.append(['console_port', self.console_port ])
- if self.addr:
- val.append(['connected', self.addr[0], self.addr[1]])
- finally:
- self.lock.release()
- return val
-
- def getLocalPort(self):
- try:
- self.lock.acquire()
- if self.channel:
- return self.channel.getLocalPort()
- else:
- return 0
- finally:
- self.lock.release()
-
- def getRemotePort(self):
- try:
- self.lock.acquire()
- if self.channel:
- return self.channel.getRemotePort()
- else:
- return 0
- finally:
- self.lock.release()
-
- def uri(self):
- """Get the uri to use to connect to the console.
- This will be a telnet: uri.
-
- return uri
- """
- host = socket.gethostname()
- return "telnet://%s:%d" % (host, self.console_port)
-
- def closed(self):
- return self.status == self.STATUS_CLOSED
-
- def connected(self):
- return self.status == self.STATUS_CONNECTED
-
- def destroy(self, change=False, reboot=False):
- """Close the console.
- """
- if reboot:
- return
- try:
- self.lock.acquire()
- self.status = self.STATUS_CLOSED
- self.listening = False
- if self.conn:
- self.conn.loseConnection()
- if self.tcp_listener:
- self.tcp_listener.stopListening()
- self.tcp_listener = None
- if self.unix_listener:
- self.unix_listener.stopListening()
- self.unix_listener = None
- finally:
- self.lock.release()
-
- def listen(self):
- """Listen for TCP connections to the console port..
- """
- try:
- self.lock.acquire()
- if self.closed():
- return
- if self.listening:
- pass
- else:
- self.listening = True
- self.status = self.STATUS_LISTENING
- if xroot.get_xend_unix_server():
- path = '/var/lib/xend/console-%s' % self.console_port
- self.unix_listener = reactor.listenUNIX(path, self)
- if xroot.get_xend_http_server():
- interface = xroot.get_console_address()
- self.tcp_listener = reactor.listenTCP(
- self.console_port, self, interface=interface)
- finally:
- self.lock.release()
-
- def buildProtocol(self, addr):
- """Factory function called to create the protocol when a connection is
accepted
- by listenTCP.
- """
- proto = ConsoleProtocol(self, self.id)
- proto.factory = self
- return proto
-
- def connect(self, addr, conn):
- """Connect a TCP connection to the console.
- Fails if closed or already connected.
-
- addr peer address
- conn connection
-
- returns 0 if ok, negative otherwise
- """
- try:
- self.lock.acquire()
- if self.closed():
- return -1
- if self.connected():
- return -1
- self.addr = addr
- self.conn = conn
- self.status = self.STATUS_CONNECTED
- self.writeOutput()
- finally:
- self.lock.release()
- return 0
-
- def disconnect(self, conn=None):
- """Disconnect the TCP connection to the console.
- """
- try:
- self.lock.acquire()
- if conn and conn != self.conn: return
- if self.conn:
- self.conn.loseConnection()
- self.addr = None
- self.conn = None
- self.status = self.STATUS_LISTENING
- self.listen()
- finally:
- self.lock.release()
-
- def receiveOutput(self, msg):
- """Receive output console data from the console channel.
-
- msg console message
- type major message type
- subtype minor message typ
- """
- # Treat the obuf as a ring buffer.
- try:
- self.lock.acquire()
- data = msg.get_payload()
- data_n = len(data)
- if self.obuf.space() < data_n:
- self.obuf.discard(data_n)
- if self.obuf.space() < data_n:
- data = data[-self.obuf.space():]
- self.obuf.write(data)
- self.writeOutput()
- finally:
- self.lock.release()
-
- def writeOutput(self):
- """Handle buffered output from the console device.
- Sends it to the connected TCP connection (if any).
- """
- try:
- self.lock.acquire()
- if self.closed():
- return -1
- writes = 0
- while self.conn and (writes < 100) and (not self.obuf.empty()):
- try:
- writes += 1
- bytes = self.conn.write(self.obuf.peek())
- if bytes > 0:
- self.obuf.discard(bytes)
- except socket.error, err:
- if err.args[0] in (EWOULDBLOCK, EAGAIN, EINTR):
- pass
- else:
- self.disconnect()
- break
-
- finally:
- self.lock.release()
- return 0
-
- def receiveInput(self, conn, data):
- """Receive console input from a TCP connection. Ignores the
- input if the calling connection (conn) is not the one
- connected to the console (self.conn).
-
- conn connection
- data input data
- """
- try:
- self.lock.acquire()
- if self.closed(): return -1
- if conn != self.conn: return 0
- self.ibuf.write(data)
- self.writeInput()
- finally:
- self.lock.release()
- return 0
-
- def writeInput(self):
- """Write pending console input to the console channel.
- Writes as much to the channel as it can.
- """
- try:
- self.lock.acquire()
- while self.channel and not self.ibuf.empty():
- msg = xu.message(CMSG_CONSOLE, 0, 0)
- msg.append_payload(self.ibuf.read(msg.MAX_PAYLOAD))
- self.channel.writeRequest(msg)
- finally:
- self.lock.release()
-
-class ConsoleController(DevController):
- """Device controller for all the consoles for a domain.
- """
-
- def __init__(self, vm, recreate=False):
- DevController.__init__(self, vm, recreate=recreate)
- self.rcvr = None
-
- def initController(self, recreate=False, reboot=False):
- self.destroyed = False
- self.rcvr = CtrlMsgRcvr(self.getChannel())
- self.rcvr.addHandler(CMSG_CONSOLE,
- 0,
- self.receiveOutput)
- self.rcvr.registerChannel()
- if reboot:
- self.rebootDevices()
-
- def destroyController(self, reboot=False):
- self.destroyed = True
- self.destroyDevices(reboot=reboot)
- self.rcvr.deregisterChannel()
-
- def newDevice(self, id, config, recreate=False):
- return ConsoleDev(self, id, config, recreate=recreate)
-
- def checkConsolePort(self, console_port):
- """Check that a console port is not in use by a console.
- """
- for c in self.getDevices():
- if c.console_port == console_port:
- raise XendError('console port in use: ' + str(console_port))
-
- def receiveOutput(self, msg):
- """Handle a control request.
- The CMSG_CONSOLE messages just contain data, and no console id,
- so just send to console 0 (if there is one).
-
- todo: extend CMSG_CONSOLE to support more than one console?
- """
- console = self.getDevice(0)
- if console:
- console.receiveOutput(msg)
- else:
- log.warning('no console: domain %d', self.getDomain())
-
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|