diff options
author | mjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com> | 2004-06-16 13:30:35 +0000 |
---|---|---|
committer | mjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com> | 2004-06-16 13:30:35 +0000 |
commit | 7b06304aceb9f2ca5f04e28e91fe5f7419f63a18 (patch) | |
tree | 4e72497bb3a350d5c490e049d284ae4f0ea1663b /tools/xenctl | |
parent | eb5277a30e0834fcfecac290917a67c17eabb757 (diff) | |
download | xen-7b06304aceb9f2ca5f04e28e91fe5f7419f63a18.tar.gz xen-7b06304aceb9f2ca5f04e28e91fe5f7419f63a18.tar.bz2 xen-7b06304aceb9f2ca5f04e28e91fe5f7419f63a18.zip |
bitkeeper revision 1.959.1.5 (40d04b7b7MkMcLlaSNJov9qsPAZ9tg)
Remove vdisk code.
Diffstat (limited to 'tools/xenctl')
-rw-r--r-- | tools/xenctl/lib/vdisk.py | 944 | ||||
-rw-r--r-- | tools/xenctl/setup.py | 2 |
2 files changed, 1 insertions, 945 deletions
diff --git a/tools/xenctl/lib/vdisk.py b/tools/xenctl/lib/vdisk.py deleted file mode 100644 index 6c4d144f9f..0000000000 --- a/tools/xenctl/lib/vdisk.py +++ /dev/null @@ -1,944 +0,0 @@ -import os -import re -import socket -import string -import sys -import tempfile -import struct - -##### Module variables - -"""Location of the Virtual Disk management database. - defaults to /var/db/xen_vdisks.sqlite -""" -VD_DB_FILE = "/var/db/xen_vdisks.sqlite" - -"""VBD expertise level - determines the strictness of the sanity checking. - This mode determines the level of complaints when disk sharing occurs - through the current VBD mappings. - 0 - only allow shared mappings if both domains have r/o access (always OK) - 1 - also allow sharing with one dom r/w and the other r/o - 2 - allow sharing with both doms r/w -""" -VBD_SAFETY_RR = 0 -VBD_SAFETY_RW = 1 -VBD_SAFETY_WW = 2 - -VBD_SECTORS_PER_MB = 2048 - -##### Module initialisation - -try: - # try to import sqlite (not everyone will have it installed) - import sqlite -except ImportError: - # on failure, just catch the error, don't do anything - pass - - - -##### VBD-related Functions - -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 ): - name = '/dev/' + name - - return os.stat(name).st_rdev - -# lookup_blkdev_partn_info( '/dev/sda3' ) -def lookup_raw_partn(partition): - """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 - """ - - if not re.match( '/dev/', partition ): - partition = '/dev/' + partition - - drive = re.split( '[0-9]', partition )[0] - - if drive == partition: - fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' ) - line = readline(fd) - if line: - return [ { 'device' : blkdev_name_to_number(drive), - 'start_sector' : long(0), - 'nr_sectors' : long(line) * 2, - 'type' : 'Disk' } ] - return None - - # determine position on disk - fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' ) - - #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012'] - lines = readlines(fd) - for line in lines: - m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' + - 'size=\s*([0-9]+), Id=\s*(\S+).*$', line) - if m: - return [ { 'device' : blkdev_name_to_number(drive), - 'start_sector' : long(m.group(1)), - 'nr_sectors' : long(m.group(2)), - 'type' : m.group(3) } ] - - return None - -def lookup_disk_uname( uname ): - """Lookup a list of segments for either a physical or a virtual device. - uname [string]: name of the device in the format \'vd:id\' for a virtual - disk, or \'phy:dev\' for a physical device - returns [list of dicts]: list of extents that make up the named device - """ - ( type, d_name ) = string.split( uname, ':' ) - - if type == "phy": - segments = lookup_raw_partn( d_name ) - elif type == "vd": - segments = vd_lookup( d_name ) - - return segments - - -##### VD Management-related functions - -##### By Mark Williamson, <mark.a.williamson@intel.com> -##### (C) Intel Research Cambridge - -# TODO: -# -# Plenty of room for enhancement to this functionality (contributions -# welcome - and then you get to have your name in the source ;-)... -# -# vd_unformat() : want facilities to unallocate virtual disk -# partitions, possibly migrating virtual disks of them, with checks to see if -# it's safe and options to force it anyway -# -# vd_create() : should have an optional argument specifying a physical -# disk preference - useful to allocate for guest doms to do RAID -# -# vd_undelete() : add ability to "best effort" undelete as much of a -# vdisk as is left in the case that some of it has already been -# reallocated. Some people might still be able to recover some of -# their data this way, even if some of the disk has disappeared. -# -# It'd be nice if we could wipe virtual disks for security purposes - -# should be easy to do this using dev if=/dev/{zero,random} on each -# extent in turn. There could be another optional flag to vd_create -# in order to allow this. -# -# Error codes could be more expressive - i.e. actually tell why the -# error occurred rather than "it broke". Currently the code avoids -# using exceptions to make control scripting simpler and more -# accessible to beginners - therefore probably should just use more -# return codes. -# -# Enhancements / additions to the example scripts are also welcome: -# some people will interact with this code mostly through those -# scripts. -# -# More documentation of how this stuff should be used is always nice - -# if you have a novel configuration that you feel isn't discussed -# enough in the HOWTO (which is currently a work in progress), feel -# free to contribute a walkthrough, or something more substantial. -# - - -def __vd_no_database(): - """Called when no database found - exits with an error - """ - print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE - sys.exit(1) - -def readlines(fd): - """Version of readlines safe against EINTR. - """ - import errno - - lines = [] - while 1: - try: - line = fd.readline() - except IOError, ex: - if ex.errno == errno.EINTR: - continue - else: - raise - if line == '': break - lines.append(line) - return lines - -def readline(fd): - """Version of readline safe against EINTR. - """ - while 1: - try: - return fd.readline() - except IOError, ex: - if ex.errno == errno.EINTR: - continue - else: - raise - - -def vd_format(partition, extent_size_mb): - """Format a partition or drive for use a virtual disk storage. - partition [string]: device file representing the partition - extent_size_mb [string]: extent size in megabytes to use on this disk - """ - - if not os.path.isfile(VD_DB_FILE): - vd_init_db(VD_DB_FILE) - - if not re.match( '/dev/', partition ): - partition = '/dev/' + partition - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("select * from vdisk_part where partition = \'" - + partition + "\'") - row = cu.fetchone() - - extent_size = extent_size_mb * VBD_SECTORS_PER_MB # convert megabytes to sectors - - if not row: - part_info = lookup_raw_partn(partition)[0] - - cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " + - "VALUES ( \'" + partition + "\', " - + str(blkdev_name_to_number(partition)) - + ", " + str(extent_size) + ")") - - - cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents " - + "WHERE vdisk_id = 0") - - max_id, = cu.fetchone() - - if max_id != None: - new_id = max_id + 1 - else: - new_id = 0 - - num_extents = part_info['nr_sectors'] / extent_size - - for i in range(num_extents): - sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id, - part_id, part_extent_no) - VALUES ("""+ str(new_id + i) + ", 0, "\ - + str(blkdev_name_to_number(partition))\ - + ", " + str(num_extents - (i + 1)) + ")" - cu.execute(sql) - - cx.commit() - cx.close() - return 0 - - -def vd_create(size_mb, expiry): - """Create a new virtual disk. - size_mb [int]: size in megabytes for the new virtual disk - expiry [int]: expiry time in seconds from now - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - size = size_mb * VBD_SECTORS_PER_MB - - cu.execute("SELECT max(vdisk_id) FROM vdisks") - max_id, = cu.fetchone() - new_id = int(max_id) + 1 - - # fetch a list of extents from the expired disks, along with information - # about their size - cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no, - vdisk_extents.part_id, extent_size - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - WHERE expires AND expiry_time <= datetime('now') - ORDER BY expiry_time ASC, vdisk_extent_no DESC - """) # aims to reuse the last extents - # from the longest-expired disks first - - allocated = 0 - - if expiry: - expiry_ts = "datetime('now', '" + str(expiry) + " seconds')" - expires = 1 - else: - expiry_ts = "NULL" - expires = 0 - - # we'll use this to build the SQL statement we want - building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \ - +" VALUES ("+str(new_id)+", "+str(size)+ ", " \ - + str(expires) + ", " + expiry_ts + "); " - - counter = 0 - - while allocated < size: - row = cu.fetchone() - if not row: - print "ran out of space, having allocated %d meg of %d" % (allocated, size) - cx.close() - return -1 - - - (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row - allocated += extent_size - building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \ - + ", " + "vdisk_extent_no = " + str(counter) \ - + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \ - + " AND vdisk_id = " + str(vdisk_id) + "; " - - counter += 1 - - - # this will execute the SQL query we build to store details of the new - # virtual disk and allocate space to it print building_sql - cu.execute(building_sql) - - cx.commit() - cx.close() - return str(new_id) - - -def vd_lookup(id): - """Lookup a Virtual Disk by ID. - id [string]: a virtual disk identifier - Returns [list of dicts]: a list of extents as dicts, containing fields: - device : Linux device number of host disk - start_sector : within the device - nr_sectors : size of this extent - type : set to \'VD Extent\' - - part_device : Linux device no of host partition - part_start_sector : within the partition - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("-- types int") - cu.execute("""SELECT COUNT(*) - FROM vdisks - WHERE (expiry_time > datetime('now') OR NOT expires) - AND vdisk_id = """ + id) - count, = cu.fetchone() - - if not count: - cx.close() - return None - - cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id) - real_size, = cu.fetchone() - - # This query tells PySQLite how to convert the data returned from the - # following query - the use of the multiplication confuses it otherwise ;-) - # This row is significant to PySQLite but is syntactically an SQL comment. - - cu.execute("-- types str, int, int, int") - - # This SQL statement is designed so that when the results are fetched they - # will be in the right format to return immediately. - cu.execute("""SELECT partition, vdisk_part.part_id, - round(part_extent_no * extent_size) as start, - extent_size - - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - - WHERE vdisk_extents.vdisk_id = """ + id - + " ORDER BY vdisk_extents.vdisk_extent_no ASC" - ) - - extent_tuples = cu.fetchall() - - # use this function to map the results from the database into a dict - # list of extents, for consistency with the rest of the code - def transform ((partition, part_device, part_offset, nr_sectors)): - return { - # the disk device this extent is on - for passing to Xen - 'device' : lookup_raw_partn(partition)[0]['device'], - # the offset of this extent within the disk - for passing to Xen - 'start_sector' : long(part_offset + lookup_raw_partn(partition)[0]['start_sector']), - # extent size, in sectors - 'nr_sectors' : nr_sectors, - # partition device this extent is on (useful to know for xenctl.utils fns) - 'part_device' : part_device, - # start sector within this partition (useful to know for xenctl.utils fns) - 'part_start_sector' : part_offset, - # type of this extent - handy to know - 'type' : 'VD Extent' } - - cx.commit() - cx.close() - - extent_dicts = map(transform, extent_tuples) - - # calculate the over-allocation in sectors (happens because - # we allocate whole extents) - allocated_size = 0 - for i in extent_dicts: - allocated_size += i['nr_sectors'] - - over_allocation = allocated_size - real_size - - # trim down the last extent's length so the resulting VBD will be the - # size requested, rather than being rounded up to the nearest extent - extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation - - return extent_dicts - - -def vd_enlarge(vdisk_id, extra_size_mb): - """Create a new virtual disk. - vdisk_id [string] : ID of the virtual disk to enlarge - extra_size_mb [int]: size in megabytes to increase the allocation by - returns [int] : 0 on success, otherwise non-zero - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - extra_size = extra_size_mb * VBD_SECTORS_PER_MB - - cu.execute("-- types int") - cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id - + " AND (expiry_time > datetime('now') OR NOT expires)") - count, = cu.fetchone() - - if not count: # no such vdisk - cx.close() - return -1 - - cu.execute("-- types int") - cu.execute("""SELECT SUM(extent_size) - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - WHERE vdisks.vdisk_id = """ + vdisk_id) - - real_size, = cu.fetchone() # get the true allocated size - - cu.execute("-- types int") - cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id) - - old_size, = cu.fetchone() - - - cu.execute("--- types int") - cu.execute("""SELECT MAX(vdisk_extent_no) - FROM vdisk_extents - WHERE vdisk_id = """ + vdisk_id) - - counter = cu.fetchone()[0] + 1 # this stores the extent numbers - - - # because of the extent-based allocation, the VD may already have more - # allocated space than they asked for. Find out how much we really - # need to add. - add_size = extra_size + old_size - real_size - - # fetch a list of extents from the expired disks, along with information - # about their size - cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no, - vdisk_extents.part_id, extent_size - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - WHERE expires AND expiry_time <= datetime('now') - ORDER BY expiry_time ASC, vdisk_extent_no DESC - """) # aims to reuse the last extents - # from the longest-expired disks first - - allocated = 0 - - building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\ - + " WHERE vdisk_id = " + vdisk_id + "; " - - while allocated < add_size: - row = cu.fetchone() - if not row: - cx.close() - return -1 - - (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row - allocated += extent_size - building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id \ - + ", " + "vdisk_extent_no = " + str(counter) \ - + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \ - + " AND vdisk_id = " + str(dead_vd_id) + "; " - - counter += 1 - - - # this will execute the SQL query we build to store details of the new - # virtual disk and allocate space to it print building_sql - cu.execute(building_sql) - - cx.commit() - cx.close() - return 0 - - -def vd_undelete(vdisk_id, expiry_time): - """Create a new virtual disk. - vdisk_id [int]: size in megabytes for the new virtual disk - expiry_time [int]: expiry time, in seconds from now - returns [int]: zero on success, non-zero on failure - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - if vdisk_id == '0': # undeleting vdisk 0 isn't sane! - return -1 - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("-- types int") - cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id) - count, = cu.fetchone() - - if not count: - cx.close() - return -1 - - cu.execute("-- types int") - cu.execute("""SELECT SUM(extent_size) - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - WHERE vdisks.vdisk_id = """ + vdisk_id) - - real_size, = cu.fetchone() # get the true allocated size - - - cu.execute("-- types int") - cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id) - - old_size, = cu.fetchone() - - if real_size < old_size: - cx.close() - return -1 - - if expiry_time == 0: - expires = '0' - else: - expires = '1' - - # this will execute the SQL query we build to store details of the new - # virtual disk and allocate space to it print building_sql - cu.execute("UPDATE vdisks SET expiry_time = datetime('now','" - + str(expiry_time) + " seconds'), expires = " + expires - + " WHERE vdisk_id = " + vdisk_id) - - cx.commit() - cx.close() - return 0 - - - - -def vd_list(): - """Lists all the virtual disks registered in the system. - returns [list of dicts] - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("""SELECT vdisk_id, size, expires, expiry_time - FROM vdisks - WHERE (NOT expires) OR expiry_time > datetime('now') - """) - - ret = cu.fetchall() - - cx.close() - - def makedicts((vdisk_id, size, expires, expiry_time)): - return { 'vdisk_id' : str(vdisk_id), 'size': size, - 'expires' : expires, 'expiry_time' : expiry_time } - - return map(makedicts, ret) - - -def vd_refresh(id, expiry): - """Change the expiry time of a virtual disk. - id [string] : a virtual disk identifier - expiry [int] : expiry time in seconds from now (0 = never expire) - returns [int]: zero on success, non-zero on failure - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("-- types int") - cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id - + " AND (expiry_time > datetime('now') OR NOT expires)") - count, = cu.fetchone() - - if not count: - cx.close() - return -1 - - if expiry: - expires = 1 - expiry_ts = "datetime('now', '" + str(expiry) + " seconds')" - else: - expires = 0 - expiry_ts = "NULL" - - cu.execute("UPDATE vdisks SET expires = " + str(expires) - + ", expiry_time = " + expiry_ts - + " WHERE (expiry_time > datetime('now') OR NOT expires)" - + " AND vdisk_id = " + id) - - cx.commit() - cx.close() - - return 0 - - -def vd_delete(id): - """Deletes a Virtual Disk, making its extents available for future VDs. - id [string] : identifier for the virtual disk to delete - returns [int] : 0 on success, -1 on failure (VD not found - or already deleted) - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("-- types int") - cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id - + " AND (expiry_time > datetime('now') OR NOT expires)") - count, = cu.fetchone() - - if not count: - cx.close() - return -1 - - cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')" - + " WHERE vdisk_id = " + id) - - cx.commit() - cx.close() - - return 0 - - -def vd_freespace(): - """Returns the amount of free space available for new virtual disks, in MB - returns [int] : free space for VDs in MB - """ - - if not os.path.isfile(VD_DB_FILE): - __vd_no_database() - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("-- types int") - - cu.execute("""SELECT SUM(extent_size) - FROM vdisks NATURAL JOIN vdisk_extents - NATURAL JOIN vdisk_part - WHERE expiry_time <= datetime('now') AND expires""") - - sum, = cu.fetchone() - - cx.close() - - return sum / VBD_SECTORS_PER_MB - - -def vd_init_db(path): - """Initialise the VD SQLite database - path [string]: path to the SQLite database file - """ - - cx = sqlite.connect(path) - cu = cx.cursor() - - cu.execute( - """CREATE TABLE vdisk_extents - ( vdisk_extent_no INT, - vdisk_id INT, - part_id INT, - part_extent_no INT ) - """) - - cu.execute( - """CREATE TABLE vdisk_part - ( part_id INT, - partition VARCHAR, - extent_size INT ) - """) - - cu.execute( - """CREATE TABLE vdisks - ( vdisk_id INT, - size INT, - expires BOOLEAN, - expiry_time TIMESTAMP ) - """) - - - cu.execute( - """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time ) - VALUES ( 0, 0, 1, datetime('now') ) - """) - - cx.commit() - cx.close() - - VD_DB_FILE = path - - - -def vd_cp_to_file(vdisk_id,filename): - """Writes the contents of a specified vdisk out into a disk file, leaving - the original copy in the virtual disk pool.""" - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - extents = vd_lookup(vdisk_id) - - if not extents: - return -1 - - file_idx = 0 # index into source file, in sectors - - for i in extents: - cu.execute("""SELECT partition, extent_size FROM vdisk_part - WHERE part_id = """ + str(i['part_device'])) - - (partition, extent_size) = cu.fetchone() - - os.system("dd bs=1b if=" + partition + " of=" + filename - + " skip=" + str(i['part_start_sector']) - + " seek=" + str(file_idx) - + " count=" + str(i['nr_sectors']) - + " > /dev/null") - - file_idx += i['nr_sectors'] - - cx.close() - - return 0 # should return -1 if something breaks - - -def vd_mv_to_file(vdisk_id,filename): - """Writes a vdisk out into a disk file and frees the space originally - taken within the virtual disk pool. - vdisk_id [string]: ID of the vdisk to write out - filename [string]: file to write vdisk contents out to - returns [int]: zero on success, nonzero on failure - """ - - if vd_cp_to_file(vdisk_id,filename): - return -1 - - if vd_delete(vdisk_id): - return -1 - - return 0 - - -def vd_read_from_file(filename,expiry): - """Reads the contents of a file directly into a vdisk, which is - automatically allocated to fit. - filename [string]: file to read disk contents from - returns [string] : vdisk ID for the destination vdisk - """ - - size_bytes = os.stat(filename).st_size - - (size_mb,leftover) = divmod(size_bytes,1048580) # size in megabytes - if leftover > 0: size_mb += 1 # round up if not an exact number of MB - - vdisk_id = vd_create(size_mb, expiry) - - if vdisk_id < 0: - return -1 - - cx = sqlite.connect(VD_DB_FILE) - cu = cx.cursor() - - cu.execute("""SELECT partition, extent_size, part_extent_no - FROM vdisk_part NATURAL JOIN vdisk_extents - WHERE vdisk_id = """ + vdisk_id + """ - ORDER BY vdisk_extent_no ASC""") - - extents = cu.fetchall() - - size_sectors = size_mb * VBD_SECTORS_PER_MB # for feeding to dd - - file_idx = 0 # index into source file, in sectors - - def write_extent_to_vd((partition, extent_size, part_extent_no), - file_idx, filename): - """Write an extent out to disk and update file_idx""" - - os.system("dd bs=512 if=" + filename + " of=" + partition - + " skip=" + str(file_idx) - + " seek=" + str(part_extent_no * extent_size) - + " count=" + str(min(extent_size, size_sectors - file_idx)) - + " > /dev/null") - - return extent_size - - for i in extents: - file_idx += write_extent_to_vd(i, file_idx, filename) - - cx.close() - - return vdisk_id - - - - -def vd_extents_validate(new_extents, new_writeable, safety=VBD_SAFETY_RR): - """Validate the extents against the existing extents. - Complains if the list supplied clashes against the extents that - are already in use in the system. - new_extents [list of dicts]: list of new extents, as dicts - new_writeable [int]: 1 if they are to be writeable, 0 otherwise - returns [int]: either the expertise level of the mapping if it doesn't - exceed VBD_EXPERT_MODE or -1 if it does (error) - """ - - import Xc # this is only needed in this function - - xc = Xc.new() - - ##### Probe for explicitly created virtual disks and build a list - ##### of extents for comparison with the ones that are being added - - probe = xc.vbd_probe() - - old_extents = [] # this will hold a list of all existing extents and - # their writeable status, as a list of (device, - # start, size, writeable?) tuples - - for vbd in probe: - this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd']) - for vbd_ext in this_vbd_extents: - vbd_ext['writeable'] = vbd['writeable'] - old_extents.append(vbd_ext) - - ##### Now scan /proc/mounts for compile a list of extents corresponding to - ##### any devices mounted in DOM0. This list is added on to old_extents - - regexp = re.compile("/dev/(\S*) \S* \S* (..).*") - fd = open('/proc/mounts', "r") - - while True: - line = readline(fd) - if not line: # if we've run out of lines then stop reading - break - - m = regexp.match(line) - - # if the regexp didn't match then it's probably a line we don't - # care about - skip to next line - if not m: - continue - - # lookup the device - ext_list = lookup_raw_partn(m.group(1)) - - # if lookup failed, skip to next mounted device - if not ext_list: - continue - - # set a writeable flag as appropriate - for ext in ext_list: - ext['writeable'] = m.group(2) == 'rw' - - # now we've got here, the contents of ext_list are in a - # suitable format to be added onto the old_extents list, ready - # for checking against the new extents - - old_extents.extend(ext_list) - - fd.close() # close /proc/mounts - - ##### By this point, old_extents contains a list of extents, in - ##### dictionary format corresponding to every extent of physical - ##### disk that's either part of an explicitly created VBD, or is - ##### mounted under DOM0. We now check these extents against the - ##### proposed additions in new_extents, to see if a conflict will - ##### happen if they are added with write status new_writeable - - level = 0 # this'll accumulate the max warning level - - # Search for clashes between the new extents and the old ones - # Takes time O(len(new_extents) * len(old_extents)) - for new_ext in new_extents: - for old_ext in old_extents: - if(new_ext['device'] == old_ext['device']): - - new_ext_start = new_ext['start_sector'] - new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1 - - old_ext_start = old_ext['start_sector'] - old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1 - - if((old_ext_start <= new_ext_start <= old_ext_end) or - (old_ext_start <= new_ext_end <= old_ext_end)): - if (not old_ext['writeable']) and new_writeable: - level = max(1,level) - elif old_ext['writeable'] and (not new_writeable): - level = max(1,level) - elif old_ext['writeable'] and new_writeable: - level = max(2,level) - - - ##### level now holds the warning level incurred by the current - ##### VBD setup and we complain appropriately to the user - - - if level == 1: - print >> sys.stderr, """Warning: one or more hard disk extents - writeable by one domain are also readable by another.""" - elif level == 2: - print >> sys.stderr, """Warning: one or more hard disk extents are - writeable by two or more domains simultaneously.""" - - if level > safety: - print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed - at the current safety level (%d).""" % safety - level = -1 - - return level - diff --git a/tools/xenctl/setup.py b/tools/xenctl/setup.py index 1d67a843ef..03f3f1e25c 100644 --- a/tools/xenctl/setup.py +++ b/tools/xenctl/setup.py @@ -2,7 +2,7 @@ from distutils.core import setup, Extension import sys -modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' , 'xenctl.vdisk' ] +modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' ] # We need the 'tempfile' module from Python 2.3. We install this ourselves # if the installed Python is older than 2.3. |