[Fedora-livecd-list] livecd-creator doesn't honor keyboard settings in f19

Joshua C. joshuacov at gmail.com
Wed Aug 7 22:09:25 UTC 2013


2013/8/7 Joshua C. <joshuacov at gmail.com>:
> 2013/8/6 Brian C. Lane <bcl at redhat.com>:
>> On Mon, Aug 05, 2013 at 11:28:46PM +0200, Joshua C. wrote:
>>> 2013/8/5 Brian C. Lane <bcl at redhat.com>:
>>> > On Mon, Aug 05, 2013 at 07:57:23PM +0200, Joshua C. wrote:
>>> >> I tried all of the following in my kickstart file:
>>> >>
>>> >> keyboard --vconsole=de-latin1-nodeadkyes --xlayouts='de (nodeadkyes)' de
>>> >>
>>> >> as well as any possible combination of these. In all cases my custom
>>> >> f19-livecd-kde image was created with "layout=us"!!!
>>> >>
>>> >> I have:
>>> >> lang en_US.utf-8
>>> >> keyboard --vconsole=de-latin1-nodeadkyes --xlayouts='de (nodeadkyes)' de
>>> >> timezone Europe/Paris
>>> >>
>>> >> I also looked in the official i18l-kickstarts and the
>>> >> anaconda/kickstart wiki - without luck.
>>> >>
>>> >> What am I missing?
>>> >
>>> > Nothing. It doesn't work. The underlying package we used to depend on
>>> > changed to use dbus, which doesn't work very well when running from
>>> > inside a mock. So I kludged in a temporary fix that really only works
>>> > with us. If anyone has suggestions for a general fix I'm open to
>>> > suggestions.
>>> >
>>> > --
>>> > Brian C. Lane | Anaconda Team | IRC: bcl #anaconda | Port Orchard, WA (PST8PDT)
>>> >
>>> > --
>>> > livecd mailing list
>>> > livecd at lists.fedoraproject.org
>>> > https://admin.fedoraproject.org/mailman/listinfo/livecd
>>>
>>>
>>> I just switched from f17 to f19 and this is the first bad surprise to
>>> find out. Anyway, which package did the creator depend on? I can at
>>> least look at it.
>>
>> system-config-keyboard
>>
>> I also see that I mis-typed that as system config kickstart in the
>> commit message :/ (commit f674482986d701ddc21120fa8f9b0249095cdeec)
>>
>> --
>> Brian C. Lane | Anaconda Team | IRC: bcl #anaconda | Port Orchard, WA (PST8PDT)
>>
>> --
>> livecd mailing list
>> livecd at lists.fedoraproject.org
>> https://admin.fedoraproject.org/mailman/listinfo/livecd
>
> I made a simple patch to restore the missing functionality. The patch
> adds a modified keyboard.py file and call the appropriate functions
> from within livecd-creator. However for some reason the written
> configs aren't read during boot?!?
>
> /etc/sysconfig/vconsole.conf has the desired settings but my keyboard
> still keeps the us layout.
>
> Any ideas?
>
> From 43716accadb8bbe63c6b3b76045dd0d5c193407c Mon Sep 17 00:00:00 2001
> From: Live System User <liveuser at localhost.localdomain>
> Date: Wed, 7 Aug 2013 20:42:58 +0200
> Subject: [PATCH] honor keyboard settings
>
> ---
>  imgcreate/keyboard_old.py | 188 ++++++++++++++++++++++++++++++++++++++++++++++
>  imgcreate/kickstart.py    |  13 +++-
>  2 files changed, 197 insertions(+), 4 deletions(-)
>  create mode 100644 imgcreate/keyboard_old.py
>
> diff --git a/imgcreate/keyboard_old.py b/imgcreate/keyboard_old.py
> new file mode 100644
> index 0000000..be458d9
> --- /dev/null
> +++ b/imgcreate/keyboard_old.py
> @@ -0,0 +1,188 @@
> +#
> +# keyboard_old.py - keyboard backend data object
> +#
> +# Brent Fox <bfox at redhat.com>
> +# Mike Fulbright <msf at redhat.com>
> +# Jeremy Katz <katzj at redhat.com>
> +# Lubomir Rintel <lkundrak at v3.sk>
> +#
> +# Copyright 2002 Red Hat, Inc.
> +# Copyright 2009 Lubomir Rintel
> +#
> +# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
> +#
> +
> +import dbus
> +import string
> +import os
> +from subprocess import call
> +import system_config_keyboard.keyboard_models as keyboard_models
> +
> +class Keyboard_old():
> +    def __init__(self):
> +        self._mods = keyboard_models.KeyboardModels()
> +
> +        self.type = "PC"
> +        self.beenset = 0
> +        self.config = []
> +        self.loadkeys = ""
> +        self.setxkbmap = ""
> +
> +        # default to us
> +        self.set("us")
> +
> +        try:
> +            bus = dbus.SystemBus()
> +            hal =
> dbus.Interface(bus.get_object("org.freedesktop.Hal","/org/freedesktop/Hal/Manager"),"org.freedesktop.Hal.Manager")
> +            kbs = hal.FindDeviceByCapability("input.keyboard")
> +            if len(kbs) == 0:
> +                self.type = "Serial"
> +            else:
> +                self._var ("KEYBOARDTYPE", "pc")
> +            kb = dbus.Interface(bus.get_object("org.freedesktop.Hal",
> kbs[0]), 'org.freedesktop.Hal.Device')
> +            if kb.GetPropertyString("info.product").startswith("Sun Type"):
> +                self.type == "Sun"
> +                self._var ("KEYBOARDTYPE", "sun")
> +        except:
> +            pass
> +
> +    def _get_models(self):
> +        return self._mods.get_models()
> +    modelDict = property(_get_models)
> +
> +    def _var (self, name, value = None):
> +        found = 0
> +        for line in self.config:
> +                if line[1] == name:
> +                        found = 1
> +                        break
> +        if not found:
> +                line = [None, None, None]
> +        # get or set?
> +        if not value:
> +            return line[2]
> +        line[1:3] = (name, value)
> +        line[0] = '{0}="{1}"\n'.format (name, value)
> +        if not found:
> +                self.config.append (line)
> +
> +    def set(self, keytable):
> +        if self.type != "Serial":
> +            kb = self.modelDict[keytable]
> +            self._var ("KEYTABLE", keytable)
> +            self._var ("MODEL", kb[2])
> +            self._var ("LAYOUT", kb[1])
> +            self._var ("VARIANT", kb[3])
> +            self._var ("OPTIONS", kb[4])
> +
> +    def get(self):
> +        return self._var ("KEYTABLE")
> +
> +    def getKeymapName(self):
> +        kbd = self.modelDict[self.get()]
> +        if not kbd:
> +            return ""
> +        (name, layout, model, variant, options) = kbd
> +        return name
> +
> +    def __getitem__(self, item):
> +        table = self._var ("KEYTABLE")
> +        if not self.modelDict.has_key(table):
> +            raise KeyError, "No such keyboard type %s" % (table,)
> +
> +        kb = self.modelDict[table]
> +        if item == "rules":
> +            return "xorg"
> +        elif item == "model":
> +            return kb[2]
> +        elif item == "layout":
> +            return kb[1]
> +        elif item == "variant":
> +            return kb[3]
> +        elif item == "options":
> +            return kb[4]
> +        elif item == "name":
> +            return kb[0]
> +        elif item == "keytable":
> +            return table
> +        else:
> +            raise KeyError, item
> +
> +    def read(self, instPath = "/"):
> +        try:
> +            file = open(instPath + "/etc/sysconfig/keyboard", "r")
> +        except:
> +            return
> +        self.config = []
> +        while 1:
> +                line = file.readline ()
> +                if not line:
> +                        break
> +                (name, value) = line.rstrip("\n").split ('=')
> +                self.config.append ([line, name, value.strip ('"'), 0])
> +        self.beenset = 1
> +
> +    def write(self, instPath = "/"):
> +    file = open(instPath + "/etc/sysconfig/keyboard", "w")
> +    for line in self.config:
> +                file.write (line[0]);
> +        try:
> +            os.unlink(instPath + "/etc/sysconfig/console/default.kmap")
> +        except:
> +            pass
> +
> +    def writeKS(self, f):
> +        f.write("keyboard %s\n" % (self.get(),))
> +
> +    def activate(self):
> +        # XXX do isys.loadkeys
> +        console_kbd = self.get()
> +        if not console_kbd:
> +            return
> +
> +        # Call loadkeys to change the console keymap
> +        if os.access("/bin/loadkeys", os.X_OK):
> +            command = "/bin/loadkeys"
> +        elif os.access("/usr/bin/loadkeys", os.X_OK):
> +            command = "/usr/bin/loadkeys"
> +        else:
> +            command = "/bin/loadkeys"
> +        argv = [ command, console_kbd ]
> +
> +        if os.access(argv[0], os.X_OK) == 1:
> +            self.loadkeys = argv
> +
> +        try:
> +            kbd = self.modelDict[console_kbd]
> +        except KeyError:
> +            return
> +
> +        if not kbd:
> +            return
> +        (name, layout, model, variant, options) = kbd
> +
> +        # XXX set the X keyboard map even if X isn't running
> +
> +        argv = [ "/usr/bin/setxkbmap", "-layout", layout ]
> +
> +        # XXX setxkbmap(1) needs one -option flag for each option
> +        if options:
> +            argv = argv + [ "-option", options ]
> +
> +        if variant:
> +            argv = argv + [ "-variant", variant ]
> +
> +        if os.access(argv[0], os.X_OK) == 1:
> +            self.setxkbmap = argv
> diff --git a/imgcreate/kickstart.py b/imgcreate/kickstart.py
> index 1059801..46ba09d 100644
> --- a/imgcreate/kickstart.py
> +++ b/imgcreate/kickstart.py
> @@ -25,10 +25,7 @@ import logging
>  import urlgrabber
>  import selinux
>
> -try:
> -    import system_config_keyboard.keyboard as keyboard
> -except ImportError:
> -    import rhpl.keyboard as keyboard
> +import keyboard_old as keyboard
>
>  import pykickstart.commands as kscommands
>  import pykickstart.constants as ksconstants
> @@ -153,6 +150,14 @@ class KeyboardConfig(KickstartConfig):
>                  f.write('FONT="%s"\n' % DEFAULT_VC_FONT)
>          except IOError as e:
>              logging.error("Cannot write vconsole configuration file: %s" % e)
> +
> +        k = keyboard.Keyboard_old()
> +        if kskeyboard.keyboard:
> +            k.set(kskeyboard.keyboard)
> +        k.write(self.instroot)
> +        k.activate()
> +        self.call(k.loadkeys)
> +        self.call(k.setxkbmap)
>
>  class TimezoneConfig(KickstartConfig):
>      """A class to apply a kickstart timezone configuration to a system."""
> --
> 1.8.3.1
>
>
>
> --
> --joshua


I came up with a better solution. The activate() method in the above
patch doesn't work in chroot because X isn't running. That's why we
get an error. We can delete the method as well as the following from
kickstart.py:
-        self.call(k.loadkeys)
-        self.call(k.setxkbmap)

Without these we have a configured keyboard settings written in
/etc/sysconfig/keyboard. Now what we need to do is to read the file
after X has started and apply the settings. My simplest solution is
adding the following code to /etc/init.d/livesys (just edit the
corresponding kickstart file -in my case fedora-live-base-kde.ks)

cat > /etc/X11/xinit/xinitrc.d/set-my-keyboard.sh << KEYBOARD_EOF
#!/bin/bash
/usr/bin/setxkbmap -layout `cat /etc/sysconfig/keyboard | grep LAYOUT
| cut -d "=" -f2`
KEYBOARD_EOF

This can be further refined to take into account all options written
in /etc/sysconfig/keyboard. A better solution can be to implement the
activate() method here. With all these our settings are applied at
boot and we are not dependent on system-config-keyboard anymore.

I hope someone to refine this further.

-- 
--joshua


More information about the livecd mailing list