diff --git a/client/Makefile b/client/Makefile index a2c29561d..b629d2f87 100644 --- a/client/Makefile +++ b/client/Makefile @@ -21,7 +21,6 @@ install: install -m 644 solo/commands/*.py $(DESTDIR)/$(LIBDIR)/entropy/client/solo/commands/ install -m 644 revision $(DESTDIR)/$(LIBDIR)/entropy/client/ install -m 755 equo.py $(DESTDIR)/$(BINDIR)/equo - install -m 755 ../services/kernel-switcher $(DESTDIR)$(BINDIR)/ # copy zsh completion install -d $(DESTDIR)$(PREFIX)/share/zsh/site-functions diff --git a/docs/TODO b/docs/TODO index 2d482cf74..ff477e2c8 100644 --- a/docs/TODO +++ b/docs/TODO @@ -1,5 +1,9 @@ Short term: +- equo PDEPEND against kernel-switcher +- kernel-switcher RDEPEND against equo + + - use .ini-like layout for entropy config - conditional deps: diff --git a/kernel-switcher/Makefile b/kernel-switcher/Makefile new file mode 100644 index 000000000..b8456e201 --- /dev/null +++ b/kernel-switcher/Makefile @@ -0,0 +1,20 @@ +SUBDIRS = +PREFIX = /usr +BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +DESTDIR = + +all: + for d in $(SUBDIRS); do $(MAKE) -C $$d; done + +install: + install -d $(DESTDIR)/$(LIBDIR)/entropy/kernel-switcher + install -d $(DESTDIR)$(BINDIR) + + install -m 644 kswitch.py $(DESTDIR)/$(LIBDIR)/entropy/kernel-switcher/ + install -m 755 kernel-switcher $(DESTDIR)/$(BINDIR)/. + + for d in $(SUBDIRS); do $(MAKE) -C $$d install; done + +clean: + for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done diff --git a/kernel-switcher/kernel-switcher b/kernel-switcher/kernel-switcher new file mode 100755 index 000000000..9c0b2634d --- /dev/null +++ b/kernel-switcher/kernel-switcher @@ -0,0 +1,126 @@ +#!/usr/bin/python +import sys +sys.path.insert(0, "/usr/lib/entropy/lib") +sys.path.insert(0, "/usr/lib/entropy/client") +sys.path.insert(0, "/usr/lib/entropy/kernel-switcher") +sys.path.insert(0, "../lib") +sys.path.insert(0, "../client") +sys.path.insert(0, "../kernel-switcher") + +import os +import argparse + +from entropy.output import brown, print_warning, print_error +from entropy.i18n import _ +from entropy.client.interfaces import Client +import entropy.dep +import entropy.tools + +from solo.utils import print_package_info + +import kswitch + + +if __name__ == "__main__": + + app_name = os.path.basename(sys.argv[0]) + parser = argparse.ArgumentParser( + description=_("Sabayon Kernel Switcher"), + formatter_class=argparse.RawDescriptionHelpFormatter, + prog=app_name) + + def _add_standard_args(_parser, restricted): + _parser.add_argument("--quiet", "-q", action="store_true", + default=False, + help=_("quiet mode")) + _parser.add_argument("--verbose", "-v", action="store_true", + default=False, + help=_("verbose mode")) + if not restricted: + _parser.add_argument("--ask", "-a", action="store_true", + default=False, + help=_("ask confirmation")) + _parser.add_argument("--pretend", "-p", action="store_true", + default=False, + help=_("just show what would be done")) + + subparsers = parser.add_subparsers( + title="kernel-switcher", + description=_("available commands")) + + def _wrap_locked_api(method, *args, **kwargs): + etp_client = None + acquired = False + try: + etp_client = Client() + acquired = entropy.tools.acquire_entropy_locks(etp_client) + if not acquired: + print_error(brown(_("Another Entropy is currently running."))) + return 1 + return method(etp_client, *args, **kwargs) + finally: + if acquired and (etp_client is not None): + entropy.tools.release_entropy_locks(etp_client) + if etp_client is not None: + etp_client.shutdown() + + def _switch_kernel(f_nsargs): + return _wrap_locked_api( + kswitch.switch_kernel, + f_nsargs.kernel, pretend=f_nsargs.pretend, + ask=f_nsargs.ask, verbose=f_nsargs.verbose, + quiet=f_nsargs.quiet, + from_running=f_nsargs.from_running) + + def _list_kernels(f_nsargs): + + def _list(etp_client): + kernels = kswitch.list_kernels(etp_client) + if not kernels: + print_warning(_("No kernel packages found")) + return 1 + for pkg_id, pkg_repo in kernels: + repo = etp_client.open_repository(pkg_repo) + print_package_info( + pkg_id, etp_client, repo, + show_repo_if_quiet = True, + extended=f_nsargs.verbose, + quiet=f_nsargs.quiet) + return 0 + + return _wrap_locked_api(_list) + + switch_parser = subparsers.add_parser( + "switch", help=_("install a new or just another kernel")) + switch_parser.set_defaults(func=_switch_kernel) + switch_parser.add_argument( + "--from-running", action="store_true", + default=False, + help=_("use 'uname -r' to determine the running kernel")) + switch_parser.add_argument( + "kernel", metavar="", + help=_("the new kernel package dependency name")) + _add_standard_args(switch_parser, False) + + list_parser = subparsers.add_parser( + "list", help=_("list kernels")) + list_parser.set_defaults(func=_list_kernels) + _add_standard_args(list_parser, True) + + help_parser = subparsers.add_parser( + "help", help=_("this help")) + def _print_help(*_args): + parser.print_help() + help_parser.set_defaults(func=_print_help) + + try: + nsargs = parser.parse_args(sys.argv[1:]) + except IOError as err: + parser.print_help() + raise SystemExit(1) + + try: + rc = nsargs.func(nsargs) + except KeyboardInterrupt: + rc = 1 + raise SystemExit(rc) diff --git a/kernel-switcher/kswitch.py b/kernel-switcher/kswitch.py new file mode 100644 index 000000000..5bc53f743 --- /dev/null +++ b/kernel-switcher/kswitch.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +""" + + @author: Fabio Erculiani + @contact: lxnay@sabayon.org + @copyright: Fabio Erculiani + @license: GPL-2 + + B{System Kernel Switch Utility Library for Sabayon}. + +""" + +import os +import subprocess +import errno +import codecs + +from entropy.const import etpConst, const_convert_to_unicode, \ + const_convert_to_rawstring +from entropy.exceptions import DependenciesNotRemovable +from entropy.i18n import _ +from entropy.output import teal, purple, darkgreen, brown, print_info, \ + red, print_warning, print_error +import entropy.dep +import entropy.tools + +from solo.commands.install import SoloInstall + + +KERNEL_BINARY_VIRTUAL = const_convert_to_unicode("virtual/linux-binary") +KERNELS_DIR = const_convert_to_rawstring("/etc/kernels") +RELEASE_LEVEL = const_convert_to_rawstring("RELEASE_LEVEL") + + +def _get_kernels(entropy_client): + matches, x_rc = entropy_client.atom_match(KERNEL_BINARY_VIRTUAL, + multi_match = True, multi_repo = True) + return matches, x_rc + + +def _remove_tag_from_slot(slot): + if not hasattr(entropy.dep, "remove_tag_from_slot"): + # backward compatibility + return slot[::-1].split(",", 1)[-1][::-1] + return entropy.dep.remove_tag_from_slot(slot) + + +def _get_target_tag(entropy_client, kernel_match): + try: + matches = entropy_client.get_reverse_queue([kernel_match], + recursive = False) + except DependenciesNotRemovable: + # wtf should not happen + raise + tags = set() + for pkg_id, pkg_repo in matches: + tag = entropy_client.open_repository(pkg_repo).retrieveTag(pkg_id) + if tag: + tags.add(tag) + + if tags: + tags = sorted(tags, reverse = True) + return tags.pop(0) + + +def _setup_kernel_symlink(target_tag): + eselect_exec = "/usr/bin/eselect" + if os.access(eselect_exec, os.X_OK): + subprocess.call((eselect_exec, "kernel", "set", target_tag)) + + +def _guess_kernel_name(kernel_atom): + """ + This method takes advantage of Entropy kernel package info files available + at /etc/kernels/-/ directory. + This function tries to read uname -r from the RELEASE_LEVEL file. + """ + namever = entropy.dep.remove_cat(kernel_atom) + kernel_meta_file = os.path.join(KERNELS_DIR, namever, RELEASE_LEVEL) + if os.path.isfile(kernel_meta_file): + try: + with open(kernel_meta_file, "r") as km_f: + kernel_name = km_f.readline().strip() + if kernel_name: + return kernel_name + except (OSError, IOError): + return None + + +def _guess_kernel_package_file(release_level): + """ + This method takes advantage of Entropy kernel package info files available + at /etc/kernels/-/ directory looking for + a RELEASE_LEVEL file whose content matches release_level (uname -r). + """ + if not os.path.isdir(KERNELS_DIR): + return None + + subs = [] + for _curdir, subs, _files in os.walk(KERNELS_DIR): + subs.extend(subs) + + for sub in subs: + sub_path = os.path.join(KERNELS_DIR, sub) + try: + dir_list = os.listdir(sub_path) + except OSError as err: + if err.errno != errno.ENOENT: + raise + continue + if RELEASE_LEVEL not in dir_list: + continue + + level_path = os.path.join( + sub_path, RELEASE_LEVEL) + with codecs.open( + level_path, "r", etpConst["conf_raw_encoding"]) as rel_f: + rel_line = rel_f.readline().strip() + + if release_level == rel_line: + return const_convert_to_unicode(level_path) + + +def _get_opengl_impl(pretend): + eselect_exec = "/usr/bin/eselect" + sts = 1 + out = "xorg-x11" + if os.access(eselect_exec, os.X_OK) and not pretend: + sts, xout = entropy.tools.getstatusoutput("%s opengl show" % ( + eselect_exec,)) + if sts == 0: + out = xout + return out + + +def _set_opengl_impl(opengl): + eselect_exec = "/usr/bin/eselect" + if os.access(eselect_exec, os.X_OK): + args = (eselect_exec, "opengl", "set", opengl) + subprocess.call(args) + + +def _show_kernel_warnings(kernel_atom): + print_info("%s %s" % (purple(kernel_atom), teal(_("has been installed.")))) + print_warning("%s: %s" % (red(_("Attention")), + brown(_("some external drivers cannot work across multiple kernels.")))) + print_warning(darkgreen(_("Please reboot your computer now !"))) + + +def switch_kernel(entropy_client, kernel_package, from_running=False, + pretend=False, ask=False, verbose=False, quiet=False): + """ + Execute a kernel switch to the given kernel package. + Caller is expected to acquire any relevant Entropy lock before + calling this function. + + @param entropy_client: an Entropy Client object instance + @type entropy_client: entropy.client.interfaces.Client + @param kernel_package: a kernel package dependency string + @type kernel_package: string + @keyword from_running: if True, determine the current kernel from the + running system + @type from_running: bool + @keyword pretend: if True, show what would be done + @type pretend: bool + @keyword ask: if True, ask interactively + @type ask: bool + @keyword verbose: if True, be more verbose + @type verbose: bool + @keyword quiet: if True, be more quiet + @type quiet: bool + """ + pkg_id, pkg_repo = entropy_client.atom_match(kernel_package) + if pkg_id == -1: + print_error("%s: %s" % (brown(_("Package does not exist")), + teal(kernel_package),)) + return 1 + kernel_matches, rc = _get_kernels(entropy_client) + + kernel_match = (pkg_id, pkg_repo) + if kernel_match not in kernel_matches: + print_error("%s: %s" % (brown(_("Not a kernel")), + teal(kernel_package),)) + return 1 + + kernel_atom = entropy_client.open_repository(pkg_repo).retrieveAtom(pkg_id) + # this can be None ! + target_tag = _get_target_tag(entropy_client, kernel_match) + + inst_repo = entropy_client.installed_repository() + # try to look for the currently running kernel first if + # --from-running is specified (use uname -r) + latest_kernel = -1 + if from_running: + try: + uname_r = os.uname()[2] + except OSError: + uname_r = None + except IndexError: + uname_r = None + + pkg_file = None + if uname_r is not None: + pkg_file = _guess_kernel_package_file(uname_r) + if pkg_file is not None: + _pkg_ids = list(inst_repo.searchBelongs(pkg_file)) + # if more than one, get the latest + _pkg_ids.sort(reverse=True) + if _pkg_ids: + latest_kernel = _pkg_ids[0] + if latest_kernel == -1: + print_error( + brown(_("Cannot find your currently running kernel."))) + print_error( + brown(_("Try without --from-running."))) + return 1 + + if latest_kernel == -1: + latest_kernel, _k_rc = inst_repo.atomMatch( + KERNEL_BINARY_VIRTUAL) + installed_revdeps = [] + if (latest_kernel != -1) and target_tag: + installed_revdeps = entropy_client.get_removal_queue( + [latest_kernel], recursive = False) + + # only pull in packages that are installed at this time. + def _installed_pkgs_translator(inst_pkg_id): + if inst_pkg_id == latest_kernel: + # will be added later + return None + key, slot = inst_repo.retrieveKeySlot(inst_pkg_id) + target_slot = _remove_tag_from_slot(slot) + "," + target_tag + + pkg_id, pkg_repo = entropy_client.atom_match(key, + match_slot = target_slot) + if pkg_id == -1: + return None + return pkg_id, pkg_repo + + matches = map(_installed_pkgs_translator, installed_revdeps) + matches = [x for x in matches if x is not None] + matches.append(kernel_match) + + opengl = _get_opengl_impl(pretend) + + install = SoloInstall([]) + rc, _show_cfgupd = install._install_action( + entropy_client, True, True, + pretend, ask, verbose, + quiet, False, False, False, False, False, + False, False, 1, [], package_matches=list(matches)) + if _show_cfgupd: + install._show_config_files_update(entropy_client) + + if rc == 0 and not pretend: + _set_opengl_impl(opengl) + if target_tag: + # if target_tag is None, we are unable to set the symlink + _setup_kernel_symlink(target_tag) + else: + # try to guess, sigh, for now + guessed_kernel_name = _guess_kernel_name(kernel_atom) + if guessed_kernel_name: + _setup_kernel_symlink(guessed_kernel_name) + _show_kernel_warnings(kernel_atom) + return rc + + +def list_kernels(entropy_client): + """ + Return a sorted (by atom) list of currently available + kernels. + + @param entropy_client: an Entropy Client object instance + @type entropy_client: entropy.client.interfaces.Client + @return: a sorted list of Entropy package matches + @rtype: list + """ + matches, _rc = _get_kernels(entropy_client) + key_sorter = lambda x: \ + entropy_client.open_repository(x[1]).retrieveAtom(x[0]) + return sorted(matches, key=key_sorter) diff --git a/services/kernel-switcher b/services/kernel-switcher deleted file mode 100755 index 3f1619109..000000000 --- a/services/kernel-switcher +++ /dev/null @@ -1,352 +0,0 @@ -#!/usr/bin/python -import sys -sys.path.insert(0, '/usr/lib/entropy/lib') -sys.path.insert(0, '/usr/lib/entropy/server') -sys.path.insert(0, '/usr/lib/entropy/client') -sys.path.insert(0, '../lib') -sys.path.insert(0, '../server') -sys.path.insert(0, '../client') - -import os -import subprocess -import errno -import codecs -import argparse - -from entropy.const import etpConst, const_convert_to_unicode, \ - const_convert_to_rawstring -from entropy.output import teal, purple, darkgreen, blue, brown, print_info, \ - red, nocolor, print_warning, print_error -from entropy.exceptions import DependenciesNotRemovable -from entropy.i18n import _ -from entropy.client.interfaces import Client -import entropy.dep -import entropy.tools - -# solo modules -from solo.commands.install import SoloInstall -from solo.utils import print_package_info - -APP_NAME = os.path.basename(sys.argv[0]) -KERNEL_BINARY_VIRTUAL = const_convert_to_unicode("virtual/linux-binary") -KERNELS_DIR = const_convert_to_rawstring("/etc/kernels") -RELEASE_LEVEL = const_convert_to_rawstring("RELEASE_LEVEL") - -def _get_kernels(etp_client): - matches, x_rc = etp_client.atom_match(KERNEL_BINARY_VIRTUAL, - multi_match = True, multi_repo = True) - return matches, x_rc - -def _remove_tag_from_slot(slot): - if not hasattr(entropy.dep, "remove_tag_from_slot"): - # backward compatibility - return slot[::-1].split(",", 1)[-1][::-1] - return entropy.dep.remove_tag_from_slot(slot) - -def _get_target_tag(etp_client, kernel_match): - try: - matches = etp_client.get_reverse_queue([kernel_match], - recursive = False) - except DependenciesNotRemovable: - # wtf should not happen - raise - tags = set() - for pkg_id, pkg_repo in matches: - tag = etp_client.open_repository(pkg_repo).retrieveTag(pkg_id) - if tag: - tags.add(tag) - - if tags: - tags = sorted(tags, reverse = True) - return tags.pop(0) - -def _setup_kernel_symlink(target_tag): - eselect_exec = "/usr/bin/eselect" - if os.access(eselect_exec, os.X_OK): - subprocess.call((eselect_exec, "kernel", "set", target_tag)) - -def _guess_kernel_name(kernel_atom): - """ - This method takes advantage of Entropy kernel package info files available - at /etc/kernels/-/ directory. - This function tries to read uname -r from the RELEASE_LEVEL file. - """ - namever = entropy.dep.remove_cat(kernel_atom) - kernel_meta_file = os.path.join(KERNELS_DIR, namever, RELEASE_LEVEL) - if os.path.isfile(kernel_meta_file): - try: - with open(kernel_meta_file, "r") as km_f: - kernel_name = km_f.readline().strip() - if kernel_name: - return kernel_name - except (OSError, IOError): - return None - -def _guess_kernel_package_file(release_level): - """ - This method takes advantage of Entropy kernel package info files available - at /etc/kernels/-/ directory looking for - a RELEASE_LEVEL file whose content matches release_level (uname -r). - """ - if not os.path.isdir(KERNELS_DIR): - return None - - subs = [] - for curdir, _subs, files in os.walk(KERNELS_DIR): - subs.extend(_subs) - - for sub in subs: - sub_path = os.path.join(KERNELS_DIR, sub) - try: - dir_list = os.listdir(sub_path) - except OSError as err: - if err.errno != errno.ENOENT: - raise - continue - if RELEASE_LEVEL not in dir_list: - continue - - level_path = os.path.join( - sub_path, RELEASE_LEVEL) - with codecs.open( - level_path, "r", etpConst['conf_raw_encoding']) as rel_f: - rel_line = rel_f.readline().strip() - - if release_level == rel_line: - return const_convert_to_unicode(level_path) - -# removing and installing proprietary drivers might reset the selected -# OpenGL implementation - -def _get_opengl_impl(pretend): - eselect_exec = "/usr/bin/eselect" - sts = 1 - out = "xorg-x11" - if os.access(eselect_exec, os.X_OK) and not pretend: - sts, xout = entropy.tools.getstatusoutput("%s opengl show" % ( - eselect_exec,)) - if sts == 0: - out = xout - return out - -def _set_opengl_impl(opengl): - eselect_exec = "/usr/bin/eselect" - if os.access(eselect_exec, os.X_OK): - args = (eselect_exec, "opengl", "set", opengl) - subprocess.call(args) - -def _show_kernel_warnings(kernel_atom): - print_info("%s %s" % (purple(kernel_atom), teal(_("has been installed.")))) - print_warning("%s: %s" % (red(_("Attention")), - brown(_("some external drivers cannot work across multiple kernels.")))) - print_warning(darkgreen(_("Please reboot your computer now !"))) - -def _switch_kernel(nsargs): - - from_running = nsargs.from_running - kernel_package = nsargs.kernel - pretend = nsargs.pretend - ask = nsargs.ask - verbose = nsargs.verbose - quiet = nsargs.quiet - - etp_client = None - acquired = False - try: - etp_client = Client() - acquired = entropy.tools.acquire_entropy_locks(etp_client) - if not acquired: - print_error(brown(_("Another Entropy is currently running."))) - return 1 - - pkg_id, pkg_repo = etp_client.atom_match(kernel_package) - if pkg_id == -1: - print_error("%s: %s" % (brown(_("Package does not exist")), - teal(kernel_package),)) - return 1 - kernel_matches, rc = _get_kernels(etp_client) - - kernel_match = (pkg_id, pkg_repo) - if kernel_match not in kernel_matches: - print_error("%s: %s" % (brown(_("Not a kernel")), - teal(kernel_package),)) - return 1 - - kernel_atom = etp_client.open_repository(pkg_repo).retrieveAtom(pkg_id) - # this can be None ! - target_tag = _get_target_tag(etp_client, kernel_match) - - inst_repo = etp_client.installed_repository() - # try to look for the currently running kernel first if - # --from-running is specified (use uname -r) - latest_kernel = -1 - k_rc = 1 - if from_running: - try: - uname_r = os.uname()[2] - except OSError: - uname_r = None - except IndexError: - uname_r = None - - pkg_file = None - if uname_r is not None: - pkg_file = _guess_kernel_package_file(uname_r) - if pkg_file is not None: - _pkg_ids = list(inst_repo.searchBelongs(pkg_file)) - # if more than one, get the latest - _pkg_ids.sort(reverse=True) - if _pkg_ids: - latest_kernel = _pkg_ids[0] - if latest_kernel == -1: - print_error( - brown(_("Cannot find your currently running kernel."))) - print_error( - brown(_("Try without --from-running."))) - return 1 - - if latest_kernel == -1: - latest_kernel, k_rc = inst_repo.atomMatch( - KERNEL_BINARY_VIRTUAL) - installed_revdeps = [] - if (latest_kernel != -1) and target_tag: - installed_revdeps = etp_client.get_removal_queue( - [latest_kernel], recursive = False) - - # only pull in packages that are installed at this time. - def _installed_pkgs_translator(inst_pkg_id): - if inst_pkg_id == latest_kernel: - # will be added later - return None - key, slot = inst_repo.retrieveKeySlot(inst_pkg_id) - target_slot = _remove_tag_from_slot(slot) + "," + target_tag - - pkg_id, pkg_repo = etp_client.atom_match(key, - match_slot = target_slot) - if pkg_id == -1: - return None - return pkg_id, pkg_repo - - matches = map(_installed_pkgs_translator, installed_revdeps) - matches = [x for x in matches if x is not None] - matches.append(kernel_match) - - opengl = _get_opengl_impl(pretend) - - install = SoloInstall([]) - rc, _show_cfgupd = install._install_action( - etp_client, True, True, - pretend, ask, verbose, - quiet, False, False, False, False, False, - False, 1, [], package_matches=list(matches)) - if _show_cfgupd: - install._show_config_files_update(etp_client) - - if rc == 0 and not pretend: - _set_opengl_impl(opengl) - if target_tag: - # if target_tag is None, we are unable to set the symlink - _setup_kernel_symlink(target_tag) - else: - # try to guess, sigh, for now - guessed_kernel_name = _guess_kernel_name(kernel_atom) - if guessed_kernel_name: - _setup_kernel_symlink(guessed_kernel_name) - _show_kernel_warnings(kernel_atom) - return rc - - finally: - if acquired and (etp_client is not None): - entropy.tools.release_entropy_locks(etp_client) - if etp_client is not None: - etp_client.shutdown() - -def _list_kernels(nsargs): - etp_client = None - acquired = False - try: - etp_client = Client() - acquired = entropy.tools.acquire_entropy_locks(etp_client) - if not acquired: - print_error(brown(_("Another Entropy is currently running."))) - return 1 - matches, rc = _get_kernels(etp_client) - if (rc != 0) or (not matches): - print_warning(_("No kernel packages found")) - return 1 - - key_sorter = lambda x: \ - etp_client.open_repository(x[1]).retrieveAtom(x[0]) - for pkg_id, pkg_repo in sorted(matches, key = key_sorter): - repo = etp_client.open_repository(pkg_repo) - print_package_info(pkg_id, etp_client, repo, - show_repo_if_quiet = True, extended = nsargs.verbose, - quiet = nsargs.quiet) - - return 0 - finally: - if acquired and (etp_client is not None): - entropy.tools.release_entropy_locks(etp_client) - if etp_client is not None: - etp_client.shutdown() - -if __name__ == "__main__": - - parser = argparse.ArgumentParser( - description=_("Sabayon Kernel Switcher"), - formatter_class=argparse.RawDescriptionHelpFormatter, - prog=APP_NAME) - - def _add_standard_args(_parser, restricted): - _parser.add_argument("--quiet", "-q", action="store_true", - default=False, - help=_("quiet mode")) - _parser.add_argument("--verbose", "-v", action="store_true", - default=False, - help=_("verbose mode")) - if not restricted: - _parser.add_argument("--ask", "-a", action="store_true", - default=False, - help=_("ask confirmation")) - _parser.add_argument("--pretend", "-p", action="store_true", - default=False, - help=_("just show what would be done")) - - subparsers = parser.add_subparsers( - title="kernel-switcher", - description=_("available commands")) - - switch_parser = subparsers.add_parser( - "switch", help=_("install a new or just another kernel")) - switch_parser.set_defaults(func=_switch_kernel) - switch_parser.add_argument( - "--from-running", action="store_true", - default=False, - help=_("use 'uname -r' to determine the running kernel")) - switch_parser.add_argument( - "kernel", metavar="", - help=_("the new kernel package dependency name")) - _add_standard_args(switch_parser, False) - - list_parser = subparsers.add_parser( - "list", help=_("list kernels")) - list_parser.set_defaults(func=_list_kernels) - _add_standard_args(list_parser, True) - - help_parser = subparsers.add_parser( - "help", help=_("this help")) - def _print_help(*args): - parser.print_help() - help_parser.set_defaults(func=_print_help) - - try: - nsargs = parser.parse_args(sys.argv[1:]) - except IOError as err: - parser.print_help() - raise SystemExit(1) - - try: - rc = nsargs.func(nsargs) - except KeyboardInterrupt: - rc = 1 - raise SystemExit(rc)