From d5f466d55870ca7ac71e410d263587d1dd48fea8 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sat, 13 Apr 2013 16:31:13 -0400 Subject: [PATCH] virtinst: util: Move keymap stuff to its own file --- virtinst/VirtualGraphics.py | 8 +- virtinst/cli.py | 4 +- virtinst/hostkeymap.py | 204 ++++++++++++++++++++++++++++++++++++ virtinst/keytable.py | 37 ------- virtinst/util.py | 159 ---------------------------- 5 files changed, 211 insertions(+), 201 deletions(-) create mode 100644 virtinst/hostkeymap.py delete mode 100644 virtinst/keytable.py diff --git a/virtinst/VirtualGraphics.py b/virtinst/VirtualGraphics.py index 835d21d1a..b0a4db883 100644 --- a/virtinst/VirtualGraphics.py +++ b/virtinst/VirtualGraphics.py @@ -20,7 +20,6 @@ import re import os -from virtinst import util from virtinst.VirtualDevice import VirtualDevice from virtinst import support from virtinst.XMLBuilderDomain import _xml_property @@ -71,9 +70,9 @@ class VirtualGraphics(VirtualDevice): """ Return a list of valid keymap values. """ - from virtinst import keytable + from virtinst import hostkeymap - orig_list = keytable.keytable.values() + orig_list = hostkeymap.keytable.values() sort_list = [] orig_list.sort() @@ -138,7 +137,8 @@ class VirtualGraphics(VirtualDevice): return None if self._local_keymap == -1: - self._local_keymap = util.default_keymap() + from virtinst import hostkeymap + self._local_keymap = hostkeymap.default_keymap() return self._local_keymap def get_type(self): diff --git a/virtinst/cli.py b/virtinst/cli.py index e8aa6d723..79fb3105d 100644 --- a/virtinst/cli.py +++ b/virtinst/cli.py @@ -1757,6 +1757,8 @@ def parse_graphics(guest, optstring, dev=None): return None def sanitize_keymap(keymap): + from virtinst import hostkeymap + if not keymap: return None if keymap.lower() == "local": @@ -1764,7 +1766,7 @@ def parse_graphics(guest, optstring, dev=None): if keymap.lower() == "none": return None - use_keymap = util.check_keytable(keymap) + use_keymap = hostkeymap.sanitize_keymap(keymap) if not use_keymap: raise ValueError( _("Didn't match keymap '%s' in keytable!") % keymap) diff --git a/virtinst/hostkeymap.py b/virtinst/hostkeymap.py new file mode 100644 index 000000000..6c80cb7c5 --- /dev/null +++ b/virtinst/hostkeymap.py @@ -0,0 +1,204 @@ +# +# Copyright 2006-2013 Red Hat, Inc. +# +# 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; either version 2 of the License, or +# (at your option) any later version. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA. +# + +import logging +import re + +# Host keytable entry : keymap name in qemu/xen +# Only use lower case entries: all lookups are .lower()'d +keytable = { + "ar": "ar", + "da": "da", "dk": "da", + "de": "de", + "de-ch": "de-ch", + "en-gb": "en-gb", "gb": "en-gb", "uk": "en-gb", + "en-us": "en-us", "us": "en-us", + "es": "es", + "et": "et", + "fi": "fi", "se_fi": "fi", + "fo": "fo", + "fr": "fr", + "fr-be": "fr-be", "be": "fr-be", + "fr-ca": "fr-ca", "ca": "fr-ca", + "fr-ch": "fr-ch", "fr_ch": "fr-ch", + "hr": "hr", + "hu": "hu", + "is": "is", + "it": "it", + "ja": "ja", "jp106": "ja", "jp": "ja", + "lt": "lt", + "lv": "lv", + "mk": "mk", + "nl": "nl", + "nl-be": "nl-be", + "no": "no", + "pl": "pl", + "pt": "pt", + "pt-br": "pt-br", "br": "pt-br", "br-abnt2": "pt-br", + "ru": "ru", + "sl": "sl", + "sv": "sv", + "th": "th", + "tr": "tr", +} + +KEYBOARD_DIR = "/etc/sysconfig/keyboard" +XORG_CONF = "/etc/X11/xorg.conf" +CONSOLE_SETUP_CONF = "/etc/default/console-setup" + + +def find_xkblayout(path): + """ + Reads a keyboard layout from a file that defines an XKBLAYOUT + variable, e.g. /etc/default/{keyboard,console-setup}. + The format of these files is such that they can be 'sourced' + in a shell script. + """ + + kt = None + try: + f = open(path, "r") + except IOError, e: + logging.debug('Could not open "%s": %s ', path, str(e)) + else: + keymap_re = re.compile(r'\s*XKBLAYOUT="(?P[a-z-]+)"') + for line in f: + m = keymap_re.match(line) + if m: + kt = m.group('kt') + break + else: + logging.debug("Didn't find keymap in '%s'!", path) + f.close() + return kt + + +def _find_keymap_from_etc_default(): + """ + Look under /etc/default for the host machine's keymap. + + This checks both /etc/default/keyboard and /etc/default/console-setup. + The former is used by Debian 6.0 (Squeeze) and later. The latter is + used by older versions of Debian, and Ubuntu. + """ + + KEYBOARD_DEFAULT = "/etc/default/keyboard" + paths = [KEYBOARD_DEFAULT, CONSOLE_SETUP_CONF] + for path in paths: + kt = find_xkblayout(path) + if kt is not None: + break + return kt + + +def _xorg_keymap(): + """Look in /etc/X11/xorg.conf for the host machine's keymap, and attempt to + map it to a keymap supported by qemu""" + + kt = None + try: + f = open(XORG_CONF, "r") + except IOError, e: + logging.debug('Could not open "%s": %s ', XORG_CONF, str(e)) + else: + keymap_re = re.compile(r'\s*Option\s+"XkbLayout"\s+"(?P[a-z-]+)"') + for line in f: + m = keymap_re.match(line) + if m: + kt = m.group('kt') + break + else: + logging.debug("Didn't find keymap in '%s'!", XORG_CONF) + f.close() + return kt + + +def default_keymap(): + """ + Look in various config files for the host machine's keymap, and attempt + to map it to a keymap supported by qemu + """ + # Set keymap to same as hosts + default = "en-us" + keymap = None + + kt = None + try: + f = open(KEYBOARD_DIR, "r") + except IOError, e: + logging.debug('Could not open "/etc/sysconfig/keyboard" ' + str(e)) + kt = _xorg_keymap() + if not kt: + kt = _find_keymap_from_etc_default() + else: + while 1: + s = f.readline() + if s == "": + break + if re.search("KEYTABLE", s) is not None or \ + (re.search("KEYBOARD", s) is not None and + re.search("KEYBOARDTYPE", s) is None): + if s.count('"'): + delim = '"' + elif s.count('='): + delim = '=' + else: + continue + kt = s.split(delim)[1].strip() + f.close() + + if kt is None: + logging.debug("Did not parse any usable keymapping.") + return default + + kt = kt.lower() + + keymap = sanitize_keymap(kt) + + if not keymap: + logging.debug("Didn't match keymap '%s' in keytable!", kt) + return default + + return keymap + + +def sanitize_keymap(kt): + """ + Make sure the passed keymap roughly matches something in keytable + """ + if kt.lower() in keytable: + return keytable[kt] + + # Try a more intelligent lookup: strip out all '-' and '_', sort + # the keytable keys putting the longest first, then compare + # by string prefix + def len_cmp(a, b): + return len(b) - len(a) + + clean_kt = kt.replace("-", "").replace("_", "") + sorted_keys = sorted(keytable.keys(), len_cmp) + + for key in sorted_keys: + origkey = key + key = key.replace("-", "").replace("_", "") + + if clean_kt.startswith(key): + return keytable[origkey] + + return None diff --git a/virtinst/keytable.py b/virtinst/keytable.py deleted file mode 100644 index 222b7a4ac..000000000 --- a/virtinst/keytable.py +++ /dev/null @@ -1,37 +0,0 @@ -# Host keytable entry : keymap name in qemu/xen -# Only use lower case entries: all lookups are .lower()'d -keytable = { - "ar": "ar", - "da": "da", "dk": "da", - "de": "de", - "de-ch": "de-ch", - "en-gb": "en-gb", "gb": "en-gb", "uk": "en-gb", - "en-us": "en-us", "us": "en-us", - "es": "es", - "et": "et", - "fi": "fi", "se_fi": "fi", - "fo": "fo", - "fr": "fr", - "fr-be": "fr-be", "be": "fr-be", - "fr-ca": "fr-ca", "ca": "fr-ca", - "fr-ch": "fr-ch", "fr_ch": "fr-ch", - "hr": "hr", - "hu": "hu", - "is": "is", - "it": "it", - "ja": "ja", "jp106": "ja", "jp": "ja", - "lt": "lt", - "lv": "lv", - "mk": "mk", - "nl": "nl", - "nl-be": "nl-be", - "no": "no", - "pl": "pl", - "pt": "pt", - "pt-br": "pt-br", "br": "pt-br", "br-abnt2": "pt-br", - "ru": "ru", - "sl": "sl", - "sv": "sv", - "th": "th", - "tr": "tr", -} diff --git a/virtinst/util.py b/virtinst/util.py index 79f435f3d..6270c0dde 100644 --- a/virtinst/util.py +++ b/virtinst/util.py @@ -18,11 +18,6 @@ # MA 02110-1301 USA. # -# -# Internal utility functions. These do NOT form part of the API and must -# not be used by clients. -# - import commands import logging import os @@ -384,50 +379,6 @@ def parse_node_helper(xml, root_name, callback, exec_class=ValueError): return ret -def find_xkblayout(path): - """ - Reads a keyboard layout from a file that defines an XKBLAYOUT - variable, e.g. /etc/default/{keyboard,console-setup}. - The format of these files is such that they can be 'sourced' - in a shell script. - """ - - kt = None - try: - f = open(path, "r") - except IOError, e: - logging.debug('Could not open "%s": %s ', path, str(e)) - else: - keymap_re = re.compile(r'\s*XKBLAYOUT="(?P[a-z-]+)"') - for line in f: - m = keymap_re.match(line) - if m: - kt = m.group('kt') - break - else: - logging.debug("Didn't find keymap in '%s'!", path) - f.close() - return kt - - -def find_keymap_from_etc_default(): - """ - Look under /etc/default for the host machine's keymap. - - This checks both /etc/default/keyboard and /etc/default/console-setup. - The former is used by Debian 6.0 (Squeeze) and later. The latter is - used by older versions of Debian, and Ubuntu. - """ - - KEYBOARD_DEFAULT = "/etc/default/keyboard" - paths = [KEYBOARD_DEFAULT, CONSOLE_SETUP_CONF] - for path in paths: - kt = find_xkblayout(path) - if kt is not None: - break - return kt - - def generate_uuid(conn): for ignore in range(256): uuid = randomUUID(conn=conn) @@ -436,13 +387,6 @@ def generate_uuid(conn): logging.error("Failed to generate non-conflicting UUID") -# -# These functions accidentally ended up in the API under virtinst.util -# - -KEYBOARD_DIR = "/etc/sysconfig/keyboard" -XORG_CONF = "/etc/X11/xorg.conf" -CONSOLE_SETUP_CONF = "/etc/default/console-setup" def default_route(nic=None): @@ -602,82 +546,6 @@ def xml_escape(xml): return xml -def _xorg_keymap(): - """Look in /etc/X11/xorg.conf for the host machine's keymap, and attempt to - map it to a keymap supported by qemu""" - - kt = None - try: - f = open(XORG_CONF, "r") - except IOError, e: - logging.debug('Could not open "%s": %s ', XORG_CONF, str(e)) - else: - keymap_re = re.compile(r'\s*Option\s+"XkbLayout"\s+"(?P[a-z-]+)"') - for line in f: - m = keymap_re.match(line) - if m: - kt = m.group('kt') - break - else: - logging.debug("Didn't find keymap in '%s'!", XORG_CONF) - f.close() - return kt - - -def _console_setup_keymap(): - """Look in /etc/default/console-setup for the host machine's keymap, and attempt to - map it to a keymap supported by qemu""" - return find_xkblayout(CONSOLE_SETUP_CONF) - - -def default_keymap(): - """Look in /etc/sysconfig for the host machine's keymap, and attempt to - map it to a keymap supported by qemu""" - - # Set keymap to same as hosts - default = "en-us" - keymap = None - - kt = None - try: - f = open(KEYBOARD_DIR, "r") - except IOError, e: - logging.debug('Could not open "/etc/sysconfig/keyboard" ' + str(e)) - kt = _xorg_keymap() - if not kt: - kt = find_keymap_from_etc_default() - else: - while 1: - s = f.readline() - if s == "": - break - if re.search("KEYTABLE", s) is not None or \ - (re.search("KEYBOARD", s) is not None and - re.search("KEYBOARDTYPE", s) is None): - if s.count('"'): - delim = '"' - elif s.count('='): - delim = '=' - else: - continue - kt = s.split(delim)[1].strip() - f.close() - - if kt is None: - logging.debug("Did not parse any usable keymapping.") - return default - - kt = kt.lower() - - keymap = check_keytable(kt) - - if not keymap: - logging.debug("Didn't match keymap '%s' in keytable!", kt) - return default - - return keymap - - def is_storage_capable(conn): """check if virConnectPtr passed has storage API support""" from virtinst import support @@ -747,33 +615,6 @@ def lookup_pool_by_path(conn, path): return None -def check_keytable(kt): - from virtinst import keytable - - keymap = None - # Try a simple lookup in the keytable - if kt.lower() in keytable.keytable: - return keytable.keytable[kt] - else: - # Try a more intelligent lookup: strip out all '-' and '_', sort - # the keytable keys putting the longest first, then compare - # by string prefix - def len_cmp(a, b): - return len(b) - len(a) - - clean_kt = kt.replace("-", "").replace("_", "") - sorted_keys = sorted(keytable.keytable.keys(), len_cmp) - - for key in sorted_keys: - origkey = key - key = key.replace("-", "").replace("_", "") - - if clean_kt.startswith(key): - return keytable.keytable[origkey] - - return keymap - - def _test(): import doctest doctest.testmod()