From e1ab5a1d0d6898c4f468bb1ba74c6fd1fcc803d7 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 21 Oct 2004 16:07:17 +0000 Subject: [PATCH 1/3] bitkeeper revision 1.1159.116.3 (4177deb5O2BSukkVC4mhGVTFnJJiwA) Fix problem with block device recreation after xend restart. Save device state info in the domain record and use when the domain info and devices are recreated. --- tools/python/xen/xend/XendDomainInfo.py | 85 +++++---- tools/python/xen/xend/server/blkif.py | 191 +++++++++++---------- tools/python/xen/xend/server/controller.py | 7 + tools/python/xen/xend/server/netif.py | 2 + 4 files changed, 160 insertions(+), 125 deletions(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 8cf30ffd25..472711ab11 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -33,8 +33,6 @@ xend = server.SrvDaemon.instance() from XendError import VmError -from server.blkif import blkdev_name_to_number - """The length of domain names that Xen can handle. The names stored in Xen itself are not used for much, and xend can handle domain names of any length. @@ -92,24 +90,6 @@ def shutdown_reason(code): """ return shutdown_reasons.get(code, "?") -def make_disk(vm, config, uname, dev, mode, recreate=0): - """Create a virtual disk device for a domain. - - @param vm: vm - @param uname: device to export - @param dev: device name in domain - @param mode: read/write mode - @param recreate: recreate flag (after xend restart) - @return: deferred - """ - idx = vm.next_device_index('vbd') - # todo: The 'dev' should be looked up in the context of the domain. - vdev = blkdev_name_to_number(dev) - if not vdev: - raise VmError("vbd: Device not found: uname=%s dev=%s" % (uname, dev)) - ctrl = xend.blkif_create(vm.dom, recreate=recreate) - return ctrl.attachDevice(idx, config, uname, vdev, mode, recreate=recreate) - def vif_up(iplist): """send an unsolicited ARP reply for all non link-local IP addresses. @@ -222,6 +202,7 @@ def vm_recreate(savedinfo, info): """ vm = XendDomainInfo() vm.recreate = 1 + vm.savedinfo = savedinfo vm.setdom(info['dom']) #vm.name = info['name'] vm.memory = info['mem_kb']/1024 @@ -239,6 +220,7 @@ def vm_recreate(savedinfo, info): vm.name = info['name'] d = defer.succeed(vm) vm.recreate = 0 + vm.savedinfo = None return d def vm_restore(src, progress=0): @@ -336,6 +318,7 @@ class XendDomainInfo: self.restart_state = None self.restart_time = None self.console_port = None + self.savedinfo = None def setdom(self, dom): """Set the domain id. @@ -397,10 +380,21 @@ class XendDomainInfo: sxpr.append(['restart_state', self.restart_state]) if self.restart_time: sxpr.append(['restart_time', str(self.restart_time)]) + devs = self.sxpr_devices() + if devs: + sxpr.append(devs) if self.config: sxpr.append(['config', self.config]) return sxpr + def sxpr_devices(self): + sxpr = ['devices'] + for devs in self.devices.values(): + for dev in devs: + if hasattr(dev, 'sxpr'): + sxpr.append(dev.sxpr()) + return sxpr + def check_name(self, name): """Check if a vm name is valid. Valid names start with a non-digit and contain alphabetic characters, digits, or characters in '_-.:/+'. @@ -586,6 +580,25 @@ class XendDomainInfo: return d return None + def get_device_savedinfo(self, type, index): + val = None + if self.savedinfo is None: + return val + index = str(index) + devinfo = sxp.child(self.savedinfo, 'devices') + if devinfo is None: + return val + for d in sxp.children(devinfo, type): + dindex = sxp.child_value(d, 'index') + if dindex is None: continue + if str(dindex) == index: + val = d + break + return val + + def get_device_recreate(self, type, index): + return self.get_device_savedinfo(type, index) or self.recreate + def add_config(self, val): """Add configuration data to a virtual machine. @@ -840,7 +853,7 @@ class XendDomainInfo: def configure_memory(self): """Configure vm memory limit. """ - maxmem = sxp.get_child_value(self.config, "maxmem") + maxmem = sxp.child_value(self.config, "maxmem") if maxmem is None: maxmem = self.memory xc.domain_setmaxmem(self.dom, maxmem_kb = maxmem * 1024) @@ -1070,9 +1083,11 @@ def vm_dev_vif(vm, val, index, change=0): vmac = sxp.child_value(val, "mac") ctrl = xend.netif_create(vm.dom, recreate=vm.recreate) log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac)) - defer = ctrl.attachDevice(vif, val, recreate=vm.recreate) + recreate = vm.get_device_recreate('vif', index) + defer = ctrl.attachDevice(vif, val, recreate=recreate) def cbok(dev): dev.vifctl('up', vmname=vm.name) + dev.setIndex(index) vm.add_device('vif', dev) if change: dev.interfaceChanged() @@ -1088,23 +1103,19 @@ def vm_dev_vbd(vm, val, index, change=0): @param index: vbd index @return: deferred """ + idx = vm.next_device_index('vbd') uname = sxp.child_value(val, 'uname') - if not uname: - raise VmError('vbd: Missing uname') - dev = sxp.child_value(val, 'dev') - if not dev: - raise VmError('vbd: Missing dev') - mode = sxp.child_value(val, 'mode', 'r') - log.debug("Creating vbd dom=%d uname=%s dev=%s", vm.dom, uname, dev) - defer = make_disk(vm, val, uname, dev, mode, vm.recreate) - def fn(vbd): - vbd.dev = dev - vbd.uname = uname - vm.add_device('vbd', vbd) + log.debug("Creating vbd dom=%d uname=%s", vm.dom, uname) + ctrl = xend.blkif_create(vm.dom, recreate=vm.recreate) + recreate = vm.get_device_recreate('vbd', index) + defer = ctrl.attachDevice(idx, val, recreate=recreate) + def cbok(dev): + dev.setIndex(index) + vm.add_device('vbd', dev) if change: - vbd.interfaceChanged() - return vbd - defer.addCallback(fn) + dev.interfaceChanged() + return dev + defer.addCallback(cbok) return defer def parse_pci(val): diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index e2ba4af4ea..79998299cb 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -16,6 +16,46 @@ import channel import controller from messages import * + +def blkdev_name_to_number(name): + """Take the given textual block-device name (e.g., '/dev/sda1', + 'hda') and return the device number used by the OS. """ + + if re.match( '^/dev/', name ): + n = name + else: + n = '/dev/' + name + + try: + return os.stat(n).st_rdev + except Exception, ex: + log.debug("exception looking up device number for %s: %s", name, ex) + pass + + # see if this is a hex device number + if re.match( '^(0x)?[0-9a-fA-F]+$', name ): + return string.atoi(name,16) + + return None + +def blkdev_segment(name): + """Take the given block-device name (e.g. '/dev/sda1', 'hda') + and return a dictionary { device, start_sector, + nr_sectors, type } + device: Device number of the given partition + start_sector: Index of first sector of the partition + nr_sectors: Number of sectors comprising this partition + type: 'Disk' or identifying name for partition type + """ + val = None + n = blkdev_name_to_number(name) + if n: + val = { 'device' : n, + 'start_sector' : long(0), + 'nr_sectors' : long(1L<<63), + 'type' : 'Disk' } + return val + class BlkifBackendController(controller.BackendController): """ Handler for the 'back-end' channel to a block device driver domain. """ @@ -231,26 +271,70 @@ class BlkDev(controller.SplitDev): """Info record for a block device. """ - def __init__(self, idx, ctrl, config, vdev, mode, segment): + def __init__(self, idx, ctrl, config): controller.SplitDev.__init__(self, idx, ctrl) - self.config = config self.dev = None self.uname = None - self.vdev = vdev - self.mode = mode - self.device = segment['device'] - self.start_sector = segment['start_sector'] - self.nr_sectors = segment['nr_sectors'] + self.vdev = None + self.mode = None + self.type = None + self.params = None + self.node = None + self.device = None + self.start_sector = None + self.nr_sectors = None + self.configure(config) + + def configure(self, config): + self.config = config + self.uname = sxp.child_value(config, 'uname') + if not self.uname: + raise VmError('vbd: Missing uname') + # Split into type and type-specific params (which are passed to the + # type-specific control script). + (self.type, self.params) = string.split(self.uname, ':', 1) + self.dev = sxp.child_value(config, 'dev') + if not self.dev: + raise VmError('vbd: Missing dev') + self.mode = sxp.child_value(config, 'mode', 'r') + # todo: The 'dev' should be looked up in the context of the domain. + self.vdev = blkdev_name_to_number(self.dev) + if not self.vdev: + raise VmError('vbd: Device not found: %s' % self.dev) try: self.backendDomain = int(sxp.child_value(config, 'backend', '0')) except: raise XendError('invalid backend domain') + def recreate(self, savedinfo): + node = sxp.child_value(savedinfo, 'node') + self.setNode(node) + + def attach(self): + node = Blkctl.block('bind', self.type, self.params) + self.setNode(node) + return self.attachBackend() + + def unbind(self): + if self.node is None: return + log.debug("Unbinding vbd (type %s) from %s" + % (self.type, self.node)) + Blkctl.block('unbind', self.type, self.node) + + def setNode(self, node): + segment = blkdev_segment(node) + if not segment: + raise VmError("vbd: Segment not found: uname=%s" % self.uname) + self.node = node + self.device = segment['device'] + self.start_sector = segment['start_sector'] + self.nr_sectors = segment['nr_sectors'] + def readonly(self): return 'w' not in self.mode def sxpr(self): - val = ['blkdev', + val = ['vbd', ['idx', self.idx], ['vdev', self.vdev], ['device', self.device], @@ -259,13 +343,12 @@ class BlkDev(controller.SplitDev): val.append(['dev', self.dev]) if self.uname: val.append(['uname', self.uname]) + if self.node: + val.append(['node', self.node]) + if self.index is not None: + val.append(['index', self.index]) return val - def unbind(self): - log.debug("Unbinding block dev (type %s) from %s" - % (self.type, self.node)) - Blkctl.block('unbind', self.type, self.node) - def destroy(self, change=0): """Destroy the device. If 'change' is true notify the front-end interface. @@ -283,7 +366,7 @@ class BlkDev(controller.SplitDev): """ self.getBackendInterface().interfaceChanged() - def attach(self): + def attachBackend(self): """Attach the device to its controller. """ @@ -356,46 +439,6 @@ class BlkDev(controller.SplitDev): return d -def blkdev_name_to_number(name): - """Take the given textual block-device name (e.g., '/dev/sda1', - 'hda') and return the device number used by the OS. """ - - if not re.match( '^/dev/', name ): - n = '/dev/' + name - else: - n = name - - try: - return os.stat(n).st_rdev - except Exception, e: - print "blkdev_name_to_number> exception looking up device number for %s: %s" % (name, e) - pass - - # see if this is a hex device number - if re.match( '^(0x)?[0-9a-fA-F]+$', name ): - return string.atoi(name,16) - - return None - -def lookup_raw_partn(name): - """Take the given block-device name (e.g., '/dev/sda1', 'hda') - and return a dictionary { device, start_sector, - nr_sectors, type } - device: Device number of the given partition - start_sector: Index of first sector of the partition - nr_sectors: Number of sectors comprising this partition - type: 'Disk' or identifying name for partition type - """ - - n = blkdev_name_to_number(name) - if n: - return [ { 'device' : n, - 'start_sector' : long(0), - 'nr_sectors' : long(1L<<63), - 'type' : 'Disk' } ] - else: - return None - class BlkifController(controller.SplitController): """Block device interface controller. Handles all block devices for a domain. @@ -418,65 +461,37 @@ class BlkifController(controller.SplitController): val = ['blkif', ['dom', self.dom]] return val - def addDevice(self, idx, config, vdev, mode, segment): + def addDevice(self, idx, config): """Add a device to the device table. @param vdev: device index @type vdev: int - @param mode: read/write mode - @type mode: string - @param segment: segment - @type segment: int + @param config: device configuration @return: device @rtype: BlkDev """ if idx in self.devices: raise XendError('device exists: ' + str(idx)) - dev = BlkDev(idx, self, config, vdev, mode, segment) + dev = BlkDev(idx, self, config ) self.devices[idx] = dev return dev - def attachDevice(self, idx, config, uname, vdev, mode, recreate=0): + def attachDevice(self, idx, config, recreate=0): """Attach a device to the specified interface. On success the returned deferred will be called with the device. @param idx: device id @param config: device configuration - @param vdev: device index - @type vdev: int - @param mode: read/write mode - @type mode: string - @param segment: segment - @type segment: int @param recreate: if true it's being recreated (after xend restart) @type recreate: bool @return: deferred @rtype: Deferred """ - if not recreate: - # Split into type and type-specific details (which are passed to the - # type-specific control script). - type, dets = string.split(uname, ':', 1) - # Special case: don't bother calling a script for phy. Could - # alternatively provide a "do nothing" script for phy devices... - node = Blkctl.block('bind', type, dets) - - segments = lookup_raw_partn(node) - - if not segments: - raise VmError("vbd: Segments not found: uname=%s" % uname) - if len(segments) > 1: - raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname) - - segment = segments[0] - - dev = self.addDevice(idx, config, vdev, mode, segment) - + dev = self.addDevice(idx, config) if recreate: + dev.recreate(recreate) d = defer.succeed(dev) else: - dev.node = node - dev.type = type d = dev.attach() return d diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index 3721b9b3b3..c8962d4675 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -682,10 +682,17 @@ class SplitDev(Dev): def __init__(self, idx, controller): Dev.__init__(self, idx, controller) self.backendDomain = 0 + self.index = None def getBackendInterface(self): return self.controller.getBackendInterface(self.backendDomain) + def getIndex(self): + return self.index + + def setIndex(self, index): + self.index = index + diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 38e722347a..a0466b0e4c 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -198,6 +198,8 @@ class NetDev(controller.SplitDev): val.append(['evtchn', self.evtchn['port1'], self.evtchn['port2']]) + if self.index is not None: + val.append(['index', self.index]) return val def get_vifname(self): From 4a22a3ffb95d364a9f699ca7dcf4c18445acd69c Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 21 Oct 2004 16:11:03 +0000 Subject: [PATCH 2/3] bitkeeper revision 1.1159.116.4 (4177df97ZOvl759Lo38Gv7CY081ZCA) Add resource control parameter to migrate. --- tools/libxc/xc_io.h | 1 + tools/python/xen/xend/XendClient.py | 5 +++-- tools/python/xen/xend/XendDomain.py | 4 ++-- tools/python/xen/xend/XendMigrate.py | 13 ++++++++----- tools/python/xen/xend/server/SrvDomain.py | 3 ++- tools/python/xen/xm/migrate.py | 6 +++++- tools/xfrd/xen_domain.c | 3 ++- tools/xfrd/xen_domain.h | 2 +- tools/xfrd/xfrd.c | 9 ++++++--- 9 files changed, 30 insertions(+), 16 deletions(-) diff --git a/tools/libxc/xc_io.h b/tools/libxc/xc_io.h index 4feca0b358..341f29be60 100644 --- a/tools/libxc/xc_io.h +++ b/tools/libxc/xc_io.h @@ -8,6 +8,7 @@ typedef struct XcIOContext { u32 domain; unsigned flags; + int resource; IOStream *io; IOStream *info; IOStream *err; diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 4ebb6acbea..4a9d265a0f 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -244,11 +244,12 @@ class Xend: {'op' : 'save', 'file' : filename }) - def xend_domain_migrate(self, id, dst, live=0): + def xend_domain_migrate(self, id, dst, live=0, resource=0): return self.xendPost(self.domainurl(id), {'op' : 'migrate', 'destination': dst, - 'live' : live }) + 'live' : live, + 'resource' : resource }) def xend_domain_pincpu(self, id, cpu): return self.xendPost(self.domainurl(id), diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 5532d5b98f..a757414483 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -594,7 +594,7 @@ class XendDomain: self.refresh_schedule() return val - def domain_migrate(self, id, dst, live): + def domain_migrate(self, id, dst, live=0, resource=0): """Start domain migration. @param id: domain id @@ -604,7 +604,7 @@ class XendDomain: # Don't forget to cancel restart for it. dominfo = self.domain_lookup(id) xmigrate = XendMigrate.instance() - val = xmigrate.migrate_begin(dominfo, dst, live=live) + val = xmigrate.migrate_begin(dominfo, dst, live=live, resource=resource) return val def domain_save(self, id, dst, progress=0): diff --git a/tools/python/xen/xend/XendMigrate.py b/tools/python/xen/xend/XendMigrate.py index f1bcf67c67..a1c261deb5 100644 --- a/tools/python/xen/xend/XendMigrate.py +++ b/tools/python/xen/xend/XendMigrate.py @@ -260,7 +260,7 @@ class XendMigrateInfo(XfrdInfo): """Representation of a migrate in-progress and its interaction with xfrd. """ - def __init__(self, xid, dominfo, host, port, live): + def __init__(self, xid, dominfo, host, port, live=0, resource=0): XfrdInfo.__init__(self) self.xid = xid self.dominfo = dominfo @@ -271,13 +271,15 @@ class XendMigrateInfo(XfrdInfo): self.dst_port = port self.dst_dom = None self.live = live + self.resource = resource self.start = 0 def sxpr(self): sxpr = ['migrate', ['id', self.xid ], ['state', self.state ], - ['live', self.live ] ] + ['live', self.live ], + ['resource', self.resource] ] sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ] sxpr.append(sxpr_src) sxpr_dst = ['dst', ['host', self.dst_host] ] @@ -300,7 +302,8 @@ class XendMigrateInfo(XfrdInfo): vmconfig, self.dst_host, self.dst_port, - self.live ]) + self.live, + self.resource ]) ## def xfr_vm_suspend(self, xfrd, val): ## def cbok(val): @@ -490,7 +493,7 @@ class XendMigrate: reactor.connectTCP('localhost', XFRD_PORT, xcf) return info.deferred - def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0): + def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0): """Begin to migrate a domain to another host. @param dominfo: domain info @@ -499,7 +502,7 @@ class XendMigrate: @return: deferred """ xid = self.nextid() - info = XendMigrateInfo(xid, dominfo, host, port, live) + info = XendMigrateInfo(xid, dominfo, host, port, live, resource) return self.session_begin(info) def save_begin(self, dominfo, file): diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index a0ec17526f..f25324470b 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -81,7 +81,8 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_migrate, [['dom', 'str'], ['destination', 'str'], - ['live', 'int']]) + ['live', 'int'], + ['resource', 'int']]) deferred = fn(req.args, {'dom': self.dom.id}) print 'op_migrate>', deferred deferred.addCallback(self._op_migrate_cb, req) diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index 366fb5f694..070905bc11 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -26,6 +26,10 @@ gopts.opt('live', short='l', fn=set_true, default=0, use="Use live migration.") +gopts.opt('resource', short='r', + fn=set_int, default=0, + use="Set level of resource usage for migration.") + def help(argv): gopts.argv = argv gopts.usage() @@ -42,5 +46,5 @@ def main(argv): dst = args[1] if dom in [DOM0_NAME, DOM0_ID]: opts.err('Cannot migrate ' + dom) - server.xend_domain_migrate(dom, dst, opts.vals.live) + server.xend_domain_migrate(dom, dst, opts.vals.live, opts.vals.resource) diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c index 453614d8fe..abc7b7dc3c 100644 --- a/tools/xfrd/xen_domain.c +++ b/tools/xfrd/xen_domain.c @@ -60,7 +60,7 @@ void xcfini(void){ int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n, - int live){ + int live, int resource){ int err = 0; #ifdef _XEN_XFR_STUB_ char buf[1024]; @@ -99,6 +99,7 @@ int xen_domain_snd(Conn *xend, IOStream *io, if(live){ ioctxt->flags |= XCFLAGS_LIVE; } + ioctxt->resource = resource; err = xc_linux_save(xcinit(), ioctxt); #endif dprintf("< err=%d\n", err); diff --git a/tools/xfrd/xen_domain.h b/tools/xfrd/xen_domain.h index 2ea66b743e..c84e8b8d63 100644 --- a/tools/xfrd/xen_domain.h +++ b/tools/xfrd/xen_domain.h @@ -10,7 +10,7 @@ extern int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n, - int live); + int live, int resource); extern int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n, diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c index 5da736f6a9..236b67755b 100644 --- a/tools/xfrd/xfrd.c +++ b/tools/xfrd/xfrd.c @@ -96,7 +96,7 @@ receiver: Sxpr oxfr_configure; // (xfr.configure ) Sxpr oxfr_err; // (xfr.err ) Sxpr oxfr_hello; // (xfr.hello ) -Sxpr oxfr_migrate; // (xfr.migrate ) +Sxpr oxfr_migrate; // (xfr.migrate ) Sxpr oxfr_migrate_ok;// (xfr.migrate.ok ) Sxpr oxfr_progress; // (xfr.progress ) Sxpr oxfr_restore; // (xfr.restore ) @@ -241,6 +241,7 @@ typedef struct XfrState { char *xfr_host; uint32_t vmid_new; int live; + int resource; } XfrState; /** Get the name of a transfer state. @@ -623,7 +624,7 @@ int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){ err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n, - state->live); + state->live, state->resource); dprintf(">*** Sent domain %u\n", state->vmid); if(err) goto exit; // Sending the domain suspends it, and there's no way back. @@ -771,7 +772,7 @@ int xfr_save(Args *args, XfrState *state, Conn *xend, char *file){ err = xen_domain_snd(xend, io, state->vmid, state->vmconfig, state->vmconfig_n, - 0); + 0, 0); if(err){ err = xfr_error(xend, err); } else { @@ -926,6 +927,8 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){ if(err) goto exit; err = intof(sxpr_childN(sxpr, n++, ONONE), &state->live); if(err) goto exit; + err = intof(sxpr_childN(sxpr, n++, ONONE), &state->resource); + if(err) goto exit; err = xfr_send(args, state, conn, addr, port); } else if(sxpr_elementp(sxpr, oxfr_save)){ From f3f86e73a616d350b1fc92de0cdc409ccc5d88f3 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 21 Oct 2004 16:12:08 +0000 Subject: [PATCH 3/3] bitkeeper revision 1.1159.116.5 (4177dfd8eoQeNDnbJVcWNL3DSAZzEg) Print traceback on error. --- tools/python/xen/xend/server/SrvDomainDir.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index 4526b996f9..08eed6da38 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -98,6 +98,7 @@ class SrvDomainDir(SrvDir): if isinstance(err, Failure): err = err.getErrorMessage() print 'op_create> Deferred Exception creating domain:', err + traceback.print_exc() req.setResponseCode(http.BAD_REQUEST, "Error creating domain: " + str(err)) return str(err)