$NetBSD: patch-am,v 1.1 2004/05/08 18:24:00 cl Exp $

--- xc/py/XenoUtil.py.orig	2004-04-18 04:29:13.000000000 +0200
+++ xc/py/XenoUtil.py
@@ -25,26 +25,40 @@ except ImportError:
     # on failure, just catch the error, don't do anything
     pass
 
+os_ifs = {'Linux' : 'eth0', 'NetBSD' : 'xennet0'}
+default_if = os_ifs[os.uname()[0]]
+
+os_vfr_paths = {'Linux' : '/proc/xeno/vfr', 'NetBSD' : '/kern/xen/vfr'}
+vfr_path = os_vfr_paths[os.uname()[0]]
+
+os_ipgw_cmds = {'Linux' : '/sbin/route -n',
+               'NetBSD' : '/sbin/route -n get default'}
+ipgw_cmd = os_ipgw_cmds[os.uname()[0]]
+
+os_ipgw_res = {'Linux' : '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
+                        '\s+\S+\s+\S*G.*%s.*',         
+              'NetBSD' : 'gateway:\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?:%s)?'}
+ipgw_re = os_ipgw_res[os.uname()[0]]
 
 ##### Networking-related functions
 
-def get_current_ipaddr(dev='eth0'):
+def get_current_ipaddr(dev=default_if):
     """Return a string containing the primary IP address for the given
-    network interface (default 'eth0').
-    """
+    network interface (default '%s').
+    """ % default_if
     fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
     lines = fd.readlines()
     for line in lines:
-        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+        m = re.search( '^\s+inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
                        line )
         if m:
             return m.group(1)
     return None
 
-def get_current_ipmask(dev='eth0'):
+def get_current_ipmask(dev=default_if):
     """Return a string containing the primary IP netmask for the given
-    network interface (default 'eth0').
-    """
+    network interface (default '%s').
+    """ % default_if
     fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
     lines = fd.readlines()
     for line in lines:
@@ -52,17 +66,22 @@ def get_current_ipmask(dev='eth0'):
                        line )
         if m:
             return m.group(1)
+        m = re.search( '^.+netmask (0x[0-9a-f]+)\s',
+                       line )
+        if m:
+            a = int(m.group(1), 16)
+            return '%d.%d.%d.%d' % ( ((a>>24)&0xff), ((a>>16)&0xff),
+                             ((a>>8)&0xff), (a&0xff) )
     return None
 
-def get_current_ipgw(dev='eth0'):
+def get_current_ipgw(dev=default_if):
     """Return a string containing the IP gateway for the given
-    network interface (default 'eth0').
-    """
-    fd = os.popen( '/sbin/route -n' )
+    network interface (default '%s').
+    """ % default_if
+    fd = os.popen( ipgw_cmd )
     lines = fd.readlines()
     for line in lines:
-        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
-                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
+        m = re.search( ipgw_re % dev, line )
         if m:
             return m.group(1)
     return None
@@ -72,7 +91,7 @@ def setup_vfr_rules_for_vif(dom,vif,addr
     is expressed as a textual dotted quad, and set up appropriate routing
     rules in Xen. No return value.
     """
-    fd = os.open( '/proc/xeno/vfr', os.O_WRONLY )
+    fd = os.open( vfr_path, os.O_WRONLY )
     if ( re.search( '169\.254', addr) ):
         os.write( fd, 'ADD ACCEPT srcaddr=' + addr +
                   ' srcaddrmask=255.255.255.255' +
@@ -117,14 +136,42 @@ def check_subnet( ip, network, netmask )
 
 ##### VBD-related Functions
 
+# ls -l /dev/hd[a-z] /dev/sd[a-z] /dev/scd* | sed -e 's#/dev/##' -e 's#,##'
+# | awk -v ORS=" " '{print "'\''" $10 "'\'':" $5 * 256 + $6 "," }';
+blkdev_name_to_number_dict = {
+    'hda':768, 'hdb':832, 'hdc':5632, 'hdd':5696, 'hde':8448,
+    'hdf':8512, 'hdg':8704, 'hdh':8768, 'hdi':14336, 'hdj':14400,
+    'hdk':14592, 'hdl':14656,
+    'sda':2048, 'sdb':2064, 'sdc':2080, 'sdd':2096,
+    'sde':2112, 'sdf':2128, 'sdg':2144, 'sdh':2160,
+    'scd0':2816, 'scd1':2817, 'scd10':2826, 'scd11':2827,
+    'scd12':2828, 'scd13':2829, 'scd14':2830, 'scd15':2831,
+    'scd16':2832, 'scd2':2818, 'scd3':2819, 'scd4':2820,
+    'scd5':2821, 'scd6':2822, 'scd7':2823, 'scd8':2824,
+    'scd9':2825
+    }
+
 def blkdev_name_to_number(name):
     """Take the given textual block-device name (e.g., '/dev/sda1',
-    'hda') and return the device number used by the OS. """
+    'hda') and return the device number used by Xen. """
 
-    if not re.match( '/dev/', name ):
-        name = '/dev/' + name
-        
-    return os.stat(name).st_rdev
+    m = re.search( '/dev/(.+)', name )
+    if m:
+        name = m.group(1)
+
+    try:
+        return blkdev_name_to_number_dict[name]
+    except KeyError:
+        pass
+
+    m = re.search( '^(...)([0-9]+)', name )
+    if not m:
+        return None
+
+    try:
+        return blkdev_name_to_number_dict[m.group(1)] + int( m.group(2) )
+    except KeyError:
+        return None
 
 # lookup_blkdev_partn_info( '/dev/sda3' )
 def lookup_raw_partn(partition):
@@ -137,6 +184,11 @@ def lookup_raw_partn(partition):
         type:         'Disk' or identifying name for partition type
     """
 
+    os_lookup = { 'Linux' : lookup_raw_partn_linux,
+                  'NetBSD' : lookup_raw_partn_netbsd }
+    return os_lookup[os.uname()[0]](partition)
+
+def lookup_raw_partn_linux(partition):
     if not re.match( '/dev/', partition ):
         partition = '/dev/' + partition
 
@@ -168,6 +220,37 @@ def lookup_raw_partn(partition):
     
     return None
 
+def lookup_raw_partn_netbsd(partition):
+    m = re.search( '^(?:/dev/)?([a-z]+[0-9]+)([a-z]*)', partition )
+    if not m:
+        return None
+
+    drive = m.group(1)
+    partition = m.group(2)
+
+    fd = os.popen( '/sbin/sysctl -n ' +
+        'machdep.domain0.diskcookie.%s' % drive )
+    try:
+        cookie = int(fd.readline())
+    except ValueError:
+        cookie = -1
+    fd.close()
+
+    fd = os.popen( '/sbin/disklabel %s' % drive )
+    lines = fd.readlines()
+    for line in lines:
+        # #        size    offset     fstype [fsize bsize cpg/sgs]
+        #  a:  80555328   9514512     4.2BSD   2048 16384 28624
+        m = re.search( '^\s+%s:\s*([0-9]+)\s+([0-9]+)\s+' % partition,
+                       line )
+        if m:
+            return [ { 'device' : int(cookie),
+                       'start_sector' : long(m.group(2)),
+                       'nr_sectors' : long(m.group(1)),
+                       'type' : '0' } ]
+
+    return None
+
 def lookup_disk_uname( uname ):
     """Lookup a list of segments for either a physical or a virtual device.
     uname [string]:  name of the device in the format \'vd:id\' for a virtual
@@ -905,11 +988,12 @@ def vd_extents_validate(new_extents,new_
             vbd_ext['writeable'] = vbd['writeable']
             old_extents.append(vbd_ext)
             
-    ##### Now scan /proc/mounts for compile a list of extents corresponding to
+    ##### Now scan /bin/mount for compile a list of extents corresponding to
     ##### any devices mounted in DOM0.  This list is added on to old_extents
 
-    regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
-    fd = open('/proc/mounts', "r")
+    mount_cmd = { 'Linux' : '/bin/mount', 'NetBSD' : '/sbin/mount' }
+    regexp = re.compile("/dev/(\S*) on \S* type \S* \(([^\),]*)")
+    fd = os.popen(mount_cmd[os.uname()[0]])
 
     while True:
         line = fd.readline()
@@ -932,7 +1016,8 @@ def vd_extents_validate(new_extents,new_
 
         # set a writeable flag as appropriate
         for ext in ext_list:
-            ext['writeable'] = m.group(2) == 'rw'
+            ext['writeable'] = (m.group(2) != 'ro' and
+                m.group(2) != 'read-only')
 
         # now we've got here, the contents of ext_list are in a
         # suitable format to be added onto the old_extents list, ready
