mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1159.37.2 (41235cfbTT69HLcXLIBHgkcsv8UcGg)
Merge xenbk@gandalf:/var/bk/xeno-unstable.bk into wray-m-3.hpl.hp.com:/home/mjw/repos-bk/xeno-unstable.bk
This commit is contained in:
commit
3a5d173236
18 files changed
+525
-644
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
@@ -1074,20 +1027,18 @@ 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')
|
||||
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):
|
||||
@@ -1098,8 +1049,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')
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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() ]
|
||||
|
||||
@@ -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
|
||||
@@ -80,8 +80,9 @@ class SrvDomain(SrvDir):
|
||||
def op_migrate(self, op, req):
|
||||
fn = FormFn(self.xd.domain_migrate,
|
||||
[['dom', 'str'],
|
||||
['destination', 'str']])
|
||||
deferred = fn(req.args, {'dom': self.dom.name})
|
||||
['destination', 'str'],
|
||||
['live', 'int']])
|
||||
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 +108,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 +119,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 +129,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 +139,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 +161,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):
|
||||
@@ -244,4 +245,5 @@ class SrvDomain(SrvDir):
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<br><input type="submit" name="op" value="migrate">')
|
||||
req.write(' To host: <input type="text" name="destination">')
|
||||
req.write('<input type="checkbox" name="live" value="1">Live')
|
||||
req.write('</form>')
|
||||
@@ -17,79 +17,18 @@ 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.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 __str__(self):
|
||||
return '<BlkifBackendController %d %d>' % (self.controller.dom, self.dom)
|
||||
|
||||
def recv_be_driver_status_changed(self, msg, req):
|
||||
"""Request handler for be_driver_status_changed messages.
|
||||
@@ -101,45 +40,110 @@ 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):
|
||||
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)
|
||||
self.attached = 1
|
||||
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
|
||||
"""
|
||||
d = defer.Deferred()
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
if blkif:
|
||||
d.callback(blkif)
|
||||
else:
|
||||
blkif = BlkifController(self, dom, backend)
|
||||
if blkif is None:
|
||||
blkif = BlkifController(self, dom)
|
||||
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)
|
||||
return d
|
||||
return blkif
|
||||
|
||||
def getDomainDevices(self, dom):
|
||||
"""Get the block devices for a domain.
|
||||
@@ -158,82 +162,20 @@ class BlkifControllerFactory(controller.SplitControllerFactory):
|
||||
@param dom: domain
|
||||
@type dom: int
|
||||
@param vdev: device index
|
||||
@type vedv: int
|
||||
@type vdev: int
|
||||
@return: device
|
||||
@rtype: device
|
||||
"""
|
||||
blkif = self.getInstanceByDom(dom)
|
||||
return (blkif and blkif.getDevice(vdev)) or None
|
||||
|
||||
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):
|
||||
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
|
||||
@@ -241,7 +183,10 @@ class BlkDev(controller.Dev):
|
||||
self.device = segment['device']
|
||||
self.start_sector = segment['start_sector']
|
||||
self.nr_sectors = segment['nr_sectors']
|
||||
self.attached = 1
|
||||
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
|
||||
@@ -260,15 +205,92 @@ 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):
|
||||
"""Attach the device to its controller.
|
||||
|
||||
"""
|
||||
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, 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' : backend.handle,
|
||||
'vdevice' : self.vdev,
|
||||
'readonly' : self.readonly() })
|
||||
backend.writeRequest(msg, response=d)
|
||||
return 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
|
||||
"""
|
||||
val = unpackMsg('blkif_be_vbd_create_t', msg)
|
||||
d = self.send_be_vbd_grow()
|
||||
d.addCallback(self.respond_be_vbd_grow)
|
||||
return d
|
||||
|
||||
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' : backend.handle,
|
||||
'vdevice' : self.vdev,
|
||||
'extent.device' : self.device,
|
||||
'extent.sector_start' : self.start_sector,
|
||||
'extent.sector_length' : self.nr_sectors })
|
||||
backend.writeRequest(msg, response=d)
|
||||
return d
|
||||
|
||||
def respond_be_vbd_grow(self, msg):
|
||||
"""Response handler for a be_vbd_grow message.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
"""
|
||||
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))
|
||||
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' : backend.handle,
|
||||
'vdevice' : self.vdev })
|
||||
self.controller.delDevice(self.vdev)
|
||||
backend.writeRequest(msg, response=response)
|
||||
|
||||
|
||||
class BlkifController(controller.SplitController):
|
||||
"""Block device interface controller. Handles all block devices
|
||||
for a domain.
|
||||
"""
|
||||
|
||||
def __init__(self, factory, dom, backend):
|
||||
controller.SplitController.__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)
|
||||
self.devices = {}
|
||||
self.addMethod(CMSG_BLKIF_FE,
|
||||
CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED,
|
||||
@@ -276,25 +298,22 @@ class BlkifController(controller.SplitController):
|
||||
self.addMethod(CMSG_BLKIF_FE,
|
||||
CMSG_BLKIF_FE_INTERFACE_CONNECT,
|
||||
self.recv_fe_interface_connect)
|
||||
self.attached = 1
|
||||
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
|
||||
@@ -306,12 +325,17 @@ 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
|
||||
|
||||
def attachDevice(self, vdev, mode, segment, recreate=0):
|
||||
def delDevice(self, vdev):
|
||||
if vdev in self.devices:
|
||||
del self.devices[vdev]
|
||||
|
||||
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.
|
||||
|
||||
@@ -326,137 +350,48 @@ 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:
|
||||
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)
|
||||
d = dev.attach()
|
||||
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.destroyBackends()
|
||||
|
||||
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 reattachDevice(self, vdev):
|
||||
"""Reattach a device, when the back-end control domain has changed.
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
msg = packMsg('blkif_fe_interface_status_changed_t',
|
||||
{ 'handle' : 0,
|
||||
'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
|
||||
self.writeRequest(msg)
|
||||
def destroyBackends(self):
|
||||
for backend in self.getBackends():
|
||||
backend.destroy()
|
||||
|
||||
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' : 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.backendController.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 send_fe_interface_status_changed(self, response=None):
|
||||
msg = packMsg('blkif_fe_interface_status_changed_t',
|
||||
{ 'handle' : 0,
|
||||
'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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -370,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
|
||||
@@ -439,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):
|
||||
@@ -450,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.
|
||||
|
||||
@@ -515,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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ def packMsg(ty, params):
|
||||
else:
|
||||
args[k] = v
|
||||
msg = xu.message(major, minor, msgid, args)
|
||||
if DEBUG: print '<packMsg', msg.get_header()['id'], ty, params
|
||||
if DEBUG: print '<packMsg', msg.get_header()['id'], ty, args
|
||||
return msg
|
||||
|
||||
def unpackMsg(ty, msg):
|
||||
@@ -231,8 +231,9 @@ def unpackMsg(ty, msg):
|
||||
@rtype: dict
|
||||
"""
|
||||
args = msg.get_payload()
|
||||
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()
|
||||
|
||||
@@ -22,45 +22,25 @@ 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)
|
||||
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):
|
||||
class NetifControllerFactory(controller.ControllerFactory):
|
||||
"""Factory for creating network interface controllers.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
controller.ControllerFactory.__init__(self)
|
||||
self.attached = 1
|
||||
|
||||
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
|
||||
@@ -69,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
|
||||
|
||||
@@ -92,35 +72,12 @@ class NetifControllerFactory(controller.SplitControllerFactory):
|
||||
netif = self.getInstanceByDom(dom)
|
||||
return (netif and netif.getDevice(vif)) or None
|
||||
|
||||
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):
|
||||
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)
|
||||
@@ -145,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()
|
||||
@@ -205,25 +167,90 @@ class NetDev(controller.Dev):
|
||||
if vnet:
|
||||
vnet.vifctl(op, self.get_vifname(), self.get_mac())
|
||||
|
||||
def attach(self):
|
||||
print 'attach>'
|
||||
d = self.send_be_create()
|
||||
d.addCallback(self.respond_be_create)
|
||||
return d
|
||||
|
||||
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.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
|
||||
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 = self.send_be_disconnect()
|
||||
d.addCallback(cb_destroy)
|
||||
self.controller.send_be_disconnect(self.vif, response=d)
|
||||
|
||||
|
||||
def send_be_disconnect(self):
|
||||
d = defer.Deferred()
|
||||
msg = packMsg('netif_be_disconnect_t',
|
||||
{ 'domid' : self.controller.dom,
|
||||
'netif_handle' : self.vif })
|
||||
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.getBackend().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.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']
|
||||
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.
|
||||
"""
|
||||
|
||||
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,
|
||||
@@ -233,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
|
||||
@@ -262,10 +292,16 @@ 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
|
||||
|
||||
def delDevice(self, vif):
|
||||
if vif in self.devices:
|
||||
del self.devices[vif]
|
||||
|
||||
def destroy(self):
|
||||
"""Destroy the controller and all devices.
|
||||
"""
|
||||
@@ -285,79 +321,29 @@ class NetifController(controller.SplitController):
|
||||
@param recreate: recreate flag (true after xend restart)
|
||||
@return: deferred
|
||||
"""
|
||||
self.addDevice(vif, config)
|
||||
d = defer.Deferred()
|
||||
dev = self.addDevice(vif, config)
|
||||
if recreate:
|
||||
d.callback(self)
|
||||
d = defer.succeed(dev)
|
||||
else:
|
||||
self.send_be_create(vif, response=d)
|
||||
d = dev.attach()
|
||||
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: dom=%d vif=%d',
|
||||
self.dom, 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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -33,10 +37,10 @@ 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]:
|
||||
opts.err('Cannot migrate ' + dom)
|
||||
server.xend_domain_migrate(dom, dst)
|
||||
server.xend_domain_migrate(dom, dst, opts.vals.live)
|
||||
|
||||