From 76a7c439c1a4d94a650cd7e169d4800176c179e2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 07:37:46 -0400 Subject: [PATCH 01/20] [displaymanager] Begin refactoring DM - Introduce a base-class to "do the stuff" for one specific display manager / desktop environment. --- src/modules/displaymanager/main.py | 42 +++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 47eb147ed..d45913d5c 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -23,16 +23,41 @@ # You should have received a copy of the GNU General Public License # along with Calamares. If not, see . +import abc import os -import collections import re import libcalamares import configparser -DesktopEnvironment = collections.namedtuple( - 'DesktopEnvironment', ['executable', 'desktop_file'] - ) +class DesktopEnvironment(metaclass=abc.ABCMeta): + """ + Desktop Environment base class. A subclass + implements DE maintainence for a specific DE. + """ + executable = None + desktop_file = None + + def find_desktop_environment(self, root_mount_point): + """ + Check if this environment is installed in the + target system at @p root_mount_point. + """ + return ( + os.path.exists("{!s}{!s}".format(root_mount_point, self.executable)) and + os.path.exists("{!s}/usr/share/xsessions/{!s}.desktop".format(root_mount_point, self.desktop_file)) + ) + + def __init__(self, exec, desktop): + self.executable = exec + self.desktop_file = desktop + +# Collect all the subclasses of DesktopEnvironment defined above, +desktop_environments = [ + c for c in globals().values() + if type(c) is abc.ABCMeta and issubclass(c, DesktopEnvironment) and c.desktop_file +] + desktop_environments = [ DesktopEnvironment('/usr/bin/startkde', 'plasma'), # KDE Plasma 5 @@ -63,14 +88,7 @@ def find_desktop_environment(root_mount_point): :return: """ for desktop_environment in desktop_environments: - if (os.path.exists("{!s}{!s}".format( - root_mount_point, desktop_environment.executable - ) - ) and os.path.exists( - "{!s}/usr/share/xsessions/{!s}.desktop".format( - root_mount_point, desktop_environment.desktop_file - ) - )): + if desktop_environment.find_desktop_environment(root_mount_point): return desktop_environment return None From f188c6f71b5fc4024485b005dde2b115199d7368 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 08:14:52 -0400 Subject: [PATCH 02/20] [displaymanager] Simplify DE class - The DE isn't being configured, and isn't where the complexity lies. Drop the ABC from it. --- src/modules/displaymanager/main.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index d45913d5c..e8ff86c4c 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -30,13 +30,16 @@ import libcalamares import configparser -class DesktopEnvironment(metaclass=abc.ABCMeta): +class DesktopEnvironment: """ - Desktop Environment base class. A subclass - implements DE maintainence for a specific DE. + Desktop Environment -- some utility functions for a desktop + environment (e.g. finding out if it is installed). This + is independent of the *Display Manager*, which is what + we're configuring in this module. """ - executable = None - desktop_file = None + def __init__(self, exec, desktop): + self.executable = exec + self.desktop_file = desktop def find_desktop_environment(self, root_mount_point): """ @@ -48,16 +51,6 @@ class DesktopEnvironment(metaclass=abc.ABCMeta): os.path.exists("{!s}/usr/share/xsessions/{!s}.desktop".format(root_mount_point, self.desktop_file)) ) - def __init__(self, exec, desktop): - self.executable = exec - self.desktop_file = desktop - -# Collect all the subclasses of DesktopEnvironment defined above, -desktop_environments = [ - c for c in globals().values() - if type(c) is abc.ABCMeta and issubclass(c, DesktopEnvironment) and c.desktop_file -] - desktop_environments = [ DesktopEnvironment('/usr/bin/startkde', 'plasma'), # KDE Plasma 5 From 7f47b2f9ca5970c5e9b90e735d66ff4ff896cdfc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 08:26:30 -0400 Subject: [PATCH 03/20] [displaymanager] Introduce class for DM configuration - Much like PackageManager, this is where the actual implementation of configuration methods will end up, for each supported DM. --- src/modules/displaymanager/main.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index e8ff86c4c..80ad2cd72 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -86,6 +86,40 @@ def find_desktop_environment(root_mount_point): return None +class DisplayManager(metaclass=abc.ABCMeta): + """ + Display Manager -- a base class for DM configuration. + """ + name = None + executable = None + + def have_dm(self, root_mount_point): + bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, self.executable) + sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, self.executable) + return ( + os.path.exists(bin_path) + or os.path.exists(sbin_path) + ) + + @abc.abstractmethod + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + """ + Configure the DM inside the given @p root_mount_point with + autologin (if @p do_autologin is True) for the given @p username. + If the DM supports it, set the default DE to @p default_desktop_environment + as well. + """ + + +# Collect all the subclasses of DisplayManager defined above, +# and index them based on the name property of each class. +display_managers = [ + (c.name, c) + for c in globals().values() + if type(c) is abc.ABCMeta and issubclass(c, DisplayManager) and c.name +] + + def have_dm(dm_name, root_mount_point): """ Checks if display manager is properly installed. From e1f7dbdbb96b59cf108747e4e94f65cdfa50e900 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 08:27:49 -0400 Subject: [PATCH 04/20] [displaymanager] Simplify do_autologin initialization --- src/modules/displaymanager/main.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 80ad2cd72..4ec7407f5 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -148,10 +148,7 @@ def set_autologin(username, :param default_desktop_environment: :param root_mount_point: """ - do_autologin = True - - if username is None: - do_autologin = False + do_autologin = (username is not None) if "mdm" == displaymanager: # Systems with MDM as Desktop Manager From 47b58083f79e7b519d38fd90491710777d561534 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 09:11:18 -0400 Subject: [PATCH 05/20] [displaymanager] Move setup_autologin to individual classes - Split the entire body of setup_autologin() to a method per implementation class. - Make the check for presence of a DM a class-method, since if it fails, instantiation is going to be useless. --- src/modules/displaymanager/main.py | 156 +++++++++++++++++++---------- 1 file changed, 101 insertions(+), 55 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 4ec7407f5..a9e8993ab 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -93,9 +93,13 @@ class DisplayManager(metaclass=abc.ABCMeta): name = None executable = None - def have_dm(self, root_mount_point): - bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, self.executable) - sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, self.executable) + @classmethod + def have_dm(cls, root_mount_point): + if cls.executable is None: + return True + + bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, cls.executable) + sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, cls.executable) return ( os.path.exists(bin_path) or os.path.exists(sbin_path) @@ -111,46 +115,11 @@ class DisplayManager(metaclass=abc.ABCMeta): """ -# Collect all the subclasses of DisplayManager defined above, -# and index them based on the name property of each class. -display_managers = [ - (c.name, c) - for c in globals().values() - if type(c) is abc.ABCMeta and issubclass(c, DisplayManager) and c.name -] +class DMmdm(DisplayManager): + name = "mdm" + executable = "mdm" - -def have_dm(dm_name, root_mount_point): - """ - Checks if display manager is properly installed. - - :param dm_name: - :param root_mount_point: - :return: - """ - bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, dm_name) - sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, dm_name) - return (os.path.exists(bin_path) - or os.path.exists(sbin_path) - ) - - -def set_autologin(username, - displaymanager, - default_desktop_environment, - root_mount_point): - """ - Enables automatic login for the installed desktop managers. - - :param username: - :param displaymanager: str - The displaymanager for which to configure autologin. - :param default_desktop_environment: - :param root_mount_point: - """ - do_autologin = (username is not None) - - if "mdm" == displaymanager: + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with MDM as Desktop Manager mdm_conf_path = os.path.join(root_mount_point, "etc/mdm/custom.conf") @@ -187,7 +156,12 @@ def set_autologin(username, else: mdm_conf.write('AutomaticLoginEnable=False\n') - if "gdm" == displaymanager: + +class DMgdm(DisplayManager): + name = "gdm" + executable = "gdm" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with GDM as Desktop Manager gdm_conf_path = os.path.join(root_mount_point, "etc/gdm/custom.conf") @@ -236,7 +210,12 @@ def set_autologin(username, userfile.write("Icon=\n") - if "kdm" == displaymanager: + +class DMkdm(DisplayManager): + name = "kdm" + executable = "kdm" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with KDM as Desktop Manager kdm_conf_path = os.path.join( root_mount_point, "usr/share/config/kdm/kdmrc" @@ -276,7 +255,12 @@ def set_autologin(username, "KDM config file {!s} does not exist".format(kdm_conf_path) ) - if "lxdm" == displaymanager: + +class DMlxdm(DisplayManager): + name = "lxdm" + executable = "lxdm" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with LXDM as Desktop Manager lxdm_conf_path = os.path.join(root_mount_point, "etc/lxdm/lxdm.conf") text = [] @@ -300,7 +284,12 @@ def set_autologin(username, "LXDM config file {!s} does not exist".format(lxdm_conf_path) ) - if "lightdm" == displaymanager: + +class DMlightdm(DisplayManager): + name = "lightdm" + executable = "lightdm" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with LightDM as Desktop Manager # Ideally, we should use configparser for the ini conf file, # but we just do a simple text replacement for now, as it @@ -342,7 +331,12 @@ def set_autologin(username, ) ) - if "slim" == displaymanager: + +class DMslim(DisplayManager): + name = "slim" + executable = "slim" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with Slim as Desktop Manager slim_conf_path = os.path.join(root_mount_point, "etc/slim.conf") text = [] @@ -369,7 +363,12 @@ def set_autologin(username, "SLIM config file {!s} does not exist".format(slim_conf_path) ) - if "sddm" == displaymanager: + +class DMsddm(DisplayManager): + name = "sddm" + executable = "sddm" + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): # Systems with Sddm as Desktop Manager sddm_conf_path = os.path.join(root_mount_point, "etc/sddm.conf") @@ -398,7 +397,12 @@ def set_autologin(username, with open(sddm_conf_path, 'w') as sddm_config_file: sddm_config.write(sddm_config_file, space_around_delimiters=False) - if "sysconfig" == displaymanager: + +class DMsysconfig(DisplayManager): + name = "sysconfig" + executable = None + + def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): dmauto = "DISPLAYMANAGER_AUTOLOGIN" os.system( @@ -410,8 +414,49 @@ def set_autologin(username, ) ) - return None +# Collect all the subclasses of DisplayManager defined above, +# and index them based on the name property of each class. +display_managers = [ + (c.name, c) + for c in globals().values() + if type(c) is abc.ABCMeta and issubclass(c, DisplayManager) and c.name +] + + +def have_dm(dm_name, root_mount_point): + """ + Checks if display manager is properly installed. + + :param dm_name: + :param root_mount_point: + :return: + """ + bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, dm_name) + sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, dm_name) + return (os.path.exists(bin_path) + or os.path.exists(sbin_path) + ) + + + +_ = """ + if "mdm" == displaymanager: + + if "gdm" == displaymanager: + + if "kdm" == displaymanager: + + if "lxdm" == displaymanager: + + if "lightdm" == displaymanager: + + if "slim" == displaymanager: + + if "sddm" == displaymanager: + + if "sysconfig" == displaymanager: +""" def run(): """ @@ -707,11 +752,12 @@ def run(): dm_setup_message = [] for dm in displaymanagers: - dm_message = set_autologin( - username, dm, - default_desktop_environment, - root_mount_point - ) + impl = [ cls for name, cls in display_managers if name == dm ] + if len(impl) == 1: + dm_message = impl[0]().set_autologin(username, default_desktop_environment, root_mount_point) + else: + dm_message = ("Can not configure {!s}".format(dm), "{!s} has {!d} implementation classes.".format(dm).format(len(impl))) + if dm_message is not None: dm_setup_message.append("{!s}: {!s}".format(*dm_message)) From cd0cdfc9af263da81abebfb4d67a00ba0c884f5d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 09:48:03 -0400 Subject: [PATCH 06/20] [displaymanager] Move basic setup to DM classes - For all the DMs that have some kind of basic setup, introduce a method in the DM class for doing just that. - The Python code now doesn't call basic setup anywhere, so this specific revision isn't going to work properly. --- src/modules/displaymanager/main.py | 300 ++++++++++++++++------------- 1 file changed, 162 insertions(+), 138 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index a9e8993ab..34f7a112b 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -114,6 +114,12 @@ class DisplayManager(metaclass=abc.ABCMeta): as well. """ + @abc.abstractmethod + def basic_setup(self): + """ + Do basic setup (e.g. users, groups, directory creation) for this DM. + """ + class DMmdm(DisplayManager): name = "mdm" @@ -156,6 +162,38 @@ class DMmdm(DisplayManager): else: mdm_conf.write('AutomaticLoginEnable=False\n') + def basic_setup(self): + if libcalamares.utils.target_env_call( + ['getent', 'group', 'mdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', '-g', '128', 'mdm'] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'passwd', 'mdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['useradd', + '-c', '"Linux Mint Display Manager"', + '-u', '128', + '-g', 'mdm', + '-d', '/var/lib/mdm', + '-s', '/usr/bin/nologin', + 'mdm' + ] + ) + + libcalamares.utils.target_env_call( + ['passwd', '-l', 'mdm'] + ) + libcalamares.utils.target_env_call( + ['chown', 'root:mdm', '/var/lib/mdm'] + ) + libcalamares.utils.target_env_call( + ['chmod', '1770', '/var/lib/mdm'] + ) + class DMgdm(DisplayManager): name = "gdm" @@ -211,6 +249,36 @@ class DMgdm(DisplayManager): userfile.write("Icon=\n") + def basic_setup(self): + if libcalamares.utils.target_env_call( + ['getent', 'group', 'gdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', '-g', '120', 'gdm'] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'passwd', 'gdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['useradd', + '-c', '"Gnome Display Manager"', + '-u', '120', + '-g', 'gdm', + '-d', '/var/lib/gdm', + '-s', '/usr/bin/nologin', + 'gdm' + ] + ) + + libcalamares.utils.target_env_call( + ['passwd', '-l', 'gdm'] + ) + libcalamares.utils.target_env_call( + ['chown', '-R', 'gdm:gdm', '/var/lib/gdm'] + ) + + class DMkdm(DisplayManager): name = "kdm" executable = "kdm" @@ -255,6 +323,33 @@ class DMkdm(DisplayManager): "KDM config file {!s} does not exist".format(kdm_conf_path) ) + def basic_setup(self): + if libcalamares.utils.target_env_call( + ['getent', 'group', 'kdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', '-g', '135', 'kdm'] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'passwd', 'kdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['useradd', + '-u', '135', + '-g', 'kdm', + '-d', '/var/lib/kdm', + '-s', '/bin/false', + '-r', + '-M', + 'kdm' + ] + ) + + libcalamares.utils.target_env_call( + ['chown', '-R', '135:135', 'var/lib/kdm'] + ) + class DMlxdm(DisplayManager): name = "lxdm" @@ -284,6 +379,24 @@ class DMlxdm(DisplayManager): "LXDM config file {!s} does not exist".format(lxdm_conf_path) ) + def basic_setup(self): + if libcalamares.utils.target_env_call( + ['getent', 'group', 'lxdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', '--system', 'lxdm'] + ) + + libcalamares.utils.target_env_call( + ['chgrp', '-R', 'lxdm', '/var/lib/lxdm'] + ) + libcalamares.utils.target_env_call( + ['chgrp', 'lxdm', '/etc/lxdm/lxdm.conf'] + ) + libcalamares.utils.target_env_call( + ['chmod', '+r', '/etc/lxdm/lxdm.conf'] + ) + class DMlightdm(DisplayManager): name = "lightdm" @@ -332,6 +445,41 @@ class DMlightdm(DisplayManager): ) + def basic_setup(self): + libcalamares.utils.target_env_call( + ['mkdir', '-p', '/run/lightdm'] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'group', 'lightdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['groupadd', '-g', '620', 'lightdm'] + ) + + if libcalamares.utils.target_env_call( + ['getent', 'passwd', 'lightdm'] + ) != 0: + libcalamares.utils.target_env_call( + ['useradd', '-c', + '"LightDM Display Manager"', + '-u', '620', + '-g', 'lightdm', + '-d', '/var/run/lightdm', + '-s', '/usr/bin/nologin', + 'lightdm' + ] + ) + + libcalamares.utils.target_env_call('passwd', '-l', 'lightdm') + libcalamares.utils.target_env_call( + ['chown', '-R', 'lightdm:lightdm', '/run/lightdm'] + ) + libcalamares.utils.target_env_call( + ['chmod', '+r' '/etc/lightdm/lightdm.conf'] + ) + + class DMslim(DisplayManager): name = "slim" executable = "slim" @@ -364,6 +512,10 @@ class DMslim(DisplayManager): ) + def basic_setup(self): + pass + + class DMsddm(DisplayManager): name = "sddm" executable = "sddm" @@ -398,6 +550,10 @@ class DMsddm(DisplayManager): sddm_config.write(sddm_config_file, space_around_delimiters=False) + def basic_setup(self): + pass + + class DMsysconfig(DisplayManager): name = "sysconfig" executable = None @@ -415,6 +571,10 @@ class DMsysconfig(DisplayManager): ) + def basic_setup(self): + pass + + # Collect all the subclasses of DisplayManager defined above, # and index them based on the name property of each class. display_managers = [ @@ -520,40 +680,6 @@ def run(): root_mount_point, "etc/lightdm/lightdm.conf" ) - if enable_basic_setup: - libcalamares.utils.target_env_call( - ['mkdir', '-p', '/run/lightdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'group', 'lightdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '620', 'lightdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'lightdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', '-c', - '"LightDM Display Manager"', - '-u', '620', - '-g', 'lightdm', - '-d', '/var/run/lightdm', - '-s', '/usr/bin/nologin', - 'lightdm' - ] - ) - - libcalamares.utils.target_env_call('passwd', '-l', 'lightdm') - libcalamares.utils.target_env_call( - ['chown', '-R', 'lightdm:lightdm', '/run/lightdm'] - ) - libcalamares.utils.target_env_call( - ['chmod', '+r' '/etc/lightdm/lightdm.conf'] - ) - if default_desktop_environment is not None: os.system( "sed -i -e \"s/^.*user-session=.*/user-session={!s}/\" " @@ -596,34 +722,7 @@ def run(): # Setup gdm if "gdm" in displaymanagers: if have_dm("gdm", root_mount_point): - if enable_basic_setup: - if libcalamares.utils.target_env_call( - ['getent', 'group', 'gdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '120', 'gdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'gdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-c', '"Gnome Display Manager"', - '-u', '120', - '-g', 'gdm', - '-d', '/var/lib/gdm', - '-s', '/usr/bin/nologin', - 'gdm' - ] - ) - - libcalamares.utils.target_env_call( - ['passwd', '-l', 'gdm'] - ) - libcalamares.utils.target_env_call( - ['chown', '-R', 'gdm:gdm', '/var/lib/gdm'] - ) + pass else: libcalamares.utils.debug("gdm selected but not installed") displaymanagers.remove("gdm") @@ -631,38 +730,6 @@ def run(): # Setup mdm if "mdm" in displaymanagers: if have_dm("mdm", root_mount_point): - if enable_basic_setup: - if libcalamares.utils.target_env_call( - ['getent', 'group', 'mdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '128', 'mdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'mdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-c', '"Linux Mint Display Manager"', - '-u', '128', - '-g', 'mdm', - '-d', '/var/lib/mdm', - '-s', '/usr/bin/nologin', - 'mdm' - ] - ) - - libcalamares.utils.target_env_call( - ['passwd', '-l', 'mdm'] - ) - libcalamares.utils.target_env_call( - ['chown', 'root:mdm', '/var/lib/mdm'] - ) - libcalamares.utils.target_env_call( - ['chmod', '1770', '/var/lib/mdm'] - ) - if default_desktop_environment is not None: os.system( "sed -i \"s|default.desktop|{!s}.desktop|g\" " @@ -678,24 +745,6 @@ def run(): # Setup lxdm if "lxdm" in displaymanagers: if have_dm("lxdm", root_mount_point): - if enable_basic_setup: - if libcalamares.utils.target_env_call( - ['getent', 'group', 'lxdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '--system', 'lxdm'] - ) - - libcalamares.utils.target_env_call( - ['chgrp', '-R', 'lxdm', '/var/lib/lxdm'] - ) - libcalamares.utils.target_env_call( - ['chgrp', 'lxdm', '/etc/lxdm/lxdm.conf'] - ) - libcalamares.utils.target_env_call( - ['chmod', '+r', '/etc/lxdm/lxdm.conf'] - ) - if default_desktop_environment is not None: os.system( "sed -i -e \"s|^.*session=.*|session={!s}|\" " @@ -711,32 +760,7 @@ def run(): # Setup kdm if "kdm" in displaymanagers: if have_dm("kdm", root_mount_point): - if enable_basic_setup: - if libcalamares.utils.target_env_call( - ['getent', 'group', 'kdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '135', 'kdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'kdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-u', '135', - '-g', 'kdm', - '-d', '/var/lib/kdm', - '-s', '/bin/false', - '-r', - '-M', - 'kdm' - ] - ) - - libcalamares.utils.target_env_call( - ['chown', '-R', '135:135', 'var/lib/kdm'] - ) + pass else: libcalamares.utils.debug("kdm selected but not installed") displaymanagers.remove("kdm") From 1c0b9e6a2a878027879e6a2c8d962f4215ec6a05 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 09:56:15 -0400 Subject: [PATCH 07/20] [displaymanager] Call basic_setup through instance - Now that basic_setup is factored out into the classes, call it via an instance before doing set_autologin. --- src/modules/displaymanager/main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 34f7a112b..1c1585f22 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -778,7 +778,12 @@ def run(): for dm in displaymanagers: impl = [ cls for name, cls in display_managers if name == dm ] if len(impl) == 1: - dm_message = impl[0]().set_autologin(username, default_desktop_environment, root_mount_point) + dm_impl = impl[0]() # Instantiate the class that was named + dm_message = None + if enable_basic_setup: + dm_message = dm_impl.basic_setup() + if dm_message is None: + dm_message = dm_impl.set_autologin(username, default_desktop_environment, root_mount_point) else: dm_message = ("Can not configure {!s}".format(dm), "{!s} has {!d} implementation classes.".format(dm).format(len(impl))) From 383e0e4f252a7bc0f821496c55949f85d8937b31 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 10:14:29 -0400 Subject: [PATCH 08/20] [displaymanager] Refactor setting up default DE - Some DMs allow setting up the default DE. Factor that out into a method like basic_setup() and setup_autologin() and add it to the configuration chain. --- src/modules/displaymanager/main.py | 64 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 1c1585f22..3ff9dd350 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -119,7 +119,15 @@ class DisplayManager(metaclass=abc.ABCMeta): """ Do basic setup (e.g. users, groups, directory creation) for this DM. """ + # Some implementations do nothing + @abc.abstractmethod + def desktop_environment_setup(self, desktop_environment): + """ + Configure the given @p desktop_environment as the default one, in + the configuration files for this DM. + """ + # Many implementations do nothing class DMmdm(DisplayManager): name = "mdm" @@ -194,6 +202,15 @@ class DMmdm(DisplayManager): ['chmod', '1770', '/var/lib/mdm'] ) + def desktop_environment_setup(self, default_desktop_environment): + os.system( + "sed -i \"s|default.desktop|{!s}.desktop|g\" " + "{!s}/etc/mdm/custom.conf".format( + default_desktop_environment.desktop_file, + root_mount_point + ) + ) + class DMgdm(DisplayManager): name = "gdm" @@ -397,6 +414,15 @@ class DMlxdm(DisplayManager): ['chmod', '+r', '/etc/lxdm/lxdm.conf'] ) + def desktop_environment_setup(self, default_desktop_environment): + os.system( + "sed -i -e \"s|^.*session=.*|session={!s}|\" " + "{!s}/etc/lxdm/lxdm.conf".format( + default_desktop_environment.executable, + root_mount_point + ) + ) + class DMlightdm(DisplayManager): name = "lightdm" @@ -479,6 +505,15 @@ class DMlightdm(DisplayManager): ['chmod', '+r' '/etc/lightdm/lightdm.conf'] ) + def desktop_environment_setup(self, default_desktop_environment): + os.system( + "sed -i -e \"s/^.*user-session=.*/user-session={!s}/\" " + "{!s}".format( + default_desktop_environment.desktop_file, + lightdm_conf_path + ) + ) + class DMslim(DisplayManager): name = "slim" @@ -680,15 +715,6 @@ def run(): root_mount_point, "etc/lightdm/lightdm.conf" ) - if default_desktop_environment is not None: - os.system( - "sed -i -e \"s/^.*user-session=.*/user-session={!s}/\" " - "{!s}".format( - default_desktop_environment.desktop_file, - lightdm_conf_path - ) - ) - # configure lightdm-greeter greeter_path = os.path.join( root_mount_point, "usr/share/xgreeters" @@ -730,14 +756,7 @@ def run(): # Setup mdm if "mdm" in displaymanagers: if have_dm("mdm", root_mount_point): - if default_desktop_environment is not None: - os.system( - "sed -i \"s|default.desktop|{!s}.desktop|g\" " - "{!s}/etc/mdm/custom.conf".format( - default_desktop_environment.desktop_file, - root_mount_point - ) - ) + pass else: libcalamares.utils.debug("mdm selected but not installed") displaymanagers.remove("mdm") @@ -745,14 +764,7 @@ def run(): # Setup lxdm if "lxdm" in displaymanagers: if have_dm("lxdm", root_mount_point): - if default_desktop_environment is not None: - os.system( - "sed -i -e \"s|^.*session=.*|session={!s}|\" " - "{!s}/etc/lxdm/lxdm.conf".format( - default_desktop_environment.executable, - root_mount_point - ) - ) + pass else: libcalamares.utils.debug("lxdm selected but not installed") displaymanagers.remove("lxdm") @@ -782,6 +794,8 @@ def run(): dm_message = None if enable_basic_setup: dm_message = dm_impl.basic_setup() + if default_desktop_environment is not None and dm_message is None: + dm_message = dm_impl.desktop_environment_setup(default_desktop_environment) if dm_message is None: dm_message = dm_impl.set_autologin(username, default_desktop_environment, root_mount_point) else: From 18392cb216623ade3a3c4a23d1fdc3e58cc0144f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 10:26:59 -0400 Subject: [PATCH 09/20] [displaymanager] Refactor greeter setup - Only lightdm has support for dynamically configuring the greeter based on what is installed. Still, refactory that to something general. --- src/modules/displaymanager/main.py | 71 +++++++++++++++++------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 3ff9dd350..942a7d470 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -129,6 +129,14 @@ class DisplayManager(metaclass=abc.ABCMeta): """ # Many implementations do nothing + @abc.abstractmethod + def greeter_setup(self): + """ + Additional setup for the greeter. + """ + # Most implementations do nothing + + class DMmdm(DisplayManager): name = "mdm" executable = "mdm" @@ -514,6 +522,38 @@ class DMlightdm(DisplayManager): ) ) + def greeter_setup(self): + lightdm_conf_path = os.path.join( + root_mount_point, "etc/lightdm/lightdm.conf" + ) + + # configure lightdm-greeter + greeter_path = os.path.join( + root_mount_point, "usr/share/xgreeters" + ) + + if (os.path.exists(greeter_path)): + # configure first found lightdm-greeter + for entry in os.listdir(greeter_path): + if entry.endswith('.desktop'): + greeter = entry.split('.')[0] + libcalamares.utils.debug( + "found greeter {!s}".format(greeter) + ) + os.system( + "sed -i -e \"s/^.*greeter-session=.*" + "/greeter-session={!s}/\" {!s}".format( + greeter, + lightdm_conf_path + ) + ) + libcalamares.utils.debug( + "{!s} configured as greeter.".format(greeter) + ) + break + else: + return ("No lightdm greeter installed.") + class DMslim(DisplayManager): name = "slim" @@ -711,36 +751,7 @@ def run(): # setup lightdm if "lightdm" in displaymanagers: if have_dm("lightdm", root_mount_point): - lightdm_conf_path = os.path.join( - root_mount_point, "etc/lightdm/lightdm.conf" - ) - - # configure lightdm-greeter - greeter_path = os.path.join( - root_mount_point, "usr/share/xgreeters" - ) - - if (os.path.exists(greeter_path)): - # configure first found lightdm-greeter - for entry in os.listdir(greeter_path): - if entry.endswith('.desktop'): - greeter = entry.split('.')[0] - libcalamares.utils.debug( - "found greeter {!s}".format(greeter) - ) - os.system( - "sed -i -e \"s/^.*greeter-session=.*" - "/greeter-session={!s}/\" {!s}".format( - greeter, - lightdm_conf_path - ) - ) - libcalamares.utils.debug( - "{!s} configured as greeter.".format(greeter) - ) - break - else: - return ("No lightdm greeter installed.") + pass else: libcalamares.utils.debug("lightdm selected but not installed") displaymanagers.remove("lightdm") From 155e212616b0c0a6f0af0e4e3e63f92f1925fcfd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 10:49:17 -0400 Subject: [PATCH 10/20] [displaymanager] Call all configuration methods through instance - Make root_mount_point a parameter of the DM classes - Create instances as needed, then check if they're available - Keep instances that actually need to be configured - Clean up remaining cruft from removing old setup_autologin() with all the string-comparison magic. --- src/modules/displaymanager/main.py | 177 +++++++++-------------------- 1 file changed, 54 insertions(+), 123 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 942a7d470..559a5bcf0 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -93,20 +93,22 @@ class DisplayManager(metaclass=abc.ABCMeta): name = None executable = None - @classmethod - def have_dm(cls, root_mount_point): + def __init__(self, root_mount_point): + self.root_mount_point = root_mount_point + + def have_dm(cls): if cls.executable is None: return True - bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, cls.executable) - sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, cls.executable) + bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, cls.executable) + sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, cls.executable) return ( os.path.exists(bin_path) or os.path.exists(sbin_path) ) @abc.abstractmethod - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): """ Configure the DM inside the given @p root_mount_point with autologin (if @p do_autologin is True) for the given @p username. @@ -141,9 +143,9 @@ class DMmdm(DisplayManager): name = "mdm" executable = "mdm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with MDM as Desktop Manager - mdm_conf_path = os.path.join(root_mount_point, "etc/mdm/custom.conf") + mdm_conf_path = os.path.join(self.root_mount_point, "etc/mdm/custom.conf") if os.path.exists(mdm_conf_path): with open(mdm_conf_path, 'r') as mdm_conf: @@ -215,7 +217,7 @@ class DMmdm(DisplayManager): "sed -i \"s|default.desktop|{!s}.desktop|g\" " "{!s}/etc/mdm/custom.conf".format( default_desktop_environment.desktop_file, - root_mount_point + self.root_mount_point ) ) @@ -224,9 +226,9 @@ class DMgdm(DisplayManager): name = "gdm" executable = "gdm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with GDM as Desktop Manager - gdm_conf_path = os.path.join(root_mount_point, "etc/gdm/custom.conf") + gdm_conf_path = os.path.join(self.root_mount_point, "etc/gdm/custom.conf") if os.path.exists(gdm_conf_path): with open(gdm_conf_path, 'r') as gdm_conf: @@ -260,7 +262,7 @@ class DMgdm(DisplayManager): if (do_autologin): accountservice_dir = "{!s}/var/lib/AccountsService/users".format( - root_mount_point + self.root_mount_point ) userfile_path = "{!s}/{!s}".format(accountservice_dir, username) if os.path.exists(accountservice_dir): @@ -308,10 +310,10 @@ class DMkdm(DisplayManager): name = "kdm" executable = "kdm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with KDM as Desktop Manager kdm_conf_path = os.path.join( - root_mount_point, "usr/share/config/kdm/kdmrc" + self.root_mount_point, "usr/share/config/kdm/kdmrc" ) # Check which path is in use: SUSE does something else. # Also double-check the default setting. Pick the first @@ -320,7 +322,7 @@ class DMkdm(DisplayManager): "usr/share/config/kdm/kdmrc", "usr/share/kde4/config/kdm/kdmrc", ): - p = os.path.join(root_mount_point, candidate_kdmrc) + p = os.path.join(self.root_mount_point, candidate_kdmrc) if os.path.exists(p): kdm_conf_path = p break @@ -380,9 +382,9 @@ class DMlxdm(DisplayManager): name = "lxdm" executable = "lxdm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with LXDM as Desktop Manager - lxdm_conf_path = os.path.join(root_mount_point, "etc/lxdm/lxdm.conf") + lxdm_conf_path = os.path.join(self.root_mount_point, "etc/lxdm/lxdm.conf") text = [] if os.path.exists(lxdm_conf_path): @@ -427,7 +429,7 @@ class DMlxdm(DisplayManager): "sed -i -e \"s|^.*session=.*|session={!s}|\" " "{!s}/etc/lxdm/lxdm.conf".format( default_desktop_environment.executable, - root_mount_point + self.root_mount_point ) ) @@ -436,13 +438,13 @@ class DMlightdm(DisplayManager): name = "lightdm" executable = "lightdm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with LightDM as Desktop Manager # Ideally, we should use configparser for the ini conf file, # but we just do a simple text replacement for now, as it # worksforme(tm) lightdm_conf_path = os.path.join( - root_mount_point, "etc/lightdm/lightdm.conf" + self.root_mount_point, "etc/lightdm/lightdm.conf" ) text = [] @@ -524,12 +526,12 @@ class DMlightdm(DisplayManager): def greeter_setup(self): lightdm_conf_path = os.path.join( - root_mount_point, "etc/lightdm/lightdm.conf" + self.root_mount_point, "etc/lightdm/lightdm.conf" ) # configure lightdm-greeter greeter_path = os.path.join( - root_mount_point, "usr/share/xgreeters" + self.root_mount_point, "usr/share/xgreeters" ) if (os.path.exists(greeter_path)): @@ -559,9 +561,9 @@ class DMslim(DisplayManager): name = "slim" executable = "slim" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with Slim as Desktop Manager - slim_conf_path = os.path.join(root_mount_point, "etc/slim.conf") + slim_conf_path = os.path.join(self.root_mount_point, "etc/slim.conf") text = [] if os.path.exists(slim_conf_path): @@ -595,9 +597,9 @@ class DMsddm(DisplayManager): name = "sddm" executable = "sddm" - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with Sddm as Desktop Manager - sddm_conf_path = os.path.join(root_mount_point, "etc/sddm.conf") + sddm_conf_path = os.path.join(self.root_mount_point, "etc/sddm.conf") sddm_config = configparser.ConfigParser(strict=False) # Make everything case sensitive @@ -633,7 +635,7 @@ class DMsysconfig(DisplayManager): name = "sysconfig" executable = None - def set_autologin(self, username, do_autologin, root_mount_point, default_desktop_environment): + def set_autologin(self, username, do_autologin, default_desktop_environment): dmauto = "DISPLAYMANAGER_AUTOLOGIN" os.system( @@ -641,7 +643,7 @@ class DMsysconfig(DisplayManager): "{!s}/etc/sysconfig/displaymanager".format( dmauto, dmauto, username if do_autologin else "", - root_mount_point + self.root_mount_point ) ) @@ -659,40 +661,6 @@ display_managers = [ ] -def have_dm(dm_name, root_mount_point): - """ - Checks if display manager is properly installed. - - :param dm_name: - :param root_mount_point: - :return: - """ - bin_path = "{!s}/usr/bin/{!s}".format(root_mount_point, dm_name) - sbin_path = "{!s}/usr/sbin/{!s}".format(root_mount_point, dm_name) - return (os.path.exists(bin_path) - or os.path.exists(sbin_path) - ) - - - -_ = """ - if "mdm" == displaymanager: - - if "gdm" == displaymanager: - - if "kdm" == displaymanager: - - if "lxdm" == displaymanager: - - if "lightdm" == displaymanager: - - if "slim" == displaymanager: - - if "sddm" == displaymanager: - - if "sysconfig" == displaymanager: -""" - def run(): """ Configure display managers. @@ -736,57 +704,23 @@ def run(): else: enable_basic_setup = False - # Setup slim - if "slim" in displaymanagers: - if not have_dm("slim", root_mount_point): - libcalamares.utils.debug("slim selected but not installed") - displaymanagers.remove("slim") - - # Setup sddm - if "sddm" in displaymanagers: - if not have_dm("sddm", root_mount_point): - libcalamares.utils.debug("sddm selected but not installed") - displaymanagers.remove("sddm") - - # setup lightdm - if "lightdm" in displaymanagers: - if have_dm("lightdm", root_mount_point): - pass + dm_impl = [] + for dm in displaymanagers: + # Find the implementation class + dm_impl = None + impl = [ cls for name, cls in display_managers if name == dm ] + if len(impl) == 1: + dm_instance = impl[0](root_mount_point) + if dm_instance.have_dm(): + dm_impl.append(dm_instance) + else: + dm_impl = None else: - libcalamares.utils.debug("lightdm selected but not installed") - displaymanagers.remove("lightdm") + libcalamares.utils.debug("{!s} has {!d} implementation classes.".format(dm).format(len(impl))) - # Setup gdm - if "gdm" in displaymanagers: - if have_dm("gdm", root_mount_point): - pass - else: - libcalamares.utils.debug("gdm selected but not installed") - displaymanagers.remove("gdm") - - # Setup mdm - if "mdm" in displaymanagers: - if have_dm("mdm", root_mount_point): - pass - else: - libcalamares.utils.debug("mdm selected but not installed") - displaymanagers.remove("mdm") - - # Setup lxdm - if "lxdm" in displaymanagers: - if have_dm("lxdm", root_mount_point): - pass - else: - libcalamares.utils.debug("lxdm selected but not installed") - displaymanagers.remove("lxdm") - - # Setup kdm - if "kdm" in displaymanagers: - if have_dm("kdm", root_mount_point): - pass - else: - libcalamares.utils.debug("kdm selected but not installed") - displaymanagers.remove("kdm") + if dm_impl is None: + libcalamares.utils.debug("{!s} selected but not installed".format(dm)) + displaymanagers.remove(dm) if username is not None: libcalamares.utils.debug( @@ -798,19 +732,16 @@ def run(): libcalamares.globalstorage.insert("displayManagers", displaymanagers) dm_setup_message = [] - for dm in displaymanagers: - impl = [ cls for name, cls in display_managers if name == dm ] - if len(impl) == 1: - dm_impl = impl[0]() # Instantiate the class that was named - dm_message = None - if enable_basic_setup: - dm_message = dm_impl.basic_setup() - if default_desktop_environment is not None and dm_message is None: - dm_message = dm_impl.desktop_environment_setup(default_desktop_environment) - if dm_message is None: - dm_message = dm_impl.set_autologin(username, default_desktop_environment, root_mount_point) - else: - dm_message = ("Can not configure {!s}".format(dm), "{!s} has {!d} implementation classes.".format(dm).format(len(impl))) + for dm in dm_impl: + dm_message = None + if enable_basic_setup: + dm_message = dm.basic_setup() + if default_desktop_environment is not None and dm_message is None: + dm_message = dm.desktop_environment_setup(default_desktop_environment) + if dm_message is None: + dm_message = dm.greeter_setup() + if dm_message is None: + dm_message = dm.set_autologin(username, do_autologin, default_desktop_environment) if dm_message is not None: dm_setup_message.append("{!s}: {!s}".format(*dm_message)) From 2d0660a54af8fde800038cc4c88b5bc0fe15c82c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 11:00:20 -0400 Subject: [PATCH 11/20] [displaymanager] Fix up missing methods - Add (empty) implementations of all the abstract methods that are not needed (or supported) by various DMs. - Order the abstract methods by calling order - Fix up have_dm --- src/modules/displaymanager/main.py | 69 ++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 559a5bcf0..b5b5bb0c1 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -96,25 +96,25 @@ class DisplayManager(metaclass=abc.ABCMeta): def __init__(self, root_mount_point): self.root_mount_point = root_mount_point - def have_dm(cls): - if cls.executable is None: + def have_dm(self): + """ + Is this DM installed in the target system? + The default implementation checks for `executable` + in the target system. + """ + if self.executable is None: return True - bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, cls.executable) - sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, cls.executable) + bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, self.executable) + sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, self.executable) return ( os.path.exists(bin_path) or os.path.exists(sbin_path) ) - @abc.abstractmethod - def set_autologin(self, username, do_autologin, default_desktop_environment): - """ - Configure the DM inside the given @p root_mount_point with - autologin (if @p do_autologin is True) for the given @p username. - If the DM supports it, set the default DE to @p default_desktop_environment - as well. - """ + # The four abstract methods below are called in the order listed here. + # They must all be implemented by subclasses, but not all of them + # actually do something for all DMs. @abc.abstractmethod def basic_setup(self): @@ -138,6 +138,15 @@ class DisplayManager(metaclass=abc.ABCMeta): """ # Most implementations do nothing + @abc.abstractmethod + def set_autologin(self, username, do_autologin, default_desktop_environment): + """ + Configure the DM inside the given @p root_mount_point with + autologin (if @p do_autologin is True) for the given @p username. + If the DM supports it, set the default DE to @p default_desktop_environment + as well. + """ + class DMmdm(DisplayManager): name = "mdm" @@ -221,6 +230,9 @@ class DMmdm(DisplayManager): ) ) + def greeter_setup(self): + pass + class DMgdm(DisplayManager): name = "gdm" @@ -305,6 +317,12 @@ class DMgdm(DisplayManager): ['chown', '-R', 'gdm:gdm', '/var/lib/gdm'] ) + def desktop_environment_setup(self, desktop_environment): + pass + + def greeter_setup(self): + pass + class DMkdm(DisplayManager): name = "kdm" @@ -377,6 +395,12 @@ class DMkdm(DisplayManager): ['chown', '-R', '135:135', 'var/lib/kdm'] ) + def desktop_environment_setup(self, desktop_environment): + pass + + def greeter_setup(self): + pass + class DMlxdm(DisplayManager): name = "lxdm" @@ -433,6 +457,9 @@ class DMlxdm(DisplayManager): ) ) + def greeter_setup(self): + pass + class DMlightdm(DisplayManager): name = "lightdm" @@ -592,6 +619,12 @@ class DMslim(DisplayManager): def basic_setup(self): pass + def desktop_environment_setup(self, desktop_environment): + pass + + def greeter_setup(self): + pass + class DMsddm(DisplayManager): name = "sddm" @@ -630,6 +663,12 @@ class DMsddm(DisplayManager): def basic_setup(self): pass + def desktop_environment_setup(self, desktop_environment): + pass + + def greeter_setup(self): + pass + class DMsysconfig(DisplayManager): name = "sysconfig" @@ -651,6 +690,12 @@ class DMsysconfig(DisplayManager): def basic_setup(self): pass + def desktop_environment_setup(self, desktop_environment): + pass + + def greeter_setup(self): + pass + # Collect all the subclasses of DisplayManager defined above, # and index them based on the name property of each class. From 59a003a41fad55b0baad04a34ac540b7975ba9a7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 11:06:49 -0400 Subject: [PATCH 12/20] [displaymanager] Expand check for no-DMs - The message refers to an empty list or unset variable, but the if only checked for unset. Also bail out if the list is empty. --- src/modules/displaymanager/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index b5b5bb0c1..183188722 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -724,7 +724,7 @@ def run(): if libcalamares.globalstorage.contains("displayManagers"): displaymanagers = libcalamares.globalstorage.value("displayManagers") - if displaymanagers is None: + if not displaymanagers: return ( "No display managers selected for the displaymanager module.", "The displaymanagers list is empty or undefined in both" From 229cc241faf874f9e4fe1cd1624f5bd3ed808fbf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 11:10:40 -0400 Subject: [PATCH 13/20] [displaymanager] Massage do_autologin - Move getting the global setting closer to where it is used - Initialize variable --- src/modules/displaymanager/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 183188722..21c9115f1 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -731,7 +731,6 @@ def run(): "globalstorage and displaymanager.conf." ) - username = libcalamares.globalstorage.value("autologinUser") root_mount_point = libcalamares.globalstorage.value("rootMountPoint") if "default_desktop_environment" in libcalamares.job.configuration: @@ -767,11 +766,12 @@ def run(): libcalamares.utils.debug("{!s} selected but not installed".format(dm)) displaymanagers.remove(dm) + username = libcalamares.globalstorage.value("autologinUser") if username is not None: - libcalamares.utils.debug( - "Setting up autologin for user {!s}.".format(username) - ) + do_autologin = True + libcalamares.utils.debug("Setting up autologin for user {!s}.".format(username)) else: + do_autologin = False libcalamares.utils.debug("Unsetting autologin.") libcalamares.globalstorage.insert("displayManagers", displaymanagers) From ebae7e1f476a28bd57b7d83d175ad7e156b875e1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 12:02:01 -0400 Subject: [PATCH 14/20] [displaymanager] Re-arrange initializations - Move variable initializations closer to where they are first used - Also warn if no implementations are available - Handle sysconfig as any other DM; there's no real reason to treat it specially. --- src/modules/displaymanager/main.py | 55 ++++++++++++++++++------------ 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 21c9115f1..8a9de1426 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -717,6 +717,7 @@ def run(): If a displaymanager is in the list but not installed, a debugging message is printed and the entry ignored. """ + # Get configuration settings for display managers displaymanagers = None if "displaymanagers" in libcalamares.job.configuration: displaymanagers = libcalamares.job.configuration["displaymanagers"] @@ -731,8 +732,39 @@ def run(): "globalstorage and displaymanager.conf." ) + # Get instances that are actually installed root_mount_point = libcalamares.globalstorage.value("rootMountPoint") + dm_impl = [] + dm_names = displaymanagers[:] + if ("sysconfigSetup" in libcalamares.job.configuration + and libcalamares.job.configuration["sysconfigSetup"]): + dm_names.append("sysconfig") + for dm in dm_names: + # Find the implementation class + dm_instance = None + impl = [ cls for name, cls in display_managers if name == dm ] + if len(impl) == 1: + dm_instance = impl[0](root_mount_point) + if dm_instance.have_dm(): + dm_impl.append(dm_instance) + else: + dm_instance = None + else: + libcalamares.utils.debug("{!s} has {!d} implementation classes.".format(dm).format(len(impl))) + if dm_instance is None: + libcalamares.utils.debug("{!s} selected but not installed".format(dm)) + if dm in displaymanagers: + displaymanagers.remove(dm) + + if not dm_impl: + return ( + "No display managers selected for the displaymanager module.", + "The list is empty after checking for installed display managers." + ) + + + # Pick up remaining settings if "default_desktop_environment" in libcalamares.job.configuration: entry = libcalamares.job.configuration["defaultDesktopEnvironment"] default_desktop_environment = DesktopEnvironment( @@ -748,24 +780,6 @@ def run(): else: enable_basic_setup = False - dm_impl = [] - for dm in displaymanagers: - # Find the implementation class - dm_impl = None - impl = [ cls for name, cls in display_managers if name == dm ] - if len(impl) == 1: - dm_instance = impl[0](root_mount_point) - if dm_instance.have_dm(): - dm_impl.append(dm_instance) - else: - dm_impl = None - else: - libcalamares.utils.debug("{!s} has {!d} implementation classes.".format(dm).format(len(impl))) - - if dm_impl is None: - libcalamares.utils.debug("{!s} selected but not installed".format(dm)) - displaymanagers.remove(dm) - username = libcalamares.globalstorage.value("autologinUser") if username is not None: do_autologin = True @@ -776,6 +790,7 @@ def run(): libcalamares.globalstorage.insert("displayManagers", displaymanagers) + # Do the actual configuration and collect messages dm_setup_message = [] for dm in dm_impl: dm_message = None @@ -791,10 +806,6 @@ def run(): if dm_message is not None: dm_setup_message.append("{!s}: {!s}".format(*dm_message)) - if ("sysconfigSetup" in libcalamares.job.configuration - and libcalamares.job.configuration["sysconfigSetup"]): - set_autologin(username, "sysconfig", None, root_mount_point) - if dm_setup_message: return ("Display manager configuration was incomplete", "\n".join(dm_setup_message)) From 5191400d89973f48a6a27cf536fd5c5537014a71 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 12:14:43 -0400 Subject: [PATCH 15/20] [displaymanager] Fix LightDM error message - Error tuple was not being constructed properly - Fix capitalization consistency --- src/modules/displaymanager/main.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 8a9de1426..464b560a6 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -581,7 +581,10 @@ class DMlightdm(DisplayManager): ) break else: - return ("No lightdm greeter installed.") + return ( + "Cannot configure LightDM", + "No LightDM greeter installed." + ) class DMslim(DisplayManager): From a83ee4984dc6f4865f0a33cb623bf6daf80b4de0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 12:28:47 -0400 Subject: [PATCH 16/20] [displaymanager] Enable translation for user-visible messages See also #991 --- src/modules/displaymanager/main.py | 47 ++++++++++++++++++------------ 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 464b560a6..4d79ccad5 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -29,6 +29,15 @@ import re import libcalamares import configparser +from libcalamares.utils import gettext_path, gettext_languages + +import gettext +_translation = gettext.translation("calamares-python", + localedir=gettext_path(), + languages=gettext_languages(), + fallback=True) +_ = _translation.gettext +_n = _translation.ngettext class DesktopEnvironment: """ @@ -364,8 +373,8 @@ class DMkdm(DisplayManager): kdm_conf.write(line) else: return ( - "Cannot write KDM configuration file", - "KDM config file {!s} does not exist".format(kdm_conf_path) + _("Cannot write KDM configuration file"), + _("KDM config file {!s} does not exist").format(kdm_conf_path) ) def basic_setup(self): @@ -426,8 +435,8 @@ class DMlxdm(DisplayManager): lxdm_conf.write(line) else: return ( - "Cannot write LXDM configuration file", - "LXDM config file {!s} does not exist".format(lxdm_conf_path) + _("Cannot write LXDM configuration file"), + _("LXDM config file {!s} does not exist").format(lxdm_conf_path) ) def basic_setup(self): @@ -501,10 +510,8 @@ class DMlightdm(DisplayManager): "#autologin-user=\n") except FileNotFoundError: return ( - "Cannot write LightDM configuration file", - "LightDM config file {!s} does not exist".format( - lightdm_conf_path - ) + _("Cannot write LightDM configuration file"), + _("LightDM config file {!s} does not exist").format(lightdm_conf_path) ) @@ -582,8 +589,8 @@ class DMlightdm(DisplayManager): break else: return ( - "Cannot configure LightDM", - "No LightDM greeter installed." + _("Cannot configure LightDM"), + _("No LightDM greeter installed.") ) @@ -614,8 +621,8 @@ class DMslim(DisplayManager): slim_conf.write(line) else: return ( - "Cannot write SLIM configuration file", - "SLIM config file {!s} does not exist".format(slim_conf_path) + _("Cannot write SLIM configuration file"), + _("SLIM config file {!s} does not exist").format(slim_conf_path) ) @@ -730,9 +737,9 @@ def run(): if not displaymanagers: return ( - "No display managers selected for the displaymanager module.", - "The displaymanagers list is empty or undefined in both" - "globalstorage and displaymanager.conf." + _("No display managers selected for the displaymanager module."), + _("The displaymanagers list is empty or undefined in both" + "globalstorage and displaymanager.conf.") ) # Get instances that are actually installed @@ -762,8 +769,8 @@ def run(): if not dm_impl: return ( - "No display managers selected for the displaymanager module.", - "The list is empty after checking for installed display managers." + _("No display managers selected for the displaymanager module."), + _("The list is empty after checking for installed display managers.") ) @@ -810,5 +817,7 @@ def run(): dm_setup_message.append("{!s}: {!s}".format(*dm_message)) if dm_setup_message: - return ("Display manager configuration was incomplete", - "\n".join(dm_setup_message)) + return ( + _("Display manager configuration was incomplete"), + "\n".join(dm_setup_message) + ) From 00e1bb9c8deb639d64f1170ecbfbe654ee8b45ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 20 Aug 2018 17:39:56 -0400 Subject: [PATCH 17/20] CI: fix the build on Travis - Make the Travis scripts a bit more verbose on failure - Fix wrong filename tested for picking up the configuration (this is why the builds were failing: missing the force-webkit flag, while webengine isn't in the dockerfile for Travis) FIXES #1018 --- ci/travis-continuous.sh | 10 +++++----- ci/travis-coverity.sh | 13 ++++++------- ci/travis.sh | 8 ++++---- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/ci/travis-continuous.sh b/ci/travis-continuous.sh index 42cfb4bd3..30fe82996 100755 --- a/ci/travis-continuous.sh +++ b/ci/travis-continuous.sh @@ -3,12 +3,12 @@ # Travis CI script for use on every-commit: # - build and install Calamares # -test -n "$BUILDDIR" || exit 1 -test -n "$SRCDIR" || exit 1 +test -n "$BUILDDIR" || { echo "! \$BUILDDIR not set" ; exit 1 ; } +test -n "$SRCDIR" || { echo "! \$SRCDIR not set" ; exit 1 ; } -test -d $BUILDDIR || exit 1 -test -d $SRCDIR || exit 1 -test -f $SRCDIR/CMakeLists.txt || exit 1 +test -d $BUILDDIR || { echo "! $BUILDDIR not a directory" ; exit 1 ; } +test -d $SRCDIR || { echo "! $SRCDIR not a directory" ; exit 1 ; } +test -f $SRCDIR/CMakeLists.txt || { echo "! Missing $SRCDIR/CMakeLists.txt" ; exit 1 ; } cd $BUILDDIR || exit 1 diff --git a/ci/travis-coverity.sh b/ci/travis-coverity.sh index c9495cf56..79b7fbdab 100755 --- a/ci/travis-coverity.sh +++ b/ci/travis-coverity.sh @@ -3,13 +3,13 @@ # Travis CI script for weekly (cron) use: # - use the coverity tool to build and and upload results # -test -n "$COVERITY_SCAN_TOKEN" || exit 1 -test -n "$BUILDDIR" || exit 1 -test -n "$SRCDIR" || exit 1 +test -n "$COVERITY_SCAN_TOKEN" || { echo "! Missing Coverity token" ; exit 1 ; } +test -n "$BUILDDIR" || { echo "! \$BUILDDIR not set" ; exit 1 ; } +test -n "$SRCDIR" || { echo "! \$SRCDIR not set" ; exit 1 ; } -test -d $BUILDDIR || exit 1 -test -d $SRCDIR || exit 1 -test -f $SRCDIR/CMakeLists.txt || exit 1 +test -d $BUILDDIR || { echo "! $BUILDDIR not a directory" ; exit 1 ; } +test -d $SRCDIR || { echo "! $SRCDIR not a directory" ; exit 1 ; } +test -f $SRCDIR/CMakeLists.txt || { echo "! Missing $SRCDIR/CMakeLists.txt" ; exit 1 ; } cd $BUILDDIR || exit 1 @@ -20,7 +20,6 @@ mkdir "$BUILDDIR/coveritytool" tar xvf coverity_tool.tar.gz -C "$BUILDDIR/coveritytool" --strip-components 2 export PATH="$BUILDDIR/coveritytool/bin:$PATH" - cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_ARGS $SRCDIR || exit 1 cov-build --dir cov-int make -j2 diff --git a/ci/travis.sh b/ci/travis.sh index 364923b9e..737da95d4 100755 --- a/ci/travis.sh +++ b/ci/travis.sh @@ -8,11 +8,11 @@ # intensive than the coverity add-on, but works on master. # D=`dirname "$0"` -test -d "$D" || exit 1 -test -x "$D/travis-continuous.sh" || exit 1 -test -x "$D/travis-coverity.sh" || exit 1 +test -d "$D" || { echo "! No directory $D" ; exit 1 ; } +test -x "$D/travis-continuous.sh" || { echo "! Missing -continuous" ; exit 1 ; } +test -x "$D/travis-coverity.sh" || { echo "! Missing -coverity" ; exit 1 ; } -test -f "$D/travis-common.sh" && . "$D/travis-config.sh" +test -f "$D/travis-config.sh" && . "$D/travis-config.sh" if test "$TRAVIS_EVENT_TYPE" = "cron" ; then exec "$D/travis-coverity.sh" From c3219a49057f2b526592c3898abde334591f518e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 21 Aug 2018 07:31:46 -0400 Subject: [PATCH 18/20] [displaymanager] Fix call in LightDM code - The parameter list was wrong, and could never have worked (apparently noone mixes LightDM with basic setup, even though it's one of the few with basic_setup()). - Shorten some lines. --- src/modules/displaymanager/main.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 16d9ccb51..3937c1551 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -541,13 +541,9 @@ class DMlightdm(DisplayManager): ] ) - libcalamares.utils.target_env_call('passwd', '-l', 'lightdm') - libcalamares.utils.target_env_call( - ['chown', '-R', 'lightdm:lightdm', '/run/lightdm'] - ) - libcalamares.utils.target_env_call( - ['chmod', '+r' '/etc/lightdm/lightdm.conf'] - ) + libcalamares.utils.target_env_call(['passwd', '-l', 'lightdm']) + libcalamares.utils.target_env_call(['chown', '-R', 'lightdm:lightdm', '/run/lightdm']) + libcalamares.utils.target_env_call(['chmod', '+r' '/etc/lightdm/lightdm.conf']) def desktop_environment_setup(self, default_desktop_environment): os.system( From f97321656f65b1d5d6fe9c9818b6e743fc0b3d9b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 21 Aug 2018 07:44:01 -0400 Subject: [PATCH 19/20] Changelog: add DM changes - Add the DM module changes - Update list of contributors for this release --- CHANGES | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 6bcb46e72..9fc3979e0 100644 --- a/CHANGES +++ b/CHANGES @@ -5,11 +5,16 @@ website will have to do for older versions. = 3.2.2 (unreleased) = +This release contains contributions from (alphabetically by first name): + - Andrius Štikonas + - artoo@cromnix.org + - Caio Carvalho + - Philip Müller + - Simon Quigley + - Walter Lapchynski + == Core == - * Contributions from the following people (alphabetically by first name): - - artoo@cromnix.org - - Caio Carvalho * Example configurations are **no longer installed** by default. The default setting for *INSTALL_CONFIG* has changed. Distributions are strongly encouraged to write their own configuration files and @@ -45,6 +50,14 @@ website will have to do for older versions. a bad configuration). The configuration is a little more flexible because a service (or target) name can be used on its own with sensible defaults. + * The displaymanager module has been entirely revamped. A long-standing + bug which ignored the settings for default desktop has been fixed + (thanks to Walter Lapchynski). Translations have been added to the + error messages. Each DM now has an implementation class for doing + all the configuration steps it needs. This groups the code needed for + a specific DM (and presumably, per-distro) in one place. + Distro's are **strongly advised** to re-test their DM configuration + and installation with the revamped code. **3.2.1** (2018-06-25) From ae0764f52ef791c86af4455f65b1a8422db7c4da Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 21 Aug 2018 07:45:44 -0400 Subject: [PATCH 20/20] CI: be more verbose in the CI --- ci/travis-continuous.sh | 1 + ci/travis-coverity.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/ci/travis-continuous.sh b/ci/travis-continuous.sh index 30fe82996..4ac243f23 100755 --- a/ci/travis-continuous.sh +++ b/ci/travis-continuous.sh @@ -12,4 +12,5 @@ test -f $SRCDIR/CMakeLists.txt || { echo "! Missing $SRCDIR/CMakeLists.txt" ; ex cd $BUILDDIR || exit 1 +echo "# cmake $CMAKE_ARGS $SRCDIR" cmake $CMAKE_ARGS $SRCDIR && make -j2 && make install DESTDIR=/build/INSTALL_ROOT diff --git a/ci/travis-coverity.sh b/ci/travis-coverity.sh index 79b7fbdab..88b6a2ab5 100755 --- a/ci/travis-coverity.sh +++ b/ci/travis-coverity.sh @@ -20,6 +20,7 @@ mkdir "$BUILDDIR/coveritytool" tar xvf coverity_tool.tar.gz -C "$BUILDDIR/coveritytool" --strip-components 2 export PATH="$BUILDDIR/coveritytool/bin:$PATH" +echo "# cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_ARGS $SRCDIR" cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_ARGS $SRCDIR || exit 1 cov-build --dir cov-int make -j2