ia64/xen-unstable

changeset 4680:f85eb51dc313

bitkeeper revision 1.1391 (4270e62dQ3ab85LBG8yTiEDbCEYRqA)

Resolve merge failure.
Signed-off-by: Mike Wray <mike.wray@hp.com>
author mjw@wray-m-3.hpl.hp.com
date Thu Apr 28 13:33:33 2005 +0000 (2005-04-28)
parents 16efdf7bbd57 10ef5cb210f7
children 397aeb925c68
files .rootkeys tools/Makefile tools/pygrub/Makefile tools/pygrub/README tools/pygrub/setup.py tools/pygrub/src/GrubConf.py tools/pygrub/src/__init__.py tools/pygrub/src/fsys/__init__.py tools/pygrub/src/fsys/ext2/__init__.py tools/pygrub/src/fsys/ext2/ext2module.c tools/pygrub/src/fsys/ext2/test.py tools/pygrub/src/pygrub tools/python/xen/util/blkif.py tools/python/xen/xend/XendBootloader.py tools/python/xen/xend/XendDB.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/blkif.py tools/python/xen/xm/create.py tools/xfrd/xfrd.c
line diff
     1.1 --- a/.rootkeys	Thu Apr 28 10:46:53 2005 +0000
     1.2 +++ b/.rootkeys	Thu Apr 28 13:33:33 2005 +0000
     1.3 @@ -803,6 +803,16 @@ 41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/mis
     1.4  4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
     1.5  4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
     1.6  40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
     1.7 +4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile
     1.8 +4270deeccyRsJn6jLnRh9odRtMW9SA tools/pygrub/README
     1.9 +4270cc81EIl7NyaS3Av6IPRk2c2a6Q tools/pygrub/setup.py
    1.10 +4270cc81t7eNCDp4Bhbh58p1CNxaCQ tools/pygrub/src/GrubConf.py
    1.11 +4270d6c2fWF4r5-zF1pSuAFwUZS0aA tools/pygrub/src/__init__.py
    1.12 +4270cc81CzKMiujDPWcaYhu709vGXw tools/pygrub/src/fsys/__init__.py
    1.13 +4270cc81RTIiq9si0dI4YRTRE4KRMw tools/pygrub/src/fsys/ext2/__init__.py
    1.14 +4270cc81YCYa4pexivBD2NdLE2F_Pg tools/pygrub/src/fsys/ext2/ext2module.c
    1.15 +4270cc81o4BL5e8Cs87aSi8EXA5NtQ tools/pygrub/src/fsys/ext2/test.py
    1.16 +4270cc81TS6L_tEO6wSp5wcURcpldQ tools/pygrub/src/pygrub
    1.17  40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
    1.18  40ffc44dOwe1CcYXGCkYHdG_NxcccA tools/python/logging/logging-0.4.9.2/PKG-INFO
    1.19  40ffc44dpqpgqgrnLfR70PsiBc3liA tools/python/logging/logging-0.4.9.2/README.txt
    1.20 @@ -879,6 +889,7 @@ 4107986e6qN1IdvIDdId0AYFmDMkiQ tools/pyt
    1.21  40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py
    1.22  40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
    1.23  40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
    1.24 +4270e4efFg3wHCCxXpA0h6yoMTkeSQ tools/python/xen/util/blkif.py
    1.25  4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/python/xen/util/console_client.py
    1.26  40c9c468IienauFHQ_xJIcqnPJ8giQ tools/python/xen/util/ip.py
    1.27  41dde8b0yuJX-S79w4xJKxBQ-Mhp1A tools/python/xen/util/memmap.py
    1.28 @@ -900,6 +911,7 @@ 41597996WNvJA-DVCBmc0xU9w_XmoA tools/pyt
    1.29  40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py
    1.30  40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
    1.31  40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
    1.32 +4270cc81xbweGYhsM4326N3dX1bGHQ tools/python/xen/xend/XendBootloader.py
    1.33  40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
    1.34  40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
    1.35  40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
     2.1 --- a/tools/Makefile	Thu Apr 28 10:46:53 2005 +0000
     2.2 +++ b/tools/Makefile	Thu Apr 28 13:33:33 2005 +0000
     2.3 @@ -13,6 +13,7 @@ SUBDIRS += xcs
     2.4  ifndef XEN_NO_IOEMU
     2.5  SUBDIRS += ioemu
     2.6  endif
     2.7 +SUBDIRS += pygrub
     2.8  
     2.9  .PHONY: all install clean check check_clean
    2.10  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/pygrub/Makefile	Thu Apr 28 13:33:33 2005 +0000
     3.3 @@ -0,0 +1,18 @@
     3.4 +
     3.5 +XEN_ROOT = ../..
     3.6 +include $(XEN_ROOT)/tools/Rules.mk
     3.7 +
     3.8 +all: build
     3.9 +build:
    3.10 +	CFLAGS="$(CFLAGS)" python setup.py build
    3.11 +
    3.12 +ifndef XEN_PYTHON_NATIVE_INSTALL
    3.13 +install: all
    3.14 +	CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr"
    3.15 +else
    3.16 +install: all
    3.17 +	CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)"
    3.18 +endif
    3.19 +
    3.20 +clean:
    3.21 +	rm -rf build *.pyc *.pyo *.o *.a *~
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/pygrub/README	Thu Apr 28 13:33:33 2005 +0000
     4.3 @@ -0,0 +1,1 @@
     4.4 +Compiling this needs RPM e2fsprogs-devel installed.
     4.5 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/pygrub/setup.py	Thu Apr 28 13:33:33 2005 +0000
     5.3 @@ -0,0 +1,25 @@
     5.4 +from distutils.core import setup, Extension
     5.5 +import os
     5.6 +
     5.7 +extra_compile_args  = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
     5.8 +
     5.9 +# in a perfect world, we'd figure out the fsys modules dynamically
    5.10 +ext2 = Extension("grub.fsys.ext2._pyext2",
    5.11 +                 extra_compile_args = extra_compile_args,
    5.12 +                 libraries = ["ext2fs"],
    5.13 +                 sources = ["src/fsys/ext2/ext2module.c"])
    5.14 +
    5.15 +setup(name='pygrub',
    5.16 +      version='0.1',
    5.17 +      description='Boot loader that looks a lot like grub for Xen',
    5.18 +      author='Jeremy Katz',
    5.19 +      author_email='katzj@redhat.com',
    5.20 +      license='GPL',
    5.21 +      package_dir={'grub': 'src'},
    5.22 +      scripts = ["src/pygrub"],
    5.23 +      packages=['grub',
    5.24 +                'grub.fsys',
    5.25 +                'grub.fsys.ext2'],
    5.26 +      ext_modules = [ext2]
    5.27 +      )
    5.28 +               
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/pygrub/src/GrubConf.py	Thu Apr 28 13:33:33 2005 +0000
     6.3 @@ -0,0 +1,229 @@
     6.4 +#
     6.5 +# GrubConf.py - Simple grub.conf parsing
     6.6 +#
     6.7 +# Copyright 2005 Red Hat, Inc.
     6.8 +# Jeremy Katz <katzj@redhat.com>
     6.9 +#
    6.10 +# This software may be freely redistributed under the terms of the GNU
    6.11 +# general public license.
    6.12 +#
    6.13 +# You should have received a copy of the GNU General Public License
    6.14 +# along with this program; if not, write to the Free Software
    6.15 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    6.16 +#
    6.17 +
    6.18 +import os, sys
    6.19 +import logging
    6.20 +
    6.21 +def grub_split(s, maxsplit = -1):
    6.22 +    """Split a grub option screen separated with either '=' or whitespace."""
    6.23 +    eq = s.find('=')
    6.24 +    if eq == -1:
    6.25 +        return s.split(None, maxsplit)
    6.26 +
    6.27 +    # see which of a space or tab is first
    6.28 +    sp = s.find(' ')
    6.29 +    tab = s.find('\t')
    6.30 +    if (tab != -1 and tab < sp) or (tab != -1 and sp == -1):
    6.31 +        sp = tab
    6.32 +
    6.33 +    if eq != -1 and eq < sp or (eq != -1 and sp == -1):
    6.34 +        return s.split('=', maxsplit)
    6.35 +    else:
    6.36 +        return s.split(None, maxsplit)
    6.37 +
    6.38 +def get_path(s):
    6.39 +    """Returns a tuple of (GrubDiskPart, path) corresponding to string."""
    6.40 +    if not s.startswith('('):
    6.41 +        return (None, s)
    6.42 +    idx = s.find(')')
    6.43 +    if idx == -1:
    6.44 +        raise ValueError, "Unable to find matching ')'"
    6.45 +    d = s[:idx]
    6.46 +    return (GrubDiskPart(d), s[idx + 1:])
    6.47 +
    6.48 +class GrubDiskPart(object):
    6.49 +    def __init__(self, str):
    6.50 +        if str.find(',') != -1:
    6.51 +            (self.disk, self.part) = str.split(",", 2)
    6.52 +        else:
    6.53 +            self.disk = str
    6.54 +            self.part = None
    6.55 +
    6.56 +    def __repr__(self):
    6.57 +        if self.part is not None:
    6.58 +            return "d%dp%d" %(self.disk, self.part)
    6.59 +        else:
    6.60 +            return "d%d" %(self,disk,)
    6.61 +
    6.62 +    def get_disk(self):
    6.63 +        return self._disk
    6.64 +    def set_disk(self, val):
    6.65 +        val = val.replace("(", "").replace(")", "")
    6.66 +        self._disk = int(val[2:])
    6.67 +    disk = property(get_disk, set_disk)
    6.68 +
    6.69 +    def get_part(self):
    6.70 +        return self._part
    6.71 +    def set_part(self, val):
    6.72 +        if val is None:
    6.73 +            self._part = val
    6.74 +            return
    6.75 +        val = val.replace("(", "").replace(")", "")
    6.76 +        self._part = int(val)
    6.77 +    part = property(get_part, set_part)
    6.78 +
    6.79 +class GrubImage(object):
    6.80 +    def __init__(self, lines):
    6.81 +        self._root = self._initrd = self._kernel = self._args = None
    6.82 +        for l in lines:
    6.83 +            (com, arg) = grub_split(l, 1)
    6.84 +
    6.85 +            if self.commands.has_key(com):
    6.86 +                if self.commands[com] is not None:
    6.87 +                    exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
    6.88 +                else:
    6.89 +                    logging.info("Ignored image directive %s" %(com,))
    6.90 +            else:
    6.91 +                logging.warning("Unknown image directive %s" %(com,))
    6.92 +
    6.93 +    def __repr__(self):
    6.94 +        return ("title: %s\n" 
    6.95 +                "  root: %s\n"
    6.96 +                "  kernel: %s\n"
    6.97 +                "  args: %s\n"
    6.98 +                "  initrd: %s" %(self.title, self.root, self.kernel,
    6.99 +                                   self.args, self.initrd))
   6.100 +
   6.101 +    def set_root(self, val):
   6.102 +        self._root = GrubDiskPart(val)
   6.103 +    def get_root(self):
   6.104 +        return self._root
   6.105 +    root = property(get_root, set_root)
   6.106 +
   6.107 +    def set_kernel(self, val):
   6.108 +        if val.find(" ") == -1:
   6.109 +            self._kernel = get_path(val)
   6.110 +            self._args = None
   6.111 +            return
   6.112 +        (kernel, args) = val.split(None, 1)
   6.113 +        self._kernel = get_path(kernel)
   6.114 +        self._args = args
   6.115 +    def get_kernel(self):
   6.116 +        return self._kernel
   6.117 +    def get_args(self):
   6.118 +        return self._args
   6.119 +    kernel = property(get_kernel, set_kernel)
   6.120 +    args = property(get_args)
   6.121 +
   6.122 +    def set_initrd(self, val):
   6.123 +        self._initrd = get_path(val)
   6.124 +    def get_initrd(self):
   6.125 +        return self._initrd
   6.126 +    initrd = property(get_initrd, set_initrd)
   6.127 +
   6.128 +    # set up command handlers
   6.129 +    commands = { "title": "self.title",
   6.130 +                 "root": "self.root",
   6.131 +                 "rootnoverify": "self.root",
   6.132 +                 "kernel": "self.kernel",
   6.133 +                 "initrd": "self.initrd",
   6.134 +                 "chainloader": None,
   6.135 +                 "module": None}
   6.136 +        
   6.137 +
   6.138 +class GrubConfigFile(object):
   6.139 +    def __init__(self, fn = None):
   6.140 +        self.filename = fn
   6.141 +        self.images = []
   6.142 +        self.timeout = -1
   6.143 +
   6.144 +        if fn is not None:
   6.145 +            self.parse()
   6.146 +
   6.147 +    def parse(self, buf = None):
   6.148 +        if buf is None:
   6.149 +            if self.filename is None:
   6.150 +                raise ValueError, "No config file defined to parse!"
   6.151 +
   6.152 +            f = open(self.filename, 'r')
   6.153 +            lines = f.readlines()
   6.154 +            f.close()
   6.155 +        else:
   6.156 +            lines = buf.split("\n")
   6.157 +
   6.158 +        img = []
   6.159 +        for l in lines:
   6.160 +            l = l.strip()
   6.161 +            # skip blank lines
   6.162 +            if len(l) == 0:
   6.163 +                continue
   6.164 +            # skip comments
   6.165 +            if l.startswith('#'):
   6.166 +                continue
   6.167 +            # new image
   6.168 +            if l.startswith("title"):
   6.169 +                if len(img) > 0:
   6.170 +                    self.images.append(GrubImage(img))
   6.171 +                img = [l]
   6.172 +                continue
   6.173 +                
   6.174 +            if len(img) > 0:
   6.175 +                img.append(l)
   6.176 +                continue
   6.177 +
   6.178 +            try:
   6.179 +                (com, arg) = grub_split(l, 1)
   6.180 +            except ValueError:
   6.181 +                com = l
   6.182 +                arg = ""
   6.183 +
   6.184 +            if self.commands.has_key(com):
   6.185 +                if self.commands[com] is not None:
   6.186 +                    exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
   6.187 +                else:
   6.188 +                    logging.info("Ignored directive %s" %(com,))
   6.189 +            else:
   6.190 +                logging.warning("Unknown directive %s" %(com,))
   6.191 +                
   6.192 +        if len(img) > 0:
   6.193 +            self.images.append(GrubImage(img))
   6.194 +
   6.195 +    def _get_default(self):
   6.196 +        return self._default
   6.197 +    def _set_default(self, val):
   6.198 +        if val == "saved":
   6.199 +            self._default = -1
   6.200 +        else:
   6.201 +            self._default = int(val)
   6.202 +
   6.203 +        if self._default < 0:
   6.204 +            raise ValueError, "default must be positive number"
   6.205 +    default = property(_get_default, _set_default)
   6.206 +
   6.207 +    def set_splash(self, val):
   6.208 +        self._splash = get_path(val)
   6.209 +    def get_splash(self):
   6.210 +        return self._splash
   6.211 +    splash = property(get_splash, set_splash)
   6.212 +
   6.213 +    # set up command handlers
   6.214 +    commands = { "default": "self.default",
   6.215 +                 "timeout": "self.timeout",
   6.216 +                 "fallback": "self.fallback",
   6.217 +                 "hiddenmenu": "self.hiddenmenu",
   6.218 +                 "splashimage": "self.splash",
   6.219 +                 "password": "self.password" }
   6.220 +    for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
   6.221 +              "pager", "partnew", "parttype", "rarp", "serial",
   6.222 +              "setkey", "terminal", "terminfo", "tftpserver", "unhide"):
   6.223 +        commands[c] = None
   6.224 +    del c
   6.225 +
   6.226 +
   6.227 +if __name__ == "__main__":
   6.228 +    if sys.argv < 2:
   6.229 +        raise RuntimeError, "Need a grub.conf to read"
   6.230 +    g = GrubConfigFile(sys.argv[1])
   6.231 +    for i in g.images:
   6.232 +        print i #, i.title, i.root, i.kernel, i.args, i.initrd
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/pygrub/src/fsys/__init__.py	Thu Apr 28 13:33:33 2005 +0000
     7.3 @@ -0,0 +1,61 @@
     7.4 +#
     7.5 +# Copyright 2005 Red Hat, Inc.
     7.6 +# Jeremy Katz <katzj@xxxxxxxxxx>
     7.7 +#
     7.8 +# This software may be freely redistributed under the terms of the GNU
     7.9 +# general public license.
    7.10 +#
    7.11 +# You should have received a copy of the GNU General Public License
    7.12 +# along with this program; if not, write to the Free Software
    7.13 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    7.14 +#
    7.15 +
    7.16 +import os
    7.17 +import sys
    7.18 +
    7.19 +fstypes = {}
    7.20 +
    7.21 +def register_fstype(x):
    7.22 +    if x.name in fstypes.keys():
    7.23 +        return
    7.24 +    fstypes[x.name] = x
    7.25 +
    7.26 +class FileSystemType(object):
    7.27 +    """A simple representation for a file system that gives a fs name
    7.28 +    and a method for sniffing a file to see if it's of the given fstype."""
    7.29 +    def __init__(self):
    7.30 +        self.name = ""
    7.31 +
    7.32 +    def sniff_magic(self, fn, offset = 0):
    7.33 +        """Look at the filesystem at fn for the appropriate magic starting at
    7.34 +        offset offset."""
    7.35 +        raise RuntimeError, "sniff_magic not implemented"
    7.36 +
    7.37 +    def open_fs(self, fn, offset = 0):
    7.38 +        """Open the given filesystem and return a filesystem object."""
    7.39 +        raise RuntimeError, "open_fs not implemented"
    7.40 +
    7.41 +class FileSystem(object):
    7.42 +    def open(self, name, flags = 0, block_size = 0):
    7.43 +        """Open the fsys on name with given flags and block_size."""
    7.44 +        raise RuntimeError, "open not implemented"
    7.45 +
    7.46 +    def close(self):
    7.47 +        """Close the fsys."""
    7.48 +        raise RuntimeError, "close not implemented"
    7.49 +
    7.50 +    def open_file(self, file, flags = None):
    7.51 +        """Open the file 'name' with the given flags.  The returned object
    7.52 +        should look similar to a native file object."""
    7.53 +        raise RuntimeError, "open_file not implemented"
    7.54 +    
    7.55 +
    7.56 +
    7.57 +mydir = sys.modules['grub.fsys'].__path__[0]
    7.58 +for f in os.listdir(mydir):
    7.59 +    if not os.path.isdir("%s/%s" %(mydir, f)):
    7.60 +        continue
    7.61 +    try:
    7.62 +        exec "import grub.fsys.%s" %(f,)        
    7.63 +    except ImportError, e:
    7.64 +        pass
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/pygrub/src/fsys/ext2/__init__.py	Thu Apr 28 13:33:33 2005 +0000
     8.3 @@ -0,0 +1,38 @@
     8.4 +# Copyright 2005 Red Hat, Inc.
     8.5 +# Jeremy Katz <katzj@redhat.com>
     8.6 +#
     8.7 +# This software may be freely redistributed under the terms of the GNU
     8.8 +# general public license.
     8.9 +#
    8.10 +# You should have received a copy of the GNU General Public License
    8.11 +# along with this program; if not, write to the Free Software
    8.12 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    8.13 +#
    8.14 +
    8.15 +from grub.fsys import register_fstype, FileSystemType
    8.16 +from _pyext2 import *
    8.17 +
    8.18 +import os, struct
    8.19 +
    8.20 +class Ext2FileSystemType(FileSystemType):
    8.21 +    def __init__(self):
    8.22 +        FileSystemType.__init__(self)
    8.23 +        self.name = "ext2"
    8.24 +
    8.25 +    def sniff_magic(self, fn, offset = 0):
    8.26 +        fd = os.open(fn, os.O_RDONLY)
    8.27 +        os.lseek(fd, offset, 0)
    8.28 +        buf = os.read(fd, 2048)
    8.29 +        
    8.30 +        if len(buf) > 1082 and \
    8.31 +               struct.unpack("<H", buf[1080:1082]) == (0xef53,):
    8.32 +            return True
    8.33 +        return False
    8.34 +
    8.35 +    def open_fs(self, fn, offset = 0):
    8.36 +        if not self.sniff_magic(fn, offset):
    8.37 +            raise ValueError, "Not an ext2 filesystem"
    8.38 +        return Ext2Fs(fn)
    8.39 +
    8.40 +register_fstype(Ext2FileSystemType())
    8.41 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/pygrub/src/fsys/ext2/ext2module.c	Thu Apr 28 13:33:33 2005 +0000
     9.3 @@ -0,0 +1,332 @@
     9.4 +/*
     9.5 + * ext2module.c - simple python binding for libext2fs
     9.6 + *
     9.7 + * Copyright 2005 Red Hat, Inc.
     9.8 + * Jeremy Katz <katzj@redhat.com>
     9.9 + *
    9.10 + * This software may be freely redistributed under the terms of the GNU
    9.11 + * general public license.
    9.12 + *
    9.13 + * You should have received a copy of the GNU General Public License
    9.14 + * along with this program; if not, write to the Free Software
    9.15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    9.16 + */
    9.17 +
    9.18 +#include <Python.h>
    9.19 +
    9.20 +#include <ext2fs/ext2fs.h>
    9.21 +#include <stdlib.h>
    9.22 +#include <stdio.h>
    9.23 +
    9.24 +#if (PYTHON_API_VERSION >= 1011)
    9.25 +#define PY_PAD 0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L,0L
    9.26 +#else
    9.27 +#define PY_PAD 0L,0L,0L,0L
    9.28 +#endif
    9.29 +
    9.30 +
    9.31 +/* global error object */
    9.32 +PyObject *Ext2Error;
    9.33 +
    9.34 +typedef struct _Ext2Fs Ext2Fs;
    9.35 +struct _Ext2Fs {
    9.36 +    PyObject_HEAD;
    9.37 +    ext2_filsys fs;
    9.38 +};
    9.39 +
    9.40 +typedef struct _Ext2File Ext2File;
    9.41 +struct _Ext2File {
    9.42 +    PyObject_HEAD;
    9.43 +    ext2_file_t file;
    9.44 +};
    9.45 +
    9.46 +/* ext2 file object */
    9.47 +
    9.48 +static PyObject *
    9.49 +ext2_file_close (Ext2File *file, PyObject *args)
    9.50 +{
    9.51 +    if (file->file != NULL)
    9.52 +        ext2fs_file_close(file->file);
    9.53 +    Py_INCREF(Py_None);
    9.54 +    return Py_None;
    9.55 +}
    9.56 +
    9.57 +static PyObject *
    9.58 +ext2_file_read (Ext2File *file, PyObject *args)
    9.59 +{
    9.60 +    int err, size = 0;
    9.61 +    size_t n, total = 0;
    9.62 +    PyObject * buffer = NULL;
    9.63 +
    9.64 +    if (file->file == NULL) {
    9.65 +        PyErr_SetString(PyExc_ValueError, "Cannot read from closed file");
    9.66 +        return NULL;
    9.67 +    }
    9.68 +
    9.69 +    if (!PyArg_ParseTuple(args, "|i", &size))
    9.70 +        return NULL;
    9.71 +
    9.72 +    buffer = PyString_FromStringAndSize((char *) NULL, (size) ? size : 4096);
    9.73 +    if (buffer == NULL)
    9.74 +        return buffer;
    9.75 + 
    9.76 +    while (1) {
    9.77 +        err = ext2fs_file_read(file->file, PyString_AS_STRING(buffer) + total, 
    9.78 +                               (size) ? size : 4096, &n);
    9.79 +        if (err) {
    9.80 +            if (buffer != NULL) { Py_DECREF(buffer); }
    9.81 +            Py_DECREF(buffer);
    9.82 +            PyErr_SetString(PyExc_ValueError, "read error");
    9.83 +            return NULL;
    9.84 +        }
    9.85 +
    9.86 +        total += n;
    9.87 +        if (n == 0)
    9.88 +            break;
    9.89 +
    9.90 +        if (size && size == total)
    9.91 +            break;
    9.92 +
    9.93 +        if (!size) {
    9.94 +            _PyString_Resize(&buffer, total + 4096);
    9.95 +        }
    9.96 +    }
    9.97 +
    9.98 +    _PyString_Resize(&buffer, total);
    9.99 +    return buffer;
   9.100 +}
   9.101 +
   9.102 +static void
   9.103 +ext2_file_dealloc (Ext2File * file)
   9.104 +{
   9.105 +    if (file->file != NULL)
   9.106 +        ext2fs_file_close(file->file);
   9.107 +    PyMem_DEL(file);
   9.108 +}
   9.109 +
   9.110 +static struct PyMethodDef Ext2FileMethods[] = {
   9.111 +        { "close",
   9.112 +          (PyCFunction) ext2_file_close,
   9.113 +          METH_VARARGS, NULL },
   9.114 +        { "read",
   9.115 +          (PyCFunction) ext2_file_read,
   9.116 +          METH_VARARGS, NULL },
   9.117 +	{ NULL, NULL, 0, NULL }	
   9.118 +};
   9.119 +
   9.120 +static PyObject *
   9.121 +ext2_file_getattr (Ext2File * file, char * name)
   9.122 +{
   9.123 +        return Py_FindMethod (Ext2FileMethods, (PyObject *) file, name);
   9.124 +}
   9.125 +
   9.126 +static char Ext2FileType__doc__[] = "This is the ext2 filesystem object";
   9.127 +PyTypeObject Ext2FileType = {
   9.128 +	PyObject_HEAD_INIT(&PyType_Type)
   9.129 +	0,				/* ob_size */
   9.130 +	"Ext2File",			/* tp_name */
   9.131 +	sizeof(Ext2File),		/* tp_size */
   9.132 +	0,				/* tp_itemsize */
   9.133 +	(destructor) ext2_file_dealloc, 	/* tp_dealloc */
   9.134 +	0,				/* tp_print */
   9.135 +	(getattrfunc) ext2_file_getattr, 	/* tp_getattr */
   9.136 +	0,				/* tp_setattr */
   9.137 +	0,				/* tp_compare */
   9.138 +	0,				/* tp_repr */
   9.139 +	0,				/* tp_as_number */
   9.140 +	0,	 			/* tp_as_sequence */
   9.141 +	0,				/* tp_as_mapping */
   9.142 +	0,           			/* tp_hash */
   9.143 +	0,                		/* tp_call */
   9.144 +	0,                    		/* tp_str */
   9.145 +	0,				/* tp_getattro */
   9.146 +	0,				/* tp_setattro */
   9.147 +	0,				/* tp_as_buffer */
   9.148 +	0L,	       			/* tp_flags */
   9.149 +	Ext2FileType__doc__,
   9.150 +	PY_PAD
   9.151 +};
   9.152 +
   9.153 +static PyObject *
   9.154 +ext2_file_open (Ext2Fs *fs, char * name, int flags)
   9.155 +{
   9.156 +    int err;
   9.157 +    ext2_file_t f;
   9.158 +    ext2_ino_t ino;
   9.159 +    Ext2File * file;
   9.160 +
   9.161 +    file = (Ext2File *) PyObject_NEW(Ext2File, &Ext2FileType);
   9.162 +    file->file = NULL;
   9.163 +
   9.164 +    err = ext2fs_namei_follow(fs->fs, EXT2_ROOT_INO, EXT2_ROOT_INO, name, &ino);
   9.165 +    if (err) {
   9.166 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
   9.167 +        return NULL;
   9.168 +    }
   9.169 +
   9.170 +    err = ext2fs_file_open(fs->fs, ino, flags, &f);
   9.171 +    if (err) {
   9.172 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
   9.173 +        return NULL;
   9.174 +    }
   9.175 +
   9.176 +    file->file = f;
   9.177 +    return (PyObject *) file;
   9.178 +}
   9.179 +
   9.180 +/* ext2fs object */
   9.181 +
   9.182 +static PyObject *
   9.183 +ext2_fs_close (Ext2Fs *fs, PyObject *args)
   9.184 +{
   9.185 +    if (fs->fs != NULL)
   9.186 +        ext2fs_close(fs->fs);
   9.187 +    Py_INCREF(Py_None);
   9.188 +    return Py_None;
   9.189 +}
   9.190 +
   9.191 +static PyObject *
   9.192 +ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
   9.193 +{
   9.194 +    static char *kwlist[] = { "name", "flags", "superblock", 
   9.195 +                              "block_size", NULL };
   9.196 +    char * name;
   9.197 +    int flags = 0, superblock = 0, err;
   9.198 +    unsigned int block_size = 0;
   9.199 +    ext2_filsys efs;
   9.200 +
   9.201 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
   9.202 +                                     &name, &flags, &superblock, &block_size))
   9.203 +                                     return NULL;
   9.204 +
   9.205 +    if (fs->fs != NULL) {
   9.206 +        PyErr_SetString(PyExc_ValueError, "already have an fs object");
   9.207 +        return NULL;
   9.208 +    }
   9.209 +
   9.210 +    err = ext2fs_open(name, flags, superblock, block_size, 
   9.211 +                      unix_io_manager, &efs);
   9.212 +    if (err) {
   9.213 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
   9.214 +        return NULL;
   9.215 +    }
   9.216 +
   9.217 +    fs->fs = efs;
   9.218 +
   9.219 +    Py_INCREF(Py_None);
   9.220 +    return Py_None;
   9.221 +}
   9.222 +
   9.223 +static PyObject *
   9.224 +ext2_fs_open_file (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
   9.225 +{
   9.226 +    static char *kwlist[] = { "name", "flags", NULL };
   9.227 +    char * name;
   9.228 +    int flags = 0;
   9.229 +
   9.230 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", kwlist, 
   9.231 +                                     &name, &flags))
   9.232 +                                     return NULL;
   9.233 +
   9.234 +    return ext2_file_open(fs, name, flags);
   9.235 +}
   9.236 +
   9.237 +static void
   9.238 +ext2_fs_dealloc (Ext2Fs * fs)
   9.239 +{
   9.240 +    if (fs->fs != NULL)
   9.241 +        ext2fs_close(fs->fs);
   9.242 +    PyMem_DEL(fs);
   9.243 +}
   9.244 +
   9.245 +static struct PyMethodDef Ext2FsMethods[] = {
   9.246 +        { "close",
   9.247 +          (PyCFunction) ext2_fs_close,
   9.248 +          METH_VARARGS, NULL },
   9.249 +        { "open",
   9.250 +          (PyCFunction) ext2_fs_open,
   9.251 +          METH_VARARGS|METH_KEYWORDS, NULL },
   9.252 +        { "open_file",
   9.253 +          (PyCFunction) ext2_fs_open_file,
   9.254 +          METH_VARARGS|METH_KEYWORDS, NULL },
   9.255 +	{ NULL, NULL, 0, NULL }	
   9.256 +};
   9.257 +
   9.258 +static PyObject *
   9.259 +ext2_fs_getattr (Ext2Fs * fs, char * name)
   9.260 +{
   9.261 +        return Py_FindMethod (Ext2FsMethods, (PyObject *) fs, name);
   9.262 +}
   9.263 +
   9.264 +static char Ext2FsType__doc__[] = "This is the ext2 filesystem object";
   9.265 +PyTypeObject Ext2FsType = {
   9.266 +	PyObject_HEAD_INIT(&PyType_Type)
   9.267 +	0,				/* ob_size */
   9.268 +	"Ext2Fs",			/* tp_name */
   9.269 +	sizeof(Ext2Fs),		/* tp_size */
   9.270 +	0,				/* tp_itemsize */
   9.271 +	(destructor) ext2_fs_dealloc, 	/* tp_dealloc */
   9.272 +	0,				/* tp_print */
   9.273 +	(getattrfunc) ext2_fs_getattr, 	/* tp_getattr */
   9.274 +	0,				/* tp_setattr */
   9.275 +	0,				/* tp_compare */
   9.276 +	0,				/* tp_repr */
   9.277 +	0,				/* tp_as_number */
   9.278 +	0,	 			/* tp_as_sequence */
   9.279 +	0,				/* tp_as_mapping */
   9.280 +	0,           			/* tp_hash */
   9.281 +	0,                		/* tp_call */
   9.282 +	0,                    		/* tp_str */
   9.283 +	0,				/* tp_getattro */
   9.284 +	0,				/* tp_setattro */
   9.285 +	0,				/* tp_as_buffer */
   9.286 +	0L,	       			/* tp_flags */
   9.287 +	Ext2FsType__doc__,
   9.288 +	PY_PAD
   9.289 +};
   9.290 +
   9.291 +static PyObject *
   9.292 +ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs) 
   9.293 +{
   9.294 +    static char *kwlist[] = { "name", "flags", "superblock", 
   9.295 +                              "block_size", NULL };
   9.296 +    char * name;
   9.297 +    int flags = 0, superblock = 0;
   9.298 +    unsigned int block_size = 0;
   9.299 +    Ext2Fs *pfs;
   9.300 +
   9.301 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
   9.302 +                                     &name, &flags, &superblock, &block_size))
   9.303 +        return NULL;
   9.304 +
   9.305 +    pfs = (Ext2Fs *) PyObject_NEW(Ext2Fs, &Ext2FsType);
   9.306 +    if (pfs == NULL)
   9.307 +        return NULL;
   9.308 +    pfs->fs = NULL;
   9.309 +
   9.310 +    if (!ext2_fs_open(pfs, 
   9.311 +                      Py_BuildValue("siii", name, flags, superblock, block_size),
   9.312 +                      NULL))
   9.313 +        return NULL;
   9.314 +
   9.315 +    return (PyObject *)pfs;
   9.316 +}
   9.317 +
   9.318 +
   9.319 +static struct PyMethodDef Ext2ModuleMethods[] = {
   9.320 +    { "Ext2Fs", (PyCFunction) ext2_fs_new, METH_VARARGS|METH_KEYWORDS, NULL },
   9.321 +    { NULL, NULL, 0, NULL }
   9.322 +};
   9.323 +
   9.324 +
   9.325 +void init_pyext2(void) {
   9.326 +    PyObject *m, *d;
   9.327 +
   9.328 +    m = Py_InitModule("_pyext2", Ext2ModuleMethods);
   9.329 +    d = PyModule_GetDict(m);
   9.330 +
   9.331 +    /*    o = PyObject_NEW(PyObject, yExt2FsConstructorType);
   9.332 +    PyDict_SetItemString(d, "PyExt2Fs", o);
   9.333 +    Py_DECREF(o);*/
   9.334 +                      
   9.335 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/pygrub/src/fsys/ext2/test.py	Thu Apr 28 13:33:33 2005 +0000
    10.3 @@ -0,0 +1,15 @@
    10.4 +#!/usr/bin/python
    10.5 +
    10.6 +
    10.7 +import _pyext2
    10.8 +import struct, os, sys
    10.9 +
   10.10 +fs = _pyext2.Ext2Fs("test.img")
   10.11 +
   10.12 +f = fs.open_file("/boot/vmlinuz-2.6.11-1.1177_FC4")
   10.13 +buf = f.read()
   10.14 +o = open("vmlinuz", "wb+")
   10.15 +o.write(buf)
   10.16 +o.close()
   10.17 +
   10.18 +f.close()
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/pygrub/src/pygrub	Thu Apr 28 13:33:33 2005 +0000
    11.3 @@ -0,0 +1,270 @@
    11.4 +#!/usr/bin/python
    11.5 +#
    11.6 +# pygrub - simple python-based bootloader for Xen
    11.7 +#
    11.8 +# Copyright 2005 Red Hat, Inc.
    11.9 +# Jeremy Katz <katzj@redhat.com>
   11.10 +#
   11.11 +# This software may be freely redistributed under the terms of the GNU
   11.12 +# general public license.
   11.13 +#
   11.14 +# You should have received a copy of the GNU General Public License
   11.15 +# along with this program; if not, write to the Free Software
   11.16 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   11.17 +#
   11.18 +
   11.19 +import os, sys, string, struct, tempfile
   11.20 +import logging
   11.21 +
   11.22 +import curses, _curses, curses.wrapper
   11.23 +import getopt
   11.24 +
   11.25 +import grub.GrubConf
   11.26 +import grub.fsys
   11.27 +
   11.28 +PYGRUB_VER = 0.02
   11.29 +
   11.30 +
   11.31 +def draw_window():
   11.32 +    stdscr = curses.initscr()
   11.33 +    curses.use_default_colors()
   11.34 +    try:
   11.35 +        curses.curs_set(0)
   11.36 +    except _curses.error:
   11.37 +        pass
   11.38 +
   11.39 +    stdscr.addstr(1, 4, "pyGRUB  version %s" %(PYGRUB_VER,))
   11.40 +
   11.41 +    win = curses.newwin(10, 74, 2, 1)
   11.42 +    win.box()
   11.43 +    win.refresh()
   11.44 +
   11.45 +    stdscr.addstr(12, 5, "Use the U and D keys to select which entry is highlighted.")
   11.46 +    stdscr.addstr(13, 5, "Press enter to boot the selected OS. 'e' to edit the")
   11.47 +    stdscr.addstr(14, 5, "commands before booting, 'a' to modify the kernel arguments ")
   11.48 +    stdscr.addstr(15, 5, "before booting, or 'c' for a command line.")
   11.49 +    stdscr.addch(12, 13, curses.ACS_UARROW)
   11.50 +    stdscr.addch(12, 19, curses.ACS_DARROW)
   11.51 +    (y, x) = stdscr.getmaxyx()
   11.52 +    stdscr.move(y - 1, x - 1)
   11.53 +
   11.54 +    stdscr.refresh()
   11.55 +    return (stdscr, win)
   11.56 +
   11.57 +def fill_entries(win, cfg, selected):
   11.58 +    y = 0
   11.59 +
   11.60 +    for i in cfg.images:
   11.61 +        if (0, y) > win.getmaxyx():
   11.62 +            break
   11.63 +        if y == selected:
   11.64 +            attr = curses.A_REVERSE
   11.65 +        else:
   11.66 +            attr = 0
   11.67 +        win.addstr(y + 1, 2, i.title.ljust(70), attr)
   11.68 +        y += 1
   11.69 +    win.refresh()
   11.70 +
   11.71 +def select(win, line):
   11.72 +    win.attron(curses.A_REVERSE)
   11.73 +    win.redrawln(line + 1, 1)
   11.74 +    win.refresh()
   11.75 +
   11.76 +def is_disk_image(file):
   11.77 +    fd = os.open(file, os.O_RDONLY)
   11.78 +    buf = os.read(fd, 512)
   11.79 +    os.close(fd)
   11.80 +
   11.81 +    if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
   11.82 +        return True
   11.83 +    return False
   11.84 +    
   11.85 +
   11.86 +def get_config(fn):
   11.87 +    if not os.access(fn, os.R_OK):
   11.88 +        raise RuntimeError, "Unable to access %s" %(fn,)
   11.89 +
   11.90 +    cf = grub.GrubConf.GrubConfigFile()
   11.91 +
   11.92 +    if is_disk_image(fn):
   11.93 +        raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
   11.94 +
   11.95 +    # open the image and read the grub config
   11.96 +    fs = None
   11.97 +    for fstype in grub.fsys.fstypes.values():
   11.98 +        if fstype.sniff_magic(fn):
   11.99 +            fs = fstype.open_fs(fn)
  11.100 +            break
  11.101 +
  11.102 +    if fs is not None:
  11.103 +        f = fs.open_file("/boot/grub/grub.conf")
  11.104 +        buf = f.read()
  11.105 +        f.close()
  11.106 +        fs.close()
  11.107 +        # then parse the grub config
  11.108 +        cf.parse(buf)
  11.109 +    else:
  11.110 +        # set the config file and parse it
  11.111 +        cf.filename = fn
  11.112 +        cf.parse()
  11.113 +    
  11.114 +    return cf
  11.115 +
  11.116 +def get_entry_idx(cf, entry):
  11.117 +    # first, see if the given entry is numeric
  11.118 +    try:
  11.119 +        idx = string.atoi(entry)
  11.120 +        return idx
  11.121 +    except ValueError:
  11.122 +        pass
  11.123 +
  11.124 +    # it's not, now check the labels for a match
  11.125 +    for i in range(len(cf.images)):
  11.126 +        if entry == cf.images[i].title:
  11.127 +            return i
  11.128 +
  11.129 +    return None
  11.130 +
  11.131 +def main(cf = None):
  11.132 +    mytime = 0
  11.133 +
  11.134 +    (stdscr, win) = draw_window()
  11.135 +    stdscr.timeout(1000)
  11.136 +    selected = cf.default
  11.137 +    
  11.138 +    while (mytime < int(cf.timeout)):
  11.139 +        if cf.timeout != -1 and mytime != -1: 
  11.140 +            stdscr.addstr(20, 5, "Will boot selected entry in %2d seconds"
  11.141 +                          %(int(cf.timeout) - mytime))
  11.142 +        else:
  11.143 +            stdscr.addstr(20, 5, " " * 80)
  11.144 +            
  11.145 +        fill_entries(win, cf, selected)
  11.146 +        c = stdscr.getch()
  11.147 +        if mytime != -1:
  11.148 +            mytime += 1
  11.149 +#        if c == ord('q'):
  11.150 +#            selected = -1
  11.151 +#            break
  11.152 +        elif c == ord('c'):
  11.153 +            # FIXME: needs to go to command line mode
  11.154 +            continue
  11.155 +        elif c == ord('a'):
  11.156 +            # FIXME: needs to go to append mode
  11.157 +            continue
  11.158 +        elif c == ord('e'):
  11.159 +            # FIXME: needs to go to edit mode
  11.160 +            continue
  11.161 +        elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')):
  11.162 +            break
  11.163 +        elif c == curses.KEY_UP:
  11.164 +            mytime = -1
  11.165 +            selected -= 1
  11.166 +        elif c == curses.KEY_DOWN:
  11.167 +            mytime = -1
  11.168 +            selected += 1
  11.169 +        else:
  11.170 +            pass
  11.171 +
  11.172 +        # bound at the top and bottom
  11.173 +        if selected < 0:
  11.174 +            selected = 0
  11.175 +        elif selected >= len(cf.images):
  11.176 +            selected = len(cf.images) - 1
  11.177 +
  11.178 +    if selected >= 0:
  11.179 +        return selected
  11.180 +
  11.181 +if __name__ == "__main__":
  11.182 +    sel = None
  11.183 +    
  11.184 +    def run_main(scr, *args):
  11.185 +        global sel
  11.186 +        sel = main(cf)
  11.187 +
  11.188 +    def usage():
  11.189 +        print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <image>" %(sys.argv[0],)
  11.190 +
  11.191 +    try:
  11.192 +        opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::',
  11.193 +                                   ["quiet", "help", "output=", "entry="])
  11.194 +    except getopt.GetoptError:
  11.195 +        usage()
  11.196 +        sys.exit(1)
  11.197 +
  11.198 +    if len(args) < 1:
  11.199 +        usage()
  11.200 +        sys.exit(1)
  11.201 +    file = args[0]
  11.202 +        
  11.203 +    output = None
  11.204 +    entry = None
  11.205 +    interactive = True
  11.206 +    for o, a in opts:
  11.207 +        if o in ("-q", "--quiet"):
  11.208 +            interactive = False
  11.209 +        elif o in ("-h", "--help"):
  11.210 +            usage()
  11.211 +            sys.exit()
  11.212 +        elif o in ("--output",):
  11.213 +            output = a
  11.214 +        elif o in ("--entry",):
  11.215 +            entry = a
  11.216 +            # specifying the entry to boot implies non-interactive
  11.217 +            interactive = False
  11.218 +
  11.219 +    if output is None or output == "-":
  11.220 +        fd = sys.stdout.fileno()
  11.221 +    else:
  11.222 +        fd = os.open(output, os.O_WRONLY)
  11.223 +
  11.224 +    cf = get_config(file)
  11.225 +    if interactive:
  11.226 +        curses.wrapper(run_main)
  11.227 +    else:
  11.228 +        sel = cf.default
  11.229 +
  11.230 +    # set the entry to boot as requested
  11.231 +    if entry is not None:
  11.232 +        idx = get_entry_idx(cf, entry)
  11.233 +        if idx is not None and idx > 0 and idx < len(cf.images):
  11.234 +            sel = idx
  11.235 +
  11.236 +    img = cf.images[sel]
  11.237 +    print "Going to boot %s" %(img.title)
  11.238 +    print "  kernel: %s" %(img.kernel[1],)
  11.239 +    if img.initrd:
  11.240 +        print "  initrd: %s" %(img.initrd[1],)
  11.241 +
  11.242 +    if is_disk_image(file):
  11.243 +        raise RuntimeError, "unable to handle full disk images yet"
  11.244 +
  11.245 +    # read the kernel and initrd onto the hostfs
  11.246 +    fs = None
  11.247 +    for fstype in grub.fsys.fstypes.values():
  11.248 +        if fstype.sniff_magic(file):
  11.249 +            fs = fstype.open_fs(file)
  11.250 +            break
  11.251 +
  11.252 +    if fs is None:
  11.253 +        raise RuntimeError, "Unable to open filesystem"
  11.254 +
  11.255 +    kernel = fs.open_file(img.kernel[1],).read()
  11.256 +    (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.")
  11.257 +    os.write(tfd, kernel)
  11.258 +    os.close(tfd)
  11.259 +    sxp = "linux (kernel %s)" %(fn,)
  11.260 +
  11.261 +    if img.initrd:
  11.262 +        initrd = fs.open_file(img.initrd[1],).read()
  11.263 +        (tfd, fn) = tempfile.mkstemp(prefix="initrd.")
  11.264 +        os.write(tfd, initrd)
  11.265 +        os.close(tfd)
  11.266 +        sxp += "(ramdisk %s)" %(fn,)
  11.267 +    else:
  11.268 +        initrd = None
  11.269 +    sxp += "(args '%s')" %(img.args,)
  11.270 +
  11.271 +    sys.stdout.flush()
  11.272 +    os.write(fd, sxp)
  11.273 +    
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/python/xen/util/blkif.py	Thu Apr 28 13:33:33 2005 +0000
    12.3 @@ -0,0 +1,84 @@
    12.4 +import os
    12.5 +import re
    12.6 +import string
    12.7 +
    12.8 +from xen.util.ip import _readline, _readlines
    12.9 +
   12.10 +def expand_dev_name(name):
   12.11 +    if not name:
   12.12 +        return name
   12.13 +    if re.match( '^/dev/', name ):
   12.14 +        return name
   12.15 +    else:
   12.16 +        return '/dev/' + name
   12.17 +
   12.18 +def blkdev_name_to_number(name):
   12.19 +    """Take the given textual block-device name (e.g., '/dev/sda1',
   12.20 +    'hda') and return the device number used by the OS. """
   12.21 +
   12.22 +    n = expand_dev_name(name)
   12.23 +
   12.24 +    try:
   12.25 +        return os.stat(n).st_rdev
   12.26 +    except Exception, ex:
   12.27 +        log.debug("exception looking up device number for %s: %s", name, ex)
   12.28 +        pass
   12.29 +
   12.30 +    if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
   12.31 +        return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
   12.32 +
   12.33 +    if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
   12.34 +        ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
   12.35 +        major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
   12.36 +        minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
   12.37 +        return major * 256 + minor
   12.38 +
   12.39 +    # see if this is a hex device number
   12.40 +    if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
   12.41 +        return string.atoi(name,16)
   12.42 +        
   12.43 +    return None
   12.44 +
   12.45 +def blkdev_segment(name):
   12.46 +    """Take the given block-device name (e.g. '/dev/sda1', 'hda')
   12.47 +    and return a dictionary { device, start_sector,
   12.48 +    nr_sectors, type }
   12.49 +        device:       Device number of the given partition
   12.50 +        start_sector: Index of first sector of the partition
   12.51 +        nr_sectors:   Number of sectors comprising this partition
   12.52 +        type:         'Disk' or identifying name for partition type
   12.53 +    """
   12.54 +    val = None
   12.55 +    n = blkdev_name_to_number(name)
   12.56 +    if n:
   12.57 +        val = { 'device'       : n,
   12.58 +                'start_sector' : long(0),
   12.59 +                'nr_sectors'   : long(1L<<63),
   12.60 +                'type'         : 'Disk' }
   12.61 +    return val
   12.62 +
   12.63 +def blkdev_uname_to_file(uname):
   12.64 +    """Take a blkdev uname and return the corresponding filename."""
   12.65 +    fn = None
   12.66 +    if uname.find(":") != -1:
   12.67 +        (typ, fn) = uname.split(":")
   12.68 +        if typ == "phy" and not fn.startswith("/dev/"):
   12.69 +            fn = "/dev/%s" %(fn,)
   12.70 +    return fn
   12.71 +
   12.72 +def mount_mode(name):
   12.73 +    mode = None
   12.74 +    name = expand_dev_name(name)
   12.75 +    lines = _readlines(os.popen('mount 2>/dev/null'))
   12.76 +    exp = re.compile('^' + name + ' .*[\(,]r(?P<mode>[ow])[,\)]')
   12.77 +    for line in lines:
   12.78 +        pm = exp.match(line)
   12.79 +        if not pm: continue
   12.80 +        mode = pm.group('mode')
   12.81 +        break
   12.82 +    if mode == 'w':
   12.83 +        return mode
   12.84 +    if mode == 'o':
   12.85 +        mode = 'r'
   12.86 +    return mode
   12.87 +    
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/python/xen/xend/XendBootloader.py	Thu Apr 28 13:33:33 2005 +0000
    13.3 @@ -0,0 +1,94 @@
    13.4 +#
    13.5 +# XendBootloader.py - Framework to run a boot loader for picking the kernel
    13.6 +#
    13.7 +# Copyright 2005 Red Hat, Inc.
    13.8 +# Jeremy Katz <katzj@xxxxxxxxxx>
    13.9 +#
   13.10 +# This software may be freely redistributed under the terms of the GNU
   13.11 +# general public license.
   13.12 +#
   13.13 +# You should have received a copy of the GNU General Public License
   13.14 +# along with this program; if not, write to the Free Software
   13.15 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   13.16 +#
   13.17 +
   13.18 +import os, sys, select
   13.19 +import sxp
   13.20 +
   13.21 +from XendLogging import log
   13.22 +from XendError import VmError
   13.23 +
   13.24 +BL_FIFO = "/var/lib/xen/xenbl"
   13.25 +
   13.26 +def bootloader(blexec, disk, quiet = 0, vcpus = None, entry = None):
   13.27 +    """Run the boot loader executable on the given disk and return a
   13.28 +    config image.
   13.29 +    @param blexec  Binary to use as the boot loader
   13.30 +    @param disk Disk to run the boot loader on.
   13.31 +    @param quiet Run in non-interactive mode, just booting the default.
   13.32 +    @param vcpus Number of vcpus for the domain.
   13.33 +    @param entry Default entry to boot."""
   13.34 +    
   13.35 +    if not os.access(blexec, os.X_OK):
   13.36 +        msg = "Bootloader isn't executable"
   13.37 +        log.error(msg)
   13.38 +        raise VmError(msg)
   13.39 +    if not os.access(disk, os.R_OK):
   13.40 +        msg = "Disk isn't accessible"
   13.41 +        log.error(msg)
   13.42 +        raise VmError(msg)
   13.43 +
   13.44 +    os.mkfifo(BL_FIFO, 0600)
   13.45 +
   13.46 +    child = os.fork()
   13.47 +    if (not child):
   13.48 +        args = [ blexec ]
   13.49 +        if quiet:
   13.50 +            args.append("-q")
   13.51 +        args.append("--output=%s" %(BL_FIFO,))
   13.52 +        if entry is not None:
   13.53 +            args.append("--entry=%s" %(entry,))
   13.54 +        args.append(disk)
   13.55 +
   13.56 +        try:
   13.57 +            os.execvp(args[0], args)
   13.58 +        except OSError, e:
   13.59 +            print e
   13.60 +            pass
   13.61 +        os._exit(1)
   13.62 +
   13.63 +    while 1:
   13.64 +        try:
   13.65 +            r = os.open(BL_FIFO, os.O_RDONLY)
   13.66 +        except OSError, e:
   13.67 +            if e.errno == 4:
   13.68 +                continue
   13.69 +        break
   13.70 +    ret = ""
   13.71 +    while 1:
   13.72 +        select.select([r], [], [])
   13.73 +        s = os.read(r, 1024)
   13.74 +        ret = ret + s
   13.75 +        if len(s) == 0:
   13.76 +            break
   13.77 +        
   13.78 +    (pid, status) = os.waitpid(child, 0)
   13.79 +    os.close(r)
   13.80 +    os.unlink(BL_FIFO)
   13.81 +
   13.82 +    if len(ret) == 0:
   13.83 +        msg = "Boot loader didn't return any data!"
   13.84 +        log.error(msg)
   13.85 +        raise VmError, msg
   13.86 +
   13.87 +    pin = sxp.Parser()
   13.88 +    pin.input(ret)
   13.89 +    pin.input_eof()
   13.90 +
   13.91 +    config_image = pin.val
   13.92 +    if vcpus and sxp.child_value(config_image, "vcpus") is None:
   13.93 +        config_image.append(['vcpus', vcpus])
   13.94 +
   13.95 +    config = ['image', config_image]
   13.96 +    return config
   13.97 +
    14.1 --- a/tools/python/xen/xend/XendDB.py	Thu Apr 28 10:46:53 2005 +0000
    14.2 +++ b/tools/python/xen/xend/XendDB.py	Thu Apr 28 13:33:33 2005 +0000
    14.3 @@ -20,6 +20,12 @@ class XendDB:
    14.4              self.dbpath = os.path.join(self.dbpath, path)
    14.5          pass
    14.6  
    14.7 +    def listdir(self, dpath):
    14.8 +        try:
    14.9 +            return dircache.listdir(dpath)
   14.10 +        except:
   14.11 +            return []
   14.12 +
   14.13      def filepath(self, path):
   14.14          return os.path.join(self.dbpath, path)
   14.15          
   14.16 @@ -52,21 +58,37 @@ class XendDB:
   14.17          return self.savefile(fpath, sxpr)
   14.18      
   14.19      def savefile(self, fpath, sxpr):
   14.20 +        backup = False
   14.21          fdir = os.path.dirname(fpath)
   14.22          if not os.path.isdir(fdir):
   14.23              os.makedirs(fdir)
   14.24 +        if os.path.exists(fpath):
   14.25 +            backup = True
   14.26 +            real_fpath = fpath
   14.27 +            fpath += ".new."
   14.28 +            
   14.29          fout = file(fpath, "wb+")
   14.30          try:
   14.31 -            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   14.32 -            fout.write("# %s %s\n" % (fpath, t))
   14.33 -            sxp.show(sxpr, out=fout)
   14.34 -        finally:
   14.35 -            fout.close()
   14.36 +            try:
   14.37 +                t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   14.38 +                fout.write("# %s %s\n" % (fpath, t))
   14.39 +                sxp.show(sxpr, out=fout)
   14.40 +            finally:
   14.41 +                fout.close()
   14.42 +        except:
   14.43 +            if backup:
   14.44 +                try:
   14.45 +                    os.unlink(fpath)
   14.46 +                except:
   14.47 +                    pass
   14.48 +                raise
   14.49 +        if backup:
   14.50 +            os.rename(fpath, real_fpath)
   14.51  
   14.52      def fetchall(self, path):
   14.53          dpath = self.filepath(path)
   14.54          d = {}
   14.55 -        for k in dircache.listdir(dpath):
   14.56 +        for k in self.listdir(dpath):
   14.57              try:
   14.58                  v = self.fetchfile(os.path.join(dpath, k))
   14.59                  d[k] = v
   14.60 @@ -84,8 +106,7 @@ class XendDB:
   14.61  
   14.62      def ls(self, path):
   14.63          dpath = self.filepath(path)
   14.64 -        return dircache.listdir(dpath)
   14.65 -            
   14.66 +        return self.listdir(dpath)
   14.67          
   14.68  
   14.69          
    15.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 28 10:46:53 2005 +0000
    15.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 28 13:33:33 2005 +0000
    15.3 @@ -16,11 +16,13 @@ import xen.lowlevel.xc; xc = xen.lowleve
    15.4  import xen.util.ip
    15.5  from xen.util.ip import _readline, _readlines
    15.6  from xen.xend.server import channel, controller
    15.7 +from xen.util.blkif import blkdev_uname_to_file
    15.8  
    15.9  from server.channel import channelFactory
   15.10  import server.SrvDaemon; xend = server.SrvDaemon.instance()
   15.11  from server import messages
   15.12  
   15.13 +from xen.xend.XendBootloader import bootloader
   15.14  import sxp
   15.15  from XendLogging import log
   15.16  from XendError import VmError
   15.17 @@ -294,6 +296,7 @@ class XendDomainInfo:
   15.18          self.image_handler = None
   15.19          self.is_vmx = False
   15.20          self.vcpus = 1
   15.21 +        self.bootloader = None
   15.22  
   15.23      def setdom(self, dom):
   15.24          """Set the domain id.
   15.25 @@ -496,6 +499,7 @@ class XendDomainInfo:
   15.26              self.find_image_handler()
   15.27              self.init_domain()
   15.28              self.register_domain()
   15.29 +            self.configure_bootloader()
   15.30  
   15.31              # Create domain devices.
   15.32              self.configure_backends()
   15.33 @@ -674,6 +678,13 @@ class XendDomainInfo:
   15.34          memory = memory * 1024 + self.pgtable_size(memory)
   15.35          dom = xc.domain_create(dom= dom, mem_kb= memory,
   15.36                                 cpu= cpu, cpu_weight= cpu_weight)
   15.37 +        if self.bootloader:
   15.38 +            try:
   15.39 +                if kernel: os.unlink(kernel)
   15.40 +                if ramdisk: os.unlink(ramdisk)
   15.41 +            except OSError, e:
   15.42 +                log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
   15.43 +
   15.44          if dom <= 0:
   15.45              raise VmError('Creating domain failed: name=%s memory=%d'
   15.46                            % (self.name, memory))
   15.47 @@ -854,6 +865,13 @@ class XendDomainInfo:
   15.48              self.config.remove(['device', dev_config])
   15.49          self.deleteDevice(type, dev.getId())
   15.50  
   15.51 +    def configure_bootloader(self):
   15.52 +        """Configure boot loader.
   15.53 +        """
   15.54 +        bl = sxp.child_value(self.config, "bootloader")
   15.55 +        if bl is not None:
   15.56 +            self.bootloader = bl
   15.57 +
   15.58      def configure_console(self):
   15.59          """Configure the vm console port.
   15.60          """
   15.61 @@ -931,10 +949,30 @@ class XendDomainInfo:
   15.62              self.state = STATE_VM_OK
   15.63              self.restart_check()
   15.64              self.restart_state = STATE_RESTART_BOOTING
   15.65 +            if self.bootloader:
   15.66 +                self.config = self.bootloader_config()
   15.67              self.construct(self.config)
   15.68          finally:
   15.69              self.restart_state = None
   15.70  
   15.71 +    def bootloader_config(self):
   15.72 +        # if we're restarting with a bootloader, we need to run it
   15.73 +        # FIXME: this assumes the disk is the first device and
   15.74 +        # that we're booting from the first disk
   15.75 +        blcfg = None
   15.76 +        # FIXME: this assumes that we want to use the first disk
   15.77 +        dev = sxp.child_value(self.config, "device")
   15.78 +        if dev:
   15.79 +            disk = sxp.child_value(dev, "uname")
   15.80 +            fn = blkdev_uname_to_file(disk)
   15.81 +            blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
   15.82 +        if blcfg is None:
   15.83 +            msg = "Had a bootloader specified, but can't find disk"
   15.84 +            log.error(msg)
   15.85 +            raise VmError(msg)
   15.86 +        config = sxp.merge(['vm', blconfig ], self.config)
   15.87 +        return config
   15.88 +
   15.89      def configure_backends(self):
   15.90          """Set configuration flags if the vm is a backend for netif or blkif.
   15.91          Configure the backends to use for vbd and vif if specified.
   15.92 @@ -1071,6 +1109,7 @@ def vm_image_linux(vm, image):
   15.93      if args:
   15.94          cmdline += " " + args
   15.95      ramdisk = sxp.child_value(image, "ramdisk", '')
   15.96 +    log.debug("creating linux domain with cmdline: %s" %(cmdline,))
   15.97      vm.create_domain("linux", kernel, ramdisk, cmdline)
   15.98      return vm
   15.99  
  15.100 @@ -1169,6 +1208,7 @@ add_config_handler('image',      vm_fiel
  15.101  add_config_handler('device',     vm_field_ignore)
  15.102  add_config_handler('backend',    vm_field_ignore)
  15.103  add_config_handler('vcpus',      vm_field_ignore)
  15.104 +add_config_handler('bootloader', vm_field_ignore)
  15.105  
  15.106  # Register other config handlers.
  15.107  add_config_handler('maxmem',     vm_field_maxmem)
    16.1 --- a/tools/python/xen/xend/server/blkif.py	Thu Apr 28 10:46:53 2005 +0000
    16.2 +++ b/tools/python/xen/xend/server/blkif.py	Thu Apr 28 13:33:33 2005 +0000
    16.3 @@ -1,11 +1,9 @@
    16.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    16.5  """Support for virtual block devices.
    16.6  """
    16.7 -
    16.8 -import os
    16.9 -import re
   16.10  import string
   16.11  
   16.12 +from xen.util import blkif
   16.13  from xen.xend.XendError import XendError, VmError
   16.14  from xen.xend import XendRoot
   16.15  from xen.xend.XendLogging import log
   16.16 @@ -16,77 +14,6 @@ import channel
   16.17  from controller import CtrlMsgRcvr, Dev, DevController
   16.18  from messages import *
   16.19  
   16.20 -from xen.util.ip import _readline, _readlines
   16.21 -
   16.22 -def expand_dev_name(name):
   16.23 -    if not name:
   16.24 -        return name
   16.25 -    if re.match( '^/dev/', name ):
   16.26 -        return name
   16.27 -    else:
   16.28 -        return '/dev/' + name
   16.29 -
   16.30 -def blkdev_name_to_number(name):
   16.31 -    """Take the given textual block-device name (e.g., '/dev/sda1',
   16.32 -    'hda') and return the device number used by the OS. """
   16.33 -
   16.34 -    n = expand_dev_name(name)
   16.35 -
   16.36 -    try:
   16.37 -        return os.stat(n).st_rdev
   16.38 -    except Exception, ex:
   16.39 -        log.debug("exception looking up device number for %s: %s", name, ex)
   16.40 -        pass
   16.41 -
   16.42 -    if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
   16.43 -        return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
   16.44 -
   16.45 -    if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
   16.46 -        ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
   16.47 -        major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
   16.48 -        minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
   16.49 -        return major * 256 + minor
   16.50 -
   16.51 -    # see if this is a hex device number
   16.52 -    if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
   16.53 -        return string.atoi(name,16)
   16.54 -        
   16.55 -    return None
   16.56 -
   16.57 -def blkdev_segment(name):
   16.58 -    """Take the given block-device name (e.g. '/dev/sda1', 'hda')
   16.59 -    and return a dictionary { device, start_sector,
   16.60 -    nr_sectors, type }
   16.61 -        device:       Device number of the given partition
   16.62 -        start_sector: Index of first sector of the partition
   16.63 -        nr_sectors:   Number of sectors comprising this partition
   16.64 -        type:         'Disk' or identifying name for partition type
   16.65 -    """
   16.66 -    val = None
   16.67 -    n = blkdev_name_to_number(name)
   16.68 -    if n:
   16.69 -        val = { 'device'       : n,
   16.70 -                'start_sector' : long(0),
   16.71 -                'nr_sectors'   : long(1L<<63),
   16.72 -                'type'         : 'Disk' }
   16.73 -    return val
   16.74 -
   16.75 -def mount_mode(name):
   16.76 -    mode = None
   16.77 -    name = expand_dev_name(name)
   16.78 -    lines = _readlines(os.popen('mount 2>/dev/null'))
   16.79 -    exp = re.compile('^' + name + ' .*[\(,]r(?P<mode>[ow])[,\)]')
   16.80 -    for line in lines:
   16.81 -        pm = exp.match(line)
   16.82 -        if not pm: continue
   16.83 -        mode = pm.group('mode')
   16.84 -        break
   16.85 -    if mode == 'w':
   16.86 -        return mode
   16.87 -    if mode == 'o':
   16.88 -        mode = 'r'
   16.89 -    return mode
   16.90 -    
   16.91  class BlkifBackend:
   16.92      """ Handler for the 'back-end' channel to a block device driver domain
   16.93      on behalf of a front-end domain.
   16.94 @@ -271,7 +198,7 @@ class BlkDev(Dev):
   16.95              raise VmError('vbd: Missing dev')
   16.96          self.mode = sxp.child_value(config, 'mode', 'r')
   16.97          
   16.98 -        self.vdev = blkdev_name_to_number(self.dev)
   16.99 +        self.vdev = blkif.blkdev_name_to_number(self.dev)
  16.100          if not self.vdev:
  16.101              raise VmError('vbd: Device not found: %s' % self.dev)
  16.102          
  16.103 @@ -324,7 +251,7 @@ class BlkDev(Dev):
  16.104                  raise VmError("vbd: Segment %s is in read-only use" %
  16.105                                self.uname)
  16.106              
  16.107 -        segment = blkdev_segment(node)
  16.108 +        segment = blkif.blkdev_segment(node)
  16.109          if not segment:
  16.110              raise VmError("vbd: Segment not found: uname=%s" % self.uname)
  16.111          self.node = node
  16.112 @@ -333,14 +260,14 @@ class BlkDev(Dev):
  16.113          self.nr_sectors = segment['nr_sectors']
  16.114  
  16.115      def check_mounted(self, name):
  16.116 -        mode = mount_mode(name)
  16.117 +        mode = blkif.mount_mode(name)
  16.118          xd = XendRoot.get_component('xen.xend.XendDomain')
  16.119          for vm in xd.domains():
  16.120              ctrl = vm.getDeviceController(self.getType(), error=False)
  16.121              if (not ctrl): continue
  16.122              for dev in ctrl.getDevices():
  16.123                  if dev is self: continue
  16.124 -                if dev.type == 'phy' and name == expand_dev_name(dev.params):
  16.125 +                if dev.type == 'phy' and name == blkif.expand_dev_name(dev.params):
  16.126                      mode = dev.mode
  16.127                      if 'w' in mode:
  16.128                          return 'w'
    17.1 --- a/tools/python/xen/xm/create.py	Thu Apr 28 10:46:53 2005 +0000
    17.2 +++ b/tools/python/xen/xm/create.py	Thu Apr 28 13:33:33 2005 +0000
    17.3 @@ -10,6 +10,8 @@ import socket
    17.4  from xen.xend import sxp
    17.5  from xen.xend import PrettyPrint
    17.6  from xen.xend.XendClient import server, XendError
    17.7 +from xen.xend.XendBootloader import bootloader
    17.8 +from xen.util import blkif
    17.9  
   17.10  from xen.util import console_client
   17.11  
   17.12 @@ -94,6 +96,14 @@ gopts.var('name', val='NAME',
   17.13            fn=set_value, default=None,
   17.14            use="Domain name. Must be unique.")
   17.15  
   17.16 +gopts.var('bootloader', val='FILE',
   17.17 +          fn=set_value, default=None,
   17.18 +          use="Path to bootloader.")
   17.19 +
   17.20 +gopts.var('bootentry', val='NAME',
   17.21 +          fn=set_value, default=None,
   17.22 +          use="Entry to boot via boot loader")
   17.23 +
   17.24  gopts.var('kernel', val='FILE',
   17.25            fn=set_value, default=None,
   17.26            use="Path to kernel image.")
   17.27 @@ -252,7 +262,7 @@ def strip(pre, s):
   17.28      else:
   17.29          return s
   17.30  
   17.31 -def configure_image(config, vals):
   17.32 +def configure_image(opts, config, vals):
   17.33      """Create the image config.
   17.34      """
   17.35      config_image = [ vals.builder ]
   17.36 @@ -272,7 +282,7 @@ def configure_image(config, vals):
   17.37      config.append(['image', config_image ])
   17.38  
   17.39      
   17.40 -def configure_disks(config_devs, vals):
   17.41 +def configure_disks(opts, config_devs, vals):
   17.42      """Create the config for disks (virtual block devices).
   17.43      """
   17.44      for (uname, dev, mode, backend) in vals.disk:
   17.45 @@ -284,14 +294,14 @@ def configure_disks(config_devs, vals):
   17.46              config_vbd.append(['backend', backend])
   17.47          config_devs.append(['device', config_vbd])
   17.48  
   17.49 -def configure_pci(config_devs, vals):
   17.50 +def configure_pci(opts, config_devs, vals):
   17.51      """Create the config for pci devices.
   17.52      """
   17.53      for (bus, dev, func) in vals.pci:
   17.54          config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
   17.55          config_devs.append(['device', config_pci])
   17.56  
   17.57 -def configure_usb(config_devs, vals):
   17.58 +def configure_usb(opts, config_devs, vals):
   17.59      for path in vals.usb:
   17.60          config_usb = ['usb', ['path', path]]
   17.61          config_devs.append(['device', config_usb])
   17.62 @@ -315,7 +325,7 @@ def randomMAC():
   17.63              random.randint(0x00, 0xff) ]
   17.64      return ':'.join(map(lambda x: "%02x" % x, mac))
   17.65  
   17.66 -def configure_vifs(config_devs, vals):
   17.67 +def configure_vifs(opts, config_devs, vals):
   17.68      """Create the config for virtual network interfaces.
   17.69      """
   17.70      vifs = vals.vif
   17.71 @@ -357,7 +367,7 @@ def configure_vifs(config_devs, vals):
   17.72              config_vif.append(['ip', ip])
   17.73          config_devs.append(['device', config_vif])
   17.74  
   17.75 -def configure_vfr(config, vals):
   17.76 +def configure_vfr(opts, config, vals):
   17.77       if not vals.ipaddr: return
   17.78       config_vfr = ['vfr']
   17.79       idx = 0 # No way of saying which IP is for which vif?
   17.80 @@ -365,7 +375,7 @@ def configure_vfr(config, vals):
   17.81           config_vfr.append(['vif', ['id', idx], ['ip', ip]])
   17.82       config.append(config_vfr)
   17.83  
   17.84 -def configure_vmx(config_devs, vals):
   17.85 +def configure_vmx(opts, config_devs, vals):
   17.86      """Create the config for VMX devices.
   17.87      """
   17.88      memmap = vals.memmap
   17.89 @@ -375,7 +385,21 @@ def configure_vmx(config_devs, vals):
   17.90      config_devs.append(['device_model', device_model])
   17.91      config_devs.append(['device_config', device_config])
   17.92  
   17.93 -def make_config(vals):
   17.94 +def run_bootloader(opts, config, vals):
   17.95 +    if not os.access(vals.bootloader, os.X_OK):
   17.96 +        opts.err("Bootloader isn't executable")
   17.97 +    if len(vals.disk) < 1:
   17.98 +        opts.err("No disks configured and boot loader requested")
   17.99 +    (uname, dev, mode, backend) = vals.disk[0]
  17.100 +    file = blkif.blkdev_uname_to_file(uname)
  17.101 +
  17.102 +    blcfg = bootloader(vals.bootloader, file, not vals.console_autoconnect,
  17.103 +                       vals.vcpus, vals.blentry)
  17.104 +
  17.105 +    config.append(['bootloader', vals.bootloader])
  17.106 +    config.append(blcfg)
  17.107 +
  17.108 +def make_config(opts, vals):
  17.109      """Create the domain configuration.
  17.110      """
  17.111      
  17.112 @@ -396,15 +420,19 @@ def make_config(vals):
  17.113          config.append(['restart', vals.restart])
  17.114      if vals.console:
  17.115          config.append(['console', vals.console])
  17.116 -    
  17.117 -    configure_image(config, vals)
  17.118 +
  17.119 +    if vals.bootloader:
  17.120 +        run_bootloader(opts, config, vals)
  17.121 +    else:
  17.122 +        configure_image(opts, config, vals)
  17.123      config_devs = []
  17.124 -    configure_disks(config_devs, vals)
  17.125 -    configure_pci(config_devs, vals)
  17.126 -    configure_vifs(config_devs, vals)
  17.127 -    configure_usb(config_devs, vals)
  17.128 -    configure_vmx(config_devs, vals)
  17.129 +    configure_disks(opts, config_devs, vals)
  17.130 +    configure_pci(opts, config_devs, vals)
  17.131 +    configure_vifs(opts, config_devs, vals)
  17.132 +    configure_usb(opts, config_devs, vals)
  17.133 +    configure_vmx(opts, config_devs, vals)
  17.134      config += config_devs
  17.135 +
  17.136      return config
  17.137  
  17.138  def preprocess_disk(opts, vals):
  17.139 @@ -587,7 +615,8 @@ def main(argv):
  17.140          preprocess(opts, opts.vals)
  17.141          if not opts.getopt('name') and opts.getopt('defconfig'):
  17.142              opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
  17.143 -        config = make_config(opts.vals)
  17.144 +        config = make_config(opts, opts.vals)
  17.145 +
  17.146      if opts.vals.dryrun:
  17.147          PrettyPrint.prettyprint(config)
  17.148      else:
    18.1 --- a/tools/xfrd/xfrd.c	Thu Apr 28 10:46:53 2005 +0000
    18.2 +++ b/tools/xfrd/xfrd.c	Thu Apr 28 13:33:33 2005 +0000
    18.3 @@ -49,7 +49,7 @@
    18.4  #include "select.h"
    18.5  
    18.6  #define MODULE_NAME "XFRD"
    18.7 -
    18.8 +#define DEBUG 1
    18.9  #include "debug.h"
   18.10  
   18.11  /*
   18.12 @@ -1226,7 +1226,9 @@ int main(int argc, char *argv[]){
   18.13      int err = 0;
   18.14      int key = 0;
   18.15      int long_index = 0;
   18.16 +#ifndef DEBUG
   18.17      static const char * LOGFILE = "/var/log/xfrd.log";
   18.18 +#endif
   18.19  
   18.20  #ifndef DEBUG
   18.21      freopen(LOGFILE, "w+", stdout);