* [PATCH] pygrub: add syslog support to pygrub
@ 2012-07-19 18:19 Zhigang Wang
2012-07-19 19:07 ` Ian Campbell
0 siblings, 1 reply; 3+ messages in thread
From: Zhigang Wang @ 2012-07-19 18:19 UTC (permalink / raw)
To: xen-devel; +Cc: Zhigang Wang
# HG changeset patch
# User Zhigang Wang <zhigang.x.wang@oracle.com>
# 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@oracle.com>
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)
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] pygrub: add syslog support to pygrub
2012-07-19 18:19 [PATCH] pygrub: add syslog support to pygrub Zhigang Wang
@ 2012-07-19 19:07 ` Ian Campbell
2012-07-19 19:39 ` Zhigang Wang
0 siblings, 1 reply; 3+ messages in thread
From: Ian Campbell @ 2012-07-19 19:07 UTC (permalink / raw)
To: Zhigang Wang; +Cc: xen-devel
On Thu, 2012-07-19 at 19:19 +0100, Zhigang Wang wrote:
> # HG changeset patch
> # User Zhigang Wang <zhigang.x.wang@oracle.com>
> # 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.
Actual xl in unstable will log to /var/log/xen/bootloader.<domid>.log
(or something like that) and print a message on failure directing the
user to it.
> This patch will log the error message to syslog.
I suppose there is no harm in also (optionally?) logging to syslog as
well, but I think we want to keep the messages to stdout also.
> Also in this patch:
>
> 1). Fix indentation for some lines.
> 2). Removed some trailing spaces.
These two make up the vast bulk of the changes and really obscure the
actual functional changes.
Please can you do this cleanup in a separate patch.
> 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.
This should also be a separate patch.
I think all of this is 4.3 material and will therefore have to wait
until 4.2 branches. Please can you resend at that point.
Ian.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] pygrub: add syslog support to pygrub
2012-07-19 19:07 ` Ian Campbell
@ 2012-07-19 19:39 ` Zhigang Wang
0 siblings, 0 replies; 3+ messages in thread
From: Zhigang Wang @ 2012-07-19 19:39 UTC (permalink / raw)
To: Ian Campbell; +Cc: xen-devel
On 07/19/2012 03:07 PM, Ian Campbell wrote:
> On Thu, 2012-07-19 at 19:19 +0100, Zhigang Wang wrote:
>> # HG changeset patch
>> # User Zhigang Wang <zhigang.x.wang@oracle.com>
>> # 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.
> Actual xl in unstable will log to /var/log/xen/bootloader.<domid>.log
> (or something like that) and print a message on failure directing the
> user to it.
I see. But it seems the design is wrong: you want all logs in stderr.
>
>> This patch will log the error message to syslog.
> I suppose there is no harm in also (optionally?) logging to syslog as
> well, but I think we want to keep the messages to stdout also.
I think we should: logs to syslog, errors to stderr.
>
>> Also in this patch:
>>
>> 1). Fix indentation for some lines.
>> 2). Removed some trailing spaces.
> These two make up the vast bulk of the changes and really obscure the
> actual functional changes.
>
> Please can you do this cleanup in a separate patch.
>
>> 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.
> This should also be a separate patch.
>
> I think all of this is 4.3 material and will therefore have to wait
> until 4.2 branches. Please can you resend at that point.
>
> Ian.
I can do it on 4.3.
Thanks,
Zhigang
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-07-19 19:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-19 18:19 [PATCH] pygrub: add syslog support to pygrub Zhigang Wang
2012-07-19 19:07 ` Ian Campbell
2012-07-19 19:39 ` Zhigang Wang
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.