* Re: [PATCH] Make Xend use consoled and xc_console
2005-08-03 21:26 Anthony Liguori
@ 2005-08-03 21:30 ` Anthony Liguori
0 siblings, 0 replies; 11+ messages in thread
From: Anthony Liguori @ 2005-08-03 21:30 UTC (permalink / raw)
To: Anthony Liguori; +Cc: xen-devel, Christian Limpach
[-- Attachment #1: Type: text/plain, Size: 1008 bytes --]
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@us.ibm.com>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
>
[-- Attachment #2: xend_consoled.diff --]
[-- Type: text/x-patch, Size: 38604 bytes --]
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@hp.com>
-"""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@hp.com>
-
-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@hp.com>
-
-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@hp.com>
-
-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@hp.com>
-
-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())
-
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 11+ messages in thread