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
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/pygrub/src/fsys/__init__.py	Thu Apr 28 13:33:33 2005 +0000
     8.3 @@ -0,0 +1,61 @@
     8.4 +#
     8.5 +# Copyright 2005 Red Hat, Inc.
     8.6 +# Jeremy Katz <katzj@xxxxxxxxxx>
     8.7 +#
     8.8 +# This software may be freely redistributed under the terms of the GNU
     8.9 +# general public license.
    8.10 +#
    8.11 +# You should have received a copy of the GNU General Public License
    8.12 +# along with this program; if not, write to the Free Software
    8.13 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    8.14 +#
    8.15 +
    8.16 +import os
    8.17 +import sys
    8.18 +
    8.19 +fstypes = {}
    8.20 +
    8.21 +def register_fstype(x):
    8.22 +    if x.name in fstypes.keys():
    8.23 +        return
    8.24 +    fstypes[x.name] = x
    8.25 +
    8.26 +class FileSystemType(object):
    8.27 +    """A simple representation for a file system that gives a fs name
    8.28 +    and a method for sniffing a file to see if it's of the given fstype."""
    8.29 +    def __init__(self):
    8.30 +        self.name = ""
    8.31 +
    8.32 +    def sniff_magic(self, fn, offset = 0):
    8.33 +        """Look at the filesystem at fn for the appropriate magic starting at
    8.34 +        offset offset."""
    8.35 +        raise RuntimeError, "sniff_magic not implemented"
    8.36 +
    8.37 +    def open_fs(self, fn, offset = 0):
    8.38 +        """Open the given filesystem and return a filesystem object."""
    8.39 +        raise RuntimeError, "open_fs not implemented"
    8.40 +
    8.41 +class FileSystem(object):
    8.42 +    def open(self, name, flags = 0, block_size = 0):
    8.43 +        """Open the fsys on name with given flags and block_size."""
    8.44 +        raise RuntimeError, "open not implemented"
    8.45 +
    8.46 +    def close(self):
    8.47 +        """Close the fsys."""
    8.48 +        raise RuntimeError, "close not implemented"
    8.49 +
    8.50 +    def open_file(self, file, flags = None):
    8.51 +        """Open the file 'name' with the given flags.  The returned object
    8.52 +        should look similar to a native file object."""
    8.53 +        raise RuntimeError, "open_file not implemented"
    8.54 +    
    8.55 +
    8.56 +
    8.57 +mydir = sys.modules['grub.fsys'].__path__[0]
    8.58 +for f in os.listdir(mydir):
    8.59 +    if not os.path.isdir("%s/%s" %(mydir, f)):
    8.60 +        continue
    8.61 +    try:
    8.62 +        exec "import grub.fsys.%s" %(f,)        
    8.63 +    except ImportError, e:
    8.64 +        pass
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/pygrub/src/fsys/ext2/__init__.py	Thu Apr 28 13:33:33 2005 +0000
     9.3 @@ -0,0 +1,38 @@
     9.4 +# Copyright 2005 Red Hat, Inc.
     9.5 +# Jeremy Katz <katzj@redhat.com>
     9.6 +#
     9.7 +# This software may be freely redistributed under the terms of the GNU
     9.8 +# general public license.
     9.9 +#
    9.10 +# You should have received a copy of the GNU General Public License
    9.11 +# along with this program; if not, write to the Free Software
    9.12 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    9.13 +#
    9.14 +
    9.15 +from grub.fsys import register_fstype, FileSystemType
    9.16 +from _pyext2 import *
    9.17 +
    9.18 +import os, struct
    9.19 +
    9.20 +class Ext2FileSystemType(FileSystemType):
    9.21 +    def __init__(self):
    9.22 +        FileSystemType.__init__(self)
    9.23 +        self.name = "ext2"
    9.24 +
    9.25 +    def sniff_magic(self, fn, offset = 0):
    9.26 +        fd = os.open(fn, os.O_RDONLY)
    9.27 +        os.lseek(fd, offset, 0)
    9.28 +        buf = os.read(fd, 2048)
    9.29 +        
    9.30 +        if len(buf) > 1082 and \
    9.31 +               struct.unpack("<H", buf[1080:1082]) == (0xef53,):
    9.32 +            return True
    9.33 +        return False
    9.34 +
    9.35 +    def open_fs(self, fn, offset = 0):
    9.36 +        if not self.sniff_magic(fn, offset):
    9.37 +            raise ValueError, "Not an ext2 filesystem"
    9.38 +        return Ext2Fs(fn)
    9.39 +
    9.40 +register_fstype(Ext2FileSystemType())
    9.41 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/pygrub/src/fsys/ext2/ext2module.c	Thu Apr 28 13:33:33 2005 +0000
    10.3 @@ -0,0 +1,332 @@
    10.4 +/*
    10.5 + * ext2module.c - simple python binding for libext2fs
    10.6 + *
    10.7 + * Copyright 2005 Red Hat, Inc.
    10.8 + * Jeremy Katz <katzj@redhat.com>
    10.9 + *
   10.10 + * This software may be freely redistributed under the terms of the GNU
   10.11 + * general public license.
   10.12 + *
   10.13 + * You should have received a copy of the GNU General Public License
   10.14 + * along with this program; if not, write to the Free Software
   10.15 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   10.16 + */
   10.17 +
   10.18 +#include <Python.h>
   10.19 +
   10.20 +#include <ext2fs/ext2fs.h>
   10.21 +#include <stdlib.h>
   10.22 +#include <stdio.h>
   10.23 +
   10.24 +#if (PYTHON_API_VERSION >= 1011)
   10.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
   10.26 +#else
   10.27 +#define PY_PAD 0L,0L,0L,0L
   10.28 +#endif
   10.29 +
   10.30 +
   10.31 +/* global error object */
   10.32 +PyObject *Ext2Error;
   10.33 +
   10.34 +typedef struct _Ext2Fs Ext2Fs;
   10.35 +struct _Ext2Fs {
   10.36 +    PyObject_HEAD;
   10.37 +    ext2_filsys fs;
   10.38 +};
   10.39 +
   10.40 +typedef struct _Ext2File Ext2File;
   10.41 +struct _Ext2File {
   10.42 +    PyObject_HEAD;
   10.43 +    ext2_file_t file;
   10.44 +};
   10.45 +
   10.46 +/* ext2 file object */
   10.47 +
   10.48 +static PyObject *
   10.49 +ext2_file_close (Ext2File *file, PyObject *args)
   10.50 +{
   10.51 +    if (file->file != NULL)
   10.52 +        ext2fs_file_close(file->file);
   10.53 +    Py_INCREF(Py_None);
   10.54 +    return Py_None;
   10.55 +}
   10.56 +
   10.57 +static PyObject *
   10.58 +ext2_file_read (Ext2File *file, PyObject *args)
   10.59 +{
   10.60 +    int err, size = 0;
   10.61 +    size_t n, total = 0;
   10.62 +    PyObject * buffer = NULL;
   10.63 +
   10.64 +    if (file->file == NULL) {
   10.65 +        PyErr_SetString(PyExc_ValueError, "Cannot read from closed file");
   10.66 +        return NULL;
   10.67 +    }
   10.68 +
   10.69 +    if (!PyArg_ParseTuple(args, "|i", &size))
   10.70 +        return NULL;
   10.71 +
   10.72 +    buffer = PyString_FromStringAndSize((char *) NULL, (size) ? size : 4096);
   10.73 +    if (buffer == NULL)
   10.74 +        return buffer;
   10.75 + 
   10.76 +    while (1) {
   10.77 +        err = ext2fs_file_read(file->file, PyString_AS_STRING(buffer) + total, 
   10.78 +                               (size) ? size : 4096, &n);
   10.79 +        if (err) {
   10.80 +            if (buffer != NULL) { Py_DECREF(buffer); }
   10.81 +            Py_DECREF(buffer);
   10.82 +            PyErr_SetString(PyExc_ValueError, "read error");
   10.83 +            return NULL;
   10.84 +        }
   10.85 +
   10.86 +        total += n;
   10.87 +        if (n == 0)
   10.88 +            break;
   10.89 +
   10.90 +        if (size && size == total)
   10.91 +            break;
   10.92 +
   10.93 +        if (!size) {
   10.94 +            _PyString_Resize(&buffer, total + 4096);
   10.95 +        }
   10.96 +    }
   10.97 +
   10.98 +    _PyString_Resize(&buffer, total);
   10.99 +    return buffer;
  10.100 +}
  10.101 +
  10.102 +static void
  10.103 +ext2_file_dealloc (Ext2File * file)
  10.104 +{
  10.105 +    if (file->file != NULL)
  10.106 +        ext2fs_file_close(file->file);
  10.107 +    PyMem_DEL(file);
  10.108 +}
  10.109 +
  10.110 +static struct PyMethodDef Ext2FileMethods[] = {
  10.111 +        { "close",
  10.112 +          (PyCFunction) ext2_file_close,
  10.113 +          METH_VARARGS, NULL },
  10.114 +        { "read",
  10.115 +          (PyCFunction) ext2_file_read,
  10.116 +          METH_VARARGS, NULL },
  10.117 +	{ NULL, NULL, 0, NULL }	
  10.118 +};
  10.119 +
  10.120 +static PyObject *
  10.121 +ext2_file_getattr (Ext2File * file, char * name)
  10.122 +{
  10.123 +        return Py_FindMethod (Ext2FileMethods, (PyObject *) file, name);
  10.124 +}
  10.125 +
  10.126 +static char Ext2FileType__doc__[] = "This is the ext2 filesystem object";
  10.127 +PyTypeObject Ext2FileType = {
  10.128 +	PyObject_HEAD_INIT(&PyType_Type)
  10.129 +	0,				/* ob_size */
  10.130 +	"Ext2File",			/* tp_name */
  10.131 +	sizeof(Ext2File),		/* tp_size */
  10.132 +	0,				/* tp_itemsize */
  10.133 +	(destructor) ext2_file_dealloc, 	/* tp_dealloc */
  10.134 +	0,				/* tp_print */
  10.135 +	(getattrfunc) ext2_file_getattr, 	/* tp_getattr */
  10.136 +	0,				/* tp_setattr */
  10.137 +	0,				/* tp_compare */
  10.138 +	0,				/* tp_repr */
  10.139 +	0,				/* tp_as_number */
  10.140 +	0,	 			/* tp_as_sequence */
  10.141 +	0,				/* tp_as_mapping */
  10.142 +	0,           			/* tp_hash */
  10.143 +	0,                		/* tp_call */
  10.144 +	0,                    		/* tp_str */
  10.145 +	0,				/* tp_getattro */
  10.146 +	0,				/* tp_setattro */
  10.147 +	0,				/* tp_as_buffer */
  10.148 +	0L,	       			/* tp_flags */
  10.149 +	Ext2FileType__doc__,
  10.150 +	PY_PAD
  10.151 +};
  10.152 +
  10.153 +static PyObject *
  10.154 +ext2_file_open (Ext2Fs *fs, char * name, int flags)
  10.155 +{
  10.156 +    int err;
  10.157 +    ext2_file_t f;
  10.158 +    ext2_ino_t ino;
  10.159 +    Ext2File * file;
  10.160 +
  10.161 +    file = (Ext2File *) PyObject_NEW(Ext2File, &Ext2FileType);
  10.162 +    file->file = NULL;
  10.163 +
  10.164 +    err = ext2fs_namei_follow(fs->fs, EXT2_ROOT_INO, EXT2_ROOT_INO, name, &ino);
  10.165 +    if (err) {
  10.166 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
  10.167 +        return NULL;
  10.168 +    }
  10.169 +
  10.170 +    err = ext2fs_file_open(fs->fs, ino, flags, &f);
  10.171 +    if (err) {
  10.172 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
  10.173 +        return NULL;
  10.174 +    }
  10.175 +
  10.176 +    file->file = f;
  10.177 +    return (PyObject *) file;
  10.178 +}
  10.179 +
  10.180 +/* ext2fs object */
  10.181 +
  10.182 +static PyObject *
  10.183 +ext2_fs_close (Ext2Fs *fs, PyObject *args)
  10.184 +{
  10.185 +    if (fs->fs != NULL)
  10.186 +        ext2fs_close(fs->fs);
  10.187 +    Py_INCREF(Py_None);
  10.188 +    return Py_None;
  10.189 +}
  10.190 +
  10.191 +static PyObject *
  10.192 +ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
  10.193 +{
  10.194 +    static char *kwlist[] = { "name", "flags", "superblock", 
  10.195 +                              "block_size", NULL };
  10.196 +    char * name;
  10.197 +    int flags = 0, superblock = 0, err;
  10.198 +    unsigned int block_size = 0;
  10.199 +    ext2_filsys efs;
  10.200 +
  10.201 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
  10.202 +                                     &name, &flags, &superblock, &block_size))
  10.203 +                                     return NULL;
  10.204 +
  10.205 +    if (fs->fs != NULL) {
  10.206 +        PyErr_SetString(PyExc_ValueError, "already have an fs object");
  10.207 +        return NULL;
  10.208 +    }
  10.209 +
  10.210 +    err = ext2fs_open(name, flags, superblock, block_size, 
  10.211 +                      unix_io_manager, &efs);
  10.212 +    if (err) {
  10.213 +        PyErr_SetString(PyExc_ValueError, "unable to open file");
  10.214 +        return NULL;
  10.215 +    }
  10.216 +
  10.217 +    fs->fs = efs;
  10.218 +
  10.219 +    Py_INCREF(Py_None);
  10.220 +    return Py_None;
  10.221 +}
  10.222 +
  10.223 +static PyObject *
  10.224 +ext2_fs_open_file (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
  10.225 +{
  10.226 +    static char *kwlist[] = { "name", "flags", NULL };
  10.227 +    char * name;
  10.228 +    int flags = 0;
  10.229 +
  10.230 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", kwlist, 
  10.231 +                                     &name, &flags))
  10.232 +                                     return NULL;
  10.233 +
  10.234 +    return ext2_file_open(fs, name, flags);
  10.235 +}
  10.236 +
  10.237 +static void
  10.238 +ext2_fs_dealloc (Ext2Fs * fs)
  10.239 +{
  10.240 +    if (fs->fs != NULL)
  10.241 +        ext2fs_close(fs->fs);
  10.242 +    PyMem_DEL(fs);
  10.243 +}
  10.244 +
  10.245 +static struct PyMethodDef Ext2FsMethods[] = {
  10.246 +        { "close",
  10.247 +          (PyCFunction) ext2_fs_close,
  10.248 +          METH_VARARGS, NULL },
  10.249 +        { "open",
  10.250 +          (PyCFunction) ext2_fs_open,
  10.251 +          METH_VARARGS|METH_KEYWORDS, NULL },
  10.252 +        { "open_file",
  10.253 +          (PyCFunction) ext2_fs_open_file,
  10.254 +          METH_VARARGS|METH_KEYWORDS, NULL },
  10.255 +	{ NULL, NULL, 0, NULL }	
  10.256 +};
  10.257 +
  10.258 +static PyObject *
  10.259 +ext2_fs_getattr (Ext2Fs * fs, char * name)
  10.260 +{
  10.261 +        return Py_FindMethod (Ext2FsMethods, (PyObject *) fs, name);
  10.262 +}
  10.263 +
  10.264 +static char Ext2FsType__doc__[] = "This is the ext2 filesystem object";
  10.265 +PyTypeObject Ext2FsType = {
  10.266 +	PyObject_HEAD_INIT(&PyType_Type)
  10.267 +	0,				/* ob_size */
  10.268 +	"Ext2Fs",			/* tp_name */
  10.269 +	sizeof(Ext2Fs),		/* tp_size */
  10.270 +	0,				/* tp_itemsize */
  10.271 +	(destructor) ext2_fs_dealloc, 	/* tp_dealloc */
  10.272 +	0,				/* tp_print */
  10.273 +	(getattrfunc) ext2_fs_getattr, 	/* tp_getattr */
  10.274 +	0,				/* tp_setattr */
  10.275 +	0,				/* tp_compare */
  10.276 +	0,				/* tp_repr */
  10.277 +	0,				/* tp_as_number */
  10.278 +	0,	 			/* tp_as_sequence */
  10.279 +	0,				/* tp_as_mapping */
  10.280 +	0,           			/* tp_hash */
  10.281 +	0,                		/* tp_call */
  10.282 +	0,                    		/* tp_str */
  10.283 +	0,				/* tp_getattro */
  10.284 +	0,				/* tp_setattro */
  10.285 +	0,				/* tp_as_buffer */
  10.286 +	0L,	       			/* tp_flags */
  10.287 +	Ext2FsType__doc__,
  10.288 +	PY_PAD
  10.289 +};
  10.290 +
  10.291 +static PyObject *
  10.292 +ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs) 
  10.293 +{
  10.294 +    static char *kwlist[] = { "name", "flags", "superblock", 
  10.295 +                              "block_size", NULL };
  10.296 +    char * name;
  10.297 +    int flags = 0, superblock = 0;
  10.298 +    unsigned int block_size = 0;
  10.299 +    Ext2Fs *pfs;
  10.300 +
  10.301 +    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
  10.302 +                                     &name, &flags, &superblock, &block_size))
  10.303 +        return NULL;
  10.304 +
  10.305 +    pfs = (Ext2Fs *) PyObject_NEW(Ext2Fs, &Ext2FsType);
  10.306 +    if (pfs == NULL)
  10.307 +        return NULL;
  10.308 +    pfs->fs = NULL;
  10.309 +
  10.310 +    if (!ext2_fs_open(pfs, 
  10.311 +                      Py_BuildValue("siii", name, flags, superblock, block_size),
  10.312 +                      NULL))
  10.313 +        return NULL;
  10.314 +
  10.315 +    return (PyObject *)pfs;
  10.316 +}
  10.317 +
  10.318 +
  10.319 +static struct PyMethodDef Ext2ModuleMethods[] = {
  10.320 +    { "Ext2Fs", (PyCFunction) ext2_fs_new, METH_VARARGS|METH_KEYWORDS, NULL },
  10.321 +    { NULL, NULL, 0, NULL }
  10.322 +};
  10.323 +
  10.324 +
  10.325 +void init_pyext2(void) {
  10.326 +    PyObject *m, *d;
  10.327 +
  10.328 +    m = Py_InitModule("_pyext2", Ext2ModuleMethods);
  10.329 +    d = PyModule_GetDict(m);
  10.330 +
  10.331 +    /*    o = PyObject_NEW(PyObject, yExt2FsConstructorType);
  10.332 +    PyDict_SetItemString(d, "PyExt2Fs", o);
  10.333 +    Py_DECREF(o);*/
  10.334 +                      
  10.335 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/pygrub/src/fsys/ext2/test.py	Thu Apr 28 13:33:33 2005 +0000
    11.3 @@ -0,0 +1,15 @@
    11.4 +#!/usr/bin/python
    11.5 +
    11.6 +
    11.7 +import _pyext2
    11.8 +import struct, os, sys
    11.9 +
   11.10 +fs = _pyext2.Ext2Fs("test.img")
   11.11 +
   11.12 +f = fs.open_file("/boot/vmlinuz-2.6.11-1.1177_FC4")
   11.13 +buf = f.read()
   11.14 +o = open("vmlinuz", "wb+")
   11.15 +o.write(buf)
   11.16 +o.close()
   11.17 +
   11.18 +f.close()
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/pygrub/src/pygrub	Thu Apr 28 13:33:33 2005 +0000
    12.3 @@ -0,0 +1,270 @@
    12.4 +#!/usr/bin/python
    12.5 +#
    12.6 +# pygrub - simple python-based bootloader for Xen
    12.7 +#
    12.8 +# Copyright 2005 Red Hat, Inc.
    12.9 +# Jeremy Katz <katzj@redhat.com>
   12.10 +#
   12.11 +# This software may be freely redistributed under the terms of the GNU
   12.12 +# general public license.
   12.13 +#
   12.14 +# You should have received a copy of the GNU General Public License
   12.15 +# along with this program; if not, write to the Free Software
   12.16 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   12.17 +#
   12.18 +
   12.19 +import os, sys, string, struct, tempfile
   12.20 +import logging
   12.21 +
   12.22 +import curses, _curses, curses.wrapper
   12.23 +import getopt
   12.24 +
   12.25 +import grub.GrubConf
   12.26 +import grub.fsys
   12.27 +
   12.28 +PYGRUB_VER = 0.02
   12.29 +
   12.30 +
   12.31 +def draw_window():
   12.32 +    stdscr = curses.initscr()
   12.33 +    curses.use_default_colors()
   12.34 +    try:
   12.35 +        curses.curs_set(0)
   12.36 +    except _curses.error:
   12.37 +        pass
   12.38 +
   12.39 +    stdscr.addstr(1, 4, "pyGRUB  version %s" %(PYGRUB_VER,))
   12.40 +
   12.41 +    win = curses.newwin(10, 74, 2, 1)
   12.42 +    win.box()
   12.43 +    win.refresh()
   12.44 +
   12.45 +    stdscr.addstr(12, 5, "Use the U and D keys to select which entry is highlighted.")
   12.46 +    stdscr.addstr(13, 5, "Press enter to boot the selected OS. 'e' to edit the")
   12.47 +    stdscr.addstr(14, 5, "commands before booting, 'a' to modify the kernel arguments ")
   12.48 +    stdscr.addstr(15, 5, "before booting, or 'c' for a command line.")
   12.49 +    stdscr.addch(12, 13, curses.ACS_UARROW)
   12.50 +    stdscr.addch(12, 19, curses.ACS_DARROW)
   12.51 +    (y, x) = stdscr.getmaxyx()
   12.52 +    stdscr.move(y - 1, x - 1)
   12.53 +
   12.54 +    stdscr.refresh()
   12.55 +    return (stdscr, win)
   12.56 +
   12.57 +def fill_entries(win, cfg, selected):
   12.58 +    y = 0
   12.59 +
   12.60 +    for i in cfg.images:
   12.61 +        if (0, y) > win.getmaxyx():
   12.62 +            break
   12.63 +        if y == selected:
   12.64 +            attr = curses.A_REVERSE
   12.65 +        else:
   12.66 +            attr = 0
   12.67 +        win.addstr(y + 1, 2, i.title.ljust(70), attr)
   12.68 +        y += 1
   12.69 +    win.refresh()
   12.70 +
   12.71 +def select(win, line):
   12.72 +    win.attron(curses.A_REVERSE)
   12.73 +    win.redrawln(line + 1, 1)
   12.74 +    win.refresh()
   12.75 +
   12.76 +def is_disk_image(file):
   12.77 +    fd = os.open(file, os.O_RDONLY)
   12.78 +    buf = os.read(fd, 512)
   12.79 +    os.close(fd)
   12.80 +
   12.81 +    if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
   12.82 +        return True
   12.83 +    return False
   12.84 +    
   12.85 +
   12.86 +def get_config(fn):
   12.87 +    if not os.access(fn, os.R_OK):
   12.88 +        raise RuntimeError, "Unable to access %s" %(fn,)
   12.89 +
   12.90 +    cf = grub.GrubConf.GrubConfigFile()
   12.91 +
   12.92 +    if is_disk_image(fn):
   12.93 +        raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
   12.94 +
   12.95 +    # open the image and read the grub config
   12.96 +    fs = None
   12.97 +    for fstype in grub.fsys.fstypes.values():
   12.98 +        if fstype.sniff_magic(fn):
   12.99 +            fs = fstype.open_fs(fn)
  12.100 +            break
  12.101 +
  12.102 +    if fs is not None:
  12.103 +        f = fs.open_file("/boot/grub/grub.conf")
  12.104 +        buf = f.read()
  12.105 +        f.close()
  12.106 +        fs.close()
  12.107 +        # then parse the grub config
  12.108 +        cf.parse(buf)
  12.109 +    else:
  12.110 +        # set the config file and parse it
  12.111 +        cf.filename = fn
  12.112 +        cf.parse()
  12.113 +    
  12.114 +    return cf
  12.115 +
  12.116 +def get_entry_idx(cf, entry):
  12.117 +    # first, see if the given entry is numeric
  12.118 +    try:
  12.119 +        idx = string.atoi(entry)
  12.120 +        return idx
  12.121 +    except ValueError:
  12.122 +        pass
  12.123 +
  12.124 +    # it's not, now check the labels for a match
  12.125 +    for i in range(len(cf.images)):
  12.126 +        if entry == cf.images[i].title:
  12.127 +            return i
  12.128 +
  12.129 +    return None
  12.130 +
  12.131 +def main(cf = None):
  12.132 +    mytime = 0
  12.133 +
  12.134 +    (stdscr, win) = draw_window()
  12.135 +    stdscr.timeout(1000)
  12.136 +    selected = cf.default
  12.137 +    
  12.138 +    while (mytime < int(cf.timeout)):
  12.139 +        if cf.timeout != -1 and mytime != -1: 
  12.140 +            stdscr.addstr(20, 5, "Will boot selected entry in %2d seconds"
  12.141 +                          %(int(cf.timeout) - mytime))
  12.142 +        else:
  12.143 +            stdscr.addstr(20, 5, " " * 80)
  12.144 +            
  12.145 +        fill_entries(win, cf, selected)
  12.146 +        c = stdscr.getch()
  12.147 +        if mytime != -1:
  12.148 +            mytime += 1
  12.149 +#        if c == ord('q'):
  12.150 +#            selected = -1
  12.151 +#            break
  12.152 +        elif c == ord('c'):
  12.153 +            # FIXME: needs to go to command line mode
  12.154 +            continue
  12.155 +        elif c == ord('a'):
  12.156 +            # FIXME: needs to go to append mode
  12.157 +            continue
  12.158 +        elif c == ord('e'):
  12.159 +            # FIXME: needs to go to edit mode
  12.160 +            continue
  12.161 +        elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')):
  12.162 +            break
  12.163 +        elif c == curses.KEY_UP:
  12.164 +            mytime = -1
  12.165 +            selected -= 1
  12.166 +        elif c == curses.KEY_DOWN:
  12.167 +            mytime = -1
  12.168 +            selected += 1
  12.169 +        else:
  12.170 +            pass
  12.171 +
  12.172 +        # bound at the top and bottom
  12.173 +        if selected < 0:
  12.174 +            selected = 0
  12.175 +        elif selected >= len(cf.images):
  12.176 +            selected = len(cf.images) - 1
  12.177 +
  12.178 +    if selected >= 0:
  12.179 +        return selected
  12.180 +
  12.181 +if __name__ == "__main__":
  12.182 +    sel = None
  12.183 +    
  12.184 +    def run_main(scr, *args):
  12.185 +        global sel
  12.186 +        sel = main(cf)
  12.187 +
  12.188 +    def usage():
  12.189 +        print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <image>" %(sys.argv[0],)
  12.190 +
  12.191 +    try:
  12.192 +        opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::',
  12.193 +                                   ["quiet", "help", "output=", "entry="])
  12.194 +    except getopt.GetoptError:
  12.195 +        usage()
  12.196 +        sys.exit(1)
  12.197 +
  12.198 +    if len(args) < 1:
  12.199 +        usage()
  12.200 +        sys.exit(1)
  12.201 +    file = args[0]
  12.202 +        
  12.203 +    output = None
  12.204 +    entry = None
  12.205 +    interactive = True
  12.206 +    for o, a in opts:
  12.207 +        if o in ("-q", "--quiet"):
  12.208 +            interactive = False
  12.209 +        elif o in ("-h", "--help"):
  12.210 +            usage()
  12.211 +            sys.exit()
  12.212 +        elif o in ("--output",):
  12.213 +            output = a
  12.214 +        elif o in ("--entry",):
  12.215 +            entry = a
  12.216 +            # specifying the entry to boot implies non-interactive
  12.217 +            interactive = False
  12.218 +
  12.219 +    if output is None or output == "-":
  12.220 +        fd = sys.stdout.fileno()
  12.221 +    else:
  12.222 +        fd = os.open(output, os.O_WRONLY)
  12.223 +
  12.224 +    cf = get_config(file)
  12.225 +    if interactive:
  12.226 +        curses.wrapper(run_main)
  12.227 +    else:
  12.228 +        sel = cf.default
  12.229 +
  12.230 +    # set the entry to boot as requested
  12.231 +    if entry is not None:
  12.232 +        idx = get_entry_idx(cf, entry)
  12.233 +        if idx is not None and idx > 0 and idx < len(cf.images):
  12.234 +            sel = idx
  12.235 +
  12.236 +    img = cf.images[sel]
  12.237 +    print "Going to boot %s" %(img.title)
  12.238 +    print "  kernel: %s" %(img.kernel[1],)
  12.239 +    if img.initrd:
  12.240 +        print "  initrd: %s" %(img.initrd[1],)
  12.241 +
  12.242 +    if is_disk_image(file):
  12.243 +        raise RuntimeError, "unable to handle full disk images yet"
  12.244 +
  12.245 +    # read the kernel and initrd onto the hostfs
  12.246 +    fs = None
  12.247 +    for fstype in grub.fsys.fstypes.values():
  12.248 +        if fstype.sniff_magic(file):
  12.249 +            fs = fstype.open_fs(file)
  12.250 +            break
  12.251 +
  12.252 +    if fs is None:
  12.253 +        raise RuntimeError, "Unable to open filesystem"
  12.254 +
  12.255 +    kernel = fs.open_file(img.kernel[1],).read()
  12.256 +    (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.")
  12.257 +    os.write(tfd, kernel)
  12.258 +    os.close(tfd)
  12.259 +    sxp = "linux (kernel %s)" %(fn,)
  12.260 +
  12.261 +    if img.initrd:
  12.262 +        initrd = fs.open_file(img.initrd[1],).read()
  12.263 +        (tfd, fn) = tempfile.mkstemp(prefix="initrd.")
  12.264 +        os.write(tfd, initrd)
  12.265 +        os.close(tfd)
  12.266 +        sxp += "(ramdisk %s)" %(fn,)
  12.267 +    else:
  12.268 +        initrd = None
  12.269 +    sxp += "(args '%s')" %(img.args,)
  12.270 +
  12.271 +    sys.stdout.flush()
  12.272 +    os.write(fd, sxp)
  12.273 +    
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/python/xen/util/blkif.py	Thu Apr 28 13:33:33 2005 +0000
    13.3 @@ -0,0 +1,84 @@
    13.4 +import os
    13.5 +import re
    13.6 +import string
    13.7 +
    13.8 +from xen.util.ip import _readline, _readlines
    13.9 +
   13.10 +def expand_dev_name(name):
   13.11 +    if not name:
   13.12 +        return name
   13.13 +    if re.match( '^/dev/', name ):
   13.14 +        return name
   13.15 +    else:
   13.16 +        return '/dev/' + name
   13.17 +
   13.18 +def blkdev_name_to_number(name):
   13.19 +    """Take the given textual block-device name (e.g., '/dev/sda1',
   13.20 +    'hda') and return the device number used by the OS. """
   13.21 +
   13.22 +    n = expand_dev_name(name)
   13.23 +
   13.24 +    try:
   13.25 +        return os.stat(n).st_rdev
   13.26 +    except Exception, ex:
   13.27 +        log.debug("exception looking up device number for %s: %s", name, ex)
   13.28 +        pass
   13.29 +
   13.30 +    if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
   13.31 +        return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
   13.32 +
   13.33 +    if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
   13.34 +        ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
   13.35 +        major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
   13.36 +        minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
   13.37 +        return major * 256 + minor
   13.38 +
   13.39 +    # see if this is a hex device number
   13.40 +    if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
   13.41 +        return string.atoi(name,16)
   13.42 +        
   13.43 +    return None
   13.44 +
   13.45 +def blkdev_segment(name):
   13.46 +    """Take the given block-device name (e.g. '/dev/sda1', 'hda')
   13.47 +    and return a dictionary { device, start_sector,
   13.48 +    nr_sectors, type }
   13.49 +        device:       Device number of the given partition
   13.50 +        start_sector: Index of first sector of the partition
   13.51 +        nr_sectors:   Number of sectors comprising this partition
   13.52 +        type:         'Disk' or identifying name for partition type
   13.53 +    """
   13.54 +    val = None
   13.55 +    n = blkdev_name_to_number(name)
   13.56 +    if n:
   13.57 +        val = { 'device'       : n,
   13.58 +                'start_sector' : long(0),
   13.59 +                'nr_sectors'   : long(1L<<63),
   13.60 +                'type'         : 'Disk' }
   13.61 +    return val
   13.62 +
   13.63 +def blkdev_uname_to_file(uname):
   13.64 +    """Take a blkdev uname and return the corresponding filename."""
   13.65 +    fn = None
   13.66 +    if uname.find(":") != -1:
   13.67 +        (typ, fn) = uname.split(":")
   13.68 +        if typ == "phy" and not fn.startswith("/dev/"):
   13.69 +            fn = "/dev/%s" %(fn,)
   13.70 +    return fn
   13.71 +
   13.72 +def mount_mode(name):
   13.73 +    mode = None
   13.74 +    name = expand_dev_name(name)
   13.75 +    lines = _readlines(os.popen('mount 2>/dev/null'))
   13.76 +    exp = re.compile('^' + name + ' .*[\(,]r(?P<mode>[ow])[,\)]')
   13.77 +    for line in lines:
   13.78 +        pm = exp.match(line)
   13.79 +        if not pm: continue
   13.80 +        mode = pm.group('mode')
   13.81 +        break
   13.82 +    if mode == 'w':
   13.83 +        return mode
   13.84 +    if mode == 'o':
   13.85 +        mode = 'r'
   13.86 +    return mode
   13.87 +    
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/python/xen/xend/XendBootloader.py	Thu Apr 28 13:33:33 2005 +0000
    14.3 @@ -0,0 +1,94 @@
    14.4 +#
    14.5 +# XendBootloader.py - Framework to run a boot loader for picking the kernel
    14.6 +#
    14.7 +# Copyright 2005 Red Hat, Inc.
    14.8 +# Jeremy Katz <katzj@xxxxxxxxxx>
    14.9 +#
   14.10 +# This software may be freely redistributed under the terms of the GNU
   14.11 +# general public license.
   14.12 +#
   14.13 +# You should have received a copy of the GNU General Public License
   14.14 +# along with this program; if not, write to the Free Software
   14.15 +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   14.16 +#
   14.17 +
   14.18 +import os, sys, select
   14.19 +import sxp
   14.20 +
   14.21 +from XendLogging import log
   14.22 +from XendError import VmError
   14.23 +
   14.24 +BL_FIFO = "/var/lib/xen/xenbl"
   14.25 +
   14.26 +def bootloader(blexec, disk, quiet = 0, vcpus = None, entry = None):
   14.27 +    """Run the boot loader executable on the given disk and return a
   14.28 +    config image.
   14.29 +    @param blexec  Binary to use as the boot loader
   14.30 +    @param disk Disk to run the boot loader on.
   14.31 +    @param quiet Run in non-interactive mode, just booting the default.
   14.32 +    @param vcpus Number of vcpus for the domain.
   14.33 +    @param entry Default entry to boot."""
   14.34 +    
   14.35 +    if not os.access(blexec, os.X_OK):
   14.36 +        msg = "Bootloader isn't executable"
   14.37 +        log.error(msg)
   14.38 +        raise VmError(msg)
   14.39 +    if not os.access(disk, os.R_OK):
   14.40 +        msg = "Disk isn't accessible"
   14.41 +        log.error(msg)
   14.42 +        raise VmError(msg)
   14.43 +
   14.44 +    os.mkfifo(BL_FIFO, 0600)
   14.45 +
   14.46 +    child = os.fork()
   14.47 +    if (not child):
   14.48 +        args = [ blexec ]
   14.49 +        if quiet:
   14.50 +            args.append("-q")
   14.51 +        args.append("--output=%s" %(BL_FIFO,))
   14.52 +        if entry is not None:
   14.53 +            args.append("--entry=%s" %(entry,))
   14.54 +        args.append(disk)
   14.55 +
   14.56 +        try:
   14.57 +            os.execvp(args[0], args)
   14.58 +        except OSError, e:
   14.59 +            print e
   14.60 +            pass
   14.61 +        os._exit(1)
   14.62 +
   14.63 +    while 1:
   14.64 +        try:
   14.65 +            r = os.open(BL_FIFO, os.O_RDONLY)
   14.66 +        except OSError, e:
   14.67 +            if e.errno == 4:
   14.68 +                continue
   14.69 +        break
   14.70 +    ret = ""
   14.71 +    while 1:
   14.72 +        select.select([r], [], [])
   14.73 +        s = os.read(r, 1024)
   14.74 +        ret = ret + s
   14.75 +        if len(s) == 0:
   14.76 +            break
   14.77 +        
   14.78 +    (pid, status) = os.waitpid(child, 0)
   14.79 +    os.close(r)
   14.80 +    os.unlink(BL_FIFO)
   14.81 +
   14.82 +    if len(ret) == 0:
   14.83 +        msg = "Boot loader didn't return any data!"
   14.84 +        log.error(msg)
   14.85 +        raise VmError, msg
   14.86 +
   14.87 +    pin = sxp.Parser()
   14.88 +    pin.input(ret)
   14.89 +    pin.input_eof()
   14.90 +
   14.91 +    config_image = pin.val
   14.92 +    if vcpus and sxp.child_value(config_image, "vcpus") is None:
   14.93 +        config_image.append(['vcpus', vcpus])
   14.94 +
   14.95 +    config = ['image', config_image]
   14.96 +    return config
   14.97 +
    15.1 --- a/tools/python/xen/xend/XendDB.py	Thu Apr 28 10:46:53 2005 +0000
    15.2 +++ b/tools/python/xen/xend/XendDB.py	Thu Apr 28 13:33:33 2005 +0000
    15.3 @@ -20,6 +20,12 @@ class XendDB:
    15.4              self.dbpath = os.path.join(self.dbpath, path)
    15.5          pass
    15.6  
    15.7 +    def listdir(self, dpath):
    15.8 +        try:
    15.9 +            return dircache.listdir(dpath)
   15.10 +        except:
   15.11 +            return []
   15.12 +
   15.13      def filepath(self, path):
   15.14          return os.path.join(self.dbpath, path)
   15.15          
   15.16 @@ -52,21 +58,37 @@ class XendDB:
   15.17          return self.savefile(fpath, sxpr)
   15.18      
   15.19      def savefile(self, fpath, sxpr):
   15.20 +        backup = False
   15.21          fdir = os.path.dirname(fpath)
   15.22          if not os.path.isdir(fdir):
   15.23              os.makedirs(fdir)
   15.24 +        if os.path.exists(fpath):
   15.25 +            backup = True
   15.26 +            real_fpath = fpath
   15.27 +            fpath += ".new."
   15.28 +            
   15.29          fout = file(fpath, "wb+")
   15.30          try:
   15.31 -            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   15.32 -            fout.write("# %s %s\n" % (fpath, t))
   15.33 -            sxp.show(sxpr, out=fout)
   15.34 -        finally:
   15.35 -            fout.close()
   15.36 +            try:
   15.37 +                t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   15.38 +                fout.write("# %s %s\n" % (fpath, t))
   15.39 +                sxp.show(sxpr, out=fout)
   15.40 +            finally:
   15.41 +                fout.close()
   15.42 +        except:
   15.43 +            if backup:
   15.44 +                try:
   15.45 +                    os.unlink(fpath)
   15.46 +                except:
   15.47 +                    pass
   15.48 +                raise
   15.49 +        if backup:
   15.50 +            os.rename(fpath, real_fpath)
   15.51  
   15.52      def fetchall(self, path):
   15.53          dpath = self.filepath(path)
   15.54          d = {}
   15.55 -        for k in dircache.listdir(dpath):
   15.56 +        for k in self.listdir(dpath):
   15.57              try:
   15.58                  v = self.fetchfile(os.path.join(dpath, k))
   15.59                  d[k] = v
   15.60 @@ -84,8 +106,7 @@ class XendDB:
   15.61  
   15.62      def ls(self, path):
   15.63          dpath = self.filepath(path)
   15.64 -        return dircache.listdir(dpath)
   15.65 -            
   15.66 +        return self.listdir(dpath)
   15.67          
   15.68  
   15.69          
    16.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 28 10:46:53 2005 +0000
    16.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Apr 28 13:33:33 2005 +0000
    16.3 @@ -16,11 +16,13 @@ import xen.lowlevel.xc; xc = xen.lowleve
    16.4  import xen.util.ip
    16.5  from xen.util.ip import _readline, _readlines
    16.6  from xen.xend.server import channel, controller
    16.7 +from xen.util.blkif import blkdev_uname_to_file
    16.8  
    16.9  from server.channel import channelFactory
   16.10  import server.SrvDaemon; xend = server.SrvDaemon.instance()
   16.11  from server import messages
   16.12  
   16.13 +from xen.xend.XendBootloader import bootloader
   16.14  import sxp
   16.15  from XendLogging import log
   16.16  from XendError import VmError
   16.17 @@ -294,6 +296,7 @@ class XendDomainInfo:
   16.18          self.image_handler = None
   16.19          self.is_vmx = False
   16.20          self.vcpus = 1
   16.21 +        self.bootloader = None
   16.22  
   16.23      def setdom(self, dom):
   16.24          """Set the domain id.
   16.25 @@ -496,6 +499,7 @@ class XendDomainInfo:
   16.26              self.find_image_handler()
   16.27              self.init_domain()
   16.28              self.register_domain()
   16.29 +            self.configure_bootloader()
   16.30  
   16.31              # Create domain devices.
   16.32              self.configure_backends()
   16.33 @@ -674,6 +678,13 @@ class XendDomainInfo:
   16.34          memory = memory * 1024 + self.pgtable_size(memory)
   16.35          dom = xc.domain_create(dom= dom, mem_kb= memory,
   16.36                                 cpu= cpu, cpu_weight= cpu_weight)
   16.37 +        if self.bootloader:
   16.38 +            try:
   16.39 +                if kernel: os.unlink(kernel)
   16.40 +                if ramdisk: os.unlink(ramdisk)
   16.41 +            except OSError, e:
   16.42 +                log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
   16.43 +
   16.44          if dom <= 0:
   16.45              raise VmError('Creating domain failed: name=%s memory=%d'
   16.46                            % (self.name, memory))
   16.47 @@ -854,6 +865,13 @@ class XendDomainInfo:
   16.48              self.config.remove(['device', dev_config])
   16.49          self.deleteDevice(type, dev.getId())
   16.50  
   16.51 +    def configure_bootloader(self):
   16.52 +        """Configure boot loader.
   16.53 +        """
   16.54 +        bl = sxp.child_value(self.config, "bootloader")
   16.55 +        if bl is not None:
   16.56 +            self.bootloader = bl
   16.57 +
   16.58      def configure_console(self):
   16.59          """Configure the vm console port.
   16.60          """
   16.61 @@ -931,10 +949,30 @@ class XendDomainInfo:
   16.62              self.state = STATE_VM_OK
   16.63              self.restart_check()
   16.64              self.restart_state = STATE_RESTART_BOOTING
   16.65 +            if self.bootloader:
   16.66 +                self.config = self.bootloader_config()
   16.67              self.construct(self.config)
   16.68          finally:
   16.69              self.restart_state = None
   16.70  
   16.71 +    def bootloader_config(self):
   16.72 +        # if we're restarting with a bootloader, we need to run it
   16.73 +        # FIXME: this assumes the disk is the first device and
   16.74 +        # that we're booting from the first disk
   16.75 +        blcfg = None
   16.76 +        # FIXME: this assumes that we want to use the first disk
   16.77 +        dev = sxp.child_value(self.config, "device")
   16.78 +        if dev:
   16.79 +            disk = sxp.child_value(dev, "uname")
   16.80 +            fn = blkdev_uname_to_file(disk)
   16.81 +            blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
   16.82 +        if blcfg is None:
   16.83 +            msg = "Had a bootloader specified, but can't find disk"
   16.84 +            log.error(msg)
   16.85 +            raise VmError(msg)
   16.86 +        config = sxp.merge(['vm', blconfig ], self.config)
   16.87 +        return config
   16.88 +
   16.89      def configure_backends(self):
   16.90          """Set configuration flags if the vm is a backend for netif or blkif.
   16.91          Configure the backends to use for vbd and vif if specified.
   16.92 @@ -1071,6 +1109,7 @@ def vm_image_linux(vm, image):
   16.93      if args:
   16.94          cmdline += " " + args
   16.95      ramdisk = sxp.child_value(image, "ramdisk", '')
   16.96 +    log.debug("creating linux domain with cmdline: %s" %(cmdline,))
   16.97      vm.create_domain("linux", kernel, ramdisk, cmdline)
   16.98      return vm
   16.99  
  16.100 @@ -1169,6 +1208,7 @@ add_config_handler('image',      vm_fiel
  16.101  add_config_handler('device',     vm_field_ignore)
  16.102  add_config_handler('backend',    vm_field_ignore)
  16.103  add_config_handler('vcpus',      vm_field_ignore)
  16.104 +add_config_handler('bootloader', vm_field_ignore)
  16.105  
  16.106  # Register other config handlers.
  16.107  add_config_handler('maxmem',     vm_field_maxmem)
    17.1 --- a/tools/python/xen/xend/server/blkif.py	Thu Apr 28 10:46:53 2005 +0000
    17.2 +++ b/tools/python/xen/xend/server/blkif.py	Thu Apr 28 13:33:33 2005 +0000
    17.3 @@ -1,11 +1,9 @@
    17.4  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    17.5  """Support for virtual block devices.
    17.6  """
    17.7 -
    17.8 -import os
    17.9 -import re
   17.10  import string
   17.11  
   17.12 +from xen.util import blkif
   17.13  from xen.xend.XendError import XendError, VmError
   17.14  from xen.xend import XendRoot
   17.15  from xen.xend.XendLogging import log
   17.16 @@ -16,77 +14,6 @@ import channel
   17.17  from controller import CtrlMsgRcvr, Dev, DevController
   17.18  from messages import *
   17.19  
   17.20 -from xen.util.ip import _readline, _readlines
   17.21 -
   17.22 -def expand_dev_name(name):
   17.23 -    if not name:
   17.24 -        return name
   17.25 -    if re.match( '^/dev/', name ):
   17.26 -        return name
   17.27 -    else:
   17.28 -        return '/dev/' + name
   17.29 -
   17.30 -def blkdev_name_to_number(name):
   17.31 -    """Take the given textual block-device name (e.g., '/dev/sda1',
   17.32 -    'hda') and return the device number used by the OS. """
   17.33 -
   17.34 -    n = expand_dev_name(name)
   17.35 -
   17.36 -    try:
   17.37 -        return os.stat(n).st_rdev
   17.38 -    except Exception, ex:
   17.39 -        log.debug("exception looking up device number for %s: %s", name, ex)
   17.40 -        pass
   17.41 -
   17.42 -    if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
   17.43 -        return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
   17.44 -
   17.45 -    if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
   17.46 -        ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
   17.47 -        major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
   17.48 -        minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
   17.49 -        return major * 256 + minor
   17.50 -
   17.51 -    # see if this is a hex device number
   17.52 -    if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
   17.53 -        return string.atoi(name,16)
   17.54 -        
   17.55 -    return None
   17.56 -
   17.57 -def blkdev_segment(name):
   17.58 -    """Take the given block-device name (e.g. '/dev/sda1', 'hda')
   17.59 -    and return a dictionary { device, start_sector,
   17.60 -    nr_sectors, type }
   17.61 -        device:       Device number of the given partition
   17.62 -        start_sector: Index of first sector of the partition
   17.63 -        nr_sectors:   Number of sectors comprising this partition
   17.64 -        type:         'Disk' or identifying name for partition type
   17.65 -    """
   17.66 -    val = None
   17.67 -    n = blkdev_name_to_number(name)
   17.68 -    if n:
   17.69 -        val = { 'device'       : n,
   17.70 -                'start_sector' : long(0),
   17.71 -                'nr_sectors'   : long(1L<<63),
   17.72 -                'type'         : 'Disk' }
   17.73 -    return val
   17.74 -
   17.75 -def mount_mode(name):
   17.76 -    mode = None
   17.77 -    name = expand_dev_name(name)
   17.78 -    lines = _readlines(os.popen('mount 2>/dev/null'))
   17.79 -    exp = re.compile('^' + name + ' .*[\(,]r(?P<mode>[ow])[,\)]')
   17.80 -    for line in lines:
   17.81 -        pm = exp.match(line)
   17.82 -        if not pm: continue
   17.83 -        mode = pm.group('mode')
   17.84 -        break
   17.85 -    if mode == 'w':
   17.86 -        return mode
   17.87 -    if mode == 'o':
   17.88 -        mode = 'r'
   17.89 -    return mode
   17.90 -    
   17.91  class BlkifBackend:
   17.92      """ Handler for the 'back-end' channel to a block device driver domain
   17.93      on behalf of a front-end domain.
   17.94 @@ -271,7 +198,7 @@ class BlkDev(Dev):
   17.95              raise VmError('vbd: Missing dev')
   17.96          self.mode = sxp.child_value(config, 'mode', 'r')
   17.97          
   17.98 -        self.vdev = blkdev_name_to_number(self.dev)
   17.99 +        self.vdev = blkif.blkdev_name_to_number(self.dev)
  17.100          if not self.vdev:
  17.101              raise VmError('vbd: Device not found: %s' % self.dev)
  17.102          
  17.103 @@ -324,7 +251,7 @@ class BlkDev(Dev):
  17.104                  raise VmError("vbd: Segment %s is in read-only use" %
  17.105                                self.uname)
  17.106              
  17.107 -        segment = blkdev_segment(node)
  17.108 +        segment = blkif.blkdev_segment(node)
  17.109          if not segment:
  17.110              raise VmError("vbd: Segment not found: uname=%s" % self.uname)
  17.111          self.node = node
  17.112 @@ -333,14 +260,14 @@ class BlkDev(Dev):
  17.113          self.nr_sectors = segment['nr_sectors']
  17.114  
  17.115      def check_mounted(self, name):
  17.116 -        mode = mount_mode(name)
  17.117 +        mode = blkif.mount_mode(name)
  17.118          xd = XendRoot.get_component('xen.xend.XendDomain')
  17.119          for vm in xd.domains():
  17.120              ctrl = vm.getDeviceController(self.getType(), error=False)
  17.121              if (not ctrl): continue
  17.122              for dev in ctrl.getDevices():
  17.123                  if dev is self: continue
  17.124 -                if dev.type == 'phy' and name == expand_dev_name(dev.params):
  17.125 +                if dev.type == 'phy' and name == blkif.expand_dev_name(dev.params):
  17.126                      mode = dev.mode
  17.127                      if 'w' in mode:
  17.128                          return 'w'
    18.1 --- a/tools/python/xen/xm/create.py	Thu Apr 28 10:46:53 2005 +0000
    18.2 +++ b/tools/python/xen/xm/create.py	Thu Apr 28 13:33:33 2005 +0000
    18.3 @@ -10,6 +10,8 @@ import socket
    18.4  from xen.xend import sxp
    18.5  from xen.xend import PrettyPrint
    18.6  from xen.xend.XendClient import server, XendError
    18.7 +from xen.xend.XendBootloader import bootloader
    18.8 +from xen.util import blkif
    18.9  
   18.10  from xen.util import console_client
   18.11  
   18.12 @@ -94,6 +96,14 @@ gopts.var('name', val='NAME',
   18.13            fn=set_value, default=None,
   18.14            use="Domain name. Must be unique.")
   18.15  
   18.16 +gopts.var('bootloader', val='FILE',
   18.17 +          fn=set_value, default=None,
   18.18 +          use="Path to bootloader.")
   18.19 +
   18.20 +gopts.var('bootentry', val='NAME',
   18.21 +          fn=set_value, default=None,
   18.22 +          use="Entry to boot via boot loader")
   18.23 +
   18.24  gopts.var('kernel', val='FILE',
   18.25            fn=set_value, default=None,
   18.26            use="Path to kernel image.")
   18.27 @@ -252,7 +262,7 @@ def strip(pre, s):
   18.28      else:
   18.29          return s
   18.30  
   18.31 -def configure_image(config, vals):
   18.32 +def configure_image(opts, config, vals):
   18.33      """Create the image config.
   18.34      """
   18.35      config_image = [ vals.builder ]
   18.36 @@ -272,7 +282,7 @@ def configure_image(config, vals):
   18.37      config.append(['image', config_image ])
   18.38  
   18.39      
   18.40 -def configure_disks(config_devs, vals):
   18.41 +def configure_disks(opts, config_devs, vals):
   18.42      """Create the config for disks (virtual block devices).
   18.43      """
   18.44      for (uname, dev, mode, backend) in vals.disk:
   18.45 @@ -284,14 +294,14 @@ def configure_disks(config_devs, vals):
   18.46              config_vbd.append(['backend', backend])
   18.47          config_devs.append(['device', config_vbd])
   18.48  
   18.49 -def configure_pci(config_devs, vals):
   18.50 +def configure_pci(opts, config_devs, vals):
   18.51      """Create the config for pci devices.
   18.52      """
   18.53      for (bus, dev, func) in vals.pci:
   18.54          config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
   18.55          config_devs.append(['device', config_pci])
   18.56  
   18.57 -def configure_usb(config_devs, vals):
   18.58 +def configure_usb(opts, config_devs, vals):
   18.59      for path in vals.usb:
   18.60          config_usb = ['usb', ['path', path]]
   18.61          config_devs.append(['device', config_usb])
   18.62 @@ -315,7 +325,7 @@ def randomMAC():
   18.63              random.randint(0x00, 0xff) ]
   18.64      return ':'.join(map(lambda x: "%02x" % x, mac))
   18.65  
   18.66 -def configure_vifs(config_devs, vals):
   18.67 +def configure_vifs(opts, config_devs, vals):
   18.68      """Create the config for virtual network interfaces.
   18.69      """
   18.70      vifs = vals.vif
   18.71 @@ -357,7 +367,7 @@ def configure_vifs(config_devs, vals):
   18.72              config_vif.append(['ip', ip])
   18.73          config_devs.append(['device', config_vif])
   18.74  
   18.75 -def configure_vfr(config, vals):
   18.76 +def configure_vfr(opts, config, vals):
   18.77       if not vals.ipaddr: return
   18.78       config_vfr = ['vfr']
   18.79       idx = 0 # No way of saying which IP is for which vif?
   18.80 @@ -365,7 +375,7 @@ def configure_vfr(config, vals):
   18.81           config_vfr.append(['vif', ['id', idx], ['ip', ip]])
   18.82       config.append(config_vfr)
   18.83  
   18.84 -def configure_vmx(config_devs, vals):
   18.85 +def configure_vmx(opts, config_devs, vals):
   18.86      """Create the config for VMX devices.
   18.87      """
   18.88      memmap = vals.memmap
   18.89 @@ -375,7 +385,21 @@ def configure_vmx(config_devs, vals):
   18.90      config_devs.append(['device_model', device_model])
   18.91      config_devs.append(['device_config', device_config])
   18.92  
   18.93 -def make_config(vals):
   18.94 +def run_bootloader(opts, config, vals):
   18.95 +    if not os.access(vals.bootloader, os.X_OK):
   18.96 +        opts.err("Bootloader isn't executable")
   18.97 +    if len(vals.disk) < 1:
   18.98 +        opts.err("No disks configured and boot loader requested")
   18.99 +    (uname, dev, mode, backend) = vals.disk[0]
  18.100 +    file = blkif.blkdev_uname_to_file(uname)
  18.101 +
  18.102 +    blcfg = bootloader(vals.bootloader, file, not vals.console_autoconnect,
  18.103 +                       vals.vcpus, vals.blentry)
  18.104 +
  18.105 +    config.append(['bootloader', vals.bootloader])
  18.106 +    config.append(blcfg)
  18.107 +
  18.108 +def make_config(opts, vals):
  18.109      """Create the domain configuration.
  18.110      """
  18.111      
  18.112 @@ -396,15 +420,19 @@ def make_config(vals):
  18.113          config.append(['restart', vals.restart])
  18.114      if vals.console:
  18.115          config.append(['console', vals.console])
  18.116 -    
  18.117 -    configure_image(config, vals)
  18.118 +
  18.119 +    if vals.bootloader:
  18.120 +        run_bootloader(opts, config, vals)
  18.121 +    else:
  18.122 +        configure_image(opts, config, vals)
  18.123      config_devs = []
  18.124 -    configure_disks(config_devs, vals)
  18.125 -    configure_pci(config_devs, vals)
  18.126 -    configure_vifs(config_devs, vals)
  18.127 -    configure_usb(config_devs, vals)
  18.128 -    configure_vmx(config_devs, vals)
  18.129 +    configure_disks(opts, config_devs, vals)
  18.130 +    configure_pci(opts, config_devs, vals)
  18.131 +    configure_vifs(opts, config_devs, vals)
  18.132 +    configure_usb(opts, config_devs, vals)
  18.133 +    configure_vmx(opts, config_devs, vals)
  18.134      config += config_devs
  18.135 +
  18.136      return config
  18.137  
  18.138  def preprocess_disk(opts, vals):
  18.139 @@ -587,7 +615,8 @@ def main(argv):
  18.140          preprocess(opts, opts.vals)
  18.141          if not opts.getopt('name') and opts.getopt('defconfig'):
  18.142              opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
  18.143 -        config = make_config(opts.vals)
  18.144 +        config = make_config(opts, opts.vals)
  18.145 +
  18.146      if opts.vals.dryrun:
  18.147          PrettyPrint.prettyprint(config)
  18.148      else:
    19.1 --- a/tools/xfrd/xfrd.c	Thu Apr 28 10:46:53 2005 +0000
    19.2 +++ b/tools/xfrd/xfrd.c	Thu Apr 28 13:33:33 2005 +0000
    19.3 @@ -49,7 +49,7 @@
    19.4  #include "select.h"
    19.5  
    19.6  #define MODULE_NAME "XFRD"
    19.7 -
    19.8 +#define DEBUG 1
    19.9  #include "debug.h"
   19.10  
   19.11  /*
   19.12 @@ -1226,7 +1226,9 @@ int main(int argc, char *argv[]){
   19.13      int err = 0;
   19.14      int key = 0;
   19.15      int long_index = 0;
   19.16 +#ifndef DEBUG
   19.17      static const char * LOGFILE = "/var/log/xfrd.log";
   19.18 +#endif
   19.19  
   19.20  #ifndef DEBUG
   19.21      freopen(LOGFILE, "w+", stdout);