From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anthony Liguori Subject: Re: [PATCH] Make Xend use consoled and xc_console Date: Wed, 03 Aug 2005 16:30:02 -0500 Message-ID: <42F1375A.1080306@us.ibm.com> References: <42F13672.20204@us.ibm.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------040309020000020803050107" Return-path: In-Reply-To: <42F13672.20204@us.ibm.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Anthony Liguori Cc: xen-devel , Christian Limpach List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --------------040309020000020803050107 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel > --------------040309020000020803050107 Content-Type: text/x-patch; name="xend_consoled.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="xend_consoled.diff" 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('

%s

' % 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('

Console %s

' - % (cid, cid)) - req.write('

Connect to console

' - % cinfo.uri()) if self.dom.config: req.write("
")
                 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 
 
-"""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], "  []"
-        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 
-
-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 
-
-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('')
-            self.print_path(req)
-            #self.ls()
-            req.write('

%s

' % self.info) - req.write('

Connect to domain %d

' - % (self.info.uri(), self.info.id)) - self.form(req) - req.write('') - - def form(self, req): - req.write('
' % req.prePathURL()) - if self.info.connected(): - req.write('') - req.write('
') 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 - -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("") - self.print_path(req) - self.ls(req) - self.ls_console(req) - #self.form(req.wfile) - req.write("") - - 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('
    ') - for c in consoles: - cid = str(c.console_port) - req.write('
  • %s
  • ' % (url, cid, cid)) - req.write('
') 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 - -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()) - --------------040309020000020803050107 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------040309020000020803050107--