mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
bitkeeper revision 1.1159.128.1 (41780f0dzQjdvnhFtMuVv1YAmVoQ8Q)
Merge ssh://xenbk@gandalf.hpl.hp.com//var/bk/xeno-unstable.bk into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
This commit is contained in:
commit
28f5e0295b
14 files changed
+217
-149
No files matched your search
@@ -239,11 +239,12 @@ class Xend:
|
||||
{'op' : 'save',
|
||||
'file' : filename })
|
||||
|
||||
def xend_domain_migrate(self, id, dst, live=0):
|
||||
def xend_domain_migrate(self, id, dst, live=0, resource=0):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{'op' : 'migrate',
|
||||
'destination': dst,
|
||||
'live' : live })
|
||||
'live' : live,
|
||||
'resource' : resource })
|
||||
|
||||
def xend_domain_pincpu(self, id, cpu):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
|
||||
@@ -585,7 +585,7 @@ class XendDomain:
|
||||
self.refresh_schedule()
|
||||
return val
|
||||
|
||||
def domain_migrate(self, id, dst, live):
|
||||
def domain_migrate(self, id, dst, live=0, resource=0):
|
||||
"""Start domain migration.
|
||||
|
||||
@param id: domain id
|
||||
@@ -595,7 +595,7 @@ class XendDomain:
|
||||
# Don't forget to cancel restart for it.
|
||||
dominfo = self.domain_lookup(id)
|
||||
xmigrate = XendMigrate.instance()
|
||||
val = xmigrate.migrate_begin(dominfo, dst, live=live)
|
||||
val = xmigrate.migrate_begin(dominfo, dst, live=live, resource=resource)
|
||||
return val
|
||||
|
||||
def domain_save(self, id, dst, progress=0):
|
||||
|
||||
@@ -33,8 +33,6 @@ xend = server.SrvDaemon.instance()
|
||||
|
||||
from XendError import VmError
|
||||
|
||||
from server.blkif import blkdev_name_to_number
|
||||
|
||||
"""The length of domain names that Xen can handle.
|
||||
The names stored in Xen itself are not used for much, and
|
||||
xend can handle domain names of any length.
|
||||
@@ -92,24 +90,6 @@ def shutdown_reason(code):
|
||||
"""
|
||||
return shutdown_reasons.get(code, "?")
|
||||
|
||||
def make_disk(vm, config, uname, dev, mode, recreate=0):
|
||||
"""Create a virtual disk device for a domain.
|
||||
|
||||
@param vm: vm
|
||||
@param uname: device to export
|
||||
@param dev: device name in domain
|
||||
@param mode: read/write mode
|
||||
@param recreate: recreate flag (after xend restart)
|
||||
@return: deferred
|
||||
"""
|
||||
idx = vm.next_device_index('vbd')
|
||||
# todo: The 'dev' should be looked up in the context of the domain.
|
||||
vdev = blkdev_name_to_number(dev)
|
||||
if not vdev:
|
||||
raise VmError("vbd: Device not found: uname=%s dev=%s" % (uname, dev))
|
||||
ctrl = xend.blkif_create(vm.dom, recreate=recreate)
|
||||
return ctrl.attachDevice(idx, config, uname, vdev, mode, recreate=recreate)
|
||||
|
||||
def vif_up(iplist):
|
||||
"""send an unsolicited ARP reply for all non link-local IP addresses.
|
||||
|
||||
@@ -222,6 +202,7 @@ def vm_recreate(savedinfo, info):
|
||||
"""
|
||||
vm = XendDomainInfo()
|
||||
vm.recreate = 1
|
||||
vm.savedinfo = savedinfo
|
||||
vm.setdom(info['dom'])
|
||||
#vm.name = info['name']
|
||||
vm.memory = info['mem_kb']/1024
|
||||
@@ -239,6 +220,7 @@ def vm_recreate(savedinfo, info):
|
||||
vm.name = sxp.child_value(savedinfo, 'name')
|
||||
d = defer.succeed(vm)
|
||||
vm.recreate = 0
|
||||
vm.savedinfo = None
|
||||
return d
|
||||
|
||||
def vm_restore(src, progress=0):
|
||||
@@ -288,6 +270,18 @@ def append_deferred(dlist, v):
|
||||
if isinstance(v, defer.Deferred):
|
||||
dlist.append(v)
|
||||
|
||||
def dlist_err(val):
|
||||
"""Error callback suitable for a deferred list.
|
||||
In a deferred list the error callback is called with with Failure((error, index)).
|
||||
This callback extracts the error and returns it.
|
||||
|
||||
@param val: Failure containing (error, index)
|
||||
@type val: twisted.internet.failure.Failure
|
||||
"""
|
||||
|
||||
(error, index) = val.value
|
||||
return error
|
||||
|
||||
class XendDomainInfo:
|
||||
"""Virtual machine object."""
|
||||
|
||||
@@ -324,6 +318,7 @@ class XendDomainInfo:
|
||||
self.restart_state = None
|
||||
self.restart_time = None
|
||||
self.console_port = None
|
||||
self.savedinfo = None
|
||||
|
||||
def setdom(self, dom):
|
||||
"""Set the domain id.
|
||||
@@ -385,10 +380,21 @@ class XendDomainInfo:
|
||||
sxpr.append(['restart_state', self.restart_state])
|
||||
if self.restart_time:
|
||||
sxpr.append(['restart_time', str(self.restart_time)])
|
||||
devs = self.sxpr_devices()
|
||||
if devs:
|
||||
sxpr.append(devs)
|
||||
if self.config:
|
||||
sxpr.append(['config', self.config])
|
||||
return sxpr
|
||||
|
||||
def sxpr_devices(self):
|
||||
sxpr = ['devices']
|
||||
for devs in self.devices.values():
|
||||
for dev in devs:
|
||||
if hasattr(dev, 'sxpr'):
|
||||
sxpr.append(dev.sxpr())
|
||||
return sxpr
|
||||
|
||||
def check_name(self, name):
|
||||
"""Check if a vm name is valid. Valid names start with a non-digit
|
||||
and contain alphabetic characters, digits, or characters in '_-.:/+'.
|
||||
@@ -572,6 +578,25 @@ class XendDomainInfo:
|
||||
return d
|
||||
return None
|
||||
|
||||
def get_device_savedinfo(self, type, index):
|
||||
val = None
|
||||
if self.savedinfo is None:
|
||||
return val
|
||||
index = str(index)
|
||||
devinfo = sxp.child(self.savedinfo, 'devices')
|
||||
if devinfo is None:
|
||||
return val
|
||||
for d in sxp.children(devinfo, type):
|
||||
dindex = sxp.child_value(d, 'index')
|
||||
if dindex is None: continue
|
||||
if str(dindex) == index:
|
||||
val = d
|
||||
break
|
||||
return val
|
||||
|
||||
def get_device_recreate(self, type, index):
|
||||
return self.get_device_savedinfo(type, index) or self.recreate
|
||||
|
||||
def add_config(self, val):
|
||||
"""Add configuration data to a virtual machine.
|
||||
|
||||
@@ -699,6 +724,10 @@ class XendDomainInfo:
|
||||
"""Build the domain boot image.
|
||||
"""
|
||||
if self.recreate or self.restore: return
|
||||
if not os.path.isfile(kernel):
|
||||
raise VmError('Kernel image does not exist: %s' % kernel)
|
||||
if ramdisk and not os.path.isfile(ramdisk):
|
||||
raise VmError('Kernel ramdisk does not exist: %s' % ramdisk)
|
||||
if len(cmdline) >= 256:
|
||||
log.warning('kernel cmdline too long, domain %d', self.dom)
|
||||
dom = self.dom
|
||||
@@ -724,11 +753,6 @@ class XendDomainInfo:
|
||||
@param ramdisk: kernel ramdisk
|
||||
@param cmdline: kernel commandline
|
||||
"""
|
||||
if not self.recreate:
|
||||
if not os.path.isfile(kernel):
|
||||
raise VmError('Kernel image does not exist: %s' % kernel)
|
||||
if ramdisk and not os.path.isfile(ramdisk):
|
||||
raise VmError('Kernel ramdisk does not exist: %s' % ramdisk)
|
||||
#self.init_domain()
|
||||
if self.console:
|
||||
self.console.registerChannel()
|
||||
@@ -761,6 +785,7 @@ class XendDomainInfo:
|
||||
append_deferred(dlist, v)
|
||||
index[dev_name] = dev_index + 1
|
||||
deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
|
||||
deferred.addErrback(dlist_err)
|
||||
return deferred
|
||||
|
||||
def device_create(self, dev_config):
|
||||
@@ -826,7 +851,7 @@ class XendDomainInfo:
|
||||
def configure_memory(self):
|
||||
"""Configure vm memory limit.
|
||||
"""
|
||||
maxmem = sxp.get_child_value(self.config, "maxmem")
|
||||
maxmem = sxp.child_value(self.config, "maxmem")
|
||||
if maxmem is None:
|
||||
maxmem = self.memory
|
||||
xc.domain_setmaxmem(self.dom, maxmem_kb = maxmem * 1024)
|
||||
@@ -992,6 +1017,7 @@ class XendDomainInfo:
|
||||
log.warning("Unknown config field %s", field_name)
|
||||
index[field_name] = field_index + 1
|
||||
d = defer.DeferredList(dlist, fireOnOneErrback=1)
|
||||
d.addErrback(dlist_err)
|
||||
return d
|
||||
|
||||
|
||||
@@ -1005,7 +1031,7 @@ def vm_image_linux(vm, image):
|
||||
"""
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
cmdline = ""
|
||||
ip = sxp.child_value(image, "ip", "dhcp")
|
||||
ip = sxp.child_value(image, "ip", None)
|
||||
if ip:
|
||||
cmdline += " ip=" + ip
|
||||
root = sxp.child_value(image, "root")
|
||||
@@ -1030,9 +1056,11 @@ def vm_dev_vif(vm, val, index, change=0):
|
||||
vmac = sxp.child_value(val, "mac")
|
||||
ctrl = xend.netif_create(vm.dom, recreate=vm.recreate)
|
||||
log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac))
|
||||
defer = ctrl.attachDevice(vif, val, recreate=vm.recreate)
|
||||
recreate = vm.get_device_recreate('vif', index)
|
||||
defer = ctrl.attachDevice(vif, val, recreate=recreate)
|
||||
def cbok(dev):
|
||||
dev.vifctl('up', vmname=vm.name)
|
||||
dev.setIndex(index)
|
||||
vm.add_device('vif', dev)
|
||||
if change:
|
||||
dev.interfaceChanged()
|
||||
@@ -1048,23 +1076,19 @@ def vm_dev_vbd(vm, val, index, change=0):
|
||||
@param index: vbd index
|
||||
@return: deferred
|
||||
"""
|
||||
idx = vm.next_device_index('vbd')
|
||||
uname = sxp.child_value(val, 'uname')
|
||||
if not uname:
|
||||
raise VmError('vbd: Missing uname')
|
||||
dev = sxp.child_value(val, 'dev')
|
||||
if not dev:
|
||||
raise VmError('vbd: Missing dev')
|
||||
mode = sxp.child_value(val, 'mode', 'r')
|
||||
log.debug("Creating vbd dom=%d uname=%s dev=%s", vm.dom, uname, dev)
|
||||
defer = make_disk(vm, val, uname, dev, mode, vm.recreate)
|
||||
def fn(vbd):
|
||||
vbd.dev = dev
|
||||
vbd.uname = uname
|
||||
vm.add_device('vbd', vbd)
|
||||
log.debug("Creating vbd dom=%d uname=%s", vm.dom, uname)
|
||||
ctrl = xend.blkif_create(vm.dom, recreate=vm.recreate)
|
||||
recreate = vm.get_device_recreate('vbd', index)
|
||||
defer = ctrl.attachDevice(idx, val, recreate=recreate)
|
||||
def cbok(dev):
|
||||
dev.setIndex(index)
|
||||
vm.add_device('vbd', dev)
|
||||
if change:
|
||||
vbd.interfaceChanged()
|
||||
return vbd
|
||||
defer.addCallback(fn)
|
||||
dev.interfaceChanged()
|
||||
return dev
|
||||
defer.addCallback(cbok)
|
||||
return defer
|
||||
|
||||
def parse_pci(val):
|
||||
|
||||
@@ -260,7 +260,7 @@ class XendMigrateInfo(XfrdInfo):
|
||||
"""Representation of a migrate in-progress and its interaction with xfrd.
|
||||
"""
|
||||
|
||||
def __init__(self, xid, dominfo, host, port, live):
|
||||
def __init__(self, xid, dominfo, host, port, live=0, resource=0):
|
||||
XfrdInfo.__init__(self)
|
||||
self.xid = xid
|
||||
self.dominfo = dominfo
|
||||
@@ -271,13 +271,15 @@ class XendMigrateInfo(XfrdInfo):
|
||||
self.dst_port = port
|
||||
self.dst_dom = None
|
||||
self.live = live
|
||||
self.resource = resource
|
||||
self.start = 0
|
||||
|
||||
def sxpr(self):
|
||||
sxpr = ['migrate',
|
||||
['id', self.xid ],
|
||||
['state', self.state ],
|
||||
['live', self.live ] ]
|
||||
['live', self.live ],
|
||||
['resource', self.resource] ]
|
||||
sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
|
||||
sxpr.append(sxpr_src)
|
||||
sxpr_dst = ['dst', ['host', self.dst_host] ]
|
||||
@@ -300,7 +302,8 @@ class XendMigrateInfo(XfrdInfo):
|
||||
vmconfig,
|
||||
self.dst_host,
|
||||
self.dst_port,
|
||||
self.live ])
|
||||
self.live,
|
||||
self.resource ])
|
||||
|
||||
## def xfr_vm_suspend(self, xfrd, val):
|
||||
## def cbok(val):
|
||||
@@ -490,7 +493,7 @@ class XendMigrate:
|
||||
reactor.connectTCP('localhost', XFRD_PORT, xcf)
|
||||
return info.deferred
|
||||
|
||||
def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0):
|
||||
def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0):
|
||||
"""Begin to migrate a domain to another host.
|
||||
|
||||
@param dominfo: domain info
|
||||
@@ -499,7 +502,7 @@ class XendMigrate:
|
||||
@return: deferred
|
||||
"""
|
||||
xid = self.nextid()
|
||||
info = XendMigrateInfo(xid, dominfo, host, port, live)
|
||||
info = XendMigrateInfo(xid, dominfo, host, port, live, resource)
|
||||
return self.session_begin(info)
|
||||
|
||||
def save_begin(self, dominfo, file):
|
||||
|
||||
@@ -81,7 +81,8 @@ class SrvDomain(SrvDir):
|
||||
fn = FormFn(self.xd.domain_migrate,
|
||||
[['dom', 'str'],
|
||||
['destination', 'str'],
|
||||
['live', 'int']])
|
||||
['live', 'int'],
|
||||
['resource', 'int']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
print 'op_migrate>', deferred
|
||||
deferred.addCallback(self._op_migrate_cb, req)
|
||||
|
||||
@@ -5,6 +5,7 @@ from StringIO import StringIO
|
||||
|
||||
from twisted.protocols import http
|
||||
from twisted.web import error
|
||||
from twisted.python.failure import Failure
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendDomain
|
||||
@@ -94,7 +95,10 @@ class SrvDomainDir(SrvDir):
|
||||
def _op_create_err(self, err, req):
|
||||
"""Callback to handle errors in deferred domain creation.
|
||||
"""
|
||||
if isinstance(err, Failure):
|
||||
err = err.getErrorMessage()
|
||||
print 'op_create> Deferred Exception creating domain:', err
|
||||
traceback.print_exc()
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error creating domain: " + str(err))
|
||||
return str(err)
|
||||
|
||||
@@ -127,6 +131,8 @@ class SrvDomainDir(SrvDir):
|
||||
return val
|
||||
|
||||
def _op_restore_err(self, err, req):
|
||||
if isinstance(err, Failure):
|
||||
err = err.getErrorMessage()
|
||||
print 'op_create> Deferred Exception restoring domain:', err
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error restoring domain: "+ str(err))
|
||||
return str(err)
|
||||
|
||||
@@ -16,6 +16,46 @@ import channel
|
||||
import controller
|
||||
from messages import *
|
||||
|
||||
|
||||
def blkdev_name_to_number(name):
|
||||
"""Take the given textual block-device name (e.g., '/dev/sda1',
|
||||
'hda') and return the device number used by the OS. """
|
||||
|
||||
if re.match( '^/dev/', name ):
|
||||
n = name
|
||||
else:
|
||||
n = '/dev/' + name
|
||||
|
||||
try:
|
||||
return os.stat(n).st_rdev
|
||||
except Exception, ex:
|
||||
log.debug("exception looking up device number for %s: %s", name, ex)
|
||||
pass
|
||||
|
||||
# see if this is a hex device number
|
||||
if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
|
||||
return string.atoi(name,16)
|
||||
|
||||
return None
|
||||
|
||||
def blkdev_segment(name):
|
||||
"""Take the given block-device name (e.g. '/dev/sda1', 'hda')
|
||||
and return a dictionary { device, start_sector,
|
||||
nr_sectors, type }
|
||||
device: Device number of the given partition
|
||||
start_sector: Index of first sector of the partition
|
||||
nr_sectors: Number of sectors comprising this partition
|
||||
type: 'Disk' or identifying name for partition type
|
||||
"""
|
||||
val = None
|
||||
n = blkdev_name_to_number(name)
|
||||
if n:
|
||||
val = { 'device' : n,
|
||||
'start_sector' : long(0),
|
||||
'nr_sectors' : long(1L<<63),
|
||||
'type' : 'Disk' }
|
||||
return val
|
||||
|
||||
class BlkifBackendController(controller.BackendController):
|
||||
""" Handler for the 'back-end' channel to a block device driver domain.
|
||||
"""
|
||||
@@ -231,26 +271,70 @@ class BlkDev(controller.SplitDev):
|
||||
"""Info record for a block device.
|
||||
"""
|
||||
|
||||
def __init__(self, idx, ctrl, config, vdev, mode, segment):
|
||||
def __init__(self, idx, ctrl, config):
|
||||
controller.SplitDev.__init__(self, idx, ctrl)
|
||||
self.config = config
|
||||
self.dev = None
|
||||
self.uname = None
|
||||
self.vdev = vdev
|
||||
self.mode = mode
|
||||
self.device = segment['device']
|
||||
self.start_sector = segment['start_sector']
|
||||
self.nr_sectors = segment['nr_sectors']
|
||||
self.vdev = None
|
||||
self.mode = None
|
||||
self.type = None
|
||||
self.params = None
|
||||
self.node = None
|
||||
self.device = None
|
||||
self.start_sector = None
|
||||
self.nr_sectors = None
|
||||
self.configure(config)
|
||||
|
||||
def configure(self, config):
|
||||
self.config = config
|
||||
self.uname = sxp.child_value(config, 'uname')
|
||||
if not self.uname:
|
||||
raise VmError('vbd: Missing uname')
|
||||
# Split into type and type-specific params (which are passed to the
|
||||
# type-specific control script).
|
||||
(self.type, self.params) = string.split(self.uname, ':', 1)
|
||||
self.dev = sxp.child_value(config, 'dev')
|
||||
if not self.dev:
|
||||
raise VmError('vbd: Missing dev')
|
||||
self.mode = sxp.child_value(config, 'mode', 'r')
|
||||
# todo: The 'dev' should be looked up in the context of the domain.
|
||||
self.vdev = blkdev_name_to_number(self.dev)
|
||||
if not self.vdev:
|
||||
raise VmError('vbd: Device not found: %s' % self.dev)
|
||||
try:
|
||||
self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
|
||||
except:
|
||||
raise XendError('invalid backend domain')
|
||||
|
||||
def recreate(self, savedinfo):
|
||||
node = sxp.child_value(savedinfo, 'node')
|
||||
self.setNode(node)
|
||||
|
||||
def attach(self):
|
||||
node = Blkctl.block('bind', self.type, self.params)
|
||||
self.setNode(node)
|
||||
return self.attachBackend()
|
||||
|
||||
def unbind(self):
|
||||
if self.node is None: return
|
||||
log.debug("Unbinding vbd (type %s) from %s"
|
||||
% (self.type, self.node))
|
||||
Blkctl.block('unbind', self.type, self.node)
|
||||
|
||||
def setNode(self, node):
|
||||
segment = blkdev_segment(node)
|
||||
if not segment:
|
||||
raise VmError("vbd: Segment not found: uname=%s" % self.uname)
|
||||
self.node = node
|
||||
self.device = segment['device']
|
||||
self.start_sector = segment['start_sector']
|
||||
self.nr_sectors = segment['nr_sectors']
|
||||
|
||||
def readonly(self):
|
||||
return 'w' not in self.mode
|
||||
|
||||
def sxpr(self):
|
||||
val = ['blkdev',
|
||||
val = ['vbd',
|
||||
['idx', self.idx],
|
||||
['vdev', self.vdev],
|
||||
['device', self.device],
|
||||
@@ -259,13 +343,12 @@ class BlkDev(controller.SplitDev):
|
||||
val.append(['dev', self.dev])
|
||||
if self.uname:
|
||||
val.append(['uname', self.uname])
|
||||
if self.node:
|
||||
val.append(['node', self.node])
|
||||
if self.index is not None:
|
||||
val.append(['index', self.index])
|
||||
return val
|
||||
|
||||
def unbind(self):
|
||||
log.debug("Unbinding block dev (type %s) from %s"
|
||||
% (self.type, self.node))
|
||||
Blkctl.block('unbind', self.type, self.node)
|
||||
|
||||
def destroy(self, change=0):
|
||||
"""Destroy the device. If 'change' is true notify the front-end interface.
|
||||
|
||||
@@ -283,7 +366,7 @@ class BlkDev(controller.SplitDev):
|
||||
"""
|
||||
self.getBackendInterface().interfaceChanged()
|
||||
|
||||
def attach(self):
|
||||
def attachBackend(self):
|
||||
"""Attach the device to its controller.
|
||||
|
||||
"""
|
||||
@@ -340,8 +423,8 @@ class BlkDev(controller.SplitDev):
|
||||
val = unpackMsg('blkif_be_vbd_grow_t', msg)
|
||||
status = val['status']
|
||||
if status != BLKIF_BE_STATUS_OKAY:
|
||||
raise XendError("Adding extent to vbd failed: device %d, error %d"
|
||||
% (self.vdev, status))
|
||||
raise XendError("Adding extent to vbd failed: device %s, error %d"
|
||||
% (sxp.to_string(self.config), status))
|
||||
return self
|
||||
|
||||
def send_be_vbd_destroy(self):
|
||||
@@ -356,46 +439,6 @@ class BlkDev(controller.SplitDev):
|
||||
return d
|
||||
|
||||
|
||||
def blkdev_name_to_number(name):
|
||||
"""Take the given textual block-device name (e.g., '/dev/sda1',
|
||||
'hda') and return the device number used by the OS. """
|
||||
|
||||
if not re.match( '^/dev/', name ):
|
||||
n = '/dev/' + name
|
||||
else:
|
||||
n = name
|
||||
|
||||
try:
|
||||
return os.stat(n).st_rdev
|
||||
except Exception, e:
|
||||
print "blkdev_name_to_number> exception looking up device number for %s: %s" % (name, e)
|
||||
pass
|
||||
|
||||
# see if this is a hex device number
|
||||
if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
|
||||
return string.atoi(name,16)
|
||||
|
||||
return None
|
||||
|
||||
def lookup_raw_partn(name):
|
||||
"""Take the given block-device name (e.g., '/dev/sda1', 'hda')
|
||||
and return a dictionary { device, start_sector,
|
||||
nr_sectors, type }
|
||||
device: Device number of the given partition
|
||||
start_sector: Index of first sector of the partition
|
||||
nr_sectors: Number of sectors comprising this partition
|
||||
type: 'Disk' or identifying name for partition type
|
||||
"""
|
||||
|
||||
n = blkdev_name_to_number(name)
|
||||
if n:
|
||||
return [ { 'device' : n,
|
||||
'start_sector' : long(0),
|
||||
'nr_sectors' : long(1L<<63),
|
||||
'type' : 'Disk' } ]
|
||||
else:
|
||||
return None
|
||||
|
||||
class BlkifController(controller.SplitController):
|
||||
"""Block device interface controller. Handles all block devices
|
||||
for a domain.
|
||||
@@ -418,65 +461,37 @@ class BlkifController(controller.SplitController):
|
||||
val = ['blkif', ['dom', self.dom]]
|
||||
return val
|
||||
|
||||
def addDevice(self, idx, config, vdev, mode, segment):
|
||||
def addDevice(self, idx, config):
|
||||
"""Add a device to the device table.
|
||||
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
@param mode: read/write mode
|
||||
@type mode: string
|
||||
@param segment: segment
|
||||
@type segment: int
|
||||
@param config: device configuration
|
||||
@return: device
|
||||
@rtype: BlkDev
|
||||
"""
|
||||
if idx in self.devices:
|
||||
raise XendError('device exists: ' + str(idx))
|
||||
dev = BlkDev(idx, self, config, vdev, mode, segment)
|
||||
dev = BlkDev(idx, self, config )
|
||||
self.devices[idx] = dev
|
||||
return dev
|
||||
|
||||
def attachDevice(self, idx, config, uname, vdev, mode, recreate=0):
|
||||
def attachDevice(self, idx, config, recreate=0):
|
||||
"""Attach a device to the specified interface.
|
||||
On success the returned deferred will be called with the device.
|
||||
|
||||
@param idx: device id
|
||||
@param config: device configuration
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
@param mode: read/write mode
|
||||
@type mode: string
|
||||
@param segment: segment
|
||||
@type segment: int
|
||||
@param recreate: if true it's being recreated (after xend restart)
|
||||
@type recreate: bool
|
||||
@return: deferred
|
||||
@rtype: Deferred
|
||||
"""
|
||||
if not recreate:
|
||||
# Split into type and type-specific details (which are passed to the
|
||||
# type-specific control script).
|
||||
type, dets = string.split(uname, ':', 1)
|
||||
# Special case: don't bother calling a script for phy. Could
|
||||
# alternatively provide a "do nothing" script for phy devices...
|
||||
node = Blkctl.block('bind', type, dets)
|
||||
|
||||
segments = lookup_raw_partn(node)
|
||||
|
||||
if not segments:
|
||||
raise VmError("vbd: Segments not found: uname=%s" % uname)
|
||||
if len(segments) > 1:
|
||||
raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
|
||||
|
||||
segment = segments[0]
|
||||
|
||||
dev = self.addDevice(idx, config, vdev, mode, segment)
|
||||
|
||||
dev = self.addDevice(idx, config)
|
||||
if recreate:
|
||||
dev.recreate(recreate)
|
||||
d = defer.succeed(dev)
|
||||
else:
|
||||
dev.node = node
|
||||
dev.type = type
|
||||
d = dev.attach()
|
||||
return d
|
||||
|
||||
|
||||
@@ -682,10 +682,17 @@ class SplitDev(Dev):
|
||||
def __init__(self, idx, controller):
|
||||
Dev.__init__(self, idx, controller)
|
||||
self.backendDomain = 0
|
||||
self.index = None
|
||||
|
||||
def getBackendInterface(self):
|
||||
return self.controller.getBackendInterface(self.backendDomain)
|
||||
|
||||
def getIndex(self):
|
||||
return self.index
|
||||
|
||||
def setIndex(self, index):
|
||||
self.index = index
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -198,6 +198,8 @@ class NetDev(controller.SplitDev):
|
||||
val.append(['evtchn',
|
||||
self.evtchn['port1'],
|
||||
self.evtchn['port2']])
|
||||
if self.index is not None:
|
||||
val.append(['index', self.index])
|
||||
return val
|
||||
|
||||
def get_vifname(self):
|
||||
|
||||
@@ -26,6 +26,10 @@ gopts.opt('live', short='l',
|
||||
fn=set_true, default=0,
|
||||
use="Use live migration.")
|
||||
|
||||
gopts.opt('resource', short='r',
|
||||
fn=set_int, default=0,
|
||||
use="Set level of resource usage for migration.")
|
||||
|
||||
def help(argv):
|
||||
gopts.argv = argv
|
||||
gopts.usage()
|
||||
@@ -42,5 +46,5 @@ def main(argv):
|
||||
dst = args[1]
|
||||
if dom in [DOM0_NAME, DOM0_ID]:
|
||||
opts.err('Cannot migrate ' + dom)
|
||||
server.xend_domain_migrate(dom, dst, opts.vals.live)
|
||||
server.xend_domain_migrate(dom, dst, opts.vals.live, opts.vals.resource)
|
||||
|
||||