From 80a5ae708a8e7f9972e8394606e279393be40657 Mon Sep 17 00:00:00 2001 From: JF Ding Date: Thu, 18 Aug 2011 11:12:28 +0800 Subject: [PATCH] add msger.py for all unified colored message output and some code cleanup --- mic/chroot.py | 14 +++--- mic/configmgr.py | 9 ++-- mic/creator.py | 4 +- mic/msger.py | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ mic/utils/fs_related.py | 5 ++- mic/utils/kickstart.py | 8 +--- tests/micng.conf | 4 -- tools/mic | 2 +- 8 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 mic/msger.py delete mode 100644 tests/micng.conf diff --git a/mic/chroot.py b/mic/chroot.py index 319839f..8b519e7 100644 --- a/mic/chroot.py +++ b/mic/chroot.py @@ -25,6 +25,7 @@ import subprocess import mic.utils.fs_related as fs_related import mic.utils.misc as misc import mic.utils.errors as errors +from mic import msger BIND_MOUNTS = ( "/proc", @@ -75,7 +76,7 @@ def check_bind_mounts(chrootdir, bindmounts): tmpdir = chrootdir + "/" + srcdst[1] if os.path.isdir(tmpdir): - print "Warning: dir %s has existed." % tmpdir + msger.warning("Warning: dir %s has existed." % tmpdir) return True @@ -98,7 +99,7 @@ def cleanup_mounts(chrootdir): args = [ umountcmd, "-l", point ] ret = subprocess.call(args, stdout=dev_null, stderr=dev_null) if ret != 0: - print "ERROR: failed to unmount %s" % point + msger.warning("failed to unmount %s" % point) os.close(dev_null) return ret @@ -152,7 +153,7 @@ def setup_chrootenv(chrootdir, bindmounts = None): def bind_mount(chrootmounts): for b in chrootmounts: - print "bind_mount: %s -> %s" % (b.src, b.dest) + msger.info("bind_mount: %s -> %s" % (b.src, b.dest)) b.mount() def setup_resolv(chrootdir): @@ -179,7 +180,7 @@ def cleanup_chrootenv(chrootdir, bindmounts = None, globalmounts = []): def bind_unmount(chrootmounts): chrootmounts.reverse() for b in chrootmounts: - print "bind_unmount: %s -> %s" % (b.src, b.dest) + msger.info("bind_unmount: %s -> %s" % (b.src, b.dest)) b.unmount() def cleanup_resolv(chrootdir): @@ -219,7 +220,7 @@ def cleanup_chrootenv(chrootdir, bindmounts = None, globalmounts = []): if len(os.listdir(tmpdir)) == 0: shutil.rmtree(tmpdir, ignore_errors = True) else: - print "Warning: dir %s isn't empty." % tmpdir + msger.warning("Warning: dir %s isn't empty." % tmpdir) chroot_lockfd.close() bind_unmount(globalmounts) @@ -281,8 +282,7 @@ def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"): raise errors.CreatorError("Failed to get architecture from any of the following files %s from chroot." % files_to_check) try: - print "Launching shell. Exit to continue." - print "----------------------------------" + msger.info("Launching shell. Exit to continue.\n----------------------------------") globalmounts = setup_chrootenv(chrootdir, bindmounts) subprocess.call(execute, preexec_fn = mychroot, shell=True) diff --git a/mic/configmgr.py b/mic/configmgr.py index 7892591..69a7727 100644 --- a/mic/configmgr.py +++ b/mic/configmgr.py @@ -22,6 +22,7 @@ import logging import ConfigParser import mic.utils as utils import mic.utils.errors as errors +from mic import msger DEFAULT_GSITECONF='/etc/mic/mic.conf' @@ -58,7 +59,7 @@ class ConfigMgr(object): self._siteconf = siteconf if not self.siteconf: self._siteconf = DEFAULT_GSITECONF - + self._ksconf = ksconf def __set_siteconf(self, siteconf): @@ -112,10 +113,10 @@ class ConfigMgr(object): try: kickstart = utils.kickstart.read_kickstart(ksconf) ksrepos = utils.misc.get_repostrs_from_ks(kickstart) + msger.info("Retrieving repo metadata:") repometadata = utils.misc.get_metadata_from_repos(ksrepos, self.create['cachedir']) - sys.stdout.write("Retrieving repo metadata:\n") - sys.stdout.write("%s" % repometadata) - sys.stdout.flush() + msger.info("\nDONE") + self.create['ks'] = kickstart self.create['repomd'] = repometadata self.create['name'] = os.path.splitext(os.path.basename(ksconf))[0] diff --git a/mic/creator.py b/mic/creator.py index 1fe9895..92594f2 100644 --- a/mic/creator.py +++ b/mic/creator.py @@ -23,6 +23,7 @@ import logging import mic.utils.cmdln as cmdln import mic.configmgr as configmgr import mic.pluginmgr as pluginmgr +from mic import msger class Creator(cmdln.Cmdln): """${name}: create an image @@ -101,8 +102,7 @@ class Creator(cmdln.Cmdln): if args: if os.geteuid() != 0: - print >> sys.stderr, "You must run %s as root" % sys.argv[0] - return 1 + msger.error('Need root permission to run this command') return self.cmd(args) diff --git a/mic/msger.py b/mic/msger.py new file mode 100644 index 0000000..030d1f0 --- /dev/null +++ b/mic/msger.py @@ -0,0 +1,111 @@ +#!/usr/bin/python -tt +# vim: ai ts=4 sts=4 et sw=4 + +# Copyright (c) 2009 Intel Corporation +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# 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., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os,sys +import re + +__ALL__ = ['set_mode', 'info', 'warning', 'error', 'ask'] + +# COLORs in ANSI +INFO_COLOR = 32 # green +WARN_COLOR = 33 # yellow +ERR_COLOR = 31 # red +ASK_COLOR = 34 # blue + +PREFIX_RE = re.compile('^<(.*?)>\s*(.*)') + +INTERACTIVE = True + +def _color_print(head, color, msg = None, stream = sys.stdout): + + colored = True + if not stream.isatty(): + colored = False + elif os.getenv('ANSI_COLORS_DISABLED') is not None: + colored = False + + if colored: + head = '\033[%dm%s:\033[0m' %(color, head) + else: + head += ':' + + if msg: + stream.write('%s %s\n' % (head, msg)) + else: + stream.write('%s ' % head) + +def _color_perror(head, color, msg): + _color_print(head, color, msg, sys.stderr) + +def _split_msg(head, msg): + if msg.startswith('\n'): + msg = msg.lstrip() + head = '\n' + head + + m = PREFIX_RE.match(msg) + if m: + head += ' <%s>' % m.group(1) + msg = m.group(2) + return head, msg + +def set_mode(interactive): + global INTERACTIVE + if interactive: + INTERACTIVE = True + else: + INTERACTIVE = False + +def info(msg): + head, msg = _split_msg('Info', msg) + _color_print(head, INFO_COLOR, msg) + +def warning(msg): + head, msg = _split_msg('Warning', msg) + _color_perror(head, WARN_COLOR, msg) + +def error(msg): + head, msg = _split_msg('Error', msg) + _color_perror(head, ERR_COLOR, msg) + sys.exit(1) + +def ask(msg, default=True): + _color_print('Q', ASK_COLOR, '') + try: + if default: + msg += '(Y/n) ' + else: + msg += '(y/N) ' + if INTERACTIVE: + repl = raw_input(msg) + if repl.lower() == 'y': + return True + elif repl.lower() == 'n': + return False + else: + return default + + else: + sys.stdout.write('%s ' % msg) + if default: + sys.stdout.write('Y\n') + else: + sys.stdout.write('N\n') + return default + except KeyboardInterrupt: + sys.stdout.write('\n') + sys.exit(2) diff --git a/mic/utils/fs_related.py b/mic/utils/fs_related.py index e73d67c..6b9a684 100644 --- a/mic/utils/fs_related.py +++ b/mic/utils/fs_related.py @@ -33,6 +33,7 @@ import termios from errors import * from urlgrabber.grabber import URLGrabber from urlgrabber.grabber import URLGrabError +from mic import msger def terminal_width(fd=1): """ Get the real terminal width """ @@ -59,7 +60,7 @@ class TextProgress(object): if self.total is None: sys.stdout.write("\rRetrieving %s ..." % truncate_url(self.url, self.termwidth - 15)) else: - sys.stdout.write("\rRetrieving %s (%d|%d) ..." % (truncate_url(self.url, self.termwidth - 25), self.counter, self.total)) + sys.stdout.write("\rRetrieving %s [%d/%d] ..." % (truncate_url(self.url, self.termwidth - 25), self.counter, self.total)) else: sys.stdout.write("Retrieving %s ..." % truncate_url(self.url, self.termwidth - 15)) @@ -921,7 +922,7 @@ def load_module(module): found = True break if not found: - print "Loading %s..." % module + msger.info("Loading %s..." % module) dev_null = os.open("/dev/null", os.O_WRONLY) modprobecmd = find_binary_path("modprobe") modprobe = subprocess.Popen([modprobecmd, module], diff --git a/mic/utils/kickstart.py b/mic/utils/kickstart.py index 827cc52..b26605f 100644 --- a/mic/utils/kickstart.py +++ b/mic/utils/kickstart.py @@ -16,7 +16,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import os +import os, sys import os.path import shutil import subprocess @@ -24,8 +24,6 @@ import time import logging import string -#import rhpl.keyboard - import pykickstart.commands as kscommands import pykickstart.constants as ksconstants import pykickstart.errors as kserrors @@ -40,9 +38,7 @@ import kscommands.desktop as desktop import kscommands.moblinrepo as moblinrepo import kscommands.micboot as micboot -import sys -sys.path.append("~/0509/mic") -import misc as misc +import misc def read_kickstart(path): """Parse a kickstart file and return a KickstartParser instance. diff --git a/tests/micng.conf b/tests/micng.conf deleted file mode 100644 index 69e77bf..0000000 --- a/tests/micng.conf +++ /dev/null @@ -1,4 +0,0 @@ -[main] -cache=./cache -outdir=. -tmpdir=/var/tmp diff --git a/tools/mic b/tools/mic index e9e9582..893831d 100755 --- a/tools/mic +++ b/tools/mic @@ -36,7 +36,7 @@ class Mic(cmdln.Cmdln): Usage: mic SUBCOMMAND [OPTS] [ARGS...] Mic Image Creation Tool. - Try 'mic help SUBCOMAND' for help on a specific subcommand. + Try 'mic help SUBCOMAND' for help on a specific subcommand. ${command_list} global ${option_list} -- 2.7.4