From 016b7a4d46cdeeb0672dc65ad69385064504a2f2 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 17 Dec 2019 14:55:20 +1300 Subject: [PATCH] use asyncio.Event()s to indicate when config is done stop using urwid signals to indicate to installprogress when a particular piece of config is done and instead call .set() on an Event that installprogress can wait on. --- subiquity/controllers/filesystem.py | 2 +- subiquity/controllers/identity.py | 2 +- subiquity/controllers/installprogress.py | 32 ++--------------- subiquity/controllers/keyboard.py | 1 + subiquity/controllers/mirror.py | 1 + subiquity/controllers/network.py | 5 ++- subiquity/controllers/proxy.py | 1 + subiquity/controllers/snaplist.py | 2 +- subiquity/controllers/ssh.py | 2 +- subiquity/controllers/welcome.py | 1 + subiquity/models/subiquity.py | 46 ++++++++++++++++++------ subiquity/models/tests/test_keyboard.py | 1 + subiquity/models/tests/test_subiquity.py | 2 +- 13 files changed, 52 insertions(+), 46 deletions(-) diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index 580f7d07..6376c7b3 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -312,7 +312,7 @@ class FilesystemController(BaseController): def finish(self): log.debug("FilesystemController.finish next_screen") # start curtin install in background - self.signal.emit_signal('installprogress:filesystem-config-done') + self.app.base_model.configured("filesystem") # switch to next screen self.app.next_screen() diff --git a/subiquity/controllers/identity.py b/subiquity/controllers/identity.py index 7fddb14f..99632d04 100644 --- a/subiquity/controllers/identity.py +++ b/subiquity/controllers/identity.py @@ -50,5 +50,5 @@ class IdentityController(BaseController): "IdentityController.done next_screen user_spec=%s", safe_spec) self.model.add_user(user_spec) - self.signal.emit_signal('installprogress:identity-config-done') + self.app.base_model.configured("identity") self.app.next_screen() diff --git a/subiquity/controllers/installprogress.py b/subiquity/controllers/installprogress.py index 404375b3..382d7b6a 100644 --- a/subiquity/controllers/installprogress.py +++ b/subiquity/controllers/installprogress.py @@ -89,12 +89,6 @@ def install_step(label): class InstallProgressController(BaseController): - signals = [ - ('installprogress:filesystem-config-done', 'filesystem_config_done'), - ('installprogress:identity-config-done', 'identity_config_done'), - ('installprogress:ssh-config-done', 'ssh_config_done'), - ('installprogress:snap-config-done', 'snap_config_done'), - ] def __init__(self, app): super().__init__(app) @@ -103,12 +97,6 @@ class InstallProgressController(BaseController): self.install_state = InstallState.NOT_STARTED self.journal_listener_handle = None - self.filesystem_event = asyncio.Event() - self._postinstall_prerequisites = { - 'ssh': asyncio.Event(), - 'identity': asyncio.Event(), - 'snap': asyncio.Event(), - } self.reboot_clicked = asyncio.Event() if self.answers.get('reboot', False): self.reboot_clicked.set() @@ -126,21 +114,6 @@ class InstallProgressController(BaseController): def tpath(self, *path): return os.path.join(self.model.target, *path) - def filesystem_config_done(self): - self.filesystem_event.set() - - def _step_done(self, step): - self._postinstall_prerequisites[step].set() - - def identity_config_done(self): - self._step_done('identity') - - def ssh_config_done(self): - self._step_done('ssh') - - def snap_config_done(self): - self._step_done('snap') - def curtin_error(self): self.install_state = InstallState.ERROR kw = {} @@ -274,12 +247,13 @@ class InstallProgressController(BaseController): async def install(self): try: - await self.filesystem_event.wait() + await asyncio.wait( + {e.wait() for e in self.model.install_events}) await self.curtin_install() await asyncio.wait( - {e.wait() for e in self._postinstall_prerequisites.values()}) + {e.wait() for e in self.model.postinstall_events}) await self.drain_curtin_events() diff --git a/subiquity/controllers/keyboard.py b/subiquity/controllers/keyboard.py index 53c39c4a..1824296e 100644 --- a/subiquity/controllers/keyboard.py +++ b/subiquity/controllers/keyboard.py @@ -56,6 +56,7 @@ class KeyboardController(BaseController): async def apply_settings(self, setting): await self.model.set_keyboard(setting) log.debug("KeyboardController next_screen") + self.app.base_model.configured("keyboard") self.app.next_screen() def done(self, setting): diff --git a/subiquity/controllers/mirror.py b/subiquity/controllers/mirror.py index c71307e6..fcafcb3a 100644 --- a/subiquity/controllers/mirror.py +++ b/subiquity/controllers/mirror.py @@ -105,4 +105,5 @@ class MirrorController(BaseController): log.debug("MirrorController.done next_screen mirror=%s", mirror) if mirror != self.model.mirror: self.model.mirror = mirror + self.app.base_model.configured("mirror") self.app.next_screen() diff --git a/subiquity/controllers/network.py b/subiquity/controllers/network.py index 7332e0d0..495ed4cf 100644 --- a/subiquity/controllers/network.py +++ b/subiquity/controllers/network.py @@ -17,4 +17,7 @@ from subiquitycore.controllers.network import NetworkController class NetworkController(NetworkController): - pass + + def done(self): + self.app.base_model.configured("network") + super().done() diff --git a/subiquity/controllers/proxy.py b/subiquity/controllers/proxy.py index 41a058d5..84573389 100644 --- a/subiquity/controllers/proxy.py +++ b/subiquity/controllers/proxy.py @@ -49,4 +49,5 @@ class ProxyController(BaseController): self.model.proxy = proxy os.environ['http_proxy'] = os.environ['https_proxy'] = proxy self.signal.emit_signal('network-proxy-set') + self.app.base_model.configured("proxy") self.app.next_screen() diff --git a/subiquity/controllers/snaplist.py b/subiquity/controllers/snaplist.py index 241bfaec..ad780fcb 100644 --- a/subiquity/controllers/snaplist.py +++ b/subiquity/controllers/snaplist.py @@ -148,7 +148,7 @@ class SnapListController(BaseController): "SnapListController.done next_screen snaps_to_install=%s", snaps_to_install) self.model.set_installed_list(snaps_to_install) - self.signal.emit_signal("installprogress:snap-config-done") + self.app.base_model.configured("snaplist") self.app.next_screen() def cancel(self, sender=None): diff --git a/subiquity/controllers/ssh.py b/subiquity/controllers/ssh.py index 19574845..87a7b045 100644 --- a/subiquity/controllers/ssh.py +++ b/subiquity/controllers/ssh.py @@ -116,5 +116,5 @@ class SSHController(BaseController): self.model.authorized_keys = result.get('authorized_keys', []) self.model.pwauth = result.get('pwauth', True) self.model.ssh_import_id = result.get('ssh_import_id', None) - self.signal.emit_signal('installprogress:ssh-config-done') + self.app.base_model.configured("ssh") self.app.next_screen() diff --git a/subiquity/controllers/welcome.py b/subiquity/controllers/welcome.py index 22ad1db6..236925b5 100644 --- a/subiquity/controllers/welcome.py +++ b/subiquity/controllers/welcome.py @@ -48,6 +48,7 @@ class WelcomeController(BaseController): log.debug("WelcomeController.done %s next_screen", code) self.signal.emit_signal('l10n:language-selected', code) self.model.switch_language(code) + self.app.base_model.configured("locale") self.app.next_screen() def cancel(self): diff --git a/subiquity/models/subiquity.py b/subiquity/models/subiquity.py index 3f61a041..4a458145 100644 --- a/subiquity/models/subiquity.py +++ b/subiquity/models/subiquity.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import asyncio from collections import OrderedDict import logging import os @@ -61,6 +62,25 @@ ff02::1 ip6-allnodes ff02::2 ip6-allrouters """ +# Models that contribute to the curtin config +INSTALL_MODEL_NAMES = [ + "keyboard", + "network", + "proxy", + "mirror", + "filesystem", + ] + +# Models that contribute to the cloud-init config +POSTINSTALL_MODEL_NAMES = [ + "locale", + "identity", + "ssh", + "snaplist", + ] + +ALL_MODEL_NAMES = INSTALL_MODEL_NAMES + POSTINSTALL_MODEL_NAMES + class SubiquityModel: """The overall model for subiquity.""" @@ -78,20 +98,23 @@ class SubiquityModel: self.proxy = ProxyModel() self.mirror = MirrorModel() self.filesystem = FilesystemModel() - - # Collect the models that produce data for the curtin config. - self._install_models = [ - self.keyboard, - self.network, - self.proxy, - self.mirror, - self.filesystem, - ] - self.identity = IdentityModel() self.ssh = SSHModel() self.snaplist = SnapListModel() + self._events = { + name: asyncio.Event() for name in ALL_MODEL_NAMES + } + self.install_events = { + self._events[name] for name in INSTALL_MODEL_NAMES + } + self.postinstall_events = { + self._events[name] for name in POSTINSTALL_MODEL_NAMES + } + + def configured(self, model_name): + self._events[model_name].set() + def get_target_groups(self): command = ['chroot', self.target, 'getent', 'group'] if self.root != '/': @@ -248,7 +271,8 @@ class SubiquityModel: }, } - for model in self._install_models: + for model_name in INSTALL_MODEL_NAMES: + model = getattr(self, model_name) log.debug("merging config from %s", model) merge_config(config, model.render()) diff --git a/subiquity/models/tests/test_keyboard.py b/subiquity/models/tests/test_keyboard.py index 4fc2c7c9..a63b3889 100644 --- a/subiquity/models/tests/test_keyboard.py +++ b/subiquity/models/tests/test_keyboard.py @@ -43,3 +43,4 @@ class TestSubiquityModel(unittest.TestCase): model.config_path) self.assertEqual(new_setting, read_setting) loop.run_until_complete(t()) + loop.close() diff --git a/subiquity/models/tests/test_subiquity.py b/subiquity/models/tests/test_subiquity.py index e1163859..ff37f95b 100644 --- a/subiquity/models/tests/test_subiquity.py +++ b/subiquity/models/tests/test_subiquity.py @@ -106,7 +106,7 @@ class TestSubiquityModel(unittest.TestCase): def test_writes_machine_id_media_info(self): model_no_proxy = SubiquityModel('test') model_proxy = SubiquityModel('test') - model_proxy.proxy = 'http://something' + model_proxy.proxy.proxy = 'http://something' for model in model_no_proxy, model_proxy: config = model.render('ident') self.assertConfigWritesFile(config, 'etc/machine-id')