[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] pygrub: add syslog support to pygrub
# HG changeset patch # User Zhigang Wang <zhigang.x.wang@xxxxxxxxxx> # Date 1342720736 14400 # Node ID ec9655b30a5fa5b5abb3e05505f681f9be559613 # Parent 43e21ce7f22151524b800a6cf0ac4ba1233b34a7 pygrub: add syslog support to pygrub Currently, when pygrub failed, we don't know the reason because xend/xl will not capture the stderr message. This patch will log the error message to syslog. We choosing syslog because pygrub could be called concurrently. If we want dedicated log file for pygrub, we need a log server. Using syslog is simple. Example /var/log/messages log: Jul 19 11:59:53 ovs030 [2012-07-19 11:59:53,504 7112] ERROR (pygrub:848) [Errno 95] Operation not supported Traceback (most recent call last): File "/share/repos/xen-unstable/tools/pygrub/src/pygrub", line 828, in ? fs = fsimage.open(file, offset, bootfsoptions) IOError: [Errno 95] Operation not supported Jul 19 11:59:53 ovs030 [2012-07-19 11:59:53,508 7112] ERROR (pygrub:892) Unable to find partition containing kernel '7112' is the pygrub PID, so we can distinguish each process. Also in this patch: 1). Fix indentation for some lines. 2). Removed some trailing spaces. 3). Mark 'isconfig' a duplicate option of 'debug' and remove the currently broken code: if isconfig: chosencfg = run_grub(file, entry, fs, incfg["args"]) 'fs' is not defined yet here, so it will raise an exception. Signed-off-by: Zhigang Wang <zhigang.x.wang@xxxxxxxxxx> diff -r 43e21ce7f221 -r ec9655b30a5f tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Tue Jul 17 17:33:31 2012 +0100 +++ b/tools/pygrub/src/pygrub Thu Jul 19 13:58:56 2012 -0400 @@ -13,9 +13,10 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -import os, sys, string, struct, tempfile, re, traceback +import os, sys, string, struct, tempfile, re import copy import logging +import logging.handlers import platform import xen.lowlevel.xc @@ -35,7 +36,7 @@ def enable_cursor(ison): val = 2 else: val = 0 - + try: curses.curs_set(val) except _curses.error: @@ -79,7 +80,7 @@ def get_solaris_slice(file, offset): if slicetag == V_ROOT: return slicesect * SECTOR_SIZE - raise RuntimeError, "No root slice found" + raise RuntimeError, "No root slice found" def get_fs_offset_gpt(file): fd = os.open(file, os.O_RDONLY) @@ -102,7 +103,7 @@ FDISK_PART_GPT=0xee def get_partition_offsets(file): image_type = identify_disk_image(file) if image_type == DISK_TYPE_RAW: - # No MBR: assume whole disk filesystem, which is like a + # No MBR: assume whole disk filesystem, which is like a # single partition starting at 0 return [0] elif image_type == DISK_TYPE_HYBRIDISO: @@ -122,7 +123,7 @@ def get_partition_offsets(file): partbuf = buf[poff:poff+16] offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE type = struct.unpack("<B", partbuf[4:5])[0] - + # offset == 0 implies this partition is not enabled if offset == 0: continue @@ -153,7 +154,7 @@ class GrubLineEditor(curses.textpad.Text screen.noutrefresh() win = curses.newwin(1, 74, startx, starty + 2) curses.textpad.Textbox.__init__(self, win) - + self.line = list(line) self.pos = len(line) self.cancelled = False @@ -219,7 +220,7 @@ class GrubLineEditor(curses.textpad.Text if self.cancelled: return None return string.join(self.line, "") - + class Grub: ENTRY_WIN_LINES = 8 @@ -243,7 +244,7 @@ class Grub: self.entry_win = curses.newwin(Grub.ENTRY_WIN_LINES + 2, 74, 2, 1) self.text_win = curses.newwin(10, 70, 12, 5) curses.def_prog_mode() - + curses.reset_prog_mode() self.screen.erase() @@ -261,7 +262,7 @@ class Grub: self.start_image = self.selected_image if self.selected_image < self.start_image: self.start_image = self.selected_image - + for y in range(self.start_image, len(self.cf.images)): i = self.cf.images[y] if y > self.start_image + maxy: @@ -311,7 +312,7 @@ class Grub: l = img.lines[idx].expandtabs().ljust(70) if len(l) > 70: l = l[:69] + ">" - + self.entry_win.addstr(idp, 2, l) if idx == curline: self.entry_win.attroff(curses.A_REVERSE) @@ -349,7 +350,7 @@ class Grub: self.command_line_mode() if self.isdone: return - + # bound at the top and bottom if curline < 0: curline = 0 @@ -357,11 +358,11 @@ class Grub: curline = len(img.lines) - 1 if self.isdone: - # Fix to allow pygrub command-line editing in Lilo bootloader (used by IA64) - if platform.machine() == 'ia64': - origimg.reset(img.lines, img.path) - else: - origimg.reset(img.lines) + # Fix to allow pygrub command-line editing in Lilo bootloader (used by IA64) + if platform.machine() == 'ia64': + origimg.reset(img.lines, img.path) + else: + origimg.reset(img.lines) def edit_line(self, line): self.screen.erase() @@ -386,7 +387,7 @@ class Grub: lines = [] while 1: t = GrubLineEditor(self.screen, y, 2) - enable_cursor(True) + enable_cursor(True) ret = t.edit() if ret: if ret in ("quit", "return"): @@ -396,7 +397,7 @@ class Grub: lines.append(ret) continue - # if we got boot, then we want to boot the entered image + # if we got boot, then we want to boot the entered image img = self.cf.new_image("entered", lines) self.cf.add_image(img) self.selected_image = len(self.cf.images) - 1 @@ -409,16 +410,16 @@ class Grub: def read_config(self, fn, fs = None): """Read the given file to parse the config. If fs = None, then we're being given a raw config file rather than a disk image.""" - + if not os.access(fn, os.R_OK): raise RuntimeError, "Unable to access %s" %(fn,) if platform.machine() == 'ia64': - cfg_list = map(lambda x: (x,grub.LiloConf.LiloConfigFile), + cfg_list = map(lambda x: (x,grub.LiloConf.LiloConfigFile), # common distributions - ["/efi/debian/elilo.conf", "/efi/gentoo/elilo.conf", - "/efi/redflag/elilo.conf", "/efi/redhat/elilo.conf", - "/efi/SuSE/elilo.conf",] + + ["/efi/debian/elilo.conf", "/efi/gentoo/elilo.conf", + "/efi/redflag/elilo.conf", "/efi/redhat/elilo.conf", + "/efi/SuSE/elilo.conf",] + # fallbacks ["/efi/boot/elilo.conf", "/elilo.conf",]) else: @@ -442,7 +443,8 @@ class Grub: for f,parser in cfg_list: if fs.file_exists(f): - print >>sys.stderr, "Using %s to parse %s" % (parser,f) + if debug: + print >> sys.stderr, "Using %s to parse %s" % (parser,f) self.cf = parser() self.cf.filename = f break @@ -465,7 +467,7 @@ class Grub: while not self.isdone: self.run_main(timeout) timeout = -1 - + return self.selected_image def run_main(self, timeout = -1): @@ -495,7 +497,7 @@ class Grub: self.start_image = 0 while (timeout == -1 or mytime < int(timeout)): draw() - if timeout != -1 and mytime != -1: + if timeout != -1 and mytime != -1: self.screen.addstr(20, 5, "Will boot selected entry in %2d seconds" %(int(timeout) - mytime)) else: @@ -566,7 +568,7 @@ class Grub: self.selected_image = 0 elif self.selected_image >= len(self.cf.images): self.selected_image = len(self.cf.images) - 1 - + def get_entry_idx(cf, entry): # first, see if the given entry is numeric try: @@ -601,7 +603,7 @@ def run_grub(file, entry, fs, arg): if entry is not None: idx = get_entry_idx(g.cf, entry) if idx is not None and idx > 0 and idx < len(g.cf.images): - sel = idx + sel = idx if sel == -1: print "No kernel image selected!" @@ -651,10 +653,10 @@ def sniff_solaris(fs, cfg): # Unpleasant. Typically we'll have 'root=foo -k' or 'root=foo /kernel -k', # and we need to maintain Xen properties (root= and ip=) and the kernel # before any user args. - + xenargs = "" userargs = "" - + if not cfg["args"]: cfg["args"] = cfg["kernel"] else: @@ -666,7 +668,7 @@ def sniff_solaris(fs, cfg): cfg["args"] = xenargs + " " + cfg["kernel"] + " " + userargs return cfg - + def sniff_netware(fs, cfg): if not fs.file_exists("/nwserver/xnloader.sys"): return cfg @@ -683,7 +685,7 @@ def format_sxp(kernel, ramdisk, args): if args: s += "(args \"%s\")" % args return s - + def format_simple(kernel, ramdisk, args, sep): s = ("kernel %s" % kernel) + sep if ramdisk: @@ -693,9 +695,19 @@ def format_simple(kernel, ramdisk, args, s += sep return s +def init_log(): + logger = logging.getLogger() + handler = logging.handlers.SysLogHandler(address='/dev/log') + file_format = ('[%(asctime)s %(process)d] %(levelname)s ' + '(%(module)s:%(lineno)d) %(message)s') + handler.setFormatter(logging.Formatter(file_format)) + logger.addHandler(handler) + logger.setLevel(logging.DEBUG) + if __name__ == "__main__": + init_log() sel = None - + def usage(): print >> sys.stderr, "Usage: %s [-q|--quiet] [-i|--interactive] [-n|--not-really] [--output=] [--kernel=] [--ramdisk=] [--args=] [--entry=] [--output-directory=] [--output-format=sxp|simple|simple0] <image>" %(sys.argv[0],) @@ -732,9 +744,9 @@ if __name__ == "__main__": try: opts, args = getopt.gnu_getopt(sys.argv[1:], 'qinh::', - ["quiet", "interactive", "not-really", "help", + ["quiet", "interactive", "not-really", "help", "output=", "output-format=", "output-directory=", - "entry=", "kernel=", + "entry=", "kernel=", "ramdisk=", "args=", "isconfig", "debug"]) except getopt.GetoptError: usage() @@ -744,7 +756,7 @@ if __name__ == "__main__": usage() sys.exit(1) file = args[0] - + output = None entry = None interactive = True @@ -783,9 +795,7 @@ if __name__ == "__main__": entry = a # specifying the entry to boot implies non-interactive interactive = False - elif o in ("--isconfig",): - isconfig = True - elif o in ("--debug",): + elif o in ("--debug", "--isconfig"): debug = True elif o in ("--output-format",): if a not in ["sxp", "simple", "simple0"]: @@ -796,96 +806,88 @@ if __name__ == "__main__": elif o in ("--output-directory",): output_directory = a - if debug: - logging.basicConfig(level=logging.DEBUG) + try: + if output is None or output == "-": + fd = sys.stdout.fileno() + else: + fd = os.open(output, os.O_WRONLY) - if output is None or output == "-": - fd = sys.stdout.fileno() - else: - fd = os.open(output, os.O_WRONLY) + # if boot filesystem is set then pass to fsimage.open + bootfsargs = '"%s"' % incfg["args"] + bootfsgroup = re.findall('zfs-bootfs=(.*?)[\s\,\"]', bootfsargs) + if bootfsgroup: + bootfsoptions = bootfsgroup[0] + else: + bootfsoptions = "" - # debug - if isconfig: - chosencfg = run_grub(file, entry, fs, incfg["args"]) - print " kernel: %s" % chosencfg["kernel"] + # get list of offsets into file which start partitions + part_offs = get_partition_offsets(file) + + for offset in part_offs: + try: + fs = fsimage.open(file, offset, bootfsoptions) + + chosencfg = sniff_solaris(fs, incfg) + + if not chosencfg["kernel"]: + chosencfg = sniff_netware(fs, incfg) + + if not chosencfg["kernel"]: + chosencfg = run_grub(file, entry, fs, incfg["args"]) + + # Break as soon as we've found the kernel so that we continue + # to use this fsimage object + if chosencfg["kernel"]: + break + fs = None + + except Exception, err: + # IOErrors raised by fsimage.open + # RuntimeErrors raised by run_grub if no menu.lst present + if debug: + logging.exception(err) + fs = None + continue + + # Did looping through partitions find us a kernel? + if not fs: + raise RuntimeError, "Unable to find partition containing kernel" + + bootcfg["kernel"] = copy_from_image(fs, chosencfg["kernel"], "kernel", + output_directory, not_really) + if chosencfg["ramdisk"]: - print " initrd: %s" % chosencfg["ramdisk"] - print " args: %s" % chosencfg["args"] - sys.exit(0) + try: + bootcfg["ramdisk"] = copy_from_image(fs, chosencfg["ramdisk"], + "ramdisk", output_directory, + not_really) + except: + if not not_really: + os.unlink(bootcfg["kernel"]) + raise + else: + initrd = None - # if boot filesystem is set then pass to fsimage.open - bootfsargs = '"%s"' % incfg["args"] - bootfsgroup = re.findall('zfs-bootfs=(.*?)[\s\,\"]', bootfsargs) - if bootfsgroup: - bootfsoptions = bootfsgroup[0] - else: - bootfsoptions = "" + args = None + if chosencfg["args"]: + zfsinfo = fsimage.getbootstring(fs) + if zfsinfo is not None: + e = re.compile("zfs-bootfs=[\w\-\.\:@/]+" ) + (chosencfg["args"],count) = e.subn(zfsinfo, chosencfg["args"]) + if count == 0: + chosencfg["args"] += " -B %s" % zfsinfo + args = chosencfg["args"] - # get list of offsets into file which start partitions - part_offs = get_partition_offsets(file) + if output_format == "sxp": + ostring = format_sxp(bootcfg["kernel"], bootcfg["ramdisk"], args) + elif output_format == "simple": + ostring = format_simple(bootcfg["kernel"], bootcfg["ramdisk"], args, "\n") + elif output_format == "simple0": + ostring = format_simple(bootcfg["kernel"], bootcfg["ramdisk"], args, "\0") - for offset in part_offs: - try: - fs = fsimage.open(file, offset, bootfsoptions) - - chosencfg = sniff_solaris(fs, incfg) - - if not chosencfg["kernel"]: - chosencfg = sniff_netware(fs, incfg) - - if not chosencfg["kernel"]: - chosencfg = run_grub(file, entry, fs, incfg["args"]) - - # Break as soon as we've found the kernel so that we continue - # to use this fsimage object - if chosencfg["kernel"]: - break - fs = None - - except: - # IOErrors raised by fsimage.open - # RuntimeErrors raised by run_grub if no menu.lst present - if debug: - traceback.print_exc() - fs = None - continue - - # Did looping through partitions find us a kernel? - if not fs: - raise RuntimeError, "Unable to find partition containing kernel" - - bootcfg["kernel"] = copy_from_image(fs, chosencfg["kernel"], "kernel", - output_directory, not_really) - - if chosencfg["ramdisk"]: - try: - bootcfg["ramdisk"] = copy_from_image(fs, chosencfg["ramdisk"], - "ramdisk", output_directory, - not_really) - except: - if not not_really: - os.unlink(bootcfg["kernel"]) - raise - else: - initrd = None - - args = None - if chosencfg["args"]: - zfsinfo = fsimage.getbootstring(fs) - if zfsinfo is not None: - e = re.compile("zfs-bootfs=[\w\-\.\:@/]+" ) - (chosencfg["args"],count) = e.subn(zfsinfo, chosencfg["args"]) - if count == 0: - chosencfg["args"] += " -B %s" % zfsinfo - args = chosencfg["args"] - - if output_format == "sxp": - ostring = format_sxp(bootcfg["kernel"], bootcfg["ramdisk"], args) - elif output_format == "simple": - ostring = format_simple(bootcfg["kernel"], bootcfg["ramdisk"], args, "\n") - elif output_format == "simple0": - ostring = format_simple(bootcfg["kernel"], bootcfg["ramdisk"], args, "\0") - - sys.stdout.flush() - os.write(fd, ostring) - + sys.stdout.flush() + os.write(fd, ostring) + except Exception, err: + print >> sys.stderr, str(err) + logging.error(err) + sys.exit(1) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |