ia64/xen-unstable

changeset 1043:eb4a4fe67cdc

bitkeeper revision 1.682 (400c3301usqWi45kB_H-oz2aBEtHyw)

maw-vd-rc2.patch
author kaf24@scramble.cl.cam.ac.uk[kaf24]
date Mon Jan 19 19:41:53 2004 +0000 (2004-01-19)
parents 3a01e5ddf625
children b51f4782dd4d
files .rootkeys tools/examples/vd_delete.py tools/examples/vd_freespace.py tools/examples/vd_list.py tools/examples/vd_refresh.py tools/examples/vd_undelete.py tools/xc/py/XenoUtil.py
line diff
     1.1 --- a/.rootkeys	Mon Jan 19 15:29:17 2004 +0000
     1.2 +++ b/.rootkeys	Mon Jan 19 19:41:53 2004 +0000
     1.3 @@ -53,7 +53,10 @@ 3fbe2f12Bnt8mwmr1ZCP6HWGS6yvYw tools/exa
     1.4  40083bb4LeyQyL-0riaV3UYDfHkl5g tools/examples/vd_create.py
     1.5  40083bb4TmKs8pcFkOcJj1bKn3zcmg tools/examples/vd_delete.py
     1.6  40083bb4u9Od6ujgect6mrxWfkk1pQ tools/examples/vd_format.py
     1.7 +400c33000SvWkdG92u4Bvdu6BPjGPw tools/examples/vd_freespace.py
     1.8 +400c3300jb_Ufz2kWsovGKNoDPEf-A tools/examples/vd_list.py
     1.9  40083bb4NhDpKiYTrebI3ZjX__oI_w tools/examples/vd_refresh.py
    1.10 +400c33001-uDKTfHBchTKUwuMFcqTA tools/examples/vd_undelete.py
    1.11  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.12  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.13  3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
     2.1 --- a/tools/examples/vd_delete.py	Mon Jan 19 15:29:17 2004 +0000
     2.2 +++ b/tools/examples/vd_delete.py	Mon Jan 19 19:41:53 2004 +0000
     2.3 @@ -18,3 +18,6 @@ else:
     2.4  print "Deleting a virtual disk with ID: " + id
     2.5  
     2.6  ret = XenoUtil.vd_delete(id)
     2.7 +
     2.8 +if ret:
     2.9 +    print "Deletion failed: invalid ID, or disk already expired / deleted"
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/examples/vd_freespace.py	Mon Jan 19 19:41:53 2004 +0000
     3.3 @@ -0,0 +1,11 @@
     3.4 +#!/usr/bin/env python
     3.5 +
     3.6 +#
     3.7 +# vd_freespace.py
     3.8 +#
     3.9 +# Prints out the amount of free space (in megabytes) for creating virtual disks.
    3.10 +#
    3.11 +
    3.12 +import XenoUtil
    3.13 +
    3.14 +print XenoUtil.vd_freespace()
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/examples/vd_list.py	Mon Jan 19 19:41:53 2004 +0000
     4.3 @@ -0,0 +1,10 @@
     4.4 +#!/usr/bin/env python
     4.5 +
     4.6 +#
     4.7 +# vd_list.py - use this to list all the unexpired virtual disks in the
     4.8 +# virtual disk database
     4.9 +#
    4.10 +
    4.11 +import XenoUtil
    4.12 +
    4.13 +print XenoUtil.vd_list()
     5.1 --- a/tools/examples/vd_refresh.py	Mon Jan 19 15:29:17 2004 +0000
     5.2 +++ b/tools/examples/vd_refresh.py	Mon Jan 19 19:41:53 2004 +0000
     5.3 @@ -29,3 +29,5 @@ print "Expiry time (seconds from now): "
     5.4  
     5.5  ret = XenoUtil.vd_refresh(id, expiry_time)
     5.6  
     5.7 +if ret:
     5.8 +    print "Refresh failed, non-existent virtual disk or disk is expired / deleted"
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/examples/vd_undelete.py	Mon Jan 19 19:41:53 2004 +0000
     6.3 @@ -0,0 +1,32 @@
     6.4 +#!/usr/bin/env python
     6.5 +
     6.6 +#
     6.7 +# vd_undelete.py vdisk_id [ new_expiry ]
     6.8 +#
     6.9 +# Undeletes a VD and, optionally, sets a new expiry time or disables
    6.10 +# expiry if the time value is zero (default)
    6.11 +#
    6.12 +
    6.13 +import XenoUtil, sys
    6.14 +
    6.15 +if len(sys.argv) < 2:
    6.16 +    print >>sys.stderr, "Usage: " + sys.argv[0] + """ vdisk_id [ new_expiry ]
    6.17 +    vdisk_id   - the identifier of the deleted VD
    6.18 +    new_expiry - optionally the new expiry time in seconds from now (0
    6.19 +                 for never expire - which is the default)
    6.20 +
    6.21 +    VDs can currently only be undeleted if it is safe to do so,
    6.22 +    i.e. if none of their space has been reallocated.
    6.23 + """
    6.24 +
    6.25 +vdisk_id = sys.argv[1]
    6.26 +
    6.27 +if len(sys.argv) == 3:
    6.28 +    expiry = int(sys.argv[2])
    6.29 +else:
    6.30 +    expiry = 0
    6.31 +
    6.32 +if XenoUtil.vd_undelete(vdisk_id, expiry):
    6.33 +    print "Undelete operation failed for virtual disk: " + vdisk_id
    6.34 +else:
    6.35 +    print "Undelete operation succeeded for virtual disk: " + vdisk_id
     7.1 --- a/tools/xc/py/XenoUtil.py	Mon Jan 19 15:29:17 2004 +0000
     7.2 +++ b/tools/xc/py/XenoUtil.py	Mon Jan 19 19:41:53 2004 +0000
     7.3 @@ -219,6 +219,7 @@ def vd_format(partition, extent_size_mb)
     7.4      cx.close()
     7.5      return 0
     7.6  
     7.7 +
     7.8  def vd_create(size_mb, expiry):
     7.9      """Create a new virtual disk.
    7.10      size_mb [int]: size in megabytes for the new virtual disk
    7.11 @@ -252,10 +253,10 @@ def vd_create(size_mb, expiry):
    7.12  
    7.13      if expiry:
    7.14          expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
    7.15 -        expires = 1;
    7.16 +        expires = 1
    7.17      else:
    7.18          expiry_ts = "NULL"
    7.19 -        expires = 0;
    7.20 +        expires = 0
    7.21  
    7.22      # we'll use this to build the SQL statement we want
    7.23      building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \
    7.24 @@ -269,6 +270,7 @@ def vd_create(size_mb, expiry):
    7.25          if not row:
    7.26              cx.close()
    7.27              return -1
    7.28 +        
    7.29  
    7.30          (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
    7.31          allocated += extent_size
    7.32 @@ -310,6 +312,19 @@ def vd_lookup(id):
    7.33      cx = sqlite.connect(VD_DB_FILE)
    7.34      cu = cx.cursor()
    7.35  
    7.36 +    cu.execute("-- types int")
    7.37 +    cu.execute("""SELECT COUNT(*)
    7.38 +                  FROM vdisks
    7.39 +                  WHERE (expiry_time > datetime('now') OR NOT expires)
    7.40 +                              AND vdisk_id = """ + id)
    7.41 +    count, = cu.fetchone()
    7.42 +
    7.43 +    if not count:
    7.44 +        cx.close()
    7.45 +        return -1
    7.46 +
    7.47 +    cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id)
    7.48 +    real_size, = cu.fetchone()
    7.49    
    7.50      # This query tells PySQLite how to convert the data returned from the
    7.51      # following query - the use of the multiplication confuses it otherwise ;-)
    7.52 @@ -326,11 +341,10 @@ def vd_lookup(id):
    7.53                    FROM vdisk_extents NATURAL JOIN vdisks
    7.54                                                  NATURAL JOIN vdisk_part
    7.55                                                  
    7.56 -                  WHERE (expiry_time > datetime('now') OR not expires)
    7.57 -                                    AND vdisk_extents.vdisk_id = """ + id
    7.58 +                  WHERE vdisk_extents.vdisk_id = """ + id
    7.59                 )
    7.60  
    7.61 -    ret = cu.fetchall()
    7.62 +    extent_tuples = cu.fetchall()
    7.63  
    7.64      # use this function to map the results from the database into a dict
    7.65      # list of extents, for consistency with the rest of the code
    7.66 @@ -341,13 +355,204 @@ def vd_lookup(id):
    7.67      cx.commit()
    7.68      cx.close()
    7.69  
    7.70 -    return map(transform, ret) # transforms the tuples into dicts to return
    7.71 +    extent_dicts = map(transform, extent_tuples)
    7.72 +
    7.73 +    # calculate the over-allocation in sectors (happens because
    7.74 +    # we allocate whole extents)
    7.75 +    allocated_size = 0
    7.76 +    for i in extent_dicts:
    7.77 +        allocated_size += i['nr_sectors']
    7.78 +
    7.79 +    over_allocation = allocated_size - real_size
    7.80 +
    7.81 +    # trim down the last extent's length so the resulting VBD will be the
    7.82 +    # size requested, rather than being rounded up to the nearest extent
    7.83 +    extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation
    7.84 +
    7.85 +    return extent_dicts
    7.86 +
    7.87 +
    7.88 +def vd_enlarge(vdisk_id, extra_size_mb):
    7.89 +    """Create a new virtual disk.
    7.90 +    vdisk_id [string]   :    ID of the virtual disk to enlarge
    7.91 +    extra_size_mb  [int]:    size in megabytes to increase the allocation by
    7.92 +    returns  [int]      :    0 on success, otherwise non-zero
    7.93 +    """
    7.94 +
    7.95 +    if not os.path.isfile(VD_DB_FILE):
    7.96 +        __vd_no_database()
    7.97 +
    7.98 +    cx = sqlite.connect(VD_DB_FILE)
    7.99 +    cu = cx.cursor()
   7.100 +
   7.101 +    extra_size = extra_size_mb * 2048
   7.102 +
   7.103 +    cu.execute("-- types int")
   7.104 +    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id
   7.105 +               + " AND (expiry_time > datetime('now') OR NOT expires)")
   7.106 +    count, = cu.fetchone()
   7.107 +
   7.108 +    if not count: # no such vdisk
   7.109 +        cx.close()
   7.110 +        return -1
   7.111 +
   7.112 +    cu.execute("-- types int")
   7.113 +    cu.execute("""SELECT SUM(extent_size)
   7.114 +                  FROM vdisks NATURAL JOIN vdisk_extents
   7.115 +                                         NATURAL JOIN vdisk_part
   7.116 +                  WHERE vdisks.vdisk_id = """ + vdisk_id)
   7.117 +
   7.118 +    real_size, = cu.fetchone() # get the true allocated size
   7.119 +
   7.120 +    cu.execute("-- types int")
   7.121 +    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
   7.122 +
   7.123 +    old_size, = cu.fetchone()
   7.124 +
   7.125 +
   7.126 +    cu.execute("--- types int")
   7.127 +    cu.execute("""SELECT MAX(vdisk_extent_no)
   7.128 +                  FROM vdisk_extents
   7.129 +                  WHERE vdisk_id = """ + vdisk_id)
   7.130 +
   7.131 +    counter = cu.fetchone()[0] + 1 # this stores the extent numbers
   7.132 +
   7.133 +
   7.134 +    # because of the extent-based allocation, the VD may already have more
   7.135 +    # allocated space than they asked for.  Find out how much we really
   7.136 +    # need to add.
   7.137 +    add_size = extra_size + old_size - real_size
   7.138 +
   7.139 +    # fetch a list of extents from the expired disks, along with information
   7.140 +    # about their size
   7.141 +    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
   7.142 +                         vdisk_extents.part_id, extent_size
   7.143 +                  FROM vdisk_extents NATURAL JOIN vdisks
   7.144 +                                                  NATURAL JOIN vdisk_part
   7.145 +                  WHERE expires AND expiry_time < datetime('now')
   7.146 +                  ORDER BY expiry_time asc, vdisk_extent_no desc
   7.147 +               """)  # aims to reuse the last extents
   7.148 +                     # from the longest-expired disks first
   7.149 +
   7.150 +    allocated = 0
   7.151 +
   7.152 +    building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\
   7.153 +                   + " WHERE vdisk_id = " + vdisk_id + "; "
   7.154 +
   7.155 +    while allocated < add_size:
   7.156 +        row = cu.fetchone()
   7.157 +        if not row:
   7.158 +            cx.close()
   7.159 +            return -1
   7.160 +
   7.161 +        (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
   7.162 +        allocated += extent_size
   7.163 +        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id    \
   7.164 +                        + ", " + "vdisk_extent_no = " + str(counter)         \
   7.165 +                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
   7.166 +                        + " AND vdisk_id = " + str(dead_vd_id) + "; "
   7.167 +
   7.168 +        counter += 1
   7.169 +        
   7.170 +
   7.171 +    # this will execute the SQL query we build to store details of the new
   7.172 +    # virtual disk and allocate space to it print building_sql
   7.173 +    cu.execute(building_sql)
   7.174 +    
   7.175 +    cx.commit()
   7.176 +    cx.close()
   7.177 +    return 0
   7.178 +
   7.179 +
   7.180 +def vd_undelete(vdisk_id, expiry_time):
   7.181 +    """Create a new virtual disk.
   7.182 +    vdisk_id      [int]: size in megabytes for the new virtual disk
   7.183 +    expiry_time   [int]: expiry time, in seconds from now
   7.184 +    returns       [int]: zero on success, non-zero on failure
   7.185 +    """
   7.186 +
   7.187 +    if not os.path.isfile(VD_DB_FILE):
   7.188 +        __vd_no_database()
   7.189 +
   7.190 +    cx = sqlite.connect(VD_DB_FILE)
   7.191 +    cu = cx.cursor()
   7.192 +
   7.193 +    cu.execute("-- types int")
   7.194 +    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id)
   7.195 +    count, = cu.fetchone()
   7.196 +
   7.197 +    if not count:
   7.198 +        cx.close()
   7.199 +        return -1
   7.200 +
   7.201 +    cu.execute("-- types int")
   7.202 +    cu.execute("""SELECT SUM(extent_size)
   7.203 +                  FROM vdisks NATURAL JOIN vdisk_extents
   7.204 +                                         NATURAL JOIN vdisk_part
   7.205 +                  WHERE vdisks.vdisk_id = """ + vdisk_id)
   7.206 +
   7.207 +    real_size, = cu.fetchone() # get the true allocated size
   7.208 +
   7.209 +
   7.210 +    cu.execute("-- types int")
   7.211 +    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
   7.212 +
   7.213 +    old_size, = cu.fetchone()
   7.214 +
   7.215 +    if real_size < old_size:
   7.216 +        cx.close()
   7.217 +        return -1
   7.218 +
   7.219 +    if expiry_time == 0:
   7.220 +        expires = '0'
   7.221 +    else:
   7.222 +        expires = '1'
   7.223 +
   7.224 +    # this will execute the SQL query we build to store details of the new
   7.225 +    # virtual disk and allocate space to it print building_sql
   7.226 +    cu.execute("UPDATE vdisks SET expiry_time = datetime('now','"
   7.227 +               + str(expiry_time) + " seconds'), expires = " + expires
   7.228 +               + " WHERE vdisk_id = " + vdisk_id)
   7.229 +    
   7.230 +    cx.commit()
   7.231 +    cx.close()
   7.232 +    return 0
   7.233 +
   7.234 +
   7.235 +
   7.236 +
   7.237 +def vd_list():
   7.238 +    """Lists all the virtual disks registered in the system.
   7.239 +    returns [list of dicts]
   7.240 +    """
   7.241 +    
   7.242 +    if not os.path.isfile(VD_DB_FILE):
   7.243 +        __vd_no_database()
   7.244 +
   7.245 +    cx = sqlite.connect(VD_DB_FILE)
   7.246 +    cu = cx.cursor()
   7.247 +
   7.248 +    cu.execute("""SELECT vdisk_id, size, expires, expiry_time
   7.249 +                  FROM vdisks
   7.250 +                  WHERE (NOT expires) OR expiry_time > datetime('now')
   7.251 +               """)
   7.252 +
   7.253 +    ret = cu.fetchall()
   7.254 +
   7.255 +    cx.close()
   7.256 +
   7.257 +    def makedicts((vdisk_id, size, expires, expiry_time)):
   7.258 +        return { 'vdisk_id' : str(vdisk_id), 'size': size,
   7.259 +                 'expires' : expires, 'expiry_time' : expiry_time }
   7.260 +
   7.261 +    return map(makedicts, ret)
   7.262  
   7.263  
   7.264  def vd_refresh(id, expiry):
   7.265      """Change the expiry time of a virtual disk.
   7.266 -    id [string]: a virtual disk identifier
   7.267 -    expiry [int]: expiry time in seconds from now (0 = never expire)
   7.268 +    id [string]  : a virtual disk identifier
   7.269 +    expiry [int] : expiry time in seconds from now (0 = never expire)
   7.270 +    returns [int]: zero on success, non-zero on failure
   7.271      """
   7.272  
   7.273      if not os.path.isfile(VD_DB_FILE):
   7.274 @@ -356,6 +561,15 @@ def vd_refresh(id, expiry):
   7.275      cx = sqlite.connect(VD_DB_FILE)
   7.276      cu = cx.cursor()
   7.277  
   7.278 +    cu.execute("-- types int")
   7.279 +    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
   7.280 +               + " AND (expiry_time > datetime('now') OR NOT expires)")
   7.281 +    count, = cu.fetchone()
   7.282 +
   7.283 +    if not count:
   7.284 +        cx.close()
   7.285 +        return -1
   7.286 +
   7.287      if expiry:
   7.288          expires = 1
   7.289          expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
   7.290 @@ -365,17 +579,20 @@ def vd_refresh(id, expiry):
   7.291  
   7.292      cu.execute("UPDATE vdisks SET expires = " + str(expires)
   7.293                 + ", expiry_time = " + expiry_ts
   7.294 -               + " WHERE vdisk_id = " + id)
   7.295 +               + " WHERE (expiry_time > datetime('now') OR NOT expires)"
   7.296 +               + " AND vdisk_id = " + id)
   7.297  
   7.298      cx.commit()
   7.299      cx.close()
   7.300      
   7.301 -    return
   7.302 +    return 0
   7.303 +
   7.304  
   7.305  def vd_delete(id):
   7.306 -    """Deletes a Virtual Disk, making its extents available for future
   7.307 -    virtual disks.
   7.308 -       [id] identifier for the virtual disk to delete
   7.309 +    """Deletes a Virtual Disk, making its extents available for future VDs.
   7.310 +       id [string]   : identifier for the virtual disk to delete
   7.311 +       returns [int] : 0 on success, -1 on failure (VD not found
   7.312 +                       or already deleted)
   7.313      """
   7.314  
   7.315      if not os.path.isfile(VD_DB_FILE):
   7.316 @@ -384,13 +601,46 @@ def vd_delete(id):
   7.317      cx = sqlite.connect(VD_DB_FILE)
   7.318      cu = cx.cursor()
   7.319  
   7.320 +    cu.execute("-- types int")
   7.321 +    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
   7.322 +               + " AND (expiry_time > datetime('now') OR NOT expires)")
   7.323 +    count, = cu.fetchone()
   7.324 +
   7.325 +    if not count:
   7.326 +        cx.close()
   7.327 +        return -1
   7.328 +
   7.329      cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')"
   7.330                 + " WHERE vdisk_id = " + id)
   7.331  
   7.332      cx.commit()
   7.333      cx.close()
   7.334      
   7.335 -    return
   7.336 +    return 0
   7.337 +
   7.338 +
   7.339 +def vd_freespace():
   7.340 +    """Returns the amount of free space available for new virtual disks, in MB
   7.341 +    returns [int] : free space for VDs in MB
   7.342 +    """
   7.343 +
   7.344 +    if not os.path.isfile(VD_DB_FILE):
   7.345 +        __vd_no_database()
   7.346 + 
   7.347 +    cx = sqlite.connect(VD_DB_FILE)
   7.348 +    cu = cx.cursor()
   7.349 +
   7.350 +    cu.execute("-- types int")
   7.351 +
   7.352 +    cu.execute("""SELECT SUM(extent_size)
   7.353 +                  FROM vdisks NATURAL JOIN vdisk_extents
   7.354 +                                           NATURAL JOIN vdisk_part
   7.355 +                  WHERE expiry_time <= datetime('now') AND expires""")
   7.356 +
   7.357 +    sum, = cu.fetchone()
   7.358 +
   7.359 +    return sum / 2048
   7.360 +
   7.361  
   7.362  def vd_init_db(path):
   7.363      """Initialise the VD SQLite database
   7.364 @@ -461,12 +711,12 @@ def vd_extents_validate(new_extents,new_
   7.365          this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd'])
   7.366          for vbd_ext in this_vbd_extents:
   7.367              vbd_ext['writeable'] = vbd['writeable']
   7.368 -            old_extents.append(vbd_ext);
   7.369 -
   7.370 +            old_extents.append(vbd_ext)
   7.371 +            
   7.372      ##### Now scan /proc/mounts for compile a list of extents corresponding to
   7.373      ##### any devices mounted in DOM0.  This list is added on to old_extents
   7.374  
   7.375 -    regexp = re.compile("/dev/(\S*) \S* \S* (..).*");
   7.376 +    regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
   7.377      fd = open('/proc/mounts', "r")
   7.378  
   7.379      while True: