ia64/xen-unstable

changeset 5156:ce83bd80b6bd

bitkeeper revision 1.1554 (4294b39736L_x3NwB1IRHYxqWe9rTQ)

Merge firebug.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into firebug.cl.cam.ac.uk:/local/scratch/cl349/xen-unstable.bk
author cl349@firebug.cl.cam.ac.uk
date Wed May 25 17:19:19 2005 +0000 (2005-05-25)
parents 6ce01dc5f62f 10992a804a2a
children f1ac5983d4d8
files .rootkeys tools/libxc/xc_linux_restore.c tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendMigrate.py tools/python/xen/xend/XendRoot.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/relocate.py
line diff
     1.1 --- a/.rootkeys	Wed May 25 14:28:37 2005 +0000
     1.2 +++ b/.rootkeys	Wed May 25 17:19:19 2005 +0000
     1.3 @@ -838,7 +838,6 @@ 40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/pyt
     1.4  40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
     1.5  40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
     1.6  40ffc44eGsgTEY355E3nN4mPLZHhMQ tools/python/xen/xend/XendLogging.py
     1.7 -40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
     1.8  40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
     1.9  4151594bhib4aUerB2SMKDl-iCtc4Q tools/python/xen/xend/XendProtocol.py
    1.10  40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
    1.11 @@ -867,6 +866,7 @@ 40c9c469yrm31i60pGKslTi2Zgpotg tools/pyt
    1.12  40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py
    1.13  40c9c469ZqILEQ8x6yWy0_51jopiCg tools/python/xen/xend/server/params.py
    1.14  4266169eI_oX3YBjwaeC0V-THBRnjg tools/python/xen/xend/server/pciif.py
    1.15 +4294a1bf8rMUcddot-B2-pOxORimOg tools/python/xen/xend/server/relocate.py
    1.16  41ee5e8dq9NtihbL4nWKjuSLOhXPUg tools/python/xen/xend/server/usbif.py
    1.17  40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py
    1.18  40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py
     2.1 --- a/tools/libxc/xc_linux_restore.c	Wed May 25 14:28:37 2005 +0000
     2.2 +++ b/tools/libxc/xc_linux_restore.c	Wed May 25 17:19:19 2005 +0000
     2.3 @@ -32,6 +32,22 @@
     2.4  #define PPRINTF(_f, _a...)
     2.5  #endif
     2.6  
     2.7 +ssize_t
     2.8 +read_exact(int fd, void *buf, size_t count)
     2.9 +{
    2.10 +    int r = 0, s;
    2.11 +    unsigned char *b = buf;
    2.12 +
    2.13 +    while (r < count) {
    2.14 +	s = read(fd, &b[r], count - r);
    2.15 +	if (s <= 0)
    2.16 +	    break;
    2.17 +	r += s;
    2.18 +    }
    2.19 +
    2.20 +    return r;
    2.21 +}
    2.22 +
    2.23  int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns)
    2.24  {
    2.25      dom0_op_t op;
    2.26 @@ -90,7 +106,7 @@ int xc_linux_restore(int xc_handle, int 
    2.27          return 1;
    2.28      }
    2.29  
    2.30 -    if (read(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) {
    2.31 +    if (read_exact(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) {
    2.32  	ERR("read pfn_to_mfn_frame_list failed");
    2.33  	goto out;
    2.34      }
    2.35 @@ -168,9 +184,9 @@ int xc_linux_restore(int xc_handle, int 
    2.36              prev_pc = this_pc;
    2.37          }
    2.38  
    2.39 -        if ( read(io_fd, &j, sizeof(int)) != sizeof(int) )
    2.40 +        if ( read_exact(io_fd, &j, sizeof(int)) != sizeof(int) )
    2.41          {
    2.42 -            ERR("Error when reading from state file");
    2.43 +            ERR("Error when reading batch size");
    2.44              goto out;
    2.45          }
    2.46  
    2.47 @@ -192,9 +208,9 @@ int xc_linux_restore(int xc_handle, int 
    2.48              goto out;
    2.49          }
    2.50   
    2.51 -        if ( read(io_fd, region_pfn_type, j*sizeof(unsigned long)) !=
    2.52 +        if ( read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long)) !=
    2.53               j*sizeof(unsigned long) ) {
    2.54 -            ERR("Error when reading from state file");
    2.55 +            ERR("Error when reading region pfn types");
    2.56              goto out;
    2.57          }
    2.58  
    2.59 @@ -245,9 +261,9 @@ int xc_linux_restore(int xc_handle, int 
    2.60              else
    2.61                  ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
    2.62  
    2.63 -            if ( read(io_fd, ppage, PAGE_SIZE) != PAGE_SIZE )
    2.64 +            if ( read_exact(io_fd, ppage, PAGE_SIZE) != PAGE_SIZE )
    2.65              {
    2.66 -                ERR("Error when reading from state file");
    2.67 +                ERR("Error when reading pagetable page");
    2.68                  goto out;
    2.69              }
    2.70  
    2.71 @@ -389,9 +405,9 @@ int xc_linux_restore(int xc_handle, int 
    2.72  	unsigned int count, *pfntab;
    2.73  	int rc;
    2.74  
    2.75 -	if ( read(io_fd, &count, sizeof(count)) != sizeof(count) )
    2.76 +	if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
    2.77  	{
    2.78 -	    ERR("Error when reading from state file");
    2.79 +	    ERR("Error when reading pfn count");
    2.80  	    goto out;
    2.81  	}
    2.82  
    2.83 @@ -402,10 +418,10 @@ int xc_linux_restore(int xc_handle, int 
    2.84  	    goto out;
    2.85  	}
    2.86  
    2.87 -	if ( read(io_fd, pfntab, sizeof(unsigned int)*count) !=
    2.88 +	if ( read_exact(io_fd, pfntab, sizeof(unsigned int)*count) !=
    2.89               sizeof(unsigned int)*count )
    2.90  	{
    2.91 -	    ERR("Error when reading pfntab from state file");
    2.92 +	    ERR("Error when reading pfntab");
    2.93  	    goto out;
    2.94  	}
    2.95  
    2.96 @@ -432,10 +448,10 @@ int xc_linux_restore(int xc_handle, int 
    2.97  	}	
    2.98      }
    2.99  
   2.100 -    if ( read(io_fd, &ctxt,            sizeof(ctxt)) != sizeof(ctxt) ||
   2.101 -         read(io_fd, shared_info_page, PAGE_SIZE) != PAGE_SIZE )
   2.102 +    if ( read_exact(io_fd, &ctxt,            sizeof(ctxt)) != sizeof(ctxt) ||
   2.103 +         read_exact(io_fd, shared_info_page, PAGE_SIZE) != PAGE_SIZE )
   2.104      {
   2.105 -        ERR("Error when reading from state file");
   2.106 +        ERR("Error when reading ctxt or shared info page");
   2.107          goto out;
   2.108      }
   2.109  
     3.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Wed May 25 14:28:37 2005 +0000
     3.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Wed May 25 17:19:19 2005 +0000
     3.3 @@ -13,6 +13,7 @@ from struct import pack, unpack, calcsiz
     3.4  from xen.util.xpopen import xPopen3
     3.5  import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
     3.6  
     3.7 +from XendError import XendError
     3.8  from XendLogging import log
     3.9  
    3.10  SIGNATURE = "LinuxGuestRecord"
     4.1 --- a/tools/python/xen/xend/XendDomain.py	Wed May 25 14:28:37 2005 +0000
     4.2 +++ b/tools/python/xen/xend/XendDomain.py	Wed May 25 17:19:19 2005 +0000
     4.3 @@ -14,12 +14,12 @@ import time
     4.4  
     4.5  import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
     4.6  
     4.7 +from xen.xend.server import relocate
     4.8  import sxp
     4.9  import XendRoot; xroot = XendRoot.instance()
    4.10  import XendCheckpoint
    4.11  import XendDB
    4.12  import XendDomainInfo
    4.13 -import XendMigrate
    4.14  import EventServer; eserver = EventServer.instance()
    4.15  from XendError import XendError
    4.16  from XendLogging import log
    4.17 @@ -511,8 +511,12 @@ class XendDomain:
    4.18          # Need a cancel too?
    4.19          # Don't forget to cancel restart for it.
    4.20          dominfo = self.domain_lookup(id)
    4.21 -        xmigrate = XendMigrate.instance()
    4.22 -        return xmigrate.migrate_begin(dominfo, dst, live=live, resource=resource)
    4.23 +
    4.24 +        port = xroot.get_xend_relocation_port()
    4.25 +        sock = relocate.setupRelocation(dst, port)
    4.26 +
    4.27 +        XendCheckpoint.save(self, sock.fileno(), dominfo)
    4.28 +        return None
    4.29  
    4.30      def domain_save(self, id, dst, progress=False):
    4.31          """Start saving a domain to file.
     5.1 --- a/tools/python/xen/xend/XendMigrate.py	Wed May 25 14:28:37 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,585 +0,0 @@
     5.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     5.5 -
     5.6 -import traceback
     5.7 -import threading
     5.8 -
     5.9 -import errno
    5.10 -import sys
    5.11 -import socket
    5.12 -import time
    5.13 -import types
    5.14 -
    5.15 -from xen.web import reactor
    5.16 -from xen.web.protocol import Protocol, ClientFactory
    5.17 -
    5.18 -import scheduler
    5.19 -import sxp
    5.20 -import XendDB
    5.21 -import EventServer; eserver = EventServer.instance()
    5.22 -from XendError import XendError
    5.23 -from XendLogging import log
    5.24 -        
    5.25 -"""The port for the migrate/save daemon xfrd."""
    5.26 -XFRD_PORT = 8002
    5.27 -
    5.28 -"""The transfer protocol major version number."""
    5.29 -XFR_PROTO_MAJOR = 1
    5.30 -"""The transfer protocol minor version number."""
    5.31 -XFR_PROTO_MINOR = 0
    5.32 -
    5.33 -class Xfrd(Protocol):
    5.34 -    """Protocol handler for a connection to the migration/save daemon xfrd.
    5.35 -    """
    5.36 -
    5.37 -    def __init__(self, xinfo):
    5.38 -        self.parser = sxp.Parser()
    5.39 -        self.xinfo = xinfo
    5.40 -
    5.41 -    def connectionMade(self, addr=None):
    5.42 -        # Send hello.
    5.43 -        self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
    5.44 -        # Send request.
    5.45 -        self.xinfo.request(self)
    5.46 -        # Run the transport mainLoop which reads from the peer.
    5.47 -        self.transport.mainLoop()
    5.48 -
    5.49 -    def request(self, req):
    5.50 -        sxp.show(req, out=self.transport)
    5.51 -
    5.52 -    def loseConnection(self):
    5.53 -        self.transport.loseConnection()
    5.54 -
    5.55 -    def connectionLost(self, reason):
    5.56 -        self.xinfo.connectionLost(reason)
    5.57 -
    5.58 -    def dataReceived(self, data):
    5.59 -        self.parser.input(data)
    5.60 -        if self.parser.ready():
    5.61 -            val = self.parser.get_val()
    5.62 -            self.xinfo.dispatch(self, val)
    5.63 -        if self.parser.at_eof():
    5.64 -            self.loseConnection()
    5.65 -            
    5.66 -class XfrdClientFactory(ClientFactory):
    5.67 -    """Factory for clients of the migration/save daemon xfrd.
    5.68 -    """
    5.69 -
    5.70 -    def __init__(self, xinfo):
    5.71 -        #ClientFactory.__init__(self)
    5.72 -        self.xinfo = xinfo
    5.73 -        self.readyCond = threading.Condition()
    5.74 -        self.ready = False
    5.75 -        self.err = None
    5.76 -
    5.77 -    def start(self):
    5.78 -        print 'XfrdClientFactory>start>'
    5.79 -        reactor.connectTCP('localhost', XFRD_PORT, self)
    5.80 -        try:
    5.81 -            self.readyCond.acquire()
    5.82 -            while not self.ready:
    5.83 -                self.readyCond.wait()
    5.84 -        finally:
    5.85 -            self.readyCond.release()
    5.86 -        print 'XfrdClientFactory>start>', 'err=', self.err
    5.87 -        if self.err:
    5.88 -            raise self.err
    5.89 -        return 0
    5.90 -
    5.91 -    def notifyReady(self):
    5.92 -        try:
    5.93 -            self.readyCond.acquire()
    5.94 -            self.ready = True
    5.95 -            self.err = self.xinfo.error_summary()
    5.96 -            self.readyCond.notify()
    5.97 -        finally:
    5.98 -            self.readyCond.release()
    5.99 -            
   5.100 -    def startedConnecting(self, connector):
   5.101 -        pass
   5.102 -
   5.103 -    def buildProtocol(self, addr):
   5.104 -        return Xfrd(self.xinfo)
   5.105 -
   5.106 -    def clientConnectionLost(self, connector, reason):
   5.107 -        print "XfrdClientFactory>clientConnectionLost>", reason
   5.108 -        self.notifyReady()
   5.109 -
   5.110 -    def clientConnectionFailed(self, connector, reason):
   5.111 -        print "XfrdClientFactory>clientConnectionFailed>", reason
   5.112 -        self.xinfo.error(reason)
   5.113 -        self.notifyReady()
   5.114 -
   5.115 -class SuspendHandler:
   5.116 -
   5.117 -    def __init__(self, xinfo, vmid, timeout):
   5.118 -        self.xinfo = xinfo
   5.119 -        self.vmid = vmid
   5.120 -        self.timeout = timeout
   5.121 -        self.readyCond = threading.Condition()
   5.122 -        self.ready = False
   5.123 -        self.err = None
   5.124 -
   5.125 -    def start(self):
   5.126 -        self.subscribe(on=True)
   5.127 -        timer = scheduler.later(self.timeout, self.onTimeout)
   5.128 -        try:
   5.129 -            self.readyCond.acquire()
   5.130 -            while not self.ready:
   5.131 -                self.readyCond.wait()
   5.132 -        finally:
   5.133 -            self.readyCond.release()
   5.134 -            self.subscribe(on=False)
   5.135 -            timer.cancel()
   5.136 -        if self.err:
   5.137 -            raise XendError(self.err)
   5.138 -
   5.139 -    def notifyReady(self, err=None):
   5.140 -        try:
   5.141 -            self.readyCond.acquire()
   5.142 -            if not self.ready:
   5.143 -                self.ready = True
   5.144 -                self.err = err
   5.145 -                self.readyCond.notify()
   5.146 -        finally:
   5.147 -            self.readyCond.release()
   5.148 -
   5.149 -    def subscribe(self, on=True):
   5.150 -        # Subscribe to 'suspended' events so we can tell when the
   5.151 -        # suspend completes. Subscribe to 'died' events so we can tell if
   5.152 -        # the domain died.
   5.153 -        if on:
   5.154 -            action = eserver.subscribe
   5.155 -        else:
   5.156 -            action = eserver.unsubscribe
   5.157 -        action('xend.domain.suspended', self.onSuspended)
   5.158 -        action('xend.domain.died', self.onDied)
   5.159 -
   5.160 -    def onSuspended(self, e, v):
   5.161 -        if v[1] != self.vmid: return
   5.162 -        print 'SuspendHandler>onSuspended>', e, v
   5.163 -        self.notifyReady()
   5.164 -                
   5.165 -    def onDied(self, e, v):
   5.166 -        if v[1] != self.vmid: return
   5.167 -        print 'SuspendHandler>onDied>', e, v
   5.168 -        self.notifyReady('Domain %s died while suspending' % self.vmid)
   5.169 -
   5.170 -    def onTimeout(self):
   5.171 -         print 'SuspendHandler>onTimeout>'
   5.172 -         self.notifyReady('Domain %s suspend timed out' % self.vmid)
   5.173 -
   5.174 -class XfrdInfo:
   5.175 -    """Abstract class for info about a session with xfrd.
   5.176 -    Has subclasses for save and migrate.
   5.177 -    """
   5.178 -
   5.179 -    """Suspend timeout (seconds).
   5.180 -    We set a timeout because suspending a domain can hang."""
   5.181 -    timeout = 30
   5.182 -
   5.183 -    def __init__(self):
   5.184 -        from xen.xend import XendDomain
   5.185 -        self.xd = XendDomain.instance()
   5.186 -        self.suspended = {}
   5.187 -        self.paused = {}
   5.188 -        self.state = 'init'
   5.189 -        # List of errors encountered.
   5.190 -        self.errors = []
   5.191 -            
   5.192 -    def vmconfig(self):
   5.193 -        dominfo = self.xd.domain_get(self.src_dom)
   5.194 -        if dominfo:
   5.195 -            val = sxp.to_string(dominfo.sxpr())
   5.196 -        else:
   5.197 -            val = None
   5.198 -        return val
   5.199 -
   5.200 -    def add_error(self, err):
   5.201 -        """Add an error to the error list.
   5.202 -        Returns the error added.
   5.203 -        """
   5.204 -        if err not in self.errors:
   5.205 -            self.errors.append(err)
   5.206 -        return err
   5.207 -
   5.208 -    def error_summary(self, msg=None):
   5.209 -        """Get a XendError summarising the errors (if any).
   5.210 -        """
   5.211 -        if not self.errors:
   5.212 -            return None
   5.213 -        if msg is None:
   5.214 -            msg = "errors"
   5.215 -        if self.errors:
   5.216 -            errmsg = msg + ': ' + ', '.join(map(str, self.errors))
   5.217 -        else:
   5.218 -            errmsg = msg
   5.219 -        return XendError(errmsg)
   5.220 -
   5.221 -    def get_errors(self):
   5.222 -        """Get the list of errors.
   5.223 -        """
   5.224 -        return self.errors
   5.225 -
   5.226 -    def error(self, err):
   5.227 -        print 'XfrdInfo>error>', err
   5.228 -        self.state = 'error'
   5.229 -        self.add_error(err)
   5.230 -
   5.231 -    def dispatch(self, xfrd, val):
   5.232 -        print 'XfrdInfo>dispatch>', val
   5.233 -        op = sxp.name(val)
   5.234 -        op = op.replace('.', '_')
   5.235 -        if op.startswith('xfr_'):
   5.236 -            fn = getattr(self, op, self.unknown)
   5.237 -        else:
   5.238 -            fn = self.unknown
   5.239 -        try:
   5.240 -            val = fn(xfrd, val)
   5.241 -            if val:
   5.242 -                sxp.show(val, out=xfrd.transport)
   5.243 -        except Exception, err:
   5.244 -            print 'XfrdInfo>dispatch> error:', err
   5.245 -            val = ['xfr.err', errno.EINVAL]
   5.246 -            sxp.show(val, out=xfrd.transport)
   5.247 -            self.error(err)
   5.248 -
   5.249 -    def unknown(self, xfrd, val):
   5.250 -        xfrd.loseConnection()
   5.251 -        return None
   5.252 -
   5.253 -    def xfr_err(self, xfrd, val):
   5.254 -        # If we get an error with non-zero code the operation failed.
   5.255 -        # An error with code zero indicates hello success.
   5.256 -        print 'XfrdInfo>xfr_err>', val
   5.257 -        v = sxp.child0(val)
   5.258 -        err = int(sxp.child0(val))
   5.259 -        if not err: return
   5.260 -        self.error("transfer daemon (xfrd) error: " + str(err))
   5.261 -        xfrd.loseConnection()
   5.262 -        return None
   5.263 -
   5.264 -    def xfr_progress(self, xfrd, val):
   5.265 -        return None
   5.266 -
   5.267 -    def xfr_vm_destroy(self, xfrd, val):
   5.268 -        try:
   5.269 -            vmid = sxp.child0(val)
   5.270 -            val = self.xd.domain_destroy(vmid)
   5.271 -            if vmid in self.paused:
   5.272 -                del self.paused[vmid]
   5.273 -            if vmid in self.suspended:
   5.274 -                del self.suspended[vmid]
   5.275 -        except StandardError, err:
   5.276 -            self.add_error("vm_destroy failed")
   5.277 -            self.add_error(err)
   5.278 -            val = errno.EINVAL
   5.279 -        return ['xfr.err', val]
   5.280 -    
   5.281 -    def xfr_vm_pause(self, xfrd, val):
   5.282 -        try:
   5.283 -            vmid = sxp.child0(val)
   5.284 -            val = self.xd.domain_pause(vmid)
   5.285 -            self.paused[vmid] = 1
   5.286 -        except StandardError, err:
   5.287 -            self.add_error("vm_pause failed")
   5.288 -            self.add_error(err)
   5.289 -            val = errno.EINVAL
   5.290 -        return ['xfr.err', val]
   5.291 -
   5.292 -    def xfr_vm_unpause(self, xfrd, val):
   5.293 -        try:
   5.294 -            vmid = sxp.child0(val)
   5.295 -            val = self.xd.domain_unpause(vmid)
   5.296 -            if vmid in self.paused:
   5.297 -                del self.paused[vmid]
   5.298 -        except StandardError, err:
   5.299 -            self.add_error("vm_unpause failed")
   5.300 -            self.add_error(err)
   5.301 -            val = errno.EINVAL
   5.302 -        return ['xfr.err', val]
   5.303 -
   5.304 -    def xfr_vm_suspend(self, xfrd, val):
   5.305 -        """Suspend a domain.
   5.306 -        Suspending can hang, so we set a timeout and fail if it
   5.307 -        takes too long.
   5.308 -        """
   5.309 -        try:
   5.310 -            vmid = sxp.child0(val)
   5.311 -            h = SuspendHandler(self, vmid, self.timeout)
   5.312 -            val = self.xd.domain_shutdown(vmid, reason='suspend')
   5.313 -            self.suspended[vmid] = 1
   5.314 -            h.start()
   5.315 -            print 'xfr_vm_suspend> suspended', vmid
   5.316 -        except Exception, err:
   5.317 -            print 'xfr_vm_suspend> err', err
   5.318 -            self.add_error("suspend failed")
   5.319 -            self.add_error(err)
   5.320 -            traceback.print_exc()
   5.321 -            val = errno.EINVAL
   5.322 -        return ['xfr.err', val]
   5.323 -
   5.324 -    def connectionLost(self, reason=None):
   5.325 -        print 'XfrdInfo>connectionLost>', reason
   5.326 -        for vmid in self.suspended:
   5.327 -            try:
   5.328 -                self.xd.domain_destroy(vmid)
   5.329 -            except:
   5.330 -                pass
   5.331 -        for vmid in self.paused:
   5.332 -            try:
   5.333 -                self.xd.domain_unpause(vmid)
   5.334 -            except:
   5.335 -                pass
   5.336 -
   5.337 -class XendMigrateInfo(XfrdInfo):
   5.338 -    """Representation of a migrate in-progress and its interaction with xfrd.
   5.339 -    """
   5.340 -
   5.341 -    def __init__(self, xid, dominfo, host, port, live=0, resource=0):
   5.342 -        XfrdInfo.__init__(self)
   5.343 -        self.xid = xid
   5.344 -        self.dominfo = dominfo
   5.345 -        self.state = 'begin'
   5.346 -        self.src_host = socket.gethostname()
   5.347 -        self.src_dom = dominfo.id
   5.348 -        self.dst_host = host
   5.349 -        self.dst_port = port
   5.350 -        self.dst_dom = None
   5.351 -        self.live = live
   5.352 -        self.resource = resource
   5.353 -        self.start = 0
   5.354 -        
   5.355 -    def sxpr(self):
   5.356 -        sxpr = ['migrate',
   5.357 -                ['id',    self.xid   ],
   5.358 -                ['state', self.state ],
   5.359 -                ['live',  self.live  ],
   5.360 -                ['resource', self.resource ] ]
   5.361 -        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
   5.362 -        sxpr.append(sxpr_src)
   5.363 -        sxpr_dst = ['dst', ['host', self.dst_host] ]
   5.364 -        if self.dst_dom:
   5.365 -            sxpr_dst.append(['domain', self.dst_dom])
   5.366 -        sxpr.append(sxpr_dst)
   5.367 -        return sxpr
   5.368 -
   5.369 -    def request(self, xfrd):
   5.370 -        vmconfig = self.vmconfig()
   5.371 -        if not vmconfig:
   5.372 -            self.error(XendError("vm config not found"))
   5.373 -            xfrd.loseConnection()
   5.374 -            return
   5.375 -        log.info('Migrate BEGIN: %s' % str(self.sxpr()))
   5.376 -        eserver.inject('xend.domain.migrate',
   5.377 -                       [ self.dominfo.name, self.dominfo.id, "begin", self.sxpr() ])
   5.378 -        xfrd.request(['xfr.migrate',
   5.379 -                      self.src_dom,
   5.380 -                      vmconfig,
   5.381 -                      self.dst_host,
   5.382 -                      self.dst_port,
   5.383 -                      self.live,
   5.384 -                      self.resource ])
   5.385 -        
   5.386 -    def xfr_migrate_ok(self, xfrd, val):
   5.387 -        dom = int(sxp.child0(val))
   5.388 -        self.state = 'ok'
   5.389 -        self.dst_dom = dom
   5.390 -        self.xd.domain_destroy(self.src_dom)
   5.391 -
   5.392 -    def connectionLost(self, reason=None):
   5.393 -        print 'XendMigrateInfo>connectionLost>', reason
   5.394 -        XfrdInfo.connectionLost(self, reason)
   5.395 -        if self.state =='ok':
   5.396 -            log.info('Migrate OK: ' + str(self.sxpr()))
   5.397 -        else:
   5.398 -            self.state = 'error'
   5.399 -            self.error("migrate failed")
   5.400 -            log.info('Migrate ERROR: ' + str(self.sxpr()))
   5.401 -        eserver.inject('xend.domain.migrate',
   5.402 -                       [ self.dominfo.name, self.dominfo.id, self.state, self.sxpr() ])
   5.403 -
   5.404 -class XendSaveInfo(XfrdInfo):
   5.405 -    """Representation of a save in-progress and its interaction with xfrd.
   5.406 -    """
   5.407 -    
   5.408 -    def __init__(self, xid, dominfo, file):
   5.409 -        XfrdInfo.__init__(self)
   5.410 -        self.xid = xid
   5.411 -        self.dominfo = dominfo
   5.412 -        self.state = 'begin'
   5.413 -        self.src_dom = dominfo.id
   5.414 -        self.file = file
   5.415 -        self.start = 0
   5.416 -        
   5.417 -    def sxpr(self):
   5.418 -        sxpr = ['save',
   5.419 -                ['id', self.xid],
   5.420 -                ['state', self.state],
   5.421 -                ['domain', self.src_dom],
   5.422 -                ['file', self.file] ]
   5.423 -        return sxpr
   5.424 -
   5.425 -    def request(self, xfrd):
   5.426 -        vmconfig = self.vmconfig()
   5.427 -        if not vmconfig:
   5.428 -            self.error(XendError("vm config not found"))
   5.429 -            xfrd.loseConnection()
   5.430 -            return
   5.431 -        log.info('Save BEGIN: ' + str(self.sxpr()))
   5.432 -        eserver.inject('xend.domain.save',
   5.433 -                       [ self.dominfo.name, self.dominfo.id,
   5.434 -                         "begin", self.sxpr() ])
   5.435 -        xfrd.request(['xfr.save', self.src_dom, vmconfig, self.file ])
   5.436 -        
   5.437 -    def xfr_save_ok(self, xfrd, val):
   5.438 -        self.state = 'ok'
   5.439 -        self.xd.domain_destroy(self.src_dom)
   5.440 -
   5.441 -    def connectionLost(self, reason=None):
   5.442 -        print 'XendSaveInfo>connectionLost>', reason
   5.443 -        XfrdInfo.connectionLost(self, reason)
   5.444 -        if self.state =='ok':
   5.445 -            log.info('Save OK: ' + str(self.sxpr()))
   5.446 -        else:
   5.447 -            self.state = 'error'
   5.448 -            self.error("save failed")
   5.449 -            log.info('Save ERROR: ' + str(self.sxpr()))
   5.450 -        eserver.inject('xend.domain.save',
   5.451 -                       [ self.dominfo.name, self.dominfo.id,
   5.452 -                         self.state, self.sxpr() ])
   5.453 -    
   5.454 -class XendRestoreInfo(XfrdInfo):
   5.455 -    """Representation of a restore in-progress and its interaction with xfrd.
   5.456 -    """
   5.457 -
   5.458 -    def __init__(self, xid, file):
   5.459 -        XfrdInfo.__init__(self)
   5.460 -        self.xid = xid
   5.461 -        self.state = 'begin'
   5.462 -        self.file = file
   5.463 -
   5.464 -    def sxpr(self):
   5.465 -         sxpr = ['restore',
   5.466 -                 ['id', self.xid],
   5.467 -                 ['file', self.file] ]
   5.468 -         return sxpr
   5.469 -
   5.470 -    def request(self, xfrd):
   5.471 -        log.info('restore BEGIN: ' + str(self.sxpr()))
   5.472 -        eserver.inject('xend.restore', [ 'begin', self.sxpr()])
   5.473 -                       
   5.474 -        xfrd.request(['xfr.restore', self.file ])
   5.475 -        
   5.476 -    def xfr_restore_ok(self, xfrd, val):
   5.477 -        dom = int(sxp.child0(val))
   5.478 -        dominfo = self.xd.domain_get(dom)
   5.479 -        self.state = 'ok'
   5.480 -         
   5.481 -    def connectionLost(self, reason=None):
   5.482 -        XfrdInfo.connectionLost(self, reason)
   5.483 -        if self.state =='ok':
   5.484 -            log.info('Restore OK: ' + self.file)
   5.485 -        else:
   5.486 -            self.state = 'error'
   5.487 -            self.error("restore failed")
   5.488 -            log.info('Restore ERROR: ' + str(self.sxpr()))
   5.489 -        eserver.inject('xend.restore', [ self.state,  self.sxpr()])
   5.490 -
   5.491 -class XendMigrate:
   5.492 -    """External api for interaction with xfrd for migrate and save.
   5.493 -    Singleton.
   5.494 -    """
   5.495 -    # Use log for indications of begin/end/errors?
   5.496 -    # Need logging of: domain create/halt, migrate begin/end/fail
   5.497 -    # Log via event server?
   5.498 -
   5.499 -    dbpath = "migrate"
   5.500 -    
   5.501 -    def __init__(self):
   5.502 -        self.db = XendDB.XendDB(self.dbpath)
   5.503 -        self.session = {}
   5.504 -        self.session_db = self.db.fetchall("")
   5.505 -        self.xid = 0
   5.506 -
   5.507 -    def nextid(self):
   5.508 -        self.xid += 1
   5.509 -        return "%d" % self.xid
   5.510 -
   5.511 -    def sync(self):
   5.512 -        self.db.saveall("", self.session_db)
   5.513 -
   5.514 -    def sync_session(self, xid):
   5.515 -        self.db.save(xid, self.session_db[xid])
   5.516 -
   5.517 -    def close(self):
   5.518 -        pass
   5.519 -
   5.520 -    def _add_session(self, info):
   5.521 -        xid = info.xid
   5.522 -        self.session[xid] = info
   5.523 -        self.session_db[xid] = info.sxpr()
   5.524 -        self.sync_session(xid)
   5.525 -
   5.526 -    def _delete_session(self, xid):
   5.527 -        if xid in self.session:
   5.528 -            del self.session[xid]
   5.529 -        if xid in self.session_db:
   5.530 -            del self.session_db[xid]
   5.531 -            self.db.delete(xid)
   5.532 -
   5.533 -    def session_ls(self):
   5.534 -        return self.session.keys()
   5.535 -
   5.536 -    def sessions(self):
   5.537 -        return self.session.values()
   5.538 -
   5.539 -    def session_get(self, xid):
   5.540 -        return self.session.get(xid)
   5.541 -
   5.542 -    def session_begin(self, info):
   5.543 -        """Add the session to the table and start it.
   5.544 -        Remove the session from the table when it finishes.
   5.545 -
   5.546 -        @param info: session
   5.547 -        """
   5.548 -        self._add_session(info)
   5.549 -        try:
   5.550 -            xcf = XfrdClientFactory(info)
   5.551 -            return xcf.start()
   5.552 -        finally:
   5.553 -            self._delete_session(info.xid)
   5.554 -    
   5.555 -    def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0):
   5.556 -        """Begin to migrate a domain to another host.
   5.557 -
   5.558 -        @param dominfo:  domain info
   5.559 -        @param host: destination host
   5.560 -        @param port: destination port
   5.561 -        """
   5.562 -        xid = self.nextid()
   5.563 -        info = XendMigrateInfo(xid, dominfo, host, port, live, resource)
   5.564 -        return self.session_begin(info)
   5.565 -
   5.566 -    def save_begin(self, dominfo, file):
   5.567 -        """Begin saving a domain to file.
   5.568 -
   5.569 -        @param dominfo:  domain info
   5.570 -        @param file: destination file
   5.571 -        """
   5.572 -        xid = self.nextid()
   5.573 -        info = XendSaveInfo(xid, dominfo, file)
   5.574 -        return self.session_begin(info)
   5.575 -
   5.576 -    def restore_begin(self, file):
   5.577 -        xid = self.nextid()
   5.578 -        info = XendRestoreInfo(xid, file)
   5.579 -        return self.session_begin(info)
   5.580 -        
   5.581 -
   5.582 -def instance():
   5.583 -    global inst
   5.584 -    try:
   5.585 -        inst
   5.586 -    except:
   5.587 -        inst = XendMigrate()
   5.588 -    return inst
     6.1 --- a/tools/python/xen/xend/XendRoot.py	Wed May 25 14:28:37 2005 +0000
     6.2 +++ b/tools/python/xen/xend/XendRoot.py	Wed May 25 17:19:19 2005 +0000
     6.3 @@ -51,12 +51,21 @@ class XendRoot:
     6.4      """Default interface address xend listens at. """
     6.5      xend_address_default      = ''
     6.6  
     6.7 +    """Default for the flag indicating whether xend should run a relocation server."""
     6.8 +    xend_relocation_server_default = 'yes'
     6.9 +
    6.10 +    """Default interface address the xend relocation server listens at. """
    6.11 +    xend_relocation_address_default = ''
    6.12 +
    6.13      """Default port xend serves HTTP at. """
    6.14      xend_port_default         = '8000'
    6.15  
    6.16      """Default port xend serves events at. """
    6.17      xend_event_port_default   = '8001'
    6.18  
    6.19 +    """Default port xend serves relocation at. """
    6.20 +    xend_relocation_port_default = '8002'
    6.21 +
    6.22      """Default for the flag indicating whether xend should run a unix-domain server."""
    6.23      xend_unix_server_default = 'yes'
    6.24  
    6.25 @@ -249,6 +258,11 @@ class XendRoot:
    6.26          """
    6.27          return self.get_config_bool("xend-http-server", self.xend_http_server_default)
    6.28  
    6.29 +    def get_xend_relocation_server(self):
    6.30 +        """Get the flag indicating whether xend should run a relocation server.
    6.31 +        """
    6.32 +        return self.get_config_bool("xend-relocation-server", self.xend_relocation_server_default)
    6.33 +
    6.34      def get_xend_port(self):
    6.35          """Get the port xend listens at for its HTTP interface.
    6.36          """
    6.37 @@ -259,6 +273,11 @@ class XendRoot:
    6.38          """
    6.39          return self.get_config_int('xend-event-port', self.xend_event_port_default)
    6.40  
    6.41 +    def get_xend_relocation_port(self):
    6.42 +        """Get the port xend listens at for connection to its relocation server.
    6.43 +        """
    6.44 +        return self.get_config_int('xend-relocation-port', self.xend_relocation_port_default)
    6.45 +
    6.46      def get_xend_address(self):
    6.47          """Get the address xend listens at for its HTTP and event ports.
    6.48          This defaults to the empty string which allows all hosts to connect.
    6.49 @@ -267,6 +286,14 @@ class XendRoot:
    6.50          """
    6.51          return self.get_config_value('xend-address', self.xend_address_default)
    6.52  
    6.53 +    def get_xend_relocation_address(self):
    6.54 +        """Get the address xend listens at for its HTTP and event ports.
    6.55 +        This defaults to the empty string which allows all hosts to connect.
    6.56 +        If this is set to 'localhost' only the localhost will be able to connect
    6.57 +        to the HTTP and event ports.
    6.58 +        """
    6.59 +        return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
    6.60 +
    6.61      def get_xend_unix_server(self):
    6.62          """Get the flag indicating whether xend should run a unix-domain server.
    6.63          """
     7.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Wed May 25 14:28:37 2005 +0000
     7.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Wed May 25 17:19:19 2005 +0000
     7.3 @@ -30,6 +30,7 @@ from xen.xend.XendLogging import log
     7.4  import channel
     7.5  import controller
     7.6  import event
     7.7 +import relocate
     7.8  from params import *
     7.9  
    7.10  DAEMONIZE = 0
    7.11 @@ -302,6 +303,7 @@ class Daemon:
    7.12              log.info("Xend Daemon started")
    7.13              self.createFactories()
    7.14              event.listenEvent(self)
    7.15 +            relocate.listenRelocation()
    7.16              self.listenChannels()
    7.17              servers = SrvServer.create()
    7.18              self.daemonize()
     8.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Wed May 25 14:28:37 2005 +0000
     8.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Wed May 25 17:19:19 2005 +0000
     8.3 @@ -75,15 +75,7 @@ class SrvDomain(SrvDir):
     8.4                       ['destination', 'str'],
     8.5                       ['live',        'int'],
     8.6                       ['resource',    'int']])
     8.7 -        info = fn(req.args, {'dom': self.dom.id})
     8.8 -        #req.setResponseCode(http.ACCEPTED)
     8.9 -        host = info.dst_host
    8.10 -        port = info.dst_port
    8.11 -        dom  = info.dst_dom
    8.12 -        url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
    8.13 -        req.setHeader("Location", url)
    8.14 -        print 'do_migrate> url=', url
    8.15 -        return url
    8.16 +        return fn(req.args, {'dom': self.dom.id})
    8.17  
    8.18      def op_pincpu(self, op, req):
    8.19          fn = FormFn(self.xd.domain_pincpu,
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/python/xen/xend/server/relocate.py	Wed May 25 17:19:19 2005 +0000
     9.3 @@ -0,0 +1,139 @@
     9.4 +
     9.5 +import socket
     9.6 +import sys
     9.7 +import StringIO
     9.8 +
     9.9 +from xen.web import reactor, protocol
    9.10 +
    9.11 +from xen.xend import scheduler
    9.12 +from xen.xend import sxp
    9.13 +from xen.xend import EventServer; eserver = EventServer.instance()
    9.14 +from xen.xend.XendError import XendError
    9.15 +from xen.xend import XendRoot; xroot = XendRoot.instance()
    9.16 +from xen.xend.XendLogging import log
    9.17 +from xen.xend import XendCheckpoint
    9.18 +
    9.19 +DEBUG = 0
    9.20 +
    9.21 +class RelocationProtocol(protocol.Protocol):
    9.22 +    """Asynchronous handler for a connected relocation socket.
    9.23 +    """
    9.24 +
    9.25 +    def __init__(self):
    9.26 +        #protocol.Protocol.__init__(self)
    9.27 +        self.parser = sxp.Parser()
    9.28 +
    9.29 +    def dataReceived(self, data):
    9.30 +        try:
    9.31 +            self.parser.input(data)
    9.32 +            if self.parser.ready():
    9.33 +                val = self.parser.get_val()
    9.34 +                res = self.dispatch(val)
    9.35 +                self.send_result(res)
    9.36 +            if self.parser.at_eof():
    9.37 +                self.loseConnection()
    9.38 +        except SystemExit:
    9.39 +            raise
    9.40 +        except:
    9.41 +            self.send_error()
    9.42 +
    9.43 +    def loseConnection(self):
    9.44 +        if self.transport:
    9.45 +            self.transport.loseConnection()
    9.46 +        if self.connected:
    9.47 +            scheduler.now(self.connectionLost)
    9.48 +
    9.49 +    def connectionLost(self, reason=None):
    9.50 +        pass
    9.51 +
    9.52 +    def send_reply(self, sxpr):
    9.53 +        io = StringIO.StringIO()
    9.54 +        sxp.show(sxpr, out=io)
    9.55 +        print >> io
    9.56 +        io.seek(0)
    9.57 +        if self.transport:
    9.58 +            return self.transport.write(io.getvalue())
    9.59 +        else:
    9.60 +            return 0
    9.61 +
    9.62 +    def send_result(self, res):
    9.63 +        if res is None:
    9.64 +            resp = ['ok']
    9.65 +        else:
    9.66 +            resp = ['ok', res]
    9.67 +        return self.send_reply(resp)
    9.68 +
    9.69 +    def send_error(self):
    9.70 +        (extype, exval) = sys.exc_info()[:2]
    9.71 +        return self.send_reply(['err',
    9.72 +                                ['type', str(extype)],
    9.73 +                                ['value', str(exval)]])
    9.74 +
    9.75 +    def opname(self, name):
    9.76 +         return 'op_' + name.replace('.', '_')
    9.77 +
    9.78 +    def operror(self, name, req):
    9.79 +        raise XendError('Invalid operation: ' +name)
    9.80 +
    9.81 +    def dispatch(self, req):
    9.82 +        op_name = sxp.name(req)
    9.83 +        op_method_name = self.opname(op_name)
    9.84 +        op_method = getattr(self, op_method_name, self.operror)
    9.85 +        return op_method(op_name, req)
    9.86 +
    9.87 +    def op_help(self, name, req):
    9.88 +        def nameop(x):
    9.89 +            if x.startswith('op_'):
    9.90 +                return x[3:].replace('_', '.')
    9.91 +            else:
    9.92 +                return x
    9.93 +        
    9.94 +        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
    9.95 +        return l
    9.96 +
    9.97 +    def op_quit(self, name, req):
    9.98 +        self.loseConnection()
    9.99 +
   9.100 +    def op_receive(self, name, req):
   9.101 +        if self.transport:
   9.102 +            self.send_reply(["ready", name])
   9.103 +            self.transport.sock.setblocking(1)
   9.104 +            xd = xroot.get_component("xen.xend.XendDomain")
   9.105 +            XendCheckpoint.restore(xd, self.transport.sock.fileno())
   9.106 +            self.transport.sock.setblocking(0)
   9.107 +        else:
   9.108 +            log.error(name + ": no transport")
   9.109 +            raise XendError(name + ": no transport")
   9.110 +
   9.111 +class RelocationFactory(protocol.ServerFactory):
   9.112 +    """Asynchronous handler for the relocation server socket.
   9.113 +    """
   9.114 +
   9.115 +    def __init__(self):
   9.116 +        #protocol.ServerFactory.__init__(self)
   9.117 +        pass
   9.118 +
   9.119 +    def buildProtocol(self, addr):
   9.120 +        return RelocationProtocol()
   9.121 +
   9.122 +def listenRelocation():
   9.123 +    factory = RelocationFactory()
   9.124 +    if xroot.get_xend_unix_server():
   9.125 +        path = '/var/lib/xend/relocation-socket'
   9.126 +        reactor.listenUNIX(path, factory)
   9.127 +    if xroot.get_xend_relocation_server():
   9.128 +        port = xroot.get_xend_relocation_port()
   9.129 +        interface = xroot.get_xend_relocation_address()
   9.130 +        reactor.listenTCP(port, factory, interface=interface)
   9.131 +
   9.132 +def setupRelocation(dst, port):
   9.133 +    try:
   9.134 +        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   9.135 +        sock.connect((dst, port))
   9.136 +    except socket.error, err:
   9.137 +        raise XendError("can't connect: %s" % err[1])
   9.138 +
   9.139 +    sock.send("receive\n")
   9.140 +    print sock.recv(80)
   9.141 +
   9.142 +    return sock