diff --git a/autoinstall-system-setup-schema.json b/autoinstall-system-setup-schema.json index e478bdc9..41cc97ac 100644 --- a/autoinstall-system-setup-schema.json +++ b/autoinstall-system-setup-schema.json @@ -48,6 +48,15 @@ "locale": { "type": "string" }, + "wslsetupoptions": { + "type": "object", + "properties": { + "install_language_support_packages": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "identity": { "type": "object", "properties": { diff --git a/examples/answers-system-setup-init.yaml b/examples/answers-system-setup-init.yaml index 05325d79..63e4b643 100644 --- a/examples/answers-system-setup-init.yaml +++ b/examples/answers-system-setup-init.yaml @@ -1,5 +1,7 @@ Welcome: lang: en_US +WSLSetupOptions: + install_language_support_packages: true WSLIdentity: realname: Ubuntu username: ubuntu diff --git a/examples/autoinstall-system-setup-full.yaml b/examples/autoinstall-system-setup-full.yaml index 7fcbc5e1..3c5f6686 100644 --- a/examples/autoinstall-system-setup-full.yaml +++ b/examples/autoinstall-system-setup-full.yaml @@ -4,6 +4,8 @@ early-commands: - ["sleep", "1"] - echo a locale: en_US +wslsetupoptions: + install_language_support_packages: true identity: realname: Ubuntu username: ubuntu @@ -20,4 +22,4 @@ wslconfadvanced: automount_enabled: false automount_mountfstab: false systemd_enabled: true -shutdown: 'poweroff' \ No newline at end of file +shutdown: 'poweroff' diff --git a/subiquity/common/apidef.py b/subiquity/common/apidef.py index cae56229..85821a3d 100644 --- a/subiquity/common/apidef.py +++ b/subiquity/common/apidef.py @@ -64,6 +64,7 @@ from subiquity.common.types import ( ZdevInfo, WSLConfigurationBase, WSLConfigurationAdvanced, + WSLSetupOptions, ) @@ -76,6 +77,7 @@ class API: updates = simple_endpoint(str) wslconfbase = simple_endpoint(WSLConfigurationBase) wslconfadvanced = simple_endpoint(WSLConfigurationAdvanced) + wslsetupoptions = simple_endpoint(WSLSetupOptions) class meta: class status: diff --git a/subiquity/common/types.py b/subiquity/common/types.py index 131c1233..1fc45270 100644 --- a/subiquity/common/types.py +++ b/subiquity/common/types.py @@ -614,3 +614,11 @@ class WSLConfigurationAdvanced: interop_enabled: bool = attr.ib(default=True) interop_appendwindowspath: bool = attr.ib(default=True) systemd_enabled: bool = attr.ib(default=False) + + +# Options that affect the setup experience itself, but won't reflect in the +# /etc/wsl.conf configuration file. +@attr.s(auto_attribs=True) +class WSLSetupOptions: + install_language_support_packages: bool = attr.ib(default=True) + diff --git a/subiquity/tests/api/test_api.py b/subiquity/tests/api/test_api.py index c3ace508..9791a42e 100755 --- a/subiquity/tests/api/test_api.py +++ b/subiquity/tests/api/test_api.py @@ -151,6 +151,18 @@ class Server(Client): pass +class SystemSetupServer(Server): + async def spawn(self, output_base, socket, machine_config, + bootloader='uefi', extra_args=None): + env = os.environ.copy() + env['SUBIQUITY_REPLAY_TIMESCALE'] = '100' + cmd = ['python3', '-m', 'system_setup.cmd.server', + '--dry-run', '--socket', socket] + if extra_args is not None: + cmd.extend(extra_args) + self.proc = await astart_command(cmd, env=env) + + class TestAPI(SubiTestCase): class _MachineConfig(os.PathLike): def __init__(self, outer, path): @@ -206,12 +218,12 @@ def tempdirs(*args, **kwargs): @contextlib.asynccontextmanager -async def start_server(*args, **kwargs): +async def start_server_factory(factory, *args, **kwargs): with tempfile.TemporaryDirectory() as tempdir: socket_path = f'{tempdir}/socket' conn = aiohttp.UnixConnector(path=socket_path) async with aiohttp.ClientSession(connector=conn) as session: - server = Server(session) + server = factory(session) try: await server.spawn(tempdir, socket_path, *args, **kwargs) await poll_for_socket_exist(socket_path) @@ -221,6 +233,18 @@ async def start_server(*args, **kwargs): await server.close() +@contextlib.asynccontextmanager +async def start_server(*args, **kwargs): + async with start_server_factory(Server, *args, **kwargs) as instance: + yield instance + + +@contextlib.asynccontextmanager +async def start_system_setup_server(*args, **kwargs): + async with start_server_factory(SystemSetupServer, *args, **kwargs) as srv: + yield srv + + @contextlib.asynccontextmanager async def connect_server(*args, **kwargs): # This is not used by the tests directly, but can be convenient when @@ -1356,3 +1380,18 @@ class TestUbuntuProContractSelection(TestAPI): await inst.post('/ubuntu_pro/contract_selection/cancel') with self.assertRaises(Exception): await inst.get('/ubuntu_pro/contract_selection/wait') + + +class TestWSLSetupOptions(TestAPI): + async def test_wslsetupoptions(self): + async with start_system_setup_server('examples/simple.json') as inst: + await inst.post('/meta/client_variant', variant='wsl_setup') + + payload = {'install_language_support_packages': False} + endpoint = '/wslsetupoptions' + resp = await inst.get(endpoint) + self.assertTrue(resp['install_language_support_packages']) + await inst.post(endpoint, payload) + + resp = await inst.get(endpoint) + self.assertFalse(resp['install_language_support_packages']) diff --git a/system_setup/models/wslsetupoptions.py b/system_setup/models/wslsetupoptions.py new file mode 100644 index 00000000..155e33f1 --- /dev/null +++ b/system_setup/models/wslsetupoptions.py @@ -0,0 +1,44 @@ +# Copyright 2022 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 . + +import logging +import attr + +log = logging.getLogger('system_setup.models.wslsetupoptions') + + +@attr.s +class WSLSetupOptions(object): + install_language_support_packages = attr.ib() + + +class WSLSetupOptionsModel(object): + """ Model representing basic wsl configuration + """ + + def __init__(self): + self._wslsetupoptions = None + + def apply_settings(self, result): + d = result.__dict__ + self._wslsetupoptions = WSLSetupOptions(**d) + + @property + def wslsetupoptions(self): + return self._wslsetupoptions + + def __repr__(self): + return "".format(self.wslsetupoptions) +