[Fedora-xen] pygrub failed
Winston Chang
winston at stdout.org
Mon Apr 3 02:09:48 UTC 2006
The installer will create the disk image and partition it. If you do
not successfully run to the installer, "xm create -c xxxx" will not
work. The script gives bad instructions when an error occurs.
The Xen hypervisor takes 32MB of RAM (I think), so you have to make
sure that your dom0 gets less than 224MB. I gave mine 192MB, with
the following in grub.conf:
kernel /xen.gz-2.6.15-1.2054_FC5 dom0_mem=196608
In my opinion, the xenguest-install.py method isn't very good at this
point.
- The installer gives poor feedback when something goes wrong, like
when memory is too low.
- pygrub crashes if your terminal emulation is a little weird
- It creates a whole disk image instead of importing partitions.
This makes it difficult to access domU filesystems from dom0, but
this is often necessary for management.
- It doesn't provide an option for creating images on LVM volumes.
An easier solution might be to use the FC5 image from jailtime.org.
If you use the images from their site, keep in mind that you have to
use a kernel from outside of the image; the kernel would have to be
readable from your dom0.
If you use the stock FC5-xenU kernel, it does not have the xennet
driver compiled in. You would have to install the kernel-xenU
package onto the domU disk image to provide the necessary driver
(assuming the disk image is mounted at /mnt/tmp):
yum --installroot=/mnt/tmp install kernel-xenU
And add the following to the domU's /etc/modprobe.conf:
alias eth0 xennet
Or you could use a kernel from xensource that has the xennet driver
compiled into the kernel. I don't know why the developers decided to
take the driver out of the kernel. Pretty much everyone would want
networking on their domU machines, and adding it in this way is just
more complicated.
--Winston
On Apr 2, 2006, at 12:40 PM, Jun OKAJIMA wrote:
>
>> I believe the error "Error: Error creating domain: The privileged
>> domain did not balloon!" happens when you don't have enough available
>> memory for the domU to boot. The xenguest-install.py script tells
>> you to restart the domain by running "xm create -c xxxx', but I think
>> the error message is just a generic one that is printed if the script
>> crashes out, and it it is the wrong thing to do in this case.
>>
>> When I had the same problem, I had to allocate less memory to dom0
>> and re-run the xenguest-install script. I see you have about 196MB
>> of RAM. Since the FC5 script needs 256MB of RAM, I don't think
>> you'll be able to install it unless you increase the amount of RAM
>> you have. But since the machine is a virtual one in VMWare, this
>> shouldn't be too difficult.
>>
>
>
> Thank you for replying.
> Unfortunately, I tried same stuff with 512MB mem but failed.
> What I suspect now is, a disk image would have to be formatted.
> xenguest-install.py just makes plain empty sparse file, but is this
> enough? I suspect it should be formatted and partitioned and so on.
> You succeeded to do an install on FC5? How you did it?
>
> Check the code of pygrub.
> See this:
> 116 fs = None
> 117 for fstype in grub.fsys.fstypes.values():
> 118 if fstype.sniff_magic(fn, offset):
> 119 fs = fstype.open_fs(fn, offset)
> 120 break
> 121
> 122 if fs is not None:
> (snip)
> 138 else:
> 139 raise RuntimeError, "Unable to read filesystem"
>
> What happened here is, in short, like this:
>
> # Check diskimage formatted as described in grub config
> 117 for fstype in grub.fsys.fstypes.values():
> 118 if fstype.sniff_magic(fn, offset):
> # If not formatted properly, raise error.
> 138 else:
> 139 raise RuntimeError, "Unable to read filesystem"
>
> --- Okajima, Jun. Tokyo, Japan.
>
>
> -------------
> [root at localhost ~]# cat -n /usr/bin/pygrub
> 1 #!/usr/bin/python
> 2 #
> 3 # pygrub - simple python-based bootloader for Xen
> 4 #
> 5 # Copyright 2005 Red Hat, Inc.
> 6 # Jeremy Katz <katzj at redhat.com>
> 7 #
> 8 # This software may be freely redistributed under the terms
> of the GNU
> 9 # general public license.
> 10 #
> 11 # You should have received a copy of the GNU General Public
> License
> 12 # along with this program; if not, write to the Free Software
> 13 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> 14 #
> 15
> 16 import os, sys, string, struct, tempfile
> 17 import logging
> 18
> 19 import curses, _curses, curses.wrapper
> 20 import getopt
> 21
> 22 sys.path = [ '/usr/lib/python' ] + sys.path
> 23
> 24 import grub.GrubConf
> 25 import grub.fsys
> 26
> 27 PYGRUB_VER = 0.3
> 28
> 29
> 30 def draw_window():
> 31 stdscr = curses.initscr()
> 32 if hasattr(curses, 'use_default_colors'):
> 33 curses.use_default_colors()
> 34 try:
> 35 curses.curs_set(0)
> 36 except _curses.error:
> 37 pass
> 38
> 39 stdscr.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,))
> 40
> 41 win = curses.newwin(10, 74, 2, 1)
> 42 win.box()
> 43 win.refresh()
> 44
> 45 stdscr.addstr(12, 5, "Use the U and D keys to select
> which entry is highlighted.")
> 46 stdscr.addstr(13, 5, "Press enter to boot the selected
> OS. 'e' to edit the")
> 47 stdscr.addstr(14, 5, "commands before booting, 'a' to
> modify the kernel arguments ")
> 48 stdscr.addstr(15, 5, "before booting, or 'c' for a
> command line.")
> 49 stdscr.addch(12, 13, curses.ACS_UARROW)
> 50 stdscr.addch(12, 19, curses.ACS_DARROW)
> 51 (y, x) = stdscr.getmaxyx()
> 52 stdscr.move(y - 1, x - 1)
> 53
> 54 stdscr.refresh()
> 55 return (stdscr, win)
> 56
> 57 def fill_entries(win, cfg, selected):
> 58 y = 0
> 59
> 60 for i in cfg.images:
> 61 if (0, y) > win.getmaxyx():
> 62 break
> 63 if y == selected:
> 64 attr = curses.A_REVERSE
> 65 else:
> 66 attr = 0
> 67 win.addstr(y + 1, 2, i.title.ljust(70), attr)
> 68 y += 1
> 69 win.refresh()
> 70
> 71 def select(win, line):
> 72 win.attron(curses.A_REVERSE)
> 73 win.redrawln(line + 1, 1)
> 74 win.refresh()
> 75
> 76 def is_disk_image(file):
> 77 fd = os.open(file, os.O_RDONLY)
> 78 buf = os.read(fd, 512)
> 79 os.close(fd)
> 80
> 81 if len(buf) >= 512 and struct.unpack("H", buf[0x1fe:
> 0x200]) == (0xaa55,):
> 82 return True
> 83 return False
> 84
> 85 SECTOR_SIZE=512
> 86 def get_active_offset(file):
> 87 """Find the offset for the start of the first active
> partition in the
> 88 disk image file."""
> 89 fd = os.open(file, os.O_RDONLY)
> 90 buf = os.read(fd, 512)
> 91 for poff in (446, 462, 478, 494): # partition offsets
> 92 # active partition has 0x80 as the first byte
> 93 if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
> 94 return struct.unpack("<L", buf[poff+8:poff+12])
> [0] * SECTOR_SIZE
> 95 return -1
> 96
> 97 def get_config(fn, isconfig = False):
> 98 if not os.access(fn, os.R_OK):
> 99 raise RuntimeError, "Unable to access %s" %(fn,)
> 100
> 101 cf = grub.GrubConf.GrubConfigFile()
> 102
> 103 if isconfig:
> 104 # set the config file and parse it
> 105 cf.filename = fn
> 106 cf.parse()
> 107 return cf
> 108
> 109 offset = 0
> 110 if is_disk_image(fn):
> 111 offset = get_active_offset(fn)
> 112 if offset == -1:
> 113 raise RuntimeError, "Unable to find active
> partition on disk"
> 114
> 115 # open the image and read the grub config
> 116 fs = None
> 117 for fstype in grub.fsys.fstypes.values():
> 118 if fstype.sniff_magic(fn, offset):
> 119 fs = fstype.open_fs(fn, offset)
> 120 break
> 121
> 122 if fs is not None:
> 123 grubfile = None
> 124 for f in ("/boot/grub/menu.lst", "/boot/grub/
> grub.conf",
> 125 "/grub/menu.lst", "/grub/grub.conf"):
> 126 if fs.file_exist(f):
> 127 grubfile = f
> 128 break
> 129 if grubfile is None:
> 130 raise RuntimeError, "we couldn't find /boot/grub
> {menu.lst,grub.conf} " + \
> 131 "in the image provided. halt!"
> 132 f = fs.open_file(grubfile)
> 133 buf = f.read()
> 134 f.close()
> 135 fs.close()
> 136 # then parse the grub config
> 137 cf.parse(buf)
> 138 else:
> 139 raise RuntimeError, "Unable to read filesystem"
> 140
> 141 return cf
> 142
> 143 def get_entry_idx(cf, entry):
> 144 # first, see if the given entry is numeric
> 145 try:
> 146 idx = string.atoi(entry)
> 147 return idx
> 148 except ValueError:
> 149 pass
> 150
> 151 # it's not, now check the labels for a match
> 152 for i in range(len(cf.images)):
> 153 if entry == cf.images[i].title:
> 154 return i
> 155
> 156 return None
> 157
> 158 def main(cf = None):
> 159 mytime = 0
> 160 timeout = int(cf.timeout)
> 161
> 162 (stdscr, win) = draw_window()
> 163 stdscr.timeout(1000)
> 164 selected = cf.default
> 165
> 166 while (timeout == -1 or mytime < int(timeout)):
> 167 if timeout != -1 and mytime != -1:
> 168 stdscr.addstr(20, 5, "Will boot selected entry
> in %2d seconds"
> 169 %(int(timeout) - mytime))
> 170 else:
> 171 stdscr.addstr(20, 5, " " * 80)
> 172
> 173 fill_entries(win, cf, selected)
> 174 c = stdscr.getch()
> 175 if mytime != -1:
> 176 mytime += 1
> 177 # if c == ord('q'):
> 178 # selected = -1
> 179 # break
> 180 if c == ord('c'):
> 181 # FIXME: needs to go to command line mode
> 182 continue
> 183 elif c == ord('a'):
> 184 # FIXME: needs to go to append mode
> 185 continue
> 186 elif c == ord('e'):
> 187 # FIXME: needs to go to edit mode
> 188 continue
> 189 elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')):
> 190 break
> 191 elif c == curses.KEY_UP:
> 192 mytime = -1
> 193 selected -= 1
> 194 elif c == curses.KEY_DOWN:
> 195 mytime = -1
> 196 selected += 1
> 197 else:
> 198 pass
> 199
> 200 # bound at the top and bottom
> 201 if selected < 0:
> 202 selected = 0
> 203 elif selected >= len(cf.images):
> 204 selected = len(cf.images) - 1
> 205
> 206 if selected >= 0:
> 207 return selected
> 208
> 209 if __name__ == "__main__":
> 210 sel = None
> 211
> 212 def run_main(scr, *args):
> 213 global sel
> 214 sel = main(cf)
> 215
> 216 def usage():
> 217 print >> sys.stderr, "Usage: %s [-q|--quiet] [--
> output=] [--entry=] <image>" %
> (sys.argv[0],)
> 218
> 219 try:
> 220 opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::',
> 221 ["quiet", "help",
> "output=", "entry=",
> 222 "isconfig"])
> 223 except getopt.GetoptError:
> 224 usage()
> 225 sys.exit(1)
> 226
> 227 if len(args) < 1:
> 228 usage()
> 229 sys.exit(1)
> 230 file = args[0]
> 231
> 232 output = None
> 233 entry = None
> 234 interactive = True
> 235 isconfig = False
> 236 for o, a in opts:
> 237 if o in ("-q", "--quiet"):
> 238 interactive = False
> 239 elif o in ("-h", "--help"):
> 240 usage()
> 241 sys.exit()
> 242 elif o in ("--output",):
> 243 output = a
> 244 elif o in ("--entry",):
> 245 entry = a
> 246 # specifying the entry to boot implies non-
> interactive
> 247 interactive = False
> 248 elif o in ("--isconfig",):
> 249 isconfig = True
> 250
> 251 if output is None or output == "-":
> 252 fd = sys.stdout.fileno()
> 253 else:
> 254 fd = os.open(output, os.O_WRONLY)
> 255
> 256 cf = get_config(file, isconfig)
> 257 if interactive:
> 258 curses.wrapper(run_main)
> 259 else:
> 260 sel = cf.default
> 261
> 262 # set the entry to boot as requested
> 263 if entry is not None:
> 264 idx = get_entry_idx(cf, entry)
> 265 if idx is not None and idx > 0 and idx < len
> (cf.images):
> 266 sel = idx
> 267
> 268 img = cf.images[sel]
> 269 print "Going to boot %s" %(img.title)
> 270 print " kernel: %s" %(img.kernel[1],)
> 271 if img.initrd:
> 272 print " initrd: %s" %(img.initrd[1],)
> 273
> 274 offset = 0
> 275 if is_disk_image(file):
> 276 offset = get_active_offset(file)
> 277 if offset == -1:
> 278 raise RuntimeError, "Unable to find active
> partition on disk"
> 279
> 280 # read the kernel and initrd onto the hostfs
> 281 fs = None
> 282 for fstype in grub.fsys.fstypes.values():
> 283 if fstype.sniff_magic(file, offset):
> 284 fs = fstype.open_fs(file, offset)
> 285 break
> 286
> 287 if fs is None:
> 288 raise RuntimeError, "Unable to open filesystem"
> 289
> 290 kernel = fs.open_file(img.kernel[1],).read()
> 291 (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.", dir="/
> var/lib/xen")
> 292 os.write(tfd, kernel)
> 293 os.close(tfd)
> 294 sxp = "linux (kernel %s)" %(fn,)
> 295
> 296 if img.initrd:
> 297 initrd = fs.open_file(img.initrd[1],).read()
> 298 (tfd, fn) = tempfile.mkstemp(prefix="initrd.",
> dir="/var/lib/xen")
> 299 os.write(tfd, initrd)
> 300 os.close(tfd)
> 301 sxp += "(ramdisk %s)" %(fn,)
> 302 else:
> 303 initrd = None
> 304 sxp += "(args '%s')" %(img.args,)
> 305
> 306 sys.stdout.flush()
> 307 os.write(fd, sxp)
> 308
> [root at localhost ~]#
More information about the Fedora-xen
mailing list