From 7166248ac4d31b4c40d63be4f952d35ea678a5ab Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 18 Aug 2004 09:17:07 +0000 Subject: [PATCH 1/5] bitkeeper revision 1.1159.38.1 (41231e93omwWBjFZGIgG3ek6UMbDYA) Refactor device setup code so that the devices do more of the messaging. --- tools/python/xen/lowlevel/xu/xu.c | 6 + tools/python/xen/xend/XendDomainInfo.py | 8 +- tools/python/xen/xend/server/SrvDomain.py | 30 +- tools/python/xen/xend/server/blkif.py | 388 ++++++++------------- tools/python/xen/xend/server/channel.py | 6 +- tools/python/xen/xend/server/controller.py | 4 +- tools/python/xen/xend/server/messages.py | 7 +- tools/python/xen/xend/server/netif.py | 182 +++++----- 8 files changed, 266 insertions(+), 365 deletions(-) diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c index d403099cec..3b078e7d33 100644 --- a/tools/python/xen/lowlevel/xu/xu.c +++ b/tools/python/xen/lowlevel/xu/xu.c @@ -426,6 +426,12 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args) C2P(netif_fe_interface_status_changed_t, handle, Int, Long); C2P(netif_fe_interface_status_changed_t, status, Int, Long); C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[0], Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[1], Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[2], Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[3], Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[4], Int, Long); + C2P(netif_fe_interface_status_changed_t, mac[5], Int, Long); return dict; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): C2P(netif_fe_driver_status_changed_t, status, Int, Long); diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 602575d0ba..d2bff39b04 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1074,8 +1074,8 @@ def vm_dev_vif(vm, val, index): @param index: vif index @return: deferred """ - if vm.netif_backend: - raise VmError('vif: vif in netif backend domain') + #if vm.netif_backend: + # raise VmError('vif: vif in netif backend domain') vif = vm.next_device_index('vif') vmac = sxp.child_value(val, "mac") backend = vm.get_device_backend('vif') @@ -1098,8 +1098,8 @@ def vm_dev_vbd(vm, val, index): @param index: vbd index @return: deferred """ - if vm.blkif_backend: - raise VmError('vbd: vbd in blkif backend domain') + #if vm.blkif_backend: + # raise VmError('vbd: vbd in blkif backend domain') uname = sxp.child_value(val, 'uname') if not uname: raise VmError('vbd: Missing uname') diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index aed8fd7e57..50aa355e62 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -48,7 +48,7 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_shutdown, [['dom', 'str'], ['reason', 'str']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) req.setResponseCode(http.ACCEPTED) req.setHeader("Location", "%s/.." % req.prePathURL()) return val @@ -57,7 +57,7 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_destroy, [['dom', 'str'], ['reason', 'str']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) req.setHeader("Location", "%s/.." % req.prePathURL()) return val @@ -65,7 +65,7 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_save, [['dom', 'str'], ['file', 'str']]) - deferred = fn(req.args, {'dom': self.dom.name}) + deferred = fn(req.args, {'dom': self.dom.id}) deferred.addCallback(self._op_save_cb, req) deferred.addErrback(self._op_save_err, req) return deferred @@ -81,7 +81,7 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_migrate, [['dom', 'str'], ['destination', 'str']]) - deferred = fn(req.args, {'dom': self.dom.name}) + deferred = fn(req.args, {'dom': self.dom.id}) print 'op_migrate>', deferred deferred.addCallback(self._op_migrate_cb, req) deferred.addErrback(self._op_migrate_err, req) @@ -107,7 +107,7 @@ class SrvDomain(SrvDir): fn = FormFn(self.xd.domain_pincpu, [['dom', 'str'], ['cpu', 'int']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_cpu_bvt_set(self, op, req): @@ -118,7 +118,7 @@ class SrvDomain(SrvDir): ['warpvalue', 'int'], ['warpl', 'long'], ['warpu', 'long']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_cpu_fbvt_set(self, op, req): @@ -128,7 +128,7 @@ class SrvDomain(SrvDir): ['warp', 'int'], ['warpl', 'int'], ['warpu', 'int']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_cpu_atropos_set(self, op, req): @@ -138,21 +138,21 @@ class SrvDomain(SrvDir): ['slice', 'int'], ['latency', 'int'], ['xtratime', 'int']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_maxmem_set(self, op, req): fn = FormFn(self.xd.domain_maxmem_set, [['dom', 'str'], ['memory', 'int']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_device_create(self, op, req): fn = FormFn(self.xd.domain_device_create, [['dom', 'str'], ['config', 'sxpr']]) - d = fn(req.args, {'dom': self.dom.name}) + d = fn(req.args, {'dom': self.dom.id}) return d def op_device_destroy(self, op, req): @@ -160,29 +160,29 @@ class SrvDomain(SrvDir): [['dom', 'str'], ['type', 'str'], ['idx', 'str']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_vifs(self, op, req): - devs = self.xd.domain_vif_ls(self.dom.name) + devs = self.xd.domain_vif_ls(self.dom.id) return [ dev.sxpr() for dev in devs ] def op_vif(self, op, req): fn = FormFn(self.xd.domain_vif_get, [['dom', 'str'], ['vif', 'str']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def op_vbds(self, op, req): - devs = self.xd.domain_vbd_ls(self.dom.name) + devs = self.xd.domain_vbd_ls(self.dom.id) return [ dev.sxpr() for dev in devs ] def op_vbd(self, op, req): fn = FormFn(self.xd.domain_vbd_get, [['dom', 'str'], ['vbd', 'str']]) - val = fn(req.args, {'dom': self.dom.name}) + val = fn(req.args, {'dom': self.dom.id}) return val def render_POST(self, req): diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index bea848bfcf..c142e59da8 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -22,74 +22,7 @@ class BlkifBackendController(controller.BackendController): self.addMethod(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) - self.attached = 1 self.registerChannel() - - def respond_be_create(self, msg, d): - """Response handler for a be_create message. - Calls I{d} with the block interface created. - - @param msg: message - @type msg: xu message - @param d: deferred to call - @type d: Deferred - """ - val = unpackMsg('blkif_be_create_t', msg) - blkif = self.factory.getInstanceByDom(val['domid']) - d.callback(blkif) - - def respond_be_connect(self, msg): - """Response handler for a be_connect message. - - @param msg: message - @type msg: xu message - """ - val = unpackMsg('blkif_be_connect_t', msg) - blkif = self.factory.getInstanceByDom(val['domid']) - if blkif: - blkif.send_fe_interface_status_changed() - else: - pass - - def respond_be_vbd_create(self, msg, dev, d): - """Response handler for a be_vbd_create message. - Tries to grow the vbd, and passes the deferred I{d} on for - the grow to call. - - @param msg: message - @type msg: xu message - @param dev: device - @type dev: BlkDev - @param d: deferred to call - @type d: Deferred - """ - val = unpackMsg('blkif_be_vbd_create_t', msg) - blkif = self.factory.getInstanceByDom(val['domid']) - if blkif: - d1 = defer.Deferred() - d1.addCallback(self.respond_be_vbd_grow, dev, d) - if d: d1.addErrback(d.errback) - blkif.send_be_vbd_grow(val['vdevice'], response=d1) - else: - pass - - def respond_be_vbd_grow(self, msg, dev, d): - """Response handler for a be_vbd_grow message. - - @param msg: message - @type msg: xu message - @param dev: device - @type dev: BlkDev - @param d: deferred to call - @type d: Deferred or None - """ - 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 %x, error %d" - % (val['extent.device'], status)) - if d: - d.callback(dev) def recv_be_driver_status_changed(self, msg, req): """Request handler for be_driver_status_changed messages. @@ -101,11 +34,6 @@ class BlkifBackendController(controller.BackendController): """ val = unpackMsg('blkif_be_driver_status_changed_t', msg) status = val['status'] - if status == BLKIF_DRIVER_STATUS_UP and not self.attached: - for blkif in self.factory.getInstances(): - if blkif.backendController == self: - blkif.detach() - class BlkifControllerFactory(controller.SplitControllerFactory): """Factory for creating block device interface controllers. @@ -113,7 +41,6 @@ class BlkifControllerFactory(controller.SplitControllerFactory): def __init__(self): controller.SplitControllerFactory.__init__(self) - self.attached = 1 def createInstance(self, dom, recreate=0, backend=0): """Create a block device controller for a domain. @@ -125,20 +52,14 @@ class BlkifControllerFactory(controller.SplitControllerFactory): @return: deferred @rtype: twisted.internet.defer.Deferred """ - d = defer.Deferred() blkif = self.getInstanceByDom(dom) if blkif: + d = defer.Deferred() d.callback(blkif) else: blkif = BlkifController(self, dom, backend) self.addInstance(blkif) - if recreate: - d.callback(blkif) - else: - d1 = defer.Deferred() - d1.addCallback(blkif.backendController.respond_be_create, d) - d1.addErrback(d.errback) - blkif.send_be_create(response=d1) + d = blkif.connect(recreate=recreate) return d def getDomainDevices(self, dom): @@ -158,7 +79,7 @@ class BlkifControllerFactory(controller.SplitControllerFactory): @param dom: domain @type dom: int @param vdev: device index - @type vedv: int + @type vdev: int @return: device @rtype: device """ @@ -168,66 +89,6 @@ class BlkifControllerFactory(controller.SplitControllerFactory): def createBackendController(self, dom): return BlkifBackendController(self, dom) - def setControlDomain(self, dom, recreate=0): - """Set the back-end block device controller domain. - - @param dom: domain - @type dom: int - @param recreate: if true it's a recreate (after xend restart) - @type recreate: int - """ - if self.dom == dom: return - self.deregisterChannel() - if not recreate: - self.attached = 0 - self.dom = dom - self.registerChannel() - - def getControlDomain(self): - """Get the back-end block device controller domain. - - @return: domain - @rtype: int - """ - return self.dom - - def reattachDevice(self, dom, vdev): - """Reattach a device (on changing control domain). - - @param dom: domain - @type dom: int - @param vdev: device index - @type vdev: int - """ - blkif = self.getInstanceByDom(dom) - if blkif: - blkif.reattachDevice(vdev) - self.attached = self.devicesAttached() - if self.attached: - self.reattached() - - def devicesAttached(self): - """Check if all devices are attached. - - @return: true if all devices attached - @rtype: bool - """ - attached = 1 - for blkif in self.getInstances(): - if not blkif.attached: - attached = 0 - break - return attached - - def reattached(self): - """Notify all block interfaces we have been reattached - (after changing control domain). - """ - for blkif in self.getInstances(): - blkif.reattached() - - - class BlkDev(controller.Dev): """Info record for a block device. """ @@ -241,7 +102,9 @@ class BlkDev(controller.Dev): self.device = segment['device'] self.start_sector = segment['start_sector'] self.nr_sectors = segment['nr_sectors'] - self.attached = 1 + + def getBackendController(self): + return self.controller.backendController def readonly(self): return 'w' not in self.mode @@ -260,7 +123,80 @@ class BlkDev(controller.Dev): def destroy(self): log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev) - self.controller.send_be_vbd_destroy(self.vdev) + self.send_be_vbd_destroy() + + def attach(self, d): + """Attach the device to its controller. + + @param d: deferred to call with the device on success + """ + d1 = defer.Deferred() + d1.addCallback(self.respond_be_vbd_create, d) + d1.addErrback(d.errback) + self.send_be_vbd_create(response=d1) + + def send_be_vbd_create(self, response=None): + msg = packMsg('blkif_be_vbd_create_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.controller.handle, + 'vdevice' : self.vdev, + 'readonly' : self.readonly() }) + self.getBackendController().writeRequest(msg, response=response) + + def respond_be_vbd_create(self, msg, d): + """Response handler for a be_vbd_create message. + Tries to grow the vbd. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred + """ + val = unpackMsg('blkif_be_vbd_create_t', msg) + d1 = defer.Deferred() + d1.addCallback(self.respond_be_vbd_grow, d) + if d: d1.addErrback(d.errback) + self.send_be_vbd_grow(response=d1) + + def send_be_vbd_grow(self, response=None): + msg = packMsg('blkif_be_vbd_grow_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.controller.handle, + 'vdevice' : self.vdev, + 'extent.device' : self.device, + 'extent.sector_start' : self.start_sector, + 'extent.sector_length' : self.nr_sectors }) + self.getBackendController().writeRequest(msg, response=response) + + def respond_be_vbd_grow(self, msg, d): + """Response handler for a be_vbd_grow message. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred or None + """ + val = unpackMsg('blkif_be_vbd_grow_t', msg) + status = val['status'] + if status != BLKIF_BE_STATUS_OKAY: + err = XendError("Adding extent to vbd failed: device %d, error %d" + % (self.vdev, status)) + #if(d): + # d.errback(err) + raise err + if d: + d.callback(self) + + def send_be_vbd_destroy(self, response=None): + log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d', + self.controller.dom, self.vdev) + msg = packMsg('blkif_be_vbd_destroy_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.controller.handle, + 'vdevice' : self.vdev }) + self.controller.delDevice(self.vdev) + self.getBackendController().writeRequest(msg, response=response) + class BlkifController(controller.SplitController): """Block device interface controller. Handles all block devices @@ -268,6 +204,10 @@ class BlkifController(controller.SplitController): """ def __init__(self, factory, dom, backend): + """Create a block device controller. + The controller must be connected using connect() before it can be used. + Do not call directly - use createInstance() on the factory instead. + """ controller.SplitController.__init__(self, factory, dom, backend) self.devices = {} self.addMethod(CMSG_BLKIF_FE, @@ -276,7 +216,7 @@ class BlkifController(controller.SplitController): self.addMethod(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT, self.recv_fe_interface_connect) - self.attached = 1 + self.handle = 0 self.evtchn = None self.registerChannel() @@ -311,6 +251,10 @@ class BlkifController(controller.SplitController): self.devices[vdev] = dev return dev + def delDevice(self, vdev): + if vdev in self.devices: + del self.devices[vdev] + def attachDevice(self, vdev, mode, segment, recreate=0): """Attach a device to the specified interface. On success the returned deferred will be called with the device. @@ -332,63 +276,75 @@ class BlkifController(controller.SplitController): if recreate: d.callback(dev) else: - d1 = defer.Deferred() - d1.addCallback(self.backendController.respond_be_vbd_create, dev, d) - d1.addErrback(d.errback) - self.send_be_vbd_create(vdev, response=d1) + dev.attach(d) return d def destroy(self): - def cb_destroy(val): - self.send_be_destroy() + """Destroy the controller and all devices. + """ log.debug("Destroying blkif domain=%d", self.dom) - d = defer.Deferred() - d.addCallback(cb_destroy) - self.send_be_disconnect(response=d) + self.destroyDevices() + self.disconnect() def destroyDevices(self): + """Destroy all devices. + """ for dev in self.getDevices(): dev.destroy() - def detach(self): - """Detach all devices, when the back-end control domain has changed. - """ - self.attached = 0 - for dev in self.devices.values(): - dev.attached = 0 - d1 = defer.Deferred() - d1.addCallback(self.backendController.respond_be_vbd_create, None, None) - self.send_be_vbd_create(vdev, response=d1) + def connect(self, recreate=0): + """Connect the controller to the blkif control interface. - def reattachDevice(self, vdev): - """Reattach a device, when the back-end control domain has changed. + @param recreate: true if after xend restart + @return: deferred """ - dev = self.devices[vdev] - dev.attached = 1 - attached = 1 - for dev in self.devices.values(): - if not dev.attached: - attached = 0 - break - self.attached = attached - return self.attached - - def reattached(self): - """All devices have been reattached after the back-end control - domain has changed. + log.debug("Connecting blkif domain=%d", self.dom) + d = defer.Deferred() + if recreate: + d.callback(self) + else: + def cbresp(msg): + return self + d.addCallback(cbresp) + self.send_be_create(response=d) + return d + + def send_be_create(self, response=None): + msg = packMsg('blkif_be_create_t', + { 'domid' : self.dom, + 'blkif_handle' : self.handle }) + self.backendController.writeRequest(msg, response=response) + + def disconnect(self): + """Disconnect from the blkif control interface and destroy it. """ - msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : 0, - 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED}) - self.writeRequest(msg) + def cb_destroy(val): + self.send_be_destroy() + d = defer.Deferred() + d.addCallback(cb_destroy) + self.send_be_disconnect(response=d) + + def send_be_disconnect(self, response=None): + log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom) + msg = packMsg('blkif_be_disconnect_t', + { 'domid' : self.dom, + 'blkif_handle' : self.handle }) + self.backendController.writeRequest(msg, response=response) + def send_be_destroy(self, response=None): + log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom) + msg = packMsg('blkif_be_destroy_t', + { 'domid' : self.dom, + 'blkif_handle' : self.handle }) + self.backendController.writeRequest(msg, response=response) + def recv_fe_driver_status_changed(self, msg, req): msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : 0, + { 'handle' : self.handle, 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED, 'evtchn' : 0 }) self.writeRequest(msg) - + def recv_fe_interface_connect(self, msg, req): val = unpackMsg('blkif_fe_interface_connect_t', msg) self.evtchn = channel.eventChannel(0, self.dom) @@ -400,63 +356,23 @@ class BlkifController(controller.SplitController): 'evtchn' : self.evtchn['port1'], 'shmem_frame' : val['shmem_frame'] }) d = defer.Deferred() - d.addCallback(self.backendController.respond_be_connect) + d.addCallback(self.respond_be_connect) self.backendController.writeRequest(msg, response=d) + def respond_be_connect(self, msg): + """Response handler for a be_connect message. + + @param msg: message + @type msg: xu message + """ + val = unpackMsg('blkif_be_connect_t', msg) + self.send_fe_interface_status_changed() + def send_fe_interface_status_changed(self, response=None): msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : 0, + { 'handle' : self.handle, 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, 'evtchn' : self.evtchn['port2'] }) self.writeRequest(msg, response=response) - - def send_be_create(self, response=None): - msg = packMsg('blkif_be_create_t', - { 'domid' : self.dom, - 'blkif_handle' : 0 }) - self.backendController.writeRequest(msg, response=response) - - def send_be_disconnect(self, response=None): - log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom) - msg = packMsg('blkif_be_disconnect_t', - { 'domid' : self.dom, - 'blkif_handle' : 0 }) - self.backendController.writeRequest(msg, response=response) - - def send_be_destroy(self, response=None): - log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom) - msg = packMsg('blkif_be_destroy_t', - { 'domid' : self.dom, - 'blkif_handle' : 0 }) - self.backendController.writeRequest(msg, response=response) - - def send_be_vbd_create(self, vdev, response=None): - dev = self.devices[vdev] - msg = packMsg('blkif_be_vbd_create_t', - { 'domid' : self.dom, - 'blkif_handle' : 0, - 'vdevice' : dev.vdev, - 'readonly' : dev.readonly() }) - self.backendController.writeRequest(msg, response=response) - - def send_be_vbd_grow(self, vdev, response=None): - dev = self.devices[vdev] - msg = packMsg('blkif_be_vbd_grow_t', - { 'domid' : self.dom, - 'blkif_handle' : 0, - 'vdevice' : dev.vdev, - 'extent.device' : dev.device, - 'extent.sector_start' : dev.start_sector, - 'extent.sector_length' : dev.nr_sectors }) - self.backendController.writeRequest(msg, response=response) - - def send_be_vbd_destroy(self, vdev, response=None): - log.debug('>BlkifController>send_be_vbd_destroy> dom=%d vdev=%d', self.dom, vdev) - dev = self.devices[vdev] - msg = packMsg('blkif_be_vbd_destroy_t', - { 'domid' : self.dom, - 'blkif_handle' : 0, - 'vdevice' : dev.vdev }) - del self.devices[vdev] - self.backendController.writeRequest(msg, response=response) + diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py index d78ba252cb..4c6dbadd17 100755 --- a/tools/python/xen/xend/server/channel.py +++ b/tools/python/xen/xend/server/channel.py @@ -333,13 +333,15 @@ class Channel(BaseChannel): (ty, subty) = self.getMessageType(msg) #todo: Must respond before writing any more messages. #todo: Should automate this (respond on write) - self.port.write_response(msg) + responded = 0 dev = self.getDevice(ty) if dev: - dev.requestReceived(msg, ty, subty) + responded = dev.requestReceived(msg, ty, subty) else: print ("requestReceived> No device: Message type %s %d:%d" % (msgTypeName(ty, subty), ty, subty)), self + if not responded: + self.port.write_response(msg) def handleResponses(self): work = 0 diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index cea9c38dfb..28662207bb 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -125,12 +125,14 @@ class CtrlMsgRcvr: if DEBUG: print 'requestReceived>', printMsg(msg, all=1) + responded = 0 method = self.getMethod(type, subtype) if method: - method(msg, 1) + responded = method(msg, 1) elif DEBUG: print ('requestReceived> No handler: Message type %s %d:%d' % (msgTypeName(type, subtype), type, subtype)), self + return responded def responseReceived(self, msg, type, subtype): """Dispatch a response to handlers. diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py index e966ec9003..8d68d95887 100644 --- a/tools/python/xen/xend/server/messages.py +++ b/tools/python/xen/xend/server/messages.py @@ -215,7 +215,7 @@ def packMsg(ty, params): else: args[k] = v msg = xu.message(major, minor, msgid, args) - if DEBUG: print 'unpackMsg', args if isinstance(args, types.StringType): - args = { 'value': args } + args = {'value': args} else: mac = [0, 0, 0, 0, 0, 0] macs = [] @@ -284,5 +285,5 @@ def printMsg(msg, out=sys.stdout, all=0): ty = msgTypeName(major, minor) print >>out, 'message:', 'type=', ty, '%d:%d' % (major, minor), 'id=%d' % msgid if all: - print >>out, 'payload=', unpackMsg(ty, msg) + print >>out, 'payload=', msg.get_payload() diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index f4247c670f..a5add8e7fb 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -27,30 +27,11 @@ class NetifBackendController(controller.BackendController): self.addMethod(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) - self.attached = 1 self.registerChannel() - def respond_be_connect(self, msg): - val = unpackMsg('netif_be_connect_t', msg) - dom = val['domid'] - vif = val['netif_handle'] - netif = self.factory.getInstanceByDom(dom) - if netif: - netif.send_interface_connected(vif) - else: - log.warning("respond_be_connect> unknown vif dom=%d vif=%d", dom, vif) - pass - def recv_be_driver_status_changed(self, msg, req): val = unpackMsg('netif_be_driver_status_changed_t', msg) status = val['status'] - if status == NETIF_DRIVER_STATUS_UP and not self.attached: - # If we are not attached the driver domain was changed, and - # this signals the new driver domain is ready. - for netif in self.factory.getInstances(): - if netif.backendController == self: - netif.reattach_devices() - self.attached = 1 class NetifControllerFactory(controller.SplitControllerFactory): """Factory for creating network interface controllers. @@ -58,7 +39,6 @@ class NetifControllerFactory(controller.SplitControllerFactory): def __init__(self): controller.ControllerFactory.__init__(self) - self.attached = 1 def createInstance(self, dom, recreate=0, backend=0): """Create or find the network interface controller for a domain. @@ -95,26 +75,6 @@ class NetifControllerFactory(controller.SplitControllerFactory): def createBackendController(self, dom): return NetifBackendController(self, dom) - def setControlDomain(self, dom, recreate=0): - """Set the 'back-end' device driver domain. - - @param dom: domain - @param recreate: if true this is a recreate (xend restarted) - """ - if self.dom == dom: return - self.deregisterChannel() - if not recreate: - self.attached = 0 - self.dom = dom - self.registerChannel() - - def getControlDomain(self): - """Get the domain id of the back-end control domain. - - @return domain id - """ - return self.dom - class NetDev(controller.Dev): """Info record for a network device. """ @@ -125,6 +85,9 @@ class NetDev(controller.Dev): self.evtchn = None self.configure(config) + def getBackendController(self): + return self.controller.backendController + def configure(self, config): self.config = config self.mac = None @@ -205,19 +168,76 @@ class NetDev(controller.Dev): if vnet: vnet.vifctl(op, self.get_vifname(), self.get_mac()) + def attach(self, d): + print 'attach>', d + self.send_be_create(response=d) + + def send_be_create(self, response=None): + msg = packMsg('netif_be_create_t', + { 'domid' : self.controller.dom, + 'netif_handle' : self.vif, + 'mac' : self.mac }) + self.getBackendController().writeRequest(msg, response=response) + def destroy(self): """Destroy the device's resources and disconnect from the back-end device controller. """ def cb_destroy(val): - self.controller.send_be_destroy(self.vif) + self.send_be_destroy() log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif) self.vifctl('down') d = defer.Deferred() d.addCallback(cb_destroy) - self.controller.send_be_disconnect(self.vif, response=d) - + self.send_be_disconnect(response=d) + def send_be_disconnect(self, response=None): + msg = packMsg('netif_be_disconnect_t', + { 'domid' : self.controller.dom, + 'netif_handle' : self.vif }) + self.getBackendController().writeRequest(msg, response=response) + + def send_be_destroy(self, response=None): + msg = packMsg('netif_be_destroy_t', + { 'domid' : self.controller.dom, + 'netif_handle' : self.vif }) + self.controller.delDevice(self.vif) + self.getBackendController().writeRequest(msg, response=response) + + def recv_fe_interface_connect(self, val, req): + if not req: return + self.evtchn = channel.eventChannel(0, self.controller.dom) + msg = packMsg('netif_be_connect_t', + { 'domid' : self.controller.dom, + 'netif_handle' : self.vif, + 'evtchn' : self.evtchn['port1'], + 'tx_shmem_frame' : val['tx_shmem_frame'], + 'rx_shmem_frame' : val['rx_shmem_frame'] }) + d = defer.Deferred() + d.addCallback(self.respond_be_connect) + self.getBackendController().writeRequest(msg, response=d) + + def respond_be_connect(self, msg): + val = unpackMsg('netif_be_connect_t', msg) + dom = val['domid'] + vif = val['netif_handle'] + print 'respond_be_connect>', ' dom=', dom, ' vif=', vif + print 'respond_be_connect>', 'self.dom=', self.controller.dom, 'self.vif=', self.vif + msg = packMsg('netif_fe_interface_status_changed_t', + { 'handle' : self.vif, + 'status' : NETIF_INTERFACE_STATUS_CONNECTED, + 'evtchn' : self.evtchn['port2'], + 'mac' : self.mac }) + self.controller.writeRequest(msg) + + def attach_fe_device(self): + msg = packMsg('netif_fe_interface_status_changed_t', + { 'handle' : self.vif, + 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED, + 'evtchn' : 0, + 'mac' : self.mac }) + self.controller.writeRequest(msg) + class NetifController(controller.SplitController): """Network interface controller. Handles all network devices for a domain. """ @@ -266,6 +286,10 @@ class NetifController(controller.SplitController): self.devices[vif] = dev return dev + def delDevice(self, vif): + if vif in self.devices: + del self.devices[vif] + def destroy(self): """Destroy the controller and all devices. """ @@ -285,79 +309,29 @@ class NetifController(controller.SplitController): @param recreate: recreate flag (true after xend restart) @return: deferred """ - self.addDevice(vif, config) + dev = self.addDevice(vif, config) d = defer.Deferred() if recreate: d.callback(self) else: - self.send_be_create(vif, response=d) + dev.attach(d) return d - def reattach_devices(self): - """Reattach all devices when the back-end control domain has changed. - """ - self.send_be_create(vif) - self.attach_fe_devices() - - def attach_fe_devices(self): - for dev in self.devices.values(): - msg = packMsg('netif_fe_interface_status_changed_t', - { 'handle' : dev.vif, - 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED, - 'evtchn' : 0, - 'mac' : dev.mac }) - self.writeRequest(msg) - def recv_fe_driver_status_changed(self, msg, req): if not req: return msg = packMsg('netif_fe_driver_status_changed_t', { 'status' : NETIF_DRIVER_STATUS_UP, 'nr_interfaces' : len(self.devices) }) self.writeRequest(msg) - self.attach_fe_devices() - + for dev in self.devices.values(): + dev.attach_fe_device() + def recv_fe_interface_connect(self, msg, req): val = unpackMsg('netif_fe_interface_connect_t', msg) - dev = self.devices[val['handle']] - dev.evtchn = channel.eventChannel(0, self.dom) - msg = packMsg('netif_be_connect_t', - { 'domid' : self.dom, - 'netif_handle' : dev.vif, - 'evtchn' : dev.evtchn['port1'], - 'tx_shmem_frame' : val['tx_shmem_frame'], - 'rx_shmem_frame' : val['rx_shmem_frame'] }) - d = defer.Deferred() - d.addCallback(self.backendController.respond_be_connect) - self.backendController.writeRequest(msg, response=d) + vif = val['handle'] + dev = self.devices.get(vif) + if dev: + dev.recv_fe_interface_connect(val, req) + else: + log.error('Received netif_fe_interface_connect for unknown vif: '+vif) - def send_interface_connected(self, vif, response=None): - dev = self.devices[vif] - msg = packMsg('netif_fe_interface_status_changed_t', - { 'handle' : dev.vif, - 'status' : NETIF_INTERFACE_STATUS_CONNECTED, - 'evtchn' : dev.evtchn['port2'], - 'mac' : dev.mac }) - self.writeRequest(msg, response=response) - - def send_be_create(self, vif, response=None): - dev = self.devices[vif] - msg = packMsg('netif_be_create_t', - { 'domid' : self.dom, - 'netif_handle' : dev.vif, - 'mac' : dev.mac }) - self.backendController.writeRequest(msg, response=response) - - def send_be_disconnect(self, vif, response=None): - dev = self.devices[vif] - msg = packMsg('netif_be_disconnect_t', - { 'domid' : self.dom, - 'netif_handle' : dev.vif }) - self.backendController.writeRequest(msg, response=response) - - def send_be_destroy(self, vif, response=None): - dev = self.devices[vif] - del self.devices[vif] - msg = packMsg('netif_be_destroy_t', - { 'domid' : self.dom, - 'netif_handle' : vif }) - self.backendController.writeRequest(msg, response=response) From b450daf7d31bf0fdffd580061c649ff2c5789a44 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 18 Aug 2004 13:07:07 +0000 Subject: [PATCH 2/5] bitkeeper revision 1.1159.38.2 (4123547bJFXytNlVQreftqrfASgQAA) Fix args to migrate. --- tools/python/xen/xm/main.py | 2 +- tools/python/xen/xm/migrate.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 6bf7f83d83..654dc553e2 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -305,7 +305,7 @@ class ProgMigrate(Prog): migrate.help([self.name] + args) def main(self, args): - migrate.main([self.name] + args) + migrate.main(args) xm.prog(ProgMigrate) diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index 3b446f0bf0..dd81aab0df 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -33,7 +33,7 @@ def main(argv): opts.usage() return if len(args) != 2: - opts.err('Invalid arguments') + opts.err('Invalid arguments: ' + str(args)) dom = args[0] dst = args[1] if dom in [DOM0_NAME, DOM0_ID]: From d82470e9a7b1521597c759923975364e82ea4cdb Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 18 Aug 2004 13:09:32 +0000 Subject: [PATCH 3/5] bitkeeper revision 1.1159.38.3 (4123550cLBAC07otAj8ftsT6MzujHQ) Make backend domain a per-device parameter. Restructure device controllers and adjust config handling. --- tools/python/xen/xend/XendDomainInfo.py | 93 ++----- tools/python/xen/xend/server/SrvDaemon.py | 35 +-- tools/python/xen/xend/server/blkif.py | 305 +++++++++++---------- tools/python/xen/xend/server/controller.py | 144 +++++----- tools/python/xen/xend/server/netif.py | 76 ++--- tools/python/xen/xm/create.py | 37 +-- 6 files changed, 321 insertions(+), 369 deletions(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index d2bff39b04..63dc7f49ab 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -137,7 +137,7 @@ def lookup_disk_uname(uname): segments = None return segments -def make_disk(vm, uname, dev, mode, recreate=0): +def make_disk(vm, config, uname, dev, mode, recreate=0): """Create a virtual disk device for a domain. @param vm: vm @@ -154,13 +154,8 @@ def make_disk(vm, uname, dev, mode, recreate=0): raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname) segment = segments[0] vdev = blkdev_name_to_number(dev) - backend = vm.get_device_backend('vbd') - ctrl = xend.blkif_create(vm.dom, recreate=recreate, backend=backend) - - def fn(ctrl): - return xend.blkif_dev_create(vm.dom, vdev, mode, segment, recreate=recreate) - ctrl.addCallback(fn) - return ctrl + ctrl = xend.blkif_create(vm.dom, recreate=recreate) + return ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate) def vif_up(iplist): """send an unsolicited ARP reply for all non link-local IP addresses. @@ -340,22 +335,6 @@ def append_deferred(dlist, v): if isinstance(v, defer.Deferred): dlist.append(v) -def _vm_configure1(val, vm): - d = vm.create_devices() - d.addCallback(_vm_configure2, vm) - return d - -def _vm_configure2(val, vm): - d = vm.configure_fields() - def cbok(results): - return vm - def cberr(err): - vm.destroy() - return err - d.addCallback(cbok) - d.addErrback(cberr) - return d - class XendDomainInfo: """Virtual machine object.""" @@ -379,7 +358,6 @@ class XendDomainInfo: self.console = None self.devices = {} self.device_index = {} - self.device_backends = {} self.configs = [] self.info = None self.ipaddrs = [] @@ -675,7 +653,6 @@ class XendDomainInfo: self.devices = {} self.device_index = {} - self.device_backends = {} self.configs = [] self.ipaddrs = [] @@ -915,25 +892,6 @@ class XendDomainInfo: self.restart_state = None return d - def configure_device_backend(self, type, sxpr): - """Configure the backend domain to use for devices of a given type. - - @param type: device type - @param sxpr: config - @raise: VmError if the domain id is missing - @raise: VmError if the domain does not exist - """ - dom = sxp.child_value(sxpr, 'domain') - if dom is None: - raise VmError('missing backend domain') - dominfo = domain_exists(dom) - if dominfo is None: - raise VmError('invalid backend domain:' + dom) - self.device_backends[type] = dominfo.dom - - def get_device_backend(self, type): - return self.device_backends.get(type, 0) - def configure_backends(self): """Set configuration flags if the vm is a backend for netif or blkif. Configure the backends to use for vbd and vif if specified. @@ -945,21 +903,9 @@ class XendDomainInfo: self.blkif_backend = 1 elif name == 'netif': self.netif_backend = 1 - elif name == 'vbd': - self.configure_device_backend('vbd', v) - elif name == 'vif': - self.configure_device_backend('vif', v) else: raise VmError('invalid backend type:' + str(name)) - def create_backends(self): - """Setup the netif and blkif backends. - """ - if self.blkif_backend: - xend.blkif_set_control_domain(self.dom, recreate=self.recreate) - if self.netif_backend: - xend.netif_set_control_domain(self.dom, recreate=self.recreate) - def configure(self): """Configure a vm. @@ -968,12 +914,19 @@ class XendDomainInfo: returns Deferred - calls callback with vm """ - if self.blkif_backend: - d = defer.Deferred() - d.callback(self) - else: - d = xend.blkif_create(self.dom, recreate=self.recreate) - d.addCallback(_vm_configure1, self) + d = self.create_devices() + d.addCallback(self._configure) + return d + + def _configure(self, val): + d = self.configure_fields() + def cbok(results): + return self + def cberr(err): + self.destroy() + return err + d.addCallback(cbok) + d.addErrback(cberr) return d def dom_construct(self, dom, config): @@ -1078,16 +1031,14 @@ def vm_dev_vif(vm, val, index): # raise VmError('vif: vif in netif backend domain') vif = vm.next_device_index('vif') vmac = sxp.child_value(val, "mac") - backend = vm.get_device_backend('vif') - xend.netif_create(vm.dom, recreate=vm.recreate, backend=backend) + 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 = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate) - def fn(id): - dev = xend.netif_dev(vm.dom, vif) + defer = ctrl.attachDevice(vif, val, recreate=vm.recreate) + def cbok(dev): dev.vifctl('up', vmname=vm.name) vm.add_device('vif', dev) - return id - defer.addCallback(fn) + return dev + defer.addCallback(cbok) return defer def vm_dev_vbd(vm, val, index): @@ -1108,7 +1059,7 @@ def vm_dev_vbd(vm, val, index): 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, uname, dev, mode, vm.recreate) + defer = make_disk(vm, val, uname, dev, mode, vm.recreate) def fn(vbd): vbd.dev = dev vbd.uname = uname diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index e6a1f30900..2cf58db57a 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -651,23 +651,12 @@ class Daemon: """ return self.channelF.getDomChannel(dom) - def blkif_set_control_domain(self, dom, recreate=0): - """Set the block device backend control domain. - """ - return self.blkifCF.setControlDomain(dom, recreate=recreate) - - def blkif_get_control_domain(self, dom): - """Get the block device backend control domain. - """ - return self.blkifCF.getControlDomain() - - def blkif_create(self, dom, recreate=0, backend=0): + def blkif_create(self, dom, recreate=0): """Create a block device interface controller. - Returns Deferred + Returns controller """ - d = self.blkifCF.createInstance(dom, recreate=recreate, backend=backend) - return d + return self.blkifCF.createInstance(dom, recreate=recreate) def blkifs(self): return [ x.sxpr() for x in self.blkifCF.getInstances() ] @@ -678,7 +667,7 @@ class Daemon: def blkif_dev(self, dom, vdev): return self.blkifCF.getDomainDevice(dom, vdev) - def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0): + def blkif_dev_create(self, dom, config, vdev, mode, segment, recreate=0): """Create a block device. Returns Deferred @@ -686,24 +675,14 @@ class Daemon: ctrl = self.blkifCF.getInstanceByDom(dom) if not ctrl: raise XendError('No blkif controller: %d' % dom) - d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate) + d = ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate) return d - def netif_set_control_domain(self, dom, recreate=0): - """Set the network interface backend control domain. - """ - return self.netifCF.setControlDomain(dom, recreate=recreate) - - def netif_get_control_domain(self, dom): - """Get the network interface backend control domain. - """ - return self.netifCF.getControlDomain() - - def netif_create(self, dom, recreate=0, backend=0): + def netif_create(self, dom, recreate=0): """Create a network interface controller. """ - return self.netifCF.createInstance(dom, recreate=recreate, backend=backend) + return self.netifCF.createInstance(dom, recreate=recreate) def netifs(self): return [ x.sxpr() for x in self.netifCF.getInstances() ] diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index c142e59da8..4a683610cb 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -17,13 +17,19 @@ class BlkifBackendController(controller.BackendController): """ Handler for the 'back-end' channel to a device driver domain. """ - def __init__(self, factory, dom): - controller.BackendController.__init__(self, factory, dom) + def __init__(self, ctrl, dom, handle): + controller.BackendController.__init__(self, ctrl, dom, handle) + self.connected = 0 + self.evtchn = None + self.handle = handle self.addMethod(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) self.registerChannel() + def __str__(self): + return '' % (self.controller.dom, self.dom) + def recv_be_driver_status_changed(self, msg, req): """Request handler for be_driver_status_changed messages. @@ -35,32 +41,109 @@ class BlkifBackendController(controller.BackendController): val = unpackMsg('blkif_be_driver_status_changed_t', msg) status = val['status'] -class BlkifControllerFactory(controller.SplitControllerFactory): + def connect(self, recreate=0): + """Connect the controller to the blkif control interface. + + @param recreate: true if after xend restart + @return: deferred + """ + log.debug("Connecting blkif %s", str(self)) + if recreate or self.connected: + d = defer.succeed(self) + else: + d = self.send_be_create() + d.addCallback(self.respond_be_create) + return d + + def send_be_create(self): + d = defer.Deferred() + msg = packMsg('blkif_be_create_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.handle }) + self.writeRequest(msg, response=d) + return d + + def respond_be_create(self, msg): + val = unpackMsg('blkif_be_create_t', msg) + print 'respond_be_create>', val + self.connected = 1 + return self + + def destroy(self): + """Disconnect from the blkif control interface and destroy it. + """ + def cb_destroy(val): + self.send_be_destroy() + d = defer.Deferred() + d.addCallback(cb_destroy) + self.send_be_disconnect(response=d) + + def send_be_disconnect(self, response=None): + log.debug('>BlkifBackendController>send_be_disconnect> %s', str(self)) + msg = packMsg('blkif_be_disconnect_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.handle }) + self.writeRequest(msg, response=response) + + def send_be_destroy(self, response=None): + log.debug('>BlkifBackendController>send_be_destroy> %s', str(self)) + msg = packMsg('blkif_be_destroy_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.handle }) + self.writeRequest(msg, response=response) + + def connectInterface(self, val): + self.evtchn = channel.eventChannel(0, self.controller.dom) + log.debug("Connecting blkif to event channel %s ports=%d:%d", + str(self), self.evtchn['port1'], self.evtchn['port2']) + msg = packMsg('blkif_be_connect_t', + { 'domid' : self.controller.dom, + 'blkif_handle' : self.handle, + 'evtchn' : self.evtchn['port1'], + 'shmem_frame' : val['shmem_frame'] }) + d = defer.Deferred() + d.addCallback(self.respond_be_connect) + self.writeRequest(msg, response=d) + + def respond_be_connect(self, msg): + """Response handler for a be_connect message. + + @param msg: message + @type msg: xu message + """ + val = unpackMsg('blkif_be_connect_t', msg) + print 'respond_be_connect>', str(self), val + self.send_fe_interface_status_changed() + + def send_fe_interface_status_changed(self, response=None): + msg = packMsg('blkif_fe_interface_status_changed_t', + { 'handle' : self.handle, + 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, + 'evtchn' : self.evtchn['port2'] }) + self.controller.writeRequest(msg, response=response) + +class BlkifControllerFactory(controller.ControllerFactory): """Factory for creating block device interface controllers. """ def __init__(self): - controller.SplitControllerFactory.__init__(self) + controller.ControllerFactory.__init__(self) - def createInstance(self, dom, recreate=0, backend=0): + def createInstance(self, dom, recreate=0): """Create a block device controller for a domain. @param dom: domain @type dom: int @param recreate: if true it's a recreate (after xend restart) @type recreate: bool - @return: deferred - @rtype: twisted.internet.defer.Deferred + @return: block device controller + @rtype: BlkifController """ blkif = self.getInstanceByDom(dom) - if blkif: - d = defer.Deferred() - d.callback(blkif) - else: - blkif = BlkifController(self, dom, backend) + if blkif is None: + blkif = BlkifController(self, dom) self.addInstance(blkif) - d = blkif.connect(recreate=recreate) - return d + return blkif def getDomainDevices(self, dom): """Get the block devices for a domain. @@ -86,15 +169,13 @@ class BlkifControllerFactory(controller.SplitControllerFactory): blkif = self.getInstanceByDom(dom) return (blkif and blkif.getDevice(vdev)) or None - def createBackendController(self, dom): - return BlkifBackendController(self, dom) - -class BlkDev(controller.Dev): +class BlkDev(controller.SplitDev): """Info record for a block device. """ - def __init__(self, ctrl, vdev, mode, segment): - controller.Dev.__init__(self, segment['device'], ctrl) + def __init__(self, ctrl, config, vdev, mode, segment): + controller.SplitDev.__init__(self, segment['device'], ctrl) + self.config = config self.dev = None self.uname = None self.vdev = vdev @@ -102,9 +183,10 @@ class BlkDev(controller.Dev): self.device = segment['device'] self.start_sector = segment['start_sector'] self.nr_sectors = segment['nr_sectors'] - - def getBackendController(self): - return self.controller.backendController + try: + self.backendDomain = int(sxp.child_value(config, 'backend', '0')) + except: + raise XendError('invalid backend domain') def readonly(self): return 'w' not in self.mode @@ -125,77 +207,77 @@ class BlkDev(controller.Dev): log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev) self.send_be_vbd_destroy() - def attach(self, d): + def attach(self): """Attach the device to its controller. - @param d: deferred to call with the device on success """ - d1 = defer.Deferred() - d1.addCallback(self.respond_be_vbd_create, d) - d1.addErrback(d.errback) - self.send_be_vbd_create(response=d1) + backend = self.getBackend() + d1 = backend.connect() + d2 = defer.Deferred() + d2.addCallback(self.send_be_vbd_create) + d1.chainDeferred(d2) + return d2 - def send_be_vbd_create(self, response=None): + def send_be_vbd_create(self, val): + d = defer.Deferred() + d.addCallback(self.respond_be_vbd_create) + backend = self.getBackend() msg = packMsg('blkif_be_vbd_create_t', { 'domid' : self.controller.dom, - 'blkif_handle' : self.controller.handle, + 'blkif_handle' : backend.handle, 'vdevice' : self.vdev, 'readonly' : self.readonly() }) - self.getBackendController().writeRequest(msg, response=response) + backend.writeRequest(msg, response=d) + return d - def respond_be_vbd_create(self, msg, d): + def respond_be_vbd_create(self, msg): """Response handler for a be_vbd_create message. Tries to grow the vbd. @param msg: message @type msg: xu message - @param d: deferred to call - @type d: Deferred """ val = unpackMsg('blkif_be_vbd_create_t', msg) - d1 = defer.Deferred() - d1.addCallback(self.respond_be_vbd_grow, d) - if d: d1.addErrback(d.errback) - self.send_be_vbd_grow(response=d1) + d = self.send_be_vbd_grow() + d.addCallback(self.respond_be_vbd_grow) + return d - def send_be_vbd_grow(self, response=None): + def send_be_vbd_grow(self): + d = defer.Deferred() + backend = self.getBackend() msg = packMsg('blkif_be_vbd_grow_t', { 'domid' : self.controller.dom, - 'blkif_handle' : self.controller.handle, + 'blkif_handle' : backend.handle, 'vdevice' : self.vdev, 'extent.device' : self.device, 'extent.sector_start' : self.start_sector, 'extent.sector_length' : self.nr_sectors }) - self.getBackendController().writeRequest(msg, response=response) + backend.writeRequest(msg, response=d) + return d - def respond_be_vbd_grow(self, msg, d): + def respond_be_vbd_grow(self, msg): """Response handler for a be_vbd_grow message. @param msg: message @type msg: xu message - @param d: deferred to call - @type d: Deferred or None """ val = unpackMsg('blkif_be_vbd_grow_t', msg) status = val['status'] if status != BLKIF_BE_STATUS_OKAY: - err = XendError("Adding extent to vbd failed: device %d, error %d" + raise XendError("Adding extent to vbd failed: device %d, error %d" % (self.vdev, status)) - #if(d): - # d.errback(err) - raise err - if d: - d.callback(self) + return self def send_be_vbd_destroy(self, response=None): log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d', self.controller.dom, self.vdev) + backend = self.getBackend() msg = packMsg('blkif_be_vbd_destroy_t', { 'domid' : self.controller.dom, - 'blkif_handle' : self.controller.handle, + 'blkif_handle' : backend.handle, 'vdevice' : self.vdev }) self.controller.delDevice(self.vdev) - self.getBackendController().writeRequest(msg, response=response) + backend.writeRequest(msg, response=response) class BlkifController(controller.SplitController): @@ -203,12 +285,12 @@ class BlkifController(controller.SplitController): for a domain. """ - def __init__(self, factory, dom, backend): + def __init__(self, factory, dom): """Create a block device controller. The controller must be connected using connect() before it can be used. Do not call directly - use createInstance() on the factory instead. """ - controller.SplitController.__init__(self, factory, dom, backend) + controller.SplitController.__init__(self, factory, dom) self.devices = {} self.addMethod(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED, @@ -216,25 +298,22 @@ class BlkifController(controller.SplitController): self.addMethod(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT, self.recv_fe_interface_connect) - self.handle = 0 - self.evtchn = None self.registerChannel() def sxpr(self): val = ['blkif', ['dom', self.dom]] - if self.evtchn: - val.append(['evtchn', - self.evtchn['port1'], - self.evtchn['port2']]) return val + def createBackend(self, dom, handle): + return BlkifBackendController(self, dom, handle) + def getDevices(self): return self.devices.values() def getDevice(self, vdev): return self.devices.get(vdev) - def addDevice(self, vdev, mode, segment): + def addDevice(self, config, vdev, mode, segment): """Add a device to the device table. @param vdev: device index @@ -246,8 +325,9 @@ class BlkifController(controller.SplitController): @return: device @rtype: BlkDev """ - if vdev in self.devices: return None - dev = BlkDev(self, vdev, mode, segment) + if vdev in self.devices: + raise XendError('device exists: ' + str(vdev)) + dev = BlkDev(self, config, vdev, mode, segment) self.devices[vdev] = dev return dev @@ -255,7 +335,7 @@ class BlkifController(controller.SplitController): if vdev in self.devices: del self.devices[vdev] - def attachDevice(self, vdev, mode, segment, recreate=0): + def attachDevice(self, config, vdev, mode, segment, recreate=0): """Attach a device to the specified interface. On success the returned deferred will be called with the device. @@ -270,13 +350,11 @@ class BlkifController(controller.SplitController): @return: deferred @rtype: Deferred """ - dev = self.addDevice(vdev, mode, segment) - if not dev: return -1 - d = defer.Deferred() + dev = self.addDevice(config, vdev, mode, segment) if recreate: - d.callback(dev) + d = defer.succeed(dev) else: - dev.attach(d) + d = dev.attach() return d def destroy(self): @@ -284,7 +362,7 @@ class BlkifController(controller.SplitController): """ log.debug("Destroying blkif domain=%d", self.dom) self.destroyDevices() - self.disconnect() + self.destroyBackends() def destroyDevices(self): """Destroy all devices. @@ -292,87 +370,28 @@ class BlkifController(controller.SplitController): for dev in self.getDevices(): dev.destroy() - def connect(self, recreate=0): - """Connect the controller to the blkif control interface. + def destroyBackends(self): + for backend in self.getBackends(): + backend.destroy() - @param recreate: true if after xend restart - @return: deferred - """ - log.debug("Connecting blkif domain=%d", self.dom) - d = defer.Deferred() - if recreate: - d.callback(self) - else: - def cbresp(msg): - return self - d.addCallback(cbresp) - self.send_be_create(response=d) - return d - - def send_be_create(self, response=None): - msg = packMsg('blkif_be_create_t', - { 'domid' : self.dom, - 'blkif_handle' : self.handle }) - self.backendController.writeRequest(msg, response=response) - - def disconnect(self): - """Disconnect from the blkif control interface and destroy it. - """ - def cb_destroy(val): - self.send_be_destroy() - d = defer.Deferred() - d.addCallback(cb_destroy) - self.send_be_disconnect(response=d) - - def send_be_disconnect(self, response=None): - log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom) - msg = packMsg('blkif_be_disconnect_t', - { 'domid' : self.dom, - 'blkif_handle' : self.handle }) - self.backendController.writeRequest(msg, response=response) - - def send_be_destroy(self, response=None): - log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom) - msg = packMsg('blkif_be_destroy_t', - { 'domid' : self.dom, - 'blkif_handle' : self.handle }) - self.backendController.writeRequest(msg, response=response) - def recv_fe_driver_status_changed(self, msg, req): + val = unpackMsg('blkif_fe_driver_status_changed_t', msg) + print 'recv_fe_driver_status_changed>', val + # For each backend? msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : self.handle, + { 'handle' : 0, 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED, 'evtchn' : 0 }) self.writeRequest(msg) def recv_fe_interface_connect(self, msg, req): val = unpackMsg('blkif_fe_interface_connect_t', msg) - self.evtchn = channel.eventChannel(0, self.dom) - log.debug("Connecting blkif to event channel dom=%d ports=%d:%d", - self.dom, self.evtchn['port1'], self.evtchn['port2']) - msg = packMsg('blkif_be_connect_t', - { 'domid' : self.dom, - 'blkif_handle' : val['handle'], - 'evtchn' : self.evtchn['port1'], - 'shmem_frame' : val['shmem_frame'] }) - d = defer.Deferred() - d.addCallback(self.respond_be_connect) - self.backendController.writeRequest(msg, response=d) + handle = val['handle'] + backend = self.getBackendByHandle(handle) + if backend: + backend.connectInterface(val) + else: + log.error('interface connect on unknown interface: handle=%d', handle) - def respond_be_connect(self, msg): - """Response handler for a be_connect message. - - @param msg: message - @type msg: xu message - """ - val = unpackMsg('blkif_be_connect_t', msg) - self.send_fe_interface_status_changed() - - def send_fe_interface_status_changed(self, response=None): - msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : self.handle, - 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, - 'evtchn' : self.evtchn['port2'] }) - self.writeRequest(msg, response=response) diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index 28662207bb..dd1a9e6ebe 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -372,68 +372,11 @@ class Controller(CtrlMsgRcvr): self.deregisterChannel() self.factory.instanceClosed(self) -class SplitControllerFactory(ControllerFactory): - """Factory for SplitControllers. - - @ivar backends: mapping of domain id to backend - @type backends: {int: BackendController} - """ - - def __init__(self): - ControllerFactory.__init__(self) - self.backends = {} - - def createInstance(self, dom, recreate=0, backend=0): - """Create an instance. Define in a subclass. - - @param dom: domain - @type dom: int - @param recreate: true if the instance is being recreated (after xend restart) - @type recreate: int - @param backend: backend domain - @type backend: int - @return: controller instance - @rtype: SplitController (or subclass) - """ - raise NotImplementedError() - - def getBackendController(self, dom): - """Get the backend controller for a domain. - - @param dom: domain - @return: backend controller - """ - ctrlr = self.backends.get(dom) - if ctrlr is None: - ctrlr = self.createBackendController(dom) - self.backends[dom] = ctrlr - return ctrlr - - def createBackendController(self, dom): - """Create a backend controller. Define in a subclass. - - @param dom: domain - """ - raise NotImplementedError() - - def delBackendController(self, ctrlr): - """Remove a backend controller. - - @param ctrlr: backend controller - """ - if ctrlr.dom in self.backends: - del self.backends[ctrlr.dom] - - def backendControllerClosed(self, ctrlr): - """Callback called when a backend is closed. - """ - self.delBackendController(ctrlr) - class BackendController(CtrlMsgRcvr): """Abstract class for a backend device controller attached to a domain. - @ivar factory: controller factory - @type factory: ControllerFactory + @ivar controller: frontend controller + @type controller: Controller @ivar dom: domain @type dom: int @ivar channel: channel to the domain @@ -441,10 +384,11 @@ class BackendController(CtrlMsgRcvr): """ - def __init__(self, factory, dom): + def __init__(self, controller, dom, handle): CtrlMsgRcvr.__init__(self) - self.factory = factory + self.controller = controller self.dom = int(dom) + self.handle = handle self.channel = None def close(self): @@ -452,31 +396,66 @@ class BackendController(CtrlMsgRcvr): def lostChannel(self): self.deregisterChannel() - self.factory.instanceClosed(self) - - + self.controller.backendClosed(self) + class SplitController(Controller): """Abstract class for a device controller attached to a domain. - A SplitController has a BackendContoller. + A SplitController manages a BackendController for each backend domain + it has at least one device for. """ - def __init__(self, factory, dom, backend): + def __init__(self, factory, dom): Controller.__init__(self, factory, dom) - self.backendDomain = None - self.backendController = None - self.setBackendDomain(backend) + self.backends = {} + self.backendHandle = 0 - def setBackendDomain(self, dom): - ctrlr = self.factory.getBackendController(dom) - self.backendDomain = ctrlr.dom - self.backendController = ctrlr + def getBackends(self): + return self.backends.values() - def getBackendDomain(self): - return self.backendDomain + def getBackendByHandle(self, handle): + for b in self.getBackends(): + if b.handle == handle: + return b + return None - def getBackendController(self): - return self.backendController + def getBackendByDomain(self, dom): + return self.backends.get(dom) + def getBackend(self, dom): + """Get the backend controller for a domain. + + @param dom: domain + @return: backend controller + """ + b = self.getBackendByDomain(dom) + if b is None: + handle = self.backendHandle + self.backendHandle += 1 + b = self.createBackend(dom, handle) + self.backends[b.dom] = b + return b + + def createBackend(self, dom, handle): + """Create a backend controller. Define in a subclass. + + @param dom: domain + @param handle: controller handle + """ + raise NotImplementedError() + + def delBackend(self, ctrlr): + """Remove a backend controller. + + @param ctrlr: backend controller + """ + if ctrlr.dom in self.backends: + del self.backends[ctrlr.dom] + + def backendClosed(self, ctrlr): + """Callback called when a backend is closed. + """ + self.delBackend(ctrlr) + class Dev: """Abstract class for a device attached to a device controller. @@ -517,4 +496,15 @@ class Dev: """ raise NotImplementedError() +class SplitDev(Dev): + + def __init__(self, idx, controller): + Dev.__init__(self, idx, controller) + self.backendDomain = 0 + + def getBackend(self): + return self.controller.getBackend(self.backendDomain) + + + diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index a5add8e7fb..864f6ebd2d 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -22,8 +22,8 @@ class NetifBackendController(controller.BackendController): """Handler for the 'back-end' channel to a device driver domain. """ - def __init__(self, factory, dom): - controller.BackendController.__init__(self, factory, dom) + def __init__(self, ctrl, dom, handle): + controller.BackendController.__init__(self, ctrl, dom, handle) self.addMethod(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED, self.recv_be_driver_status_changed) @@ -33,14 +33,14 @@ class NetifBackendController(controller.BackendController): val = unpackMsg('netif_be_driver_status_changed_t', msg) status = val['status'] -class NetifControllerFactory(controller.SplitControllerFactory): +class NetifControllerFactory(controller.ControllerFactory): """Factory for creating network interface controllers. """ def __init__(self): controller.ControllerFactory.__init__(self) - def createInstance(self, dom, recreate=0, backend=0): + def createInstance(self, dom, recreate=0): """Create or find the network interface controller for a domain. @param dom: domain @@ -49,7 +49,7 @@ class NetifControllerFactory(controller.SplitControllerFactory): """ netif = self.getInstanceByDom(dom) if netif is None: - netif = NetifController(self, dom, backend=backend) + netif = NetifController(self, dom) self.addInstance(netif) return netif @@ -72,22 +72,16 @@ class NetifControllerFactory(controller.SplitControllerFactory): netif = self.getInstanceByDom(dom) return (netif and netif.getDevice(vif)) or None - def createBackendController(self, dom): - return NetifBackendController(self, dom) - -class NetDev(controller.Dev): +class NetDev(controller.SplitDev): """Info record for a network device. """ def __init__(self, ctrl, vif, config): - controller.Dev.__init__(self, vif, ctrl) + controller.SplitDev.__init__(self, vif, ctrl) self.vif = vif self.evtchn = None self.configure(config) - def getBackendController(self): - return self.controller.backendController - def configure(self, config): self.config = config self.mac = None @@ -108,6 +102,11 @@ class NetDev(controller.Dev): for ipaddr in ipaddrs: self.ipaddr.append(sxp.child0(ipaddr)) + try: + self.backendDomain = int(sxp.child_value(config, 'backend', '0')) + except: + raise XendError('invalid backend domain') + def sxpr(self): vif = str(self.vif) mac = self.get_mac() @@ -168,16 +167,25 @@ class NetDev(controller.Dev): if vnet: vnet.vifctl(op, self.get_vifname(), self.get_mac()) - def attach(self, d): - print 'attach>', d - self.send_be_create(response=d) + def attach(self): + print 'attach>' + d = self.send_be_create() + d.addCallback(self.respond_be_create) + return d - def send_be_create(self, response=None): + def send_be_create(self): + d = defer.Deferred() msg = packMsg('netif_be_create_t', { 'domid' : self.controller.dom, 'netif_handle' : self.vif, 'mac' : self.mac }) - self.getBackendController().writeRequest(msg, response=response) + self.getBackend().writeRequest(msg, response=d) + return d + + def respond_be_create(self, msg): + val = unpackMsg('netif_be_create_t', msg) + print 'respond_be_create>', val + return self def destroy(self): """Destroy the device's resources and disconnect from the back-end @@ -187,22 +195,23 @@ class NetDev(controller.Dev): self.send_be_destroy() log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif) self.vifctl('down') - d = defer.Deferred() + d = self.send_be_disconnect() d.addCallback(cb_destroy) - self.send_be_disconnect(response=d) - def send_be_disconnect(self, response=None): + def send_be_disconnect(self): + d = defer.Deferred() msg = packMsg('netif_be_disconnect_t', { 'domid' : self.controller.dom, 'netif_handle' : self.vif }) - self.getBackendController().writeRequest(msg, response=response) + self.getBackend().writeRequest(msg, response=d) + return d def send_be_destroy(self, response=None): msg = packMsg('netif_be_destroy_t', { 'domid' : self.controller.dom, 'netif_handle' : self.vif }) self.controller.delDevice(self.vif) - self.getBackendController().writeRequest(msg, response=response) + self.getBackend().writeRequest(msg, response=response) def recv_fe_interface_connect(self, val, req): if not req: return @@ -215,14 +224,12 @@ class NetDev(controller.Dev): 'rx_shmem_frame' : val['rx_shmem_frame'] }) d = defer.Deferred() d.addCallback(self.respond_be_connect) - self.getBackendController().writeRequest(msg, response=d) + self.getBackend().writeRequest(msg, response=d) def respond_be_connect(self, msg): val = unpackMsg('netif_be_connect_t', msg) dom = val['domid'] vif = val['netif_handle'] - print 'respond_be_connect>', ' dom=', dom, ' vif=', vif - print 'respond_be_connect>', 'self.dom=', self.controller.dom, 'self.vif=', self.vif msg = packMsg('netif_fe_interface_status_changed_t', { 'handle' : self.vif, 'status' : NETIF_INTERFACE_STATUS_CONNECTED, @@ -242,8 +249,8 @@ class NetifController(controller.SplitController): """Network interface controller. Handles all network devices for a domain. """ - def __init__(self, factory, dom, backend): - controller.SplitController.__init__(self, factory, dom, backend) + def __init__(self, factory, dom): + controller.SplitController.__init__(self, factory, dom) self.devices = {} self.addMethod(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED, @@ -253,6 +260,9 @@ class NetifController(controller.SplitController): self.recv_fe_interface_connect) self.registerChannel() + def createBackend(self, dom, handle): + return NetifBackendController(self, dom, handle) + def sxpr(self): val = ['netif', ['dom', self.dom]] return val @@ -282,6 +292,8 @@ class NetifController(controller.SplitController): @param config: device configuration @return: device """ + if vif in self.devices: + raise XendError('device exists:' + str(vif)) dev = NetDev(self, vif, config) self.devices[vif] = dev return dev @@ -310,11 +322,10 @@ class NetifController(controller.SplitController): @return: deferred """ dev = self.addDevice(vif, config) - d = defer.Deferred() if recreate: - d.callback(self) + d = defer.succeed(dev) else: - dev.attach(d) + d = dev.attach() return d def recv_fe_driver_status_changed(self, msg, req): @@ -333,5 +344,6 @@ class NetifController(controller.SplitController): if dev: dev.recv_fe_interface_connect(val, req) else: - log.error('Received netif_fe_interface_connect for unknown vif: '+vif) + log.error('Received netif_fe_interface_connect for unknown vif: dom=%d vif=%d', + self.dom, vif) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 1a05da4e14..d23bfcfd60 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -126,19 +126,12 @@ gopts.var('netif', val='no|yes', fn=set_bool, default=0, use="Make the domain a network interface backend.") -gopts.var('vbd_backend', val='DOM', - fn=set_value, default=None, - use='Set the domain to use for the vbd backend.') - -gopts.var('vif_backend', val='DOM', - fn=set_value, default=None, - use='Set the domain to use for the vif backend.') - -gopts.var('disk', val='phy:DEV,VDEV,MODE', +gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]', fn=append_value, default=[], use="""Add a disk device to a domain. The physical device is DEV, which is exported to the domain as VDEV. The disk is read-only if MODE - is 'r', read-write if MODE is 'w'. + is 'r', read-write if MODE is 'w'. If DOM is specified it defines the + backend driver domain to use for the disk. The option may be repeated to add more than one disk. """) @@ -153,13 +146,14 @@ gopts.var('ipaddr', val="IPADDR", fn=append_value, default=[], use="Add an IP address to the domain.") -gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT", +gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM", fn=append_value, default=[], use="""Add a network interface with the given MAC address and bridge. The vif is configured by calling the given configuration script. If mac is not specified a random MAC address is used. If bridge is not specified the default bridge is used. If script is not specified the default script is used. + If backend is not specified the default backend driver domain is used. This option may be repeated to add more than one vif. Specifying vifs will increase the number of interfaces as needed. """) @@ -241,11 +235,13 @@ def configure_image(config, vals): def configure_disks(config_devs, vals): """Create the config for disks (virtual block devices). """ - for (uname, dev, mode) in vals.disk: + for (uname, dev, mode, backend) in vals.disk: config_vbd = ['vbd', ['uname', uname], ['dev', dev ], ['mode', mode ] ] + if backend: + config_vbd.append(['backend', backend]) config_devs.append(['device', config_vbd]) def configure_pci(config_devs, vals): @@ -285,16 +281,20 @@ def configure_vifs(config_devs, vals): mac = d.get('mac') bridge = d.get('bridge') script = d.get('script') + backend = d.get('backend') else: mac = randomMAC() bridge = None script = None + backend = None config_vif = ['vif'] config_vif.append(['mac', mac]) if bridge: config_vif.append(['bridge', bridge]) if script: config_vif.append(['script', script]) + if backend: + config_vif.append(['backend', backend]) config_devs.append(['device', config_vif]) def configure_vfr(config, vals): @@ -320,10 +320,6 @@ def make_config(vals): config.append(['backend', ['blkif']]) if vals.netif: config.append(['backend', ['netif']]) - if vals.vbd_backend: - config.append(['backend', ['vbd', ['dom', vals.vbd_backend]]]) - if vals.vif_backend: - config.append(['backend', ['vif', ['dom', vals.vif_backend]]]) if vals.restart: config.append(['restart', vals.restart]) if vals.console: @@ -342,7 +338,12 @@ def preprocess_disk(opts, vals): disk = [] for v in vals.disk: d = v.split(',') - if len(d) != 3: + n = len(d) + if n == 3: + d.append(none) + elif n == 4: + pass + else: opts.err('Invalid disk specifier: ' + v) disk.append(d) vals.disk = disk @@ -369,7 +370,7 @@ def preprocess_vifs(opts, vals): (k, v) = b.strip().split('=', 1) k = k.strip() v = v.strip() - if k not in ['mac', 'bridge']: + if k not in ['mac', 'bridge', 'script', 'backend']: opts.err('Invalid vif specifier: ' + vif) d[k] = v vifs.append(d) From 4a4b2b5c4101eec401fc4515dbea2419adf0e5e2 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 18 Aug 2004 13:36:27 +0000 Subject: [PATCH 4/5] bitkeeper revision 1.1159.38.4 (41235b5b8R2aV73aJwQTq0FCRPc6UA) Fix typo. --- tools/python/xen/xm/create.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index d23bfcfd60..dad9c8ee34 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -340,7 +340,7 @@ def preprocess_disk(opts, vals): d = v.split(',') n = len(d) if n == 3: - d.append(none) + d.append(None) elif n == 4: pass else: From 17acf34b9f791e3362444400b2d2ea19cbc1177e Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Wed, 18 Aug 2004 13:37:48 +0000 Subject: [PATCH 5/5] bitkeeper revision 1.1159.38.5 (41235bac45keyRYBSLnIxXITxalrzg) Add 'live' parameter to migrate. --- tools/python/xen/xend/XendClient.py | 7 ++++--- tools/python/xen/xend/XendDomain.py | 4 ++-- tools/python/xen/xend/XendMigrate.py | 15 ++++++++++----- tools/python/xen/xend/server/SrvDomain.py | 4 +++- tools/python/xen/xm/migrate.py | 6 +++++- tools/xfrd/xen_domain.c | 9 +++++++-- tools/xfrd/xen_domain.h | 5 ++++- tools/xfrd/xfrd.c | 16 ++++++++++++---- 8 files changed, 47 insertions(+), 19 deletions(-) diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index a5194fa748..5041e06cb7 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -480,10 +480,11 @@ class Xend: {'op' : 'save', 'file' : filename }) - def xend_domain_migrate(self, id, dst): + def xend_domain_migrate(self, id, dst, live=0): return self.xendPost(self.domainurl(id), - {'op' : 'migrate', - 'destination': dst }) + {'op' : 'migrate', + 'destination': dst, + 'live' : live }) 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 7dead8f820..05eb28cbe8 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -586,7 +586,7 @@ class XendDomain: self.refresh_schedule() return val - def domain_migrate(self, id, dst): + def domain_migrate(self, id, dst, live): """Start domain migration. @param id: domain id @@ -597,7 +597,7 @@ class XendDomain: print 'domain_migrate>', id, dst dominfo = self.domain_lookup(id) xmigrate = XendMigrate.instance() - val = xmigrate.migrate_begin(dominfo.id, dst) + val = xmigrate.migrate_begin(dominfo.id, dst, live=live) print 'domain_migrate<', val return val diff --git a/tools/python/xen/xend/XendMigrate.py b/tools/python/xen/xend/XendMigrate.py index b98e5d87fc..de207aeb5c 100644 --- a/tools/python/xen/xend/XendMigrate.py +++ b/tools/python/xen/xend/XendMigrate.py @@ -259,7 +259,7 @@ class XendMigrateInfo(XfrdInfo): """Representation of a migrate in-progress and its interaction with xfrd. """ - def __init__(self, xid, dom, host, port): + def __init__(self, xid, dom, host, port, live): XfrdInfo.__init__(self) self.xid = xid self.state = 'begin' @@ -268,10 +268,14 @@ class XendMigrateInfo(XfrdInfo): self.dst_host = host self.dst_port = port self.dst_dom = None + self.live = live self.start = 0 def sxpr(self): - sxpr = ['migrate', ['id', self.xid], ['state', self.state] ] + sxpr = ['migrate', + ['id', self.xid ], + ['state', self.state ], + ['live', self.live ] ] sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ] sxpr.append(sxpr_src) sxpr_dst = ['dst', ['host', self.dst_host] ] @@ -289,7 +293,8 @@ class XendMigrateInfo(XfrdInfo): self.src_dom, vmconfig, self.dst_host, - self.dst_port]) + self.dst_port, + self.live ]) def xfr_migrate_ok(self, xfrd, val): dom = int(sxp.child0(val)) @@ -410,7 +415,7 @@ class XendMigrate: reactor.connectTCP('localhost', XFRD_PORT, xcf) return info - def migrate_begin(self, dom, host, port=XFRD_PORT): + def migrate_begin(self, dom, host, port=XFRD_PORT, live=0): """Begin to migrate a domain to another host. @param dom: domain @@ -421,7 +426,7 @@ class XendMigrate: # Check dom for existence, not migrating already. # Subscribe to migrate notifications (for updating). xid = self.nextid() - info = XendMigrateInfo(xid, dom, host, port) + info = XendMigrateInfo(xid, dom, host, port, live) self.session_begin(info) return info.deferred diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index 50aa355e62..bdd57524ce 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -80,7 +80,8 @@ class SrvDomain(SrvDir): def op_migrate(self, op, req): fn = FormFn(self.xd.domain_migrate, [['dom', 'str'], - ['destination', 'str']]) + ['destination', 'str'], + ['live', 'int']]) deferred = fn(req.args, {'dom': self.dom.id}) print 'op_migrate>', deferred deferred.addCallback(self._op_migrate_cb, req) @@ -244,4 +245,5 @@ class SrvDomain(SrvDir): req.write('
' % url) req.write('
') req.write(' To host: ') + req.write('Live') req.write('
') diff --git a/tools/python/xen/xm/migrate.py b/tools/python/xen/xm/migrate.py index dd81aab0df..366fb5f694 100644 --- a/tools/python/xen/xm/migrate.py +++ b/tools/python/xen/xm/migrate.py @@ -22,6 +22,10 @@ gopts.opt('help', short='h', fn=set_true, default=0, use="Print this help.") +gopts.opt('live', short='l', + fn=set_true, default=0, + use="Use live migration.") + def help(argv): gopts.argv = argv gopts.usage() @@ -38,5 +42,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) + server.xend_domain_migrate(dom, dst, opts.vals.live) diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c index 2f6d0fa8f2..5f4dcda506 100644 --- a/tools/xfrd/xen_domain.c +++ b/tools/xfrd/xen_domain.c @@ -53,7 +53,10 @@ void xcfini(void){ * At some point during this the domain is suspended, and then there's no way back. * Even if something later goes wrong we can't restart the domain. */ -int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n){ +int xen_domain_snd(Conn *xend, IOStream *io, + uint32_t dom, + char *vmconfig, int vmconfig_n, + int live){ int err = 0; #ifdef _XEN_XFR_STUB_ char buf[1024]; @@ -89,7 +92,9 @@ int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int v ioctxt->suspend = domain_suspend; ioctxt->vmconfig = vmconfig; ioctxt->vmconfig_n = vmconfig_n; - + if(live){ + ioctxt->flags |= XCFLAGS_LIVE; + } 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 4b2e1c7e04..2b59f502ee 100644 --- a/tools/xfrd/xen_domain.h +++ b/tools/xfrd/xen_domain.h @@ -7,7 +7,10 @@ /** Define to use stubs. Undefine to use Xen ops. */ //#define _XEN_XFR_STUB_ -extern int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n); +extern int xen_domain_snd(Conn *xend, IOStream *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); diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c index 5f3b4752bf..87fbac7bb5 100644 --- a/tools/xfrd/xfrd.c +++ b/tools/xfrd/xfrd.c @@ -81,7 +81,7 @@ receiver: (xfr.hello ) (xfr.err ) - xend->xfrd (xfr.migrate ) + xend->xfrd (xfr.migrate ) (xfr.save ) xfrd->xend (xfr.suspend ) xfrd->xend (xfr.progress ) @@ -95,7 +95,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_save; // (xfr.save ) @@ -235,6 +235,7 @@ typedef struct XfrState { unsigned long xfr_port; char *xfr_host; uint32_t vmid_new; + int live; } XfrState; /** Get the name of a transfer state. @@ -607,7 +608,9 @@ int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){ if(err) goto exit; dprintf(">*** Sending domain %u\n", state->vmid); err = xen_domain_snd(xend, peer->out, - state->vmid, state->vmconfig, state->vmconfig_n); + state->vmid, + state->vmconfig, state->vmconfig_n, + state->live); dprintf(">*** Sent domain %u\n", state->vmid); if(err) goto exit; // Sending the domain suspends it, and there's no way back. @@ -752,7 +755,10 @@ int xfr_save(Args *args, XfrState *state, Conn *xend, char *file){ err = -EINVAL; goto exit; } - err = xen_domain_snd(xend, io, state->vmid, state->vmconfig, state->vmconfig_n); + err = xen_domain_snd(xend, io, + state->vmid, + state->vmconfig, state->vmconfig_n, + 0); if(err){ err = xfr_error(xend, err); } else { @@ -852,6 +858,8 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){ if(err) goto exit; err = portof(sxpr_childN(sxpr, n++, ONONE), &port); if(err) goto exit; + err = intof(sxpr_childN(sxpr, n++, ONONE), &state->live); + if(err) goto exit; err = xfr_send(args, state, conn, addr, port); } else if(sxpr_elementp(sxpr, oxfr_save)){