ia64/xen-unstable

changeset 1483:2183b086ef7d

bitkeeper revision 1.959.1.5 (40d04b7b7MkMcLlaSNJov9qsPAZ9tg)

Remove vdisk code.
author mjw@wray-m-3.hpl.hp.com
date Wed Jun 16 13:30:35 2004 +0000 (2004-06-16)
parents 74aec78554a4
children 00ee5e841bd7
files .rootkeys tools/examples/xc_vd_tool.py tools/examples/xm_vd_tool.py tools/xenctl/lib/vdisk.py tools/xenctl/setup.py tools/xenmgr/lib/XendDomain.py tools/xenmgr/lib/XendDomainInfo.py tools/xenmgr/lib/XendVdisk.py tools/xenmgr/lib/server/SrvRoot.py tools/xenmgr/lib/server/SrvVdisk.py tools/xenmgr/lib/server/SrvVdiskDir.py
line diff
     1.1 --- a/.rootkeys	Wed Jun 16 13:26:31 2004 +0000
     1.2 +++ b/.rootkeys	Wed Jun 16 13:30:35 2004 +0000
     1.3 @@ -164,10 +164,8 @@ 40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/exa
     1.4  401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
     1.5  401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
     1.6  403b7cf7J7FsSSoEPGhx6gXR4pIdZg tools/examples/xc_physinfo.py
     1.7 -401d7e16X4iojyKopo_j63AyzYZd2A tools/examples/xc_vd_tool.py
     1.8  40c9c4684Wfg8VgMKtRFa_ULi2e_tQ tools/examples/xm_dom_control.py
     1.9  40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
    1.10 -40c9c468QKoqBHjb5Qwrm60pNVcVng tools/examples/xm_vd_tool.py
    1.11  40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
    1.12  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.13  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.14 @@ -214,7 +212,6 @@ 4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen
    1.15  40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xenctl/lib/ip.py
    1.16  4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
    1.17  3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
    1.18 -40c9c468F36e06WH38kpYrD3JfXC0Q tools/xenctl/lib/vdisk.py
    1.19  4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
    1.20  40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
    1.21  4055ad95Se-FqttgxollqOAAHB94zA tools/xend/lib/__init__.py
    1.22 @@ -241,7 +238,6 @@ 40c9c4685ykq87_n1kVUbMr9flx9fg tools/xen
    1.23  40c9c46854nsHmuxHQHncKk5rAs5NA tools/xenmgr/lib/XendMigrate.py
    1.24  40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xenmgr/lib/XendNode.py
    1.25  40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xenmgr/lib/XendRoot.py
    1.26 -40c9c468P75aHqyIE156JXwc-5W92A tools/xenmgr/lib/XendVdisk.py
    1.27  40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xenmgr/lib/XendVnet.py
    1.28  40c9c468x191zetrVlMnExfsQWHxIQ tools/xenmgr/lib/__init__.py
    1.29  40c9c468S2YnCEKmk4ey8XQIST7INg tools/xenmgr/lib/encode.py
    1.30 @@ -257,8 +253,6 @@ 40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xen
    1.31  40c9c4694eu5759Dehr4Uhakei0EMg tools/xenmgr/lib/server/SrvNode.py
    1.32  40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xenmgr/lib/server/SrvRoot.py
    1.33  40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xenmgr/lib/server/SrvServer.py
    1.34 -40c9c469JlUVPkwGWZyVnqIsU8U6Bw tools/xenmgr/lib/server/SrvVdisk.py
    1.35 -40c9c469sG8iuyxjVH3zKw8XOAyxtQ tools/xenmgr/lib/server/SrvVdiskDir.py
    1.36  40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xenmgr/lib/server/SrvVnetDir.py
    1.37  40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xenmgr/lib/server/__init__.py
    1.38  40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xenmgr/lib/server/blkif.py
     2.1 --- a/tools/examples/xc_vd_tool.py	Wed Jun 16 13:26:31 2004 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,153 +0,0 @@
     2.4 -#!/usr/bin/env python
     2.5 -
     2.6 -import xenctl.utils, sys, re, string
     2.7 -
     2.8 -def usage():
     2.9 -
    2.10 -    print >>sys.stderr,"""
    2.11 -Usage: %s command <params>
    2.12 -
    2.13 -  initialise [dev] [[ext_size]] - init. a physcial partition to store vd's
    2.14 -  create [size] [[expiry]]      - allocate a vd of specified size (and expiry)
    2.15 -  enlarge [vdid] [extra_size]   - enlarge a specified vd by some amount
    2.16 -  delete [vdid]                 - delete a vd
    2.17 -  import [filename] [[expiry]]  - create a vd and populate w/ image from file
    2.18 -  export [vdid] [filename]      - copy vd's contents to a file
    2.19 -  setexpiry [vdid] [[expiry]]   - update the expiry time for a vd
    2.20 -  list                          - list all the unexpired virtual disks  
    2.21 -  undelete [vdid] [[expiry]]    - attempts to recover an expired vd
    2.22 -  freespace                     - print out the amount of space in free pool
    2.23 -
    2.24 -notes:
    2.25 -  vdid      - the virtual disk's identity string
    2.26 -  size      - measured in MB
    2.27 -  expiry    - is the expiry time of the virtual disk in seconds from now
    2.28 -               (0 = don't expire) 
    2.29 -  device    - physical partition to 'format' to hold vd's. e.g. hda4
    2.30 -  ext_size  - extent size (default 64MB)
    2.31 -""" % sys.argv[0]  
    2.32 -
    2.33 -if len(sys.argv) < 2: 
    2.34 -    usage()
    2.35 -    sys.exit(-1)
    2.36 -
    2.37 -rc=''
    2.38 -src=''
    2.39 -expiry_time = 0
    2.40 -cmd = sys.argv[1]
    2.41 -
    2.42 -if cmd == 'initialise':
    2.43 -
    2.44 -    dev = sys.argv[2]
    2.45 -
    2.46 -    if len(sys.argv) > 3:
    2.47 -	extent_size = int(sys.argv[3])
    2.48 -    else:
    2.49 -	print """No extent size specified - using default size of 64MB"""
    2.50 -	extent_size = 64
    2.51 -
    2.52 -    print "Formatting for virtual disks"
    2.53 -    print "Device: " + dev
    2.54 -    print "Extent size: " + str(extent_size) + "MB"
    2.55 -
    2.56 -    rc = xenctl.utils.vd_format(dev, extent_size)
    2.57 -
    2.58 -elif cmd == 'create':
    2.59 - 
    2.60 -    size = int(sys.argv[2])
    2.61 -    
    2.62 -    if len(sys.argv) > 3:
    2.63 -	expiry_time = int(sys.argv[3])
    2.64 -
    2.65 -    print "Creating a virtual disk"
    2.66 -    print "Size: %d" % size
    2.67 -    print "Expiry time (seconds from now): %d" % expiry_time
    2.68 -
    2.69 -    src = xenctl.utils.vd_create(size, expiry_time)
    2.70 -
    2.71 -elif cmd == 'enlarge':
    2.72 -
    2.73 -    id = sys.argv[2]
    2.74 -
    2.75 -    extra_size = int(sys.argv[3])
    2.76 -
    2.77 -    rc = xenctl.utils.vd_enlarge(id, extra_size)
    2.78 -
    2.79 -elif cmd == 'delete':
    2.80 -
    2.81 -    id = sys.argv[2]
    2.82 -
    2.83 -    print "Deleting a virtual disk with ID: " + id
    2.84 -
    2.85 -    rc = xenctl.utils.vd_delete(id)
    2.86 -
    2.87 -elif cmd == 'import':
    2.88 -
    2.89 -    file = sys.argv[2]
    2.90 -    
    2.91 -    if len(sys.argv) > 3:
    2.92 -	expiry_time = int(sys.argv[3])
    2.93 -
    2.94 -    print "Allocate new virtual disk and populate from file : %s" % file
    2.95 -
    2.96 -    print xenctl.utils.vd_read_from_file(file, expiry_time)
    2.97 -
    2.98 -elif cmd == 'export':
    2.99 -
   2.100 -    id = sys.argv[2]
   2.101 -    file = sys.argv[3]
   2.102 -
   2.103 -    print "Dump contents of virtual disk to file : %s" % file
   2.104 -
   2.105 -    rc = xenctl.utils.vd_cp_to_file(id, file )
   2.106 -
   2.107 -elif cmd == 'setexpiry':
   2.108 -
   2.109 -    id = sys.argv[2]
   2.110 -
   2.111 -    if len(sys.argv) > 3:
   2.112 -	expiry_time = int(sys.argv[3])
   2.113 -
   2.114 -    print "Refreshing a virtual disk"
   2.115 -    print "Id: " + id
   2.116 -    print "Expiry time (seconds from now [or 0]): " + str(expiry_time)
   2.117 -
   2.118 -    rc = xenctl.utils.vd_refresh(id, expiry_time)
   2.119 -
   2.120 -elif cmd == 'list':
   2.121 -    print 'ID    Size(MB)      Expiry'
   2.122 -
   2.123 -    for vbd in xenctl.utils.vd_list():
   2.124 -        vbd['size_mb'] = vbd['size'] / 2048
   2.125 -        vbd['expiry'] = (vbd['expires'] and vbd['expiry_time']) or 'never'
   2.126 -        print '%(vdisk_id)-4s  %(size_mb)-12d  %(expiry)s' % vbd
   2.127 -
   2.128 -elif cmd == 'freespace':
   2.129 -
   2.130 -    print xenctl.utils.vd_freespace()
   2.131 -
   2.132 -elif cmd == 'undelete':
   2.133 -
   2.134 -    id = sys.argv[2]
   2.135 -
   2.136 -    if len(sys.argv) > 3:
   2.137 -	expiry_time = int(sys.argv[3])
   2.138 -   
   2.139 -    if xenctl.utils.vd_undelete(id, expiry_time):
   2.140 -	print "Undelete operation failed for virtual disk: " + id
   2.141 -    else:
   2.142 -	print "Undelete operation succeeded for virtual disk: " + id
   2.143 -
   2.144 -else:
   2.145 -    usage()
   2.146 -    sys.exit(-1)
   2.147 -
   2.148 -
   2.149 -if src != '':  
   2.150 -    print "Returned virtual disk id is : %s" % src
   2.151 -
   2.152 -if rc != '':
   2.153 -    print "return code %d" % rc
   2.154 -
   2.155 -
   2.156 -
     3.1 --- a/tools/examples/xm_vd_tool.py	Wed Jun 16 13:26:31 2004 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,157 +0,0 @@
     3.4 -#!/usr/bin/env python
     3.5 -
     3.6 -import sys
     3.7 -import re
     3.8 -import string
     3.9 -
    3.10 -from xenctl import vdisk
    3.11 -
    3.12 -def usage():
    3.13 -
    3.14 -    print >>sys.stderr,"""
    3.15 -Usage: %s command <params>
    3.16 -
    3.17 -  initialise [dev] [[ext_size]] - init. a physcial partition to store vd's
    3.18 -  create [size] [[expiry]]      - allocate a vd of specified size (and expiry)
    3.19 -  enlarge [vdid] [extra_size]   - enlarge a specified vd by some amount
    3.20 -  delete [vdid]                 - delete a vd
    3.21 -  import [filename] [[expiry]]  - create a vd and populate w/ image from file
    3.22 -  export [vdid] [filename]      - copy vd's contents to a file
    3.23 -  setexpiry [vdid] [[expiry]]   - update the expiry time for a vd
    3.24 -  list                          - list all the unexpired virtual disks  
    3.25 -  undelete [vdid] [[expiry]]    - attempts to recover an expired vd
    3.26 -  freespace                     - print out the amount of space in free pool
    3.27 -
    3.28 -notes:
    3.29 -  vdid      - the virtual disk's identity string
    3.30 -  size      - measured in MB
    3.31 -  expiry    - is the expiry time of the virtual disk in seconds from now
    3.32 -               (0 = don't expire) 
    3.33 -  device    - physical partition to 'format' to hold vd's. e.g. hda4
    3.34 -  ext_size  - extent size (default 64MB)
    3.35 -""" % sys.argv[0]  
    3.36 -
    3.37 -if len(sys.argv) < 2: 
    3.38 -    usage()
    3.39 -    sys.exit(-1)
    3.40 -
    3.41 -rc=''
    3.42 -src=''
    3.43 -expiry_time = 0
    3.44 -cmd = sys.argv[1]
    3.45 -
    3.46 -if cmd == 'initialise':
    3.47 -
    3.48 -    dev = sys.argv[2]
    3.49 -
    3.50 -    if len(sys.argv) > 3:
    3.51 -	extent_size = int(sys.argv[3])
    3.52 -    else:
    3.53 -	print """No extent size specified - using default size of 64MB"""
    3.54 -	extent_size = 64
    3.55 -
    3.56 -    print "Formatting for virtual disks"
    3.57 -    print "Device: " + dev
    3.58 -    print "Extent size: " + str(extent_size) + "MB"
    3.59 -
    3.60 -    rc = vdisk.vd_format(dev, extent_size)
    3.61 -
    3.62 -elif cmd == 'create':
    3.63 - 
    3.64 -    size = int(sys.argv[2])
    3.65 -    
    3.66 -    if len(sys.argv) > 3:
    3.67 -	expiry_time = int(sys.argv[3])
    3.68 -
    3.69 -    print "Creating a virtual disk"
    3.70 -    print "Size: %d" % size
    3.71 -    print "Expiry time (seconds from now): %d" % expiry_time
    3.72 -
    3.73 -    src = vdisk.vd_create(size, expiry_time)
    3.74 -
    3.75 -elif cmd == 'enlarge':
    3.76 -
    3.77 -    id = sys.argv[2]
    3.78 -
    3.79 -    extra_size = int(sys.argv[3])
    3.80 -
    3.81 -    rc = vdisk.vd_enlarge(id, extra_size)
    3.82 -
    3.83 -elif cmd == 'delete':
    3.84 -
    3.85 -    id = sys.argv[2]
    3.86 -
    3.87 -    print "Deleting a virtual disk with ID: " + id
    3.88 -
    3.89 -    rc = vdisk.vd_delete(id)
    3.90 -
    3.91 -elif cmd == 'import':
    3.92 -
    3.93 -    file = sys.argv[2]
    3.94 -    
    3.95 -    if len(sys.argv) > 3:
    3.96 -	expiry_time = int(sys.argv[3])
    3.97 -
    3.98 -    print "Allocate new virtual disk and populate from file : %s" % file
    3.99 -
   3.100 -    print vdisk.vd_read_from_file(file, expiry_time)
   3.101 -
   3.102 -elif cmd == 'export':
   3.103 -
   3.104 -    id = sys.argv[2]
   3.105 -    file = sys.argv[3]
   3.106 -
   3.107 -    print "Dump contents of virtual disk to file : %s" % file
   3.108 -
   3.109 -    rc = vdisk.vd_cp_to_file(id, file )
   3.110 -
   3.111 -elif cmd == 'setexpiry':
   3.112 -
   3.113 -    id = sys.argv[2]
   3.114 -
   3.115 -    if len(sys.argv) > 3:
   3.116 -	expiry_time = int(sys.argv[3])
   3.117 -
   3.118 -    print "Refreshing a virtual disk"
   3.119 -    print "Id: " + id
   3.120 -    print "Expiry time (seconds from now [or 0]): " + str(expiry_time)
   3.121 -
   3.122 -    rc = vdisk.vd_refresh(id, expiry_time)
   3.123 -
   3.124 -elif cmd == 'list':
   3.125 -    print 'ID    Size(MB)      Expiry'
   3.126 -
   3.127 -    for vbd in vdisk.vd_list():
   3.128 -        vbd['size_mb'] = vbd['size'] / vdisk.VBD_SECTORS_PER_MB
   3.129 -        vbd['expiry'] = (vbd['expires'] and vbd['expiry_time']) or 'never'
   3.130 -        print '%(vdisk_id)-4s  %(size_mb)-12d  %(expiry)s' % vbd
   3.131 -
   3.132 -elif cmd == 'freespace':
   3.133 -
   3.134 -    print vdisk.vd_freespace()
   3.135 -
   3.136 -elif cmd == 'undelete':
   3.137 -
   3.138 -    id = sys.argv[2]
   3.139 -
   3.140 -    if len(sys.argv) > 3:
   3.141 -	expiry_time = int(sys.argv[3])
   3.142 -   
   3.143 -    if vdisk.vd_undelete(id, expiry_time):
   3.144 -	print "Undelete operation failed for virtual disk: " + id
   3.145 -    else:
   3.146 -	print "Undelete operation succeeded for virtual disk: " + id
   3.147 -
   3.148 -else:
   3.149 -    usage()
   3.150 -    sys.exit(-1)
   3.151 -
   3.152 -
   3.153 -if src != '':  
   3.154 -    print "Returned virtual disk id is : %s" % src
   3.155 -
   3.156 -if rc != '':
   3.157 -    print "return code %d" % rc
   3.158 -
   3.159 -
   3.160 -
     4.1 --- a/tools/xenctl/lib/vdisk.py	Wed Jun 16 13:26:31 2004 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,944 +0,0 @@
     4.4 -import os
     4.5 -import re
     4.6 -import socket
     4.7 -import string
     4.8 -import sys
     4.9 -import tempfile
    4.10 -import struct
    4.11 -
    4.12 -##### Module variables
    4.13 -
    4.14 -"""Location of the Virtual Disk management database.
    4.15 -   defaults to /var/db/xen_vdisks.sqlite
    4.16 -"""
    4.17 -VD_DB_FILE = "/var/db/xen_vdisks.sqlite"
    4.18 -
    4.19 -"""VBD expertise level - determines the strictness of the sanity checking.
    4.20 -  This mode determines the level of complaints when disk sharing occurs
    4.21 -  through the current VBD mappings.
    4.22 -   0 - only allow shared mappings if both domains have r/o access (always OK)
    4.23 -   1 - also allow sharing with one dom r/w and the other r/o
    4.24 -   2 - allow sharing with both doms r/w
    4.25 -"""
    4.26 -VBD_SAFETY_RR = 0
    4.27 -VBD_SAFETY_RW = 1
    4.28 -VBD_SAFETY_WW = 2
    4.29 -
    4.30 -VBD_SECTORS_PER_MB = 2048
    4.31 -
    4.32 -##### Module initialisation
    4.33 -
    4.34 -try:
    4.35 -    # try to import sqlite (not everyone will have it installed)
    4.36 -    import sqlite
    4.37 -except ImportError:
    4.38 -    # on failure, just catch the error, don't do anything
    4.39 -    pass
    4.40 -
    4.41 -
    4.42 -
    4.43 -##### VBD-related Functions
    4.44 -
    4.45 -def blkdev_name_to_number(name):
    4.46 -    """Take the given textual block-device name (e.g., '/dev/sda1',
    4.47 -    'hda') and return the device number used by the OS. """
    4.48 -
    4.49 -    if not re.match( '/dev/', name ):
    4.50 -        name = '/dev/' + name
    4.51 -        
    4.52 -    return os.stat(name).st_rdev
    4.53 -
    4.54 -# lookup_blkdev_partn_info( '/dev/sda3' )
    4.55 -def lookup_raw_partn(partition):
    4.56 -    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
    4.57 -    and return a dictionary { device, start_sector,
    4.58 -    nr_sectors, type }
    4.59 -        device:       Device number of the given partition
    4.60 -        start_sector: Index of first sector of the partition
    4.61 -        nr_sectors:   Number of sectors comprising this partition
    4.62 -        type:         'Disk' or identifying name for partition type
    4.63 -    """
    4.64 -
    4.65 -    if not re.match( '/dev/', partition ):
    4.66 -        partition = '/dev/' + partition
    4.67 -
    4.68 -    drive = re.split( '[0-9]', partition )[0]
    4.69 -
    4.70 -    if drive == partition:
    4.71 -        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
    4.72 -        line = readline(fd)
    4.73 -        if line:
    4.74 -            return [ { 'device' : blkdev_name_to_number(drive),
    4.75 -                       'start_sector' : long(0),
    4.76 -                       'nr_sectors' : long(line) * 2,
    4.77 -                       'type' : 'Disk' } ]
    4.78 -        return None
    4.79 -
    4.80 -    # determine position on disk
    4.81 -    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
    4.82 -
    4.83 -    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
    4.84 -    lines = readlines(fd)
    4.85 -    for line in lines:
    4.86 -        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
    4.87 -                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
    4.88 -        if m:
    4.89 -            return [ { 'device' : blkdev_name_to_number(drive),
    4.90 -                       'start_sector' : long(m.group(1)),
    4.91 -                       'nr_sectors' : long(m.group(2)),
    4.92 -                       'type' : m.group(3) } ]
    4.93 -    
    4.94 -    return None
    4.95 -
    4.96 -def lookup_disk_uname( uname ):
    4.97 -    """Lookup a list of segments for either a physical or a virtual device.
    4.98 -    uname [string]:  name of the device in the format \'vd:id\' for a virtual
    4.99 -                     disk, or \'phy:dev\' for a physical device
   4.100 -    returns [list of dicts]: list of extents that make up the named device
   4.101 -    """
   4.102 -    ( type, d_name ) = string.split( uname, ':' )
   4.103 -
   4.104 -    if type == "phy":
   4.105 -        segments = lookup_raw_partn( d_name )
   4.106 -    elif type == "vd":
   4.107 -	segments = vd_lookup( d_name )
   4.108 -
   4.109 -    return segments
   4.110 -
   4.111 -
   4.112 -##### VD Management-related functions
   4.113 -
   4.114 -##### By Mark Williamson, <mark.a.williamson@intel.com>
   4.115 -##### (C) Intel Research Cambridge
   4.116 -
   4.117 -# TODO:
   4.118 -#
   4.119 -# Plenty of room for enhancement to this functionality (contributions
   4.120 -# welcome - and then you get to have your name in the source ;-)...
   4.121 -#
   4.122 -# vd_unformat() : want facilities to unallocate virtual disk
   4.123 -# partitions, possibly migrating virtual disks of them, with checks to see if
   4.124 -# it's safe and options to force it anyway
   4.125 -#
   4.126 -# vd_create() : should have an optional argument specifying a physical
   4.127 -# disk preference - useful to allocate for guest doms to do RAID
   4.128 -#
   4.129 -# vd_undelete() : add ability to "best effort" undelete as much of a
   4.130 -# vdisk as is left in the case that some of it has already been
   4.131 -# reallocated.  Some people might still be able to recover some of
   4.132 -# their data this way, even if some of the disk has disappeared.
   4.133 -#
   4.134 -# It'd be nice if we could wipe virtual disks for security purposes -
   4.135 -# should be easy to do this using dev if=/dev/{zero,random} on each
   4.136 -# extent in turn.  There could be another optional flag to vd_create
   4.137 -# in order to allow this.
   4.138 -#
   4.139 -# Error codes could be more expressive - i.e. actually tell why the
   4.140 -# error occurred rather than "it broke".  Currently the code avoids
   4.141 -# using exceptions to make control scripting simpler and more
   4.142 -# accessible to beginners - therefore probably should just use more
   4.143 -# return codes.
   4.144 -#
   4.145 -# Enhancements / additions to the example scripts are also welcome:
   4.146 -# some people will interact with this code mostly through those
   4.147 -# scripts.
   4.148 -#
   4.149 -# More documentation of how this stuff should be used is always nice -
   4.150 -# if you have a novel configuration that you feel isn't discussed
   4.151 -# enough in the HOWTO (which is currently a work in progress), feel
   4.152 -# free to contribute a walkthrough, or something more substantial.
   4.153 -#
   4.154 -
   4.155 -
   4.156 -def __vd_no_database():
   4.157 -    """Called when no database found - exits with an error
   4.158 -    """
   4.159 -    print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE
   4.160 -    sys.exit(1)
   4.161 -
   4.162 -def readlines(fd):
   4.163 -    """Version of readlines safe against EINTR.
   4.164 -    """
   4.165 -    import errno
   4.166 -    
   4.167 -    lines = []
   4.168 -    while 1:
   4.169 -        try:
   4.170 -            line = fd.readline()
   4.171 -        except IOError, ex:
   4.172 -            if ex.errno == errno.EINTR:
   4.173 -                continue
   4.174 -            else:
   4.175 -                raise
   4.176 -        if line == '': break
   4.177 -        lines.append(line)
   4.178 -    return lines
   4.179 -
   4.180 -def readline(fd):
   4.181 -    """Version of readline safe against EINTR.
   4.182 -    """
   4.183 -    while 1:
   4.184 -        try:
   4.185 -            return fd.readline()
   4.186 -        except IOError, ex:
   4.187 -            if ex.errno == errno.EINTR:
   4.188 -                continue
   4.189 -            else:
   4.190 -                raise
   4.191 -        
   4.192 -
   4.193 -def vd_format(partition, extent_size_mb):
   4.194 -    """Format a partition or drive for use a virtual disk storage.
   4.195 -    partition [string]: device file representing the partition
   4.196 -    extent_size_mb [string]: extent size in megabytes to use on this disk
   4.197 -    """
   4.198 -
   4.199 -    if not os.path.isfile(VD_DB_FILE):
   4.200 -        vd_init_db(VD_DB_FILE)
   4.201 -    
   4.202 -    if not re.match( '/dev/', partition ):
   4.203 -        partition = '/dev/' + partition
   4.204 -
   4.205 -    cx = sqlite.connect(VD_DB_FILE)
   4.206 -    cu = cx.cursor()
   4.207 -
   4.208 -    cu.execute("select * from vdisk_part where partition = \'"
   4.209 -               + partition + "\'")
   4.210 -    row = cu.fetchone()
   4.211 -
   4.212 -    extent_size = extent_size_mb * VBD_SECTORS_PER_MB # convert megabytes to sectors
   4.213 -    
   4.214 -    if not row:
   4.215 -        part_info = lookup_raw_partn(partition)[0]
   4.216 -        
   4.217 -        cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " +
   4.218 -                   "VALUES ( \'" + partition + "\', "
   4.219 -                   + str(blkdev_name_to_number(partition))
   4.220 -                   + ", " + str(extent_size) + ")")
   4.221 -
   4.222 -
   4.223 -        cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents "
   4.224 -                   + "WHERE vdisk_id = 0")
   4.225 -        
   4.226 -        max_id, = cu.fetchone()
   4.227 -
   4.228 -        if max_id != None:
   4.229 -            new_id = max_id + 1
   4.230 -        else:
   4.231 -            new_id = 0
   4.232 -
   4.233 -        num_extents = part_info['nr_sectors'] / extent_size
   4.234 -
   4.235 -        for i in range(num_extents):
   4.236 -            sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id,
   4.237 -                                              part_id, part_extent_no)
   4.238 -                    VALUES ("""+ str(new_id + i) + ", 0, "\
   4.239 -                               + str(blkdev_name_to_number(partition))\
   4.240 -                               + ", " + str(num_extents - (i + 1)) + ")"
   4.241 -            cu.execute(sql)
   4.242 -
   4.243 -    cx.commit()
   4.244 -    cx.close()
   4.245 -    return 0
   4.246 -
   4.247 -
   4.248 -def vd_create(size_mb, expiry):
   4.249 -    """Create a new virtual disk.
   4.250 -    size_mb [int]: size in megabytes for the new virtual disk
   4.251 -    expiry [int]: expiry time in seconds from now
   4.252 -    """
   4.253 -
   4.254 -    if not os.path.isfile(VD_DB_FILE):
   4.255 -        __vd_no_database()
   4.256 -
   4.257 -    cx = sqlite.connect(VD_DB_FILE)
   4.258 -    cu = cx.cursor()
   4.259 -
   4.260 -    size = size_mb * VBD_SECTORS_PER_MB
   4.261 -
   4.262 -    cu.execute("SELECT max(vdisk_id) FROM vdisks")
   4.263 -    max_id, = cu.fetchone()
   4.264 -    new_id = int(max_id) + 1
   4.265 -
   4.266 -    # fetch a list of extents from the expired disks, along with information
   4.267 -    # about their size
   4.268 -    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
   4.269 -                         vdisk_extents.part_id, extent_size
   4.270 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.271 -                                                  NATURAL JOIN vdisk_part
   4.272 -                  WHERE expires AND expiry_time <= datetime('now')
   4.273 -                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
   4.274 -               """)  # aims to reuse the last extents
   4.275 -                     # from the longest-expired disks first
   4.276 -
   4.277 -    allocated = 0
   4.278 -
   4.279 -    if expiry:
   4.280 -        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
   4.281 -        expires = 1
   4.282 -    else:
   4.283 -        expiry_ts = "NULL"
   4.284 -        expires = 0
   4.285 -
   4.286 -    # we'll use this to build the SQL statement we want
   4.287 -    building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \
   4.288 -                   +" VALUES ("+str(new_id)+", "+str(size)+ ", "              \
   4.289 -                   + str(expires) + ", " + expiry_ts + "); "
   4.290 -
   4.291 -    counter = 0
   4.292 -
   4.293 -    while allocated < size:
   4.294 -        row = cu.fetchone()
   4.295 -        if not row:
   4.296 -            print "ran out of space, having allocated %d meg of %d" % (allocated, size)
   4.297 -            cx.close()
   4.298 -            return -1
   4.299 -        
   4.300 -
   4.301 -        (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
   4.302 -        allocated += extent_size
   4.303 -        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \
   4.304 -                        + ", " + "vdisk_extent_no = " + str(counter)         \
   4.305 -                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
   4.306 -                        + " AND vdisk_id = " + str(vdisk_id) + "; "
   4.307 -
   4.308 -        counter += 1
   4.309 -        
   4.310 -
   4.311 -    # this will execute the SQL query we build to store details of the new
   4.312 -    # virtual disk and allocate space to it print building_sql
   4.313 -    cu.execute(building_sql)
   4.314 -    
   4.315 -    cx.commit()
   4.316 -    cx.close()
   4.317 -    return str(new_id)
   4.318 -
   4.319 -
   4.320 -def vd_lookup(id):
   4.321 -    """Lookup a Virtual Disk by ID.
   4.322 -    id [string]: a virtual disk identifier
   4.323 -    Returns [list of dicts]: a list of extents as dicts, containing fields:
   4.324 -                             device : Linux device number of host disk
   4.325 -                             start_sector : within the device
   4.326 -                             nr_sectors : size of this extent
   4.327 -                             type : set to \'VD Extent\'
   4.328 -                             
   4.329 -                             part_device : Linux device no of host partition
   4.330 -                             part_start_sector : within the partition
   4.331 -    """
   4.332 -
   4.333 -    if not os.path.isfile(VD_DB_FILE):
   4.334 -        __vd_no_database()
   4.335 -
   4.336 -    cx = sqlite.connect(VD_DB_FILE)
   4.337 -    cu = cx.cursor()
   4.338 -
   4.339 -    cu.execute("-- types int")
   4.340 -    cu.execute("""SELECT COUNT(*)
   4.341 -                  FROM vdisks
   4.342 -                  WHERE (expiry_time > datetime('now') OR NOT expires)
   4.343 -                              AND vdisk_id = """ + id)
   4.344 -    count, = cu.fetchone()
   4.345 -
   4.346 -    if not count:
   4.347 -        cx.close()
   4.348 -        return None
   4.349 -
   4.350 -    cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id)
   4.351 -    real_size, = cu.fetchone()
   4.352 -  
   4.353 -    # This query tells PySQLite how to convert the data returned from the
   4.354 -    # following query - the use of the multiplication confuses it otherwise ;-)
   4.355 -    # This row is significant to PySQLite but is syntactically an SQL comment.
   4.356 -
   4.357 -    cu.execute("-- types str, int, int, int")
   4.358 -
   4.359 -    # This SQL statement is designed so that when the results are fetched they
   4.360 -    # will be in the right format to return immediately.
   4.361 -    cu.execute("""SELECT partition, vdisk_part.part_id,
   4.362 -                         round(part_extent_no * extent_size) as start,
   4.363 -                         extent_size
   4.364 -                         
   4.365 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.366 -                                             NATURAL JOIN vdisk_part
   4.367 -                                                
   4.368 -                  WHERE vdisk_extents.vdisk_id = """ + id
   4.369 -               + " ORDER BY vdisk_extents.vdisk_extent_no ASC"
   4.370 -               )
   4.371 -
   4.372 -    extent_tuples = cu.fetchall()
   4.373 -
   4.374 -    # use this function to map the results from the database into a dict
   4.375 -    # list of extents, for consistency with the rest of the code
   4.376 -    def transform ((partition, part_device, part_offset, nr_sectors)):
   4.377 -        return {
   4.378 -                 # the disk device this extent is on - for passing to Xen
   4.379 -                 'device' : lookup_raw_partn(partition)[0]['device'],
   4.380 -                 # the offset of this extent within the disk - for passing to Xen
   4.381 -                 'start_sector' : long(part_offset + lookup_raw_partn(partition)[0]['start_sector']),
   4.382 -                 # extent size, in sectors
   4.383 -                 'nr_sectors' : nr_sectors,
   4.384 -                 # partition device this extent is on (useful to know for xenctl.utils fns)
   4.385 -                 'part_device' : part_device,
   4.386 -                 # start sector within this partition (useful to know for xenctl.utils fns)
   4.387 -                 'part_start_sector' : part_offset,
   4.388 -                 # type of this extent - handy to know
   4.389 -                 'type' : 'VD Extent' }
   4.390 -
   4.391 -    cx.commit()
   4.392 -    cx.close()
   4.393 -
   4.394 -    extent_dicts = map(transform, extent_tuples)
   4.395 -
   4.396 -    # calculate the over-allocation in sectors (happens because
   4.397 -    # we allocate whole extents)
   4.398 -    allocated_size = 0
   4.399 -    for i in extent_dicts:
   4.400 -        allocated_size += i['nr_sectors']
   4.401 -
   4.402 -    over_allocation = allocated_size - real_size
   4.403 -
   4.404 -    # trim down the last extent's length so the resulting VBD will be the
   4.405 -    # size requested, rather than being rounded up to the nearest extent
   4.406 -    extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation
   4.407 -
   4.408 -    return extent_dicts
   4.409 -
   4.410 -
   4.411 -def vd_enlarge(vdisk_id, extra_size_mb):
   4.412 -    """Create a new virtual disk.
   4.413 -    vdisk_id [string]   :    ID of the virtual disk to enlarge
   4.414 -    extra_size_mb  [int]:    size in megabytes to increase the allocation by
   4.415 -    returns  [int]      :    0 on success, otherwise non-zero
   4.416 -    """
   4.417 -
   4.418 -    if not os.path.isfile(VD_DB_FILE):
   4.419 -        __vd_no_database()
   4.420 -
   4.421 -    cx = sqlite.connect(VD_DB_FILE)
   4.422 -    cu = cx.cursor()
   4.423 -
   4.424 -    extra_size = extra_size_mb * VBD_SECTORS_PER_MB
   4.425 -
   4.426 -    cu.execute("-- types int")
   4.427 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id
   4.428 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
   4.429 -    count, = cu.fetchone()
   4.430 -
   4.431 -    if not count: # no such vdisk
   4.432 -        cx.close()
   4.433 -        return -1
   4.434 -
   4.435 -    cu.execute("-- types int")
   4.436 -    cu.execute("""SELECT SUM(extent_size)
   4.437 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.438 -                                         NATURAL JOIN vdisk_part
   4.439 -                  WHERE vdisks.vdisk_id = """ + vdisk_id)
   4.440 -
   4.441 -    real_size, = cu.fetchone() # get the true allocated size
   4.442 -
   4.443 -    cu.execute("-- types int")
   4.444 -    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
   4.445 -
   4.446 -    old_size, = cu.fetchone()
   4.447 -
   4.448 -
   4.449 -    cu.execute("--- types int")
   4.450 -    cu.execute("""SELECT MAX(vdisk_extent_no)
   4.451 -                  FROM vdisk_extents
   4.452 -                  WHERE vdisk_id = """ + vdisk_id)
   4.453 -
   4.454 -    counter = cu.fetchone()[0] + 1 # this stores the extent numbers
   4.455 -
   4.456 -
   4.457 -    # because of the extent-based allocation, the VD may already have more
   4.458 -    # allocated space than they asked for.  Find out how much we really
   4.459 -    # need to add.
   4.460 -    add_size = extra_size + old_size - real_size
   4.461 -
   4.462 -    # fetch a list of extents from the expired disks, along with information
   4.463 -    # about their size
   4.464 -    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
   4.465 -                         vdisk_extents.part_id, extent_size
   4.466 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.467 -                                                  NATURAL JOIN vdisk_part
   4.468 -                  WHERE expires AND expiry_time <= datetime('now')
   4.469 -                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
   4.470 -               """)  # aims to reuse the last extents
   4.471 -                     # from the longest-expired disks first
   4.472 -
   4.473 -    allocated = 0
   4.474 -
   4.475 -    building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\
   4.476 -                   + " WHERE vdisk_id = " + vdisk_id + "; "
   4.477 -
   4.478 -    while allocated < add_size:
   4.479 -        row = cu.fetchone()
   4.480 -        if not row:
   4.481 -            cx.close()
   4.482 -            return -1
   4.483 -
   4.484 -        (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
   4.485 -        allocated += extent_size
   4.486 -        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id    \
   4.487 -                        + ", " + "vdisk_extent_no = " + str(counter)         \
   4.488 -                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
   4.489 -                        + " AND vdisk_id = " + str(dead_vd_id) + "; "
   4.490 -
   4.491 -        counter += 1
   4.492 -        
   4.493 -
   4.494 -    # this will execute the SQL query we build to store details of the new
   4.495 -    # virtual disk and allocate space to it print building_sql
   4.496 -    cu.execute(building_sql)
   4.497 -    
   4.498 -    cx.commit()
   4.499 -    cx.close()
   4.500 -    return 0
   4.501 -
   4.502 -
   4.503 -def vd_undelete(vdisk_id, expiry_time):
   4.504 -    """Create a new virtual disk.
   4.505 -    vdisk_id      [int]: size in megabytes for the new virtual disk
   4.506 -    expiry_time   [int]: expiry time, in seconds from now
   4.507 -    returns       [int]: zero on success, non-zero on failure
   4.508 -    """
   4.509 -
   4.510 -    if not os.path.isfile(VD_DB_FILE):
   4.511 -        __vd_no_database()
   4.512 -
   4.513 -    if vdisk_id == '0': #  undeleting vdisk 0 isn't sane!
   4.514 -        return -1
   4.515 -
   4.516 -    cx = sqlite.connect(VD_DB_FILE)
   4.517 -    cu = cx.cursor()
   4.518 -
   4.519 -    cu.execute("-- types int")
   4.520 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id)
   4.521 -    count, = cu.fetchone()
   4.522 -
   4.523 -    if not count:
   4.524 -        cx.close()
   4.525 -        return -1
   4.526 -
   4.527 -    cu.execute("-- types int")
   4.528 -    cu.execute("""SELECT SUM(extent_size)
   4.529 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.530 -                                         NATURAL JOIN vdisk_part
   4.531 -                  WHERE vdisks.vdisk_id = """ + vdisk_id)
   4.532 -
   4.533 -    real_size, = cu.fetchone() # get the true allocated size
   4.534 -
   4.535 -
   4.536 -    cu.execute("-- types int")
   4.537 -    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
   4.538 -
   4.539 -    old_size, = cu.fetchone()
   4.540 -
   4.541 -    if real_size < old_size:
   4.542 -        cx.close()
   4.543 -        return -1
   4.544 -
   4.545 -    if expiry_time == 0:
   4.546 -        expires = '0'
   4.547 -    else:
   4.548 -        expires = '1'
   4.549 -
   4.550 -    # this will execute the SQL query we build to store details of the new
   4.551 -    # virtual disk and allocate space to it print building_sql
   4.552 -    cu.execute("UPDATE vdisks SET expiry_time = datetime('now','"
   4.553 -               + str(expiry_time) + " seconds'), expires = " + expires
   4.554 -               + " WHERE vdisk_id = " + vdisk_id)
   4.555 -    
   4.556 -    cx.commit()
   4.557 -    cx.close()
   4.558 -    return 0
   4.559 -
   4.560 -
   4.561 -
   4.562 -
   4.563 -def vd_list():
   4.564 -    """Lists all the virtual disks registered in the system.
   4.565 -    returns [list of dicts]
   4.566 -    """
   4.567 -    
   4.568 -    if not os.path.isfile(VD_DB_FILE):
   4.569 -        __vd_no_database()
   4.570 -
   4.571 -    cx = sqlite.connect(VD_DB_FILE)
   4.572 -    cu = cx.cursor()
   4.573 -
   4.574 -    cu.execute("""SELECT vdisk_id, size, expires, expiry_time
   4.575 -                  FROM vdisks
   4.576 -                  WHERE (NOT expires) OR expiry_time > datetime('now')
   4.577 -               """)
   4.578 -
   4.579 -    ret = cu.fetchall()
   4.580 -
   4.581 -    cx.close()
   4.582 -
   4.583 -    def makedicts((vdisk_id, size, expires, expiry_time)):
   4.584 -        return { 'vdisk_id' : str(vdisk_id), 'size': size,
   4.585 -                 'expires' : expires, 'expiry_time' : expiry_time }
   4.586 -
   4.587 -    return map(makedicts, ret)
   4.588 -
   4.589 -
   4.590 -def vd_refresh(id, expiry):
   4.591 -    """Change the expiry time of a virtual disk.
   4.592 -    id [string]  : a virtual disk identifier
   4.593 -    expiry [int] : expiry time in seconds from now (0 = never expire)
   4.594 -    returns [int]: zero on success, non-zero on failure
   4.595 -    """
   4.596 -
   4.597 -    if not os.path.isfile(VD_DB_FILE):
   4.598 -        __vd_no_database()
   4.599 -    
   4.600 -    cx = sqlite.connect(VD_DB_FILE)
   4.601 -    cu = cx.cursor()
   4.602 -
   4.603 -    cu.execute("-- types int")
   4.604 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
   4.605 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
   4.606 -    count, = cu.fetchone()
   4.607 -
   4.608 -    if not count:
   4.609 -        cx.close()
   4.610 -        return -1
   4.611 -
   4.612 -    if expiry:
   4.613 -        expires = 1
   4.614 -        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
   4.615 -    else:
   4.616 -        expires = 0
   4.617 -        expiry_ts = "NULL"
   4.618 -
   4.619 -    cu.execute("UPDATE vdisks SET expires = " + str(expires)
   4.620 -               + ", expiry_time = " + expiry_ts
   4.621 -               + " WHERE (expiry_time > datetime('now') OR NOT expires)"
   4.622 -               + " AND vdisk_id = " + id)
   4.623 -
   4.624 -    cx.commit()
   4.625 -    cx.close()
   4.626 -    
   4.627 -    return 0
   4.628 -
   4.629 -
   4.630 -def vd_delete(id):
   4.631 -    """Deletes a Virtual Disk, making its extents available for future VDs.
   4.632 -       id [string]   : identifier for the virtual disk to delete
   4.633 -       returns [int] : 0 on success, -1 on failure (VD not found
   4.634 -                       or already deleted)
   4.635 -    """
   4.636 -
   4.637 -    if not os.path.isfile(VD_DB_FILE):
   4.638 -        __vd_no_database()
   4.639 -    
   4.640 -    cx = sqlite.connect(VD_DB_FILE)
   4.641 -    cu = cx.cursor()
   4.642 -
   4.643 -    cu.execute("-- types int")
   4.644 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
   4.645 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
   4.646 -    count, = cu.fetchone()
   4.647 -
   4.648 -    if not count:
   4.649 -        cx.close()
   4.650 -        return -1
   4.651 -
   4.652 -    cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')"
   4.653 -               + " WHERE vdisk_id = " + id)
   4.654 -
   4.655 -    cx.commit()
   4.656 -    cx.close()
   4.657 -    
   4.658 -    return 0
   4.659 -
   4.660 -
   4.661 -def vd_freespace():
   4.662 -    """Returns the amount of free space available for new virtual disks, in MB
   4.663 -    returns [int] : free space for VDs in MB
   4.664 -    """
   4.665 -
   4.666 -    if not os.path.isfile(VD_DB_FILE):
   4.667 -        __vd_no_database()
   4.668 - 
   4.669 -    cx = sqlite.connect(VD_DB_FILE)
   4.670 -    cu = cx.cursor()
   4.671 -
   4.672 -    cu.execute("-- types int")
   4.673 -
   4.674 -    cu.execute("""SELECT SUM(extent_size)
   4.675 -                  FROM vdisks NATURAL JOIN vdisk_extents
   4.676 -                                           NATURAL JOIN vdisk_part
   4.677 -                  WHERE expiry_time <= datetime('now') AND expires""")
   4.678 -
   4.679 -    sum, = cu.fetchone()
   4.680 -
   4.681 -    cx.close()
   4.682 -
   4.683 -    return sum / VBD_SECTORS_PER_MB
   4.684 -
   4.685 -
   4.686 -def vd_init_db(path):
   4.687 -    """Initialise the VD SQLite database
   4.688 -    path [string]: path to the SQLite database file
   4.689 -    """
   4.690 -
   4.691 -    cx = sqlite.connect(path)
   4.692 -    cu = cx.cursor()
   4.693 -
   4.694 -    cu.execute(
   4.695 -        """CREATE TABLE vdisk_extents
   4.696 -                           ( vdisk_extent_no INT,
   4.697 -                             vdisk_id INT,
   4.698 -                             part_id INT,
   4.699 -                             part_extent_no INT )
   4.700 -        """)
   4.701 -
   4.702 -    cu.execute(
   4.703 -        """CREATE TABLE vdisk_part
   4.704 -                           ( part_id INT,
   4.705 -                             partition VARCHAR,
   4.706 -                             extent_size INT )
   4.707 -        """)
   4.708 -
   4.709 -    cu.execute(
   4.710 -        """CREATE TABLE vdisks
   4.711 -                           ( vdisk_id INT,
   4.712 -                             size INT,
   4.713 -                             expires BOOLEAN,
   4.714 -                             expiry_time TIMESTAMP )
   4.715 -        """)
   4.716 -
   4.717 -
   4.718 -    cu.execute(
   4.719 -        """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time )
   4.720 -                       VALUES ( 0,        0,    1,       datetime('now') )
   4.721 -        """)
   4.722 -
   4.723 -    cx.commit()
   4.724 -    cx.close()
   4.725 -
   4.726 -    VD_DB_FILE = path
   4.727 -
   4.728 -
   4.729 -
   4.730 -def vd_cp_to_file(vdisk_id,filename):
   4.731 -    """Writes the contents of a specified vdisk out into a disk file, leaving
   4.732 -    the original copy in the virtual disk pool."""
   4.733 -
   4.734 -    cx = sqlite.connect(VD_DB_FILE)
   4.735 -    cu = cx.cursor()
   4.736 -
   4.737 -    extents = vd_lookup(vdisk_id)
   4.738 -
   4.739 -    if not extents:
   4.740 -        return -1
   4.741 -    
   4.742 -    file_idx = 0 # index into source file, in sectors
   4.743 -
   4.744 -    for i in extents:
   4.745 -        cu.execute("""SELECT partition, extent_size FROM vdisk_part
   4.746 -                      WHERE part_id =  """ + str(i['part_device']))
   4.747 -
   4.748 -        (partition, extent_size) = cu.fetchone()
   4.749 -
   4.750 -        os.system("dd bs=1b if=" + partition + " of=" + filename
   4.751 -                  + " skip=" + str(i['part_start_sector'])
   4.752 -                  + " seek=" + str(file_idx)
   4.753 -                  + " count=" + str(i['nr_sectors'])
   4.754 -                  + " > /dev/null")
   4.755 -
   4.756 -        file_idx += i['nr_sectors']
   4.757 -
   4.758 -    cx.close()
   4.759 -
   4.760 -    return 0 # should return -1 if something breaks
   4.761 -    
   4.762 -
   4.763 -def vd_mv_to_file(vdisk_id,filename):
   4.764 -    """Writes a vdisk out into a disk file and frees the space originally
   4.765 -    taken within the virtual disk pool.
   4.766 -    vdisk_id [string]: ID of the vdisk to write out
   4.767 -    filename [string]: file to write vdisk contents out to
   4.768 -    returns [int]: zero on success, nonzero on failure
   4.769 -    """
   4.770 -
   4.771 -    if vd_cp_to_file(vdisk_id,filename):
   4.772 -        return -1
   4.773 -
   4.774 -    if vd_delete(vdisk_id):
   4.775 -        return -1
   4.776 -
   4.777 -    return 0
   4.778 -
   4.779 -
   4.780 -def vd_read_from_file(filename,expiry):
   4.781 -    """Reads the contents of a file directly into a vdisk, which is
   4.782 -    automatically allocated to fit.
   4.783 -    filename [string]: file to read disk contents from
   4.784 -    returns [string] : vdisk ID for the destination vdisk
   4.785 -    """
   4.786 -
   4.787 -    size_bytes = os.stat(filename).st_size
   4.788 -
   4.789 -    (size_mb,leftover) =  divmod(size_bytes,1048580) # size in megabytes
   4.790 -    if leftover > 0: size_mb += 1 # round up if not an exact number of MB
   4.791 -
   4.792 -    vdisk_id = vd_create(size_mb, expiry)
   4.793 -
   4.794 -    if vdisk_id < 0:
   4.795 -        return -1
   4.796 -
   4.797 -    cx = sqlite.connect(VD_DB_FILE)
   4.798 -    cu = cx.cursor()
   4.799 -
   4.800 -    cu.execute("""SELECT partition, extent_size, part_extent_no
   4.801 -                  FROM vdisk_part NATURAL JOIN vdisk_extents
   4.802 -                  WHERE vdisk_id =  """ + vdisk_id + """
   4.803 -                  ORDER BY vdisk_extent_no ASC""")
   4.804 -
   4.805 -    extents = cu.fetchall()
   4.806 -
   4.807 -    size_sectors = size_mb * VBD_SECTORS_PER_MB # for feeding to dd
   4.808 -
   4.809 -    file_idx = 0 # index into source file, in sectors
   4.810 -
   4.811 -    def write_extent_to_vd((partition, extent_size, part_extent_no),
   4.812 -                           file_idx, filename):
   4.813 -        """Write an extent out to disk and update file_idx"""
   4.814 -
   4.815 -        os.system("dd bs=512 if=" + filename + " of=" + partition
   4.816 -                  + " skip=" + str(file_idx)
   4.817 -                  + " seek=" + str(part_extent_no * extent_size)
   4.818 -                  + " count=" + str(min(extent_size, size_sectors - file_idx))
   4.819 -                  + " > /dev/null")
   4.820 -
   4.821 -        return extent_size
   4.822 -
   4.823 -    for i in extents:
   4.824 -        file_idx += write_extent_to_vd(i, file_idx, filename)
   4.825 -
   4.826 -    cx.close()
   4.827 -
   4.828 -    return vdisk_id
   4.829 -    
   4.830 -
   4.831 -
   4.832 -
   4.833 -def vd_extents_validate(new_extents, new_writeable, safety=VBD_SAFETY_RR):
   4.834 -    """Validate the extents against the existing extents.
   4.835 -    Complains if the list supplied clashes against the extents that
   4.836 -    are already in use in the system.
   4.837 -    new_extents [list of dicts]: list of new extents, as dicts
   4.838 -    new_writeable [int]: 1 if they are to be writeable, 0 otherwise
   4.839 -    returns [int]: either the expertise level of the mapping if it doesn't
   4.840 -                   exceed VBD_EXPERT_MODE or -1 if it does (error)
   4.841 -    """
   4.842 -
   4.843 -    import Xc # this is only needed in this function
   4.844 -
   4.845 -    xc = Xc.new()
   4.846 -
   4.847 -    ##### Probe for explicitly created virtual disks and build a list
   4.848 -    ##### of extents for comparison with the ones that are being added
   4.849 -
   4.850 -    probe = xc.vbd_probe()
   4.851 -
   4.852 -    old_extents = [] # this will hold a list of all existing extents and
   4.853 -                     # their writeable status, as a list of (device,
   4.854 -                     # start, size, writeable?) tuples
   4.855 -
   4.856 -    for vbd in probe:
   4.857 -        this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd'])
   4.858 -        for vbd_ext in this_vbd_extents:
   4.859 -            vbd_ext['writeable'] = vbd['writeable']
   4.860 -            old_extents.append(vbd_ext)
   4.861 -            
   4.862 -    ##### Now scan /proc/mounts for compile a list of extents corresponding to
   4.863 -    ##### any devices mounted in DOM0.  This list is added on to old_extents
   4.864 -
   4.865 -    regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
   4.866 -    fd = open('/proc/mounts', "r")
   4.867 -
   4.868 -    while True:
   4.869 -        line = readline(fd)
   4.870 -        if not line: # if we've run out of lines then stop reading
   4.871 -            break
   4.872 -        
   4.873 -        m = regexp.match(line)
   4.874 -
   4.875 -        # if the regexp didn't match then it's probably a line we don't
   4.876 -        # care about - skip to next line
   4.877 -        if not m:
   4.878 -            continue
   4.879 -
   4.880 -        # lookup the device
   4.881 -        ext_list = lookup_raw_partn(m.group(1))
   4.882 -
   4.883 -        # if lookup failed, skip to next mounted device
   4.884 -        if not ext_list:
   4.885 -            continue
   4.886 -
   4.887 -        # set a writeable flag as appropriate
   4.888 -        for ext in ext_list:
   4.889 -            ext['writeable'] = m.group(2) == 'rw'
   4.890 -
   4.891 -        # now we've got here, the contents of ext_list are in a
   4.892 -        # suitable format to be added onto the old_extents list, ready
   4.893 -        # for checking against the new extents
   4.894 -
   4.895 -        old_extents.extend(ext_list)
   4.896 -
   4.897 -    fd.close() # close /proc/mounts
   4.898 -
   4.899 -    ##### By this point, old_extents contains a list of extents, in
   4.900 -    ##### dictionary format corresponding to every extent of physical
   4.901 -    ##### disk that's either part of an explicitly created VBD, or is
   4.902 -    ##### mounted under DOM0.  We now check these extents against the
   4.903 -    ##### proposed additions in new_extents, to see if a conflict will
   4.904 -    ##### happen if they are added with write status new_writeable
   4.905 -
   4.906 -    level = 0 # this'll accumulate the max warning level
   4.907 -
   4.908 -    # Search for clashes between the new extents and the old ones
   4.909 -    # Takes time O(len(new_extents) * len(old_extents))
   4.910 -    for new_ext in new_extents:
   4.911 -        for old_ext in old_extents:
   4.912 -            if(new_ext['device'] == old_ext['device']):
   4.913 -
   4.914 -                new_ext_start = new_ext['start_sector']
   4.915 -                new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1
   4.916 -                
   4.917 -                old_ext_start = old_ext['start_sector']
   4.918 -                old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1
   4.919 -                
   4.920 -                if((old_ext_start <= new_ext_start <= old_ext_end) or
   4.921 -                   (old_ext_start <= new_ext_end <= old_ext_end)):
   4.922 -                    if (not old_ext['writeable']) and new_writeable:
   4.923 -                        level = max(1,level)
   4.924 -                    elif old_ext['writeable'] and (not new_writeable):
   4.925 -                        level = max(1,level)
   4.926 -                    elif old_ext['writeable'] and new_writeable:
   4.927 -                        level = max(2,level)
   4.928 -
   4.929 -
   4.930 -    ##### level now holds the warning level incurred by the current
   4.931 -    ##### VBD setup and we complain appropriately to the user
   4.932 -
   4.933 -
   4.934 -    if level == 1:
   4.935 -        print >> sys.stderr, """Warning: one or more hard disk extents
   4.936 -         writeable by one domain are also readable by another."""
   4.937 -    elif level == 2:
   4.938 -        print >> sys.stderr, """Warning: one or more hard disk extents are
   4.939 -         writeable by two or more domains simultaneously."""
   4.940 -
   4.941 -    if level > safety:
   4.942 -        print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed
   4.943 -        at the current safety level (%d).""" % safety
   4.944 -        level = -1
   4.945 -
   4.946 -    return level
   4.947 -
     5.1 --- a/tools/xenctl/setup.py	Wed Jun 16 13:26:31 2004 +0000
     5.2 +++ b/tools/xenctl/setup.py	Wed Jun 16 13:30:35 2004 +0000
     5.3 @@ -2,7 +2,7 @@
     5.4  from distutils.core import setup, Extension
     5.5  import sys
     5.6  
     5.7 -modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' , 'xenctl.vdisk' ]
     5.8 +modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' ]
     5.9  
    5.10  # We need the 'tempfile' module from Python 2.3. We install this ourselves
    5.11  # if the installed Python is older than 2.3.
     6.1 --- a/tools/xenmgr/lib/XendDomain.py	Wed Jun 16 13:26:31 2004 +0000
     6.2 +++ b/tools/xenmgr/lib/XendDomain.py	Wed Jun 16 13:30:35 2004 +0000
     6.3 @@ -49,18 +49,28 @@ class XendDomain:
     6.4      def initial_refresh(self):
     6.5          """Refresh initial domain info from domain_db.
     6.6          """
     6.7 +        print "initial_refresh> db=", self.domain_db.values()
     6.8          domlist = xc.domain_getinfo()
     6.9 +        print "doms=", domlist
    6.10          doms = {}
    6.11          for d in domlist:
    6.12              domid = str(d['dom'])
    6.13              doms[domid] = d
    6.14          for config in self.domain_db.values():
    6.15              domid = int(sxp.child_value(config, 'id'))
    6.16 +            print "dom=", domid, "config=", config
    6.17              if domid in doms:
    6.18 +                print "dom=", domid, "new"
    6.19                  self._new_domain(config)
    6.20              else:
    6.21 +                print "dom=", domid, "del"
    6.22                  self._delete_domain(domid)
    6.23 +        print "doms:"
    6.24 +        for d in self.domain.values(): print d
    6.25 +        print "refresh..."
    6.26          self.refresh()
    6.27 +        print "doms:"
    6.28 +        for d in self.domain.values(): print d
    6.29  
    6.30      def sync(self):
    6.31          """Sync domain db to disk.
    6.32 @@ -132,7 +142,7 @@ class XendDomain:
    6.33                  image = None
    6.34                  newinfo = XendDomainInfo.XendDomainInfo(
    6.35                      config, d['dom'], d['name'], d['mem_kb']/1024, image)
    6.36 -                self._add_domain(id, newinfo)
    6.37 +                self._add_domain(newinfo.id, newinfo)
    6.38          # Remove entries for domains that no longer exist.
    6.39          for d in self.domain.values():
    6.40              dominfo = doms.get(d.id)
    6.41 @@ -319,18 +329,18 @@ class XendDomain:
    6.42                  return v
    6.43          return None
    6.44  
    6.45 -    def domain_vbd_add(self, dom, uname, dev, mode):
    6.46 -        dom = int(dom)
    6.47 -        vbd = vm.make_disk(dom, uname, dev, mode)
    6.48 -        return vbd
    6.49 +##     def domain_vbd_add(self, dom, uname, dev, mode):
    6.50 +##         dom = int(dom)
    6.51 +##         vbd = vm.make_disk(dom, uname, dev, mode)
    6.52 +##         return vbd
    6.53  
    6.54 -    def domain_vbd_remove(self, dom, dev):
    6.55 -        dom = int(dom)
    6.56 -        vbd = xenctl.vdisk.blkdev_name_to_number(dev)
    6.57 -        if vbd < 0: return vbd
    6.58 -        err = xc.vbd_destroy(dom, vbd)
    6.59 -        if err < 0: return err
    6.60 -        return vbd
    6.61 +##     def domain_vbd_remove(self, dom, dev):
    6.62 +##         dom = int(dom)
    6.63 +##         vbd = xenctl.vdisk.blkdev_name_to_number(dev)
    6.64 +##         if vbd < 0: return vbd
    6.65 +##         err = xc.vbd_destroy(dom, vbd)
    6.66 +##         if err < 0: return err
    6.67 +##         return vbd
    6.68  
    6.69      def domain_shadow_control(self, dom, op):
    6.70          dom = int(dom)
     7.1 --- a/tools/xenmgr/lib/XendDomainInfo.py	Wed Jun 16 13:26:31 2004 +0000
     7.2 +++ b/tools/xenmgr/lib/XendDomainInfo.py	Wed Jun 16 13:30:35 2004 +0000
     7.3 @@ -9,6 +9,8 @@ Author: Mike Wray <mike.wray@hpl.hp.com>
     7.4  
     7.5  """
     7.6  
     7.7 +import string
     7.8 +import re
     7.9  import sys
    7.10  import os
    7.11  
    7.12 @@ -17,7 +19,6 @@ from twisted.internet import defer
    7.13  import Xc; xc = Xc.new()
    7.14  
    7.15  import xenctl.ip
    7.16 -import xenctl.vdisk
    7.17  
    7.18  import sxp
    7.19  
    7.20 @@ -27,6 +28,24 @@ xendConsole = XendConsole.instance()
    7.21  import server.SrvConsoleServer
    7.22  xend = server.SrvConsoleServer.instance()
    7.23  
    7.24 +def readlines(fd):
    7.25 +    """Version of readlines safe against EINTR.
    7.26 +    """
    7.27 +    import errno
    7.28 +    
    7.29 +    lines = []
    7.30 +    while 1:
    7.31 +        try:
    7.32 +            line = fd.readline()
    7.33 +        except IOError, ex:
    7.34 +            if ex.errno == errno.EINTR:
    7.35 +                continue
    7.36 +            else:
    7.37 +                raise
    7.38 +        if line == '': break
    7.39 +        lines.append(line)
    7.40 +    return lines
    7.41 +
    7.42  class VmError(ValueError):
    7.43      """Vm construction error."""
    7.44  
    7.45 @@ -60,6 +79,7 @@ class XendDomainInfo:
    7.46          self.devices = {}
    7.47          self.configs = []
    7.48          self.info = None
    7.49 +        self.ipaddrs = []
    7.50  
    7.51          #todo: state: running, suspended
    7.52          self.state = 'running'
    7.53 @@ -127,6 +147,12 @@ class XendDomainInfo:
    7.54          return sxp.child_with_id(self.get_devices(type), id)
    7.55  
    7.56      def get_device_by_index(self, type, idx):
    7.57 +        """Get the device with the given index.
    7.58 +
    7.59 +        idx       device index
    7.60 +
    7.61 +        returns  device or None
    7.62 +        """
    7.63          dl = self.get_devices(type)
    7.64          if 0 <= idx < len(dl):
    7.65              return dl[idx]
    7.66 @@ -163,48 +189,81 @@ class XendDomainInfo:
    7.67              print
    7.68          print "]"
    7.69  
    7.70 -def safety_level(sharing):
    7.71 -    if sharing == 'rw':
    7.72 -        return xenctl.vdisk.VBD_SAFETY_RW
    7.73 -    if sharing == 'ww':
    7.74 -        return xenctl.vdisk.VBD_SAFETY_WW
    7.75 -    return xenctl.vdisk.VBD_SAFETY_RR
    7.76 +def blkdev_name_to_number(name):
    7.77 +    """Take the given textual block-device name (e.g., '/dev/sda1',
    7.78 +    'hda') and return the device number used by the OS. """
    7.79 +
    7.80 +    if not re.match( '/dev/', name ):
    7.81 +        name = '/dev/' + name
    7.82 +        
    7.83 +    return os.stat(name).st_rdev
    7.84  
    7.85 +def lookup_raw_partn(partition):
    7.86 +    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
    7.87 +    and return a dictionary { device, start_sector,
    7.88 +    nr_sectors, type }
    7.89 +        device:       Device number of the given partition
    7.90 +        start_sector: Index of first sector of the partition
    7.91 +        nr_sectors:   Number of sectors comprising this partition
    7.92 +        type:         'Disk' or identifying name for partition type
    7.93 +    """
    7.94 +
    7.95 +    if not re.match( '/dev/', partition ):
    7.96 +        partition = '/dev/' + partition
    7.97 +
    7.98 +    drive = re.split( '[0-9]', partition )[0]
    7.99  
   7.100 -def make_disk_old(dom, uname, dev, mode, sharing):
   7.101 -    writeable = ('w' in mode)
   7.102 -    safety = safety_level(sharing)
   7.103 -    vbd = xenctl.vdisk.blkdev_name_to_number(dev)
   7.104 -    extents = xenctl.vdisk.lookup_disk_uname(uname)
   7.105 -    if not extents:
   7.106 -        raise VmError("vbd: Extents not found: uname=%s" % uname)
   7.107 +    if drive == partition:
   7.108 +        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
   7.109 +        line = readline(fd)
   7.110 +        if line:
   7.111 +            return [ { 'device' : blkdev_name_to_number(drive),
   7.112 +                       'start_sector' : long(0),
   7.113 +                       'nr_sectors' : long(line) * 2,
   7.114 +                       'type' : 'Disk' } ]
   7.115 +        return None
   7.116 +
   7.117 +    # determine position on disk
   7.118 +    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
   7.119  
   7.120 -    # check that setting up this VBD won't violate the sharing
   7.121 -    # allowed by the current VBD expertise level
   7.122 -    if xenctl.vdisk.vd_extents_validate(extents, writeable, safety=safety) < 0:
   7.123 -        raise VmError("vbd: Extents invalid: uname=%s" % uname)
   7.124 -            
   7.125 -    if xc.vbd_create(dom=dom, vbd=vbd, writeable=writeable):
   7.126 -        raise VmError("vbd: Creating device failed: dom=%d uname=%s vbd=%d mode=%s"
   7.127 -                      % (dom, uname, vbdmode))
   7.128 +    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
   7.129 +    lines = readlines(fd)
   7.130 +    for line in lines:
   7.131 +        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
   7.132 +                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
   7.133 +        if m:
   7.134 +            return [ { 'device' : blkdev_name_to_number(drive),
   7.135 +                       'start_sector' : long(m.group(1)),
   7.136 +                       'nr_sectors' : long(m.group(2)),
   7.137 +                       'type' : m.group(3) } ]
   7.138 +    
   7.139 +    return None
   7.140  
   7.141 -    if xc.vbd_setextents(dom=dom, vbd=vbd, extents=extents):
   7.142 -        raise VMError("vbd: Setting extents failed: dom=%d uname=%s vbd=%d"
   7.143 -                      % (dom, uname, vbd))
   7.144 -    return vbd
   7.145 +def lookup_disk_uname( uname ):
   7.146 +    """Lookup a list of segments for a physical device.
   7.147 +    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
   7.148 +    returns [list of dicts]: list of extents that make up the named device
   7.149 +    """
   7.150 +    ( type, d_name ) = string.split( uname, ':' )
   7.151 +
   7.152 +    if type == "phy":
   7.153 +        segments = lookup_raw_partn( d_name )
   7.154 +    else:
   7.155 +        segments = None
   7.156 +    return segments
   7.157  
   7.158  def make_disk(dom, uname, dev, mode, sharing):
   7.159      """Create a virtual disk device for a domain.
   7.160  
   7.161      @returns Deferred
   7.162      """
   7.163 -    segments = xenctl.vdisk.lookup_disk_uname(uname)
   7.164 +    segments = lookup_disk_uname(uname)
   7.165      if not segments:
   7.166          raise VmError("vbd: Segments not found: uname=%s" % uname)
   7.167      if len(segments) > 1:
   7.168          raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
   7.169      segment = segments[0]
   7.170 -    vdev = xenctl.vdisk.blkdev_name_to_number(dev)
   7.171 +    vdev = blkdev_name_to_number(dev)
   7.172      ctrl = xend.blkif_create(dom)
   7.173      
   7.174      def fn(ctrl):
   7.175 @@ -212,13 +271,6 @@ def make_disk(dom, uname, dev, mode, sha
   7.176      ctrl.addCallback(fn)
   7.177      return ctrl
   7.178          
   7.179 -def make_vif_old(dom, vif, vmac, vnet):
   7.180 -    return # todo: Not supported yet.
   7.181 -    err = xc.vif_setinfo(dom=dom, vif=vif, vmac=vmac, vnet=vnet)
   7.182 -    if err < 0:
   7.183 -        raise VmError('vnet: Error %d setting vif mac dom=%d vif=%d vmac=%s vnet=%d' %
   7.184 -                        (err, dom, vif, vmac, vnet))
   7.185 -
   7.186  def make_vif(dom, vif, vmac):
   7.187      """Create a virtual network device for a domain.
   7.188  
   7.189 @@ -230,8 +282,10 @@ def make_vif(dom, vif, vmac):
   7.190      return d
   7.191  
   7.192  def vif_up(iplist):
   7.193 -    #todo: Need a better way.
   7.194 -    # send an unsolicited ARP reply for all non link-local IPs
   7.195 +    """send an unsolicited ARP reply for all non link-local IP addresses.
   7.196 +
   7.197 +    iplist IP addresses
   7.198 +    """
   7.199  
   7.200      IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
   7.201      
   7.202 @@ -260,6 +314,18 @@ def vif_up(iplist):
   7.203          if not nlb: set_ip_nonlocal_bind(0)
   7.204  
   7.205  def xen_domain_create(config, ostype, name, memory, kernel, ramdisk, cmdline, vifs_n):
   7.206 +    """Create a domain. Builds the image but does not configure it.
   7.207 +
   7.208 +    config  configuration
   7.209 +    ostype  OS type
   7.210 +    name    domain name
   7.211 +    memory  domain memory (MB)
   7.212 +    kernel  kernel image
   7.213 +    ramdisk kernel ramdisk
   7.214 +    cmdline kernel commandline
   7.215 +    vifs_n  number of network interfaces
   7.216 +    returns vm
   7.217 +    """
   7.218      if not os.path.isfile(kernel):
   7.219          raise VmError('Kernel image does not exist: %s' % kernel)
   7.220      if ramdisk and not os.path.isfile(ramdisk):
   7.221 @@ -380,11 +446,22 @@ def vm_create(config):
   7.222      return deferred
   7.223  
   7.224  def vm_restore(src, config, progress=0):
   7.225 +    """Restore a VM.
   7.226 +
   7.227 +    src      saved state to restore
   7.228 +    config   configuration
   7.229 +    progress progress reporting flag
   7.230 +    returns  deferred
   7.231 +    raises   VmError for invalid configuration
   7.232 +    """
   7.233      ostype = "linux" #todo set from config
   7.234      restorefn = getattr(xc, "%s_restore" % ostype)
   7.235      dom = restorefn(state_file=src, progress=progress)
   7.236      if dom < 0: return dom
   7.237      deferred = dom_configure(dom, config)
   7.238 +    def vifs_cb(val, vm):
   7.239 +        vif_up(vm.ipaddrs)
   7.240 +    deferred.addCallback(vifs_cb, vm)
   7.241      return deferred
   7.242      
   7.243  def dom_get(dom):
   7.244 @@ -394,6 +471,12 @@ def dom_get(dom):
   7.245      return None
   7.246      
   7.247  def dom_configure(dom, config):
   7.248 +    """Configure a domain.
   7.249 +
   7.250 +    dom    domain id
   7.251 +    config configuration
   7.252 +    returns deferred
   7.253 +    """
   7.254      d = dom_get(dom)
   7.255      if not d:
   7.256          raise VMError("Domain not found: %d" % dom)
   7.257 @@ -628,6 +711,7 @@ def vm_field_vfr(vm, config, val, index)
   7.258      # Get the rules and add them.
   7.259      # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
   7.260      list = sxp.children(val, 'vif')
   7.261 +    ipaddrs = []
   7.262      for v in list:
   7.263          id = sxp.child_value(v, 'id')
   7.264          if id is None:
   7.265 @@ -640,9 +724,11 @@ def vm_field_vfr(vm, config, val, index)
   7.266          ip = sxp.child_value(v, 'ip')
   7.267          if not ip:
   7.268              raise VmError('vfr: missing ip address')
   7.269 +        ipaddrs.append(ip);
   7.270          #Don't do this in new i/o model.
   7.271          #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
   7.272          #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
   7.273 +    vm.ipaddrs = ipaddrs
   7.274  
   7.275  def vnet_bridge(vnet, vmac, dom, idx):
   7.276      """Add the device for the vif to the bridge for its vnet.
     8.1 --- a/tools/xenmgr/lib/XendVdisk.py	Wed Jun 16 13:26:31 2004 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,111 +0,0 @@
     8.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     8.5 -
     8.6 -"""Handler for vdisk operations.
     8.7 -
     8.8 -"""
     8.9 -
    8.10 -import os
    8.11 -import os.path
    8.12 -
    8.13 -from xenctl import vdisk
    8.14 -    
    8.15 -import sxp
    8.16 -
    8.17 -class XendVdiskInfo:
    8.18 -
    8.19 -    def __init__(self, info):
    8.20 -        self.info = info
    8.21 -        self.id = info['vdisk_id']
    8.22 -
    8.23 -    def __str__(self):
    8.24 -        return ("vdisk id=%(vdisk_id)s size=%(size)d expires=%(expires)d expiry_time=%(expiry_time)d"
    8.25 -                % self.info)
    8.26 -
    8.27 -    def sxpr(self):
    8.28 -        val = ['vdisk']
    8.29 -        for (k,v) in self.info.items():
    8.30 -            val.append([k, str(v)])
    8.31 -        return val     
    8.32 -
    8.33 -class XendVdisk:
    8.34 -    """Index of all vdisks. Singleton.
    8.35 -    """
    8.36 -
    8.37 -    dbpath = "vdisk"
    8.38 -
    8.39 -    def __init__(self):
    8.40 -        # Table of vdisk info indexed by vdisk id.
    8.41 -        self.vdisk = {}
    8.42 -        if not os.path.isfile(vdisk.VD_DB_FILE):
    8.43 -            vdisk.vd_init_db(vdisk.VD_DB_FILE)
    8.44 -        self.vdisk_refresh()
    8.45 -
    8.46 -    def vdisk_refresh(self):
    8.47 -        # vdisk = {vdisk_id, size, expires, expiry_time}
    8.48 -        try:
    8.49 -            vdisks = vdisk.vd_list()
    8.50 -        except:
    8.51 -            vdisks = []
    8.52 -        for vdisk in vdisks:
    8.53 -            vdiskinfo = XendVdiskInfo(vdisk)
    8.54 -            self.vdisk[vdiskinfo.id] = vdiskinfo
    8.55 -
    8.56 -    def vdisk_ls(self):
    8.57 -        """List all vdisk ids.
    8.58 -        """
    8.59 -        return self.vdisk.keys()
    8.60 -
    8.61 -    def vdisks(self):
    8.62 -        return self.vdisk.values()
    8.63 -    
    8.64 -    def vdisk_get(self, id):
    8.65 -        """Get a vdisk.
    8.66 -
    8.67 -        id	vdisk id
    8.68 -        """
    8.69 -        return self.vdisk.get(id)
    8.70 -
    8.71 -    def vdisk_create(self, info):
    8.72 -        """Create a vdisk.
    8.73 -
    8.74 -        info	config
    8.75 -        """
    8.76 -        # Need to configure for real.
    8.77 -        # vdisk.vd_create(size, expiry)
    8.78 -
    8.79 -    def vdisk_configure(self, info):
    8.80 -        """Configure a vdisk.
    8.81 -        id	vdisk id
    8.82 -        info	config
    8.83 -        """
    8.84 -        # Need to configure for real.
    8.85 -        # Make bigger: vdisk.vd_enlarge(id, extra_size)
    8.86 -        # Update expiry time: vdisk.vd_refresh(id, expiry)
    8.87 -        # Try to recover an expired vdisk : vdisk.vd_undelete(id, expiry)
    8.88 -        
    8.89 -
    8.90 -    def vdisk_delete(self, id):
    8.91 -        """Delete a vdisk.
    8.92 -
    8.93 -        id	vdisk id
    8.94 -        """
    8.95 -        # Need to delete vdisk for real. What if fails?
    8.96 -        del self.vdisk[id]
    8.97 -        vdisk.vd_delete(id)
    8.98 -
    8.99 -    # def vdisk_copy: copy contents to file, vdisk still exists
   8.100 -    # def vdisk_export: copy contents to file then delete the vdisk 
   8.101 -    # def vdisk_import: create a vdisk from a file
   8.102 -    # def vdisk_space: space left for new vdisks
   8.103 -
   8.104 -    # def vdisk_recover: recover an expired vdisk
   8.105 -
   8.106 -    # def vdisk_init_partition: setup a physical partition for vdisks
   8.107 -
   8.108 -def instance():
   8.109 -    global inst
   8.110 -    try:
   8.111 -        inst
   8.112 -    except:
   8.113 -        inst = XendVdisk()
   8.114 -    return inst
     9.1 --- a/tools/xenmgr/lib/server/SrvRoot.py	Wed Jun 16 13:26:31 2004 +0000
     9.2 +++ b/tools/xenmgr/lib/server/SrvRoot.py	Wed Jun 16 13:30:35 2004 +0000
     9.3 @@ -17,7 +17,6 @@ class SrvRoot(SrvDir):
     9.4          ('domain',  'SrvDomainDir'  ),
     9.5          ('console', 'SrvConsoleDir' ),
     9.6          ('event',   'SrvEventDir'   ),
     9.7 -        ('vdisk',   'SrvVdiskDir'   ),
     9.8          ('device',  'SrvDeviceDir'  ),
     9.9          ('vnet',    'SrvVnetDir'    ),
    9.10          ]
    10.1 --- a/tools/xenmgr/lib/server/SrvVdisk.py	Wed Jun 16 13:26:31 2004 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,12 +0,0 @@
    10.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    10.5 -
    10.6 -from xenmgr import XendVdisk
    10.7 -from SrvVdiskDir import SrvVdiskDir
    10.8 -
    10.9 -class SrvVdisk(SrvDir):
   10.10 -    """A virtual disk.
   10.11 -    """
   10.12 -
   10.13 -    def __init__(self):
   10.14 -        SrvDir.__init__(self)
   10.15 -        self.xvdisk = XendVdisk.instance()
    11.1 --- a/tools/xenmgr/lib/server/SrvVdiskDir.py	Wed Jun 16 13:26:31 2004 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,28 +0,0 @@
    11.4 -# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    11.5 -
    11.6 -from xenmgr import XendVdisk
    11.7 -from SrvDir import SrvDir
    11.8 -
    11.9 -class SrvVdiskDir(SrvDir):
   11.10 -    """Virtual disk directory.
   11.11 -    """
   11.12 -
   11.13 -    def __init__(self):
   11.14 -        SrvDir.__init__(self)
   11.15 -        self.xvdisk = XendVdisk.instance()
   11.16 -
   11.17 -    def vdisk(self, x):
   11.18 -        val = None
   11.19 -        try:
   11.20 -            dom = self.xvdisk.vdisk_get(x)
   11.21 -            val = SrvVdisk(dom)
   11.22 -        except KeyError:
   11.23 -            pass
   11.24 -        return val
   11.25 -
   11.26 -    def get(self, x):
   11.27 -        v = SrvDir.get(self, x)
   11.28 -        if v is not None:
   11.29 -            return v
   11.30 -        v = self.vdisk(x)
   11.31 -        return v