virtinst: util: Move keymap stuff to its own file

This commit is contained in:
Cole Robinson 2013-04-13 16:31:13 -04:00
parent abbc828b70
commit d5f466d558
5 changed files with 211 additions and 201 deletions

View File

@ -20,7 +20,6 @@
import re import re
import os import os
from virtinst import util
from virtinst.VirtualDevice import VirtualDevice from virtinst.VirtualDevice import VirtualDevice
from virtinst import support from virtinst import support
from virtinst.XMLBuilderDomain import _xml_property from virtinst.XMLBuilderDomain import _xml_property
@ -71,9 +70,9 @@ class VirtualGraphics(VirtualDevice):
""" """
Return a list of valid keymap values. 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 = [] sort_list = []
orig_list.sort() orig_list.sort()
@ -138,7 +137,8 @@ class VirtualGraphics(VirtualDevice):
return None return None
if self._local_keymap == -1: 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 return self._local_keymap
def get_type(self): def get_type(self):

View File

@ -1757,6 +1757,8 @@ def parse_graphics(guest, optstring, dev=None):
return None return None
def sanitize_keymap(keymap): def sanitize_keymap(keymap):
from virtinst import hostkeymap
if not keymap: if not keymap:
return None return None
if keymap.lower() == "local": if keymap.lower() == "local":
@ -1764,7 +1766,7 @@ def parse_graphics(guest, optstring, dev=None):
if keymap.lower() == "none": if keymap.lower() == "none":
return None return None
use_keymap = util.check_keytable(keymap) use_keymap = hostkeymap.sanitize_keymap(keymap)
if not use_keymap: if not use_keymap:
raise ValueError( raise ValueError(
_("Didn't match keymap '%s' in keytable!") % keymap) _("Didn't match keymap '%s' in keytable!") % keymap)

204
virtinst/hostkeymap.py Normal file
View File

@ -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<kt>[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<kt>[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

View File

@ -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",
}

View File

@ -18,11 +18,6 @@
# MA 02110-1301 USA. # 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 commands
import logging import logging
import os import os
@ -384,50 +379,6 @@ def parse_node_helper(xml, root_name, callback, exec_class=ValueError):
return ret 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<kt>[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): def generate_uuid(conn):
for ignore in range(256): for ignore in range(256):
uuid = randomUUID(conn=conn) uuid = randomUUID(conn=conn)
@ -436,13 +387,6 @@ def generate_uuid(conn):
logging.error("Failed to generate non-conflicting UUID") 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): def default_route(nic=None):
@ -602,82 +546,6 @@ def xml_escape(xml):
return 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<kt>[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): def is_storage_capable(conn):
"""check if virConnectPtr passed has storage API support""" """check if virConnectPtr passed has storage API support"""
from virtinst import support from virtinst import support
@ -747,33 +615,6 @@ def lookup_pool_by_path(conn, path):
return None 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(): def _test():
import doctest import doctest
doctest.testmod() doctest.testmod()