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 8d77e15082..82b2dbde81 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -239,11 +239,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 8c616be689..44e4b5f500 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -585,7 +585,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 @@ -595,7 +595,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/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index ca665bd906..2ed5180355 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 = sxp.child_value(savedinfo, 'name') d = defer.succeed(vm) vm.recreate = 0 + vm.savedinfo = None return d def vm_restore(src, progress=0): @@ -288,6 +270,18 @@ def append_deferred(dlist, v): if isinstance(v, defer.Deferred): dlist.append(v) +def dlist_err(val): + """Error callback suitable for a deferred list. + In a deferred list the error callback is called with with Failure((error, index)). + This callback extracts the error and returns it. + + @param val: Failure containing (error, index) + @type val: twisted.internet.failure.Failure + """ + + (error, index) = val.value + return error + class XendDomainInfo: """Virtual machine object.""" @@ -324,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. @@ -385,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 '_-.:/+'. @@ -572,6 +578,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. @@ -699,6 +724,10 @@ class XendDomainInfo: """Build the domain boot image. """ if self.recreate or self.restore: return + if not os.path.isfile(kernel): + raise VmError('Kernel image does not exist: %s' % kernel) + if ramdisk and not os.path.isfile(ramdisk): + raise VmError('Kernel ramdisk does not exist: %s' % ramdisk) if len(cmdline) >= 256: log.warning('kernel cmdline too long, domain %d', self.dom) dom = self.dom @@ -724,11 +753,6 @@ class XendDomainInfo: @param ramdisk: kernel ramdisk @param cmdline: kernel commandline """ - if not self.recreate: - if not os.path.isfile(kernel): - raise VmError('Kernel image does not exist: %s' % kernel) - if ramdisk and not os.path.isfile(ramdisk): - raise VmError('Kernel ramdisk does not exist: %s' % ramdisk) #self.init_domain() if self.console: self.console.registerChannel() @@ -761,6 +785,7 @@ class XendDomainInfo: append_deferred(dlist, v) index[dev_name] = dev_index + 1 deferred = defer.DeferredList(dlist, fireOnOneErrback=1) + deferred.addErrback(dlist_err) return deferred def device_create(self, dev_config): @@ -826,7 +851,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) @@ -992,6 +1017,7 @@ class XendDomainInfo: log.warning("Unknown config field %s", field_name) index[field_name] = field_index + 1 d = defer.DeferredList(dlist, fireOnOneErrback=1) + d.addErrback(dlist_err) return d @@ -1005,7 +1031,7 @@ def vm_image_linux(vm, image): """ kernel = sxp.child_value(image, "kernel") cmdline = "" - ip = sxp.child_value(image, "ip", "dhcp") + ip = sxp.child_value(image, "ip", None) if ip: cmdline += " ip=" + ip root = sxp.child_value(image, "root") @@ -1030,9 +1056,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() @@ -1048,23 +1076,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/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 093097046a..c06b260ce1 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/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py index 6307b25089..08eed6da38 100644 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ b/tools/python/xen/xend/server/SrvDomainDir.py @@ -5,6 +5,7 @@ from StringIO import StringIO from twisted.protocols import http from twisted.web import error +from twisted.python.failure import Failure from xen.xend import sxp from xen.xend import XendDomain @@ -94,7 +95,10 @@ class SrvDomainDir(SrvDir): def _op_create_err(self, err, req): """Callback to handle errors in deferred domain creation. """ + 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) @@ -127,6 +131,8 @@ class SrvDomainDir(SrvDir): return val def _op_restore_err(self, err, req): + if isinstance(err, Failure): + err = err.getErrorMessage() print 'op_create> Deferred Exception restoring domain:', err req.setResponseCode(http.BAD_REQUEST, "Error restoring domain: "+ str(err)) return str(err) diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index 69f9431f48..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. """ @@ -340,8 +423,8 @@ class BlkDev(controller.SplitDev): val = unpackMsg('blkif_be_vbd_grow_t', msg) status = val['status'] if status != BLKIF_BE_STATUS_OKAY: - raise XendError("Adding extent to vbd failed: device %d, error %d" - % (self.vdev, status)) + raise XendError("Adding extent to vbd failed: device %s, error %d" + % (sxp.to_string(self.config), status)) return self def send_be_vbd_destroy(self): @@ -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): 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)){