# HG changeset patch # User iap10@labyrinth.cl.cam.ac.uk # Date 1096814111 0 # Node ID 98bdf2c88015728748c86e432e19c25644c0ea67 # Parent 80fce5fd8284e3f5c98372acddf30e4be851e4dd# Parent b661254cb10b0c8a8c76c30a1309a430dda7b2dc bitkeeper revision 1.1159.1.201 (41600e1fkVMoQU0dVgk1h6vT502hEg) Merge diff -r 80fce5fd8284 -r 98bdf2c88015 tools/libxc/xc.h --- a/tools/libxc/xc.h Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/libxc/xc.h Sun Oct 03 14:35:11 2004 +0000 @@ -75,9 +75,10 @@ int xc_shadow_control(int xc_handle, xc_shadow_control_stats_t *stats); -#define XCFLAGS_VERBOSE 1 -#define XCFLAGS_LIVE 2 -#define XCFLAGS_DEBUG 4 +#define XCFLAGS_VERBOSE 1 +#define XCFLAGS_LIVE 2 +#define XCFLAGS_DEBUG 4 +#define XCFLAGS_CONFIGURE 8 struct XcIOContext; int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt); diff -r 80fce5fd8284 -r 98bdf2c88015 tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/libxc/xc_linux_restore.c Sun Oct 03 14:35:11 2004 +0000 @@ -243,6 +243,15 @@ int xc_linux_restore(int xc_handle, XcIO } shared_info_frame = op.u.getdomaininfo.shared_info_frame; + if(ioctxt->flags & XCFLAGS_CONFIGURE) + { + if(xcio_configure_domain(ioctxt)) + { + xcio_error(ioctxt, "Configuring domain failed"); + goto out; + } + } + /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) { diff -r 80fce5fd8284 -r 98bdf2c88015 tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/python/xen/xend/XendDomain.py Sun Oct 03 14:35:11 2004 +0000 @@ -211,9 +211,9 @@ class XendDomain: @param id: domain id @param notify: send a domain died event if true """ - for info in self.domain_by_name.values(): + for (k, info) in self.domain_by_name.items(): if info.id == id: - del self.domain_by_name[info.name] + del self.domain_by_name[k] if id in self.domain_by_id: info = self.domain_by_id[id] del self.domain_by_id[id] @@ -408,11 +408,15 @@ class XendDomain: @return: deferred """ - def cbok(dominfo): - self._add_domain(dominfo) - return dominfo - deferred = XendDomainInfo.vm_restore(src, progress=progress) - deferred.addCallback(cbok) + if 0: + def cbok(dominfo): + self._add_domain(dominfo) + return dominfo + deferred = XendDomainInfo.vm_restore(src, progress=progress) + deferred.addCallback(cbok) + else: + xmigrate = XendMigrate.instance() + deferred = xmigrate.restore_begin(src) return deferred def domain_get(self, id): diff -r 80fce5fd8284 -r 98bdf2c88015 tools/python/xen/xend/XendMigrate.py --- a/tools/python/xen/xend/XendMigrate.py Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/python/xen/xend/XendMigrate.py Sun Oct 03 14:35:11 2004 +0000 @@ -302,6 +302,19 @@ class XendMigrateInfo(XfrdInfo): self.dst_port, self.live ]) +## def xfr_vm_suspend(self, xfrd, val): +## def cbok(val): +## # Special case for localhost: destroy devices early. +## if self.dst_host in ["localhost", "127.0.0.1"]: +## self.dominfo.restart_cancel() +## self.dominfo.cleanup() +## self.dominfo.destroy_console() +## return val + +## d = XfrdInfo.xfr_vm_suspend(self, xfrd, val) +## d.addCallback(cbok) +## return d + def xfr_migrate_ok(self, xfrd, val): dom = int(sxp.child0(val)) self.state = 'ok' @@ -376,7 +389,35 @@ class XendSaveInfo(XfrdInfo): [ self.dominfo.name, self.dominfo.id, self.state, self.sxpr() ]) +class XendRestoreInfo(XfrdInfo): + """Representation of a restore in-progress and its interaction with xfrd. + """ + def __init__(self, xid, file): + XfrdInfo.__init__(self) + self.xid = xid + self.state = 'begin' + self.file = file + + def sxpr(self): + sxpr = ['restore', + ['id', self.xid], + ['file', self.file] ] + return sxpr + + def request(self, xfrd): + print '***request>', self.file + log.info('restore BEGIN: ' + str(self.sxpr())) + xfrd.request(['xfr.restore', self.file ]) + + def xfr_restore_ok(self, xfrd, val): + dom = int(sxp.child0(val)) + dominfo = self.xd.domain_get(dom) + self.state = 'ok' + if not self.deferred.called: + self.deferred.callback(dominfo) + + class XendMigrate: """External api for interaction with xfrd for migrate and save. Singleton. @@ -472,6 +513,12 @@ class XendMigrate: info = XendSaveInfo(xid, dominfo, file) return self.session_begin(info) + def restore_begin(self, file): + xid = self.nextid() + info = XendRestoreInfo(xid, file) + return self.session_begin(info) + + def instance(): global inst try: diff -r 80fce5fd8284 -r 98bdf2c88015 tools/python/xen/xend/server/SrvDomainDir.py --- a/tools/python/xen/xend/server/SrvDomainDir.py Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Sun Oct 03 14:35:11 2004 +0000 @@ -45,7 +45,7 @@ class SrvDomainDir(SrvDir): errmsg = '' try: configstring = req.args.get('config')[0] - print 'config:', configstring + #print 'op_create>', 'config:', configstring pin = sxp.Parser() pin.input(configstring) pin.input_eof() diff -r 80fce5fd8284 -r 98bdf2c88015 tools/xfrd/xen_domain.c --- a/tools/xfrd/xen_domain.c Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/xfrd/xen_domain.c Sun Oct 03 14:35:11 2004 +0000 @@ -108,7 +108,10 @@ int xen_domain_snd(Conn *xend, IOStream /** Receive domain state. * Create a new domain and store the received state into it. */ -int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n){ +int xen_domain_rcv(IOStream *io, + uint32_t *dom, + char **vmconfig, int *vmconfig_n, + int *configured){ int err = 0; #ifdef _XEN_XFR_STUB_ char buf[1024]; @@ -135,11 +138,15 @@ int xen_domain_rcv(IOStream *io, uint32_ ioctxt->info = iostdout; ioctxt->err = iostderr; ioctxt->configure = domain_configure; + if(!configured){ + ioctxt->flags |= XCFLAGS_CONFIGURE; + } err = xc_linux_restore(xcinit(), ioctxt); *dom = ioctxt->domain; *vmconfig = ioctxt->vmconfig; *vmconfig_n = ioctxt->vmconfig_n; + *configured = (ioctxt->flags & XCFLAGS_CONFIGURE); #endif dprintf("< err=%d\n", err); return err; diff -r 80fce5fd8284 -r 98bdf2c88015 tools/xfrd/xen_domain.h --- a/tools/xfrd/xen_domain.h Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/xfrd/xen_domain.h Sun Oct 03 14:35:11 2004 +0000 @@ -11,7 +11,10 @@ extern int xen_domain_snd(Conn *xend, IO uint32_t dom, char *vmconfig, int vmconfig_n, int live); -extern int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n); +extern int xen_domain_rcv(IOStream *io, + uint32_t *dom, + char **vmconfig, int *vmconfig_n, + int *configured); extern int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n); diff -r 80fce5fd8284 -r 98bdf2c88015 tools/xfrd/xfrd.c --- a/tools/xfrd/xfrd.c Sat Oct 02 14:25:55 2004 +0000 +++ b/tools/xfrd/xfrd.c Sun Oct 03 14:35:11 2004 +0000 @@ -99,6 +99,8 @@ Sxpr oxfr_hello; // (xfr.hello ) Sxpr oxfr_migrate_ok;// (xfr.migrate.ok ) Sxpr oxfr_progress; // (xfr.progress ) +Sxpr oxfr_restore; // (xfr.restore ) +Sxpr oxfr_restore_ok;// (xfr.restore.ok ) Sxpr oxfr_save; // (xfr.save ) Sxpr oxfr_save_ok; // (xfr.save.ok) Sxpr oxfr_vm_destroy;// (xfr.vm.destroy ) @@ -113,6 +115,8 @@ void xfr_init(void){ oxfr_migrate = intern("xfr.migrate"); oxfr_migrate_ok = intern("xfr.migrate.ok"); oxfr_progress = intern("xfr.progress"); + oxfr_restore = intern("xfr.restore"); + oxfr_restore_ok = intern("xfr.restore.ok"); oxfr_save = intern("xfr.save"); oxfr_save_ok = intern("xfr.save.ok"); oxfr_vm_destroy = intern("xfr.vm.destroy"); @@ -540,6 +544,14 @@ int xfr_send_migrate_ok(Conn *conn, uint return (err < 0 ? err : 0); } +int xfr_send_restore_ok(Conn *conn, uint32_t vmid){ + int err = 0; + + err = IOStream_print(conn->out, "(%s %d)", + atom_name(oxfr_restore_ok), vmid); + return (err < 0 ? err : 0); +} + int xfr_send_save_ok(Conn *conn){ int err = 0; @@ -777,6 +789,46 @@ int xfr_save(Args *args, XfrState *state return err; } +/** Restore a vm from file. + * + * @return 0 on success, error code otherwise + */ +int xfr_restore(Args *args, XfrState *state, Conn *xend, char *file){ + int err = 0; + IOStream *io = NULL; + int configured=0; + + dprintf("> file=%s\n", file); + io = gzip_stream_fopen(file, "rb"); + if(!io){ + eprintf("> Failed to open %s\n", file); + err = -EINVAL; + goto exit; + } + err = xen_domain_rcv(io, + &state->vmid_new, + &state->vmconfig, &state->vmconfig_n, + &configured); + if(err) goto exit; + if(!configured){ + err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n); + if(err) goto exit; + } + err = xen_domain_unpause(state->vmid_new); + exit: + if(io){ + IOStream_close(io); + IOStream_free(io); + } + if(err){ + xfr_error(xend, err); + } else { + xfr_send_restore_ok(xend, state->vmid_new); + } + dprintf("< err=%d\n", err); + return err; +} + /** Accept the transfer of a vm from another node. * * @param peer connection @@ -787,17 +839,31 @@ int xfr_recv(Args *args, XfrState *state int err = 0; time_t t0 = time(NULL), t1; Sxpr sxpr; + int configured=0; - dprintf(">\n"); - err = xen_domain_rcv(peer->in, &state->vmid_new, &state->vmconfig, &state->vmconfig_n); + dprintf("> peer=%s\n", inet_ntoa(peer->addr.sin_addr)); + // If receiving from localhost set configured so that that xen_domain_rcv() + // does not attempt to configure the new domain. This is because the old + // domain still exists and will make it fail. + if(peer->addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)){ + dprintf("> Peer is localhost\n"); + configured = 1; + } + err = xen_domain_rcv(peer->in, + &state->vmid_new, + &state->vmconfig, &state->vmconfig_n, + &configured); if(err) goto exit; // Read from the peer. This is just so we wait before configuring. // When migrating to the same host the peer must destroy the domain // before we configure the new one. err = Conn_sxpr(peer, &sxpr); if(err) goto exit; - err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n); - if(err) goto exit; + if(!configured){ + dprintf("> Configuring...\n"); + err = xen_domain_configure(state->vmid_new, state->vmconfig, state->vmconfig_n); + if(err) goto exit; + } err = xen_domain_unpause(state->vmid_new); if(err) goto exit; // Report new domain id to peer. @@ -878,6 +944,17 @@ int xfrd_service(Args *args, int peersoc if(err) goto exit; err = xfr_save(args, state, conn, file); + } else if(sxpr_elementp(sxpr, oxfr_restore)){ + // Restore message from xend. + char *file; + XfrState _state = {}, *state = &_state; + int n = 0; + + dprintf("> xfr.restore\n"); + err = stringof(sxpr_childN(sxpr, n++, ONONE), &file); + if(err) goto exit; + err = xfr_restore(args, state, conn, file); + } else if(sxpr_elementp(sxpr, oxfr_xfr)){ // Xfr message from peer xfrd. XfrState _state = {}, *state = &_state; @@ -1144,9 +1221,11 @@ int main(int argc, char *argv[]){ int long_index = 0; static const char * LOGFILE = "/var/log/xfrd.log"; +#ifndef DEBUG freopen(LOGFILE, "w+", stdout); fclose(stderr); stderr = stdout; +#endif dprintf(">\n"); set_defaults(args); while(1){