ia64/xen-unstable

changeset 1594:c8e677f40f9d

bitkeeper revision 1.1010.1.10 (40dfd40bszbCgYF9OJJKWOo1n7X8hw)

Rename xenctl, move things around.
author mjw@wray-m-3.hpl.hp.com
date Mon Jun 28 08:17:15 2004 +0000 (2004-06-28)
parents cb0967db88bc
children 3d3f21585b96 7fc121a3c8a0
files .rootkeys tools/Makefile tools/examples/xc_physinfo.py tools/examples/xm_dom_control.py tools/examples/xmdefaults tools/examples/xmnetbsd tools/xen/lib/ext/__init__.py tools/xen/lib/util/__init__.py tools/xen/lib/util/console_client.py tools/xen/lib/util/ip.py tools/xen/lib/util/tempfile.py tools/xen/lib/xm/main.py tools/xen/setup.py tools/xenctl/Makefile tools/xenctl/lib/__init__.py tools/xenctl/lib/console_client.py tools/xenctl/lib/ip.py tools/xenctl/lib/tempfile.py tools/xenctl/lib/utils.py tools/xenctl/setup.py tools/xu/Makefile
line diff
     1.1 --- a/.rootkeys	Fri Jun 25 15:10:48 2004 +0000
     1.2 +++ b/.rootkeys	Mon Jun 28 08:17:15 2004 +0000
     1.3 @@ -162,10 +162,9 @@ 40278d94cIUWl2eRgnwZtr4hTyWT1Q tools/exa
     1.4  40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
     1.5  401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
     1.6  401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
     1.7 -403b7cf7J7FsSSoEPGhx6gXR4pIdZg tools/examples/xc_physinfo.py
     1.8 -40c9c4684Wfg8VgMKtRFa_ULi2e_tQ tools/examples/xm_dom_control.py
     1.9  40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
    1.10  40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
    1.11 +40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
    1.12  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.13  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.14  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.15 @@ -200,6 +199,11 @@ 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/
    1.16  3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
    1.17  40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
    1.18  40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
    1.19 +40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
    1.20 +40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
    1.21 +4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
    1.22 +40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
    1.23 +4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xen/lib/util/tempfile.py
    1.24  40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
    1.25  40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
    1.26  40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
    1.27 @@ -250,13 +254,6 @@ 40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xen
    1.28  40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
    1.29  40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
    1.30  40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
    1.31 -4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
    1.32 -4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
    1.33 -4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
    1.34 -40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xenctl/lib/ip.py
    1.35 -4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
    1.36 -3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
    1.37 -4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
    1.38  40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
    1.39  4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
    1.40  4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
    1.41 @@ -274,6 +271,7 @@ 4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xen
    1.42  403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
    1.43  403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
    1.44  4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
    1.45 +40dfd40a0QtsSGigB9TCpVGWZmhlNA tools/xu/Makefile
    1.46  40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
    1.47  40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
    1.48  40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
     2.1 --- a/tools/Makefile	Fri Jun 25 15:10:48 2004 +0000
     2.2 +++ b/tools/Makefile	Mon Jun 28 08:17:15 2004 +0000
     2.3 @@ -5,17 +5,14 @@ all:
     2.4  	$(MAKE) -C misc
     2.5  	$(MAKE) -C examples
     2.6  	$(MAKE) -C xentrace
     2.7 -	$(MAKE) -C xenctl
     2.8  	$(MAKE) -C xen
     2.9  
    2.10  install: all
    2.11  	$(MAKE) -C xc install
    2.12  	$(MAKE) -C xu install
    2.13  	$(MAKE) -C misc install
    2.14 -	$(MAKE) -C xenctl install
    2.15  	$(MAKE) -C examples install
    2.16  	$(MAKE) -C xentrace install
    2.17 -	$(MAKE) -C xenctl install
    2.18  	$(MAKE) -C xen install
    2.19  
    2.20  dist: $(TARGET)
    2.21 @@ -28,6 +25,5 @@ clean:
    2.22  	$(MAKE) -C misc clean
    2.23  	$(MAKE) -C examples clean
    2.24  	$(MAKE) -C xentrace clean
    2.25 -	$(MAKE) -C xenctl clean
    2.26  	$(MAKE) -C xen clean
    2.27  
     3.1 --- a/tools/examples/xc_physinfo.py	Fri Jun 25 15:10:48 2004 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,20 +0,0 @@
     3.4 -#!/usr/bin/env python
     3.5 -
     3.6 -# Get information about the physical host machine
     3.7 -
     3.8 -import Xc
     3.9 -
    3.10 -xc = Xc.new()
    3.11 -
    3.12 -info = xc.physinfo()
    3.13 -
    3.14 -fmt_info = [ ( 'CPU cores', info['cores']),
    3.15 -             ('Hyperthreads per core', info['ht_per_core']),
    3.16 -             ('CPU Speed (MHz)', info['cpu_khz'] / 1000),
    3.17 -             ('Total physical mem (MB)', info['total_pages'] / 256),
    3.18 -             ('Free physical mem (MB)', info['free_pages'] / 256) ]
    3.19 -      
    3.20 -
    3.21 -for (item, val) in fmt_info:
    3.22 -    print "%-23s" % item, ':', val
    3.23 -
     4.1 --- a/tools/examples/xm_dom_control.py	Fri Jun 25 15:10:48 2004 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,235 +0,0 @@
     4.4 -#!/usr/bin/env python
     4.5 -
     4.6 -import sys
     4.7 -import re
     4.8 -import string
     4.9 -import time
    4.10 -import os
    4.11 -import os.path
    4.12 -import signal
    4.13 -
    4.14 -from xenmgr import sxp
    4.15 -from xenmgr.XendClient import server
    4.16 -
    4.17 -# usage: xc_dom_control [command] <params>
    4.18 -#
    4.19 -# this script isn't very smart, but it'll do for now.
    4.20 -#
    4.21 -
    4.22 -def usage (rc=0):
    4.23 -    if rc:
    4.24 -        out = sys.stderr
    4.25 -    else:
    4.26 -        out = sys.stdout
    4.27 -    print >> out, """
    4.28 -Usage: %s [command] <params>
    4.29 -
    4.30 -  help                   -- print usage
    4.31 -  pause     [dom]        -- pause a domain
    4.32 -  unpause   [dom]        -- un-pause a domain
    4.33 -  shutdown  [dom] [[-w]] -- request a domain to shutdown (can specify 'all')
    4.34 -                            (optionally wait for complete shutdown)
    4.35 -  destroy   [dom]        -- immediately terminate a domain
    4.36 -  pincpu    [dom] [cpu]  -- pin a domain to the specified CPU
    4.37 -  suspend   [dom] [file] -- write domain's memory to a file and terminate
    4.38 -			    (resume by re-running xc_dom_create with -L option)
    4.39 -  unwatch   [dom]        -- kill the auto-restart daemon for a domain
    4.40 -  list                   -- print info about all domains
    4.41 -  listvbds               -- print info about all virtual block devs
    4.42 -  cpu_bvtset [dom] [mcuadv] [warp] [warpl] [warpu]
    4.43 -                         -- set BVT scheduling parameters for domain
    4.44 -  cpu_bvtslice [slice]   -- set default BVT scheduler slice
    4.45 -  cpu_atropos_set [dom] [period] [slice] [latency] [xtratime]
    4.46 -                         -- set Atropos scheduling parameters for domain
    4.47 -  cpu_rrobin_slice [slice] -- set Round Robin scheduler slice
    4.48 -  vif_stats [dom] [vif]  -- get stats for a given network vif
    4.49 -  vif_addip [dom] [vif] [ip]  -- add an IP address to a given vif
    4.50 -  vif_setsched [dom] [vif] [bytes] [usecs] -- rate limit vif bandwidth
    4.51 -  vif_getsched [dom] [vif] -- print vif's scheduling parameters
    4.52 -  vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to 
    4.53 -                            domain as dev e.g. 'vbd_add 2 phy:sda3 hda1 w'
    4.54 -  vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' 
    4.55 -""" % sys.argv[0]
    4.56 -    if rc: sys.exit(rc)
    4.57 -
    4.58 -if len(sys.argv) < 2: usage(1)
    4.59 -cmd = sys.argv[1]
    4.60 -
    4.61 -#todo: replace all uses of xc with the new api.
    4.62 -import Xc; xc = Xc.new()
    4.63 -
    4.64 -rc = ''
    4.65 -dom = None
    4.66 -
    4.67 -
    4.68 -def auto_restart_pid_file(dom):
    4.69 -    # The auto-restart daemon's pid file.
    4.70 -    return '/var/run/xendomains/%d.pid' % dom
    4.71 -
    4.72 -def auto_restart_pid(dom):
    4.73 -    watcher = auto_restart_pid_file(dom)
    4.74 -    if os.path.isfile(watcher):
    4.75 -        fd = open(watcher,'r')
    4.76 -        pid = int(fd.readline())
    4.77 -    else:
    4.78 -        pid = None
    4.79 -    return pid
    4.80 - 
    4.81 -def auto_restart_kill(dom):
    4.82 -    #todo: replace this - tell xend not to restart any more.
    4.83 -    # Kill a domain's auto restart daemon.
    4.84 -    pid = auto_restart_pid(dom)
    4.85 -    if pid:
    4.86 -        os.kill(pid, signal.SIGTERM)
    4.87 -
    4.88 -
    4.89 -if len( sys.argv ) > 2 and re.match('\d+$', sys.argv[2]):
    4.90 -    dom = long(sys.argv[2])
    4.91 -
    4.92 -if cmd == "help":
    4.93 -    usage()
    4.94 -    
    4.95 -elif cmd == 'pause':
    4.96 -    rc = server.xend_domain_pause(dom)
    4.97 -
    4.98 -elif cmd == 'unpause':
    4.99 -    rc = server.xend_domain_unpause(dom)    
   4.100 -
   4.101 -elif cmd == 'shutdown':
   4.102 -    doms = []
   4.103 -    shutdown = []
   4.104 -    if dom != None:
   4.105 -        doms = [ dom ]
   4.106 -    elif sys.argv[2] == 'all':
   4.107 -        doms = server.xend_domains()
   4.108 -        doms.remove('0')
   4.109 -    for d in doms:
   4.110 -        ret = server.xend_domain_shutdown(d)
   4.111 -        if ret == 0:
   4.112 -            shutdown.append(d)
   4.113 -        else:
   4.114 -            rc = ret
   4.115 -
   4.116 -    wait = (len(sys.argv) == 4 and sys.argv[3] == "-w")
   4.117 -    if wait:
   4.118 -        # wait for all domains we shut down to terminate
   4.119 -        for dom in shutdown:
   4.120 -            while True:
   4.121 -                info = server.xend_domain(dom)
   4.122 -                if not info: break
   4.123 -                time.sleep(1)
   4.124 -
   4.125 -elif cmd == 'destroy':
   4.126 -    rc = server.xend_domain_halt(dom)    
   4.127 -
   4.128 -elif cmd == 'pincpu':
   4.129 -    if len(sys.argv) < 4: usage(1)
   4.130 -    cpu = int(sys.argv[3])
   4.131 -    rc = server.xend_domain_pincpu(dom, cpu)
   4.132 -
   4.133 -elif cmd == 'list':
   4.134 -    print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
   4.135 -    doms = server.xend_domains()
   4.136 -    doms.sort()
   4.137 -    for dom in doms:
   4.138 -        info = server.xend_domain(dom)
   4.139 -        d = {}
   4.140 -        d['dom'] = int(dom)
   4.141 -        d['name'] = sxp.child_value(info, 'name', '??')
   4.142 -        d['mem'] = int(sxp.child_value(info, 'memory', '0'))
   4.143 -        d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
   4.144 -        d['state'] = sxp.child_value(info, 'state', '??')
   4.145 -        d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
   4.146 -        print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8.2f" % d)
   4.147 -
   4.148 -elif cmd == 'unwatch':
   4.149 -    auto_restart_kill(dom)
   4.150 -
   4.151 -elif cmd == 'listvbds':
   4.152 -    print 'Dom   Dev   Mode   Size(MB)'
   4.153 -    for dom in server.xend_domains():
   4.154 -        for vbd in server.xend_domain_vbds(dom):
   4.155 -            info = server.xend_domain_vbd(vbd)
   4.156 -            v['vbd'] = vbd
   4.157 -            v['size'] = int(sxp.get_child_value(info, 'size', '0'))
   4.158 -            v['mode'] = sxp.get_child_value(info, 'mode', '??')
   4.159 -            vbd['size_mb'] = vbd['nr_sectors'] / 2048
   4.160 -            print ('%(dom)-4d  %(vbd)04x  %(mode)-2s      %(size)d' % v)
   4.161 -
   4.162 -elif cmd == 'suspend':
   4.163 -    if len(sys.argv) < 4: usage(1)
   4.164 -    file = os.path.abspath(sys.argv[3])
   4.165 -    auto_restart_kill(dom)
   4.166 -    rc = server.xend_domain_save(dom, file, progress=1)
   4.167 -
   4.168 -elif cmd == 'cpu_bvtslice':
   4.169 -    if len(sys.argv) < 3: usage(1)
   4.170 -    slice = sys.argv[2]
   4.171 -    rc = server.xend_node_cpu_bvt_slice_set(slice)
   4.172 -
   4.173 -elif cmd == 'cpu_bvtset':
   4.174 -    if len(sys.argv) < 7: usage(1)
   4.175 -    (mcuadv, warp, warpl, warpu) = map(int, sys.argv[3:7])
   4.176 -    
   4.177 -    rc = server.xend_domain_cpu_bvt_set(dom, mcuadv, warp, warpl, warpu)
   4.178 -    
   4.179 -elif cmd == 'vif_stats':
   4.180 -    if len(sys.argv) < 4: usage(1)
   4.181 -    vif = int(sys.argv[3])
   4.182 -
   4.183 -    print server.xend_domain_vif_stats(dom, vif)
   4.184 -
   4.185 -elif cmd == 'vif_addip':
   4.186 -    if len(sys.argv) < 5: usage(1)
   4.187 -    vif = int(sys.argv[3])
   4.188 -    ip  = sys.argv[4]
   4.189 -    rc = server.xend_domain_vif_addip(dom, vif, ip)
   4.190 -
   4.191 -elif cmd == 'vif_setsched':
   4.192 -    if len(sys.argv) < 6: usage(1)
   4.193 -    (vif, bytes, usecs) = map(int, sys.argv[3:6])
   4.194 -    rc = server.xend_domain_vif_scheduler_set(dom, vif, bytes, usecs)
   4.195 -
   4.196 -elif cmd == 'vif_getsched':
   4.197 -    if len(sys.argv) < 4: usage(1)
   4.198 -    vif = int(sys.argv[3])
   4.199 -    print server.xend_domain_vif_scheduler_get(dom, vif)
   4.200 -
   4.201 -elif cmd == 'vbd_add':
   4.202 -    if len(sys.argv) < 6: usage(1)
   4.203 -    uname = sys.argv[3]
   4.204 -    dev = sys.argv[4]
   4.205 -    mode = sys.argv[5]
   4.206 -    try:
   4.207 -        vbd = server.xend_domain_vbd_add(dom, uname, dev, mode)
   4.208 -    except StandardError, ex:
   4.209 -        print "Error:", ex
   4.210 -        sys.exit(1)
   4.211 -    print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, vbd)
   4.212 -
   4.213 -elif cmd == 'vbd_remove':
   4.214 -    if len(sys.argv) < 4: usage(1)
   4.215 -    dev = sys.argv[3]
   4.216 -    vbd = server.xend_domain_vbd_remove(dom, dev)
   4.217 -    if vbd < 0:
   4.218 -	print "Failed"
   4.219 -	sys.exit(1)
   4.220 -    else:
   4.221 -	print "Removed disk/partition attached as device %s (%x) in domain %d" % (dev, vbd, dom)
   4.222 -
   4.223 -elif cmd == 'cpu_atropos_set': # args: dom period slice latency xtratime
   4.224 -    if len(sys.argv) < 6: usage(1)
   4.225 -    (period, slice, latency, xtratime) = map(int, sys.argv[3:7])
   4.226 -    rc = server.xend_domain_cpu_atropos_set(
   4.227 -        dom, period, slice, latency, xtratime)
   4.228 -
   4.229 -elif cmd == 'cpu_rrobin_slice':
   4.230 -    if len(sys.argv) < 3: usage(1)
   4.231 -    slice = int(sys.argv[2])
   4.232 -    rc = server.xend_node_rrobin_set(slice=slice)
   4.233 -
   4.234 -else:
   4.235 -    usage(1)
   4.236 -
   4.237 -if rc != '':
   4.238 -    print "return code %d" % rc
     5.1 --- a/tools/examples/xmdefaults	Fri Jun 25 15:10:48 2004 +0000
     5.2 +++ b/tools/examples/xmdefaults	Mon Jun 28 08:17:15 2004 +0000
     5.3 @@ -44,10 +44,9 @@ cpu = vmid  # set based on vmid (mod num
     5.4  # Number of network interfaces. Default is 1.
     5.5  #nics=1
     5.6  
     5.7 -# List of MAC addresses for the network interfaces.
     5.8 -# If there aren't enough addresses for all the interfaces
     5.9 -# the rest get random MACs.
    5.10 -#mac = [ "aa:00:00:00:00:11" ]
    5.11 +# Optionally define mac and/or bridge for the network interfaces.
    5.12 +# Random MACs are assigned if not given.
    5.13 +#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
    5.14  
    5.15  #----------------------------------------------------------------------------
    5.16  # Define the disk devices you want the domain to have access to, and
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/examples/xmnetbsd	Mon Jun 28 08:17:15 2004 +0000
     6.3 @@ -0,0 +1,102 @@
     6.4 +#  -*- mode: python; -*-
     6.5 +#============================================================================
     6.6 +# Python defaults setup for 'xm create'.
     6.7 +# Edit this file to reflect the configuration of your system.
     6.8 +# This file expects the variable 'vmid' to be set.
     6.9 +#============================================================================
    6.10 +
    6.11 +def config_usage ():
    6.12 +    print >>sys.stderr,"""
    6.13 +The config file '%s' requires the following variable to be defined:
    6.14 + vmid             -- Numeric identifier for the new domain, used to calculate
    6.15 +                     the VM's IP address and root partition. E.g. -Dvmid=1
    6.16 +""" % config_file
    6.17 +
    6.18 +
    6.19 +try:
    6.20 +    vmid = int(vmid) # convert to integer
    6.21 +except:
    6.22 +    raise ValueError, "Variable 'vmid' must be an integer"
    6.23 +
    6.24 +if vmid <= 0:
    6.25 +    raise ValueError, "Variable 'vmid' must be greater than 0" 
    6.26 +
    6.27 +#----------------------------------------------------------------------------
    6.28 +# Kernel image file.
    6.29 +image = "/boot/netbsd"
    6.30 +
    6.31 +# The domain build function.
    6.32 +builder='netbsd'
    6.33 +
    6.34 +# Initial memory allocation (in megabytes) for the new domain.
    6.35 +memory = 16
    6.36 +
    6.37 +# A handy name for your new domain.
    6.38 +name = "NetBSD VM %d" % vmid
    6.39 +
    6.40 +#----------------------------------------------------------------------------
    6.41 +# Define network interfaces.
    6.42 +
    6.43 +# Number of network interfaces. Default is 1.
    6.44 +#nics=1
    6.45 +
    6.46 +# Optionally define mac and/or bridge for the network interfaces.
    6.47 +# Random MACs are assigned if not given.
    6.48 +#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
    6.49 +
    6.50 +# Specify IP address(es), for the new domain.  You need to
    6.51 +# configure IP addrs within the domain just as you do normally.  This
    6.52 +# is just to let Xen know about them so it can route packets
    6.53 +# appropriately.
    6.54 +
    6.55 +#ipaddr = [ xenctl.utils.add_offset_to_ip(xenctl.utils.get_current_ipaddr(),vmid),
    6.56 +#           xenctl.utils.add_offset_to_ip('169.254.1.0',vmid),
    6.57 +#           ]
    6.58 +
    6.59 +#----------------------------------------------------------------------------
    6.60 +# Define the disk devices you want the domain to have access to, and
    6.61 +# what you want them accessible as.
    6.62 +# Each disk entry is of the form phy:DEV,VDEV,MODE
    6.63 +# where DEV is the device, VDEV is the device name the domain will see,
    6.64 +# and MODE is r for read-only, w for read-write.
    6.65 +
    6.66 +#disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
    6.67 +#         'phy:sda6,sda6,r' ]
    6.68 +
    6.69 +#----------------------------------------------------------------------------
    6.70 +# Set the kernel command line for the new domain.
    6.71 +# You only need to define the IP parameters and hostname if the domain's
    6.72 +# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
    6.73 +# You can use 'extra' to set the runlevel and custom environment
    6.74 +# variables used by custom rc scripts (e.g. VMID=, usr= ).
    6.75 +
    6.76 +# Set if you want dhcp to allocate the IP address.
    6.77 +#dhcp="dhcp"
    6.78 +# Set netmask.
    6.79 +#netmask=
    6.80 +# Set default gateway.
    6.81 +#gateway=
    6.82 +# Set the hostname.
    6.83 +#hostname= "vm%d" % vmid
    6.84 +
    6.85 +# Set root device.
    6.86 +root = "/dev/sda1 ro"
    6.87 +
    6.88 +# Root device for nfs.
    6.89 +#root = "/dev/nfs"
    6.90 +# The nfs server.
    6.91 +#nfs_server = '169.254.1.0'  
    6.92 +# Root directory on the nfs server.
    6.93 +#nfs_root   = '/full/path/to/root/directory'
    6.94 +
    6.95 +# Sets runlevel 4 and the device for /usr.
    6.96 +#extra = "4 VMID=%d usr=/dev/sda6" % vmid
    6.97 +extra = "4 VMID=%d bootdev=xennet0" % vmid
    6.98 +
    6.99 +
   6.100 +#----------------------------------------------------------------------------
   6.101 +# Set according to whether you want the domain  restarted when it exits.
   6.102 +# The default is False.
   6.103 +#restart = True
   6.104 +
   6.105 +#============================================================================
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/xen/lib/ext/__init__.py	Mon Jun 28 08:17:15 2004 +0000
     7.3 @@ -0,0 +1,1 @@
     7.4 + 
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/xen/lib/util/__init__.py	Mon Jun 28 08:17:15 2004 +0000
     8.3 @@ -0,0 +1,1 @@
     8.4 + 
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/xen/lib/util/console_client.py	Mon Jun 28 08:17:15 2004 +0000
     9.3 @@ -0,0 +1,82 @@
     9.4 +#!/usr/bin/env python
     9.5 +
     9.6 +##############################################
     9.7 +# Console client for Xen guest OSes
     9.8 +# Copyright (c) 2004, K A Fraser
     9.9 +##############################################
    9.10 +
    9.11 +import errno, os, signal, socket, struct, sys
    9.12 +
    9.13 +from termios import *
    9.14 +# Indexes into termios.tcgetattr() list.
    9.15 +IFLAG  = 0
    9.16 +OFLAG  = 1
    9.17 +CFLAG  = 2
    9.18 +LFLAG  = 3
    9.19 +ISPEED = 4
    9.20 +OSPEED = 5
    9.21 +CC     = 6
    9.22 +
    9.23 +def __child_death(signum, frame):
    9.24 +    global stop
    9.25 +    stop = True
    9.26 +
    9.27 +def __recv_from_sock(sock):
    9.28 +    global stop
    9.29 +    stop = False
    9.30 +    while not stop:
    9.31 +        try:
    9.32 +            data = sock.recv(1024)
    9.33 +            os.write(1, data)
    9.34 +        except socket.error, error:
    9.35 +            if error[0] != errno.EINTR:
    9.36 +                raise
    9.37 +    os.wait()
    9.38 +
    9.39 +def __send_to_sock(sock):
    9.40 +    while 1:
    9.41 +        data = os.read(0,1024)
    9.42 +        if ord(data[0]) == ord(']')-64:
    9.43 +            break
    9.44 +        try:
    9.45 +            sock.send(data)
    9.46 +        except socket.error, error:
    9.47 +            if error[0] == errno.EPIPE:
    9.48 +                sys.exit(0)
    9.49 +            if error[0] != errno.EINTR:
    9.50 +                raise
    9.51 +    sys.exit(0)
    9.52 +
    9.53 +def connect(host,port):
    9.54 +    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    9.55 +    sock.connect((host,port))
    9.56 +
    9.57 +    oattrs = tcgetattr(0)
    9.58 +    nattrs = tcgetattr(0)
    9.59 +    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
    9.60 +    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
    9.61 +    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
    9.62 +    nattrs[CFLAG] = nattrs[CFLAG] | CS8
    9.63 +    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
    9.64 +    nattrs[CC][VMIN] = 1
    9.65 +    nattrs[CC][VTIME] = 0
    9.66 +
    9.67 +    if os.fork():
    9.68 +        signal.signal(signal.SIGCHLD, __child_death)
    9.69 +        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
    9.70 +        tcsetattr(0, TCSAFLUSH, nattrs)
    9.71 +        try:
    9.72 +            __recv_from_sock(sock)
    9.73 +        finally:
    9.74 +            tcsetattr(0, TCSAFLUSH, oattrs)
    9.75 +            print
    9.76 +            print "************ REMOTE CONSOLE EXITED *****************"
    9.77 +    else:
    9.78 +        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
    9.79 +        __send_to_sock(sock)
    9.80 +
    9.81 +if __name__ == '__main__':
    9.82 +    if len(sys.argv) != 3:
    9.83 +        print sys.argv[0] + " <host> <port>"
    9.84 +        sys.exit(1)
    9.85 +    connect(str(sys.argv[1]),int(sys.argv[2]))
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/xen/lib/util/ip.py	Mon Jun 28 08:17:15 2004 +0000
    10.3 @@ -0,0 +1,113 @@
    10.4 +import os
    10.5 +import re
    10.6 +import socket
    10.7 +import struct
    10.8 +
    10.9 +def readlines(fd):
   10.10 +    """Version of readlines safe against EINTR.
   10.11 +    """
   10.12 +    import errno
   10.13 +    
   10.14 +    lines = []
   10.15 +    while 1:
   10.16 +        try:
   10.17 +            line = fd.readline()
   10.18 +        except IOError, ex:
   10.19 +            if ex.errno == errno.EINTR:
   10.20 +                continue
   10.21 +            else:
   10.22 +                raise
   10.23 +        if line == '': break
   10.24 +        lines.append(line)
   10.25 +    return lines
   10.26 +
   10.27 +def readline(fd):
   10.28 +    """Version of readline safe against EINTR.
   10.29 +    """
   10.30 +    while 1:
   10.31 +        try:
   10.32 +            return fd.readline()
   10.33 +        except IOError, ex:
   10.34 +            if ex.errno == errno.EINTR:
   10.35 +                continue
   10.36 +            else:
   10.37 +                raise
   10.38 +
   10.39 +##### Networking-related functions
   10.40 +
   10.41 +"""Bridge for network backend.
   10.42 +When bridging is used, eth0 may not have an IP address,
   10.43 +as it may have been moved onto the bridge.
   10.44 +"""
   10.45 +NBE_BRIDGE = 'nbe-br'
   10.46 +
   10.47 +def get_current_ipaddr(dev='eth0'):
   10.48 +    """Return a string containing the primary IP address for the given
   10.49 +    network interface (default 'eth0').
   10.50 +    """
   10.51 +    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   10.52 +    lines = readlines(fd)
   10.53 +    for line in lines:
   10.54 +        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   10.55 +                       line )
   10.56 +        if m:
   10.57 +            return m.group(1)
   10.58 +    if dev == 'eth0':
   10.59 +        return get_current_ipaddr(NBE_BRIDGE)
   10.60 +    return None
   10.61 +
   10.62 +def get_current_ipmask(dev='eth0'):
   10.63 +    """Return a string containing the primary IP netmask for the given
   10.64 +    network interface (default 'eth0').
   10.65 +    """
   10.66 +    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   10.67 +    lines = readlines(fd)
   10.68 +    for line in lines:
   10.69 +        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   10.70 +                       line )
   10.71 +        if m:
   10.72 +            return m.group(1)
   10.73 +    if dev == 'eth0':
   10.74 +        return get_current_ipmask(NBE_BRIDGE)
   10.75 +    return None
   10.76 +
   10.77 +def get_current_ipgw(dev='eth0'):
   10.78 +    """Return a string containing the IP gateway for the given
   10.79 +    network interface (default 'eth0').
   10.80 +    """
   10.81 +    fd = os.popen( '/sbin/route -n' )
   10.82 +    lines = readlines(fd)
   10.83 +    for line in lines:
   10.84 +        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
   10.85 +                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
   10.86 +        if m:
   10.87 +            return m.group(1)
   10.88 +    if dev == 'eth0':
   10.89 +        return get_current_ipgw(NBE_BRIDGE)
   10.90 +    return None
   10.91 +
   10.92 +def inet_aton(addr):
   10.93 +    """Convert an IP addr in IPv4 dot notation into an int.
   10.94 +    """
   10.95 +    b = socket.inet_aton(addr)
   10.96 +    return struct.unpack('!I', b)[0]
   10.97 +
   10.98 +def inet_ntoa(n):
   10.99 +    """Convert an int into an IP addr in IPv4 dot notation.
  10.100 +    """
  10.101 +    b = struct.pack('!I', n)
  10.102 +    return socket.inet_ntoa(b)
  10.103 +
  10.104 +def add_offset_to_ip(addr, offset):
  10.105 +    """Add a numerical offset to an IP addr in IPv4 dot notation.
  10.106 +    """
  10.107 +    n = inet_aton(addr)
  10.108 +    n += offset
  10.109 +    return inet_ntoa(n)
  10.110 +
  10.111 +def check_subnet( ip, network, netmask ):
  10.112 +    n_ip = inet_aton(ip)
  10.113 +    n_net = inet_aton(network)
  10.114 +    n_mask = inet_aton(netmask)
  10.115 +    return (n_ip & n_mask) == (n_net & n_mask)
  10.116 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/xen/lib/util/tempfile.py	Mon Jun 28 08:17:15 2004 +0000
    11.3 @@ -0,0 +1,451 @@
    11.4 +"""Temporary files.
    11.5 +
    11.6 +This module provides generic, low- and high-level interfaces for
    11.7 +creating temporary files and directories.  The interfaces listed
    11.8 +as "safe" just below can be used without fear of race conditions.
    11.9 +Those listed as "unsafe" cannot, and are provided for backward
   11.10 +compatibility only.
   11.11 +
   11.12 +This module also provides some data items to the user:
   11.13 +
   11.14 +  TMP_MAX  - maximum number of names that will be tried before
   11.15 +             giving up.
   11.16 +  template - the default prefix for all temporary names.
   11.17 +             You may change this to control the default prefix.
   11.18 +  tempdir  - If this is set to a string before the first use of
   11.19 +             any routine from this module, it will be considered as
   11.20 +             another candidate location to store temporary files.
   11.21 +"""
   11.22 +
   11.23 +__all__ = [
   11.24 +    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
   11.25 +    "mkstemp", "mkdtemp",                  # low level safe interfaces
   11.26 +    "mktemp",                              # deprecated unsafe interface
   11.27 +    "TMP_MAX", "gettempprefix",            # constants
   11.28 +    "tempdir", "gettempdir"
   11.29 +   ]
   11.30 +
   11.31 +
   11.32 +# Imports.
   11.33 +
   11.34 +import os as _os
   11.35 +import errno as _errno
   11.36 +from random import Random as _Random
   11.37 +
   11.38 +if _os.name == 'mac':
   11.39 +    import Carbon.Folder as _Folder
   11.40 +    import Carbon.Folders as _Folders
   11.41 +
   11.42 +try:
   11.43 +    import fcntl as _fcntl
   11.44 +    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
   11.45 +    # imported, and we don't get an ImportError then.  Provoke
   11.46 +    # an AttributeError instead in that case.
   11.47 +    _fcntl.fcntl
   11.48 +except (ImportError, AttributeError):
   11.49 +    def _set_cloexec(fd):
   11.50 +        pass
   11.51 +else:
   11.52 +    def _set_cloexec(fd):
   11.53 +        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
   11.54 +        if flags >= 0:
   11.55 +            # flags read successfully, modify
   11.56 +            flags |= _fcntl.FD_CLOEXEC
   11.57 +            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
   11.58 +
   11.59 +
   11.60 +try:
   11.61 +    import thread as _thread
   11.62 +except ImportError:
   11.63 +    import dummy_thread as _thread
   11.64 +_allocate_lock = _thread.allocate_lock
   11.65 +
   11.66 +_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
   11.67 +if hasattr(_os, 'O_NOINHERIT'):
   11.68 +    _text_openflags |= _os.O_NOINHERIT
   11.69 +if hasattr(_os, 'O_NOFOLLOW'):
   11.70 +    _text_openflags |= _os.O_NOFOLLOW
   11.71 +
   11.72 +_bin_openflags = _text_openflags
   11.73 +if hasattr(_os, 'O_BINARY'):
   11.74 +    _bin_openflags |= _os.O_BINARY
   11.75 +
   11.76 +if hasattr(_os, 'TMP_MAX'):
   11.77 +    TMP_MAX = _os.TMP_MAX
   11.78 +else:
   11.79 +    TMP_MAX = 10000
   11.80 +
   11.81 +template = "tmp"
   11.82 +
   11.83 +tempdir = None
   11.84 +
   11.85 +# Internal routines.
   11.86 +
   11.87 +_once_lock = _allocate_lock()
   11.88 +
   11.89 +class _RandomNameSequence:
   11.90 +    """An instance of _RandomNameSequence generates an endless
   11.91 +    sequence of unpredictable strings which can safely be incorporated
   11.92 +    into file names.  Each string is six characters long.  Multiple
   11.93 +    threads can safely use the same instance at the same time.
   11.94 +
   11.95 +    _RandomNameSequence is an iterator."""
   11.96 +
   11.97 +    characters = ("abcdefghijklmnopqrstuvwxyz" +
   11.98 +                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
   11.99 +                  "0123456789-_")
  11.100 +
  11.101 +    def __init__(self):
  11.102 +        self.mutex = _allocate_lock()
  11.103 +        self.rng = _Random()
  11.104 +        self.normcase = _os.path.normcase
  11.105 +
  11.106 +    def __iter__(self):
  11.107 +        return self
  11.108 +
  11.109 +    def next(self):
  11.110 +        m = self.mutex
  11.111 +        c = self.characters
  11.112 +        choose = self.rng.choice
  11.113 +
  11.114 +        m.acquire()
  11.115 +        try:
  11.116 +            letters = [choose(c) for dummy in "123456"]
  11.117 +        finally:
  11.118 +            m.release()
  11.119 +
  11.120 +        return self.normcase(''.join(letters))
  11.121 +
  11.122 +def _candidate_tempdir_list():
  11.123 +    """Generate a list of candidate temporary directories which
  11.124 +    _get_default_tempdir will try."""
  11.125 +
  11.126 +    dirlist = []
  11.127 +
  11.128 +    # First, try the environment.
  11.129 +    for envname in 'TMPDIR', 'TEMP', 'TMP':
  11.130 +        dirname = _os.getenv(envname)
  11.131 +        if dirname: dirlist.append(dirname)
  11.132 +
  11.133 +    # Failing that, try OS-specific locations.
  11.134 +    if _os.name == 'mac':
  11.135 +        try:
  11.136 +            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
  11.137 +                                              _Folders.kTemporaryFolderType, 1)
  11.138 +            dirname = fsr.as_pathname()
  11.139 +            dirlist.append(dirname)
  11.140 +        except _Folder.error:
  11.141 +            pass
  11.142 +    elif _os.name == 'riscos':
  11.143 +        dirname = _os.getenv('Wimp$ScrapDir')
  11.144 +        if dirname: dirlist.append(dirname)
  11.145 +    elif _os.name == 'nt':
  11.146 +        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
  11.147 +    else:
  11.148 +        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
  11.149 +
  11.150 +    # As a last resort, the current directory.
  11.151 +    try:
  11.152 +        dirlist.append(_os.getcwd())
  11.153 +    except (AttributeError, _os.error):
  11.154 +        dirlist.append(_os.curdir)
  11.155 +
  11.156 +    return dirlist
  11.157 +
  11.158 +def _get_default_tempdir():
  11.159 +    """Calculate the default directory to use for temporary files.
  11.160 +    This routine should be called exactly once.
  11.161 +
  11.162 +    We determine whether or not a candidate temp dir is usable by
  11.163 +    trying to create and write to a file in that directory.  If this
  11.164 +    is successful, the test file is deleted.  To prevent denial of
  11.165 +    service, the name of the test file must be randomized."""
  11.166 +
  11.167 +    namer = _RandomNameSequence()
  11.168 +    dirlist = _candidate_tempdir_list()
  11.169 +    flags = _text_openflags
  11.170 +
  11.171 +    for dir in dirlist:
  11.172 +        if dir != _os.curdir:
  11.173 +            dir = _os.path.normcase(_os.path.abspath(dir))
  11.174 +        # Try only a few names per directory.
  11.175 +        for seq in xrange(100):
  11.176 +            name = namer.next()
  11.177 +            filename = _os.path.join(dir, name)
  11.178 +            try:
  11.179 +                fd = _os.open(filename, flags, 0600)
  11.180 +                fp = _os.fdopen(fd, 'w')
  11.181 +                fp.write('blat')
  11.182 +                fp.close()
  11.183 +                _os.unlink(filename)
  11.184 +                del fp, fd
  11.185 +                return dir
  11.186 +            except (OSError, IOError), e:
  11.187 +                if e[0] != _errno.EEXIST:
  11.188 +                    break # no point trying more names in this directory
  11.189 +                pass
  11.190 +    raise IOError, (_errno.ENOENT,
  11.191 +                    ("No usable temporary directory found in %s" % dirlist))
  11.192 +
  11.193 +_name_sequence = None
  11.194 +
  11.195 +def _get_candidate_names():
  11.196 +    """Common setup sequence for all user-callable interfaces."""
  11.197 +
  11.198 +    global _name_sequence
  11.199 +    if _name_sequence is None:
  11.200 +        _once_lock.acquire()
  11.201 +        try:
  11.202 +            if _name_sequence is None:
  11.203 +                _name_sequence = _RandomNameSequence()
  11.204 +        finally:
  11.205 +            _once_lock.release()
  11.206 +    return _name_sequence
  11.207 +
  11.208 +
  11.209 +def _mkstemp_inner(dir, pre, suf, flags):
  11.210 +    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
  11.211 +
  11.212 +    names = _get_candidate_names()
  11.213 +
  11.214 +    for seq in xrange(TMP_MAX):
  11.215 +        name = names.next()
  11.216 +        file = _os.path.join(dir, pre + name + suf)
  11.217 +        try:
  11.218 +            fd = _os.open(file, flags, 0600)
  11.219 +            _set_cloexec(fd)
  11.220 +            return (fd, file)
  11.221 +        except OSError, e:
  11.222 +            if e.errno == _errno.EEXIST:
  11.223 +                continue # try again
  11.224 +            raise
  11.225 +
  11.226 +    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
  11.227 +
  11.228 +
  11.229 +# User visible interfaces.
  11.230 +
  11.231 +def gettempprefix():
  11.232 +    """Accessor for tempdir.template."""
  11.233 +    return template
  11.234 +
  11.235 +tempdir = None
  11.236 +
  11.237 +def gettempdir():
  11.238 +    """Accessor for tempdir.tempdir."""
  11.239 +    global tempdir
  11.240 +    if tempdir is None:
  11.241 +        _once_lock.acquire()
  11.242 +        try:
  11.243 +            if tempdir is None:
  11.244 +                tempdir = _get_default_tempdir()
  11.245 +        finally:
  11.246 +            _once_lock.release()
  11.247 +    return tempdir
  11.248 +
  11.249 +def mkstemp(suffix="", prefix=template, dir=None, text=False):
  11.250 +    """mkstemp([suffix, [prefix, [dir, [text]]]])
  11.251 +    User-callable function to create and return a unique temporary
  11.252 +    file.  The return value is a pair (fd, name) where fd is the
  11.253 +    file descriptor returned by os.open, and name is the filename.
  11.254 +
  11.255 +    If 'suffix' is specified, the file name will end with that suffix,
  11.256 +    otherwise there will be no suffix.
  11.257 +
  11.258 +    If 'prefix' is specified, the file name will begin with that prefix,
  11.259 +    otherwise a default prefix is used.
  11.260 +
  11.261 +    If 'dir' is specified, the file will be created in that directory,
  11.262 +    otherwise a default directory is used.
  11.263 +
  11.264 +    If 'text' is specified and true, the file is opened in text
  11.265 +    mode.  Else (the default) the file is opened in binary mode.  On
  11.266 +    some operating systems, this makes no difference.
  11.267 +
  11.268 +    The file is readable and writable only by the creating user ID.
  11.269 +    If the operating system uses permission bits to indicate whether a
  11.270 +    file is executable, the file is executable by no one. The file
  11.271 +    descriptor is not inherited by children of this process.
  11.272 +
  11.273 +    Caller is responsible for deleting the file when done with it.
  11.274 +    """
  11.275 +
  11.276 +    if dir is None:
  11.277 +        dir = gettempdir()
  11.278 +
  11.279 +    if text:
  11.280 +        flags = _text_openflags
  11.281 +    else:
  11.282 +        flags = _bin_openflags
  11.283 +
  11.284 +    return _mkstemp_inner(dir, prefix, suffix, flags)
  11.285 +
  11.286 +
  11.287 +def mkdtemp(suffix="", prefix=template, dir=None):
  11.288 +    """mkdtemp([suffix, [prefix, [dir]]])
  11.289 +    User-callable function to create and return a unique temporary
  11.290 +    directory.  The return value is the pathname of the directory.
  11.291 +
  11.292 +    Arguments are as for mkstemp, except that the 'text' argument is
  11.293 +    not accepted.
  11.294 +
  11.295 +    The directory is readable, writable, and searchable only by the
  11.296 +    creating user.
  11.297 +
  11.298 +    Caller is responsible for deleting the directory when done with it.
  11.299 +    """
  11.300 +
  11.301 +    if dir is None:
  11.302 +        dir = gettempdir()
  11.303 +
  11.304 +    names = _get_candidate_names()
  11.305 +
  11.306 +    for seq in xrange(TMP_MAX):
  11.307 +        name = names.next()
  11.308 +        file = _os.path.join(dir, prefix + name + suffix)
  11.309 +        try:
  11.310 +            _os.mkdir(file, 0700)
  11.311 +            return file
  11.312 +        except OSError, e:
  11.313 +            if e.errno == _errno.EEXIST:
  11.314 +                continue # try again
  11.315 +            raise
  11.316 +
  11.317 +    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
  11.318 +
  11.319 +def mktemp(suffix="", prefix=template, dir=None):
  11.320 +    """mktemp([suffix, [prefix, [dir]]])
  11.321 +    User-callable function to return a unique temporary file name.  The
  11.322 +    file is not created.
  11.323 +
  11.324 +    Arguments are as for mkstemp, except that the 'text' argument is
  11.325 +    not accepted.
  11.326 +
  11.327 +    This function is unsafe and should not be used.  The file name
  11.328 +    refers to a file that did not exist at some point, but by the time
  11.329 +    you get around to creating it, someone else may have beaten you to
  11.330 +    the punch.
  11.331 +    """
  11.332 +
  11.333 +##    from warnings import warn as _warn
  11.334 +##    _warn("mktemp is a potential security risk to your program",
  11.335 +##          RuntimeWarning, stacklevel=2)
  11.336 +
  11.337 +    if dir is None:
  11.338 +        dir = gettempdir()
  11.339 +
  11.340 +    names = _get_candidate_names()
  11.341 +    for seq in xrange(TMP_MAX):
  11.342 +        name = names.next()
  11.343 +        file = _os.path.join(dir, prefix + name + suffix)
  11.344 +        if not _os.path.exists(file):
  11.345 +            return file
  11.346 +
  11.347 +    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
  11.348 +
  11.349 +class _TemporaryFileWrapper:
  11.350 +    """Temporary file wrapper
  11.351 +
  11.352 +    This class provides a wrapper around files opened for
  11.353 +    temporary use.  In particular, it seeks to automatically
  11.354 +    remove the file when it is no longer needed.
  11.355 +    """
  11.356 +
  11.357 +    def __init__(self, file, name):
  11.358 +        self.file = file
  11.359 +        self.name = name
  11.360 +        self.close_called = False
  11.361 +
  11.362 +    def __getattr__(self, name):
  11.363 +        file = self.__dict__['file']
  11.364 +        a = getattr(file, name)
  11.365 +        if type(a) != type(0):
  11.366 +            setattr(self, name, a)
  11.367 +        return a
  11.368 +
  11.369 +    # NT provides delete-on-close as a primitive, so we don't need
  11.370 +    # the wrapper to do anything special.  We still use it so that
  11.371 +    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
  11.372 +    if _os.name != 'nt':
  11.373 +
  11.374 +        # Cache the unlinker so we don't get spurious errors at
  11.375 +        # shutdown when the module-level "os" is None'd out.  Note
  11.376 +        # that this must be referenced as self.unlink, because the
  11.377 +        # name TemporaryFileWrapper may also get None'd out before
  11.378 +        # __del__ is called.
  11.379 +        unlink = _os.unlink
  11.380 +
  11.381 +        def close(self):
  11.382 +            if not self.close_called:
  11.383 +                self.close_called = True
  11.384 +                self.file.close()
  11.385 +                self.unlink(self.name)
  11.386 +
  11.387 +        def __del__(self):
  11.388 +            self.close()
  11.389 +
  11.390 +def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
  11.391 +                       prefix=template, dir=None):
  11.392 +    """Create and return a temporary file.
  11.393 +    Arguments:
  11.394 +    'prefix', 'suffix', 'dir' -- as for mkstemp.
  11.395 +    'mode' -- the mode argument to os.fdopen (default "w+b").
  11.396 +    'bufsize' -- the buffer size argument to os.fdopen (default -1).
  11.397 +    The file is created as mkstemp() would do it.
  11.398 +
  11.399 +    Returns a file object; the name of the file is accessible as
  11.400 +    file.name.  The file will be automatically deleted when it is
  11.401 +    closed.
  11.402 +    """
  11.403 +
  11.404 +    if dir is None:
  11.405 +        dir = gettempdir()
  11.406 +
  11.407 +    if 'b' in mode:
  11.408 +        flags = _bin_openflags
  11.409 +    else:
  11.410 +        flags = _text_openflags
  11.411 +
  11.412 +    # Setting O_TEMPORARY in the flags causes the OS to delete
  11.413 +    # the file when it is closed.  This is only supported by Windows.
  11.414 +    if _os.name == 'nt':
  11.415 +        flags |= _os.O_TEMPORARY
  11.416 +
  11.417 +    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  11.418 +    file = _os.fdopen(fd, mode, bufsize)
  11.419 +    return _TemporaryFileWrapper(file, name)
  11.420 +
  11.421 +if _os.name != 'posix' or _os.sys.platform == 'cygwin':
  11.422 +    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
  11.423 +    # while it is open.
  11.424 +    TemporaryFile = NamedTemporaryFile
  11.425 +
  11.426 +else:
  11.427 +    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
  11.428 +                      prefix=template, dir=None):
  11.429 +        """Create and return a temporary file.
  11.430 +        Arguments:
  11.431 +        'prefix', 'suffix', 'directory' -- as for mkstemp.
  11.432 +        'mode' -- the mode argument to os.fdopen (default "w+b").
  11.433 +        'bufsize' -- the buffer size argument to os.fdopen (default -1).
  11.434 +        The file is created as mkstemp() would do it.
  11.435 +
  11.436 +        Returns a file object.  The file has no name, and will cease to
  11.437 +        exist when it is closed.
  11.438 +        """
  11.439 +
  11.440 +        if dir is None:
  11.441 +            dir = gettempdir()
  11.442 +
  11.443 +        if 'b' in mode:
  11.444 +            flags = _bin_openflags
  11.445 +        else:
  11.446 +            flags = _text_openflags
  11.447 +
  11.448 +        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  11.449 +        try:
  11.450 +            _os.unlink(name)
  11.451 +            return _os.fdopen(fd, mode, bufsize)
  11.452 +        except:
  11.453 +            _os.close(fd)
  11.454 +            raise
    12.1 --- a/tools/xen/lib/xm/main.py	Fri Jun 25 15:10:48 2004 +0000
    12.2 +++ b/tools/xen/lib/xm/main.py	Mon Jun 28 08:17:15 2004 +0000
    12.3 @@ -439,7 +439,7 @@ class ProgConsole(Prog):
    12.4          if not console:
    12.5              self.err("No console information")
    12.6          port = sxp.child_value(console, "port")
    12.7 -        from xenctl import console_client
    12.8 +        from xen.util import console_client
    12.9          console_client.connect("localhost", int(port))
   12.10  
   12.11  xm.prog(ProgConsole)
    13.1 --- a/tools/xen/setup.py	Fri Jun 25 15:10:48 2004 +0000
    13.2 +++ b/tools/xen/setup.py	Mon Jun 28 08:17:15 2004 +0000
    13.3 @@ -8,6 +8,7 @@ setup(name            = 'xen',
    13.4        author_email    = 'mike.wray@hp.com',
    13.5        packages        = ['xen',
    13.6                           'xen.ext',
    13.7 +                         'xen.util',
    13.8                           'xen.xend',
    13.9                           'xen.xend.server',
   13.10                           'xen.xm',
    14.1 --- a/tools/xenctl/Makefile	Fri Jun 25 15:10:48 2004 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,15 +0,0 @@
    14.4 -
    14.5 -all:
    14.6 -	python setup.py build
    14.7 -
    14.8 -install: all
    14.9 -	if [ "$(prefix)" = "" ]; then                   \
   14.10 -	    python setup.py install;                    \
   14.11 -	elif [ "$(dist)" = "yes" ]; then                \
   14.12 -	    python setup.py install --home="$(prefix)"; \
   14.13 -	else                                            \
   14.14 -	    python setup.py install --root="$(prefix)"; \
   14.15 -	fi
   14.16 -
   14.17 -clean:
   14.18 -	rm -rf build *.pyc *.pyo *.o *.a *~
    16.1 --- a/tools/xenctl/lib/console_client.py	Fri Jun 25 15:10:48 2004 +0000
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,82 +0,0 @@
    16.4 -#!/usr/bin/env python
    16.5 -
    16.6 -##############################################
    16.7 -# Console client for Xen guest OSes
    16.8 -# Copyright (c) 2004, K A Fraser
    16.9 -##############################################
   16.10 -
   16.11 -import errno, os, signal, socket, struct, sys
   16.12 -
   16.13 -from termios import *
   16.14 -# Indexes into termios.tcgetattr() list.
   16.15 -IFLAG  = 0
   16.16 -OFLAG  = 1
   16.17 -CFLAG  = 2
   16.18 -LFLAG  = 3
   16.19 -ISPEED = 4
   16.20 -OSPEED = 5
   16.21 -CC     = 6
   16.22 -
   16.23 -def __child_death(signum, frame):
   16.24 -    global stop
   16.25 -    stop = True
   16.26 -
   16.27 -def __recv_from_sock(sock):
   16.28 -    global stop
   16.29 -    stop = False
   16.30 -    while not stop:
   16.31 -        try:
   16.32 -            data = sock.recv(1024)
   16.33 -            os.write(1, data)
   16.34 -        except socket.error, error:
   16.35 -            if error[0] != errno.EINTR:
   16.36 -                raise
   16.37 -    os.wait()
   16.38 -
   16.39 -def __send_to_sock(sock):
   16.40 -    while 1:
   16.41 -        data = os.read(0,1024)
   16.42 -        if ord(data[0]) == ord(']')-64:
   16.43 -            break
   16.44 -        try:
   16.45 -            sock.send(data)
   16.46 -        except socket.error, error:
   16.47 -            if error[0] == errno.EPIPE:
   16.48 -                sys.exit(0)
   16.49 -            if error[0] != errno.EINTR:
   16.50 -                raise
   16.51 -    sys.exit(0)
   16.52 -
   16.53 -def connect(host,port):
   16.54 -    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
   16.55 -    sock.connect((host,port))
   16.56 -
   16.57 -    oattrs = tcgetattr(0)
   16.58 -    nattrs = tcgetattr(0)
   16.59 -    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
   16.60 -    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
   16.61 -    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
   16.62 -    nattrs[CFLAG] = nattrs[CFLAG] | CS8
   16.63 -    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
   16.64 -    nattrs[CC][VMIN] = 1
   16.65 -    nattrs[CC][VTIME] = 0
   16.66 -
   16.67 -    if os.fork():
   16.68 -        signal.signal(signal.SIGCHLD, __child_death)
   16.69 -        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
   16.70 -        tcsetattr(0, TCSAFLUSH, nattrs)
   16.71 -        try:
   16.72 -            __recv_from_sock(sock)
   16.73 -        finally:
   16.74 -            tcsetattr(0, TCSAFLUSH, oattrs)
   16.75 -            print
   16.76 -            print "************ REMOTE CONSOLE EXITED *****************"
   16.77 -    else:
   16.78 -        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
   16.79 -        __send_to_sock(sock)
   16.80 -
   16.81 -if __name__ == '__main__':
   16.82 -    if len(sys.argv) != 3:
   16.83 -        print sys.argv[0] + " <host> <port>"
   16.84 -        sys.exit(1)
   16.85 -    connect(str(sys.argv[1]),int(sys.argv[2]))
    17.1 --- a/tools/xenctl/lib/ip.py	Fri Jun 25 15:10:48 2004 +0000
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,113 +0,0 @@
    17.4 -import os
    17.5 -import re
    17.6 -import socket
    17.7 -import struct
    17.8 -
    17.9 -def readlines(fd):
   17.10 -    """Version of readlines safe against EINTR.
   17.11 -    """
   17.12 -    import errno
   17.13 -    
   17.14 -    lines = []
   17.15 -    while 1:
   17.16 -        try:
   17.17 -            line = fd.readline()
   17.18 -        except IOError, ex:
   17.19 -            if ex.errno == errno.EINTR:
   17.20 -                continue
   17.21 -            else:
   17.22 -                raise
   17.23 -        if line == '': break
   17.24 -        lines.append(line)
   17.25 -    return lines
   17.26 -
   17.27 -def readline(fd):
   17.28 -    """Version of readline safe against EINTR.
   17.29 -    """
   17.30 -    while 1:
   17.31 -        try:
   17.32 -            return fd.readline()
   17.33 -        except IOError, ex:
   17.34 -            if ex.errno == errno.EINTR:
   17.35 -                continue
   17.36 -            else:
   17.37 -                raise
   17.38 -
   17.39 -##### Networking-related functions
   17.40 -
   17.41 -"""Bridge for network backend.
   17.42 -When bridging is used, eth0 may not have an IP address,
   17.43 -as it may have been moved onto the bridge.
   17.44 -"""
   17.45 -NBE_BRIDGE = 'nbe-br'
   17.46 -
   17.47 -def get_current_ipaddr(dev='eth0'):
   17.48 -    """Return a string containing the primary IP address for the given
   17.49 -    network interface (default 'eth0').
   17.50 -    """
   17.51 -    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   17.52 -    lines = readlines(fd)
   17.53 -    for line in lines:
   17.54 -        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   17.55 -                       line )
   17.56 -        if m:
   17.57 -            return m.group(1)
   17.58 -    if dev == 'eth0':
   17.59 -        return get_current_ipaddr(NBE_BRIDGE)
   17.60 -    return None
   17.61 -
   17.62 -def get_current_ipmask(dev='eth0'):
   17.63 -    """Return a string containing the primary IP netmask for the given
   17.64 -    network interface (default 'eth0').
   17.65 -    """
   17.66 -    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   17.67 -    lines = readlines(fd)
   17.68 -    for line in lines:
   17.69 -        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   17.70 -                       line )
   17.71 -        if m:
   17.72 -            return m.group(1)
   17.73 -    if dev == 'eth0':
   17.74 -        return get_current_ipmask(NBE_BRIDGE)
   17.75 -    return None
   17.76 -
   17.77 -def get_current_ipgw(dev='eth0'):
   17.78 -    """Return a string containing the IP gateway for the given
   17.79 -    network interface (default 'eth0').
   17.80 -    """
   17.81 -    fd = os.popen( '/sbin/route -n' )
   17.82 -    lines = readlines(fd)
   17.83 -    for line in lines:
   17.84 -        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
   17.85 -                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
   17.86 -        if m:
   17.87 -            return m.group(1)
   17.88 -    if dev == 'eth0':
   17.89 -        return get_current_ipgw(NBE_BRIDGE)
   17.90 -    return None
   17.91 -
   17.92 -def inet_aton(addr):
   17.93 -    """Convert an IP addr in IPv4 dot notation into an int.
   17.94 -    """
   17.95 -    b = socket.inet_aton(addr)
   17.96 -    return struct.unpack('!I', b)[0]
   17.97 -
   17.98 -def inet_ntoa(n):
   17.99 -    """Convert an int into an IP addr in IPv4 dot notation.
  17.100 -    """
  17.101 -    b = struct.pack('!I', n)
  17.102 -    return socket.inet_ntoa(b)
  17.103 -
  17.104 -def add_offset_to_ip(addr, offset):
  17.105 -    """Add a numerical offset to an IP addr in IPv4 dot notation.
  17.106 -    """
  17.107 -    n = inet_aton(addr)
  17.108 -    n += offset
  17.109 -    return inet_ntoa(n)
  17.110 -
  17.111 -def check_subnet( ip, network, netmask ):
  17.112 -    n_ip = inet_aton(ip)
  17.113 -    n_net = inet_aton(network)
  17.114 -    n_mask = inet_aton(netmask)
  17.115 -    return (n_ip & n_mask) == (n_net & n_mask)
  17.116 -
    18.1 --- a/tools/xenctl/lib/tempfile.py	Fri Jun 25 15:10:48 2004 +0000
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,451 +0,0 @@
    18.4 -"""Temporary files.
    18.5 -
    18.6 -This module provides generic, low- and high-level interfaces for
    18.7 -creating temporary files and directories.  The interfaces listed
    18.8 -as "safe" just below can be used without fear of race conditions.
    18.9 -Those listed as "unsafe" cannot, and are provided for backward
   18.10 -compatibility only.
   18.11 -
   18.12 -This module also provides some data items to the user:
   18.13 -
   18.14 -  TMP_MAX  - maximum number of names that will be tried before
   18.15 -             giving up.
   18.16 -  template - the default prefix for all temporary names.
   18.17 -             You may change this to control the default prefix.
   18.18 -  tempdir  - If this is set to a string before the first use of
   18.19 -             any routine from this module, it will be considered as
   18.20 -             another candidate location to store temporary files.
   18.21 -"""
   18.22 -
   18.23 -__all__ = [
   18.24 -    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
   18.25 -    "mkstemp", "mkdtemp",                  # low level safe interfaces
   18.26 -    "mktemp",                              # deprecated unsafe interface
   18.27 -    "TMP_MAX", "gettempprefix",            # constants
   18.28 -    "tempdir", "gettempdir"
   18.29 -   ]
   18.30 -
   18.31 -
   18.32 -# Imports.
   18.33 -
   18.34 -import os as _os
   18.35 -import errno as _errno
   18.36 -from random import Random as _Random
   18.37 -
   18.38 -if _os.name == 'mac':
   18.39 -    import Carbon.Folder as _Folder
   18.40 -    import Carbon.Folders as _Folders
   18.41 -
   18.42 -try:
   18.43 -    import fcntl as _fcntl
   18.44 -    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
   18.45 -    # imported, and we don't get an ImportError then.  Provoke
   18.46 -    # an AttributeError instead in that case.
   18.47 -    _fcntl.fcntl
   18.48 -except (ImportError, AttributeError):
   18.49 -    def _set_cloexec(fd):
   18.50 -        pass
   18.51 -else:
   18.52 -    def _set_cloexec(fd):
   18.53 -        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
   18.54 -        if flags >= 0:
   18.55 -            # flags read successfully, modify
   18.56 -            flags |= _fcntl.FD_CLOEXEC
   18.57 -            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
   18.58 -
   18.59 -
   18.60 -try:
   18.61 -    import thread as _thread
   18.62 -except ImportError:
   18.63 -    import dummy_thread as _thread
   18.64 -_allocate_lock = _thread.allocate_lock
   18.65 -
   18.66 -_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
   18.67 -if hasattr(_os, 'O_NOINHERIT'):
   18.68 -    _text_openflags |= _os.O_NOINHERIT
   18.69 -if hasattr(_os, 'O_NOFOLLOW'):
   18.70 -    _text_openflags |= _os.O_NOFOLLOW
   18.71 -
   18.72 -_bin_openflags = _text_openflags
   18.73 -if hasattr(_os, 'O_BINARY'):
   18.74 -    _bin_openflags |= _os.O_BINARY
   18.75 -
   18.76 -if hasattr(_os, 'TMP_MAX'):
   18.77 -    TMP_MAX = _os.TMP_MAX
   18.78 -else:
   18.79 -    TMP_MAX = 10000
   18.80 -
   18.81 -template = "tmp"
   18.82 -
   18.83 -tempdir = None
   18.84 -
   18.85 -# Internal routines.
   18.86 -
   18.87 -_once_lock = _allocate_lock()
   18.88 -
   18.89 -class _RandomNameSequence:
   18.90 -    """An instance of _RandomNameSequence generates an endless
   18.91 -    sequence of unpredictable strings which can safely be incorporated
   18.92 -    into file names.  Each string is six characters long.  Multiple
   18.93 -    threads can safely use the same instance at the same time.
   18.94 -
   18.95 -    _RandomNameSequence is an iterator."""
   18.96 -
   18.97 -    characters = ("abcdefghijklmnopqrstuvwxyz" +
   18.98 -                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
   18.99 -                  "0123456789-_")
  18.100 -
  18.101 -    def __init__(self):
  18.102 -        self.mutex = _allocate_lock()
  18.103 -        self.rng = _Random()
  18.104 -        self.normcase = _os.path.normcase
  18.105 -
  18.106 -    def __iter__(self):
  18.107 -        return self
  18.108 -
  18.109 -    def next(self):
  18.110 -        m = self.mutex
  18.111 -        c = self.characters
  18.112 -        choose = self.rng.choice
  18.113 -
  18.114 -        m.acquire()
  18.115 -        try:
  18.116 -            letters = [choose(c) for dummy in "123456"]
  18.117 -        finally:
  18.118 -            m.release()
  18.119 -
  18.120 -        return self.normcase(''.join(letters))
  18.121 -
  18.122 -def _candidate_tempdir_list():
  18.123 -    """Generate a list of candidate temporary directories which
  18.124 -    _get_default_tempdir will try."""
  18.125 -
  18.126 -    dirlist = []
  18.127 -
  18.128 -    # First, try the environment.
  18.129 -    for envname in 'TMPDIR', 'TEMP', 'TMP':
  18.130 -        dirname = _os.getenv(envname)
  18.131 -        if dirname: dirlist.append(dirname)
  18.132 -
  18.133 -    # Failing that, try OS-specific locations.
  18.134 -    if _os.name == 'mac':
  18.135 -        try:
  18.136 -            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
  18.137 -                                              _Folders.kTemporaryFolderType, 1)
  18.138 -            dirname = fsr.as_pathname()
  18.139 -            dirlist.append(dirname)
  18.140 -        except _Folder.error:
  18.141 -            pass
  18.142 -    elif _os.name == 'riscos':
  18.143 -        dirname = _os.getenv('Wimp$ScrapDir')
  18.144 -        if dirname: dirlist.append(dirname)
  18.145 -    elif _os.name == 'nt':
  18.146 -        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
  18.147 -    else:
  18.148 -        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
  18.149 -
  18.150 -    # As a last resort, the current directory.
  18.151 -    try:
  18.152 -        dirlist.append(_os.getcwd())
  18.153 -    except (AttributeError, _os.error):
  18.154 -        dirlist.append(_os.curdir)
  18.155 -
  18.156 -    return dirlist
  18.157 -
  18.158 -def _get_default_tempdir():
  18.159 -    """Calculate the default directory to use for temporary files.
  18.160 -    This routine should be called exactly once.
  18.161 -
  18.162 -    We determine whether or not a candidate temp dir is usable by
  18.163 -    trying to create and write to a file in that directory.  If this
  18.164 -    is successful, the test file is deleted.  To prevent denial of
  18.165 -    service, the name of the test file must be randomized."""
  18.166 -
  18.167 -    namer = _RandomNameSequence()
  18.168 -    dirlist = _candidate_tempdir_list()
  18.169 -    flags = _text_openflags
  18.170 -
  18.171 -    for dir in dirlist:
  18.172 -        if dir != _os.curdir:
  18.173 -            dir = _os.path.normcase(_os.path.abspath(dir))
  18.174 -        # Try only a few names per directory.
  18.175 -        for seq in xrange(100):
  18.176 -            name = namer.next()
  18.177 -            filename = _os.path.join(dir, name)
  18.178 -            try:
  18.179 -                fd = _os.open(filename, flags, 0600)
  18.180 -                fp = _os.fdopen(fd, 'w')
  18.181 -                fp.write('blat')
  18.182 -                fp.close()
  18.183 -                _os.unlink(filename)
  18.184 -                del fp, fd
  18.185 -                return dir
  18.186 -            except (OSError, IOError), e:
  18.187 -                if e[0] != _errno.EEXIST:
  18.188 -                    break # no point trying more names in this directory
  18.189 -                pass
  18.190 -    raise IOError, (_errno.ENOENT,
  18.191 -                    ("No usable temporary directory found in %s" % dirlist))
  18.192 -
  18.193 -_name_sequence = None
  18.194 -
  18.195 -def _get_candidate_names():
  18.196 -    """Common setup sequence for all user-callable interfaces."""
  18.197 -
  18.198 -    global _name_sequence
  18.199 -    if _name_sequence is None:
  18.200 -        _once_lock.acquire()
  18.201 -        try:
  18.202 -            if _name_sequence is None:
  18.203 -                _name_sequence = _RandomNameSequence()
  18.204 -        finally:
  18.205 -            _once_lock.release()
  18.206 -    return _name_sequence
  18.207 -
  18.208 -
  18.209 -def _mkstemp_inner(dir, pre, suf, flags):
  18.210 -    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
  18.211 -
  18.212 -    names = _get_candidate_names()
  18.213 -
  18.214 -    for seq in xrange(TMP_MAX):
  18.215 -        name = names.next()
  18.216 -        file = _os.path.join(dir, pre + name + suf)
  18.217 -        try:
  18.218 -            fd = _os.open(file, flags, 0600)
  18.219 -            _set_cloexec(fd)
  18.220 -            return (fd, file)
  18.221 -        except OSError, e:
  18.222 -            if e.errno == _errno.EEXIST:
  18.223 -                continue # try again
  18.224 -            raise
  18.225 -
  18.226 -    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
  18.227 -
  18.228 -
  18.229 -# User visible interfaces.
  18.230 -
  18.231 -def gettempprefix():
  18.232 -    """Accessor for tempdir.template."""
  18.233 -    return template
  18.234 -
  18.235 -tempdir = None
  18.236 -
  18.237 -def gettempdir():
  18.238 -    """Accessor for tempdir.tempdir."""
  18.239 -    global tempdir
  18.240 -    if tempdir is None:
  18.241 -        _once_lock.acquire()
  18.242 -        try:
  18.243 -            if tempdir is None:
  18.244 -                tempdir = _get_default_tempdir()
  18.245 -        finally:
  18.246 -            _once_lock.release()
  18.247 -    return tempdir
  18.248 -
  18.249 -def mkstemp(suffix="", prefix=template, dir=None, text=False):
  18.250 -    """mkstemp([suffix, [prefix, [dir, [text]]]])
  18.251 -    User-callable function to create and return a unique temporary
  18.252 -    file.  The return value is a pair (fd, name) where fd is the
  18.253 -    file descriptor returned by os.open, and name is the filename.
  18.254 -
  18.255 -    If 'suffix' is specified, the file name will end with that suffix,
  18.256 -    otherwise there will be no suffix.
  18.257 -
  18.258 -    If 'prefix' is specified, the file name will begin with that prefix,
  18.259 -    otherwise a default prefix is used.
  18.260 -
  18.261 -    If 'dir' is specified, the file will be created in that directory,
  18.262 -    otherwise a default directory is used.
  18.263 -
  18.264 -    If 'text' is specified and true, the file is opened in text
  18.265 -    mode.  Else (the default) the file is opened in binary mode.  On
  18.266 -    some operating systems, this makes no difference.
  18.267 -
  18.268 -    The file is readable and writable only by the creating user ID.
  18.269 -    If the operating system uses permission bits to indicate whether a
  18.270 -    file is executable, the file is executable by no one. The file
  18.271 -    descriptor is not inherited by children of this process.
  18.272 -
  18.273 -    Caller is responsible for deleting the file when done with it.
  18.274 -    """
  18.275 -
  18.276 -    if dir is None:
  18.277 -        dir = gettempdir()
  18.278 -
  18.279 -    if text:
  18.280 -        flags = _text_openflags
  18.281 -    else:
  18.282 -        flags = _bin_openflags
  18.283 -
  18.284 -    return _mkstemp_inner(dir, prefix, suffix, flags)
  18.285 -
  18.286 -
  18.287 -def mkdtemp(suffix="", prefix=template, dir=None):
  18.288 -    """mkdtemp([suffix, [prefix, [dir]]])
  18.289 -    User-callable function to create and return a unique temporary
  18.290 -    directory.  The return value is the pathname of the directory.
  18.291 -
  18.292 -    Arguments are as for mkstemp, except that the 'text' argument is
  18.293 -    not accepted.
  18.294 -
  18.295 -    The directory is readable, writable, and searchable only by the
  18.296 -    creating user.
  18.297 -
  18.298 -    Caller is responsible for deleting the directory when done with it.
  18.299 -    """
  18.300 -
  18.301 -    if dir is None:
  18.302 -        dir = gettempdir()
  18.303 -
  18.304 -    names = _get_candidate_names()
  18.305 -
  18.306 -    for seq in xrange(TMP_MAX):
  18.307 -        name = names.next()
  18.308 -        file = _os.path.join(dir, prefix + name + suffix)
  18.309 -        try:
  18.310 -            _os.mkdir(file, 0700)
  18.311 -            return file
  18.312 -        except OSError, e:
  18.313 -            if e.errno == _errno.EEXIST:
  18.314 -                continue # try again
  18.315 -            raise
  18.316 -
  18.317 -    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
  18.318 -
  18.319 -def mktemp(suffix="", prefix=template, dir=None):
  18.320 -    """mktemp([suffix, [prefix, [dir]]])
  18.321 -    User-callable function to return a unique temporary file name.  The
  18.322 -    file is not created.
  18.323 -
  18.324 -    Arguments are as for mkstemp, except that the 'text' argument is
  18.325 -    not accepted.
  18.326 -
  18.327 -    This function is unsafe and should not be used.  The file name
  18.328 -    refers to a file that did not exist at some point, but by the time
  18.329 -    you get around to creating it, someone else may have beaten you to
  18.330 -    the punch.
  18.331 -    """
  18.332 -
  18.333 -##    from warnings import warn as _warn
  18.334 -##    _warn("mktemp is a potential security risk to your program",
  18.335 -##          RuntimeWarning, stacklevel=2)
  18.336 -
  18.337 -    if dir is None:
  18.338 -        dir = gettempdir()
  18.339 -
  18.340 -    names = _get_candidate_names()
  18.341 -    for seq in xrange(TMP_MAX):
  18.342 -        name = names.next()
  18.343 -        file = _os.path.join(dir, prefix + name + suffix)
  18.344 -        if not _os.path.exists(file):
  18.345 -            return file
  18.346 -
  18.347 -    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
  18.348 -
  18.349 -class _TemporaryFileWrapper:
  18.350 -    """Temporary file wrapper
  18.351 -
  18.352 -    This class provides a wrapper around files opened for
  18.353 -    temporary use.  In particular, it seeks to automatically
  18.354 -    remove the file when it is no longer needed.
  18.355 -    """
  18.356 -
  18.357 -    def __init__(self, file, name):
  18.358 -        self.file = file
  18.359 -        self.name = name
  18.360 -        self.close_called = False
  18.361 -
  18.362 -    def __getattr__(self, name):
  18.363 -        file = self.__dict__['file']
  18.364 -        a = getattr(file, name)
  18.365 -        if type(a) != type(0):
  18.366 -            setattr(self, name, a)
  18.367 -        return a
  18.368 -
  18.369 -    # NT provides delete-on-close as a primitive, so we don't need
  18.370 -    # the wrapper to do anything special.  We still use it so that
  18.371 -    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
  18.372 -    if _os.name != 'nt':
  18.373 -
  18.374 -        # Cache the unlinker so we don't get spurious errors at
  18.375 -        # shutdown when the module-level "os" is None'd out.  Note
  18.376 -        # that this must be referenced as self.unlink, because the
  18.377 -        # name TemporaryFileWrapper may also get None'd out before
  18.378 -        # __del__ is called.
  18.379 -        unlink = _os.unlink
  18.380 -
  18.381 -        def close(self):
  18.382 -            if not self.close_called:
  18.383 -                self.close_called = True
  18.384 -                self.file.close()
  18.385 -                self.unlink(self.name)
  18.386 -
  18.387 -        def __del__(self):
  18.388 -            self.close()
  18.389 -
  18.390 -def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
  18.391 -                       prefix=template, dir=None):
  18.392 -    """Create and return a temporary file.
  18.393 -    Arguments:
  18.394 -    'prefix', 'suffix', 'dir' -- as for mkstemp.
  18.395 -    'mode' -- the mode argument to os.fdopen (default "w+b").
  18.396 -    'bufsize' -- the buffer size argument to os.fdopen (default -1).
  18.397 -    The file is created as mkstemp() would do it.
  18.398 -
  18.399 -    Returns a file object; the name of the file is accessible as
  18.400 -    file.name.  The file will be automatically deleted when it is
  18.401 -    closed.
  18.402 -    """
  18.403 -
  18.404 -    if dir is None:
  18.405 -        dir = gettempdir()
  18.406 -
  18.407 -    if 'b' in mode:
  18.408 -        flags = _bin_openflags
  18.409 -    else:
  18.410 -        flags = _text_openflags
  18.411 -
  18.412 -    # Setting O_TEMPORARY in the flags causes the OS to delete
  18.413 -    # the file when it is closed.  This is only supported by Windows.
  18.414 -    if _os.name == 'nt':
  18.415 -        flags |= _os.O_TEMPORARY
  18.416 -
  18.417 -    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  18.418 -    file = _os.fdopen(fd, mode, bufsize)
  18.419 -    return _TemporaryFileWrapper(file, name)
  18.420 -
  18.421 -if _os.name != 'posix' or _os.sys.platform == 'cygwin':
  18.422 -    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
  18.423 -    # while it is open.
  18.424 -    TemporaryFile = NamedTemporaryFile
  18.425 -
  18.426 -else:
  18.427 -    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
  18.428 -                      prefix=template, dir=None):
  18.429 -        """Create and return a temporary file.
  18.430 -        Arguments:
  18.431 -        'prefix', 'suffix', 'directory' -- as for mkstemp.
  18.432 -        'mode' -- the mode argument to os.fdopen (default "w+b").
  18.433 -        'bufsize' -- the buffer size argument to os.fdopen (default -1).
  18.434 -        The file is created as mkstemp() would do it.
  18.435 -
  18.436 -        Returns a file object.  The file has no name, and will cease to
  18.437 -        exist when it is closed.
  18.438 -        """
  18.439 -
  18.440 -        if dir is None:
  18.441 -            dir = gettempdir()
  18.442 -
  18.443 -        if 'b' in mode:
  18.444 -            flags = _bin_openflags
  18.445 -        else:
  18.446 -            flags = _text_openflags
  18.447 -
  18.448 -        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  18.449 -        try:
  18.450 -            _os.unlink(name)
  18.451 -            return _os.fdopen(fd, mode, bufsize)
  18.452 -        except:
  18.453 -            _os.close(fd)
  18.454 -            raise
    19.1 --- a/tools/xenctl/lib/utils.py	Fri Jun 25 15:10:48 2004 +0000
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,944 +0,0 @@
    19.4 -import os, re, socket, string, sys, tempfile, xenctl.ip
    19.5 -
    19.6 -##### Module variables
    19.7 -
    19.8 -"""Location of the Virtual Disk management database.
    19.9 -   defaults to /var/db/xen_vdisks.sqlite
   19.10 -"""
   19.11 -VD_DB_FILE = "/var/db/xen_vdisks.sqlite"
   19.12 -
   19.13 -"""VBD expertise level - determines the strictness of the sanity checking.
   19.14 -  This mode determines the level of complaints when disk sharing occurs
   19.15 -  through the current VBD mappings.
   19.16 -   0 - only allow shared mappings if both domains have r/o access (always OK)
   19.17 -   1 - also allow sharing with one dom r/w and the other r/o
   19.18 -   2 - allow sharing with both doms r/w
   19.19 -"""
   19.20 -VBD_EXPERT_MODE = 0
   19.21 -
   19.22 -##### Module initialisation
   19.23 -
   19.24 -try:
   19.25 -    # try to import sqlite (not everyone will have it installed)
   19.26 -    import sqlite
   19.27 -except ImportError:
   19.28 -    # on failure, just catch the error, don't do anything
   19.29 -    pass
   19.30 -
   19.31 -
   19.32 -##### Networking-related functions
   19.33 -
   19.34 -def get_current_ipaddr(dev='eth0'):
   19.35 -    return xenctl.ip.get_current_ipaddr(dev)
   19.36 -def get_current_ipmask(dev='eth0'):
   19.37 -    return xenctl.ip.get_current_ipmask(dev)
   19.38 -def get_current_ipgw(dev='eth0'):
   19.39 -    return xenctl.ip.get_current_ipgw(dev)
   19.40 -def setup_vfr_rules_for_vif(dom,vif,addr):
   19.41 -    return xenctl.ip.setup_vfr_rules_for_vif(dom,vif,addr)
   19.42 -def inet_aton(addr):
   19.43 -    return xenctl.ip.inet_aton(addr)
   19.44 -def inet_ntoa(n):
   19.45 -    return xenctl.ip.inet_ntoa(n)
   19.46 -def add_offset_to_ip(addr, offset):
   19.47 -    return xenctl.ip.add_offset_to_ip(addr, offset)
   19.48 -def check_subnet( ip, network, netmask ):
   19.49 -    return xenctl.ip.check_subnet( ip, network, netmask )
   19.50 -
   19.51 -##### VBD-related Functions
   19.52 -
   19.53 -def blkdev_name_to_number(name):
   19.54 -    """Take the given textual block-device name (e.g., '/dev/sda1',
   19.55 -    'hda') and return the device number used by the OS. """
   19.56 -
   19.57 -    if not re.match( '/dev/', name ):
   19.58 -        name = '/dev/' + name
   19.59 -        
   19.60 -    return os.stat(name).st_rdev
   19.61 -
   19.62 -# lookup_blkdev_partn_info( '/dev/sda3' )
   19.63 -def lookup_raw_partn(partition):
   19.64 -    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
   19.65 -    and return a dictionary { device, start_sector,
   19.66 -    nr_sectors, type }
   19.67 -        device:       Device number of the given partition
   19.68 -        start_sector: Index of first sector of the partition
   19.69 -        nr_sectors:   Number of sectors comprising this partition
   19.70 -        type:         'Disk' or identifying name for partition type
   19.71 -    """
   19.72 -
   19.73 -    if not re.match( '/dev/', partition ):
   19.74 -        partition = '/dev/' + partition
   19.75 -
   19.76 -    drive = re.split( '[0-9]', partition )[0]
   19.77 -
   19.78 -    if drive == partition:
   19.79 -        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
   19.80 -        line = fd.readline()
   19.81 -        if line:
   19.82 -            return [ { 'device' : blkdev_name_to_number(drive),
   19.83 -                       'start_sector' : long(0),
   19.84 -                       'nr_sectors' : long(line) * 2,
   19.85 -                       'type' : 'Disk' } ]
   19.86 -        return None
   19.87 -
   19.88 -    # determine position on disk
   19.89 -    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
   19.90 -
   19.91 -    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
   19.92 -    lines = fd.readlines()
   19.93 -    for line in lines:
   19.94 -        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
   19.95 -                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
   19.96 -        if m:
   19.97 -            return [ { 'device' : blkdev_name_to_number(drive),
   19.98 -                       'start_sector' : long(m.group(1)),
   19.99 -                       'nr_sectors' : long(m.group(2)),
  19.100 -                       'type' : m.group(3) } ]
  19.101 -    
  19.102 -    return None
  19.103 -
  19.104 -def lookup_disk_uname( uname ):
  19.105 -    """Lookup a list of segments for either a physical or a virtual device.
  19.106 -    uname [string]:  name of the device in the format \'vd:id\' for a virtual
  19.107 -                     disk, or \'phy:dev\' for a physical device
  19.108 -    returns [list of dicts]: list of extents that make up the named device
  19.109 -    """
  19.110 -    ( type, d_name ) = string.split( uname, ':' )
  19.111 -
  19.112 -    if type == "phy":
  19.113 -        segments = lookup_raw_partn( d_name )
  19.114 -    elif type == "vd":
  19.115 -	segments = vd_lookup( d_name )
  19.116 -
  19.117 -    return segments
  19.118 -
  19.119 -
  19.120 -##### Management of the Xen control daemon
  19.121 -##### (c) Keir Fraser, University of Cambridge
  19.122 -
  19.123 -def xend_control_message( message ):
  19.124 -    """Takes a textual control message and sends it to the 'xend' Xen
  19.125 -    control daemon. Returns a dictionary containing the daemon's multi-part
  19.126 -    response."""
  19.127 -    tmpdir = tempfile.mkdtemp()
  19.128 -    try:
  19.129 -        ctl = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
  19.130 -        ctl.bind(tmpdir+'/sock')
  19.131 -        ctl.sendto(message, '/var/run/xend/management_sock')
  19.132 -        data, addr = ctl.recvfrom(2048)
  19.133 -        ctl.close()
  19.134 -    finally:
  19.135 -        if os.path.exists(tmpdir+'/sock'):
  19.136 -            os.unlink(tmpdir+'/sock')
  19.137 -        if os.path.exists(tmpdir):
  19.138 -            os.rmdir(tmpdir)    
  19.139 -    return eval(data)
  19.140 -
  19.141 -
  19.142 -##### VD Management-related functions
  19.143 -
  19.144 -##### By Mark Williamson, <mark.a.williamson@intel.com>
  19.145 -##### (C) Intel Research Cambridge
  19.146 -
  19.147 -# TODO:
  19.148 -#
  19.149 -# Plenty of room for enhancement to this functionality (contributions
  19.150 -# welcome - and then you get to have your name in the source ;-)...
  19.151 -#
  19.152 -# vd_unformat() : want facilities to unallocate virtual disk
  19.153 -# partitions, possibly migrating virtual disks of them, with checks to see if
  19.154 -# it's safe and options to force it anyway
  19.155 -#
  19.156 -# vd_create() : should have an optional argument specifying a physical
  19.157 -# disk preference - useful to allocate for guest doms to do RAID
  19.158 -#
  19.159 -# vd_undelete() : add ability to "best effort" undelete as much of a
  19.160 -# vdisk as is left in the case that some of it has already been
  19.161 -# reallocated.  Some people might still be able to recover some of
  19.162 -# their data this way, even if some of the disk has disappeared.
  19.163 -#
  19.164 -# It'd be nice if we could wipe virtual disks for security purposes -
  19.165 -# should be easy to do this using dev if=/dev/{zero,random} on each
  19.166 -# extent in turn.  There could be another optional flag to vd_create
  19.167 -# in order to allow this.
  19.168 -#
  19.169 -# Error codes could be more expressive - i.e. actually tell why the
  19.170 -# error occurred rather than "it broke".  Currently the code avoids
  19.171 -# using exceptions to make control scripting simpler and more
  19.172 -# accessible to beginners - therefore probably should just use more
  19.173 -# return codes.
  19.174 -#
  19.175 -# Enhancements / additions to the example scripts are also welcome:
  19.176 -# some people will interact with this code mostly through those
  19.177 -# scripts.
  19.178 -#
  19.179 -# More documentation of how this stuff should be used is always nice -
  19.180 -# if you have a novel configuration that you feel isn't discussed
  19.181 -# enough in the HOWTO (which is currently a work in progress), feel
  19.182 -# free to contribute a walkthrough, or something more substantial.
  19.183 -#
  19.184 -
  19.185 -
  19.186 -def __vd_no_database():
  19.187 -    """Called when no database found - exits with an error
  19.188 -    """
  19.189 -    print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE
  19.190 -    sys.exit(1)
  19.191 -
  19.192 -
  19.193 -def vd_format(partition, extent_size_mb):
  19.194 -    """Format a partition or drive for use a virtual disk storage.
  19.195 -    partition [string]: device file representing the partition
  19.196 -    extent_size_mb [string]: extent size in megabytes to use on this disk
  19.197 -    """
  19.198 -
  19.199 -    if not os.path.isfile(VD_DB_FILE):
  19.200 -        vd_init_db(VD_DB_FILE)
  19.201 -    
  19.202 -    if not re.match( '/dev/', partition ):
  19.203 -        partition = '/dev/' + partition
  19.204 -
  19.205 -    cx = sqlite.connect(VD_DB_FILE)
  19.206 -    cu = cx.cursor()
  19.207 -
  19.208 -    cu.execute("select * from vdisk_part where partition = \'"
  19.209 -               + partition + "\'")
  19.210 -    row = cu.fetchone()
  19.211 -
  19.212 -    extent_size = extent_size_mb * 2048 # convert megabytes to sectors
  19.213 -    
  19.214 -    if not row:
  19.215 -        part_info = lookup_raw_partn(partition)[0]
  19.216 -        
  19.217 -        cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " +
  19.218 -                   "VALUES ( \'" + partition + "\', "
  19.219 -                   + str(blkdev_name_to_number(partition))
  19.220 -                   + ", " + str(extent_size) + ")")
  19.221 -
  19.222 -
  19.223 -        cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents "
  19.224 -                   + "WHERE vdisk_id = 0")
  19.225 -        
  19.226 -        max_id, = cu.fetchone()
  19.227 -
  19.228 -        if max_id != None:
  19.229 -            new_id = max_id + 1
  19.230 -        else:
  19.231 -            new_id = 0
  19.232 -
  19.233 -        num_extents = part_info['nr_sectors'] / extent_size
  19.234 -
  19.235 -        for i in range(num_extents):
  19.236 -            sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id,
  19.237 -                                              part_id, part_extent_no)
  19.238 -                    VALUES ("""+ str(new_id + i) + ", 0, "\
  19.239 -                               + str(blkdev_name_to_number(partition))\
  19.240 -                               + ", " + str(num_extents - (i + 1)) + ")"
  19.241 -            cu.execute(sql)
  19.242 -
  19.243 -    cx.commit()
  19.244 -    cx.close()
  19.245 -    return 0
  19.246 -
  19.247 -
  19.248 -def vd_create(size_mb, expiry):
  19.249 -    """Create a new virtual disk.
  19.250 -    size_mb [int]: size in megabytes for the new virtual disk
  19.251 -    expiry [int]: expiry time in seconds from now
  19.252 -    """
  19.253 -
  19.254 -    if not os.path.isfile(VD_DB_FILE):
  19.255 -        __vd_no_database()
  19.256 -
  19.257 -    cx = sqlite.connect(VD_DB_FILE)
  19.258 -    cu = cx.cursor()
  19.259 -
  19.260 -    size = size_mb * 2048
  19.261 -
  19.262 -    cu.execute("SELECT max(vdisk_id) FROM vdisks")
  19.263 -    max_id, = cu.fetchone()
  19.264 -    new_id = int(max_id) + 1
  19.265 -
  19.266 -    # fetch a list of extents from the expired disks, along with information
  19.267 -    # about their size
  19.268 -    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
  19.269 -                         vdisk_extents.part_id, extent_size
  19.270 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.271 -                                                  NATURAL JOIN vdisk_part
  19.272 -                  WHERE expires AND expiry_time <= datetime('now')
  19.273 -                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
  19.274 -               """)  # aims to reuse the last extents
  19.275 -                     # from the longest-expired disks first
  19.276 -
  19.277 -    allocated = 0
  19.278 -
  19.279 -    if expiry:
  19.280 -        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
  19.281 -        expires = 1
  19.282 -    else:
  19.283 -        expiry_ts = "NULL"
  19.284 -        expires = 0
  19.285 -
  19.286 -    # we'll use this to build the SQL statement we want
  19.287 -    building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \
  19.288 -                   +" VALUES ("+str(new_id)+", "+str(size)+ ", "              \
  19.289 -                   + str(expires) + ", " + expiry_ts + "); "
  19.290 -
  19.291 -    counter = 0
  19.292 -
  19.293 -    while allocated < size:
  19.294 -        row = cu.fetchone()
  19.295 -        if not row:
  19.296 -            print "ran out of space, having allocated %d meg of %d" % (allocated, size)
  19.297 -            cx.close()
  19.298 -            return -1
  19.299 -        
  19.300 -
  19.301 -        (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
  19.302 -        allocated += extent_size
  19.303 -        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \
  19.304 -                        + ", " + "vdisk_extent_no = " + str(counter)         \
  19.305 -                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
  19.306 -                        + " AND vdisk_id = " + str(vdisk_id) + "; "
  19.307 -
  19.308 -        counter += 1
  19.309 -        
  19.310 -
  19.311 -    # this will execute the SQL query we build to store details of the new
  19.312 -    # virtual disk and allocate space to it print building_sql
  19.313 -    cu.execute(building_sql)
  19.314 -    
  19.315 -    cx.commit()
  19.316 -    cx.close()
  19.317 -    return str(new_id)
  19.318 -
  19.319 -
  19.320 -def vd_lookup(id):
  19.321 -    """Lookup a Virtual Disk by ID.
  19.322 -    id [string]: a virtual disk identifier
  19.323 -    Returns [list of dicts]: a list of extents as dicts, containing fields:
  19.324 -                             device : Linux device number of host disk
  19.325 -                             start_sector : within the device
  19.326 -                             nr_sectors : size of this extent
  19.327 -                             type : set to \'VD Extent\'
  19.328 -                             
  19.329 -                             part_device : Linux device no of host partition
  19.330 -                             part_start_sector : within the partition
  19.331 -    """
  19.332 -
  19.333 -    if not os.path.isfile(VD_DB_FILE):
  19.334 -        __vd_no_database()
  19.335 -
  19.336 -    cx = sqlite.connect(VD_DB_FILE)
  19.337 -    cu = cx.cursor()
  19.338 -
  19.339 -    cu.execute("-- types int")
  19.340 -    cu.execute("""SELECT COUNT(*)
  19.341 -                  FROM vdisks
  19.342 -                  WHERE (expiry_time > datetime('now') OR NOT expires)
  19.343 -                              AND vdisk_id = """ + id)
  19.344 -    count, = cu.fetchone()
  19.345 -
  19.346 -    if not count:
  19.347 -        cx.close()
  19.348 -        return None
  19.349 -
  19.350 -    cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id)
  19.351 -    real_size, = cu.fetchone()
  19.352 -  
  19.353 -    # This query tells PySQLite how to convert the data returned from the
  19.354 -    # following query - the use of the multiplication confuses it otherwise ;-)
  19.355 -    # This row is significant to PySQLite but is syntactically an SQL comment.
  19.356 -
  19.357 -    cu.execute("-- types str, int, int, int")
  19.358 -
  19.359 -    # This SQL statement is designed so that when the results are fetched they
  19.360 -    # will be in the right format to return immediately.
  19.361 -    cu.execute("""SELECT partition, vdisk_part.part_id,
  19.362 -                         round(part_extent_no * extent_size) as start,
  19.363 -                         extent_size
  19.364 -                         
  19.365 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.366 -                                             NATURAL JOIN vdisk_part
  19.367 -                                                
  19.368 -                  WHERE vdisk_extents.vdisk_id = """ + id
  19.369 -               + " ORDER BY vdisk_extents.vdisk_extent_no ASC"
  19.370 -               )
  19.371 -
  19.372 -    extent_tuples = cu.fetchall()
  19.373 -
  19.374 -    # use this function to map the results from the database into a dict
  19.375 -    # list of extents, for consistency with the rest of the code
  19.376 -    def transform ((partition, part_device, part_offset, nr_sectors)):
  19.377 -        return {
  19.378 -                 # the disk device this extent is on - for passing to Xen
  19.379 -                 'device' : lookup_raw_partn(partition)[0]['device'],
  19.380 -                 # the offset of this extent within the disk - for passing to Xen
  19.381 -                 'start_sector' : long(part_offset + lookup_raw_partn(partition)[0]['start_sector']),
  19.382 -                 # extent size, in sectors
  19.383 -                 'nr_sectors' : nr_sectors,
  19.384 -                 # partition device this extent is on (useful to know for xenctl.utils fns)
  19.385 -                 'part_device' : part_device,
  19.386 -                 # start sector within this partition (useful to know for xenctl.utils fns)
  19.387 -                 'part_start_sector' : part_offset,
  19.388 -                 # type of this extent - handy to know
  19.389 -                 'type' : 'VD Extent' }
  19.390 -
  19.391 -    cx.commit()
  19.392 -    cx.close()
  19.393 -
  19.394 -    extent_dicts = map(transform, extent_tuples)
  19.395 -
  19.396 -    # calculate the over-allocation in sectors (happens because
  19.397 -    # we allocate whole extents)
  19.398 -    allocated_size = 0
  19.399 -    for i in extent_dicts:
  19.400 -        allocated_size += i['nr_sectors']
  19.401 -
  19.402 -    over_allocation = allocated_size - real_size
  19.403 -
  19.404 -    # trim down the last extent's length so the resulting VBD will be the
  19.405 -    # size requested, rather than being rounded up to the nearest extent
  19.406 -    extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation
  19.407 -
  19.408 -    return extent_dicts
  19.409 -
  19.410 -
  19.411 -def vd_enlarge(vdisk_id, extra_size_mb):
  19.412 -    """Create a new virtual disk.
  19.413 -    vdisk_id [string]   :    ID of the virtual disk to enlarge
  19.414 -    extra_size_mb  [int]:    size in megabytes to increase the allocation by
  19.415 -    returns  [int]      :    0 on success, otherwise non-zero
  19.416 -    """
  19.417 -
  19.418 -    if not os.path.isfile(VD_DB_FILE):
  19.419 -        __vd_no_database()
  19.420 -
  19.421 -    cx = sqlite.connect(VD_DB_FILE)
  19.422 -    cu = cx.cursor()
  19.423 -
  19.424 -    extra_size = extra_size_mb * 2048
  19.425 -
  19.426 -    cu.execute("-- types int")
  19.427 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id
  19.428 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
  19.429 -    count, = cu.fetchone()
  19.430 -
  19.431 -    if not count: # no such vdisk
  19.432 -        cx.close()
  19.433 -        return -1
  19.434 -
  19.435 -    cu.execute("-- types int")
  19.436 -    cu.execute("""SELECT SUM(extent_size)
  19.437 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.438 -                                         NATURAL JOIN vdisk_part
  19.439 -                  WHERE vdisks.vdisk_id = """ + vdisk_id)
  19.440 -
  19.441 -    real_size, = cu.fetchone() # get the true allocated size
  19.442 -
  19.443 -    cu.execute("-- types int")
  19.444 -    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
  19.445 -
  19.446 -    old_size, = cu.fetchone()
  19.447 -
  19.448 -
  19.449 -    cu.execute("--- types int")
  19.450 -    cu.execute("""SELECT MAX(vdisk_extent_no)
  19.451 -                  FROM vdisk_extents
  19.452 -                  WHERE vdisk_id = """ + vdisk_id)
  19.453 -
  19.454 -    counter = cu.fetchone()[0] + 1 # this stores the extent numbers
  19.455 -
  19.456 -
  19.457 -    # because of the extent-based allocation, the VD may already have more
  19.458 -    # allocated space than they asked for.  Find out how much we really
  19.459 -    # need to add.
  19.460 -    add_size = extra_size + old_size - real_size
  19.461 -
  19.462 -    # fetch a list of extents from the expired disks, along with information
  19.463 -    # about their size
  19.464 -    cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
  19.465 -                         vdisk_extents.part_id, extent_size
  19.466 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.467 -                                                  NATURAL JOIN vdisk_part
  19.468 -                  WHERE expires AND expiry_time <= datetime('now')
  19.469 -                  ORDER BY expiry_time ASC, vdisk_extent_no DESC
  19.470 -               """)  # aims to reuse the last extents
  19.471 -                     # from the longest-expired disks first
  19.472 -
  19.473 -    allocated = 0
  19.474 -
  19.475 -    building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\
  19.476 -                   + " WHERE vdisk_id = " + vdisk_id + "; "
  19.477 -
  19.478 -    while allocated < add_size:
  19.479 -        row = cu.fetchone()
  19.480 -        if not row:
  19.481 -            cx.close()
  19.482 -            return -1
  19.483 -
  19.484 -        (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
  19.485 -        allocated += extent_size
  19.486 -        building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id    \
  19.487 -                        + ", " + "vdisk_extent_no = " + str(counter)         \
  19.488 -                        + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
  19.489 -                        + " AND vdisk_id = " + str(dead_vd_id) + "; "
  19.490 -
  19.491 -        counter += 1
  19.492 -        
  19.493 -
  19.494 -    # this will execute the SQL query we build to store details of the new
  19.495 -    # virtual disk and allocate space to it print building_sql
  19.496 -    cu.execute(building_sql)
  19.497 -    
  19.498 -    cx.commit()
  19.499 -    cx.close()
  19.500 -    return 0
  19.501 -
  19.502 -
  19.503 -def vd_undelete(vdisk_id, expiry_time):
  19.504 -    """Create a new virtual disk.
  19.505 -    vdisk_id      [int]: size in megabytes for the new virtual disk
  19.506 -    expiry_time   [int]: expiry time, in seconds from now
  19.507 -    returns       [int]: zero on success, non-zero on failure
  19.508 -    """
  19.509 -
  19.510 -    if not os.path.isfile(VD_DB_FILE):
  19.511 -        __vd_no_database()
  19.512 -
  19.513 -    if vdisk_id == '0': #  undeleting vdisk 0 isn't sane!
  19.514 -        return -1
  19.515 -
  19.516 -    cx = sqlite.connect(VD_DB_FILE)
  19.517 -    cu = cx.cursor()
  19.518 -
  19.519 -    cu.execute("-- types int")
  19.520 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id)
  19.521 -    count, = cu.fetchone()
  19.522 -
  19.523 -    if not count:
  19.524 -        cx.close()
  19.525 -        return -1
  19.526 -
  19.527 -    cu.execute("-- types int")
  19.528 -    cu.execute("""SELECT SUM(extent_size)
  19.529 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.530 -                                         NATURAL JOIN vdisk_part
  19.531 -                  WHERE vdisks.vdisk_id = """ + vdisk_id)
  19.532 -
  19.533 -    real_size, = cu.fetchone() # get the true allocated size
  19.534 -
  19.535 -
  19.536 -    cu.execute("-- types int")
  19.537 -    cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
  19.538 -
  19.539 -    old_size, = cu.fetchone()
  19.540 -
  19.541 -    if real_size < old_size:
  19.542 -        cx.close()
  19.543 -        return -1
  19.544 -
  19.545 -    if expiry_time == 0:
  19.546 -        expires = '0'
  19.547 -    else:
  19.548 -        expires = '1'
  19.549 -
  19.550 -    # this will execute the SQL query we build to store details of the new
  19.551 -    # virtual disk and allocate space to it print building_sql
  19.552 -    cu.execute("UPDATE vdisks SET expiry_time = datetime('now','"
  19.553 -               + str(expiry_time) + " seconds'), expires = " + expires
  19.554 -               + " WHERE vdisk_id = " + vdisk_id)
  19.555 -    
  19.556 -    cx.commit()
  19.557 -    cx.close()
  19.558 -    return 0
  19.559 -
  19.560 -
  19.561 -
  19.562 -
  19.563 -def vd_list():
  19.564 -    """Lists all the virtual disks registered in the system.
  19.565 -    returns [list of dicts]
  19.566 -    """
  19.567 -    
  19.568 -    if not os.path.isfile(VD_DB_FILE):
  19.569 -        __vd_no_database()
  19.570 -
  19.571 -    cx = sqlite.connect(VD_DB_FILE)
  19.572 -    cu = cx.cursor()
  19.573 -
  19.574 -    cu.execute("""SELECT vdisk_id, size, expires, expiry_time
  19.575 -                  FROM vdisks
  19.576 -                  WHERE (NOT expires) OR expiry_time > datetime('now')
  19.577 -               """)
  19.578 -
  19.579 -    ret = cu.fetchall()
  19.580 -
  19.581 -    cx.close()
  19.582 -
  19.583 -    def makedicts((vdisk_id, size, expires, expiry_time)):
  19.584 -        return { 'vdisk_id' : str(vdisk_id), 'size': size,
  19.585 -                 'expires' : expires, 'expiry_time' : expiry_time }
  19.586 -
  19.587 -    return map(makedicts, ret)
  19.588 -
  19.589 -
  19.590 -def vd_refresh(id, expiry):
  19.591 -    """Change the expiry time of a virtual disk.
  19.592 -    id [string]  : a virtual disk identifier
  19.593 -    expiry [int] : expiry time in seconds from now (0 = never expire)
  19.594 -    returns [int]: zero on success, non-zero on failure
  19.595 -    """
  19.596 -
  19.597 -    if not os.path.isfile(VD_DB_FILE):
  19.598 -        __vd_no_database()
  19.599 -    
  19.600 -    cx = sqlite.connect(VD_DB_FILE)
  19.601 -    cu = cx.cursor()
  19.602 -
  19.603 -    cu.execute("-- types int")
  19.604 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
  19.605 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
  19.606 -    count, = cu.fetchone()
  19.607 -
  19.608 -    if not count:
  19.609 -        cx.close()
  19.610 -        return -1
  19.611 -
  19.612 -    if expiry:
  19.613 -        expires = 1
  19.614 -        expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
  19.615 -    else:
  19.616 -        expires = 0
  19.617 -        expiry_ts = "NULL"
  19.618 -
  19.619 -    cu.execute("UPDATE vdisks SET expires = " + str(expires)
  19.620 -               + ", expiry_time = " + expiry_ts
  19.621 -               + " WHERE (expiry_time > datetime('now') OR NOT expires)"
  19.622 -               + " AND vdisk_id = " + id)
  19.623 -
  19.624 -    cx.commit()
  19.625 -    cx.close()
  19.626 -    
  19.627 -    return 0
  19.628 -
  19.629 -
  19.630 -def vd_delete(id):
  19.631 -    """Deletes a Virtual Disk, making its extents available for future VDs.
  19.632 -       id [string]   : identifier for the virtual disk to delete
  19.633 -       returns [int] : 0 on success, -1 on failure (VD not found
  19.634 -                       or already deleted)
  19.635 -    """
  19.636 -
  19.637 -    if not os.path.isfile(VD_DB_FILE):
  19.638 -        __vd_no_database()
  19.639 -    
  19.640 -    cx = sqlite.connect(VD_DB_FILE)
  19.641 -    cu = cx.cursor()
  19.642 -
  19.643 -    cu.execute("-- types int")
  19.644 -    cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
  19.645 -               + " AND (expiry_time > datetime('now') OR NOT expires)")
  19.646 -    count, = cu.fetchone()
  19.647 -
  19.648 -    if not count:
  19.649 -        cx.close()
  19.650 -        return -1
  19.651 -
  19.652 -    cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')"
  19.653 -               + " WHERE vdisk_id = " + id)
  19.654 -
  19.655 -    cx.commit()
  19.656 -    cx.close()
  19.657 -    
  19.658 -    return 0
  19.659 -
  19.660 -
  19.661 -def vd_freespace():
  19.662 -    """Returns the amount of free space available for new virtual disks, in MB
  19.663 -    returns [int] : free space for VDs in MB
  19.664 -    """
  19.665 -
  19.666 -    if not os.path.isfile(VD_DB_FILE):
  19.667 -        __vd_no_database()
  19.668 - 
  19.669 -    cx = sqlite.connect(VD_DB_FILE)
  19.670 -    cu = cx.cursor()
  19.671 -
  19.672 -    cu.execute("-- types int")
  19.673 -
  19.674 -    cu.execute("""SELECT SUM(extent_size)
  19.675 -                  FROM vdisks NATURAL JOIN vdisk_extents
  19.676 -                                           NATURAL JOIN vdisk_part
  19.677 -                  WHERE expiry_time <= datetime('now') AND expires""")
  19.678 -
  19.679 -    sum, = cu.fetchone()
  19.680 -
  19.681 -    cx.close()
  19.682 -
  19.683 -    return sum / 2048
  19.684 -
  19.685 -
  19.686 -def vd_init_db(path):
  19.687 -    """Initialise the VD SQLite database
  19.688 -    path [string]: path to the SQLite database file
  19.689 -    """
  19.690 -
  19.691 -    cx = sqlite.connect(path)
  19.692 -    cu = cx.cursor()
  19.693 -
  19.694 -    cu.execute(
  19.695 -        """CREATE TABLE vdisk_extents
  19.696 -                           ( vdisk_extent_no INT,
  19.697 -                             vdisk_id INT,
  19.698 -                             part_id INT,
  19.699 -                             part_extent_no INT )
  19.700 -        """)
  19.701 -
  19.702 -    cu.execute(
  19.703 -        """CREATE TABLE vdisk_part
  19.704 -                           ( part_id INT,
  19.705 -                             partition VARCHAR,
  19.706 -                             extent_size INT )
  19.707 -        """)
  19.708 -
  19.709 -    cu.execute(
  19.710 -        """CREATE TABLE vdisks
  19.711 -                           ( vdisk_id INT,
  19.712 -                             size INT,
  19.713 -                             expires BOOLEAN,
  19.714 -                             expiry_time TIMESTAMP )
  19.715 -        """)
  19.716 -
  19.717 -
  19.718 -    cu.execute(
  19.719 -        """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time )
  19.720 -                       VALUES ( 0,        0,    1,       datetime('now') )
  19.721 -        """)
  19.722 -
  19.723 -    cx.commit()
  19.724 -    cx.close()
  19.725 -
  19.726 -    VD_DB_FILE = path
  19.727 -
  19.728 -
  19.729 -
  19.730 -def vd_cp_to_file(vdisk_id,filename):
  19.731 -    """Writes the contents of a specified vdisk out into a disk file, leaving
  19.732 -    the original copy in the virtual disk pool."""
  19.733 -
  19.734 -    cx = sqlite.connect(VD_DB_FILE)
  19.735 -    cu = cx.cursor()
  19.736 -
  19.737 -    extents = vd_lookup(vdisk_id)
  19.738 -
  19.739 -    if not extents:
  19.740 -        return -1
  19.741 -    
  19.742 -    file_idx = 0 # index into source file, in sectors
  19.743 -
  19.744 -    for i in extents:
  19.745 -        cu.execute("""SELECT partition, extent_size FROM vdisk_part
  19.746 -                      WHERE part_id =  """ + str(i['part_device']))
  19.747 -
  19.748 -        (partition, extent_size) = cu.fetchone()
  19.749 -
  19.750 -        os.system("dd bs=1b if=" + partition + " of=" + filename
  19.751 -                  + " skip=" + str(i['part_start_sector'])
  19.752 -                  + " seek=" + str(file_idx)
  19.753 -                  + " count=" + str(i['nr_sectors'])
  19.754 -                  + " > /dev/null")
  19.755 -
  19.756 -        file_idx += i['nr_sectors']
  19.757 -
  19.758 -    cx.close()
  19.759 -
  19.760 -    return 0 # should return -1 if something breaks
  19.761 -    
  19.762 -
  19.763 -def vd_mv_to_file(vdisk_id,filename):
  19.764 -    """Writes a vdisk out into a disk file and frees the space originally
  19.765 -    taken within the virtual disk pool.
  19.766 -    vdisk_id [string]: ID of the vdisk to write out
  19.767 -    filename [string]: file to write vdisk contents out to
  19.768 -    returns [int]: zero on success, nonzero on failure
  19.769 -    """
  19.770 -
  19.771 -    if vd_cp_to_file(vdisk_id,filename):
  19.772 -        return -1
  19.773 -
  19.774 -    if vd_delete(vdisk_id):
  19.775 -        return -1
  19.776 -
  19.777 -    return 0
  19.778 -
  19.779 -
  19.780 -def vd_read_from_file(filename,expiry):
  19.781 -    """Reads the contents of a file directly into a vdisk, which is
  19.782 -    automatically allocated to fit.
  19.783 -    filename [string]: file to read disk contents from
  19.784 -    returns [string] : vdisk ID for the destination vdisk
  19.785 -    """
  19.786 -
  19.787 -    size_bytes = os.stat(filename).st_size
  19.788 -
  19.789 -    (size_mb,leftover) =  divmod(size_bytes,1048580) # size in megabytes
  19.790 -    if leftover > 0: size_mb += 1 # round up if not an exact number of MB
  19.791 -
  19.792 -    vdisk_id = vd_create(size_mb, expiry)
  19.793 -
  19.794 -    if vdisk_id < 0:
  19.795 -        return -1
  19.796 -
  19.797 -    cx = sqlite.connect(VD_DB_FILE)
  19.798 -    cu = cx.cursor()
  19.799 -
  19.800 -    cu.execute("""SELECT partition, extent_size, part_extent_no
  19.801 -                  FROM vdisk_part NATURAL JOIN vdisk_extents
  19.802 -                  WHERE vdisk_id =  """ + vdisk_id + """
  19.803 -                  ORDER BY vdisk_extent_no ASC""")
  19.804 -
  19.805 -    extents = cu.fetchall()
  19.806 -
  19.807 -    size_sectors = size_mb * 2048 # for feeding to dd
  19.808 -
  19.809 -    file_idx = 0 # index into source file, in sectors
  19.810 -
  19.811 -    def write_extent_to_vd((partition, extent_size, part_extent_no),
  19.812 -                           file_idx, filename):
  19.813 -        """Write an extent out to disk and update file_idx"""
  19.814 -
  19.815 -        os.system("dd bs=512 if=" + filename + " of=" + partition
  19.816 -                  + " skip=" + str(file_idx)
  19.817 -                  + " seek=" + str(part_extent_no * extent_size)
  19.818 -                  + " count=" + str(min(extent_size, size_sectors - file_idx))
  19.819 -                  + " > /dev/null")
  19.820 -
  19.821 -        return extent_size
  19.822 -
  19.823 -    for i in extents:
  19.824 -        file_idx += write_extent_to_vd(i, file_idx, filename)
  19.825 -
  19.826 -    cx.close()
  19.827 -
  19.828 -    return vdisk_id
  19.829 -    
  19.830 -
  19.831 -
  19.832 -
  19.833 -def vd_extents_validate(new_extents,new_writeable):
  19.834 -    """Validate the extents against the existing extents.
  19.835 -    Complains if the list supplied clashes against the extents that
  19.836 -    are already in use in the system.
  19.837 -    new_extents [list of dicts]: list of new extents, as dicts
  19.838 -    new_writeable [int]: 1 if they are to be writeable, 0 otherwise
  19.839 -    returns [int]: either the expertise level of the mapping if it doesn't
  19.840 -                   exceed VBD_EXPERT_MODE or -1 if it does (error)
  19.841 -    """
  19.842 -
  19.843 -    import Xc # this is only needed in this function
  19.844 -
  19.845 -    xc = Xc.new()
  19.846 -
  19.847 -    ##### Probe for explicitly created virtual disks and build a list
  19.848 -    ##### of extents for comparison with the ones that are being added
  19.849 -
  19.850 -    probe = xc.vbd_probe()
  19.851 -
  19.852 -    old_extents = [] # this will hold a list of all existing extents and
  19.853 -                     # their writeable status, as a list of (device,
  19.854 -                     # start, size, writeable?) tuples
  19.855 -
  19.856 -    for vbd in probe:
  19.857 -        this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd'])
  19.858 -        for vbd_ext in this_vbd_extents:
  19.859 -            vbd_ext['writeable'] = vbd['writeable']
  19.860 -            old_extents.append(vbd_ext)
  19.861 -            
  19.862 -    ##### Now scan /proc/mounts for compile a list of extents corresponding to
  19.863 -    ##### any devices mounted in DOM0.  This list is added on to old_extents
  19.864 -
  19.865 -    regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
  19.866 -    fd = open('/proc/mounts', "r")
  19.867 -
  19.868 -    while True:
  19.869 -        line = fd.readline()
  19.870 -        if not line: # if we've run out of lines then stop reading
  19.871 -            break
  19.872 -        
  19.873 -        m = regexp.match(line)
  19.874 -
  19.875 -        # if the regexp didn't match then it's probably a line we don't
  19.876 -        # care about - skip to next line
  19.877 -        if not m:
  19.878 -            continue
  19.879 -
  19.880 -        # lookup the device
  19.881 -        ext_list = lookup_raw_partn(m.group(1))
  19.882 -
  19.883 -        # if lookup failed, skip to next mounted device
  19.884 -        if not ext_list:
  19.885 -            continue
  19.886 -
  19.887 -        # set a writeable flag as appropriate
  19.888 -        for ext in ext_list:
  19.889 -            ext['writeable'] = m.group(2) == 'rw'
  19.890 -
  19.891 -        # now we've got here, the contents of ext_list are in a
  19.892 -        # suitable format to be added onto the old_extents list, ready
  19.893 -        # for checking against the new extents
  19.894 -
  19.895 -        old_extents.extend(ext_list)
  19.896 -
  19.897 -    fd.close() # close /proc/mounts
  19.898 -
  19.899 -    ##### By this point, old_extents contains a list of extents, in
  19.900 -    ##### dictionary format corresponding to every extent of physical
  19.901 -    ##### disk that's either part of an explicitly created VBD, or is
  19.902 -    ##### mounted under DOM0.  We now check these extents against the
  19.903 -    ##### proposed additions in new_extents, to see if a conflict will
  19.904 -    ##### happen if they are added with write status new_writeable
  19.905 -
  19.906 -    level = 0 # this'll accumulate the max warning level
  19.907 -
  19.908 -    # Search for clashes between the new extents and the old ones
  19.909 -    # Takes time O(len(new_extents) * len(old_extents))
  19.910 -    for new_ext in new_extents:
  19.911 -        for old_ext in old_extents:
  19.912 -            if(new_ext['device'] == old_ext['device']):
  19.913 -
  19.914 -                new_ext_start = new_ext['start_sector']
  19.915 -                new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1
  19.916 -                
  19.917 -                old_ext_start = old_ext['start_sector']
  19.918 -                old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1
  19.919 -                
  19.920 -                if((old_ext_start <= new_ext_start <= old_ext_end) or
  19.921 -                   (old_ext_start <= new_ext_end <= old_ext_end)):
  19.922 -                    if (not old_ext['writeable']) and new_writeable:
  19.923 -                        level = max(1,level)
  19.924 -                    elif old_ext['writeable'] and (not new_writeable):
  19.925 -                        level = max(1,level)
  19.926 -                    elif old_ext['writeable'] and new_writeable:
  19.927 -                        level = max(2,level)
  19.928 -
  19.929 -
  19.930 -    ##### level now holds the warning level incurred by the current
  19.931 -    ##### VBD setup and we complain appropriately to the user
  19.932 -
  19.933 -
  19.934 -    if level == 1:
  19.935 -        print >> sys.stderr, """Warning: one or more hard disk extents
  19.936 -         writeable by one domain are also readable by another."""
  19.937 -    elif level == 2:
  19.938 -        print >> sys.stderr, """Warning: one or more hard disk extents are
  19.939 -         writeable by two or more domains simultaneously."""
  19.940 -
  19.941 -    if level > VBD_EXPERT_MODE:
  19.942 -        print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed
  19.943 -        at the current safety level (%d).""" % VBD_EXPERT_MODE
  19.944 -        level = -1
  19.945 -
  19.946 -    return level
  19.947 -
    20.1 --- a/tools/xenctl/setup.py	Fri Jun 25 15:10:48 2004 +0000
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,19 +0,0 @@
    20.4 -
    20.5 -from distutils.core import setup, Extension
    20.6 -import sys
    20.7 -
    20.8 -modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' ]
    20.9 -
   20.10 -# We need the 'tempfile' module from Python 2.3. We install this ourselves
   20.11 -# if the installed Python is older than 2.3.
   20.12 -major = sys.version_info[0]
   20.13 -minor = sys.version_info[1]
   20.14 -if major == 2 and minor < 3:
   20.15 -    modules.append('xenctl.tempfile')
   20.16 -
   20.17 -setup(name = 'xenctl',
   20.18 -      version = '1.0',
   20.19 -      py_modules = modules,
   20.20 -      package_dir = { 'xenctl' : 'lib' },
   20.21 -      )
   20.22 -
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/xu/Makefile	Mon Jun 28 08:17:15 2004 +0000
    21.3 @@ -0,0 +1,15 @@
    21.4 +
    21.5 +all:
    21.6 +	python setup.py build
    21.7 +
    21.8 +install: all
    21.9 +	if [ "$(prefix)" = "" ]; then                   \
   21.10 +	    python setup.py install;                    \
   21.11 +	elif [ "$(dist)" = "yes" ]; then                \
   21.12 +	    python setup.py install --home="$(prefix)"; \
   21.13 +	else                                            \
   21.14 +	    python setup.py install --root="$(prefix)"; \
   21.15 +	fi
   21.16 +
   21.17 +clean:
   21.18 +	rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm