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 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):

View File

@ -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)

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.
#
#
# 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<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):
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<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):
"""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()