ia64/xen-unstable
changeset 1041:7c3b17193b4b
bitkeeper revision 1.680 (40083bb4Kb4q4cb9z5eySYtCRnVh3A)
maw_vd.patch
maw_vd.patch
author | kaf24@scramble.cl.cam.ac.uk[kaf24] |
---|---|
date | Fri Jan 16 19:29:56 2004 +0000 (2004-01-16) |
parents | d75b1dfddb4b |
children | 3a01e5ddf625 |
files | .rootkeys docs/VBD-HOWTO.txt tools/examples/add_vbd_to_dom.py tools/examples/createlinuxdom.py tools/examples/list_vbds.py tools/examples/remove_vbd_from_dom.py tools/examples/vd_create.py tools/examples/vd_delete.py tools/examples/vd_format.py tools/examples/vd_refresh.py tools/xc/py/XenoUtil.py |
line diff
1.1 --- a/.rootkeys Fri Jan 16 17:32:17 2004 +0000 1.2 +++ b/.rootkeys Fri Jan 16 19:29:56 2004 +0000 1.3 @@ -7,6 +7,7 @@ 3f5ef5a24IaQasQE2tyMxrfxskMmvw README 1.4 3f5ef5a2l4kfBYSQTUaOyyD76WROZQ README.CD 1.5 3f69d8abYB1vMyD_QVDvzxy5Zscf1A TODO 1.6 3f9e7d53iC47UnlfORp9iC1vai6kWw docs/Makefile 1.7 +40083bb4LVQzRqA3ABz0__pPhGNwtA docs/VBD-HOWTO.txt 1.8 3fafbf11blCNItRsHe0UHwyu5CCDkw docs/Xeno-HOWTO 1.9 3f9e7d60PWZJeVh5xdnk0nLUdxlqEA docs/eps/xenlogo.eps 1.10 3f9e7d63lTwQbp2fnx7yY93epWS-eQ docs/figs/dummy 1.11 @@ -39,13 +40,20 @@ 3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Mak 1.12 3e6377b24eQqYMsDi9XrFkIgTzZ47A tools/balloon/Makefile 1.13 3e6377d6eiFjF1hHIS6JEIOFk62xSA tools/balloon/README 1.14 3e6377dbGcgnisKw16DPCaND7oGO3Q tools/balloon/balloon.c 1.15 +40083bb4_j61quzxosgZ19LUgLlgYw tools/examples/add_vbd_to_dom.py 1.16 3fbe2f12OPAkzIUtumU3wRAihnhocQ tools/examples/createlinuxdom.py 1.17 3fbe2f12dZbmXLlgQdMgkmnSUj23AQ tools/examples/destroydom.py 1.18 +40083bb4lxCIf5HRu6fwWUyHCYOHKA tools/examples/list_vbds.py 1.19 3fbe2f12ltvweb13kBSsxqzZDAq4sg tools/examples/listdoms.py 1.20 3fca7700PVj36cZObaFZlQicRiw1pQ tools/examples/pincpu.py 1.21 3fd8bc48ww3aOqPhYjCr8KGulG0NQQ tools/examples/readxenconsolering.py 1.22 +40083bb4zWkCUTHJKd1ApEOoPAuihg tools/examples/remove_vbd_from_dom.py 1.23 3fccbe068ov0YCxnk-2m4law19QMmA tools/examples/startdom.py 1.24 3fbe2f12Bnt8mwmr1ZCP6HWGS6yvYw tools/examples/stopdom.py 1.25 +40083bb4LeyQyL-0riaV3UYDfHkl5g tools/examples/vd_create.py 1.26 +40083bb4TmKs8pcFkOcJj1bKn3zcmg tools/examples/vd_delete.py 1.27 +40083bb4u9Od6ujgect6mrxWfkk1pQ tools/examples/vd_format.py 1.28 +40083bb4NhDpKiYTrebI3ZjX__oI_w tools/examples/vd_refresh.py 1.29 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile 1.30 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile 1.31 3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/docs/VBD-HOWTO.txt Fri Jan 16 19:29:56 2004 +0000 2.3 @@ -0,0 +1,273 @@ 2.4 +Virtual Block Devices / Virtual Disks in Xen - HOWTO 2.5 +==================================================== 2.6 + 2.7 +HOWTO for Xen 1.2 2.8 + 2.9 +Mark A. Williamson (mark.a.williamson@intel.com) 2.10 +(C) Intel Research Cambridge 2004 2.11 + 2.12 +Introduction 2.13 +------------ 2.14 + 2.15 +This document describes the new Virtual Block Device (VBD) and Virtual Disk 2.16 +features available in Xen release 1.2. First, a brief introduction to some 2.17 +basic disk concepts on a Xen system: 2.18 + 2.19 +Virtual Block Devices (VBDs): 2.20 + VBDs are the disk abstraction provided by Xen. All XenoLinux disk accesses 2.21 + go through the VBD driver. Using the VBD functionality, it is possible 2.22 + to selectively grant domains access to portions of the physical disks 2.23 + in the system. 2.24 + 2.25 + A virtual block device can also consist of multiple extents from the 2.26 + physical disks in the system, allowing them to be accessed as a single 2.27 + uniform device from the domain with access to that VBD. 2.28 + 2.29 + Everyone who uses Xen / XenoLinux uses VBDs but for less advanced uses 2.30 + they can almost be ignored. 2.31 + 2.32 +Virtual Disks (VDs): 2.33 + VDs are an abstraction built on top of the functionality provided by 2.34 + VBDs. The VD management code maintains a "free pool" of disk space on 2.35 + the system that has been reserved for use with VDs. The tools can 2.36 + automatically allocate collections of extents from this free pool to 2.37 + create "virtual disks" on demand. 2.38 + 2.39 + VDs can then be used just like normal disks by domains. VDs appear 2.40 + just like any other disk to guest domains, since they use the same VBD 2.41 + abstraction, as provided by Xen. 2.42 + 2.43 + Using VDs is optional, since it's always possible to dedicate 2.44 + partitions, or entire disks to your virtual machines. VDs are handy 2.45 + when you have a dynamically changing set of virtual machines and you 2.46 + don't want to have to keep repartitioning in order to provide them with 2.47 + disk space. 2.48 + 2.49 +If that didn't all make sense, it doesn't matter too much ;-) Using the 2.50 +functionality is fairly straightforward and some examples will clarify things. 2.51 +The text below expands a bit on the concepts involved, finishing up with a 2.52 +walkthrough of some simple virtual disk management tasks. 2.53 + 2.54 + 2.55 +Virtual Block Devices 2.56 +--------------------- 2.57 + 2.58 +Before covering VD management, it's worth discussing some aspects of the VBD 2.59 +functionality that will be useful to know. 2.60 + 2.61 +A VBD is made up of a number of extents from physical disk devices. The 2.62 +extents for a VBD don't have to be contiguous, or even on the same device. Xen 2.63 +performs address translation so that they appear as a single contiguous 2.64 +device. 2.65 + 2.66 +When the VBD layer is used to give access to entire drives or entire 2.67 +partitions, the VBDs simply consist of a single extent, corresponding to the 2.68 +drive or partition used. When used with Virtual Disks, the extent list 2.69 +functionality will be used (discussed later). 2.70 + 2.71 +Xen 1.2 and its associated XenoLinux release support automatic registration / 2.72 +removal of VBDs. It has always been possible to add a VBD to a running 2.73 +XenoLinux domain but it was then necessary to run "xen_vbd_refresh" in order 2.74 +for the new device to be detected. Nowadays, when a VBD is added, the domain 2.75 +it's added to automatically registers the disk. 2.76 + 2.77 +Note that it is possible to use the VBD functionality to allow multiple domains 2.78 +write access to the same areas of disk. This is almost always a bad thing! 2.79 + 2.80 +The provided example script createlinuxdom.py does its best to check that disk 2.81 +areas are not shared unsafely and will catch many cases of this. Setting the 2.82 +vbd_expert variable in that script controls how unsafe it allows VBD mappings 2.83 +to be - 0 should be right for most people ;-) 2.84 + 2.85 + 2.86 +Virtual Disk Management 2.87 +----------------------- 2.88 + 2.89 +The VD management code runs entirely in userspace. The code is written in 2.90 +Python and can therefore be accessed from custom scripts, as well as from the 2.91 +convenience scripts provided. The underlying VD database is a SQLite database 2.92 +in /var/spool/xen_vdisks.sqlite. 2.93 + 2.94 +The scripts provided are as follows: 2.95 + 2.96 +vd_format.py - "Formats" a partition or disk device for use storing 2.97 + virtual disks. This does not actually write data to the 2.98 + specified device. Rather, it adds the device to the VD 2.99 + free-space pool, for later allocation. 2.100 + 2.101 + You should only add devices that correspond directly to 2.102 + physical disks / partitions - trying to use a VBD that you 2.103 + have created yourself as part of the free space pool has 2.104 + undefined (possibly nasty) results. 2.105 + 2.106 +vd_create.py - Creates a virtual disk of specified size by allocating space 2.107 + from the free space pool. The virtual disk is identified 2.108 + in future by the unique ID returned by this script. 2.109 + 2.110 + The disk can be given an expiry time, if desired. For 2.111 + most users, the best idea is to specify a time of 0 (which 2.112 + has the special meaning "never expire") and then 2.113 + explicitly delete the VD when finished with it - 2.114 + otherwise, VDs could disappear unexpectedly... 2.115 + 2.116 +vd_refresh.py - Allows the expiry time of a (not yet expired) virtual disk to 2.117 + be modified. Be aware the VD will disappear when the time has 2.118 + expired. 2.119 + 2.120 +vd_delete.py - Explicitly delete a VD. Makes it disappear immediately. 2.121 + 2.122 + 2.123 +The functionality provided by these scripts is also available directly from 2.124 +Python functions in the XenoUtil module - you can use this functionality in 2.125 +your own scripts. 2.126 + 2.127 +Populating VDs: 2.128 + 2.129 +Once you've created a VD, you might want to populate it from DOM0 (for 2.130 +instance, to put a root filesystem onto it for a guest domain). This can be 2.131 +done by dynamically creating a VBD - this is discussed below. 2.132 + 2.133 +More detail: 2.134 + 2.135 +When you use vd_format.py to add a device to the free space pool, the device is 2.136 +logically split up into extents. These extents are recorded in the Virtual 2.137 +Disk Management database in /var/spool/xen_vdisks.sqlite. 2.138 + 2.139 +When you use vd_create.py to add create a virtual disk, some of the extents in 2.140 +the free space pool are reallocated for that virtual disk and a record for that 2.141 +VD is added to the database. When VDs are mapped into domains as VBDs, the 2.142 +system looks up the allocated extents for the virtual disk in order to set up 2.143 +the underlying VBD. 2.144 + 2.145 +Free space is identified by the fact that it belongs to an "expired" disk. 2.146 +When vd_format.py adds a real device to the free pool, it actually divides it 2.147 +into extents and adds them to an already-expired virtual disk. 2.148 + 2.149 +If you set an expiry time on a VD, its extents will be liable to be reallocated 2.150 +to new VDs as soon as that expiry time runs out. Therefore, be careful when 2.151 +setting expiry times. 2.152 + 2.153 +Finally, vd_delete.py can be used to delete virtual disks when they are no 2.154 +longer needed. It works by causing them to expire immediately. 2.155 + 2.156 +Security note: 2.157 + 2.158 +The disk space for VDs is not zeroed when it is initially added to the free 2.159 +space pool OR when a VD expires OR when a VD is created. Therefore, if this is 2.160 +not done manually it is possible for a domain to read a VD to determine what 2.161 +was written by previous owners of its constituent extents. If this is a 2.162 +problem, users should manually clean the VD in some way before allocating 2.163 + 2.164 + 2.165 +Dynamically Registering VBDs 2.166 +---------------------------- 2.167 + 2.168 +Two scripts are included to make it easy to add VDs to domains. 2.169 + 2.170 +add_vbd_to_dom.py - Creates a VBD corresponding to either a physical 2.171 + device or a virtual disk and adds it as a specified 2.172 + device under the target domain, with either read or 2.173 + write access. 2.174 + 2.175 +remove_vbd_from_dom.py - Removes the VBD associated with a specified device 2.176 + node from the target domain. 2.177 + 2.178 +These scripts are most useful when populating VDs. VDs can't be populated 2.179 +directly, since they don't correspond to real devices. Using: 2.180 + 2.181 + add_vbd_to_dom.py vd:your_vd_id /dev/wherever 0 rw 2.182 + 2.183 +You can make a virtual disk available to DOM0. Sensible devices to map VDs to 2.184 +in DOM0 are the /dev/xvd* nodes, since that makes it obvious that they are Xen 2.185 +virtual devices that don't correspond to real physical devices. 2.186 + 2.187 +You can then format, mount and populate the VD through the nominated device 2.188 +node. When you've finished, use: 2.189 + 2.190 + remove_vbd_from_dom.py /dev/whatever 0 2.191 + 2.192 +To revoke DOM0's access to it. It's then ready for use in a guest domain. 2.193 + 2.194 + 2.195 + 2.196 +You can also use add_vbd_to_dom.py to grant access to a physical device to a 2.197 +guest - you might use this to temporarily share a partition, or to add access 2.198 +to a partition that wasn't granted at boot time. Again, remove_vbd_from_dom.py 2.199 +allows you to revoke access. 2.200 + 2.201 +When playing with VBDs, remember that in general, it is only safe for two 2.202 +domains to have access to a filesystem if they both have read-only access. You 2.203 +shouldn't be trying to share anything which is writeable, even if only by one 2.204 +domain, unless you're really sure you know what you're doing! 2.205 + 2.206 + 2.207 + 2.208 +Walkthrough: Booting a domain from a VD 2.209 +--------------------------------------- 2.210 + 2.211 +As an example, here is a sequence of commands you might use to create a virtual 2.212 +disk, populate it with a root filesystem and boot a domain from it. These 2.213 +steps assume that you've installed the example scripts somewhere on your PATH - 2.214 +if you haven't done that, you'll need to specify a fully qualified pathname in 2.215 +the examples below. The steps also assume that you know how to use the 2.216 +createlinuxdom.py script provided and have already set it up for your local 2.217 +configuration, apart from the virtual disks info. 2.218 + 2.219 +First, if you haven't done so already, you'll initialise the free space pool by 2.220 +adding a real partition to it. The details are stored in the database, so 2.221 +you'll only need to do it once. You can also use this command to add further 2.222 +partitions to the existing free space pool. 2.223 + 2.224 +> vd_format.py /dev/<real partition> 2.225 + 2.226 +Now you'll want to allocate the space for your virtual disk. Do so using the 2.227 +following, specifying the size in megabytes. 2.228 + 2.229 +> vd_create.py <chosen size> 2.230 + 2.231 +At this point, the vd_create.py program will tell you the virtual disk ID. 2.232 +Note it down, as it is how you will identify the virtual device in future. 2.233 + 2.234 +If you don't want the VD to be bootable (i.e. you're booting a domain from some 2.235 +other medium and just want it to be able to access this VD), you can simply add 2.236 +it to the vbds list in your custom createlinuxdom.py (step 5) and then run that 2.237 +script. Any formatting / populating of the VD can be done from that domain. 2.238 + 2.239 +If you want to boot off your new VD as well then you need to populate it with a 2.240 +standard Linux root filesystem. You'll need to temporarily add the VD to DOM0 2.241 +in order to do this. To give DOM0 r/w access to the VD, use the following 2.242 +command line, substituting the ID you got earlier. 2.243 + 2.244 +> add_vbd_to_dom.py vd:<id> /dev/xvda 0 rw 2.245 + 2.246 +This attaches the VD to the device /dev/xvda - you can use other devices if you 2.247 +choose too but with the xvd* devices it's obvious you're using a virtual device. 2.248 + 2.249 +Now make a filesystem on this device, mount it and populate it with a root 2.250 +filesystem. These steps are exactly the same as under normal Linux. When 2.251 +you've finished, unmount the filesystem again. 2.252 + 2.253 +You should now remove the VD from DOM0. This will prevent you accidentally 2.254 +changing it in DOM0, whilst the guest domain is using it. 2.255 + 2.256 +> remove_vbd_from_dom.py /dev/xvda 0 2.257 + 2.258 +It should now be possible to boot a guest domain from the VD. To do this, you 2.259 +should add the VD's details to the vbds list in step 5 of createlinuxdom.py and 2.260 +set the value of rootbit in step 6. For instance, you might add: 2.261 + 2.262 +('vd:<id>', '/dev/xvda', 'w') 2.263 + 2.264 +To the vbds list in step 5 - this gives the domain writeable access to the VD 2.265 +as if it were the domain's /dev/xvda. 2.266 + 2.267 +Then you would set: 2.268 + 2.269 +rootbit = "root=/dev/xvda ro" 2.270 + 2.271 +In step 6 to tell the kernel where the root filesystem is. 2.272 + 2.273 + 2.274 + 2.275 +Once these variables are set, you can run createlinuxdom.py to start your new 2.276 +domain.
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/examples/add_vbd_to_dom.py Fri Jan 16 19:29:56 2004 +0000 3.3 @@ -0,0 +1,51 @@ 3.4 +#!/usr/bin/env python 3.5 + 3.6 +# Used to map a VBD into a domain's device space. Useful for populating a new 3.7 +# VBD with data from DOM0 before starting a new domain using it, for instance. 3.8 + 3.9 +import Xc, XenoUtil, sys 3.10 + 3.11 +XenoUtil.VBD_EXPERT_LEVEL = 0 # sets the allowed level of potentially unsafe mappings 3.12 + 3.13 +def usage(): 3.14 + print >>sys.stderr,"""Usage: add_vdisk_to_dom.py uname target-dev target-dom [perms] 3.15 + uname - the uname of the source device, e.g. vd:2341 or phy:hda3 3.16 + target-dev - the device node to map the VBD to 3.17 + target-dom - domain to add the new VBD to 3.18 + perms - optionally specify 'r', or 'rw' (default is 'r') 3.19 + """ 3.20 + sys.exit(1) 3.21 + 3.22 +xc = Xc.new() 3.23 + 3.24 +if not 4 <= len(sys.argv) <= 5: 3.25 + print len(sys.argv) 3.26 + usage() 3.27 + 3.28 +writeable = 0 3.29 + 3.30 +if len(sys.argv) == 5: 3.31 + if sys.argv[4] == 'rw': 3.32 + writeable = 1; 3.33 + else: 3.34 + if sys.argv[4] != 'r': 3.35 + usage() 3.36 + 3.37 +segments = XenoUtil.lookup_disk_uname(sys.argv[1]) 3.38 + 3.39 +if XenoUtil.vd_extents_validate(segments,writeable) < 0: 3.40 + print "That mapping is too unsafe for the current VBD expertise level" 3.41 + sys.exit(1) 3.42 + 3.43 +virt_dev = XenoUtil.blkdev_name_to_number(sys.argv[2]) 3.44 + 3.45 +target_dom = int(sys.argv[3]) 3.46 + 3.47 +xc.vbd_create(target_dom,virt_dev,writeable) 3.48 + 3.49 +if xc.vbd_setextents( target_dom, virt_dev, segments ): 3.50 + print "Error populating VBD vbd=%d\n" % virt_dev 3.51 + sys.exit(1) 3.52 + 3.53 + 3.54 +print "Added " + sys.argv[1] + " to domain " + sys.argv[3] + " as device " + sys.argv[2]
4.1 --- a/tools/examples/createlinuxdom.py Fri Jan 16 17:32:17 2004 +0000 4.2 +++ b/tools/examples/createlinuxdom.py Fri Jan 16 19:29:56 2004 +0000 4.3 @@ -51,6 +51,12 @@ vbds = [ ('phy:sda%d'%(7+guestid),'sda1' 4.4 ('phy:sda6','sda6','r'), 4.5 ('phy:cdrom','hdd','r') ] 4.6 4.7 +# STEP 5b. Set the VBD expertise level. Most people should leave this 4.8 +# on 0, at least to begin with - this script can detect most dangerous 4.9 +# disk sharing between domains and with this set to zero it will only 4.10 +# allow read only sharing. 4.11 +vbd_expert = 0 4.12 + 4.13 # STEP 6. Build the command line for the new domain. Edit as req'd. 4.14 # You only need the ip= line if you're NFS booting or the root file system 4.15 # doesn't set it later e.g. in ifcfg-eth0 or via DHCP 4.16 @@ -96,7 +102,7 @@ def make_domain(): 4.17 4.18 # set up access to the global variables declared above 4.19 global image, memory_megabytes, domain_name, ipaddr, netmask 4.20 - global vbds, cmdline, xc 4.21 + global vbds, cmdline, xc, vbd_expert 4.22 4.23 if not os.path.isfile( image ): 4.24 print "Image file '" + image + "' does not exist" 4.25 @@ -116,6 +122,10 @@ def make_domain(): 4.26 sys.exit() 4.27 4.28 # setup the virtual block devices 4.29 + 4.30 + # set the expertise level appropriately 4.31 + XenoUtil.VBD_EXPERT_MODE = vbd_expert 4.32 + 4.33 for ( uname, virt_name, rw ) in vbds: 4.34 virt_dev = XenoUtil.blkdev_name_to_number( virt_name ) 4.35 4.36 @@ -125,20 +135,23 @@ def make_domain(): 4.37 xc.domain_destroy ( dom=id ) 4.38 sys.exit() 4.39 4.40 + # check that setting up this VBD won't violate the sharing 4.41 + # allowed by the current VBD expertise level 4.42 + if XenoUtil.vd_extents_validate(segments, rw=='w') < 0: 4.43 + xc.domain_destroy( dom = id ) 4.44 + sys.exit() 4.45 + 4.46 if xc.vbd_create( dom=id, vbd=virt_dev, writeable= rw=='w' ): 4.47 print "Error creating VBD vbd=%d writeable=%d\n" % (virt_dev,rw) 4.48 xc.domain_destroy ( dom=id ) 4.49 sys.exit() 4.50 4.51 - for (s_dev,s_start,s_len,s_type) in segments: 4.52 - if xc.vbd_grow( dom=id, 4.53 - vbd=virt_dev, 4.54 - device=s_dev, 4.55 - start_sector=s_start, 4.56 - nr_sectors=s_len ): 4.57 - print "Error populating VBD vbd=%d\n" % virt_dev 4.58 - xc.domain_destroy ( dom=id ) 4.59 - sys.exit() 4.60 + if xc.vbd_setextents( dom=id, 4.61 + vbd=virt_dev, 4.62 + extents=segments): 4.63 + print "Error populating VBD vbd=%d\n" % virt_dev 4.64 + xc.domain_destroy ( dom=id ) 4.65 + sys.exit() 4.66 4.67 # setup virtual firewall rules for all aliases 4.68 for ip in ipaddr:
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/tools/examples/list_vbds.py Fri Jan 16 19:29:56 2004 +0000 5.3 @@ -0,0 +1,8 @@ 5.4 +#!/usr/bin/env python 5.5 + 5.6 + 5.7 +import Xc, sys 5.8 + 5.9 +xc = Xc.new() 5.10 + 5.11 +print xc.vbd_probe()
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/tools/examples/remove_vbd_from_dom.py Fri Jan 16 19:29:56 2004 +0000 6.3 @@ -0,0 +1,29 @@ 6.4 +#!/usr/bin/env python 6.5 + 6.6 +# Used to map a VBD into a domain's device space. Useful for populating a new 6.7 +# VBD with data from DOM0 before starting a new domain using it, for instance. 6.8 + 6.9 +# Usage: add_vdisk_to_dom.py uname target-dev-name target-dom-number 6.10 +# uname - the uname of the device, e.g. vd:2341 or phy:hda3 6.11 +# target-dev-name - the device node to map the VBD to 6.12 +# target-dom-number - domain to add the new VBD to 6.13 + 6.14 +import Xc, XenoUtil, sys 6.15 + 6.16 +xc = Xc.new() 6.17 + 6.18 +if len(sys.argv) != 3: 6.19 + print >>sys.stderr,"""Usage: add_vdisk_to_dom.py target-dev target-dom 6.20 + target-dev - the device node the VBD is mapped to 6.21 + target-dom - domain to remove the VBD from""" 6.22 + sys.exit(1) 6.23 + 6.24 +virt_dev = XenoUtil.blkdev_name_to_number(sys.argv[1]) 6.25 + 6.26 +target_dom = int(sys.argv[2]) 6.27 + 6.28 +if not xc.vbd_destroy(target_dom,virt_dev): 6.29 + print "Removed " + sys.argv[1] + " from domain " + sys.argv[2] 6.30 +else: 6.31 + print "Failed" 6.32 + sys.exit(1)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tools/examples/vd_create.py Fri Jan 16 19:29:56 2004 +0000 7.3 @@ -0,0 +1,36 @@ 7.4 +#!/usr/bin/env python 7.5 + 7.6 +# 7.7 +# Wrapper script for creating a virtual disk. 7.8 +# 7.9 +# Usage: vd_create.py size [expiry] 7.10 +# 7.11 + 7.12 +import XenoUtil, sys 7.13 + 7.14 +if len(sys.argv) > 1: 7.15 + size = int(sys.argv[1]) 7.16 +else: 7.17 + print "Usage: " + sys.argv[0] + """ size [expiry] 7.18 + Allocates a Virtual Disk out of the free space pool. An expiry time 7.19 + can be specified in seconds from now (0 means never expire) - the default 7.20 + is for disks to never expire.""" 7.21 + sys.exit(1) 7.22 + 7.23 +if len(sys.argv) > 2: 7.24 + expiry_time = int(sys.argv[2]) 7.25 +else: 7.26 + print "No expiry time specified - using default\n" 7.27 + expiry_time = 0 7.28 + 7.29 +print "Creating a virtual disk" 7.30 +print "Size: %d" % size 7.31 +print "Expiry time (seconds from now): %d" % expiry_time 7.32 + 7.33 +ret = XenoUtil.vd_create(size, expiry_time) 7.34 + 7.35 +if ret < 0: 7.36 + print >> sys.stderr, "An error occurred creating the the disk" 7.37 + sys.exit(ret) 7.38 +else: 7.39 + print "Virtual disk allocated, with ID: " + ret
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/tools/examples/vd_delete.py Fri Jan 16 19:29:56 2004 +0000 8.3 @@ -0,0 +1,20 @@ 8.4 +#!/usr/bin/env python 8.5 + 8.6 +# 8.7 +# Wrapper script for deleting a virtual disk. 8.8 +# 8.9 +# Usage: vd_create.py id 8.10 +# 8.11 + 8.12 +import sys, XenoUtil 8.13 + 8.14 +if len(sys.argv) > 1: 8.15 + id = sys.argv[1] 8.16 +else: 8.17 + print "Usage: " + sys.argv[0] + """ id 8.18 + Deletes a virtual disk.""" 8.19 + sys.exit(1) 8.20 + 8.21 +print "Deleting a virtual disk with ID: " + id 8.22 + 8.23 +ret = XenoUtil.vd_delete(id)
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/tools/examples/vd_format.py Fri Jan 16 19:29:56 2004 +0000 9.3 @@ -0,0 +1,34 @@ 9.4 +#!/usr/bin/env python 9.5 + 9.6 +# 9.7 +# Wrapper script for formatting a device to host Xen virtual disk extents 9.8 +# 9.9 +# Usage: vd_format.py device [extent_size] 9.10 +# 9.11 + 9.12 +import sys, XenoUtil 9.13 + 9.14 +if len(sys.argv) > 1: 9.15 + device = sys.argv[1] 9.16 +else: 9.17 + print "Usage: " + sys.argv[0] + """ device [extent_size] 9.18 + Formats a device to host Xen virtual disk extents. The extent size can 9.19 + optionally be specified in megabytes (default 64MB).""" 9.20 + sys.exit(1) 9.21 + 9.22 +if len(sys.argv) > 2: 9.23 + extent_size = int(sys.argv[2]) 9.24 +else: 9.25 + print """No extent size specified - using default size 9.26 + (for really small devices, the default size of 64MB might not work)""" 9.27 + extent_size = 64 9.28 + 9.29 +print "Formatting for virtual disks" 9.30 +print "Device: " + sys.argv[1] 9.31 +print "Extent size: " + str(extent_size) + "MB" 9.32 + 9.33 +ret = XenoUtil.vd_format(device, extent_size) 9.34 + 9.35 +if ret: 9.36 + print >> sys.stderr, "An error occurred formatting the device" 9.37 + sys.exit(ret)
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/tools/examples/vd_refresh.py Fri Jan 16 19:29:56 2004 +0000 10.3 @@ -0,0 +1,31 @@ 10.4 +#!/usr/bin/env python 10.5 + 10.6 +# 10.7 +# Wrapper script for creating a virtual disk. 10.8 +# 10.9 +# Usage: vd_refresh.py id [new-expiry] 10.10 +# 10.11 + 10.12 +import sys, XenoUtil 10.13 + 10.14 +if len(sys.argv) > 1: 10.15 + id = sys.argv[1] 10.16 +else: 10.17 + print "Usage: " + sys.argv[0] + """ ID [expiry-new] 10.18 + Refreshes a Virtual Disk expiry time. An expiry time 10.19 + can be specified in seconds from now (0 means never expire) - the default 10.20 + is for disks to never expire.""" 10.21 + sys.exit(1) 10.22 + 10.23 +if len(sys.argv) > 2: 10.24 + expiry_time = int(sys.argv[2]) 10.25 +else: 10.26 + print "No expiry time specified - using default\n" 10.27 + expiry_time = 0 10.28 + 10.29 +print "Refreshing a virtual disk" 10.30 +print "Id: " + sys.argv[1] 10.31 +print "Expiry time (seconds from now): " + sys.argv[2] 10.32 + 10.33 +ret = XenoUtil.vd_refresh(id, expiry_time) 10.34 +
11.1 --- a/tools/xc/py/XenoUtil.py Fri Jan 16 17:32:17 2004 +0000 11.2 +++ b/tools/xc/py/XenoUtil.py Fri Jan 16 19:29:56 2004 +0000 11.3 @@ -1,67 +1,22 @@ 11.4 - 11.5 -import string, re, os 11.6 +import string, re, os, sqlite, Xc, sys 11.7 11.8 -def blkdev_name_to_number(name): 11.9 - """Take the given textual block-device name (e.g., '/dev/sda1', 11.10 - 'hda') and return the device number used by the OS. """ 11.11 - 11.12 - if not re.match( '/dev/', name ): 11.13 - name = '/dev/' + name 11.14 - 11.15 - return os.stat(name).st_rdev 11.16 - 11.17 +##### Module variables 11.18 11.19 -# lookup_blkdev_partn_info( '/dev/sda3' ) 11.20 -def lookup_raw_partn(partition): 11.21 - """Take the given block-device name (e.g., '/dev/sda1', 'hda') 11.22 - and return a information tuple ( partn-dev, disc-dev, start-sect, 11.23 - nr-sects, type ) 11.24 - partn-dev: Device number of the given partition 11.25 - disc-dev: Device number of the disc containing the partition 11.26 - start-sect: Index of first sector of the partition 11.27 - nr-sects: Number of sectors comprising this partition 11.28 - type: 'Disk' or identifying name for partition type 11.29 - """ 11.30 - 11.31 - if not re.match( '/dev/', partition ): 11.32 - partition = '/dev/' + partition 11.33 - 11.34 - drive = re.split( '[0-9]', partition )[0] 11.35 +"""Location of the Virtual Disk management database. 11.36 + defaults to /var/spool/xen_vdisks.sqlite 11.37 +""" 11.38 +VD_DB_FILE = "/var/spool/xen_vdisks.sqlite" 11.39 11.40 - if drive == partition: 11.41 - fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' ) 11.42 - line = fd.readline() 11.43 - if line: 11.44 - return [( blkdev_name_to_number(drive), 11.45 - 0, 11.46 - string.atol(line) * 2, 11.47 - 'Disk' )] 11.48 - return None 11.49 - 11.50 - # determine position on disk 11.51 - fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' ) 11.52 +"""VBD expertise level - determines the strictness of the sanity checking. 11.53 + This mode determines the level of complaints when disk sharing occurs 11.54 + through the current VBD mappings. 11.55 + 0 - only allow shared mappings if both domains have r/o access (always OK) 11.56 + 1 - also allow sharing with one dom r/w and the other r/o 11.57 + 2 - allow sharing with both doms r/w 11.58 +""" 11.59 +VBD_EXPERT_MODE = 0 11.60 11.61 - #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012'] 11.62 - lines = fd.readlines() 11.63 - for line in lines: 11.64 - m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' + 11.65 - 'size=\s*([0-9]+), Id=\s*(\S+).*$', line) 11.66 - if m: 11.67 - return [( blkdev_name_to_number(drive), 11.68 - string.atol(m.group(1)), 11.69 - string.atol(m.group(2)), 11.70 - m.group(3) )] 11.71 - return None 11.72 - 11.73 -def lookup_disk_uname( uname ): 11.74 - ( type, d_name ) = string.split( uname, ':' ) 11.75 - 11.76 - if type == "phy": 11.77 - segments = lookup_raw_partn( d_name ) 11.78 - elif type == "vd": 11.79 - segments = lookup_vd( d_name ) 11.80 - 11.81 - return segments 11.82 +##### Networking-related functions 11.83 11.84 def get_current_ipaddr(dev='eth0'): 11.85 """Return a string containing the primary IP address for the given 11.86 @@ -134,3 +89,463 @@ def add_offset_to_ip( ip, off ): 11.87 return '%d.%d.%d.%d' % ( ((a>>24)&0xff), ((a>>16)&0xff), 11.88 ((a>>8)&0xff), (a&0xff) ) 11.89 11.90 +##### VBD-related Functions 11.91 + 11.92 +def blkdev_name_to_number(name): 11.93 + """Take the given textual block-device name (e.g., '/dev/sda1', 11.94 + 'hda') and return the device number used by the OS. """ 11.95 + 11.96 + if not re.match( '/dev/', name ): 11.97 + name = '/dev/' + name 11.98 + 11.99 + return os.stat(name).st_rdev 11.100 + 11.101 +# lookup_blkdev_partn_info( '/dev/sda3' ) 11.102 +def lookup_raw_partn(partition): 11.103 + """Take the given block-device name (e.g., '/dev/sda1', 'hda') 11.104 + and return a dictionary { partn-dev, start-sect, 11.105 + nr-sects, type } 11.106 + device: Device number of the given partition 11.107 + start_sector: Index of first sector of the partition 11.108 + nr_sectsors: Number of sectors comprising this partition 11.109 + type: 'Disk' or identifying name for partition type 11.110 + """ 11.111 + 11.112 + if not re.match( '/dev/', partition ): 11.113 + partition = '/dev/' + partition 11.114 + 11.115 + drive = re.split( '[0-9]', partition )[0] 11.116 + 11.117 + if drive == partition: 11.118 + fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' ) 11.119 + line = fd.readline() 11.120 + if line: 11.121 + return [ { 'device' : blkdev_name_to_number(drive), 11.122 + 'start_sector' : 0, 11.123 + 'nr_sectors' : string.atol(line) * 2, 11.124 + 'type' : 'Disk' } ] 11.125 + return None 11.126 + 11.127 + # determine position on disk 11.128 + fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' ) 11.129 + 11.130 + #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012'] 11.131 + lines = fd.readlines() 11.132 + for line in lines: 11.133 + m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' + 11.134 + 'size=\s*([0-9]+), Id=\s*(\S+).*$', line) 11.135 + if m: 11.136 + return [ { 'device' : blkdev_name_to_number(drive), 11.137 + 'start_sector' : string.atol(m.group(1)), 11.138 + 'nr_sectors' : string.atol(m.group(2)), 11.139 + 'type' : m.group(3) } ] 11.140 + 11.141 + return None 11.142 + 11.143 +def lookup_disk_uname( uname ): 11.144 + """Lookup a list of segments for either a physical or a virtual device. 11.145 + uname [string]: name of the device in the format \'vd:id\' for a virtual 11.146 + disk, or \'phy:dev\' for a physical device 11.147 + returns [list of dicts]: list of extents that make up the named device 11.148 + """ 11.149 + ( type, d_name ) = string.split( uname, ':' ) 11.150 + 11.151 + if type == "phy": 11.152 + segments = lookup_raw_partn( d_name ) 11.153 + elif type == "vd": 11.154 + segments = vd_lookup( d_name ) 11.155 + 11.156 + return segments 11.157 + 11.158 + 11.159 + 11.160 +##### VD Management-related functions 11.161 + 11.162 + 11.163 + 11.164 +def __vd_no_database(): 11.165 + """Called when no database found - exits with an error 11.166 + """ 11.167 + print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE 11.168 + sys.exit(1) 11.169 + 11.170 +def vd_format(partition, extent_size_mb): 11.171 + """Format a partition or drive for use a virtual disk storage. 11.172 + partition [string]: device file representing the partition 11.173 + extent_size_mb [string]: extent size in megabytes to use on this disk 11.174 + """ 11.175 + 11.176 + if not os.path.isfile(VD_DB_FILE): 11.177 + vd_init_db(VD_DB_FILE) 11.178 + 11.179 + if not re.match( '/dev/', partition ): 11.180 + partition = '/dev/' + partition 11.181 + 11.182 + cx = sqlite.connect(VD_DB_FILE) 11.183 + cu = cx.cursor() 11.184 + 11.185 + cu.execute("select * from vdisk_part where partition = \'" 11.186 + + partition + "\'") 11.187 + row = cu.fetchone() 11.188 + 11.189 + extent_size = extent_size_mb * 2048 # convert megabytes to sectors 11.190 + 11.191 + if not row: 11.192 + part_info = lookup_raw_partn(partition)[0] 11.193 + 11.194 + cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " + 11.195 + "VALUES ( \'" + partition + "\', " + str(part_info['device']) 11.196 + + ", " + str(extent_size) + ")") 11.197 + 11.198 + 11.199 + cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents " 11.200 + + "WHERE vdisk_id = 0") 11.201 + 11.202 + max_id, = cu.fetchone() 11.203 + 11.204 + if max_id != None: 11.205 + new_id = max_id + 1 11.206 + else: 11.207 + new_id = 0 11.208 + 11.209 + for i in range(part_info['nr_sectors'] / extent_size): 11.210 + sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id, 11.211 + part_id, part_extent_no) 11.212 + VALUES ("""+ str(new_id + i) + ", 0, "\ 11.213 + + str(part_info['device']) + ", " + str(i) + ")" 11.214 + cu.execute(sql) 11.215 + 11.216 + cx.commit() 11.217 + cx.close() 11.218 + return 0 11.219 + 11.220 +def vd_create(size_mb, expiry): 11.221 + """Create a new virtual disk. 11.222 + size_mb [int]: size in megabytes for the new virtual disk 11.223 + expiry [int]: expiry time in seconds from now 11.224 + """ 11.225 + 11.226 + if not os.path.isfile(VD_DB_FILE): 11.227 + __vd_no_database() 11.228 + 11.229 + cx = sqlite.connect(VD_DB_FILE) 11.230 + cu = cx.cursor() 11.231 + 11.232 + size = size_mb * 2048 11.233 + 11.234 + cu.execute("SELECT max(vdisk_id) FROM vdisks") 11.235 + max_id, = cu.fetchone() 11.236 + new_id = int(max_id) + 1 11.237 + 11.238 + # fetch a list of extents from the expired disks, along with information 11.239 + # about their size 11.240 + cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no, 11.241 + vdisk_extents.part_id, extent_size 11.242 + FROM vdisk_extents NATURAL JOIN vdisks 11.243 + NATURAL JOIN vdisk_part 11.244 + WHERE expires AND expiry_time < datetime('now') 11.245 + ORDER BY expiry_time asc, vdisk_extent_no desc 11.246 + """) # aims to reuse the last extents 11.247 + # from the longest-expired disks first 11.248 + 11.249 + allocated = 0 11.250 + 11.251 + if expiry: 11.252 + expiry_ts = "datetime('now', '" + str(expiry) + " seconds')" 11.253 + expires = 1; 11.254 + else: 11.255 + expiry_ts = "NULL" 11.256 + expires = 0; 11.257 + 11.258 + # we'll use this to build the SQL statement we want 11.259 + building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \ 11.260 + +" VALUES ("+str(new_id)+", "+str(size)+ ", " \ 11.261 + + str(expires) + ", " + expiry_ts + "); " 11.262 + 11.263 + counter = 0 11.264 + 11.265 + while allocated < size: 11.266 + row = cu.fetchone() 11.267 + if not row: 11.268 + cx.close() 11.269 + return -1 11.270 + 11.271 + (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row 11.272 + allocated += extent_size 11.273 + building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \ 11.274 + + ", " + "vdisk_extent_no = " + str(counter) \ 11.275 + + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \ 11.276 + + " AND vdisk_id = " + str(vdisk_id) + "; " 11.277 + 11.278 + counter += 1 11.279 + 11.280 + 11.281 + # this will execute the SQL query we build to store details of the new 11.282 + # virtual disk and allocate space to it print building_sql 11.283 + cu.execute(building_sql) 11.284 + 11.285 + cx.commit() 11.286 + cx.close() 11.287 + return str(new_id) 11.288 + 11.289 + 11.290 +# Future work: Disk sizes aren't modified when vd_create scavenges extents from 11.291 +# expired disks. As a result it is possible to check if a disk is expired but 11.292 +# intact (assuming VD IDs are not reused) - could allow recovery when people 11.293 +# mess up. 11.294 + 11.295 +def vd_lookup(id): 11.296 + """Lookup a Virtual Disk by ID. 11.297 + id [string]: a virtual disk identifier 11.298 + Returns [list of dicts]: a list of extents as dicts, contain fields: 11.299 + device : Linux device number 11.300 + start_sector : within the device 11.301 + nr_sectors : size of this extent 11.302 + type : set to \'VD Extent\' 11.303 + """ 11.304 + 11.305 + if not os.path.isfile(VD_DB_FILE): 11.306 + __vd_no_database() 11.307 + 11.308 + cx = sqlite.connect(VD_DB_FILE) 11.309 + cu = cx.cursor() 11.310 + 11.311 + 11.312 + # This query tells PySQLite how to convert the data returned from the 11.313 + # following query - the use of the multiplication confuses it otherwise ;-) 11.314 + # This row is significant to PySQLite but is syntactically an SQL comment. 11.315 + 11.316 + cu.execute("-- types int, int, int") 11.317 + 11.318 + # This SQL statement is designed so that when the results are fetched they 11.319 + # will be in the right format to return immediately. 11.320 + cu.execute("""SELECT vdisk_extents.part_id, 11.321 + round(part_extent_no * extent_size) as start, 11.322 + extent_size 11.323 + 11.324 + FROM vdisk_extents NATURAL JOIN vdisks 11.325 + NATURAL JOIN vdisk_part 11.326 + 11.327 + WHERE (expiry_time > datetime('now') OR not expires) 11.328 + AND vdisk_extents.vdisk_id = """ + id 11.329 + ) 11.330 + 11.331 + ret = cu.fetchall() 11.332 + 11.333 + # use this function to map the results from the database into a dict 11.334 + # list of extents, for consistency with the rest of the code 11.335 + def transform ((device, start_sector, nr_sectors)): 11.336 + return {'device' : device, 'start_sector' : int(start_sector), 11.337 + 'nr_sectors' : nr_sectors, 'type' : 'VD Extent' } 11.338 + 11.339 + cx.commit() 11.340 + cx.close() 11.341 + 11.342 + return map(transform, ret) # transforms the tuples into dicts to return 11.343 + 11.344 + 11.345 +def vd_refresh(id, expiry): 11.346 + """Change the expiry time of a virtual disk. 11.347 + id [string]: a virtual disk identifier 11.348 + expiry [int]: expiry time in seconds from now (0 = never expire) 11.349 + """ 11.350 + 11.351 + if not os.path.isfile(VD_DB_FILE): 11.352 + __vd_no_database() 11.353 + 11.354 + cx = sqlite.connect(VD_DB_FILE) 11.355 + cu = cx.cursor() 11.356 + 11.357 + if expiry: 11.358 + expires = 1 11.359 + expiry_ts = "datetime('now', '" + str(expiry) + " seconds')" 11.360 + else: 11.361 + expires = 0 11.362 + expiry_ts = "NULL" 11.363 + 11.364 + cu.execute("UPDATE vdisks SET expires = " + str(expires) 11.365 + + ", expiry_time = " + expiry_ts 11.366 + + " WHERE vdisk_id = " + id) 11.367 + 11.368 + cx.commit() 11.369 + cx.close() 11.370 + 11.371 + return 11.372 + 11.373 +def vd_delete(id): 11.374 + """Deletes a Virtual Disk, making its extents available for future 11.375 + virtual disks. 11.376 + [id] identifier for the virtual disk to delete 11.377 + """ 11.378 + 11.379 + if not os.path.isfile(VD_DB_FILE): 11.380 + __vd_no_database() 11.381 + 11.382 + cx = sqlite.connect(VD_DB_FILE) 11.383 + cu = cx.cursor() 11.384 + 11.385 + cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')" 11.386 + + " WHERE vdisk_id = " + id) 11.387 + 11.388 + cx.commit() 11.389 + cx.close() 11.390 + 11.391 + return 11.392 + 11.393 +def vd_init_db(path): 11.394 + """Initialise the VD SQLite database 11.395 + path [string]: path to the SQLite database file 11.396 + """ 11.397 + 11.398 + cx = sqlite.connect(path) 11.399 + cu = cx.cursor() 11.400 + 11.401 + cu.execute( 11.402 + """CREATE TABLE vdisk_extents 11.403 + ( vdisk_extent_no INT, 11.404 + vdisk_id INT, 11.405 + part_id INT, 11.406 + part_extent_no INT ) 11.407 + """) 11.408 + 11.409 + cu.execute( 11.410 + """CREATE TABLE vdisk_part 11.411 + ( part_id INT, 11.412 + partition VARCHAR, 11.413 + extent_size INT ) 11.414 + """) 11.415 + 11.416 + cu.execute( 11.417 + """CREATE TABLE vdisks 11.418 + ( vdisk_id INT, 11.419 + size INT, 11.420 + expires BOOLEAN, 11.421 + expiry_time TIMESTAMP ) 11.422 + """) 11.423 + 11.424 + 11.425 + cu.execute( 11.426 + """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time ) 11.427 + VALUES ( 0, 0, 1, datetime('now') ) 11.428 + """) 11.429 + 11.430 + cx.commit() 11.431 + cx.close() 11.432 + 11.433 + VD_DB_FILE = path 11.434 + 11.435 + 11.436 + 11.437 +def vd_extents_validate(new_extents,new_writeable): 11.438 + """Validate the extents against the existing extents. 11.439 + Complains if the list supplied clashes against the extents that 11.440 + are already in use in the system. 11.441 + new_extents [list of dicts]: list of new extents, as dicts 11.442 + new_writeable [int]: 1 if they are to be writeable, 0 otherwise 11.443 + returns [int]: either the expertise level of the mapping if it doesn't 11.444 + exceed VBD_EXPERT_MODE or -1 if it does (error) 11.445 + """ 11.446 + 11.447 + xc = Xc.new() 11.448 + 11.449 + ##### Probe for explicitly created virtual disks and build a list 11.450 + ##### of extents for comparison with the ones that are being added 11.451 + 11.452 + probe = xc.vbd_probe() 11.453 + 11.454 + old_extents = [] # this will hold a list of all existing extents and 11.455 + # their writeable status, as a list of (device, 11.456 + # start, size, writeable?) tuples 11.457 + 11.458 + for vbd in probe: 11.459 + this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd']) 11.460 + for vbd_ext in this_vbd_extents: 11.461 + vbd_ext['writeable'] = vbd['writeable'] 11.462 + old_extents.append(vbd_ext); 11.463 + 11.464 + ##### Now scan /proc/mounts for compile a list of extents corresponding to 11.465 + ##### any devices mounted in DOM0. This list is added on to old_extents 11.466 + 11.467 + regexp = re.compile("/dev/(\S*) \S* \S* (..).*"); 11.468 + fd = open('/proc/mounts', "r") 11.469 + 11.470 + while True: 11.471 + line = fd.readline() 11.472 + if not line: # if we've run out of lines then stop reading 11.473 + break 11.474 + 11.475 + m = regexp.match(line) 11.476 + 11.477 + # if the regexp didn't match then it's probably a line we don't 11.478 + # care about - skip to next line 11.479 + if not m: 11.480 + continue 11.481 + 11.482 + # lookup the device 11.483 + ext_list = lookup_raw_partn(m.group(1)) 11.484 + 11.485 + # if lookup failed, skip to next mounted device 11.486 + if not ext_list: 11.487 + continue 11.488 + 11.489 + # set a writeable flag as appropriate 11.490 + for ext in ext_list: 11.491 + ext['writeable'] = m.group(2) == 'rw' 11.492 + 11.493 + # now we've got here, the contents of ext_list are in a 11.494 + # suitable format to be added onto the old_extents list, ready 11.495 + # for checking against the new extents 11.496 + 11.497 + old_extents.extend(ext_list) 11.498 + 11.499 + fd.close() # close /proc/mounts 11.500 + 11.501 + ##### By this point, old_extents contains a list of extents, in 11.502 + ##### dictionary format corresponding to every extent of physical 11.503 + ##### disk that's either part of an explicitly created VBD, or is 11.504 + ##### mounted under DOM0. We now check these extents against the 11.505 + ##### proposed additions in new_extents, to see if a conflict will 11.506 + ##### happen if they are added with write status new_writeable 11.507 + 11.508 + level = 0 # this'll accumulate the max warning level 11.509 + 11.510 + # Search for clashes between the new extents and the old ones 11.511 + # Takes time O(len(new_extents) * len(old_extents)) 11.512 + for new_ext in new_extents: 11.513 + for old_ext in old_extents: 11.514 + if(new_ext['device'] == old_ext['device']): 11.515 + 11.516 + new_ext_start = new_ext['start_sector'] 11.517 + new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1 11.518 + 11.519 + old_ext_start = old_ext['start_sector'] 11.520 + old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1 11.521 + 11.522 + if((old_ext_start <= new_ext_start <= old_ext_end) or 11.523 + (old_ext_start <= new_ext_end <= old_ext_end)): 11.524 + if (not old_ext['writeable']) and new_writeable: 11.525 + level = max(1,level) 11.526 + elif old_ext['writeable'] and (not new_writeable): 11.527 + level = max(1,level) 11.528 + elif old_ext['writeable'] and new_writeable: 11.529 + level = max(2,level) 11.530 + 11.531 + 11.532 + ##### level now holds the warning level incurred by the current 11.533 + ##### VBD setup and we complain appropriately to the user 11.534 + 11.535 + 11.536 + if level == 1: 11.537 + print >> sys.stderr, """Warning: one or more hard disk extents 11.538 + writeable by one domain are also readable by another.""" 11.539 + elif level == 2: 11.540 + print >> sys.stderr, """Warning: one or more hard disk extents are 11.541 + writeable by two or more domains simultaneously.""" 11.542 + 11.543 + if level > VBD_EXPERT_MODE: 11.544 + print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed 11.545 + at the current safety level (%d).""" % VBD_EXPERT_MODE 11.546 + level = -1 11.547 + 11.548 + return level 11.549 +