diff options
-rw-r--r-- | cloudinit/config/cc_keyboard.py | 125 | ||||
-rwxr-xr-x | cloudinit/distros/__init__.py | 15 | ||||
-rw-r--r-- | cloudinit/distros/debian.py | 7 | ||||
-rw-r--r-- | config/cloud.cfg.tmpl | 1 | ||||
-rw-r--r-- | doc/rtd/topics/modules.rst | 1 | ||||
-rw-r--r-- | tests/integration_tests/modules/test_keyboard.py | 17 | ||||
-rw-r--r-- | tests/unittests/config/test_schema.py | 1 | ||||
-rw-r--r-- | tools/.github-cla-signers | 1 |
8 files changed, 168 insertions, 0 deletions
diff --git a/cloudinit/config/cc_keyboard.py b/cloudinit/config/cc_keyboard.py new file mode 100644 index 00000000..17eb9a54 --- /dev/null +++ b/cloudinit/config/cc_keyboard.py @@ -0,0 +1,125 @@ +# Copyright (c) 2022 Floris Bos +# +# Author: Floris Bos <bos@je-eigen-domein.nl> +# +# This file is part of cloud-init. See LICENSE file for license information. + +"""keyboard: set keyboard layout""" + +from textwrap import dedent + +from cloudinit import distros +from cloudinit import log as logging +from cloudinit.config.schema import get_meta_doc, validate_cloudconfig_schema +from cloudinit.settings import PER_INSTANCE + +frequency = PER_INSTANCE + +# FIXME: setting keyboard layout should be supported by all OSes. +# But currently only implemented for Linux distributions that use systemd. +osfamilies = ["arch", "debian", "redhat", "suse"] +distros = distros.Distro.expand_osfamily(osfamilies) + +DEFAULT_KEYBOARD_MODEL = "pc105" + +meta = { + "id": "cc_keyboard", + "name": "Keyboard", + "title": "Set keyboard layout", + "description": dedent( + """\ + Handle keyboard configuration. + """ + ), + "distros": distros, + "examples": [ + dedent( + """\ + # Set keyboard layout to "us" + keyboard: + layout: us + """ + ), + dedent( + """\ + # Set specific keyboard layout, model, variant, options + keyboard: + layout: de + model: pc105 + variant: nodeadkeys + options: compose:rwin + """ + ), + ], + "frequency": frequency, +} + + +schema = { + "type": "object", + "properties": { + "keyboard": { + "type": "object", + "properties": { + "layout": { + "type": "string", + "description": dedent( + """\ + Required. Keyboard layout. Corresponds to XKBLAYOUT. + """ + ), + }, + "model": { + "type": "string", + "default": DEFAULT_KEYBOARD_MODEL, + "description": dedent( + """\ + Optional. Keyboard model. Corresponds to XKBMODEL. + """ + ), + }, + "variant": { + "type": "string", + "description": dedent( + """\ + Optional. Keyboard variant. Corresponds to XKBVARIANT. + """ + ), + }, + "options": { + "type": "string", + "description": dedent( + """\ + Optional. Keyboard options. Corresponds to XKBOPTIONS. + """ + ), + }, + }, + "required": ["layout"], + "additionalProperties": False, + } + }, +} + +__doc__ = get_meta_doc(meta, schema) + +LOG = logging.getLogger(__name__) + + +def handle(name, cfg, cloud, log, args): + if "keyboard" not in cfg: + LOG.debug( + "Skipping module named %s, no 'keyboard' section found", name + ) + return + validate_cloudconfig_schema(cfg, schema) + kb_cfg = cfg["keyboard"] + layout = kb_cfg["layout"] + model = kb_cfg.get("model", DEFAULT_KEYBOARD_MODEL) + variant = kb_cfg.get("variant", "") + options = kb_cfg.get("options", "") + LOG.debug("Setting keyboard layout to '%s'", layout) + cloud.distro.set_keymap(layout, model, variant, options) + + +# vi: ts=4 expandtab diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index de000b52..a261c16e 100755 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -881,6 +881,21 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): cmd = list(init_cmd) + list(cmds[action]) return subp.subp(cmd, capture=True) + def set_keymap(self, layout, model, variant, options): + if self.uses_systemd(): + subp.subp( + [ + "localectl", + "set-x11-keymap", + layout, + model, + variant, + options, + ] + ) + else: + raise NotImplementedError() + def _apply_hostname_transformations_to_url(url: str, transformations: list): """ diff --git a/cloudinit/distros/debian.py b/cloudinit/distros/debian.py index 9effa0a0..6dc1ad40 100644 --- a/cloudinit/distros/debian.py +++ b/cloudinit/distros/debian.py @@ -300,6 +300,13 @@ class Distro(distros.Distro): def get_primary_arch(self): return util.get_dpkg_architecture() + def set_keymap(self, layout, model, variant, options): + # Let localectl take care of updating /etc/default/keyboard + distros.Distro.set_keymap(self, layout, model, variant, options) + # Workaround for localectl not applying new settings instantly + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=926037 + self.manage_service("restart", "console-setup") + def _get_wrapper_prefix(cmd, mode): if isinstance(cmd, str): diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl index 741b23d5..37c223f3 100644 --- a/config/cloud.cfg.tmpl +++ b/config/cloud.cfg.tmpl @@ -107,6 +107,7 @@ cloud_config_modules: {% endif %} {% if variant not in ["photon"] %} - ssh-import-id + - keyboard - locale {% endif %} - set-passwords diff --git a/doc/rtd/topics/modules.rst b/doc/rtd/topics/modules.rst index 3ca6b9e3..8ee4fe57 100644 --- a/doc/rtd/topics/modules.rst +++ b/doc/rtd/topics/modules.rst @@ -23,6 +23,7 @@ Modules .. automodule:: cloudinit.config.cc_growpart .. automodule:: cloudinit.config.cc_grub_dpkg .. automodule:: cloudinit.config.cc_install_hotplug +.. automodule:: cloudinit.config.cc_keyboard .. automodule:: cloudinit.config.cc_keys_to_console .. automodule:: cloudinit.config.cc_landscape .. automodule:: cloudinit.config.cc_locale diff --git a/tests/integration_tests/modules/test_keyboard.py b/tests/integration_tests/modules/test_keyboard.py new file mode 100644 index 00000000..7db35014 --- /dev/null +++ b/tests/integration_tests/modules/test_keyboard.py @@ -0,0 +1,17 @@ +import pytest + +USER_DATA = """\ +#cloud-config +keyboard: + layout: de + model: pc105 + variant: nodeadkeys + options: compose:rwin +""" + + +class TestKeyboard: + @pytest.mark.user_data(USER_DATA) + def test_keyboard(self, client): + lc = client.execute("localectl") + assert "X11 Layout: de" in lc diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py index 822efe5a..93206bdd 100644 --- a/tests/unittests/config/test_schema.py +++ b/tests/unittests/config/test_schema.py @@ -87,6 +87,7 @@ class GetSchemaTest(CiTestCase): "cc_apk_configure", "cc_apt_configure", "cc_bootcmd", + "cc_keyboard", "cc_locale", "cc_ntp", "cc_resizefs", diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers index e4b64b0d..62e6017a 100644 --- a/tools/.github-cla-signers +++ b/tools/.github-cla-signers @@ -52,6 +52,7 @@ mamercad manuelisimo marlluslustosa matthewruffell +maxnet mitechie nazunalika nicolasbock |