From 0a0c53a61bc6ead78f9c46e5edad16d1c4d795c1 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Tue, 28 Sep 2021 20:48:30 +0800 Subject: [PATCH 01/10] system_setup: move all write file actions to configure controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This completes 5. Move all “Commits/Write to file” in the configure controller. --- system_setup/models/wslconfadvanced.py | 50 +------ system_setup/models/wslconfbase.py | 25 +--- system_setup/server/controllers/configure.py | 125 ++++++++++++++++++ .../server/controllers/wslconfadvanced.py | 39 +----- .../server/controllers/wslconfbase.py | 8 +- 5 files changed, 136 insertions(+), 111 deletions(-) diff --git a/system_setup/models/wslconfadvanced.py b/system_setup/models/wslconfadvanced.py index 6fe5380a..6b3bd4d2 100644 --- a/system_setup/models/wslconfadvanced.py +++ b/system_setup/models/wslconfadvanced.py @@ -14,11 +14,8 @@ # along with this program. If not, see . import logging -import subprocess import attr -from subiquitycore.utils import run_command - log = logging.getLogger('subiquity.models.wsl_configuration_advanced') @@ -42,9 +39,8 @@ class WSLConfigurationAdvancedModel(object): def __init__(self): self._wslconfadvanced = None - # TODO WSL: Load settings from system - def apply_settings(self, result, is_dry_run=False): + def apply_settings(self, result): d = {} # TODO: placholder settings; should be dynamically assgined using # ubuntu-wsl-integration @@ -59,50 +55,6 @@ class WSLConfigurationAdvancedModel(object): d['automount'] = result.automount d['mountfstab'] = result.mountfstab self._wslconfadvanced = WSLConfigurationAdvanced(**d) - # TODO WSL: Drop all calls of ubuntuwsl here and ensure the data - # are passed to the app model - if not is_dry_run: - # reset to keep everything as refreshed as new - run_command(["/usr/bin/ubuntuwsl", "reset", "-y"], - stdout=subprocess.DEVNULL) - # set the settings - # TODO: placholder settings; should be dynamically generated using - # ubuntu-wsl-integration - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.enabled", result.automount], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.mountfstab", result.mountfstab], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.interop.enabled", - result.interop_enabled], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.interop.appendwindowspath", - result.interop_appendwindowspath], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.GUI.followwintheme", - result.gui_followwintheme], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.GUI.theme", result.gui_theme], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.guiintergration", result.legacy_gui], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.audiointegration", - result.legacy_audio], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.advancedipdetection", - result.adv_ip_detect], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Motd.wslnewsenabled", result.wsl_motd_news], - stdout=subprocess.DEVNULL) @property def wslconfadvanced(self): diff --git a/system_setup/models/wslconfbase.py b/system_setup/models/wslconfbase.py index c2df10b5..50e06814 100644 --- a/system_setup/models/wslconfbase.py +++ b/system_setup/models/wslconfbase.py @@ -14,11 +14,8 @@ # along with this program. If not, see . import logging -import subprocess import attr -from subiquitycore.utils import run_command - log = logging.getLogger('subiquity.models.wsl_configuration_base') @@ -38,33 +35,13 @@ class WSLConfigurationBaseModel(object): self._wslconfbase = None # TODO WSL: Load settings from system - def apply_settings(self, result, is_dry_run=False): + def apply_settings(self, result): d = {} d['custom_path'] = result.custom_path d['custom_mount_opt'] = result.custom_mount_opt d['gen_host'] = result.gen_host d['gen_resolvconf'] = result.gen_resolvconf self._wslconfbase = WSLConfigurationBase(**d) - # TODO WSL: Drop all calls of ubuntuwsl here and ensure the data - # are passed to the app model - if not is_dry_run: - # reset to keep everything as refreshed as new - run_command(["/usr/bin/ubuntuwsl", "reset", "-y"], - stdout=subprocess.DEVNULL) - # set the settings - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.root", result.custom_path], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.options", result.custom_mount_opt], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generatehosts", result.gen_host], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generateresolvconf", - result.gen_resolvconf], - stdout=subprocess.DEVNULL) @property def wslconfbase(self): diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 8547a819..3c4a3153 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -14,6 +14,9 @@ # along with this program. If not, see . import logging +import os +import subprocess +from subiquitycore.utils import run_command from subiquitycore.context import with_context @@ -69,6 +72,111 @@ class ConfigureController(SubiquityController): self.app.update_state(ApplicationState.POST_RUNNING) + variant = self.model.client_variant + if variant == "wsl_setup": + wsl_identity = self.model.identity + run_command(["/usr/sbin/useradd", "-m", "-s", "/bin/bash", + "-p", wsl_identity.password, + wsl_identity.username]) + run_command(["/usr/sbin/usermod", "-a", + "-c", wsl_identity.realname, + "-G", self.get_userandgroups(), + wsl_identity.username]) + + wslconf_base = self.model.wslconfbase + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.root", + wslconf_base.custom_path], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.options", + wslconf_base.custom_mount_opt], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generatehosts", + wslconf_base.gen_host], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generateresolvconf", + wslconf_base.gen_resolvconf], + stdout=subprocess.DEVNULL) + else: + wslconf_ad = self.model.wslconfadvanced + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.enabled", + wslconf_ad.automount], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.mountfstab", + wslconf_ad.mountfstab], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.root", + wslconf_ad.custom_path], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.options", + wslconf_ad.custom_mount_opt], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generatehosts", + wslconf_ad.gen_host], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generateresolvconf", + wslconf_ad.gen_resolvconf], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.interop.enabled", + wslconf_ad.interop_enabled], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.interop.appendwindowspath", + wslconf_ad.interop_appendwindowspath], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.GUI.followwintheme", + wslconf_ad.gui_followwintheme], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.GUI.theme", + wslconf_ad.gui_theme], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.Interop.guiintergration", + wslconf_ad.legacy_gui], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.Interop.audiointegration", + wslconf_ad.legacy_audio], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.Interop.advancedipdetection", + wslconf_ad.adv_ip_detect], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "ubuntu.Motd.wslnewsenabled", + wslconf_ad.wsl_motd_news], + stdout=subprocess.DEVNULL) + + wslconf_base = self.model.wslconfbase + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.root", + wslconf_base.custom_path], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.automount.options", + wslconf_base.custom_mount_opt], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generatehosts", + wslconf_base.gen_host], + stdout=subprocess.DEVNULL) + run_command(["/usr/bin/ubuntuwsl", "update", + "WSL.network.generateresolvconf", + wslconf_base.gen_resolvconf], + stdout=subprocess.DEVNULL) + self.app.update_state(ApplicationState.DONE) except Exception: kw = {} @@ -76,6 +184,23 @@ class ConfigureController(SubiquityController): ErrorReportKind.INSTALL_FAIL, "configuration failed", **kw) raise + def get_userandgroups(self): + usergroups_path = '/usr/share/subiquity/users-and-groups' + build_usergroups_path = \ + os.path.realpath(__file__ + '/../../../users-and-groups') + if os.path.isfile(build_usergroups_path): + usergroups_path = build_usergroups_path + user_groups = set() + if os.path.exists(usergroups_path): + with open(usergroups_path) as fp: + for line in fp: + line = line.strip() + if line.startswith('#') or not line: + continue + user_groups.add(line) + oneline_usergroups = ",".join(user_groups) + return oneline_usergroups + def stop_uu(self): # This is a no-op to allow Shutdown controller to depend on this one pass diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index b5f478ca..3f84f886 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -52,35 +52,6 @@ class WSLConfigurationAdvancedController(SubiquityController): 'additionalProperties': False, } - # this is a temporary simplified reference. The future complete reference - # should use the default.json in `ubuntu-wsl-integration`. - config_ref = { - "wsl": { - "automount": { - "enabled": "automount", - "mountfstab": "mountfstab", - }, - "interop": { - "enabled": "interop_enabled", - "appendwindowspath": "interop_appendwindowspath", - } - }, - "ubuntu": { - "GUI": { - "theme": "gui_theme", - "followwintheme": "gui_followwintheme", - }, - "Interop": { - "guiintegration": "legacy_gui", - "audiointegration": "legacy_audio", - "advancedipdetection": "adv_ip_detect", - }, - "Motd": { - "wslnewsenabled": "wsl_motd_news", - } - } - } - def __init__(self, app): super().__init__(app) @@ -100,7 +71,7 @@ class WSLConfigurationAdvancedController(SubiquityController): ubuntuconfig = configparser.ConfigParser() ubuntuconfig.read('/etc/ubuntu-wsl.conf') for conf_sec in ubuntuconfig: - if conf_sec in self.config_ref['ubuntu']: + if conf_sec in config_ref['ubuntu']: conf_sec_list = ubuntuconfig[conf_sec] for conf_item in conf_sec_list: if conf_item in config_ref['ubuntu'][conf_sec]: @@ -122,7 +93,7 @@ class WSLConfigurationAdvancedController(SubiquityController): automount=bool_converter(data['automount']), mountfstab=bool_converter(data['mountfstab']), ) - self.model.apply_settings(reconf_data, self.opts.dry_run) + self.model.apply_settings(reconf_data) def load_autoinstall_data(self, data): if data is not None: @@ -138,7 +109,7 @@ class WSLConfigurationAdvancedController(SubiquityController): automount=data['automount'], mountfstab=data['mountfstab'] ) - self.model.apply_settings(reconf_data, self.opts.dry_run) + self.model.apply_settings(reconf_data) @with_context() async def apply_autoinstall_config(self, context=None): @@ -166,5 +137,5 @@ class WSLConfigurationAdvancedController(SubiquityController): return data async def POST(self, data: WSLConfigurationAdvanced): - self.model.apply_settings(data, self.opts.dry_run) - await self.configured() + self.model.apply_settings(data) + self.configured() diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index 810a7401..401addb6 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -72,7 +72,7 @@ class WSLConfigurationBaseController(SubiquityController): gen_host=bool_converter(data['gen_host']), gen_resolvconf=bool_converter(data['gen_resolvconf']), ) - self.model.apply_settings(conf_data, self.opts.dry_run) + self.model.apply_settings(conf_data) def load_autoinstall_data(self, data): if data is not None: @@ -82,7 +82,7 @@ class WSLConfigurationBaseController(SubiquityController): gen_host=data['gen_host'], gen_resolvconf=data['gen_resolvconf'], ) - self.model.apply_settings(identity_data, self.opts.dry_run) + self.model.apply_settings(identity_data) @with_context() async def apply_autoinstall_config(self, context=None): @@ -102,5 +102,5 @@ class WSLConfigurationBaseController(SubiquityController): return data async def POST(self, data: WSLConfigurationBase): - self.model.apply_settings(data, self.opts.dry_run) - await self.configured() + self.model.apply_settings(data) + self.configured() From a211689e08315925d11a927149f82455d54c119c Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Tue, 14 Sep 2021 16:16:06 +0800 Subject: [PATCH 02/10] system_setup: update client_variant to variant --- system_setup/server/controllers/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 3c4a3153..82dcaf0a 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -72,7 +72,7 @@ class ConfigureController(SubiquityController): self.app.update_state(ApplicationState.POST_RUNNING) - variant = self.model.client_variant + variant = self.app.variant if variant == "wsl_setup": wsl_identity = self.model.identity run_command(["/usr/sbin/useradd", "-m", "-s", "/bin/bash", From 032412a938279e08139ac93a06a87ccc17a2c436 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Thu, 23 Sep 2021 16:52:31 +0800 Subject: [PATCH 03/10] system_setup: provide configuration calls --- system_setup/common/conf.py | 79 +++++++++ system_setup/server/controllers/configure.py | 171 +++++++------------ 2 files changed, 138 insertions(+), 112 deletions(-) create mode 100644 system_setup/common/conf.py diff --git a/system_setup/common/conf.py b/system_setup/common/conf.py new file mode 100644 index 00000000..6c283d5f --- /dev/null +++ b/system_setup/common/conf.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# Copyright 2015-2021 Canonical, Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +# original code from ubuntuwslctl.core.loader +# Copyright (C) 2021 Canonical Ltd. + +import logging +from configparser import ConfigParser + +log = logging.getLogger("system_setup.common.conf") + + +class WSLConfig: + def __init__(self, inst_type, conf_file): + self.inst_type = inst_type + self.conf_file = conf_file + + self.config = ConfigParser() + self.config.BasicInterpolcation = None + self.config.read(conf_file) + + def update(self, config_section, config_setting, config_value): + self.config[config_section][config_setting] = config_value + with open(self.conf_file, 'w') as configfile: + self.config.write(configfile) + + +class WSLConfigHandler: + + def __init__(self, is_dry_run): + self.is_dry_run = is_dry_run + self.ubuntu_conf = \ + WSLConfig("ubuntu", "/etc/ubuntu-wsl.conf") + self.wsl_conf = WSLConfig("wsl", "/etc/wsl.conf") + + def _select_config(self, type_input): + type_input = type_input.lower() + if type_input == "ubuntu": + return self.ubuntu_conf + elif type_input == "wsl": + return self.wsl_conf + else: + raise ValueError("Invalid config name. Please check again.") + + def _update(self, config_type, section, config, value): + self._select_config(config_type).update(section, config, value) + + def update(self, config_name, value): + if self.is_dry_run: + log.debug("mimicking setting config %s with %s", + config_name, value) + return + config_name_set = config_name.split(".") + # it should always be three level: type, section, and config. + if len(config_name_set) == 3: + self._update(config_name_set[0], config_name_set[1], + config_name_set[2], value) + elif len(config_name_set) == 2: # if type is missing, guess + if not (config_name_set[0] in ("ubuntu", "wsl") + and config_name_set[1] == "*"): # no top level wild card + type_name = "ubuntu" if config_name_set[0] in ( + "Motd", "Interop", "GUI") else "wsl" + self._update(type_name, config_name_set[0], + config_name_set[1], value) + else: # invaild name + raise ValueError("Invalid config name '{}'.".format(config_name)) diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 82dcaf0a..0e4525f2 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -15,19 +15,13 @@ import logging import os -import subprocess -from subiquitycore.utils import run_command - -from subiquitycore.context import with_context from subiquity.common.errorreport import ErrorReportKind -from subiquity.server.controller import ( - SubiquityController, - ) - -from subiquity.common.types import ( - ApplicationState, - ) +from subiquity.common.types import ApplicationState +from subiquity.server.controller import SubiquityController +from subiquitycore.context import with_context +from subiquitycore.utils import run_command +from system_setup.common.conf import WSLConfigHandler log = logging.getLogger("system_setup.server.controllers.configure") @@ -72,110 +66,63 @@ class ConfigureController(SubiquityController): self.app.update_state(ApplicationState.POST_RUNNING) + dryrun = self.app.opts.dry_run variant = self.app.variant + config = WSLConfigHandler(dryrun) if variant == "wsl_setup": - wsl_identity = self.model.identity - run_command(["/usr/sbin/useradd", "-m", "-s", "/bin/bash", - "-p", wsl_identity.password, - wsl_identity.username]) - run_command(["/usr/sbin/usermod", "-a", - "-c", wsl_identity.realname, - "-G", self.get_userandgroups(), - wsl_identity.username]) - - wslconf_base = self.model.wslconfbase - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.root", - wslconf_base.custom_path], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.options", - wslconf_base.custom_mount_opt], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generatehosts", - wslconf_base.gen_host], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generateresolvconf", - wslconf_base.gen_resolvconf], - stdout=subprocess.DEVNULL) + wsl_identity = self.model.identity.user + if dryrun: + log.debug("mimicking creating user %s", + wsl_identity.username) + else: + run_command(["/usr/sbin/useradd", "-m", "-s", "/bin/bash", + "-p", wsl_identity.password, + wsl_identity.username]) + run_command(["/usr/sbin/usermod", "-a", + "-c", wsl_identity.realname, + "-G", self.get_userandgroups(), + wsl_identity.username]) else: - wslconf_ad = self.model.wslconfadvanced - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.enabled", - wslconf_ad.automount], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.mountfstab", - wslconf_ad.mountfstab], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.root", - wslconf_ad.custom_path], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.options", - wslconf_ad.custom_mount_opt], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generatehosts", - wslconf_ad.gen_host], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generateresolvconf", - wslconf_ad.gen_resolvconf], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.interop.enabled", - wslconf_ad.interop_enabled], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.interop.appendwindowspath", - wslconf_ad.interop_appendwindowspath], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.GUI.followwintheme", - wslconf_ad.gui_followwintheme], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.GUI.theme", - wslconf_ad.gui_theme], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.guiintergration", - wslconf_ad.legacy_gui], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.audiointegration", - wslconf_ad.legacy_audio], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Interop.advancedipdetection", - wslconf_ad.adv_ip_detect], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "ubuntu.Motd.wslnewsenabled", - wslconf_ad.wsl_motd_news], - stdout=subprocess.DEVNULL) - - wslconf_base = self.model.wslconfbase - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.root", - wslconf_base.custom_path], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.automount.options", - wslconf_base.custom_mount_opt], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generatehosts", - wslconf_base.gen_host], - stdout=subprocess.DEVNULL) - run_command(["/usr/bin/ubuntuwsl", "update", - "WSL.network.generateresolvconf", - wslconf_base.gen_resolvconf], - stdout=subprocess.DEVNULL) + wslconf_ad = self.model.wslconfadvanced.wslconfadvanced + config.update("WSL.automount.enabled", + wslconf_ad.automount) + config.update("WSL.automount.mountfstab", + wslconf_ad.mountfstab) + config.update("WSL.automount.root", + wslconf_ad.custom_path) + config.update("WSL.automount.options", + wslconf_ad.custom_mount_opt) + config.update("WSL.network.generatehosts", + wslconf_ad.gen_host) + config.update("WSL.network.generateresolvconf", + wslconf_ad.gen_resolvconf) + config.update("WSL.interop.enabled", + wslconf_ad.interop_enabled) + config.update( + "WSL.interop.appendwindowspath", + wslconf_ad.interop_appendwindowspath) + config.update("ubuntu.GUI.followwintheme", + wslconf_ad.gui_followwintheme) + config.update("ubuntu.GUI.theme", + wslconf_ad.gui_theme) + config.update("ubuntu.Interop.guiintergration", + wslconf_ad.legacy_gui) + config.update("ubuntu.Interop.audiointegration", + wslconf_ad.legacy_audio) + config.update("ubuntu.Interop.advancedipdetection", + wslconf_ad.adv_ip_detect) + config.update("ubuntu.Motd.wslnewsenabled", + wslconf_ad.wsl_motd_news) + + wslconf_base = self.model.wslconfbase.wslconfbase + config.update("WSL.automount.root", + wslconf_base.custom_path) + config.update("WSL.automount.options", + wslconf_base.custom_mount_opt) + config.update("WSL.network.generatehosts", + wslconf_base.gen_host) + config.update("WSL.network.generateresolvconf", + wslconf_base.gen_resolvconf) self.app.update_state(ApplicationState.DONE) except Exception: From 225cb1bd377160d50788d4e8e52626a48cccf4fe Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Tue, 28 Sep 2021 20:50:34 +0800 Subject: [PATCH 04/10] system_setup: fixes for after rebasing 1. add extra logs 2. improve the answers file 3. await the self.configured in wslconf API --- examples/answers-system-setup.yaml | 2 +- system_setup/models/wslconfadvanced.py | 2 +- system_setup/models/wslconfbase.py | 2 +- system_setup/server/controllers/wslconfadvanced.py | 2 +- system_setup/server/controllers/wslconfbase.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/answers-system-setup.yaml b/examples/answers-system-setup.yaml index 4da0b03e..822ba174 100644 --- a/examples/answers-system-setup.yaml +++ b/examples/answers-system-setup.yaml @@ -7,7 +7,7 @@ WSLIdentity: password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1' WSLConfigurationBase: custom_path: '/custom_mnt_path' - custom_mount_opt: 'opt1 opt2 opt3' + custom_mount_opt: 'metadata' gen_host: false gen_resolvconf: false Summary: diff --git a/system_setup/models/wslconfadvanced.py b/system_setup/models/wslconfadvanced.py index 6b3bd4d2..cc6852a0 100644 --- a/system_setup/models/wslconfadvanced.py +++ b/system_setup/models/wslconfadvanced.py @@ -16,7 +16,7 @@ import logging import attr -log = logging.getLogger('subiquity.models.wsl_configuration_advanced') +log = logging.getLogger('system_setup.models.wsl_configuration_advanced') @attr.s diff --git a/system_setup/models/wslconfbase.py b/system_setup/models/wslconfbase.py index 50e06814..01f2ca94 100644 --- a/system_setup/models/wslconfbase.py +++ b/system_setup/models/wslconfbase.py @@ -16,7 +16,7 @@ import logging import attr -log = logging.getLogger('subiquity.models.wsl_configuration_base') +log = logging.getLogger('system_setup.models.wsl_configuration_base') @attr.s diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index 3f84f886..b47bdeb0 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -138,4 +138,4 @@ class WSLConfigurationAdvancedController(SubiquityController): async def POST(self, data: WSLConfigurationAdvanced): self.model.apply_settings(data) - self.configured() + await self.configured() diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index 401addb6..b33bc9ee 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -103,4 +103,4 @@ class WSLConfigurationBaseController(SubiquityController): async def POST(self, data: WSLConfigurationBase): self.model.apply_settings(data) - self.configured() + await self.configured() From f31e2524361b1ecf6409099e4e5550e2fd6c959a Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Wed, 29 Sep 2021 00:37:26 +0800 Subject: [PATCH 05/10] system_setup: reduce code duplication in getting default value --- system_setup/common/{conf.py => wsl_conf.py} | 50 ++++++++++++++++++- system_setup/common/wsl_utils.py | 33 ------------ system_setup/server/controllers/configure.py | 2 +- .../server/controllers/wslconfadvanced.py | 28 ++--------- .../server/controllers/wslconfbase.py | 17 ++----- 5 files changed, 58 insertions(+), 72 deletions(-) rename system_setup/common/{conf.py => wsl_conf.py} (67%) diff --git a/system_setup/common/conf.py b/system_setup/common/wsl_conf.py similarity index 67% rename from system_setup/common/conf.py rename to system_setup/common/wsl_conf.py index 6c283d5f..1dc9e428 100644 --- a/system_setup/common/conf.py +++ b/system_setup/common/wsl_conf.py @@ -19,8 +19,56 @@ import logging from configparser import ConfigParser +from os import path -log = logging.getLogger("system_setup.common.conf") +log = logging.getLogger("system_setup.common.wsl_conf") + +config_ref = { + "wsl": { + "automount": { + "enabled": "automount", + "mountfstab": "mountfstab", + "root": "custom_path", + "options": "custom_mount_opt", + }, + "network": { + "generatehosts": "gen_host", + "generateresolvconf": "gen_resolvconf", + }, + "interop": { + "enabled": "interop_enabled", + "appendwindowspath": "interop_appendwindowspath", + } + }, + "ubuntu": { + "GUI": { + "theme": "gui_theme", + "followwintheme": "gui_followwintheme", + }, + "Interop": { + "guiintegration": "legacy_gui", + "audiointegration": "legacy_audio", + "advancedipdetection": "adv_ip_detect", + }, + "Motd": { + "wslnewsenabled": "wsl_motd_news", + } + } +} + + +def wsl_config_loader(data, pathname, id): + if path.exists(pathname): + config = ConfigParser() + config.read(pathname) + for conf_sec in config: + if conf_sec in config_ref[id]: + conf_sec_list = config[conf_sec] + for conf_item in conf_sec_list: + if conf_item in config_ref[id][conf_sec]: + data[config_ref[id][conf_sec][conf_item]] = \ + conf_sec_list[conf_item] + return data class WSLConfig: diff --git a/system_setup/common/wsl_utils.py b/system_setup/common/wsl_utils.py index 0dcadfe3..f6a393ad 100644 --- a/system_setup/common/wsl_utils.py +++ b/system_setup/common/wsl_utils.py @@ -20,39 +20,6 @@ import subprocess log = logging.getLogger("subiquity.system_setup.common.wsl_utils") -config_ref = { - "wsl": { - "automount": { - "enabled": "automount", - "mountfstab": "mountfstab", - "root": "custom_path", - "options": "custom_mount_opt", - }, - "network": { - "generatehosts": "gen_host", - "generateresolvconf": "gen_resolvconf", - }, - "interop": { - "enabled": "interop_enabled", - "appendwindowspath": "interop_appendwindowspath", - } - }, - "ubuntu": { - "GUI": { - "theme": "gui_theme", - "followwintheme": "gui_followwintheme", - }, - "Interop": { - "guiintegration": "legacy_gui", - "audiointegration": "legacy_audio", - "advancedipdetection": "adv_ip_detect", - }, - "Motd": { - "wslnewsenabled": "wsl_motd_news", - } - } -} - def is_reconfigure(is_dryrun): if is_dryrun and \ diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 0e4525f2..721a99ed 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -21,7 +21,7 @@ from subiquity.common.types import ApplicationState from subiquity.server.controller import SubiquityController from subiquitycore.context import with_context from subiquitycore.utils import run_command -from system_setup.common.conf import WSLConfigHandler +from system_setup.common.wsl_conf import WSLConfigHandler log = logging.getLogger("system_setup.server.controllers.configure") diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index b47bdeb0..15b2b3b1 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -16,15 +16,13 @@ import logging import attr -from os import path -import configparser from subiquitycore.context import with_context from subiquity.common.apidef import API from subiquity.common.types import WSLConfigurationAdvanced from subiquity.server.controller import SubiquityController -from system_setup.common.wsl_utils import config_ref +from system_setup.common.wsl_conf import wsl_config_loader log = logging.getLogger( 'system_setup.server.controllers.wsl_configuration_advanced') @@ -57,26 +55,10 @@ class WSLConfigurationAdvancedController(SubiquityController): # load the config file data = {} - if path.exists('/etc/wsl.conf'): - wslconfig = configparser.ConfigParser() - wslconfig.read('/etc/wsl.conf') - for conf_sec in wslconfig: - if conf_sec in config_ref['wsl']: - conf_sec_list = wslconfig[conf_sec] - for conf_item in conf_sec_list: - if conf_item in config_ref['wsl'][conf_sec]: - data[config_ref['wsl'][conf_sec][conf_item]] = \ - conf_sec_list[conf_item] - if path.exists('/etc/ubuntu-wsl.conf'): - ubuntuconfig = configparser.ConfigParser() - ubuntuconfig.read('/etc/ubuntu-wsl.conf') - for conf_sec in ubuntuconfig: - if conf_sec in config_ref['ubuntu']: - conf_sec_list = ubuntuconfig[conf_sec] - for conf_item in conf_sec_list: - if conf_item in config_ref['ubuntu'][conf_sec]: - data[config_ref['ubuntu'][conf_sec][conf_item]] = \ - conf_sec_list[conf_item] + + data = wsl_config_loader(data, "/etc/wsl.conf", "wsl") + data = wsl_config_loader(data, "/etc/ubuntu-wsl.conf", "ubuntu") + if data: def bool_converter(x): return x.lower() == 'true' diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index b33bc9ee..4fe24a64 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -13,10 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import configparser import logging -from os import path - import attr from subiquitycore.context import with_context @@ -25,7 +22,7 @@ from subiquity.common.apidef import API from subiquity.common.types import WSLConfigurationBase from subiquity.server.controller import SubiquityController -from system_setup.common.wsl_utils import config_ref +from system_setup.common.wsl_conf import wsl_config_loader log = logging.getLogger('system_setup.server' + '.controllers.wsl_configuration_base') @@ -53,16 +50,8 @@ class WSLConfigurationBaseController(SubiquityController): # load the config file data = {} - if path.exists('/etc/wsl.conf'): - wslconfig = configparser.ConfigParser() - wslconfig.read('/etc/wsl.conf') - for conf_sec in wslconfig: - if conf_sec in config_ref['wsl']: - conf_sec_list = wslconfig[conf_sec] - for conf_item in conf_sec_list: - if conf_item in config_ref['wsl'][conf_sec]: - data[config_ref['wsl'][conf_sec][conf_item]] = \ - conf_sec_list[conf_item] + data = wsl_config_loader(data, "/etc/wsl.conf", "wsl") + if data: def bool_converter(x): return x.lower() == 'true' From 32a62748c9b58932917aa52492fdee5dd35e1cbb Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Fri, 1 Oct 2021 00:00:32 +0800 Subject: [PATCH 06/10] system_setup: initial redesign of generic config handler Also have to change the logic for default loader --- system_setup/common/wsl_conf.py | 132 ++++++++++++++---- system_setup/server/controllers/configure.py | 41 +----- .../server/controllers/wslconfadvanced.py | 7 +- .../server/controllers/wslconfbase.py | 6 +- 4 files changed, 109 insertions(+), 77 deletions(-) diff --git a/system_setup/common/wsl_conf.py b/system_setup/common/wsl_conf.py index 1dc9e428..2fe00759 100644 --- a/system_setup/common/wsl_conf.py +++ b/system_setup/common/wsl_conf.py @@ -23,11 +23,9 @@ from os import path log = logging.getLogger("system_setup.common.wsl_conf") -config_ref = { +config_base_ref = { "wsl": { "automount": { - "enabled": "automount", - "mountfstab": "mountfstab", "root": "custom_path", "options": "custom_mount_opt", }, @@ -35,6 +33,28 @@ config_ref = { "generatehosts": "gen_host", "generateresolvconf": "gen_resolvconf", }, + } +} + +config_base_default = { + "wsl": { + "automount": { + "root": "/mnt/", + "options": "" + }, + "network": { + "generatehosts": "true", + "generateresolvconf": "true" + } + } +} + +config_adv_ref = { + "wsl": { + "automount": { + "enabled": "automount", + "mountfstab": "mountfstab", + }, "interop": { "enabled": "interop_enabled", "appendwindowspath": "interop_appendwindowspath", @@ -56,8 +76,35 @@ config_ref = { } } +config_adv_default = { + "wsl": { + "automount": { + "enabled": "true", + "mountfstab": "true" + }, + "interop": { + "enabled": "true", + "appendwindowspath": "true" + } + }, + "ubuntu": { + "GUI": { + "theme": "default", + "followwintheme": "false" + }, + "Interop": { + "guiintegration": "false", + "audiointegration": "false", + "advancedipdetection": "false" + }, + "Motd": { + "wslnewsenabled": "true" + } + } +} -def wsl_config_loader(data, pathname, id): + +def wsl_config_loader(data, pathname, config_ref, id): if path.exists(pathname): config = ConfigParser() config.read(pathname) @@ -71,15 +118,30 @@ def wsl_config_loader(data, pathname, id): return data +def default_loader(is_advanced): + data = {} + conf_ref = config_adv_ref if is_advanced else config_base_ref + data = wsl_config_loader(data, "/etc/wsl.conf", conf_ref, "wsl") + if is_advanced: + data = \ + wsl_config_loader(data, "/etc/ubuntu-wsl.conf", conf_ref, "ubuntu") + return data + + class WSLConfig: - def __init__(self, inst_type, conf_file): - self.inst_type = inst_type + def __init__(self, conf_file): self.conf_file = conf_file self.config = ConfigParser() self.config.BasicInterpolcation = None self.config.read(conf_file) + def drop_if_exists(self, config_section, config_setting): + if config_setting in self.config[config_section]: + self.config.remove_option(config_section, config_setting) + with open(self.conf_file, 'w') as configfile: + self.config.write(configfile) + def update(self, config_section, config_setting, config_value): self.config[config_section][config_setting] = config_value with open(self.conf_file, 'w') as configfile: @@ -91,8 +153,8 @@ class WSLConfigHandler: def __init__(self, is_dry_run): self.is_dry_run = is_dry_run self.ubuntu_conf = \ - WSLConfig("ubuntu", "/etc/ubuntu-wsl.conf") - self.wsl_conf = WSLConfig("wsl", "/etc/wsl.conf") + WSLConfig("/etc/ubuntu-wsl.conf") + self.wsl_conf = WSLConfig("/etc/wsl.conf") def _select_config(self, type_input): type_input = type_input.lower() @@ -101,27 +163,39 @@ class WSLConfigHandler: elif type_input == "wsl": return self.wsl_conf else: - raise ValueError("Invalid config name. Please check again.") + raise ValueError("Invalid config type '{}'.".format(type_input)) - def _update(self, config_type, section, config, value): - self._select_config(config_type).update(section, config, value) - - def update(self, config_name, value): + def update(self, config_class): + if self.is_dry_run: + log.debug("mimicking setting config %s", + config_class) + temp_conf_ref = {} + temp_conf_default = {} + test_confname = config_class.__str__() + if test_confname.startswith("WSLConfigurationBase"): + temp_conf_ref = config_base_ref + temp_conf_default = config_base_default + elif test_confname.startswith("WSLConfigurationAdvanced"): + temp_conf_ref = config_adv_ref + temp_conf_default = config_adv_default + else: + raise TypeError("Invalid type name.") if self.is_dry_run: - log.debug("mimicking setting config %s with %s", - config_name, value) return - config_name_set = config_name.split(".") - # it should always be three level: type, section, and config. - if len(config_name_set) == 3: - self._update(config_name_set[0], config_name_set[1], - config_name_set[2], value) - elif len(config_name_set) == 2: # if type is missing, guess - if not (config_name_set[0] in ("ubuntu", "wsl") - and config_name_set[1] == "*"): # no top level wild card - type_name = "ubuntu" if config_name_set[0] in ( - "Motd", "Interop", "GUI") else "wsl" - self._update(type_name, config_name_set[0], - config_name_set[1], value) - else: # invaild name - raise ValueError("Invalid config name '{}'.".format(config_name)) + for config_type in temp_conf_ref: + config_sections = temp_conf_ref[config_type] + for config_section in config_sections: + config_settings = config_sections[config_section] + for config_setting in config_settings: + config_realname = config_settings[config_setting] + config_value = config_class.__dict__[config_realname] + if temp_conf_default[config_type][config_section][ + config_setting] == config_value: + self._select_config(config_type). \ + drop_if_exists(config_section, + config_setting) + else: + self._select_config(config_type). \ + update(config_section, + config_setting, + config_value) diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 721a99ed..3d656f5f 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -83,46 +83,9 @@ class ConfigureController(SubiquityController): "-G", self.get_userandgroups(), wsl_identity.username]) else: - wslconf_ad = self.model.wslconfadvanced.wslconfadvanced - config.update("WSL.automount.enabled", - wslconf_ad.automount) - config.update("WSL.automount.mountfstab", - wslconf_ad.mountfstab) - config.update("WSL.automount.root", - wslconf_ad.custom_path) - config.update("WSL.automount.options", - wslconf_ad.custom_mount_opt) - config.update("WSL.network.generatehosts", - wslconf_ad.gen_host) - config.update("WSL.network.generateresolvconf", - wslconf_ad.gen_resolvconf) - config.update("WSL.interop.enabled", - wslconf_ad.interop_enabled) - config.update( - "WSL.interop.appendwindowspath", - wslconf_ad.interop_appendwindowspath) - config.update("ubuntu.GUI.followwintheme", - wslconf_ad.gui_followwintheme) - config.update("ubuntu.GUI.theme", - wslconf_ad.gui_theme) - config.update("ubuntu.Interop.guiintergration", - wslconf_ad.legacy_gui) - config.update("ubuntu.Interop.audiointegration", - wslconf_ad.legacy_audio) - config.update("ubuntu.Interop.advancedipdetection", - wslconf_ad.adv_ip_detect) - config.update("ubuntu.Motd.wslnewsenabled", - wslconf_ad.wsl_motd_news) + config.update(self.model.wslconfadvanced.wslconfadvanced) - wslconf_base = self.model.wslconfbase.wslconfbase - config.update("WSL.automount.root", - wslconf_base.custom_path) - config.update("WSL.automount.options", - wslconf_base.custom_mount_opt) - config.update("WSL.network.generatehosts", - wslconf_base.gen_host) - config.update("WSL.network.generateresolvconf", - wslconf_base.gen_resolvconf) + config.update(self.model.wslconfbase.wslconfbase) self.app.update_state(ApplicationState.DONE) except Exception: diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index 15b2b3b1..29a9825a 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -22,7 +22,7 @@ from subiquity.common.apidef import API from subiquity.common.types import WSLConfigurationAdvanced from subiquity.server.controller import SubiquityController -from system_setup.common.wsl_conf import wsl_config_loader +from system_setup.common.wsl_conf import default_loader log = logging.getLogger( 'system_setup.server.controllers.wsl_configuration_advanced') @@ -54,10 +54,7 @@ class WSLConfigurationAdvancedController(SubiquityController): super().__init__(app) # load the config file - data = {} - - data = wsl_config_loader(data, "/etc/wsl.conf", "wsl") - data = wsl_config_loader(data, "/etc/ubuntu-wsl.conf", "ubuntu") + data = default_loader(True) if data: def bool_converter(x): diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index 4fe24a64..bbe9c593 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -22,7 +22,7 @@ from subiquity.common.apidef import API from subiquity.common.types import WSLConfigurationBase from subiquity.server.controller import SubiquityController -from system_setup.common.wsl_conf import wsl_config_loader +from system_setup.common.wsl_conf import default_loader log = logging.getLogger('system_setup.server' + '.controllers.wsl_configuration_base') @@ -48,9 +48,7 @@ class WSLConfigurationBaseController(SubiquityController): super().__init__(app) # load the config file - data = {} - - data = wsl_config_loader(data, "/etc/wsl.conf", "wsl") + data = default_loader(False) if data: def bool_converter(x): From 9fbff87fe1cdaf17269ff97c60dec268bd158584 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Fri, 1 Oct 2021 00:19:05 +0800 Subject: [PATCH 07/10] system_setup: changes to the get-usersandgroups --- system_setup/common/wsl_utils.py | 21 ++++++++++++++++++++ system_setup/server/controllers/configure.py | 21 ++------------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/system_setup/common/wsl_utils.py b/system_setup/common/wsl_utils.py index f6a393ad..a19953b1 100644 --- a/system_setup/common/wsl_utils.py +++ b/system_setup/common/wsl_utils.py @@ -18,6 +18,8 @@ import os import logging import subprocess +from subiquity.common.resources import resource_path + log = logging.getLogger("subiquity.system_setup.common.wsl_utils") @@ -59,3 +61,22 @@ def get_windows_locale(): except OSError as e: log.info(windows_locale_failed_msg + e.strerror) return None + + +def get_userandgroups(): + usergroups_path = resource_path('users-and-groups') + build_usergroups_path = \ + os.path.realpath(__file__ + '/../../../users-and-groups') + if os.path.isfile(build_usergroups_path): + usergroups_path = build_usergroups_path + + user_groups = set() + if os.path.exists(usergroups_path): + with open(usergroups_path) as fp: + for line in fp: + line = line.strip() + if line.startswith('#') or not line: + continue + user_groups.add(line) + oneline_usergroups = ",".join(user_groups) + return oneline_usergroups diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 3d656f5f..ef90c547 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -14,7 +14,6 @@ # along with this program. If not, see . import logging -import os from subiquity.common.errorreport import ErrorReportKind from subiquity.common.types import ApplicationState @@ -22,6 +21,7 @@ from subiquity.server.controller import SubiquityController from subiquitycore.context import with_context from subiquitycore.utils import run_command from system_setup.common.wsl_conf import WSLConfigHandler +from system_setup.common.wsl_utils import get_userandgroups log = logging.getLogger("system_setup.server.controllers.configure") @@ -80,7 +80,7 @@ class ConfigureController(SubiquityController): wsl_identity.username]) run_command(["/usr/sbin/usermod", "-a", "-c", wsl_identity.realname, - "-G", self.get_userandgroups(), + "-G", get_userandgroups(), wsl_identity.username]) else: config.update(self.model.wslconfadvanced.wslconfadvanced) @@ -94,23 +94,6 @@ class ConfigureController(SubiquityController): ErrorReportKind.INSTALL_FAIL, "configuration failed", **kw) raise - def get_userandgroups(self): - usergroups_path = '/usr/share/subiquity/users-and-groups' - build_usergroups_path = \ - os.path.realpath(__file__ + '/../../../users-and-groups') - if os.path.isfile(build_usergroups_path): - usergroups_path = build_usergroups_path - user_groups = set() - if os.path.exists(usergroups_path): - with open(usergroups_path) as fp: - for line in fp: - line = line.strip() - if line.startswith('#') or not line: - continue - user_groups.add(line) - oneline_usergroups = ",".join(user_groups) - return oneline_usergroups - def stop_uu(self): # This is a no-op to allow Shutdown controller to depend on this one pass From 5c0e64e78a0fcb4110da0bf69437b65a570be206 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Mon, 4 Oct 2021 15:23:02 +0800 Subject: [PATCH 08/10] system_setup: address the run_command fail issue --- system_setup/server/controllers/configure.py | 28 +++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index ef90c547..7193c4eb 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -70,18 +70,28 @@ class ConfigureController(SubiquityController): variant = self.app.variant config = WSLConfigHandler(dryrun) if variant == "wsl_setup": - wsl_identity = self.model.identity.user + wsl_id = self.model.identity.user if dryrun: log.debug("mimicking creating user %s", - wsl_identity.username) + wsl_id.username) else: - run_command(["/usr/sbin/useradd", "-m", "-s", "/bin/bash", - "-p", wsl_identity.password, - wsl_identity.username]) - run_command(["/usr/sbin/usermod", "-a", - "-c", wsl_identity.realname, - "-G", get_userandgroups(), - wsl_identity.username]) + create_user_act = \ + run_command(["/usr/sbin/useradd", "-m", "-s", + "/bin/bash", "-p", + wsl_id.password, + wsl_id.username]) + if create_user_act.returncode != 0: + raise Exception("Failed to create user %s" + % wsl_id.username) + log.debug("created user %s", wsl_id.username) + assign_grp_act = \ + run_command(["/usr/sbin/usermod", "-a", + "-c", wsl_id.realname, + "-G", get_userandgroups(), + wsl_id.username]) + if assign_grp_act.returncode != 0: + raise Exception("Failed to assign groups to user %s" % + wsl_id.username) else: config.update(self.model.wslconfadvanced.wslconfadvanced) From 1a7274dbba1ec89ad2e08366ce83259b7da4f348 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Mon, 4 Oct 2021 18:55:25 +0800 Subject: [PATCH 09/10] system_setup: unify api names and simply WSLconfig class into function --- examples/answers-system-setup.yaml | 8 +- subiquity/common/types.py | 20 +- .../client/controllers/wslconfadvanced.py | 21 +- .../client/controllers/wslconfbase.py | 13 +- system_setup/common/wsl_conf.py | 203 ++++++++---------- system_setup/models/wslconfadvanced.py | 24 +-- system_setup/models/wslconfbase.py | 16 +- system_setup/server/controllers/configure.py | 8 +- .../server/controllers/wslconfadvanced.py | 66 +++--- .../server/controllers/wslconfbase.py | 36 ++-- system_setup/ui/views/wslconfadvanced.py | 124 +++++------ system_setup/ui/views/wslconfbase.py | 48 +++-- 12 files changed, 293 insertions(+), 294 deletions(-) diff --git a/examples/answers-system-setup.yaml b/examples/answers-system-setup.yaml index 822ba174..05325d79 100644 --- a/examples/answers-system-setup.yaml +++ b/examples/answers-system-setup.yaml @@ -6,9 +6,9 @@ WSLIdentity: # ubuntu password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1' WSLConfigurationBase: - custom_path: '/custom_mnt_path' - custom_mount_opt: 'metadata' - gen_host: false - gen_resolvconf: false + automount_root: '/custom_mnt_path' + automount_options: 'metadata' + network_generatehosts: false + network_generateresolvconf: false Summary: reboot: yes \ No newline at end of file diff --git a/subiquity/common/types.py b/subiquity/common/types.py index ee230158..edf17fbe 100644 --- a/subiquity/common/types.py +++ b/subiquity/common/types.py @@ -356,21 +356,21 @@ class ShutdownMode(enum.Enum): @attr.s(auto_attribs=True) class WSLConfigurationBase: - custom_path: str = attr.ib(default='/mnt/') - custom_mount_opt: str = '' - gen_host: bool = attr.ib(default=True) - gen_resolvconf: bool = attr.ib(default=True) + automount_root: str = attr.ib(default='/mnt/') + automount_options: str = '' + network_generatehosts: bool = attr.ib(default=True) + network_generateresolvconf: bool = attr.ib(default=True) @attr.s(auto_attribs=True) class WSLConfigurationAdvanced: gui_theme: str = attr.ib(default='default') gui_followwintheme: bool = attr.ib(default=True) - legacy_gui: bool = attr.ib(default=False) - legacy_audio: bool = attr.ib(default=False) - adv_ip_detect: bool = attr.ib(default=False) - wsl_motd_news: bool = attr.ib(default=True) - automount: bool = attr.ib(default=True) - mountfstab: bool = attr.ib(default=True) + interop_guiintegration: bool = attr.ib(default=False) + interop_audiointegration: bool = attr.ib(default=False) + interop_advancedipdetection: bool = attr.ib(default=False) + motd_wslnewsenabled: bool = attr.ib(default=True) + automount_enabled: bool = attr.ib(default=True) + automount_mountfstab: bool = attr.ib(default=True) interop_enabled: bool = attr.ib(default=True) interop_appendwindowspath: bool = attr.ib(default=True) diff --git a/system_setup/client/controllers/wslconfadvanced.py b/system_setup/client/controllers/wslconfadvanced.py index 41eef92c..b1b012dd 100644 --- a/system_setup/client/controllers/wslconfadvanced.py +++ b/system_setup/client/controllers/wslconfadvanced.py @@ -33,21 +33,24 @@ class WSLConfigurationAdvancedController(SubiquityTuiController): def run_answers(self): if all(elem in self.answers for elem in ['interop_enabled', 'interop_appendwindowspath', - 'gui_theme', 'gui_followwintheme', 'legacy_gui', - 'legacy_audio', 'adv_ip_detect', - 'wsl_motd_news', 'automount', 'mountfstab']): + 'gui_theme', 'gui_followwintheme', 'interop_guiintegration', + 'interop_audiointegration', 'interop_advancedipdetection', + 'motd_wslnewsenabled', 'automount_enabled', + 'automount_mountfstab']): reconfiguration = WSLConfigurationAdvanced( interop_enabled=self.answers['interop_enabled'], interop_appendwindowspath=self .answers['interop_appendwindowspath'], gui_theme=self.answers['gui_theme'], gui_followwintheme=self.answers['gui_followwintheme'], - legacy_gui=self.answers['legacy_gui'], - legacy_audio=self.answers['legacy_audio'], - adv_ip_detect=self.answers['adv_ip_detect'], - wsl_motd_news=self.answers['wsl_motd_news'], - automount=self.answers['automount'], - mountfstab=self.answers['mountfstab'] + interop_guiintegration=self.answers['interop_guiintegration'], + interop_audiointegration=self + .answers['interop_audiointegration'], + interop_advancedipdetection=self + .answers['interop_advancedipdetection'], + motd_wslnewsenabled=self.answers['motd_wslnewsenabled'], + automount_enabled=self.answers['automount_enabled'], + automount_mountfstab=self.answers['automount_mountfstab'] ) self.done(reconfiguration) diff --git a/system_setup/client/controllers/wslconfbase.py b/system_setup/client/controllers/wslconfbase.py index a83efc0d..2afacd2f 100644 --- a/system_setup/client/controllers/wslconfbase.py +++ b/system_setup/client/controllers/wslconfbase.py @@ -16,13 +16,14 @@ class WSLConfigurationBaseController(SubiquityTuiController): def run_answers(self): if all(elem in self.answers for elem in - ['custom_path', 'custom_mount_opt', - 'gen_host', 'gen_resolvconf']): + ['automount_root', 'automount_options', + 'network_generatehosts', 'network_generateresolvconf']): configuration = WSLConfigurationBase( - custom_path=self.answers['custom_path'], - custom_mount_opt=self.answers['custom_mount_opt'], - gen_host=self.answers['gen_host'], - gen_resolvconf=self.answers['gen_resolvconf']) + automount_root=self.answers['automount_root'], + automount_options=self.answers['automount_options'], + network_generatehosts=self.answers['network_generatehosts'], + network_generateresolvconf=self + .answers['network_generateresolvconf']) self.done(configuration) def done(self, configuration_data): diff --git a/system_setup/common/wsl_conf.py b/system_setup/common/wsl_conf.py index 2fe00759..4bd7e003 100644 --- a/system_setup/common/wsl_conf.py +++ b/system_setup/common/wsl_conf.py @@ -17,25 +17,12 @@ # original code from ubuntuwslctl.core.loader # Copyright (C) 2021 Canonical Ltd. +import os import logging from configparser import ConfigParser -from os import path log = logging.getLogger("system_setup.common.wsl_conf") -config_base_ref = { - "wsl": { - "automount": { - "root": "custom_path", - "options": "custom_mount_opt", - }, - "network": { - "generatehosts": "gen_host", - "generateresolvconf": "gen_resolvconf", - }, - } -} - config_base_default = { "wsl": { "automount": { @@ -49,33 +36,6 @@ config_base_default = { } } -config_adv_ref = { - "wsl": { - "automount": { - "enabled": "automount", - "mountfstab": "mountfstab", - }, - "interop": { - "enabled": "interop_enabled", - "appendwindowspath": "interop_appendwindowspath", - } - }, - "ubuntu": { - "GUI": { - "theme": "gui_theme", - "followwintheme": "gui_followwintheme", - }, - "Interop": { - "guiintegration": "legacy_gui", - "audiointegration": "legacy_audio", - "advancedipdetection": "adv_ip_detect", - }, - "Motd": { - "wslnewsenabled": "wsl_motd_news", - } - } -} - config_adv_default = { "wsl": { "automount": { @@ -105,22 +65,38 @@ config_adv_default = { def wsl_config_loader(data, pathname, config_ref, id): - if path.exists(pathname): - config = ConfigParser() - config.read(pathname) - for conf_sec in config: - if conf_sec in config_ref[id]: - conf_sec_list = config[conf_sec] - for conf_item in conf_sec_list: - if conf_item in config_ref[id][conf_sec]: - data[config_ref[id][conf_sec][conf_item]] = \ - conf_sec_list[conf_item] + """ + Loads the configuration from the given file type, + section and reference config. + + :param data: dict, the data to load into + :param pathname: string, the path to the file to load + :param id: string, the name of the section to load + """ + if not os.path.exists(pathname): + return data + config = ConfigParser() + config.read(pathname) + for conf_sec in config: + if conf_sec in config_ref[id]: + conf_sec_list = config[conf_sec] + for conf_item in conf_sec_list: + if conf_item in config_ref[id][conf_sec]: + data[conf_sec.lower() + + "_" + conf_item.lower()] = \ + conf_sec_list[conf_item] return data def default_loader(is_advanced): + """ + This will load the default WSL config for the given type. + + :param is_advanced: boolean, True if it is WSLConfigurationAdvanced, + else is WSLConfigurationBase + """ data = {} - conf_ref = config_adv_ref if is_advanced else config_base_ref + conf_ref = config_adv_default if is_advanced else config_base_default data = wsl_config_loader(data, "/etc/wsl.conf", conf_ref, "wsl") if is_advanced: data = \ @@ -128,74 +104,67 @@ def default_loader(is_advanced): return data -class WSLConfig: - def __init__(self, conf_file): - self.conf_file = conf_file +# TODO: remove dryrun and add root param once we write the option to .subiquity +def wsl_config_update(config_class, is_dry_run): + """ + This update the configuration file for the given class.zzd - self.config = ConfigParser() - self.config.BasicInterpolcation = None - self.config.read(conf_file) + :param config_class: WSLConfigurationBase or WSLConfigurationAdvanced + :param is_dry_run: boolean, True if it is a dry run + """ + if is_dry_run: + log.debug("mimicking setting config %s", config_class) + temp_conf_default = {} + temp_confname = config_class.__str__() + if temp_confname.startswith("WSLConfigurationBase"): + temp_conf_default = config_base_default + elif temp_confname.startswith("WSLConfigurationAdvanced"): + temp_conf_default = config_adv_default + else: + raise TypeError("Invalid type name.") + if is_dry_run: + return - def drop_if_exists(self, config_section, config_setting): - if config_setting in self.config[config_section]: - self.config.remove_option(config_section, config_setting) - with open(self.conf_file, 'w') as configfile: - self.config.write(configfile) + # update the config file + for config_type in temp_conf_default: + config_sections = temp_conf_default[config_type] - def update(self, config_section, config_setting, config_value): - self.config[config_section][config_setting] = config_value - with open(self.conf_file, 'w') as configfile: - self.config.write(configfile) + config = ConfigParser() + config.BasicInterpolcation = None - -class WSLConfigHandler: - - def __init__(self, is_dry_run): - self.is_dry_run = is_dry_run - self.ubuntu_conf = \ - WSLConfig("/etc/ubuntu-wsl.conf") - self.wsl_conf = WSLConfig("/etc/wsl.conf") - - def _select_config(self, type_input): - type_input = type_input.lower() - if type_input == "ubuntu": - return self.ubuntu_conf - elif type_input == "wsl": - return self.wsl_conf + if config_type == "wsl": + conf_file = "/etc/wsl.conf" + elif config_type == "ubuntu": + conf_file = "/etc/ubuntu-wsl.conf" else: - raise ValueError("Invalid config type '{}'.".format(type_input)) + raise TypeError("Invalid type name " % config_type) - def update(self, config_class): - if self.is_dry_run: - log.debug("mimicking setting config %s", - config_class) - temp_conf_ref = {} - temp_conf_default = {} - test_confname = config_class.__str__() - if test_confname.startswith("WSLConfigurationBase"): - temp_conf_ref = config_base_ref - temp_conf_default = config_base_default - elif test_confname.startswith("WSLConfigurationAdvanced"): - temp_conf_ref = config_adv_ref - temp_conf_default = config_adv_default - else: - raise TypeError("Invalid type name.") - if self.is_dry_run: - return - for config_type in temp_conf_ref: - config_sections = temp_conf_ref[config_type] - for config_section in config_sections: - config_settings = config_sections[config_section] - for config_setting in config_settings: - config_realname = config_settings[config_setting] - config_value = config_class.__dict__[config_realname] - if temp_conf_default[config_type][config_section][ - config_setting] == config_value: - self._select_config(config_type). \ - drop_if_exists(config_section, - config_setting) - else: - self._select_config(config_type). \ - update(config_section, - config_setting, - config_value) + config.read(conf_file) + + for config_section in config_sections: + config_settings = config_sections[config_section] + for config_setting in config_settings: + config_default_value = config_settings[config_setting] + config_api_name = \ + config_section.lower() + "_" + config_setting.lower() + config_value = config_class.__dict__[config_api_name] + # if the value for the setting is defualt value, drop it + if config_default_value == config_value: + if config_setting in config[config_section]: + config.remove_option(config_section, config_setting) + # drop the section if it become empty + if config[config_section] == {}: + config.remove_section(config_section) + else: + if config_section not in config: + config.add_section(config_section) + if isinstance(config_value, bool): + config_value = str(config_value).lower() + config[config_section][config_setting] = config_value + + with open(conf_file + ".new", 'w+') as configfile: + config.write(configfile) + + if os.isfile(conf_file): + os.rename(conf_file, conf_file + ".old") + os.move(conf_file + ".new", conf_file) diff --git a/system_setup/models/wslconfadvanced.py b/system_setup/models/wslconfadvanced.py index cc6852a0..167551c6 100644 --- a/system_setup/models/wslconfadvanced.py +++ b/system_setup/models/wslconfadvanced.py @@ -23,12 +23,12 @@ log = logging.getLogger('system_setup.models.wsl_configuration_advanced') class WSLConfigurationAdvanced(object): gui_theme = attr.ib() gui_followwintheme = attr.ib() - legacy_gui = attr.ib() - legacy_audio = attr.ib() - adv_ip_detect = attr.ib() - wsl_motd_news = attr.ib() - automount = attr.ib() - mountfstab = attr.ib() + interop_guiintegration = attr.ib() + interop_audiointegration = attr.ib() + interop_advancedipdetection = attr.ib() + motd_wslnewsenabled = attr.ib() + automount_enabled = attr.ib() + automount_mountfstab = attr.ib() interop_enabled = attr.ib() interop_appendwindowspath = attr.ib() @@ -48,12 +48,12 @@ class WSLConfigurationAdvancedModel(object): d['interop_appendwindowspath'] = result.interop_appendwindowspath d['gui_theme'] = result.gui_theme d['gui_followwintheme'] = result.gui_followwintheme - d['legacy_gui'] = result.legacy_gui - d['legacy_audio'] = result.legacy_audio - d['adv_ip_detect'] = result.adv_ip_detect - d['wsl_motd_news'] = result.wsl_motd_news - d['automount'] = result.automount - d['mountfstab'] = result.mountfstab + d['interop_guiintegration'] = result.interop_guiintegration + d['interop_audiointegration'] = result.interop_audiointegration + d['interop_advancedipdetection'] = result.interop_advancedipdetection + d['motd_wslnewsenabled'] = result.motd_wslnewsenabled + d['automount_enabled'] = result.automount_enabled + d['automount_mountfstab'] = result.automount_mountfstab self._wslconfadvanced = WSLConfigurationAdvanced(**d) @property diff --git a/system_setup/models/wslconfbase.py b/system_setup/models/wslconfbase.py index 01f2ca94..5162c943 100644 --- a/system_setup/models/wslconfbase.py +++ b/system_setup/models/wslconfbase.py @@ -21,10 +21,10 @@ log = logging.getLogger('system_setup.models.wsl_configuration_base') @attr.s class WSLConfigurationBase(object): - custom_path = attr.ib() - custom_mount_opt = attr.ib() - gen_host = attr.ib() - gen_resolvconf = attr.ib() + automount_root = attr.ib() + automount_options = attr.ib() + network_generatehosts = attr.ib() + network_generateresolvconf = attr.ib() class WSLConfigurationBaseModel(object): @@ -37,10 +37,10 @@ class WSLConfigurationBaseModel(object): def apply_settings(self, result): d = {} - d['custom_path'] = result.custom_path - d['custom_mount_opt'] = result.custom_mount_opt - d['gen_host'] = result.gen_host - d['gen_resolvconf'] = result.gen_resolvconf + d['automount_root'] = result.automount_root + d['automount_options'] = result.automount_options + d['network_generatehosts'] = result.network_generatehosts + d['network_generateresolvconf'] = result.network_generateresolvconf self._wslconfbase = WSLConfigurationBase(**d) @property diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index 7193c4eb..c20fadd3 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -20,7 +20,7 @@ from subiquity.common.types import ApplicationState from subiquity.server.controller import SubiquityController from subiquitycore.context import with_context from subiquitycore.utils import run_command -from system_setup.common.wsl_conf import WSLConfigHandler +from system_setup.common.wsl_conf import wsl_config_update from system_setup.common.wsl_utils import get_userandgroups log = logging.getLogger("system_setup.server.controllers.configure") @@ -68,7 +68,6 @@ class ConfigureController(SubiquityController): dryrun = self.app.opts.dry_run variant = self.app.variant - config = WSLConfigHandler(dryrun) if variant == "wsl_setup": wsl_id = self.model.identity.user if dryrun: @@ -93,9 +92,10 @@ class ConfigureController(SubiquityController): raise Exception("Failed to assign groups to user %s" % wsl_id.username) else: - config.update(self.model.wslconfadvanced.wslconfadvanced) + wsl_config_update(self.model.wslconfadvanced.wslconfadvanced, + dryrun) - config.update(self.model.wslconfbase.wslconfbase) + wsl_config_update(self.model.wslconfbase.wslconfbase, dryrun) self.app.update_state(ApplicationState.DONE) except Exception: diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index 29a9825a..f8a3b615 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -40,12 +40,12 @@ class WSLConfigurationAdvancedController(SubiquityController): 'interop_appendwindowspath': {'type': 'boolean'}, 'gui_theme': {'type': 'string'}, 'gui_followwintheme': {'type': 'boolean'}, - 'legacy_gui': {'type': 'boolean'}, - 'legacy_audio': {'type': 'boolean'}, - 'adv_ip_detect': {'type': 'boolean'}, - 'wsl_motd_news': {'type': 'boolean'}, - 'automount': {'type': 'boolean'}, - 'mountfstab': {'type': 'boolean'} + 'interop_guiintegration': {'type': 'boolean'}, + 'interop_audiointegration': {'type': 'boolean'}, + 'interop_advancedipdetection': {'type': 'boolean'}, + 'motd_wslnewsenabled': {'type': 'boolean'}, + 'automount_enabled': {'type': 'boolean'}, + 'automount_mountfstab': {'type': 'boolean'} }, 'additionalProperties': False, } @@ -65,12 +65,17 @@ class WSLConfigurationAdvancedController(SubiquityController): data['interop_appendwindowspath']), gui_theme=data['gui_theme'], gui_followwintheme=bool_converter(data['gui_followwintheme']), - legacy_gui=bool_converter(data['legacy_gui']), - legacy_audio=bool_converter(data['legacy_audio']), - adv_ip_detect=bool_converter(data['adv_ip_detect']), - wsl_motd_news=bool_converter(data['wsl_motd_news']), - automount=bool_converter(data['automount']), - mountfstab=bool_converter(data['mountfstab']), + interop_guiintegration=bool_converter( + data['interop_guiintegration']), + interop_audiointegration=bool_converter( + data['interop_audiointegration']), + interop_advancedipdetection=bool_converter( + data['interop_advancedipdetection']), + motd_wslnewsenabled=bool_converter( + data['motd_wslnewsenabled']), + automount_enabled=bool_converter(data['automount_enabled']), + automount_mountfstab=bool_converter( + data['automount_mountfstab']), ) self.model.apply_settings(reconf_data) @@ -81,12 +86,13 @@ class WSLConfigurationAdvancedController(SubiquityController): interop_appendwindowspath=data['interop_appendwindowspath'], gui_theme=data['gui_theme'], gui_followwintheme=data['gui_followwintheme'], - legacy_gui=data['legacy_gui'], - legacy_audio=data['legacy_audio'], - adv_ip_detect=data['adv_ip_detect'], - wsl_motd_news=data['wsl_motd_news'], - automount=data['automount'], - mountfstab=data['mountfstab'] + interop_guiintegration=data['interop_guiintegration'], + interop_audiointegration=data['interop_audiointegration'], + interop_advancedipdetection=data[ + 'interop_advancedipdetection'], + motd_wslnewsenabled=data['motd_wslnewsenabled'], + automount_enabled=data['automount_enabled'], + automount_mountfstab=data['automount_mountfstab'] ) self.model.apply_settings(reconf_data) @@ -101,18 +107,26 @@ class WSLConfigurationAdvancedController(SubiquityController): async def GET(self) -> WSLConfigurationAdvanced: data = WSLConfigurationAdvanced() if self.model.wslconfadvanced is not None: - data.interop_enabled = self.model.wslconfadvanced.interop_enabled + data.interop_enabled = \ + self.model.wslconfadvanced.interop_enabled data.interop_appendwindowspath = \ self.model.wslconfadvanced.interop_appendwindowspath - data.gui_theme = self.model.wslconfadvanced.gui_theme + data.gui_theme = \ + self.model.wslconfadvanced.gui_theme data.gui_followwintheme = \ self.model.wslconfadvanced.gui_followwintheme - data.legacy_gui = self.model.wslconfadvanced.legacy_gui - data.legacy_audio = self.model.wslconfadvanced.legacy_audio - data.adv_ip_detect = self.model.wslconfadvanced.adv_ip_detect - data.wsl_motd_news = self.model.wslconfadvanced.wsl_motd_news - data.automount = self.model.wslconfadvanced.automount - data.mountfstab = self.model.wslconfadvanced.mountfstab + data.interop_guiintegration = \ + self.model.wslconfadvanced.interop_guiintegration + data.interop_audiointegration = \ + self.model.wslconfadvanced.interop_audiointegration + data.interop_advancedipdetection = \ + self.model.wslconfadvanced.interop_advancedipdetection + data.motd_wslnewsenabled = \ + self.model.wslconfadvanced.motd_wslnewsenabled + data.automount_enabled = \ + self.model.wslconfadvanced.automount_enabled + data.automount_mountfstab = \ + self.model.wslconfadvanced.automount_mountfstab return data async def POST(self, data: WSLConfigurationAdvanced): diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index bbe9c593..d78f9a90 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -36,10 +36,10 @@ class WSLConfigurationBaseController(SubiquityController): autoinstall_schema = { 'type': 'object', 'properties': { - 'custom_path': {'type': 'string'}, - 'custom_mount_opt': {'type': 'string'}, - 'gen_host': {'type': 'boolean'}, - 'gen_resolvconf': {'type': 'boolean'}, + 'automount_root': {'type': 'string'}, + 'automount_options': {'type': 'string'}, + 'network_generatehosts': {'type': 'boolean'}, + 'network_generateresolvconf': {'type': 'boolean'}, }, 'additionalProperties': False, } @@ -54,20 +54,22 @@ class WSLConfigurationBaseController(SubiquityController): def bool_converter(x): return x.lower() == 'true' conf_data = WSLConfigurationBase( - custom_path=data['custom_path'], - custom_mount_opt=data['custom_mount_opt'], - gen_host=bool_converter(data['gen_host']), - gen_resolvconf=bool_converter(data['gen_resolvconf']), + automount_root=data['automount_root'], + automount_options=data['automount_options'], + network_generatehosts=bool_converter( + data['network_generatehosts']), + network_generateresolvconf=bool_converter( + data['network_generateresolvconf']), ) self.model.apply_settings(conf_data) def load_autoinstall_data(self, data): if data is not None: identity_data = WSLConfigurationBase( - custom_path=data['custom_path'], - custom_mount_opt=data['custom_mount_opt'], - gen_host=data['gen_host'], - gen_resolvconf=data['gen_resolvconf'], + automount_root=data['automount_root'], + automount_options=data['automount_options'], + network_generatehosts=data['network_generatehosts'], + network_generateresolvconf=data['network_generateresolvconf'], ) self.model.apply_settings(identity_data) @@ -82,10 +84,12 @@ class WSLConfigurationBaseController(SubiquityController): async def GET(self) -> WSLConfigurationBase: data = WSLConfigurationBase() if self.model.wslconfbase is not None: - data.custom_path = self.model.wslconfbase.custom_path - data.custom_mount_opt = self.model.wslconfbase.custom_mount_opt - data.gen_host = self.model.wslconfbase.gen_host - data.gen_resolvconf = self.model.wslconfbase.gen_resolvconf + data.automount_root = self.model.wslconfbase.automount_root + data.automount_options = self.model.wslconfbase.automount_options + data.network_generatehosts = \ + self.model.wslconfbase.network_generatehosts + data.network_generateresolvconf = \ + self.model.wslconfbase.network_generateresolvconf return data async def POST(self, data: WSLConfigurationBase): diff --git a/system_setup/ui/views/wslconfadvanced.py b/system_setup/ui/views/wslconfadvanced.py index fc4f2170..afa87fd8 100644 --- a/system_setup/ui/views/wslconfadvanced.py +++ b/system_setup/ui/views/wslconfadvanced.py @@ -42,55 +42,53 @@ class WSLConfigurationAdvancedForm(Form): def __init__(self, initial): super().__init__(initial=initial) - automount = BooleanField(_("Enable Auto-Mount"), - help=_("Whether the Auto-Mount freature is" - " enabled. This feature allows you " - "to mount Windows drive in WSL")) - mountfstab = BooleanField(_("Mount `/etc/fstab`"), - help=_("Whether `/etc/fstab` will be mounted." - " The configuration file `/etc/fstab` " - "contains the necessary information to" - " automate the process of mounting " - "partitions. ")) - interop_enabled = BooleanField(_("Enable Interop"), - help=_("Whether the interoperability is" - " enabled")) - interop_appendwindowspath = BooleanField(_("Append Windows Path"), - help=_("Whether Windows Path " - "will be append in the" - " PATH environment " - "variable in WSL.")) - gui_theme = ChoiceField(_("GUI Theme"), - help=_("This option changes the Ubuntu theme."), - choices=["default", "light", "dark"]) - gui_followwintheme = BooleanField(_("Follow Windows Theme"), - help=_("This option manages whether the" - " Ubuntu theme follows the " - "Windows theme; that is, when " - "Windows uses dark theme, " - "Ubuntu also uses dark theme." - " Requires WSL interoperability" - " enabled. ")) - legacy_gui = BooleanField(_("Legacy GUI Integration"), - help=_("This option enables the Legacy GUI " - "Integration on Windows 10. Requires" - " a Third-party X Server.")) - legacy_audio = BooleanField(_("Legacy Audio Integration"), - help=_("This option enables the Legacy " - "Audio Integration on Windows 10. " - "Requires PulseAudio for " - "Windows Installed.")) - adv_ip_detect = BooleanField(_("Advanced IP Detection"), - help=_("This option enables advanced " - "detection of IP by Windows " - "IPv4 Address which is more " - "reliable to use with WSL2. " - "Requires WSL interoperability" - " enabled.")) - wsl_motd_news = BooleanField(_("Enable WSL News"), - help=_("This options allows you to control" - " your MOTD News. Toggling it on " - "allows you to see the MOTD.")) + automount_enabled = \ + BooleanField(_("Enable Auto-Mount"), + help=_("Whether the Auto-Mount freature is enabled. " + "This feature allows you to mount Windows drive" + " in WSL.")) + automount_mountfstab = \ + BooleanField(_("Mount `/etc/fstab`"), + help=_("Whether `/etc/fstab` will be mounted. The " + "configuration file `/etc/fstab` contains " + "the necessary information to automate the" + " process of mounting partitions. ")) + interop_enabled = \ + BooleanField(_("Enable Interop"), + help=_("Whether the interoperability is enabled")) + interop_appendwindowspath = \ + BooleanField(_("Append Windows Path"), + help=_("Whether Windows Path will be append in the" + " PATH environment variable in WSL.")) + gui_theme = \ + ChoiceField(_("GUI Theme"), + help=_("This option changes the Ubuntu theme."), + choices=["default", "light", "dark"]) + gui_followwintheme = \ + BooleanField(_("Follow Windows Theme"), + help=_("This option manages whether the Ubuntu theme" + " follows the Windows theme; that is, when " + "Windows uses dark theme, Ubuntu also uses dark" + " theme. Requires WSL interoperability enabled. ")) + interop_guiintegration = \ + BooleanField(_("Legacy GUI Integration"), + help=_("This option enables the Legacy GUI Integration " + "on Windows 10. Requires a Third-party X Server.")) + interop_audiointegration = \ + BooleanField(_("Legacy Audio Integration"), + help=_("This option enables the Legacy Audio Integration " + "on Windows 10. Requires PulseAudio for Windows " + "Installed.")) + interop_advancedipdetection = \ + BooleanField(_("Advanced IP Detection"), + help=_("This option enables advanced detection of IP by " + "Windows IPv4 Address which is more reliable to " + "use with WSL2. Requires WSL interoperability " + "enabled.")) + motd_wslnewsenabled = \ + BooleanField(_("Enable WSL News"), + help=_("This option allows you to control your MOTD News." + " Toggling it on allows you to see the MOTD.")) class WSLConfigurationAdvancedView(BaseView): @@ -107,12 +105,15 @@ class WSLConfigurationAdvancedView(BaseView): configuration_data.interop_appendwindowspath, 'gui_theme': configuration_data.gui_theme, 'gui_followwintheme': configuration_data.gui_followwintheme, - 'legacy_gui': configuration_data.legacy_gui, - 'legacy_audio': configuration_data.legacy_audio, - 'adv_ip_detect': configuration_data.adv_ip_detect, - 'wsl_motd_news': configuration_data.wsl_motd_news, - 'automount': configuration_data.automount, - 'mountfstab': configuration_data.mountfstab, + 'interop_guiintegration': configuration_data + .interop_guiintegration, + 'interop_audiointegration': configuration_data + .interop_audiointegration, + 'interop_advancedipdetection': configuration_data + .interop_advancedipdetection, + 'motd_wslnewsenabled': configuration_data.motd_wslnewsenabled, + 'automount_enabled': configuration_data.automount_enabled, + 'automount_mountfstab': configuration_data.automount_mountfstab, } self.form = WSLConfigurationAdvancedForm(initial=initial) @@ -133,10 +134,11 @@ class WSLConfigurationAdvancedView(BaseView): .interop_appendwindowspath.value, gui_theme=self.form.gui_theme.value, gui_followwintheme=self.form.gui_followwintheme.value, - legacy_gui=self.form.legacy_gui.value, - legacy_audio=self.form.legacy_audio.value, - adv_ip_detect=self.form.adv_ip_detect.value, - wsl_motd_news=self.form.wsl_motd_news.value, - automount=self.form.automount.value, - mountfstab=self.form.mountfstab.value, + interop_guiintegration=self.form.interop_guiintegration.value, + interop_audiointegration=self.form.interop_audiointegration.value, + interop_advancedipdetection=self + .form.interop_advancedipdetection.value, + motd_wslnewsenabled=self.form.motd_wslnewsenabled.value, + automount_enabled=self.form.automount_enabled.value, + automount_mountfstab=self.form.automount_mountfstab.value, )) diff --git a/system_setup/ui/views/wslconfbase.py b/system_setup/ui/views/wslconfbase.py index 96086d1b..d1346003 100644 --- a/system_setup/ui/views/wslconfbase.py +++ b/system_setup/ui/views/wslconfbase.py @@ -41,24 +41,28 @@ class WSLConfBaseForm(Form): def __init__(self, initial): super().__init__(initial=initial) - custom_path = MountField(_("Mount Location"), - help=_("Location for the automount")) - custom_mount_opt = StringField(_("Mount Option"), - help=_("Mount option passed " - "for the automount")) - gen_host = BooleanField(_("Enable Host Generation"), help=_( - "Selecting enables /etc/host re-generation at every start")) - gen_resolvconf = BooleanField(_("Enable resolv.conf Generation"), help=_( - "Selecting enables /etc/resolv.conf re-generation at every start")) + automount_root = MountField(_("Mount Location"), + help=_("Location for the automount")) + automount_options = StringField(_("Mount Option"), + help=_("Mount option passed " + "for the automount")) + network_generatehosts = \ + BooleanField(_("Enable Host Generation"), + help=_("Selecting enables /etc/host re-generation at" + " every start")) + network_generateresolvconf = \ + BooleanField(_("Enable resolv.conf Generation"), + help=_("Selecting enables /etc/resolv.conf re-generation" + " at every start")) - def validate_custom_path(self): - p = self.custom_path.value + def validate_automount_root(self): + p = self.automount_root.value if p != "" and (re.fullmatch(r"(/[^/ ]*)+/?", p) is None): return _("Mount location must be a absolute UNIX path" " without space.") - def validate_custom_mount_opt(self): - o = self.custom_mount_opt.value + def validate_automount_options(self): + o = self.automount_options.value # filesystem independent mount option fsimo = [r"async", r"(no)?atime", r"(no)?auto", r"(fs|def|root)?context=\w+", r"(no)?dev", r"(no)?diratime", @@ -99,10 +103,11 @@ class WSLConfigurationBaseView(BaseView): self.controller = controller initial = { - 'custom_path': configuration_data.custom_path, - 'custom_mount_opt': configuration_data.custom_mount_opt, - 'gen_host': configuration_data.gen_host, - 'gen_resolvconf': configuration_data.gen_resolvconf, + 'automount_root': configuration_data.automount_root, + 'automount_options': configuration_data.automount_options, + 'network_generatehosts': configuration_data.network_generatehosts, + 'network_generateresolvconf': configuration_data + .network_generateresolvconf, } self.form = WSLConfBaseForm(initial=initial) @@ -118,8 +123,9 @@ class WSLConfigurationBaseView(BaseView): def done(self, result): self.controller.done(WSLConfigurationBase( - custom_path=self.form.custom_path.value, - custom_mount_opt=self.form.custom_mount_opt.value, - gen_host=self.form.gen_host.value, - gen_resolvconf=self.form.gen_resolvconf.value + automount_root=self.form.automount_root.value, + automount_options=self.form.automount_options.value, + network_generatehosts=self.form.network_generatehosts.value, + network_generateresolvconf=self + .form.network_generateresolvconf.value )) From c934268813708ac2956d58b99aae41cc52e17958 Mon Sep 17 00:00:00 2001 From: Patrick Wu Date: Tue, 5 Oct 2021 09:38:10 +0800 Subject: [PATCH 10/10] system_setup: changes and fixes 1. rebase with main and update autoinstall-system-setup.yml 2. provide a more unified indent style 3. update get_userandgroups() to the dropped one 4. fix the problematic os action 5. simply asignments 6. assign default_loader a default value 7. provide a type-to-file dict in wsl_conf 8. provide stderr info when providing error in creating user 9. update schema and example files --- autoinstall-system-setup-schema.json | 20 +++---- examples/autoinstall-system-setup.yaml | 16 +++-- .../client/controllers/wslconfadvanced.py | 17 +----- .../client/controllers/wslconfbase.py | 7 +-- system_setup/common/wsl_conf.py | 25 ++++---- system_setup/common/wsl_utils.py | 39 ++++++++----- system_setup/models/wslconfadvanced.py | 14 +---- system_setup/models/wslconfbase.py | 6 +- system_setup/server/controllers/configure.py | 11 ++-- .../server/controllers/wslconfadvanced.py | 40 ++----------- .../server/controllers/wslconfbase.py | 23 ++------ system_setup/ui/views/wslconfadvanced.py | 58 ++++++++++++------- system_setup/ui/views/wslconfbase.py | 26 +++++---- 13 files changed, 128 insertions(+), 174 deletions(-) diff --git a/autoinstall-system-setup-schema.json b/autoinstall-system-setup-schema.json index 487ce5da..e2d58bdc 100644 --- a/autoinstall-system-setup-schema.json +++ b/autoinstall-system-setup-schema.json @@ -70,16 +70,16 @@ "wslconfbase": { "type": "object", "properties": { - "custom_path": { + "automount_root": { "type": "string" }, - "custom_mount_opt": { + "automount_options": { "type": "string" }, - "gen_host": { + "network_generatehosts": { "type": "boolean" }, - "gen_resolvconf": { + "network_generateresolvconf": { "type": "boolean" } }, @@ -100,22 +100,22 @@ "gui_followwintheme": { "type": "boolean" }, - "legacy_gui": { + "interop_guiintegration": { "type": "boolean" }, - "legacy_audio": { + "interop_audiointegration": { "type": "boolean" }, - "adv_ip_detect": { + "interop_advancedipdetection": { "type": "boolean" }, - "wsl_motd_news": { + "motd_wslnewsenabled": { "type": "boolean" }, - "automount": { + "automount_enabled": { "type": "boolean" }, - "mountfstab": { + "automount_mountfstab": { "type": "boolean" } }, diff --git a/examples/autoinstall-system-setup.yaml b/examples/autoinstall-system-setup.yaml index 4d4cf739..a3f1db74 100644 --- a/examples/autoinstall-system-setup.yaml +++ b/examples/autoinstall-system-setup.yaml @@ -3,17 +3,15 @@ early-commands: - echo a - ["sleep", "1"] - echo a -Welcome: - lang: en_US +locale: en_US identity: realname: Ubuntu username: ubuntu # ubuntu password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1' -WSLConfigurationBase: - custom_path: '/custom_mnt_path' - custom_mount_opt: 'opt1 opt2 opt3' - gen_host: false - gen_resolvconf: false -Summary: - reboot: yes \ No newline at end of file +wslconfbase: + automount_root: '/custom_mnt_path' + automount_options: 'metadata' + network_generatehosts: false + network_generateresolvconf: false +shutdown: 'reboot' \ No newline at end of file diff --git a/system_setup/client/controllers/wslconfadvanced.py b/system_setup/client/controllers/wslconfadvanced.py index b1b012dd..b366c256 100644 --- a/system_setup/client/controllers/wslconfadvanced.py +++ b/system_setup/client/controllers/wslconfadvanced.py @@ -37,21 +37,8 @@ class WSLConfigurationAdvancedController(SubiquityTuiController): 'interop_audiointegration', 'interop_advancedipdetection', 'motd_wslnewsenabled', 'automount_enabled', 'automount_mountfstab']): - reconfiguration = WSLConfigurationAdvanced( - interop_enabled=self.answers['interop_enabled'], - interop_appendwindowspath=self - .answers['interop_appendwindowspath'], - gui_theme=self.answers['gui_theme'], - gui_followwintheme=self.answers['gui_followwintheme'], - interop_guiintegration=self.answers['interop_guiintegration'], - interop_audiointegration=self - .answers['interop_audiointegration'], - interop_advancedipdetection=self - .answers['interop_advancedipdetection'], - motd_wslnewsenabled=self.answers['motd_wslnewsenabled'], - automount_enabled=self.answers['automount_enabled'], - automount_mountfstab=self.answers['automount_mountfstab'] - ) + + reconfiguration = WSLConfigurationAdvanced(**self.answers) self.done(reconfiguration) def done(self, reconf_data): diff --git a/system_setup/client/controllers/wslconfbase.py b/system_setup/client/controllers/wslconfbase.py index 2afacd2f..7ab7e1a9 100644 --- a/system_setup/client/controllers/wslconfbase.py +++ b/system_setup/client/controllers/wslconfbase.py @@ -18,12 +18,7 @@ class WSLConfigurationBaseController(SubiquityTuiController): if all(elem in self.answers for elem in ['automount_root', 'automount_options', 'network_generatehosts', 'network_generateresolvconf']): - configuration = WSLConfigurationBase( - automount_root=self.answers['automount_root'], - automount_options=self.answers['automount_options'], - network_generatehosts=self.answers['network_generatehosts'], - network_generateresolvconf=self - .answers['network_generateresolvconf']) + configuration = WSLConfigurationBase(**self.answers) self.done(configuration) def done(self, configuration_data): diff --git a/system_setup/common/wsl_conf.py b/system_setup/common/wsl_conf.py index 4bd7e003..f41b05ca 100644 --- a/system_setup/common/wsl_conf.py +++ b/system_setup/common/wsl_conf.py @@ -63,8 +63,13 @@ config_adv_default = { } } +conf_type_to_file = { + "wsl": "/etc/wsl.conf", + "ubuntu": "/etc/ubuntu-wsl.conf" +} -def wsl_config_loader(data, pathname, config_ref, id): + +def wsl_config_loader(data, config_ref, id): """ Loads the configuration from the given file type, section and reference config. @@ -73,6 +78,7 @@ def wsl_config_loader(data, pathname, config_ref, id): :param pathname: string, the path to the file to load :param id: string, the name of the section to load """ + pathname = conf_type_to_file[id] if not os.path.exists(pathname): return data config = ConfigParser() @@ -88,7 +94,7 @@ def wsl_config_loader(data, pathname, config_ref, id): return data -def default_loader(is_advanced): +def default_loader(is_advanced=False): """ This will load the default WSL config for the given type. @@ -97,10 +103,10 @@ def default_loader(is_advanced): """ data = {} conf_ref = config_adv_default if is_advanced else config_base_default - data = wsl_config_loader(data, "/etc/wsl.conf", conf_ref, "wsl") + data = wsl_config_loader(data, conf_ref, "wsl") if is_advanced: data = \ - wsl_config_loader(data, "/etc/ubuntu-wsl.conf", conf_ref, "ubuntu") + wsl_config_loader(data, conf_ref, "ubuntu") return data @@ -132,12 +138,7 @@ def wsl_config_update(config_class, is_dry_run): config = ConfigParser() config.BasicInterpolcation = None - if config_type == "wsl": - conf_file = "/etc/wsl.conf" - elif config_type == "ubuntu": - conf_file = "/etc/ubuntu-wsl.conf" - else: - raise TypeError("Invalid type name " % config_type) + conf_file = conf_type_to_file[config_type] config.read(conf_file) @@ -165,6 +166,4 @@ def wsl_config_update(config_class, is_dry_run): with open(conf_file + ".new", 'w+') as configfile: config.write(configfile) - if os.isfile(conf_file): - os.rename(conf_file, conf_file + ".old") - os.move(conf_file + ".new", conf_file) + os.rename(conf_file + ".new", conf_file) diff --git a/system_setup/common/wsl_utils.py b/system_setup/common/wsl_utils.py index a19953b1..cb33d726 100644 --- a/system_setup/common/wsl_utils.py +++ b/system_setup/common/wsl_utils.py @@ -18,8 +18,6 @@ import os import logging import subprocess -from subiquity.common.resources import resource_path - log = logging.getLogger("subiquity.system_setup.common.wsl_utils") @@ -64,19 +62,28 @@ def get_windows_locale(): def get_userandgroups(): - usergroups_path = resource_path('users-and-groups') - build_usergroups_path = \ - os.path.realpath(__file__ + '/../../../users-and-groups') - if os.path.isfile(build_usergroups_path): - usergroups_path = build_usergroups_path + from subiquity.common.resources import resource_path + from subiquitycore.utils import run_command - user_groups = set() - if os.path.exists(usergroups_path): - with open(usergroups_path) as fp: - for line in fp: - line = line.strip() - if line.startswith('#') or not line: - continue - user_groups.add(line) - oneline_usergroups = ",".join(user_groups) + users_and_groups_path = resource_path('users-and-groups') + if os.path.exists(users_and_groups_path): + groups = open(users_and_groups_path).read().split() + else: + groups = ['admin'] + groups.append('sudo') + + command = ['getent', 'group'] + cp = run_command(command, check=True) + target_groups = set() + for line in cp.stdout.splitlines(): + target_groups.add(line.split(':')[0]) + + groups = [group for group in groups if group in target_groups] + oneline_usergroups = ",".join(groups) return oneline_usergroups + + +def convert_if_bool(value): + if value.lower() in ('true', 'false'): + return value.lower() == 'true' + return value diff --git a/system_setup/models/wslconfadvanced.py b/system_setup/models/wslconfadvanced.py index 167551c6..797dc41f 100644 --- a/system_setup/models/wslconfadvanced.py +++ b/system_setup/models/wslconfadvanced.py @@ -41,19 +41,7 @@ class WSLConfigurationAdvancedModel(object): self._wslconfadvanced = None def apply_settings(self, result): - d = {} - # TODO: placholder settings; should be dynamically assgined using - # ubuntu-wsl-integration - d['interop_enabled'] = result.interop_enabled - d['interop_appendwindowspath'] = result.interop_appendwindowspath - d['gui_theme'] = result.gui_theme - d['gui_followwintheme'] = result.gui_followwintheme - d['interop_guiintegration'] = result.interop_guiintegration - d['interop_audiointegration'] = result.interop_audiointegration - d['interop_advancedipdetection'] = result.interop_advancedipdetection - d['motd_wslnewsenabled'] = result.motd_wslnewsenabled - d['automount_enabled'] = result.automount_enabled - d['automount_mountfstab'] = result.automount_mountfstab + d = result.__dict__ self._wslconfadvanced = WSLConfigurationAdvanced(**d) @property diff --git a/system_setup/models/wslconfbase.py b/system_setup/models/wslconfbase.py index 5162c943..0b84ecac 100644 --- a/system_setup/models/wslconfbase.py +++ b/system_setup/models/wslconfbase.py @@ -36,11 +36,7 @@ class WSLConfigurationBaseModel(object): # TODO WSL: Load settings from system def apply_settings(self, result): - d = {} - d['automount_root'] = result.automount_root - d['automount_options'] = result.automount_options - d['network_generatehosts'] = result.network_generatehosts - d['network_generateresolvconf'] = result.network_generateresolvconf + d = result.__dict__ self._wslconfbase = WSLConfigurationBase(**d) @property diff --git a/system_setup/server/controllers/configure.py b/system_setup/server/controllers/configure.py index c20fadd3..b094acb9 100644 --- a/system_setup/server/controllers/configure.py +++ b/system_setup/server/controllers/configure.py @@ -80,8 +80,9 @@ class ConfigureController(SubiquityController): wsl_id.password, wsl_id.username]) if create_user_act.returncode != 0: - raise Exception("Failed to create user %s" - % wsl_id.username) + raise Exception("Failed to create user %s: %s" + % (wsl_id.username, + create_user_act.stderr)) log.debug("created user %s", wsl_id.username) assign_grp_act = \ run_command(["/usr/sbin/usermod", "-a", @@ -89,8 +90,10 @@ class ConfigureController(SubiquityController): "-G", get_userandgroups(), wsl_id.username]) if assign_grp_act.returncode != 0: - raise Exception("Failed to assign groups to user %s" % - wsl_id.username) + raise Exception(("Failed to assign group" + " to user %s: %s") + % (wsl_id.username, + assign_grp_act.stderr)) else: wsl_config_update(self.model.wslconfadvanced.wslconfadvanced, dryrun) diff --git a/system_setup/server/controllers/wslconfadvanced.py b/system_setup/server/controllers/wslconfadvanced.py index f8a3b615..6993bf2d 100644 --- a/system_setup/server/controllers/wslconfadvanced.py +++ b/system_setup/server/controllers/wslconfadvanced.py @@ -23,6 +23,7 @@ from subiquity.common.types import WSLConfigurationAdvanced from subiquity.server.controller import SubiquityController from system_setup.common.wsl_conf import default_loader +from system_setup.common.wsl_utils import convert_if_bool log = logging.getLogger( 'system_setup.server.controllers.wsl_configuration_advanced') @@ -54,46 +55,17 @@ class WSLConfigurationAdvancedController(SubiquityController): super().__init__(app) # load the config file - data = default_loader(True) + data = default_loader(is_advanced=True) if data: - def bool_converter(x): - return x.lower() == 'true' - reconf_data = WSLConfigurationAdvanced( - interop_enabled=bool_converter(data['interop_enabled']), - interop_appendwindowspath=bool_converter( - data['interop_appendwindowspath']), - gui_theme=data['gui_theme'], - gui_followwintheme=bool_converter(data['gui_followwintheme']), - interop_guiintegration=bool_converter( - data['interop_guiintegration']), - interop_audiointegration=bool_converter( - data['interop_audiointegration']), - interop_advancedipdetection=bool_converter( - data['interop_advancedipdetection']), - motd_wslnewsenabled=bool_converter( - data['motd_wslnewsenabled']), - automount_enabled=bool_converter(data['automount_enabled']), - automount_mountfstab=bool_converter( - data['automount_mountfstab']), - ) + proc_data = \ + {key: convert_if_bool(value) for (key, value) in data.items()} + reconf_data = WSLConfigurationAdvanced(**proc_data) self.model.apply_settings(reconf_data) def load_autoinstall_data(self, data): if data is not None: - reconf_data = WSLConfigurationAdvanced( - interop_enabled=data['interop_enabled'], - interop_appendwindowspath=data['interop_appendwindowspath'], - gui_theme=data['gui_theme'], - gui_followwintheme=data['gui_followwintheme'], - interop_guiintegration=data['interop_guiintegration'], - interop_audiointegration=data['interop_audiointegration'], - interop_advancedipdetection=data[ - 'interop_advancedipdetection'], - motd_wslnewsenabled=data['motd_wslnewsenabled'], - automount_enabled=data['automount_enabled'], - automount_mountfstab=data['automount_mountfstab'] - ) + reconf_data = WSLConfigurationAdvanced(**data) self.model.apply_settings(reconf_data) @with_context() diff --git a/system_setup/server/controllers/wslconfbase.py b/system_setup/server/controllers/wslconfbase.py index d78f9a90..d3897121 100644 --- a/system_setup/server/controllers/wslconfbase.py +++ b/system_setup/server/controllers/wslconfbase.py @@ -23,6 +23,7 @@ from subiquity.common.types import WSLConfigurationBase from subiquity.server.controller import SubiquityController from system_setup.common.wsl_conf import default_loader +from system_setup.common.wsl_utils import convert_if_bool log = logging.getLogger('system_setup.server' + '.controllers.wsl_configuration_base') @@ -48,29 +49,17 @@ class WSLConfigurationBaseController(SubiquityController): super().__init__(app) # load the config file - data = default_loader(False) + data = default_loader() if data: - def bool_converter(x): - return x.lower() == 'true' - conf_data = WSLConfigurationBase( - automount_root=data['automount_root'], - automount_options=data['automount_options'], - network_generatehosts=bool_converter( - data['network_generatehosts']), - network_generateresolvconf=bool_converter( - data['network_generateresolvconf']), - ) + proc_data = \ + {key: convert_if_bool(value) for (key, value) in data.items()} + conf_data = WSLConfigurationBase(**proc_data) self.model.apply_settings(conf_data) def load_autoinstall_data(self, data): if data is not None: - identity_data = WSLConfigurationBase( - automount_root=data['automount_root'], - automount_options=data['automount_options'], - network_generatehosts=data['network_generatehosts'], - network_generateresolvconf=data['network_generateresolvconf'], - ) + identity_data = WSLConfigurationBase(**data) self.model.apply_settings(identity_data) @with_context() diff --git a/system_setup/ui/views/wslconfadvanced.py b/system_setup/ui/views/wslconfadvanced.py index afa87fd8..36978852 100644 --- a/system_setup/ui/views/wslconfadvanced.py +++ b/system_setup/ui/views/wslconfadvanced.py @@ -100,20 +100,26 @@ class WSLConfigurationAdvancedView(BaseView): self.controller = controller initial = { - 'interop_enabled': configuration_data.interop_enabled, + 'interop_enabled': + configuration_data.interop_enabled, 'interop_appendwindowspath': configuration_data.interop_appendwindowspath, - 'gui_theme': configuration_data.gui_theme, - 'gui_followwintheme': configuration_data.gui_followwintheme, - 'interop_guiintegration': configuration_data - .interop_guiintegration, - 'interop_audiointegration': configuration_data - .interop_audiointegration, - 'interop_advancedipdetection': configuration_data - .interop_advancedipdetection, - 'motd_wslnewsenabled': configuration_data.motd_wslnewsenabled, - 'automount_enabled': configuration_data.automount_enabled, - 'automount_mountfstab': configuration_data.automount_mountfstab, + 'gui_theme': + configuration_data.gui_theme, + 'gui_followwintheme': + configuration_data.gui_followwintheme, + 'interop_guiintegration': + configuration_data.interop_guiintegration, + 'interop_audiointegration': + configuration_data.interop_audiointegration, + 'interop_advancedipdetection': + configuration_data.interop_advancedipdetection, + 'motd_wslnewsenabled': + configuration_data.motd_wslnewsenabled, + 'automount_enabled': + configuration_data.automount_enabled, + 'automount_mountfstab': + configuration_data.automount_mountfstab, } self.form = WSLConfigurationAdvancedForm(initial=initial) @@ -129,16 +135,24 @@ class WSLConfigurationAdvancedView(BaseView): def done(self, result): self.controller.done(WSLConfigurationAdvanced( - interop_enabled=self.form.interop_enabled.value, + interop_enabled=self.form + .interop_enabled.value, interop_appendwindowspath=self.form .interop_appendwindowspath.value, - gui_theme=self.form.gui_theme.value, - gui_followwintheme=self.form.gui_followwintheme.value, - interop_guiintegration=self.form.interop_guiintegration.value, - interop_audiointegration=self.form.interop_audiointegration.value, - interop_advancedipdetection=self - .form.interop_advancedipdetection.value, - motd_wslnewsenabled=self.form.motd_wslnewsenabled.value, - automount_enabled=self.form.automount_enabled.value, - automount_mountfstab=self.form.automount_mountfstab.value, + gui_theme=self.form + .gui_theme.value, + gui_followwintheme=self.form + .gui_followwintheme.value, + interop_guiintegration=self.form + .interop_guiintegration.value, + interop_audiointegration=self.form + .interop_audiointegration.value, + interop_advancedipdetection=self.form + .interop_advancedipdetection.value, + motd_wslnewsenabled=self.form + .motd_wslnewsenabled.value, + automount_enabled=self.form + .automount_enabled.value, + automount_mountfstab=self.form + .automount_mountfstab.value, )) diff --git a/system_setup/ui/views/wslconfbase.py b/system_setup/ui/views/wslconfbase.py index d1346003..dd5e93c4 100644 --- a/system_setup/ui/views/wslconfbase.py +++ b/system_setup/ui/views/wslconfbase.py @@ -103,11 +103,14 @@ class WSLConfigurationBaseView(BaseView): self.controller = controller initial = { - 'automount_root': configuration_data.automount_root, - 'automount_options': configuration_data.automount_options, - 'network_generatehosts': configuration_data.network_generatehosts, - 'network_generateresolvconf': configuration_data - .network_generateresolvconf, + 'automount_root': + configuration_data.automount_root, + 'automount_options': + configuration_data.automount_options, + 'network_generatehosts': + configuration_data.network_generatehosts, + 'network_generateresolvconf': + configuration_data.network_generateresolvconf, } self.form = WSLConfBaseForm(initial=initial) @@ -123,9 +126,12 @@ class WSLConfigurationBaseView(BaseView): def done(self, result): self.controller.done(WSLConfigurationBase( - automount_root=self.form.automount_root.value, - automount_options=self.form.automount_options.value, - network_generatehosts=self.form.network_generatehosts.value, - network_generateresolvconf=self - .form.network_generateresolvconf.value + automount_root=self.form + .automount_root.value, + automount_options=self.form + .automount_options.value, + network_generatehosts=self.form + .network_generatehosts.value, + network_generateresolvconf=self.form + .network_generateresolvconf.value ))