[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