Reconfigure mode: WIP
This commit is contained in:
parent
6cbe3e8a36
commit
a97cc28ae6
7
Makefile
7
Makefile
|
@ -8,6 +8,7 @@ PROBERTDIR=./probert
|
||||||
PROBERT_REPO=https://github.com/canonical/probert
|
PROBERT_REPO=https://github.com/canonical/probert
|
||||||
DRYRUN?=--dry-run --bootloader uefi --machine-config examples/simple.json
|
DRYRUN?=--dry-run --bootloader uefi --machine-config examples/simple.json
|
||||||
SYSTEM_SETUP_DRYRUN?=--dry-run
|
SYSTEM_SETUP_DRYRUN?=--dry-run
|
||||||
|
RECONFIG?=--reconfigure
|
||||||
export PYTHONPATH
|
export PYTHONPATH
|
||||||
CWD := $(shell pwd)
|
CWD := $(shell pwd)
|
||||||
|
|
||||||
|
@ -55,6 +56,12 @@ dryrun-system-setup:
|
||||||
dryrun-system-setup-server:
|
dryrun-system-setup-server:
|
||||||
$(PYTHON) -m system_setup.cmd.server $(SYSTEM_SETUP_DRYRUN)
|
$(PYTHON) -m system_setup.cmd.server $(SYSTEM_SETUP_DRYRUN)
|
||||||
|
|
||||||
|
dryrun-system-setup-recon:
|
||||||
|
$(PYTHON) -m system_setup.cmd.tui $(SYSTEM_SETUP_DRYRUN) $(RECONFIG)
|
||||||
|
|
||||||
|
dryrun-system-setup-server-recon:
|
||||||
|
$(PYTHON) -m system_setup.cmd.server $(SYSTEM_SETUP_DRYRUN) $(RECONFIG)
|
||||||
|
|
||||||
lint: flake8
|
lint: flake8
|
||||||
|
|
||||||
flake8:
|
flake8:
|
||||||
|
|
|
@ -24,6 +24,8 @@ log = logging.getLogger('system_setup.client.client')
|
||||||
|
|
||||||
class SystemSetupClient(SubiquityClient):
|
class SystemSetupClient(SubiquityClient):
|
||||||
|
|
||||||
|
from system_setup.client import controllers as controllers_mod
|
||||||
|
|
||||||
snapd_socket_path = None
|
snapd_socket_path = None
|
||||||
|
|
||||||
controllers = [
|
controllers = [
|
||||||
|
@ -34,8 +36,16 @@ class SystemSetupClient(SubiquityClient):
|
||||||
"Overview",
|
"Overview",
|
||||||
"Progress",
|
"Progress",
|
||||||
]
|
]
|
||||||
|
def __init__(self, opts):
|
||||||
|
if opts.reconfigure:
|
||||||
|
self.controllers = [
|
||||||
|
"Welcome",
|
||||||
|
"Reconfiguration",
|
||||||
|
"Progress",
|
||||||
|
]
|
||||||
|
super().__init__(opts)
|
||||||
|
|
||||||
|
|
||||||
from system_setup.client import controllers as controllers_mod
|
|
||||||
|
|
||||||
def restart(self, remove_last_screen=True, restart_server=False):
|
def restart(self, remove_last_screen=True, restart_server=False):
|
||||||
log.debug(f"restart {remove_last_screen} {restart_server}")
|
log.debug(f"restart {remove_last_screen} {restart_server}")
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
from .identity import WSLIdentityController
|
from .identity import WSLIdentityController
|
||||||
from .integration import IntegrationController
|
from .integration import IntegrationController
|
||||||
from .overview import OverviewController
|
from .overview import OverviewController
|
||||||
|
from .reconfiguration import ReconfigurationController
|
||||||
|
|
||||||
from subiquity.client.controllers import (ProgressController, WelcomeController)
|
from subiquity.client.controllers import (ProgressController, WelcomeController)
|
||||||
|
|
||||||
|
@ -27,5 +28,6 @@ __all__ = [
|
||||||
'ProgressController',
|
'ProgressController',
|
||||||
'IntegrationController',
|
'IntegrationController',
|
||||||
'OverviewController',
|
'OverviewController',
|
||||||
|
'ReconfigurationController',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import attr
|
||||||
|
|
||||||
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
|
from subiquity.client.controller import SubiquityTuiController
|
||||||
|
from subiquity.common.types import WSLConfiguration2Data
|
||||||
|
from system_setup.ui.views.reconfiguration import ReconfigurationView
|
||||||
|
|
||||||
|
log = logging.getLogger('system_setup.client.controllers.reconfiguration')
|
||||||
|
|
||||||
|
|
||||||
|
class ReconfigurationController(SubiquityTuiController):
|
||||||
|
endpoint_name = 'wslconf2'
|
||||||
|
|
||||||
|
async def make_ui(self):
|
||||||
|
data = await self.endpoint.GET()
|
||||||
|
return ReconfigurationView(self, data)
|
||||||
|
|
||||||
|
def run_answers(self):
|
||||||
|
if all(elem in self.answers for elem in
|
||||||
|
['custom_path', 'custom_mount_opt', 'gen_host', 'gen_resolvconf', 'interop_enabled', 'interop_appendwindowspath', 'gui_theme', 'gui_followwintheme', 'legacy_gui', 'legacy_audio', 'adv_ip_detect', 'wsl_motd_news', 'automount', 'mountfstab']):
|
||||||
|
reconfiguration = WSLConfiguration2Data(
|
||||||
|
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'],
|
||||||
|
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']
|
||||||
|
)
|
||||||
|
self.done(reconfiguration)
|
||||||
|
|
||||||
|
def done(self, reconf_data):
|
||||||
|
log.debug(
|
||||||
|
"ConfigurationController.done next_screen user_spec=%s",
|
||||||
|
reconf_data)
|
||||||
|
self.app.next_screen(self.endpoint.POST(reconf_data))
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.app.prev_screen()
|
|
@ -35,6 +35,7 @@ def make_server_args_parser():
|
||||||
help='menu-only, do not call installer function')
|
help='menu-only, do not call installer function')
|
||||||
parser.add_argument('--socket')
|
parser.add_argument('--socket')
|
||||||
parser.add_argument('--autoinstall', action='store')
|
parser.add_argument('--autoinstall', action='store')
|
||||||
|
parser.add_argument('--reconfigure', action='store_true')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ def make_client_args_parser():
|
||||||
help='Synthesize a click on a button matching PAT')
|
help='Synthesize a click on a button matching PAT')
|
||||||
parser.add_argument('--answers')
|
parser.add_argument('--answers')
|
||||||
parser.add_argument('--server-pid')
|
parser.add_argument('--server-pid')
|
||||||
|
parser.add_argument('--reconfigure', action='store_true')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +91,8 @@ def main():
|
||||||
sock_path = '.subiquity/socket'
|
sock_path = '.subiquity/socket'
|
||||||
opts.socket = sock_path
|
opts.socket = sock_path
|
||||||
server_args = ['--dry-run', '--socket=' + sock_path] + unknown
|
server_args = ['--dry-run', '--socket=' + sock_path] + unknown
|
||||||
|
if '--reconfigure' in args:
|
||||||
|
server_args.append('--reconfigure')
|
||||||
server_parser = make_server_args_parser()
|
server_parser = make_server_args_parser()
|
||||||
server_parser.parse_args(server_args) # just to check
|
server_parser.parse_args(server_args) # just to check
|
||||||
server_output = open('.subiquity/server-output', 'w')
|
server_output = open('.subiquity/server-output', 'w')
|
||||||
|
|
|
@ -50,6 +50,7 @@ class WSLConfiguration2Model(object):
|
||||||
|
|
||||||
def apply_settings(self, result, is_dry_run=False):
|
def apply_settings(self, result, is_dry_run=False):
|
||||||
d = {}
|
d = {}
|
||||||
|
#TODO: placholder settings; should be dynamically assgined using ubuntu-wsl-integration
|
||||||
d['custom_path'] = result.custom_path
|
d['custom_path'] = result.custom_path
|
||||||
d['custom_mount_opt'] = result.custom_mount_opt
|
d['custom_mount_opt'] = result.custom_mount_opt
|
||||||
d['gen_host'] = result.gen_host
|
d['gen_host'] = result.gen_host
|
||||||
|
@ -70,6 +71,7 @@ class WSLConfiguration2Model(object):
|
||||||
run_command(["/usr/bin/ubuntuwsl", "reset", "-y"],
|
run_command(["/usr/bin/ubuntuwsl", "reset", "-y"],
|
||||||
stdout=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL)
|
||||||
# set the settings
|
# set the settings
|
||||||
|
#TODO: placholder settings; should be dynamically generated using ubuntu-wsl-integration
|
||||||
run_command(["/usr/bin/ubuntuwsl", "update",
|
run_command(["/usr/bin/ubuntuwsl", "update",
|
||||||
"WSL.automount.enabled", result.automount],
|
"WSL.automount.enabled", result.automount],
|
||||||
stdout=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL)
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
from os import path
|
||||||
|
import configparser
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.common.apidef import API
|
from subiquity.common.apidef import API
|
||||||
|
@ -53,9 +54,87 @@ class WSLConfiguration2Controller(SubiquityController):
|
||||||
'additionalProperties': False,
|
'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",
|
||||||
|
"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 __init__(self, app):
|
||||||
|
super().__init__(app)
|
||||||
|
|
||||||
|
# load the config file
|
||||||
|
data = {}
|
||||||
|
if path.exists('/etc/wsl.conf'):
|
||||||
|
wslconfig = configparser.ConfigParser()
|
||||||
|
wslconfig.read('/etc/wsl.conf')
|
||||||
|
for a in wslconfig:
|
||||||
|
if a in self.config_ref['wsl']:
|
||||||
|
a_x = wslconfig[a]
|
||||||
|
for b in a_x:
|
||||||
|
if b in self.config_ref['wsl'][a]:
|
||||||
|
data[self.config_ref['wsl'][a][b]] = a_x[b]
|
||||||
|
if path.exists('/etc/ubuntu-wsl.conf'):
|
||||||
|
ubuntuconfig = configparser.ConfigParser()
|
||||||
|
ubuntuconfig.read('/etc/ubuntu-wsl.conf')
|
||||||
|
for a in ubuntuconfig:
|
||||||
|
if a in self.config_ref['ubuntu']:
|
||||||
|
a_x = ubuntuconfig[a]
|
||||||
|
for b in a_x:
|
||||||
|
if b in self.config_ref['ubuntu'][a]:
|
||||||
|
data[self.config_ref['ubuntu'][a][b]] = a_x[b]
|
||||||
|
if data:
|
||||||
|
yes_no_converter = lambda x: x == 'true'
|
||||||
|
reconf_data = WSLConfiguration2Data(
|
||||||
|
custom_path=data['custom_path'],
|
||||||
|
custom_mount_opt=data['custom_mount_opt'],
|
||||||
|
gen_host=yes_no_converter(data['gen_host']),
|
||||||
|
gen_resolvconf=yes_no_converter(data['gen_resolvconf']),
|
||||||
|
interop_enabled=yes_no_converter(data['interop_enabled']),
|
||||||
|
interop_appendwindowspath=yes_no_converter(data['interop_appendwindowspath']),
|
||||||
|
gui_theme=data['gui_theme'],
|
||||||
|
gui_followwintheme=yes_no_converter(data['gui_followwintheme']),
|
||||||
|
legacy_gui=yes_no_converter(data['legacy_gui']),
|
||||||
|
legacy_audio=yes_no_converter(data['legacy_audio']),
|
||||||
|
adv_ip_detect=yes_no_converter(data['adv_ip_detect']),
|
||||||
|
wsl_motd_news=yes_no_converter(data['wsl_motd_news']),
|
||||||
|
automount=yes_no_converter(data['automount']),
|
||||||
|
mountfstab=yes_no_converter(data['mountfstab']),
|
||||||
|
)
|
||||||
|
self.model.apply_settings(reconf_data, self.opts.dry_run)
|
||||||
|
|
||||||
def load_autoinstall_data(self, data):
|
def load_autoinstall_data(self, data):
|
||||||
if data is not None:
|
if data is not None:
|
||||||
identity_data = WSLConfiguration2Data(
|
reconf_data = WSLConfiguration2Data(
|
||||||
custom_path=data['custom_path'],
|
custom_path=data['custom_path'],
|
||||||
custom_mount_opt=data['custom_mount_opt'],
|
custom_mount_opt=data['custom_mount_opt'],
|
||||||
gen_host=data['gen_host'],
|
gen_host=data['gen_host'],
|
||||||
|
@ -71,7 +150,7 @@ class WSLConfiguration2Controller(SubiquityController):
|
||||||
automount=data['automount'],
|
automount=data['automount'],
|
||||||
mountfstab=data['mountfstab']
|
mountfstab=data['mountfstab']
|
||||||
)
|
)
|
||||||
self.model.apply_settings(identity_data, self.opts.dry_run)
|
self.model.apply_settings(reconf_data, self.opts.dry_run)
|
||||||
|
|
||||||
@with_context()
|
@with_context()
|
||||||
async def apply_autoinstall_config(self, context=None):
|
async def apply_autoinstall_config(self, context=None):
|
||||||
|
|
|
@ -28,9 +28,18 @@ class SystemSetupServer(SubiquityServer):
|
||||||
"Locale",
|
"Locale",
|
||||||
"Identity",
|
"Identity",
|
||||||
"WSLConfiguration1",
|
"WSLConfiguration1",
|
||||||
"WSLConfiguration2"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def __init__(self, opts, block_log_dir):
|
||||||
|
if opts.reconfigure:
|
||||||
|
self.controllers = [
|
||||||
|
"Reporting",
|
||||||
|
"Error",
|
||||||
|
"Locale",
|
||||||
|
"WSLConfiguration2",
|
||||||
|
]
|
||||||
|
super().__init__(opts, block_log_dir)
|
||||||
|
|
||||||
def make_model(self):
|
def make_model(self):
|
||||||
root = '/'
|
root = '/'
|
||||||
if self.opts.dry_run:
|
if self.opts.dry_run:
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
from .identity import WSLIdentityView
|
from .identity import WSLIdentityView
|
||||||
from .integration import IntegrationView
|
from .integration import IntegrationView
|
||||||
from .overview import OverviewView
|
from .overview import OverviewView
|
||||||
|
from .reconfiguration import ReconfigurationView
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'WSLIdentityView',
|
'WSLIdentityView',
|
||||||
'IntegrationView',
|
'IntegrationView',
|
||||||
'OverviewView',
|
'OverviewView',
|
||||||
|
'ReconfigurationView',
|
||||||
]
|
]
|
|
@ -0,0 +1,151 @@
|
||||||
|
""" Reconfiguration View
|
||||||
|
|
||||||
|
Integration provides user with options to set up integration configurations.
|
||||||
|
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from urwid import (
|
||||||
|
connect_signal,
|
||||||
|
)
|
||||||
|
|
||||||
|
from subiquitycore.ui.form import (
|
||||||
|
Form,
|
||||||
|
BooleanField,
|
||||||
|
ChoiceField,
|
||||||
|
simple_field,
|
||||||
|
WantsToKnowFormField
|
||||||
|
)
|
||||||
|
from subiquitycore.ui.interactive import StringEditor
|
||||||
|
from subiquitycore.ui.utils import screen
|
||||||
|
from subiquitycore.view import BaseView
|
||||||
|
from subiquity.common.types import WSLConfiguration2Data
|
||||||
|
|
||||||
|
|
||||||
|
class MountEditor(StringEditor, WantsToKnowFormField):
|
||||||
|
def keypress(self, size, key):
|
||||||
|
''' restrict what chars we allow for mountpoints '''
|
||||||
|
|
||||||
|
mountpoint = r'[a-zA-Z0-9_/\.\-]'
|
||||||
|
if re.match(mountpoint, key) is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return super().keypress(size, key)
|
||||||
|
|
||||||
|
|
||||||
|
MountField = simple_field(MountEditor)
|
||||||
|
StringField = simple_field(StringEditor)
|
||||||
|
|
||||||
|
|
||||||
|
class ReconfigurationForm(Form):
|
||||||
|
def __init__(self, initial):
|
||||||
|
super().__init__(initial=initial)
|
||||||
|
|
||||||
|
#TODO: placholder settings UI; should be dynamically generated using ubuntu-wsl-integration
|
||||||
|
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. "))
|
||||||
|
custom_path = MountField(_("Auto-Mount Location"), help=_("Location for the automount"))
|
||||||
|
custom_mount_opt = StringField(_("Auto-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"))
|
||||||
|
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."))
|
||||||
|
|
||||||
|
def validate_custom_path(self):
|
||||||
|
p = self.custom_path.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
|
||||||
|
# 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",
|
||||||
|
r"dirsync", r"(no)?exec", r"group", r"(no)?iversion", r"(no)?mand", r"_netdev", r"nofail",
|
||||||
|
r"(no)?relatime", r"(no)?strictatime", r"(no)?suid", r"owner", r"remount", r"ro", r"rw",
|
||||||
|
r"_rnetdev", r"sync", r"(no)?user", r"users"]
|
||||||
|
# DrvFs filesystem mount option
|
||||||
|
drvfsmo = r"case=(dir|force|off)|metadata|(u|g)id=\d+|(u|f|d)mask=\d+|"
|
||||||
|
fso = "{0}{1}".format(drvfsmo, '|'.join(fsimo))
|
||||||
|
|
||||||
|
if o != "":
|
||||||
|
e_t = ""
|
||||||
|
p = o.split(',')
|
||||||
|
x = True
|
||||||
|
for i in p:
|
||||||
|
if i == "":
|
||||||
|
e_t += _("an empty entry detected; ")
|
||||||
|
x = x and False
|
||||||
|
elif re.fullmatch(fso, i) is not None:
|
||||||
|
x = x and True
|
||||||
|
else:
|
||||||
|
e_t += _("{} is not a valid mount option; ").format(i)
|
||||||
|
x = x and False
|
||||||
|
if not x:
|
||||||
|
return _("Invalid Input: {}Please check "
|
||||||
|
"https://docs.microsoft.com/en-us/windows/wsl/wsl-config#mount-options "
|
||||||
|
"for correct valid input").format(e_t)
|
||||||
|
|
||||||
|
class ReconfigurationView(BaseView):
|
||||||
|
title = _("Configuration")
|
||||||
|
excerpt = _("In this page, you can tweak Ubuntu WSL to your needs. \n"
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, controller, integration_data):
|
||||||
|
self.controller = controller
|
||||||
|
|
||||||
|
initial = {
|
||||||
|
'custom_path': integration_data.custom_path,
|
||||||
|
'custom_mount_opt':integration_data.custom_mount_opt,
|
||||||
|
'gen_host': integration_data.gen_host,
|
||||||
|
'gen_resolvconf': integration_data.gen_resolvconf,
|
||||||
|
'interop_enabled': integration_data.interop_enabled,
|
||||||
|
'interop_appendwindowspath': integration_data.interop_appendwindowspath,
|
||||||
|
'gui_theme': integration_data.gui_theme,
|
||||||
|
'gui_followwintheme': integration_data.gui_followwintheme,
|
||||||
|
'legacy_gui': integration_data.legacy_gui,
|
||||||
|
'legacy_audio': integration_data.legacy_audio,
|
||||||
|
'adv_ip_detect': integration_data.adv_ip_detect,
|
||||||
|
'wsl_motd_news': integration_data.wsl_motd_news,
|
||||||
|
'automount': integration_data.automount,
|
||||||
|
'mountfstab': integration_data.mountfstab,
|
||||||
|
}
|
||||||
|
self.form = ReconfigurationForm(initial=initial)
|
||||||
|
|
||||||
|
|
||||||
|
connect_signal(self.form, 'submit', self.done)
|
||||||
|
super().__init__(
|
||||||
|
screen(
|
||||||
|
self.form.as_rows(),
|
||||||
|
[self.form.done_btn],
|
||||||
|
focus_buttons=True,
|
||||||
|
excerpt=self.excerpt,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def done(self, result):
|
||||||
|
self.controller.done(WSLConfiguration2Data(
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
))
|
Loading…
Reference in New Issue