ia64/xen-unstable
changeset 1744:afd530477bfd
bitkeeper revision 1.1062.3.2 (40f29f095EmGaaKsbz1zoQ1AZH6dQw)
Integrating save/migrate handling with xfrd.
Add suspend callback to save.
Integrating save/migrate handling with xfrd.
Add suspend callback to save.
author | mjw@wray-m-3.hpl.hp.com |
---|---|
date | Mon Jul 12 14:24:09 2004 +0000 (2004-07-12) |
parents | 982f815497e4 |
children | 3000423a41b1 |
files | tools/libxc/xc_io.h tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendMigrate.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/SrvDomainDir.py tools/xfrd/Makefile tools/xfrd/xen_domain.c tools/xfrd/xfrd.c tools/xfrd/xfrd.h |
line diff
1.1 --- a/tools/libxc/xc_io.h Mon Jul 12 14:18:52 2004 +0000 1.2 +++ b/tools/libxc/xc_io.h Mon Jul 12 14:24:09 2004 +0000 1.3 @@ -1,6 +1,7 @@ 1.4 #ifndef __XC_XC_IO_H__ 1.5 #define __XC_XC_IO_H__ 1.6 1.7 +#include <errno.h> 1.8 #include "xc_private.h" 1.9 #include "iostream.h" 1.10 1.11 @@ -12,8 +13,21 @@ typedef struct XcIOContext { 1.12 IOStream *err; 1.13 char *vmconfig; 1.14 int vmconfig_n; 1.15 + int (*suspend)(u32 domain, void *data); 1.16 + void *data; 1.17 } XcIOContext; 1.18 1.19 +static inline int xcio_suspend_domain(XcIOContext *ctxt){ 1.20 + int err = 0; 1.21 + 1.22 + if(ctxt->suspend){ 1.23 + err = ctxt->suspend(ctxt->domain, ctxt->data); 1.24 + } else { 1.25 + err = -EINVAL; 1.26 + } 1.27 + return err; 1.28 +} 1.29 + 1.30 static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){ 1.31 int rc; 1.32
2.1 --- a/tools/python/xen/xend/XendClient.py Mon Jul 12 14:18:52 2004 +0000 2.2 +++ b/tools/python/xen/xend/XendClient.py Mon Jul 12 14:24:09 2004 +0000 2.3 @@ -225,6 +225,11 @@ class Xend: 2.4 def xend_domain(self, id): 2.5 return xend_get(self.domainurl(id)) 2.6 2.7 + def xend_domain_configure(self, id, config): 2.8 + return xend_call(self.domainurl(id), 2.9 + {'op' : 'configure', 2.10 + 'config' : fileof(conf) }) 2.11 + 2.12 def xend_domain_unpause(self, id): 2.13 return xend_call(self.domainurl(id), 2.14 {'op' : 'unpause'})
3.1 --- a/tools/python/xen/xend/XendDomain.py Mon Jul 12 14:18:52 2004 +0000 3.2 +++ b/tools/python/xen/xend/XendDomain.py Mon Jul 12 14:24:09 2004 +0000 3.3 @@ -311,6 +311,42 @@ class XendDomain: 3.4 return dominfo 3.5 deferred.addCallback(fn) 3.6 return deferred 3.7 + 3.8 + def domain_configure(self, id, config): 3.9 + """Configure an existing domain. This is intended for internal 3.10 + use by domain restore and migrate. 3.11 + 3.12 + @param id: domain id 3.13 + @param config: configuration 3.14 + @return: deferred 3.15 + """ 3.16 + dom = int(id) 3.17 + dominfo = self.domain_get(dom) 3.18 + if not dominfo: 3.19 + raise ValueError("Invalid domain: " + str(id)) 3.20 + if dominfo.config: 3.21 + raise ValueError("Domain already configured: " + str(id)) 3.22 + def fn(dominfo): 3.23 + self._add_domain(dominfo.id, dominfo) 3.24 + return dominfo 3.25 + deferred = dominfo.construct(config) 3.26 + deferred.addCallback(fn) 3.27 + return deferred 3.28 + 3.29 + def domain_restore(self, src, progress=0): 3.30 + """Restore a domain from file. 3.31 + 3.32 + @param src: source file 3.33 + @param progress: output progress if true 3.34 + @return: deferred 3.35 + """ 3.36 + 3.37 + def fn(dominfo): 3.38 + self._add_domain(dominfo.id, dominfo) 3.39 + return dominfo 3.40 + deferred = XendDomainInfo.vm_restore(src, progress=progress) 3.41 + deferred.addCallback(fn) 3.42 + return deferred 3.43 3.44 def domain_get(self, id): 3.45 """Get up-to-date info about a domain. 3.46 @@ -346,6 +382,8 @@ class XendDomain: 3.47 - reboot: domain will restart. 3.48 - halt: domain will not restart (even if has autorestart set). 3.49 3.50 + Returns immediately. 3.51 + 3.52 @param id: domain id 3.53 @param reason: shutdown type: poweroff, reboot, suspend, halt 3.54 """ 3.55 @@ -443,7 +481,7 @@ class XendDomain: 3.56 3.57 def domain_destroy(self, id): 3.58 """Terminate domain immediately. 3.59 - Camcels any restart for the domain. 3.60 + Cancels any restart for the domain. 3.61 3.62 @param id: domain id 3.63 """ 3.64 @@ -456,6 +494,7 @@ class XendDomain: 3.65 """Start domain migration. 3.66 3.67 @param id: domain id 3.68 + @return: deferred 3.69 """ 3.70 # Need a cancel too? 3.71 # Don't forget to cancel restart for it. 3.72 @@ -464,41 +503,16 @@ class XendDomain: 3.73 return xmigrate.migrate_begin(dom, dst) 3.74 3.75 def domain_save(self, id, dst, progress=0): 3.76 - """Save domain state to file, destroy domain on success. 3.77 - Leave domain running on error. 3.78 + """Start saving a domain to file. 3.79 3.80 @param id: domain id 3.81 @param dst: destination file 3.82 @param progress: output progress if true 3.83 + @return: deferred 3.84 """ 3.85 dom = int(id) 3.86 - dominfo = self.domain_get(id) 3.87 - if not dominfo: 3.88 - return -1 3.89 - vmconfig = sxp.to_string(dominfo.sxpr()) 3.90 - self.domain_pause(id) 3.91 - eserver.inject('xend.domain.save', id) 3.92 - try: 3.93 - rc = xc.linux_save(dom=dom, state_file=dst, 3.94 - vmconfig=vmconfig, progress=progress) 3.95 - except: 3.96 - rc = -1 3.97 - if rc == 0: 3.98 - self.domain_destroy(id) 3.99 - else: 3.100 - self.domain_unpause(id) 3.101 - return rc 3.102 - 3.103 - def domain_restore(self, src, progress=0): 3.104 - """Restore domain from file. 3.105 - 3.106 - @param src : source file 3.107 - @param progress: output progress if true 3.108 - @return: domain object 3.109 - """ 3.110 - dominfo = XendDomainInfo.vm_restore(src, progress=progress) 3.111 - self._add_domain(dominfo.id, dominfo) 3.112 - return dominfo 3.113 + xmigrate = XendMigrate.instance() 3.114 + return xmigrate.save_begin(dom, dst) 3.115 3.116 def domain_pincpu(self, dom, cpu): 3.117 """Pin a domain to a cpu.
4.1 --- a/tools/python/xen/xend/XendMigrate.py Mon Jul 12 14:18:52 2004 +0000 4.2 +++ b/tools/python/xen/xend/XendMigrate.py Mon Jul 12 14:24:09 2004 +0000 4.3 @@ -1,5 +1,6 @@ 4.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 4.5 4.6 +import errno 4.7 import sys 4.8 import socket 4.9 import time 4.10 @@ -14,9 +15,12 @@ import sxp 4.11 import XendDB 4.12 import EventServer; eserver = EventServer.instance() 4.13 4.14 +"""The port for the migrate/save daemon xfrd.""" 4.15 XFRD_PORT = 8002 4.16 4.17 +"""The transfer protocol major version number.""" 4.18 XFR_PROTO_MAJOR = 1 4.19 +"""The transfer protocol minor version number.""" 4.20 XFR_PROTO_MINOR = 0 4.21 4.22 class Xfrd(Protocol): 4.23 @@ -55,16 +59,16 @@ class XfrdClientFactory(ClientFactory): 4.24 """Factory for clients of the migration/save daemon xfrd. 4.25 """ 4.26 4.27 - def __init__(self, minfo): 4.28 + def __init__(self, xinfo): 4.29 #ClientFactory.__init__(self) 4.30 - self.minfo = minfo 4.31 + self.xinfo = xinfo 4.32 4.33 def startedConnecting(self, connector): 4.34 print 'Started to connect', 'self=', self, 'connector=', connector 4.35 4.36 def buildProtocol(self, addr): 4.37 print 'buildProtocol>', addr 4.38 - return Migrate(self.minfo) 4.39 + return Xfrd(self.xinfo) 4.40 4.41 def clientConnectionLost(self, connector, reason): 4.42 print 'clientConnectionLost>', 'connector=', connector, 'reason=', reason 4.43 @@ -76,13 +80,15 @@ class XfrdInfo: 4.44 """Abstract class for info about a session with xfrd. 4.45 Has subclasses for save and migrate. 4.46 """ 4.47 - 4.48 + 4.49 + def __init__(self): 4.50 + from xen.xend import XendDomain 4.51 + self.xd = XendDomain.instance() 4.52 + self.deferred = defer.Deferred() 4.53 + 4.54 def vmconfig(self): 4.55 print 'vmconfig>' 4.56 - from xen.xend import XendDomain 4.57 - xd = XendDomain.instance() 4.58 - 4.59 - dominfo = xd.domain_get(self.src_dom) 4.60 + dominfo = self.xd.domain_get(self.src_dom) 4.61 print 'vmconfig>', type(dominfo), dominfo 4.62 if dominfo: 4.63 val = sxp.to_string(dominfo.sxpr()) 4.64 @@ -93,6 +99,8 @@ class XfrdInfo: 4.65 4.66 def error(self, err): 4.67 self.state = 'error' 4.68 + if not self.deferred.called: 4.69 + self.deferred.errback(err) 4.70 4.71 def dispatch(self, xfrd, val): 4.72 op = sxp.name(val) 4.73 @@ -100,14 +108,18 @@ class XfrdInfo: 4.74 if op.startswith('xfr_'): 4.75 fn = getattr(self, op, self.unknown) 4.76 else: 4.77 - fn = self.unknown() 4.78 - fn(xfrd, val) 4.79 + fn = self.unknown 4.80 + val = fn(xfrd, val) 4.81 + if val is not None: 4.82 + sxp.show(val, out=self.transport) 4.83 4.84 def unknown(self, xfrd, val): 4.85 print 'unknown>', val 4.86 + xfrd.loseConnection() 4.87 + return None 4.88 4.89 def xfr_err(self, xfrd, val): 4.90 - # If we get an error with non-zero code the migrate failed. 4.91 + # If we get an error with non-zero code the operation failed. 4.92 # An error with code zero indicates hello success. 4.93 print 'xfr_err>', val 4.94 v = sxp.child(val) 4.95 @@ -116,21 +128,49 @@ class XfrdInfo: 4.96 if not err: return 4.97 self.error(err); 4.98 xfrd.loseConnection() 4.99 + #try: 4.100 + # self.xd.domain_unpause(self.src_dom) 4.101 + #except: 4.102 + # print >>sys.stdout, "Error unpausing domain:", self.src_dom 4.103 + return None 4.104 4.105 def xfr_progress(self, val): 4.106 print 'xfr_progress>', val 4.107 + return None 4.108 4.109 - def xfr_domain_pause(self, val): 4.110 - print 'xfr__domain_pause>', val 4.111 + def xfr_vm_pause(self, val): 4.112 + print 'xfr_vm_pause>', val 4.113 + try: 4.114 + vmid = sxp.child0(val) 4.115 + val = self.xd.domain_pause(vmid) 4.116 + except: 4.117 + val = errno.EINVAL 4.118 + return ['xfr.err', val] 4.119 4.120 - def xfr_domain_suspend(self, val): 4.121 - print 'xfr_domain_suspend>', val 4.122 + def xfr_vm_unpause(self, val): 4.123 + print 'xfr_vm_unpause>', val 4.124 + try: 4.125 + vmid = sxp.child0(val) 4.126 + val = self.xd.domain_unpause(vmid) 4.127 + except: 4.128 + val = errno.EINVAL 4.129 + return ['xfr.err', val] 4.130 + 4.131 + def xfr_vm_suspend(self, val): 4.132 + print 'xfr_vm_suspend>', val 4.133 + try: 4.134 + vmid = sxp.child0(val) 4.135 + val = self.xd.domain_shutdown(vmid, reason='suspend') 4.136 + except: 4.137 + val = errno.EINVAL 4.138 + return ['xfr.err', val] 4.139 4.140 class XendMigrateInfo(XfrdInfo): 4.141 """Representation of a migrate in-progress and its interaction with xfrd. 4.142 """ 4.143 4.144 def __init__(self, id, dom, host, port): 4.145 + XfrdInfo.__init__(self) 4.146 self.id = id 4.147 self.state = 'begin' 4.148 self.src_host = socket.gethostname() 4.149 @@ -139,7 +179,6 @@ class XendMigrateInfo(XfrdInfo): 4.150 self.dst_port = port 4.151 self.dst_dom = None 4.152 self.start = 0 4.153 - self.deferred = defer.Deferred() 4.154 4.155 def sxpr(self): 4.156 sxpr = ['migrate', ['id', self.id], ['state', self.state] ] 4.157 @@ -160,12 +199,15 @@ class XendMigrateInfo(XfrdInfo): 4.158 self.src_dom, 4.159 vmconfig, 4.160 self.dst_host, 4.161 - self.d.dst_port]) 4.162 + self.dst_port]) 4.163 4.164 def xfr_migrate_ok(self, val): 4.165 dom = int(sxp.child0(val)) 4.166 self.state = 'ok' 4.167 self.dst_dom = dom 4.168 + self.xd_domain_destroy(self.src_dom) 4.169 + if not self.deferred.called: 4.170 + self.deferred.callback(self) 4.171 4.172 def connectionLost(self, reason=None): 4.173 if self.state =='ok': 4.174 @@ -179,12 +221,12 @@ class XendSaveInfo(XfrdInfo): 4.175 """ 4.176 4.177 def __init__(self, id, dom, file): 4.178 + XfrdInfo.__init__(self) 4.179 self.id = id 4.180 self.state = 'begin' 4.181 self.src_dom = dom 4.182 self.file = file 4.183 self.start = 0 4.184 - self.deferred = defer.Deferred() 4.185 4.186 def sxpr(self): 4.187 sxpr = ['save', 4.188 @@ -204,6 +246,9 @@ class XendSaveInfo(XfrdInfo): 4.189 def xfr_save_ok(self, val): 4.190 dom = int(sxp.child0(val)) 4.191 self.state = 'ok' 4.192 + self.xd_domain_destroy(self.src_dom) 4.193 + if not self.deferred.called: 4.194 + self.deferred.callback(self) 4.195 4.196 def connectionLost(self, reason=None): 4.197 if self.state =='ok': 4.198 @@ -217,7 +262,6 @@ class XendMigrate: 4.199 """External api for interaction with xfrd for migrate and save. 4.200 Singleton. 4.201 """ 4.202 - # Represents migration in progress. 4.203 # Use log for indications of begin/end/errors? 4.204 # Need logging of: domain create/halt, migrate begin/end/fail 4.205 # Log via event server? 4.206 @@ -226,8 +270,8 @@ class XendMigrate: 4.207 4.208 def __init__(self): 4.209 self.db = XendDB.XendDB(self.dbpath) 4.210 - self.migrate = {} 4.211 - self.migrate_db = self.db.fetchall("") 4.212 + self.session = {} 4.213 + self.session_db = self.db.fetchall("") 4.214 self.id = 0 4.215 4.216 def nextid(self): 4.217 @@ -235,44 +279,67 @@ class XendMigrate: 4.218 return "%d" % self.id 4.219 4.220 def sync(self): 4.221 - self.db.saveall("", self.migrate_db) 4.222 + self.db.saveall("", self.session_db) 4.223 4.224 - def sync_migrate(self, id): 4.225 - self.db.save(id, self.migrate_db[id]) 4.226 + def sync_session(self, id): 4.227 + self.db.save(id, self.session_db[id]) 4.228 4.229 def close(self): 4.230 pass 4.231 4.232 - def _add_migrate(self, id, info): 4.233 - self.migrate[id] = info 4.234 - self.migrate_db[id] = info.sxpr() 4.235 - self.sync_migrate(id) 4.236 + def _add_session(self, id, info): 4.237 + self.session[id] = info 4.238 + self.session_db[id] = info.sxpr() 4.239 + self.sync_session(id) 4.240 #eserver.inject('xend.migrate.begin', info.sxpr()) 4.241 4.242 - def _delete_migrate(self, id): 4.243 + def _delete_session(self, id): 4.244 #eserver.inject('xend.migrate.end', id) 4.245 - del self.migrate[id] 4.246 - del self.migrate_db[id] 4.247 + del self.session[id] 4.248 + del self.session_db[id] 4.249 self.db.delete(id) 4.250 4.251 - def migrate_ls(self): 4.252 - return self.migrate.keys() 4.253 + def session_ls(self): 4.254 + return self.session.keys() 4.255 + 4.256 + def sessions(self): 4.257 + return self.session.values() 4.258 4.259 - def migrates(self): 4.260 - return self.migrate.values() 4.261 + def session_get(self, id): 4.262 + return self.session.get(id) 4.263 4.264 - def migrate_get(self, id): 4.265 - return self.migrate.get(id) 4.266 + def session_begin(self, info): 4.267 + self._add_session(id, info) 4.268 + mcf = XfrdClientFactory(info) 4.269 + reactor.connectTCP('localhost', XFRD_PORT, mcf) 4.270 + return info 4.271 4.272 def migrate_begin(self, dom, host, port=XFRD_PORT): 4.273 + """Begin to migrate a domain to another host. 4.274 + 4.275 + @param dom: domain 4.276 + @param host: destination host 4.277 + @param port: destination port 4.278 + @return: deferred 4.279 + """ 4.280 # Check dom for existence, not migrating already. 4.281 # Subscribe to migrate notifications (for updating). 4.282 id = self.nextid() 4.283 info = XendMigrateInfo(id, dom, host, port) 4.284 - self._add_migrate(id, info) 4.285 - mcf = XfrdClientFactory(info) 4.286 - reactor.connectTCP('localhost', XFRD_PORT, mcf) 4.287 - return info 4.288 + self.session_begin(info) 4.289 + return info.deferred 4.290 + 4.291 + def save_begin(self, dom, file): 4.292 + """Begin saving a domain to file. 4.293 + 4.294 + @param dom: domain 4.295 + @param file: destination file 4.296 + @return: deferred 4.297 + """ 4.298 + id = self.nextid() 4.299 + info = XendSaveInfo(id, dom, file) 4.300 + self.session_begin(info) 4.301 + return info.deferred 4.302 4.303 def instance(): 4.304 global inst
5.1 --- a/tools/python/xen/xend/server/SrvDomain.py Mon Jul 12 14:18:52 2004 +0000 5.2 +++ b/tools/python/xen/xend/server/SrvDomain.py Mon Jul 12 14:24:09 2004 +0000 5.3 @@ -18,6 +18,14 @@ class SrvDomain(SrvDir): 5.4 self.xd = XendDomain.instance() 5.5 self.xconsole = XendConsole.instance() 5.6 5.7 + def op_configure(self, op, req): 5.8 + fn = FormFn(self.xd.domain_configure, 5.9 + [['dom', 'int'], 5.10 + ['config', 'sxp']]) 5.11 + val = fn(req.args, {'dom': self.dom.id}) 5.12 + #todo: may need to add ok and err callbacks. 5.13 + return val 5.14 + 5.15 def op_unpause(self, op, req): 5.16 val = self.xd.domain_unpause(self.dom.id) 5.17 return val 5.18 @@ -27,7 +35,6 @@ class SrvDomain(SrvDir): 5.19 return val 5.20 5.21 def op_shutdown(self, op, req): 5.22 - #val = self.xd.domain_shutdown(self.dom.id) 5.23 fn = FormFn(self.xd.domain_shutdown, 5.24 [['dom', 'int'], 5.25 ['reason', 'str']]) 5.26 @@ -202,8 +209,22 @@ class SrvDomain(SrvDir): 5.27 req.write('<form method="post" action="%s">' % req.prePathURL()) 5.28 req.write('<input type="submit" name="op" value="unpause">') 5.29 req.write('<input type="submit" name="op" value="pause">') 5.30 + req.write('<input type="submit" name="op" value="destroy">') 5.31 + req.write('</form>') 5.32 + 5.33 + req.write('<form method="post" action="%s">' % req.prePathURL()) 5.34 req.write('<input type="submit" name="op" value="shutdown">') 5.35 - req.write('<input type="submit" name="op" value="destroy">') 5.36 + req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff<br>') 5.37 + req.write('<input type="radio" name="reason" value="halt">Halt<br>') 5.38 + req.write('<input type="radio" name="reason" value="reboot">Reboot<br>') 5.39 + req.write('</form>') 5.40 + 5.41 + req.write('<form method="post" action="%s">' % req.prePathURL()) 5.42 + req.write('<br><input type="submit" name="op" value="save">') 5.43 + req.write('To file: <input type="text" name="file">') 5.44 + req.write('</form>') 5.45 + 5.46 + req.write('<form method="post" action="%s">' % req.prePathURL()) 5.47 req.write('<br><input type="submit" name="op" value="migrate">') 5.48 - req.write('To: <input type="text" name="destination">') 5.49 + req.write('To host: <input type="text" name="destination">') 5.50 req.write('</form>')
6.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py Mon Jul 12 14:18:52 2004 +0000 6.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Mon Jul 12 14:24:09 2004 +0000 6.3 @@ -105,7 +105,10 @@ class SrvDomainDir(SrvDir): 6.4 6.5 def op_restore(self, op, req): 6.6 """Restore a domain from file. 6.7 + 6.8 + @return: deferred 6.9 """ 6.10 + #todo: return is deferred. May need ok and err callbacks. 6.11 fn = FormFn(self.xd.domain_restore, 6.12 [['file', 'str']]) 6.13 val = fn(req.args) 6.14 @@ -154,9 +157,10 @@ class SrvDomainDir(SrvDir): 6.15 req.write('<button type="submit" name="op" value="create">Create Domain</button>') 6.16 req.write('Config <input type="file" name="config"><br>') 6.17 req.write('</form>') 6.18 + 6.19 req.write('<form method="post" action="%s" enctype="multipart/form-data">' 6.20 % req.prePathURL()) 6.21 - req.write('<button type="submit" name="op" value="create">Restore Domain</button>') 6.22 + req.write('<button type="submit" name="op" value="restore">Restore Domain</button>') 6.23 req.write('State <input type="string" name="state"><br>') 6.24 req.write('</form>') 6.25
7.1 --- a/tools/xfrd/Makefile Mon Jul 12 14:18:52 2004 +0000 7.2 +++ b/tools/xfrd/Makefile Mon Jul 12 14:24:09 2004 +0000 7.3 @@ -18,6 +18,9 @@ INCLUDES += -I $(XEN_LINUX_INCLUDE) 7.4 vpath %.h $(XEN_XU) 7.5 INCLUDES += -I $(XEN_XU) 7.6 7.7 +vpath %.h $(XEN_LIBXC) 7.8 +INCLUDES += -I $(XEN_LIBXC) 7.9 + 7.10 vpath %c $(XEN_LIBXUTIL) 7.11 INCLUDES += -I $(XEN_LIBXUTIL) 7.12 7.13 @@ -28,7 +31,9 @@ UTIL_LIB_OBJ = $(UTIL_LIB_SRC:.c=.o) 7.14 XFRD_PROG_OBJ = $(XFRD_PROG_SRC:.c=.o) 7.15 XFRD_PROG_OBJ += $(UTIL_LIB) 7.16 7.17 -CPPFLAGS += -D _XEN_XFR_STUB_ 7.18 +# Flag controlling whether to use stubs. 7.19 +# Define to use stubs, undefine to use the real Xen functions. 7.20 +#CPPFLAGS += -D _XEN_XFR_STUB_ 7.21 7.22 CFLAGS += -g 7.23 CFLAGS += -Wall 7.24 @@ -38,15 +43,31 @@ CFLAGS += $(INCLUDES) 7.25 CFLAGS += -Wp,-MD,.$(@F).d 7.26 PROG_DEP = .*.d 7.27 7.28 -#LDFLAGS += -L $(COMPRESS_DIR) -lz 7.29 +#$(warning XFRD_PROG_OBJ= $(XFRD_PROG_OBJ)) 7.30 +#$(warning UTIL_LIB= $(UTIL_LIB)) 7.31 +#$(warning UTIL_LIB_OBJ= $(UTIL_LIB_OBJ)) 7.32 + 7.33 +# Libraries for xfrd. 7.34 +XFRD_LIBS := 7.35 + 7.36 +XFRD_LIBS += -L $(XEN_LIBXC) -lxc 7.37 +XFRD_LIBS += -L $(XEN_LIBXUTIL) -lxutil 7.38 7.39 -$(warning XFRD_PROG_OBJ= $(XFRD_PROG_OBJ)) 7.40 -$(warning UTIL_LIB= $(UTIL_LIB)) 7.41 -$(warning UTIL_LIB_OBJ= $(UTIL_LIB_OBJ)) 7.42 +# zlib library. 7.43 +XFRD_LIBS += -lz 7.44 + 7.45 +CURL_FLAGS = $(shell curl-config --cflags) 7.46 +CURL_LIBS = $(shell curl-config --libs) 7.47 +CFLAGS += $(CURL_FLAGS) 7.48 +# libcurl libraries. 7.49 +XFRD_LIBS += $(CURL_LIBS) 7.50 + 7.51 +#$(warning XFRD_LIBS = $(XFRD_LIBS)) 7.52 7.53 all: xfrd 7.54 7.55 -xfrd: $(XFRD_PROG_OBJ) -lz 7.56 +xfrd: $(XFRD_PROG_OBJ) 7.57 + $(CC) -o $@ $^ $(XFRD_LIBS) 7.58 7.59 .PHONY: install 7.60 install: xfrd 7.61 @@ -64,5 +85,6 @@ clean: 7.62 $(RM) *.o *.a *.so *~ xfrd 7.63 $(RM) $(PROG_DEP) 7.64 7.65 +$(XFRD_PROG_OBJ): Makefile 7.66 -include $(PROG_DEP) 7.67
8.1 --- a/tools/xfrd/xen_domain.c Mon Jul 12 14:18:52 2004 +0000 8.2 +++ b/tools/xfrd/xen_domain.c Mon Jul 12 14:24:09 2004 +0000 8.3 @@ -3,18 +3,43 @@ 8.4 #include <stdio.h> 8.5 8.6 #ifndef _XEN_XFR_STUB_ 8.7 -#include "dom0_defs.h" 8.8 -#include "mem_defs.h" 8.9 +#include "xc.h" 8.10 +#include "xc_io.h" 8.11 #endif 8.12 8.13 #include "xen_domain.h" 8.14 #include "marshal.h" 8.15 #include "xdr.h" 8.16 +#include "xfrd.h" 8.17 8.18 #define MODULE_NAME "XFRD" 8.19 #define DEBUG 1 8.20 #include "debug.h" 8.21 8.22 +#ifndef _XEN_XFR_STUB_ 8.23 +static int domain_suspend(u32 dom, void *data){ 8.24 + Conn *xend = data; 8.25 + 8.26 + return xfr_vm_suspend(xend, dom); 8.27 +} 8.28 + 8.29 +static int xc_handle = 0; 8.30 + 8.31 +int xcinit(void){ 8.32 + if(xc_handle <= 0){ 8.33 + xc_handle = xc_interface_open(); 8.34 + } 8.35 + return xc_handle; 8.36 +} 8.37 + 8.38 +void xcfini(void){ 8.39 + if(xc_handle > 0){ 8.40 + xc_interface_close(xc_handle); 8.41 + xc_handle = 0; 8.42 + } 8.43 +} 8.44 +#endif 8.45 + 8.46 /** Write domain state. 8.47 * 8.48 * At some point during this the domain is suspended, and then there's no way back. 8.49 @@ -22,10 +47,10 @@ 8.50 */ 8.51 int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n){ 8.52 int err = 0; 8.53 +#ifdef _XEN_XFR_STUB_ 8.54 char buf[1024]; 8.55 int n, k, d, buf_n; 8.56 dprintf("> dom=%d\n", dom); 8.57 -#ifdef _XEN_XFR_STUB_ 8.58 err = marshal_uint32(io, dom); 8.59 if(err) goto exit; 8.60 err = marshal_string(io, vmconfig, vmconfig_n); 8.61 @@ -43,6 +68,15 @@ int xen_domain_snd(Conn *xend, IOStream 8.62 8.63 exit: 8.64 #else 8.65 + XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt; 8.66 + dprintf("> dom=%d\n", dom); 8.67 + ioctxt->io = io; 8.68 + ioctxt->info = iostdout; 8.69 + ioctxt->err = iostderr; 8.70 + ioctxt->data = xend; 8.71 + ioctxt->suspend = domain_suspend; 8.72 + 8.73 + err = xc_linux_save(xcinit(), ioctxt); 8.74 #endif 8.75 dprintf("< err=%d\n", err); 8.76 return err; 8.77 @@ -53,10 +87,10 @@ int xen_domain_snd(Conn *xend, IOStream 8.78 */ 8.79 int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n){ 8.80 int err = 0; 8.81 +#ifdef _XEN_XFR_STUB_ 8.82 char buf[1024]; 8.83 int n, k, d, buf_n; 8.84 dprintf(">\n"); 8.85 -#ifdef _XEN_XFR_STUB_ 8.86 err = unmarshal_uint32(io, dom); 8.87 if(err) goto exit; 8.88 err = unmarshal_new_string(io, vmconfig, vmconfig_n); 8.89 @@ -72,19 +106,104 @@ int xen_domain_rcv(IOStream *io, uint32_ 8.90 } 8.91 exit: 8.92 #else 8.93 + XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt; 8.94 + dprintf(">\n"); 8.95 + ioctxt->io = io; 8.96 + ioctxt->info = iostdout; 8.97 + ioctxt->err = iostderr; 8.98 + 8.99 + err = xc_linux_restore(xcinit(), ioctxt); 8.100 #endif 8.101 dprintf("< err=%d\n", err); 8.102 return err; 8.103 } 8.104 8.105 -/** Configure a new domain. Talk to xend. Use libcurl? 8.106 +#include <curl/curl.h> 8.107 + 8.108 +static int do_curl_global_init = 1; 8.109 + 8.110 +static CURL *curlinit(void){ 8.111 + if(do_curl_global_init){ 8.112 + do_curl_global_init = 0; 8.113 + curl_global_init(CURL_GLOBAL_ALL); 8.114 + } 8.115 + return curl_easy_init(); 8.116 +} 8.117 + 8.118 +/** Configure a new domain. Talk to xend using libcurl. 8.119 */ 8.120 int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){ 8.121 int err = 0; 8.122 - dprintf(">\n"); 8.123 + CURL *curl = NULL; 8.124 + CURLcode curlcode = 0; 8.125 + char domainurl[128] = {}; 8.126 + int domainurl_n = sizeof(domainurl) - 1; 8.127 + int n; 8.128 + struct curl_httppost *form = NULL, *last = NULL; 8.129 + CURLFORMcode formcode = 0; 8.130 + 8.131 + dprintf("> dom=%u\n", dom); 8.132 + curl = curlinit(); 8.133 + if(!curl){ 8.134 + eprintf("> Could not init libcurl\n"); 8.135 + err = -ENOMEM; 8.136 + goto exit; 8.137 + } 8.138 + n = snprintf(domainurl, domainurl_n, 8.139 + "http://localhost:%d/xend/domain/%u", XEND_PORT, dom); 8.140 + if(n <= 0 || n >= domainurl_n){ 8.141 + err = -ENOMEM; 8.142 + eprintf("Out of memory in url.\n"); 8.143 + goto exit; 8.144 + } 8.145 + // Config field - set from vmconfig. 8.146 + formcode = curl_formadd(&form, &last, 8.147 + CURLFORM_COPYNAME, "config", 8.148 + CURLFORM_BUFFER, "config", 8.149 + CURLFORM_BUFFERPTR, vmconfig, 8.150 + CURLFORM_BUFFERLENGTH, vmconfig_n, 8.151 + CURLFORM_CONTENTTYPE, "application/octet-stream", 8.152 + CURLFORM_END); 8.153 + if(formcode){ 8.154 + eprintf("> Error adding config field.\n"); 8.155 + goto exit; 8.156 + } 8.157 + // Op field. 8.158 + formcode = curl_formadd(&form, &last, 8.159 + CURLFORM_COPYNAME, "op", 8.160 + CURLFORM_COPYCONTENTS, "configure", 8.161 + CURLFORM_END); 8.162 + 8.163 + if(formcode){ 8.164 + eprintf("> Error adding op field.\n"); 8.165 + goto exit; 8.166 + } 8.167 + // No progress meter. 8.168 + //curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); 8.169 + // Completely quiet. 8.170 + //curl_easy_setopt(curl, CURLOPT_MUTE, 1); 8.171 + // Set the URL. 8.172 + curl_easy_setopt(curl, CURLOPT_URL, domainurl); 8.173 + // POST the form. 8.174 + curl_easy_setopt(curl, CURLOPT_HTTPPOST, form); 8.175 + dprintf("> curl perform...\n"); 8.176 #ifdef _XEN_XFR_STUB_ 8.177 -#else 8.178 -#endif 8.179 + dprintf("> _XEN_XFR_STUB_ defined - not calling xend\n"); 8.180 + curlcode = 0; 8.181 +#else 8.182 + curlcode = curl_easy_perform(curl); 8.183 +#endif 8.184 + exit: 8.185 + if(curl) curl_easy_cleanup(curl); 8.186 + if(form) curl_formfree(form); 8.187 + if(formcode){ 8.188 + dprintf("> formcode=%d\n", formcode); 8.189 + err = -EINVAL; 8.190 + } 8.191 + if(curlcode){ 8.192 + dprintf("> curlcode=%d\n", curlcode); 8.193 + err = -EINVAL; 8.194 + } 8.195 dprintf("< err=%d\n", err); 8.196 return err; 8.197 }
9.1 --- a/tools/xfrd/xfrd.c Mon Jul 12 14:18:52 2004 +0000 9.2 +++ b/tools/xfrd/xfrd.c Mon Jul 12 14:24:09 2004 +0000 9.3 @@ -93,22 +93,26 @@ Sxpr oxfr_configure; // (xfr.configure < 9.4 Sxpr oxfr_err; // (xfr.err <code>) 9.5 Sxpr oxfr_hello; // (xfr.hello <major> <minor>) 9.6 Sxpr oxfr_migrate; // (xfr.migrate <vmid> <vmconfig> <host> <port>) 9.7 -Sxpr oxfr_ok; // (xfr.ok <value>) 9.8 +Sxpr oxfr_migrate_ok;// (xfr.migrate.ok <value>) 9.9 Sxpr oxfr_progress; // (xfr.progress <percent> <rate: kb/s>) 9.10 Sxpr oxfr_save; // (xfr.save <vmid> <vmconfig> <file>) 9.11 -Sxpr oxfr_suspend; // (xfr.suspend <vmid>) 9.12 +Sxpr oxfr_save_ok; // (xfr.save.ok) 9.13 +Sxpr oxfr_vm_suspend;// (xfr.vm.suspend <vmid>) 9.14 Sxpr oxfr_xfr; // (xfr.xfr <vmid>) 9.15 +Sxpr oxfr_xfr_ok; // (xfr.xfr.ok <vmid>) 9.16 9.17 void xfr_init(void){ 9.18 - oxfr_configure = intern("xfr.configure"); 9.19 - oxfr_err = intern("xfr.err"); 9.20 - oxfr_hello = intern("xfr.hello"); 9.21 - oxfr_migrate = intern("xfr.migrate"); 9.22 - oxfr_ok = intern("xfr.ok"); 9.23 - oxfr_progress = intern("xfr.progress"); 9.24 - oxfr_save = intern("xfr.save"); 9.25 - oxfr_suspend = intern("xfr.suspend"); 9.26 - oxfr_xfr = intern("xfr.xfr"); 9.27 + oxfr_configure = intern("xfr.configure"); 9.28 + oxfr_err = intern("xfr.err"); 9.29 + oxfr_hello = intern("xfr.hello"); 9.30 + oxfr_migrate = intern("xfr.migrate"); 9.31 + oxfr_migrate_ok = intern("xfr.migrate.ok"); 9.32 + oxfr_progress = intern("xfr.progress"); 9.33 + oxfr_save = intern("xfr.save"); 9.34 + oxfr_save_ok = intern("xfr.save.ok"); 9.35 + oxfr_vm_suspend = intern("xfr.vm.suspend"); 9.36 + oxfr_xfr = intern("xfr.xfr"); 9.37 + oxfr_xfr_ok = intern("xfr.xfr.ok"); 9.38 } 9.39 9.40 #ifndef TRUE 9.41 @@ -518,11 +522,27 @@ int xfr_send_xfr(Conn *conn, uint32_t vm 9.42 return (err < 0 ? err : 0); 9.43 } 9.44 9.45 -int xfr_send_ok(Conn *conn, uint32_t vmid){ 9.46 +int xfr_send_xfr_ok(Conn *conn, uint32_t vmid){ 9.47 int err = 0; 9.48 9.49 err = IOStream_print(conn->out, "(%s %d)", 9.50 - atom_name(oxfr_ok), vmid); 9.51 + atom_name(oxfr_xfr_ok), vmid); 9.52 + return (err < 0 ? err : 0); 9.53 +} 9.54 + 9.55 +int xfr_send_migrate_ok(Conn *conn, uint32_t vmid){ 9.56 + int err = 0; 9.57 + 9.58 + err = IOStream_print(conn->out, "(%s %d)", 9.59 + atom_name(oxfr_migrate_ok), vmid); 9.60 + return (err < 0 ? err : 0); 9.61 +} 9.62 + 9.63 +int xfr_send_save_ok(Conn *conn){ 9.64 + int err = 0; 9.65 + 9.66 + err = IOStream_print(conn->out, "(%s)", 9.67 + atom_name(oxfr_save_ok)); 9.68 return (err < 0 ? err : 0); 9.69 } 9.70 9.71 @@ -530,10 +550,22 @@ int xfr_send_suspend(Conn *conn, uint32_ 9.72 int err = 0; 9.73 9.74 err = IOStream_print(conn->out, "(%s %d)", 9.75 - atom_name(oxfr_suspend), vmid); 9.76 + atom_name(oxfr_vm_suspend), vmid); 9.77 return (err < 0 ? err : 0); 9.78 } 9.79 9.80 +/** Suspend a vm on behalf of save/migrate. 9.81 + */ 9.82 +int xfr_vm_suspend(Conn *xend, uint32_t vmid){ 9.83 + int err = 0; 9.84 + err = xfr_send_suspend(xend, vmid); 9.85 + if(err) goto exit; 9.86 + IOStream_flush(xend->out); 9.87 + err = xfr_response(xend); 9.88 + exit: 9.89 + return err; 9.90 +} 9.91 + 9.92 /** Get vm state. Send transfer message. 9.93 * 9.94 * @param peer connection 9.95 @@ -561,7 +593,7 @@ int xfr_send_state(XfrState *state, Conn 9.96 int errcode; 9.97 err = intof(sxpr_childN(sxpr, 0, ONONE), &errcode); 9.98 if(!err) err = errcode; 9.99 - } else if(sxpr_elementp(sxpr, oxfr_ok)){ 9.100 + } else if(sxpr_elementp(sxpr, oxfr_xfr_ok)){ 9.101 // Ok - get the new domain id. 9.102 err = intof(sxpr_childN(sxpr, 0, ONONE), &state->vmid_new); 9.103 xfr_error(peer, err); 9.104 @@ -592,7 +624,7 @@ int xfr_send_done(XfrState *state, Conn 9.105 err = xfr_error(xend, first_err); 9.106 } else { 9.107 // Report new domain id to xend. 9.108 - err = xfr_send_ok(xend, state->vmid_new); 9.109 + err = xfr_send_migrate_ok(xend, state->vmid_new); 9.110 } 9.111 9.112 XfrState_set_err(state, err); 9.113 @@ -683,6 +715,11 @@ int xfr_save(Args *args, XfrState *state 9.114 goto exit; 9.115 } 9.116 err = xen_domain_snd(xend, io, state->vmid, state->vmconfig, state->vmconfig_n); 9.117 + if(err){ 9.118 + err = xfr_error(xend, err); 9.119 + } else { 9.120 + err = xfr_send_save_ok(xend); 9.121 + } 9.122 exit: 9.123 if(io){ 9.124 IOStream_close(io); 9.125 @@ -709,7 +746,7 @@ int xfr_recv(Args *args, XfrState *state 9.126 if(err) goto exit; 9.127 9.128 // Report new domain id to peer. 9.129 - err = xfr_send_ok(peer, state->vmid_new); 9.130 + err = xfr_send_xfr_ok(peer, state->vmid_new); 9.131 if(err) goto exit; 9.132 // Get the final ok. 9.133 err = xfr_response(peer);
10.1 --- a/tools/xfrd/xfrd.h Mon Jul 12 14:18:52 2004 +0000 10.2 +++ b/tools/xfrd/xfrd.h Mon Jul 12 14:24:09 2004 +0000 10.3 @@ -2,7 +2,7 @@ 10.4 #define _XFRD_XFRD_H_ 10.5 10.6 /** Xend port in host order. */ 10.7 -#define XEND_PORT 8001 10.8 +#define XEND_PORT 8000 10.9 10.10 /** Xfrd port in host order. */ 10.11 #define XFRD_PORT 8002 10.12 @@ -11,4 +11,6 @@ 10.13 #define XFR_PROTO_MAJOR 1 10.14 #define XFR_PROTO_MINOR 0 10.15 10.16 +struct Conn; 10.17 +extern int xfr_vm_suspend(struct Conn *xend, uint32_t vmid); 10.18 #endif