aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>2005-04-28 12:27:47 +0000
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>2005-04-28 12:27:47 +0000
commit51a9f171a5de469910dcf8a4fc1f34e042e17fac (patch)
tree6f4594dc095baf69fef1a058aa669acd2bd28c2d
parentb4ac7763beeabbc040395b860560d92014ce5005 (diff)
downloadxen-51a9f171a5de469910dcf8a4fc1f34e042e17fac.tar.gz
xen-51a9f171a5de469910dcf8a4fc1f34e042e17fac.tar.bz2
xen-51a9f171a5de469910dcf8a4fc1f34e042e17fac.zip
bitkeeper revision 1.1327.2.13 (4270d6c35WpxFmhdkREjmSvk82s-Bg)
Merge Jeremy's pygrub bootloader patch. Signed-off-by: Jeremy Katz <katzj@redhat.com> Signed-off-by: Mike Wray <mike.wray@hp.com>
-rw-r--r--.rootkeys10
-rw-r--r--tools/Makefile1
-rw-r--r--tools/pygrub/Makefile18
-rw-r--r--tools/pygrub/setup.py25
-rw-r--r--tools/pygrub/src/GrubConf.py229
-rw-r--r--tools/pygrub/src/__init__.py0
-rw-r--r--tools/pygrub/src/fsys/__init__.py61
-rw-r--r--tools/pygrub/src/fsys/ext2/__init__.py38
-rw-r--r--tools/pygrub/src/fsys/ext2/ext2module.c332
-rw-r--r--tools/pygrub/src/fsys/ext2/test.py15
-rw-r--r--tools/pygrub/src/pygrub270
-rw-r--r--tools/python/xen/xend/XendBootloader.py94
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py40
-rwxr-xr-xtools/python/xen/xend/server/blkif.py9
-rw-r--r--tools/python/xen/xm/create.py61
-rw-r--r--tools/xfrd/xfrd.c4
16 files changed, 1190 insertions, 17 deletions
diff --git a/.rootkeys b/.rootkeys
index 2037a99828..e53f3b2576 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -799,6 +799,15 @@
4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
+4270cc81g3nSNYCZ1ryCMDEbLtMtbQ tools/pygrub/Makefile
+4270cc81EIl7NyaS3Av6IPRk2c2a6Q tools/pygrub/setup.py
+4270cc81t7eNCDp4Bhbh58p1CNxaCQ tools/pygrub/src/GrubConf.py
+4270d6c2fWF4r5-zF1pSuAFwUZS0aA tools/pygrub/src/__init__.py
+4270cc81CzKMiujDPWcaYhu709vGXw tools/pygrub/src/fsys/__init__.py
+4270cc81RTIiq9si0dI4YRTRE4KRMw tools/pygrub/src/fsys/ext2/__init__.py
+4270cc81YCYa4pexivBD2NdLE2F_Pg tools/pygrub/src/fsys/ext2/ext2module.c
+4270cc81o4BL5e8Cs87aSi8EXA5NtQ tools/pygrub/src/fsys/ext2/test.py
+4270cc81TS6L_tEO6wSp5wcURcpldQ tools/pygrub/src/pygrub
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
40ffc44dOwe1CcYXGCkYHdG_NxcccA tools/python/logging/logging-0.4.9.2/PKG-INFO
40ffc44dpqpgqgrnLfR70PsiBc3liA tools/python/logging/logging-0.4.9.2/README.txt
@@ -896,6 +905,7 @@
40c9c468Um_qc66OQeLEceIz1pgD5g tools/python/xen/xend/EventServer.py
40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
+4270cc81xbweGYhsM4326N3dX1bGHQ tools/python/xen/xend/XendBootloader.py
40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
diff --git a/tools/Makefile b/tools/Makefile
index da2fe19a72..9f4a601d02 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -11,6 +11,7 @@ SUBDIRS += python
SUBDIRS += xfrd
SUBDIRS += xcs
SUBDIRS += ioemu
+SUBDIRS += pygrub
.PHONY: all install clean check check_clean
diff --git a/tools/pygrub/Makefile b/tools/pygrub/Makefile
new file mode 100644
index 0000000000..a676cdf0e9
--- /dev/null
+++ b/tools/pygrub/Makefile
@@ -0,0 +1,18 @@
+
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+all: build
+build:
+ CFLAGS="$(CFLAGS)" python setup.py build
+
+ifndef XEN_PYTHON_NATIVE_INSTALL
+install: all
+ CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr"
+else
+install: all
+ CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)"
+endif
+
+clean:
+ rm -rf build *.pyc *.pyo *.o *.a *~
diff --git a/tools/pygrub/setup.py b/tools/pygrub/setup.py
new file mode 100644
index 0000000000..193c160a3b
--- /dev/null
+++ b/tools/pygrub/setup.py
@@ -0,0 +1,25 @@
+from distutils.core import setup, Extension
+import os
+
+extra_compile_args = [ "-fno-strict-aliasing", "-Wall", "-Werror" ]
+
+# in a perfect world, we'd figure out the fsys modules dynamically
+ext2 = Extension("grub.fsys.ext2._pyext2",
+ extra_compile_args = extra_compile_args,
+ libraries = ["ext2fs"],
+ sources = ["src/fsys/ext2/ext2module.c"])
+
+setup(name='pygrub',
+ version='0.1',
+ description='Boot loader that looks a lot like grub for Xen',
+ author='Jeremy Katz',
+ author_email='katzj@redhat.com',
+ license='GPL',
+ package_dir={'grub': 'src'},
+ scripts = ["src/pygrub"],
+ packages=['grub',
+ 'grub.fsys',
+ 'grub.fsys.ext2'],
+ ext_modules = [ext2]
+ )
+
diff --git a/tools/pygrub/src/GrubConf.py b/tools/pygrub/src/GrubConf.py
new file mode 100644
index 0000000000..3603b72243
--- /dev/null
+++ b/tools/pygrub/src/GrubConf.py
@@ -0,0 +1,229 @@
+#
+# GrubConf.py - Simple grub.conf parsing
+#
+# Copyright 2005 Red Hat, Inc.
+# Jeremy Katz <katzj@redhat.com>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os, sys
+import logging
+
+def grub_split(s, maxsplit = -1):
+ """Split a grub option screen separated with either '=' or whitespace."""
+ eq = s.find('=')
+ if eq == -1:
+ return s.split(None, maxsplit)
+
+ # see which of a space or tab is first
+ sp = s.find(' ')
+ tab = s.find('\t')
+ if (tab != -1 and tab < sp) or (tab != -1 and sp == -1):
+ sp = tab
+
+ if eq != -1 and eq < sp or (eq != -1 and sp == -1):
+ return s.split('=', maxsplit)
+ else:
+ return s.split(None, maxsplit)
+
+def get_path(s):
+ """Returns a tuple of (GrubDiskPart, path) corresponding to string."""
+ if not s.startswith('('):
+ return (None, s)
+ idx = s.find(')')
+ if idx == -1:
+ raise ValueError, "Unable to find matching ')'"
+ d = s[:idx]
+ return (GrubDiskPart(d), s[idx + 1:])
+
+class GrubDiskPart(object):
+ def __init__(self, str):
+ if str.find(',') != -1:
+ (self.disk, self.part) = str.split(",", 2)
+ else:
+ self.disk = str
+ self.part = None
+
+ def __repr__(self):
+ if self.part is not None:
+ return "d%dp%d" %(self.disk, self.part)
+ else:
+ return "d%d" %(self,disk,)
+
+ def get_disk(self):
+ return self._disk
+ def set_disk(self, val):
+ val = val.replace("(", "").replace(")", "")
+ self._disk = int(val[2:])
+ disk = property(get_disk, set_disk)
+
+ def get_part(self):
+ return self._part
+ def set_part(self, val):
+ if val is None:
+ self._part = val
+ return
+ val = val.replace("(", "").replace(")", "")
+ self._part = int(val)
+ part = property(get_part, set_part)
+
+class GrubImage(object):
+ def __init__(self, lines):
+ self._root = self._initrd = self._kernel = self._args = None
+ for l in lines:
+ (com, arg) = grub_split(l, 1)
+
+ if self.commands.has_key(com):
+ if self.commands[com] is not None:
+ exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ else:
+ logging.info("Ignored image directive %s" %(com,))
+ else:
+ logging.warning("Unknown image directive %s" %(com,))
+
+ def __repr__(self):
+ return ("title: %s\n"
+ " root: %s\n"
+ " kernel: %s\n"
+ " args: %s\n"
+ " initrd: %s" %(self.title, self.root, self.kernel,
+ self.args, self.initrd))
+
+ def set_root(self, val):
+ self._root = GrubDiskPart(val)
+ def get_root(self):
+ return self._root
+ root = property(get_root, set_root)
+
+ def set_kernel(self, val):
+ if val.find(" ") == -1:
+ self._kernel = get_path(val)
+ self._args = None
+ return
+ (kernel, args) = val.split(None, 1)
+ self._kernel = get_path(kernel)
+ self._args = args
+ def get_kernel(self):
+ return self._kernel
+ def get_args(self):
+ return self._args
+ kernel = property(get_kernel, set_kernel)
+ args = property(get_args)
+
+ def set_initrd(self, val):
+ self._initrd = get_path(val)
+ def get_initrd(self):
+ return self._initrd
+ initrd = property(get_initrd, set_initrd)
+
+ # set up command handlers
+ commands = { "title": "self.title",
+ "root": "self.root",
+ "rootnoverify": "self.root",
+ "kernel": "self.kernel",
+ "initrd": "self.initrd",
+ "chainloader": None,
+ "module": None}
+
+
+class GrubConfigFile(object):
+ def __init__(self, fn = None):
+ self.filename = fn
+ self.images = []
+ self.timeout = -1
+
+ if fn is not None:
+ self.parse()
+
+ def parse(self, buf = None):
+ if buf is None:
+ if self.filename is None:
+ raise ValueError, "No config file defined to parse!"
+
+ f = open(self.filename, 'r')
+ lines = f.readlines()
+ f.close()
+ else:
+ lines = buf.split("\n")
+
+ img = []
+ for l in lines:
+ l = l.strip()
+ # skip blank lines
+ if len(l) == 0:
+ continue
+ # skip comments
+ if l.startswith('#'):
+ continue
+ # new image
+ if l.startswith("title"):
+ if len(img) > 0:
+ self.images.append(GrubImage(img))
+ img = [l]
+ continue
+
+ if len(img) > 0:
+ img.append(l)
+ continue
+
+ try:
+ (com, arg) = grub_split(l, 1)
+ except ValueError:
+ com = l
+ arg = ""
+
+ if self.commands.has_key(com):
+ if self.commands[com] is not None:
+ exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
+ else:
+ logging.info("Ignored directive %s" %(com,))
+ else:
+ logging.warning("Unknown directive %s" %(com,))
+
+ if len(img) > 0:
+ self.images.append(GrubImage(img))
+
+ def _get_default(self):
+ return self._default
+ def _set_default(self, val):
+ if val == "saved":
+ self._default = -1
+ else:
+ self._default = int(val)
+
+ if self._default < 0:
+ raise ValueError, "default must be positive number"
+ default = property(_get_default, _set_default)
+
+ def set_splash(self, val):
+ self._splash = get_path(val)
+ def get_splash(self):
+ return self._splash
+ splash = property(get_splash, set_splash)
+
+ # set up command handlers
+ commands = { "default": "self.default",
+ "timeout": "self.timeout",
+ "fallback": "self.fallback",
+ "hiddenmenu": "self.hiddenmenu",
+ "splashimage": "self.splash",
+ "password": "self.password" }
+ for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
+ "pager", "partnew", "parttype", "rarp", "serial",
+ "setkey", "terminal", "terminfo", "tftpserver", "unhide"):
+ commands[c] = None
+ del c
+
+
+if __name__ == "__main__":
+ if sys.argv < 2:
+ raise RuntimeError, "Need a grub.conf to read"
+ g = GrubConfigFile(sys.argv[1])
+ for i in g.images:
+ print i #, i.title, i.root, i.kernel, i.args, i.initrd
diff --git a/tools/pygrub/src/__init__.py b/tools/pygrub/src/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tools/pygrub/src/__init__.py
diff --git a/tools/pygrub/src/fsys/__init__.py b/tools/pygrub/src/fsys/__init__.py
new file mode 100644
index 0000000000..6d76301deb
--- /dev/null
+++ b/tools/pygrub/src/fsys/__init__.py
@@ -0,0 +1,61 @@
+#
+# Copyright 2005 Red Hat, Inc.
+# Jeremy Katz <katzj@xxxxxxxxxx>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os
+import sys
+
+fstypes = {}
+
+def register_fstype(x):
+ if x.name in fstypes.keys():
+ return
+ fstypes[x.name] = x
+
+class FileSystemType(object):
+ """A simple representation for a file system that gives a fs name
+ and a method for sniffing a file to see if it's of the given fstype."""
+ def __init__(self):
+ self.name = ""
+
+ def sniff_magic(self, fn, offset = 0):
+ """Look at the filesystem at fn for the appropriate magic starting at
+ offset offset."""
+ raise RuntimeError, "sniff_magic not implemented"
+
+ def open_fs(self, fn, offset = 0):
+ """Open the given filesystem and return a filesystem object."""
+ raise RuntimeError, "open_fs not implemented"
+
+class FileSystem(object):
+ def open(self, name, flags = 0, block_size = 0):
+ """Open the fsys on name with given flags and block_size."""
+ raise RuntimeError, "open not implemented"
+
+ def close(self):
+ """Close the fsys."""
+ raise RuntimeError, "close not implemented"
+
+ def open_file(self, file, flags = None):
+ """Open the file 'name' with the given flags. The returned object
+ should look similar to a native file object."""
+ raise RuntimeError, "open_file not implemented"
+
+
+
+mydir = sys.modules['grub.fsys'].__path__[0]
+for f in os.listdir(mydir):
+ if not os.path.isdir("%s/%s" %(mydir, f)):
+ continue
+ try:
+ exec "import grub.fsys.%s" %(f,)
+ except ImportError, e:
+ pass
diff --git a/tools/pygrub/src/fsys/ext2/__init__.py b/tools/pygrub/src/fsys/ext2/__init__.py
new file mode 100644
index 0000000000..ff8f7af48f
--- /dev/null
+++ b/tools/pygrub/src/fsys/ext2/__init__.py
@@ -0,0 +1,38 @@
+# Copyright 2005 Red Hat, Inc.
+# Jeremy Katz <katzj@redhat.com>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+from grub.fsys import register_fstype, FileSystemType
+from _pyext2 import *
+
+import os, struct
+
+class Ext2FileSystemType(FileSystemType):
+ def __init__(self):
+ FileSystemType.__init__(self)
+ self.name = "ext2"
+
+ def sniff_magic(self, fn, offset = 0):
+ fd = os.open(fn, os.O_RDONLY)
+ os.lseek(fd, offset, 0)
+ buf = os.read(fd, 2048)
+
+ if len(buf) > 1082 and \
+ struct.unpack("<H", buf[1080:1082]) == (0xef53,):
+ return True
+ return False
+
+ def open_fs(self, fn, offset = 0):
+ if not self.sniff_magic(fn, offset):
+ raise ValueError, "Not an ext2 filesystem"
+ return Ext2Fs(fn)
+
+register_fstype(Ext2FileSystemType())
+
diff --git a/tools/pygrub/src/fsys/ext2/ext2module.c b/tools/pygrub/src/fsys/ext2/ext2module.c
new file mode 100644
index 0000000000..30cfd043ae
--- /dev/null
+++ b/tools/pygrub/src/fsys/ext2/ext2module.c
@@ -0,0 +1,332 @@
+/*
+ * ext2module.c - simple python binding for libext2fs
+ *
+ * Copyright 2005 Red Hat, Inc.
+ * Jeremy Katz <katzj@redhat.com>
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * general public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <Python.h>
+
+#include <ext2fs/ext2fs.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if (PYTHON_API_VERSION >= 1011)
+#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
+#else
+#define PY_PAD 0L,0L,0L,0L
+#endif
+
+
+/* global error object */
+PyObject *Ext2Error;
+
+typedef struct _Ext2Fs Ext2Fs;
+struct _Ext2Fs {
+ PyObject_HEAD;
+ ext2_filsys fs;
+};
+
+typedef struct _Ext2File Ext2File;
+struct _Ext2File {
+ PyObject_HEAD;
+ ext2_file_t file;
+};
+
+/* ext2 file object */
+
+static PyObject *
+ext2_file_close (Ext2File *file, PyObject *args)
+{
+ if (file->file != NULL)
+ ext2fs_file_close(file->file);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+ext2_file_read (Ext2File *file, PyObject *args)
+{
+ int err, size = 0;
+ size_t n, total = 0;
+ PyObject * buffer = NULL;
+
+ if (file->file == NULL) {
+ PyErr_SetString(PyExc_ValueError, "Cannot read from closed file");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "|i", &size))
+ return NULL;
+
+ buffer = PyString_FromStringAndSize((char *) NULL, (size) ? size : 4096);
+ if (buffer == NULL)
+ return buffer;
+
+ while (1) {
+ err = ext2fs_file_read(file->file, PyString_AS_STRING(buffer) + total,
+ (size) ? size : 4096, &n);
+ if (err) {
+ if (buffer != NULL) { Py_DECREF(buffer); }
+ Py_DECREF(buffer);
+ PyErr_SetString(PyExc_ValueError, "read error");
+ return NULL;
+ }
+
+ total += n;
+ if (n == 0)
+ break;
+
+ if (size && size == total)
+ break;
+
+ if (!size) {
+ _PyString_Resize(&buffer, total + 4096);
+ }
+ }
+
+ _PyString_Resize(&buffer, total);
+ return buffer;
+}
+
+static void
+ext2_file_dealloc (Ext2File * file)
+{
+ if (file->file != NULL)
+ ext2fs_file_close(file->file);
+ PyMem_DEL(file);
+}
+
+static struct PyMethodDef Ext2FileMethods[] = {
+ { "close",
+ (PyCFunction) ext2_file_close,
+ METH_VARARGS, NULL },
+ { "read",
+ (PyCFunction) ext2_file_read,
+ METH_VARARGS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+static PyObject *
+ext2_file_getattr (Ext2File * file, char * name)
+{
+ return Py_FindMethod (Ext2FileMethods, (PyObject *) file, name);
+}
+
+static char Ext2FileType__doc__[] = "This is the ext2 filesystem object";
+PyTypeObject Ext2FileType = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+ "Ext2File", /* tp_name */
+ sizeof(Ext2File), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) ext2_file_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc) ext2_file_getattr, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0L, /* tp_flags */
+ Ext2FileType__doc__,
+ PY_PAD
+};
+
+static PyObject *
+ext2_file_open (Ext2Fs *fs, char * name, int flags)
+{
+ int err;
+ ext2_file_t f;
+ ext2_ino_t ino;
+ Ext2File * file;
+
+ file = (Ext2File *) PyObject_NEW(Ext2File, &Ext2FileType);
+ file->file = NULL;
+
+ err = ext2fs_namei_follow(fs->fs, EXT2_ROOT_INO, EXT2_ROOT_INO, name, &ino);
+ if (err) {
+ PyErr_SetString(PyExc_ValueError, "unable to open file");
+ return NULL;
+ }
+
+ err = ext2fs_file_open(fs->fs, ino, flags, &f);
+ if (err) {
+ PyErr_SetString(PyExc_ValueError, "unable to open file");
+ return NULL;
+ }
+
+ file->file = f;
+ return (PyObject *) file;
+}
+
+/* ext2fs object */
+
+static PyObject *
+ext2_fs_close (Ext2Fs *fs, PyObject *args)
+{
+ if (fs->fs != NULL)
+ ext2fs_close(fs->fs);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "name", "flags", "superblock",
+ "block_size", NULL };
+ char * name;
+ int flags = 0, superblock = 0, err;
+ unsigned int block_size = 0;
+ ext2_filsys efs;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist,
+ &name, &flags, &superblock, &block_size))
+ return NULL;
+
+ if (fs->fs != NULL) {
+ PyErr_SetString(PyExc_ValueError, "already have an fs object");
+ return NULL;
+ }
+
+ err = ext2fs_open(name, flags, superblock, block_size,
+ unix_io_manager, &efs);
+ if (err) {
+ PyErr_SetString(PyExc_ValueError, "unable to open file");
+ return NULL;
+ }
+
+ fs->fs = efs;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+ext2_fs_open_file (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "name", "flags", NULL };
+ char * name;
+ int flags = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i", kwlist,
+ &name, &flags))
+ return NULL;
+
+ return ext2_file_open(fs, name, flags);
+}
+
+static void
+ext2_fs_dealloc (Ext2Fs * fs)
+{
+ if (fs->fs != NULL)
+ ext2fs_close(fs->fs);
+ PyMem_DEL(fs);
+}
+
+static struct PyMethodDef Ext2FsMethods[] = {
+ { "close",
+ (PyCFunction) ext2_fs_close,
+ METH_VARARGS, NULL },
+ { "open",
+ (PyCFunction) ext2_fs_open,
+ METH_VARARGS|METH_KEYWORDS, NULL },
+ { "open_file",
+ (PyCFunction) ext2_fs_open_file,
+ METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+static PyObject *
+ext2_fs_getattr (Ext2Fs * fs, char * name)
+{
+ return Py_FindMethod (Ext2FsMethods, (PyObject *) fs, name);
+}
+
+static char Ext2FsType__doc__[] = "This is the ext2 filesystem object";
+PyTypeObject Ext2FsType = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+ "Ext2Fs", /* tp_name */
+ sizeof(Ext2Fs), /* tp_size */
+ 0, /* tp_itemsize */
+ (destructor) ext2_fs_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc) ext2_fs_getattr, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0L, /* tp_flags */
+ Ext2FsType__doc__,
+ PY_PAD
+};
+
+static PyObject *
+ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "name", "flags", "superblock",
+ "block_size", NULL };
+ char * name;
+ int flags = 0, superblock = 0;
+ unsigned int block_size = 0;
+ Ext2Fs *pfs;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist,
+ &name, &flags, &superblock, &block_size))
+ return NULL;
+
+ pfs = (Ext2Fs *) PyObject_NEW(Ext2Fs, &Ext2FsType);
+ if (pfs == NULL)
+ return NULL;
+ pfs->fs = NULL;
+
+ if (!ext2_fs_open(pfs,
+ Py_BuildValue("siii", name, flags, superblock, block_size),
+ NULL))
+ return NULL;
+
+ return (PyObject *)pfs;
+}
+
+
+static struct PyMethodDef Ext2ModuleMethods[] = {
+ { "Ext2Fs", (PyCFunction) ext2_fs_new, METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+
+void init_pyext2(void) {
+ PyObject *m, *d;
+
+ m = Py_InitModule("_pyext2", Ext2ModuleMethods);
+ d = PyModule_GetDict(m);
+
+ /* o = PyObject_NEW(PyObject, yExt2FsConstructorType);
+ PyDict_SetItemString(d, "PyExt2Fs", o);
+ Py_DECREF(o);*/
+
+}
diff --git a/tools/pygrub/src/fsys/ext2/test.py b/tools/pygrub/src/fsys/ext2/test.py
new file mode 100644
index 0000000000..eeb79506ee
--- /dev/null
+++ b/tools/pygrub/src/fsys/ext2/test.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+
+import _pyext2
+import struct, os, sys
+
+fs = _pyext2.Ext2Fs("test.img")
+
+f = fs.open_file("/boot/vmlinuz-2.6.11-1.1177_FC4")
+buf = f.read()
+o = open("vmlinuz", "wb+")
+o.write(buf)
+o.close()
+
+f.close()
diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub
new file mode 100644
index 0000000000..4439092625
--- /dev/null
+++ b/tools/pygrub/src/pygrub
@@ -0,0 +1,270 @@
+#!/usr/bin/python
+#
+# pygrub - simple python-based bootloader for Xen
+#
+# Copyright 2005 Red Hat, Inc.
+# Jeremy Katz <katzj@redhat.com>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os, sys, string, struct, tempfile
+import logging
+
+import curses, _curses, curses.wrapper
+import getopt
+
+import grub.GrubConf
+import grub.fsys
+
+PYGRUB_VER = 0.02
+
+
+def draw_window():
+ stdscr = curses.initscr()
+ curses.use_default_colors()
+ try:
+ curses.curs_set(0)
+ except _curses.error:
+ pass
+
+ stdscr.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,))
+
+ win = curses.newwin(10, 74, 2, 1)
+ win.box()
+ win.refresh()
+
+ stdscr.addstr(12, 5, "Use the U and D keys to select which entry is highlighted.")
+ stdscr.addstr(13, 5, "Press enter to boot the selected OS. 'e' to edit the")
+ stdscr.addstr(14, 5, "commands before booting, 'a' to modify the kernel arguments ")
+ stdscr.addstr(15, 5, "before booting, or 'c' for a command line.")
+ stdscr.addch(12, 13, curses.ACS_UARROW)
+ stdscr.addch(12, 19, curses.ACS_DARROW)
+ (y, x) = stdscr.getmaxyx()
+ stdscr.move(y - 1, x - 1)
+
+ stdscr.refresh()
+ return (stdscr, win)
+
+def fill_entries(win, cfg, selected):
+ y = 0
+
+ for i in cfg.images:
+ if (0, y) > win.getmaxyx():
+ break
+ if y == selected:
+ attr = curses.A_REVERSE
+ else:
+ attr = 0
+ win.addstr(y + 1, 2, i.title.ljust(70), attr)
+ y += 1
+ win.refresh()
+
+def select(win, line):
+ win.attron(curses.A_REVERSE)
+ win.redrawln(line + 1, 1)
+ win.refresh()
+
+def is_disk_image(file):
+ fd = os.open(file, os.O_RDONLY)
+ buf = os.read(fd, 512)
+ os.close(fd)
+
+ if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
+ return True
+ return False
+
+
+def get_config(fn):
+ if not os.access(fn, os.R_OK):
+ raise RuntimeError, "Unable to access %s" %(fn,)
+
+ cf = grub.GrubConf.GrubConfigFile()
+
+ if is_disk_image(fn):
+ raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
+
+ # open the image and read the grub config
+ fs = None
+ for fstype in grub.fsys.fstypes.values():
+ if fstype.sniff_magic(fn):
+ fs = fstype.open_fs(fn)
+ break
+
+ if fs is not None:
+ f = fs.open_file("/boot/grub/grub.conf")
+ buf = f.read()
+ f.close()
+ fs.close()
+ # then parse the grub config
+ cf.parse(buf)
+ else:
+ # set the config file and parse it
+ cf.filename = fn
+ cf.parse()
+
+ return cf
+
+def get_entry_idx(cf, entry):
+ # first, see if the given entry is numeric
+ try:
+ idx = string.atoi(entry)
+ return idx
+ except ValueError:
+ pass
+
+ # it's not, now check the labels for a match
+ for i in range(len(cf.images)):
+ if entry == cf.images[i].title:
+ return i
+
+ return None
+
+def main(cf = None):
+ mytime = 0
+
+ (stdscr, win) = draw_window()
+ stdscr.timeout(1000)
+ selected = cf.default
+
+ while (mytime < int(cf.timeout)):
+ if cf.timeout != -1 and mytime != -1:
+ stdscr.addstr(20, 5, "Will boot selected entry in %2d seconds"
+ %(int(cf.timeout) - mytime))
+ else:
+ stdscr.addstr(20, 5, " " * 80)
+
+ fill_entries(win, cf, selected)
+ c = stdscr.getch()
+ if mytime != -1:
+ mytime += 1
+# if c == ord('q'):
+# selected = -1
+# break
+ elif c == ord('c'):
+ # FIXME: needs to go to command line mode
+ continue
+ elif c == ord('a'):
+ # FIXME: needs to go to append mode
+ continue
+ elif c == ord('e'):
+ # FIXME: needs to go to edit mode
+ continue
+ elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')):
+ break
+ elif c == curses.KEY_UP:
+ mytime = -1
+ selected -= 1
+ elif c == curses.KEY_DOWN:
+ mytime = -1
+ selected += 1
+ else:
+ pass
+
+ # bound at the top and bottom
+ if selected < 0:
+ selected = 0
+ elif selected >= len(cf.images):
+ selected = len(cf.images) - 1
+
+ if selected >= 0:
+ return selected
+
+if __name__ == "__main__":
+ sel = None
+
+ def run_main(scr, *args):
+ global sel
+ sel = main(cf)
+
+ def usage():
+ print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <image>" %(sys.argv[0],)
+
+ try:
+ opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::',
+ ["quiet", "help", "output=", "entry="])
+ except getopt.GetoptError:
+ usage()
+ sys.exit(1)
+
+ if len(args) < 1:
+ usage()
+ sys.exit(1)
+ file = args[0]
+
+ output = None
+ entry = None
+ interactive = True
+ for o, a in opts:
+ if o in ("-q", "--quiet"):
+ interactive = False
+ elif o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("--output",):
+ output = a
+ elif o in ("--entry",):
+ entry = a
+ # specifying the entry to boot implies non-interactive
+ interactive = False
+
+ if output is None or output == "-":
+ fd = sys.stdout.fileno()
+ else:
+ fd = os.open(output, os.O_WRONLY)
+
+ cf = get_config(file)
+ if interactive:
+ curses.wrapper(run_main)
+ else:
+ sel = cf.default
+
+ # set the entry to boot as requested
+ if entry is not None:
+ idx = get_entry_idx(cf, entry)
+ if idx is not None and idx > 0 and idx < len(cf.images):
+ sel = idx
+
+ img = cf.images[sel]
+ print "Going to boot %s" %(img.title)
+ print " kernel: %s" %(img.kernel[1],)
+ if img.initrd:
+ print " initrd: %s" %(img.initrd[1],)
+
+ if is_disk_image(file):
+ raise RuntimeError, "unable to handle full disk images yet"
+
+ # read the kernel and initrd onto the hostfs
+ fs = None
+ for fstype in grub.fsys.fstypes.values():
+ if fstype.sniff_magic(file):
+ fs = fstype.open_fs(file)
+ break
+
+ if fs is None:
+ raise RuntimeError, "Unable to open filesystem"
+
+ kernel = fs.open_file(img.kernel[1],).read()
+ (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.")
+ os.write(tfd, kernel)
+ os.close(tfd)
+ sxp = "linux (kernel %s)" %(fn,)
+
+ if img.initrd:
+ initrd = fs.open_file(img.initrd[1],).read()
+ (tfd, fn) = tempfile.mkstemp(prefix="initrd.")
+ os.write(tfd, initrd)
+ os.close(tfd)
+ sxp += "(ramdisk %s)" %(fn,)
+ else:
+ initrd = None
+ sxp += "(args '%s')" %(img.args,)
+
+ sys.stdout.flush()
+ os.write(fd, sxp)
+
diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py
new file mode 100644
index 0000000000..09a50f8e8c
--- /dev/null
+++ b/tools/python/xen/xend/XendBootloader.py
@@ -0,0 +1,94 @@
+#
+# XendBootloader.py - Framework to run a boot loader for picking the kernel
+#
+# Copyright 2005 Red Hat, Inc.
+# Jeremy Katz <katzj@xxxxxxxxxx>
+#
+# This software may be freely redistributed under the terms of the GNU
+# general public license.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os, sys, select
+import sxp
+
+from XendLogging import log
+from XendError import VmError
+
+BL_FIFO = "/var/lib/xen/xenbl"
+
+def bootloader(blexec, disk, quiet = 0, vcpus = None, entry = None):
+ """Run the boot loader executable on the given disk and return a
+ config image.
+ @param blexec Binary to use as the boot loader
+ @param disk Disk to run the boot loader on.
+ @param quiet Run in non-interactive mode, just booting the default.
+ @param vcpus Number of vcpus for the domain.
+ @param entry Default entry to boot."""
+
+ if not os.access(blexec, os.X_OK):
+ msg = "Bootloader isn't executable"
+ log.error(msg)
+ raise VmError(msg)
+ if not os.access(disk, os.R_OK):
+ msg = "Disk isn't accessible"
+ log.error(msg)
+ raise VmError(msg)
+
+ os.mkfifo(BL_FIFO, 0600)
+
+ child = os.fork()
+ if (not child):
+ args = [ blexec ]
+ if quiet:
+ args.append("-q")
+ args.append("--output=%s" %(BL_FIFO,))
+ if entry is not None:
+ args.append("--entry=%s" %(entry,))
+ args.append(disk)
+
+ try:
+ os.execvp(args[0], args)
+ except OSError, e:
+ print e
+ pass
+ os._exit(1)
+
+ while 1:
+ try:
+ r = os.open(BL_FIFO, os.O_RDONLY)
+ except OSError, e:
+ if e.errno == 4:
+ continue
+ break
+ ret = ""
+ while 1:
+ select.select([r], [], [])
+ s = os.read(r, 1024)
+ ret = ret + s
+ if len(s) == 0:
+ break
+
+ (pid, status) = os.waitpid(child, 0)
+ os.close(r)
+ os.unlink(BL_FIFO)
+
+ if len(ret) == 0:
+ msg = "Boot loader didn't return any data!"
+ log.error(msg)
+ raise VmError, msg
+
+ pin = sxp.Parser()
+ pin.input(ret)
+ pin.input_eof()
+
+ config_image = pin.val
+ if vcpus and sxp.child_value(config_image, "vcpus") is None:
+ config_image.append(['vcpus', vcpus])
+
+ config = ['image', config_image]
+ return config
+
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index c5f7ae3d99..36d1cb887d 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -16,11 +16,13 @@ import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
import xen.util.ip
from xen.util.ip import _readline, _readlines
from xen.xend.server import channel, controller
+from xen.xend.server.blkif import blkdev_uname_to_file
from server.channel import channelFactory
import server.SrvDaemon; xend = server.SrvDaemon.instance()
from server import messages
+from xen.xend.XendBootloader import bootloader
import sxp
from XendLogging import log
from XendError import VmError
@@ -294,6 +296,7 @@ class XendDomainInfo:
self.image_handler = None
self.is_vmx = False
self.vcpus = 1
+ self.bootloader = None
def setdom(self, dom):
"""Set the domain id.
@@ -496,6 +499,7 @@ class XendDomainInfo:
self.find_image_handler()
self.init_domain()
self.register_domain()
+ self.configure_bootloader()
# Create domain devices.
self.configure_backends()
@@ -674,6 +678,13 @@ class XendDomainInfo:
memory = memory * 1024 + self.pgtable_size(memory)
dom = xc.domain_create(dom= dom, mem_kb= memory,
cpu= cpu, cpu_weight= cpu_weight)
+ if self.bootloader:
+ try:
+ if kernel: os.unlink(kernel)
+ if ramdisk: os.unlink(ramdisk)
+ except OSError, e:
+ log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
+
if dom <= 0:
raise VmError('Creating domain failed: name=%s memory=%d'
% (self.name, memory))
@@ -854,6 +865,13 @@ class XendDomainInfo:
self.config.remove(['device', dev_config])
self.deleteDevice(type, dev.getId())
+ def configure_bootloader(self):
+ """Configure boot loader.
+ """
+ bl = sxp.child_value(self.config, "bootloader")
+ if bl is not None:
+ self.bootloader = bl
+
def configure_console(self):
"""Configure the vm console port.
"""
@@ -931,10 +949,30 @@ class XendDomainInfo:
self.state = STATE_VM_OK
self.restart_check()
self.restart_state = STATE_RESTART_BOOTING
+ if self.bootloader:
+ self.config = self.bootloader_config()
self.construct(self.config)
finally:
self.restart_state = None
+ def bootloader_config(self):
+ # if we're restarting with a bootloader, we need to run it
+ # FIXME: this assumes the disk is the first device and
+ # that we're booting from the first disk
+ blcfg = None
+ # FIXME: this assumes that we want to use the first disk
+ dev = sxp.child_value(self.config, "device")
+ if dev:
+ disk = sxp.child_value(dev, "uname")
+ fn = blkdev_uname_to_file(disk)
+ blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
+ if blcfg is None:
+ msg = "Had a bootloader specified, but can't find disk"
+ log.error(msg)
+ raise VmError(msg)
+ config = sxp.merge(['vm', blconfig ], self.config)
+ return config
+
def configure_backends(self):
"""Set configuration flags if the vm is a backend for netif or blkif.
Configure the backends to use for vbd and vif if specified.
@@ -1071,6 +1109,7 @@ def vm_image_linux(vm, image):
if args:
cmdline += " " + args
ramdisk = sxp.child_value(image, "ramdisk", '')
+ log.debug("creating linux domain with cmdline: %s" %(cmdline,))
vm.create_domain("linux", kernel, ramdisk, cmdline)
return vm
@@ -1169,6 +1208,7 @@ add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
add_config_handler('backend', vm_field_ignore)
add_config_handler('vcpus', vm_field_ignore)
+add_config_handler('bootloader', vm_field_ignore)
# Register other config handlers.
add_config_handler('maxmem', vm_field_maxmem)
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
index 10ce6c9eac..6be499d64e 100755
--- a/tools/python/xen/xend/server/blkif.py
+++ b/tools/python/xen/xend/server/blkif.py
@@ -71,6 +71,15 @@ def blkdev_segment(name):
'type' : 'Disk' }
return val
+def blkdev_uname_to_file(uname):
+ """Take a blkdev uname and return the corresponding filename."""
+ fn = None
+ if uname.find(":") != -1:
+ (typ, fn) = uname.split(":")
+ if typ == "phy" and not fn.startswith("/dev/"):
+ fn = "/dev/%s" %(fn,)
+ return fn
+
def mount_mode(name):
mode = None
name = expand_dev_name(name)
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 82fd0b7a22..5b775d8d57 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -10,6 +10,8 @@ import socket
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend.XendClient import server, XendError
+from xen.xend.XendBootloader import bootloader
+from xen.xend.server import blkif
from xen.util import console_client
@@ -94,6 +96,14 @@ gopts.var('name', val='NAME',
fn=set_value, default=None,
use="Domain name. Must be unique.")
+gopts.var('bootloader', val='FILE',
+ fn=set_value, default=None,
+ use="Path to bootloader.")
+
+gopts.var('bootentry', val='NAME',
+ fn=set_value, default=None,
+ use="Entry to boot via boot loader")
+
gopts.var('kernel', val='FILE',
fn=set_value, default=None,
use="Path to kernel image.")
@@ -252,7 +262,7 @@ def strip(pre, s):
else:
return s
-def configure_image(config, vals):
+def configure_image(opts, config, vals):
"""Create the image config.
"""
config_image = [ vals.builder ]
@@ -272,7 +282,7 @@ def configure_image(config, vals):
config.append(['image', config_image ])
-def configure_disks(config_devs, vals):
+def configure_disks(opts, config_devs, vals):
"""Create the config for disks (virtual block devices).
"""
for (uname, dev, mode, backend) in vals.disk:
@@ -284,14 +294,14 @@ def configure_disks(config_devs, vals):
config_vbd.append(['backend', backend])
config_devs.append(['device', config_vbd])
-def configure_pci(config_devs, vals):
+def configure_pci(opts, config_devs, vals):
"""Create the config for pci devices.
"""
for (bus, dev, func) in vals.pci:
config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
config_devs.append(['device', config_pci])
-def configure_usb(config_devs, vals):
+def configure_usb(opts, config_devs, vals):
for path in vals.usb:
config_usb = ['usb', ['path', path]]
config_devs.append(['device', config_usb])
@@ -315,7 +325,7 @@ def randomMAC():
random.randint(0x00, 0xff) ]
return ':'.join(map(lambda x: "%02x" % x, mac))
-def configure_vifs(config_devs, vals):
+def configure_vifs(opts, config_devs, vals):
"""Create the config for virtual network interfaces.
"""
vifs = vals.vif
@@ -357,7 +367,7 @@ def configure_vifs(config_devs, vals):
config_vif.append(['ip', ip])
config_devs.append(['device', config_vif])
-def configure_vfr(config, vals):
+def configure_vfr(opts, config, vals):
if not vals.ipaddr: return
config_vfr = ['vfr']
idx = 0 # No way of saying which IP is for which vif?
@@ -365,7 +375,7 @@ def configure_vfr(config, vals):
config_vfr.append(['vif', ['id', idx], ['ip', ip]])
config.append(config_vfr)
-def configure_vmx(config_devs, vals):
+def configure_vmx(opts, config_devs, vals):
"""Create the config for VMX devices.
"""
memmap = vals.memmap
@@ -375,7 +385,21 @@ def configure_vmx(config_devs, vals):
config_devs.append(['device_model', device_model])
config_devs.append(['device_config', device_config])
-def make_config(vals):
+def run_bootloader(opts, config, vals):
+ if not os.access(vals.bootloader, os.X_OK):
+ opts.err("Bootloader isn't executable")
+ if len(vals.disk) < 1:
+ opts.err("No disks configured and boot loader requested")
+ (uname, dev, mode, backend) = vals.disk[0]
+ file = blkif.blkdev_uname_to_file(uname)
+
+ blcfg = bootloader(vals.bootloader, file, not vals.console_autoconnect,
+ vals.vcpus, vals.blentry)
+
+ config.append(['bootloader', vals.bootloader])
+ config.append(blcfg)
+
+def make_config(opts, vals):
"""Create the domain configuration.
"""
@@ -396,15 +420,19 @@ def make_config(vals):
config.append(['restart', vals.restart])
if vals.console:
config.append(['console', vals.console])
-
- configure_image(config, vals)
+
+ if vals.bootloader:
+ run_bootloader(opts, config, vals)
+ else:
+ configure_image(opts, config, vals)
config_devs = []
- configure_disks(config_devs, vals)
- configure_pci(config_devs, vals)
- configure_vifs(config_devs, vals)
- configure_usb(config_devs, vals)
- configure_vmx(config_devs, vals)
+ configure_disks(opts, config_devs, vals)
+ configure_pci(opts, config_devs, vals)
+ configure_vifs(opts, config_devs, vals)
+ configure_usb(opts, config_devs, vals)
+ configure_vmx(opts, config_devs, vals)
config += config_devs
+
return config
def preprocess_disk(opts, vals):
@@ -587,7 +615,8 @@ def main(argv):
preprocess(opts, opts.vals)
if not opts.getopt('name') and opts.getopt('defconfig'):
opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
- config = make_config(opts.vals)
+ config = make_config(opts, opts.vals)
+
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c
index be91098dbb..89353e0e3b 100644
--- a/tools/xfrd/xfrd.c
+++ b/tools/xfrd/xfrd.c
@@ -49,7 +49,7 @@
#include "select.h"
#define MODULE_NAME "XFRD"
-
+#define DEBUG 1
#include "debug.h"
/*
@@ -1226,7 +1226,9 @@ int main(int argc, char *argv[]){
int err = 0;
int key = 0;
int long_index = 0;
+#ifndef DEBUG
static const char * LOGFILE = "/var/log/xfrd.log";
+#endif
#ifndef DEBUG
freopen(LOGFILE, "w+", stdout);