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:
iap10@labyrinth.cl.cam.ac.uk committed 2004-10-21 19:33:33 +00:00
commit 28f5e0295b
14 files changed
+217 -149

No files matched your search

+3 -2
View File
@@ -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),
+2 -2
View File
@@ -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):
+67 -43
View File
@@ -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):
+8 -5
View File
@@ -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):
+2 -1
View 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)
+105 -90
View File
@@ -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
+2
View File
@@ -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):
+5 -1
View File
@@ -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)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.