bitkeeper revision 1.1159.1.191 (41597997cc5ZJzvh6XLLSIhJ9hLEnA)

Initial support for automatic management of non-phy block devices.
This commit is contained in:
mwilli2@equilibrium.research committed 2004-09-28 14:47:51 +00:00
1 parent 0182d31a2a
commit e52d6a8915
8 files changed
+197 -65

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
"""Xend interface to block control scripts.
"""
import os
import os.path
import sys
import string
from xen.xend import XendRoot
xroot = XendRoot.instance()
"""Where network control scripts live."""
SCRIPT_DIR = xroot.block_script_dir
def block(op, type, dets, script=None):
"""Call a block control script.
Xend calls this with op 'bind' when it is about to export a block device
(other than a raw partition). The script is called with unbind when a
device is no longer in use and should be removed.
@param op: operation (start, stop, status)
@param type: type of block device (determines the script used)
@param dets: arguments to the control script
@param script: block script name
"""
if op not in ['bind', 'unbind']:
raise ValueError('Invalid operation:' + op)
# Special case phy devices - they don't require any (un)binding
if type == 'phy':
return dets
if script is None:
script = xroot.get_block_script(type)
script = os.path.join(SCRIPT_DIR, script)
args = [op] + string.split(dets, ':')
args = ' '.join(args)
out = os.popen(script + ' ' + args)
output = out.readline()
out.close()
return string.rstrip(output)
+3 -62
View File
@@ -33,6 +33,8 @@ 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.
@@ -90,61 +92,6 @@ def shutdown_reason(code):
"""
return shutdown_reasons.get(code, "?")
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:
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
def lookup_disk_uname(uname):
"""Lookup a list of segments for a physical device.
@param uname: name of the device in the format \'phy:dev\' for a physical device
@type uname: string
@return: list of extents that make up the named device
@rtype: [dict]
"""
( type, d_name ) = string.split( uname, ':' )
if type == "phy":
segments = lookup_raw_partn( d_name )
else:
segments = None
return segments
def make_disk(vm, config, uname, dev, mode, recreate=0):
"""Create a virtual disk device for a domain.
@@ -156,18 +103,12 @@ def make_disk(vm, config, uname, dev, mode, recreate=0):
@return: deferred
"""
idx = vm.next_device_index('vbd')
segments = lookup_disk_uname(uname)
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]
# 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, vdev, mode, segment, 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.
+6
View File
@@ -46,6 +46,9 @@ class XendRoot:
"""Where network control scripts live."""
network_script_dir = "/etc/xen/scripts"
"""Where block control scripts live."""
block_script_dir = "/etc/xen/scripts"
logfile_default = "/var/log/xend.log"
loglevel_default = 'DEBUG'
@@ -260,6 +263,9 @@ class XendRoot:
def get_xend_address(self):
return self.get_config_value('xend-address', '')
def get_block_script(self, type):
return self.get_config_value('block-%s' % type, '')
def get_network_script(self):
return self.get_config_value('network-script', 'network')
+73 -3
View File
@@ -5,9 +5,13 @@
from twisted.internet import defer
from xen.xend import sxp
from xen.xend import Blkctl
from xen.xend.XendLogging import log
from xen.xend.XendError import XendError
from xen.xend.XendError import XendError, VmError
import os
import re
import string
import channel
import controller
from messages import *
@@ -257,6 +261,11 @@ class BlkDev(controller.SplitDev):
val.append(['uname', self.uname])
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.
@@ -266,6 +275,7 @@ class BlkDev(controller.SplitDev):
d = self.send_be_vbd_destroy()
if change:
d.addCallback(lambda val: self.interfaceChanged())
d.addCallback(lambda val: self.unbind())
def interfaceChanged(self):
"""Tell the back-end to notify the front-end that a device has been
@@ -345,7 +355,47 @@ class BlkDev(controller.SplitDev):
backend.writeRequest(msg, response=d)
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.
@@ -386,7 +436,7 @@ class BlkifController(controller.SplitController):
self.devices[idx] = dev
return dev
def attachDevice(self, idx, config, vdev, mode, segment, recreate=0):
def attachDevice(self, idx, config, uname, vdev, mode, recreate=0):
"""Attach a device to the specified interface.
On success the returned deferred will be called with the device.
@@ -403,10 +453,30 @@ class BlkifController(controller.SplitController):
@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)
if recreate:
d = defer.succeed(dev)
else:
dev.node = node
dev.type = type
d = dev.attach()
return d
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.