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.
This commit is contained in:
Michael Hudson-Doyle 2019-12-17 14:55:20 +13:00
parent 2e59d11ad3
commit 016b7a4d46
13 changed files with 52 additions and 46 deletions

View File

@ -312,7 +312,7 @@ class FilesystemController(BaseController):
def finish(self): def finish(self):
log.debug("FilesystemController.finish next_screen") log.debug("FilesystemController.finish next_screen")
# start curtin install in background # start curtin install in background
self.signal.emit_signal('installprogress:filesystem-config-done') self.app.base_model.configured("filesystem")
# switch to next screen # switch to next screen
self.app.next_screen() self.app.next_screen()

View File

@ -50,5 +50,5 @@ class IdentityController(BaseController):
"IdentityController.done next_screen user_spec=%s", "IdentityController.done next_screen user_spec=%s",
safe_spec) safe_spec)
self.model.add_user(user_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() self.app.next_screen()

View File

@ -89,12 +89,6 @@ def install_step(label):
class InstallProgressController(BaseController): 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): def __init__(self, app):
super().__init__(app) super().__init__(app)
@ -103,12 +97,6 @@ class InstallProgressController(BaseController):
self.install_state = InstallState.NOT_STARTED self.install_state = InstallState.NOT_STARTED
self.journal_listener_handle = None 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() self.reboot_clicked = asyncio.Event()
if self.answers.get('reboot', False): if self.answers.get('reboot', False):
self.reboot_clicked.set() self.reboot_clicked.set()
@ -126,21 +114,6 @@ class InstallProgressController(BaseController):
def tpath(self, *path): def tpath(self, *path):
return os.path.join(self.model.target, *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): def curtin_error(self):
self.install_state = InstallState.ERROR self.install_state = InstallState.ERROR
kw = {} kw = {}
@ -274,12 +247,13 @@ class InstallProgressController(BaseController):
async def install(self): async def install(self):
try: try:
await self.filesystem_event.wait() await asyncio.wait(
{e.wait() for e in self.model.install_events})
await self.curtin_install() await self.curtin_install()
await asyncio.wait( 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() await self.drain_curtin_events()

View File

@ -56,6 +56,7 @@ class KeyboardController(BaseController):
async def apply_settings(self, setting): async def apply_settings(self, setting):
await self.model.set_keyboard(setting) await self.model.set_keyboard(setting)
log.debug("KeyboardController next_screen") log.debug("KeyboardController next_screen")
self.app.base_model.configured("keyboard")
self.app.next_screen() self.app.next_screen()
def done(self, setting): def done(self, setting):

View File

@ -105,4 +105,5 @@ class MirrorController(BaseController):
log.debug("MirrorController.done next_screen mirror=%s", mirror) log.debug("MirrorController.done next_screen mirror=%s", mirror)
if mirror != self.model.mirror: if mirror != self.model.mirror:
self.model.mirror = mirror self.model.mirror = mirror
self.app.base_model.configured("mirror")
self.app.next_screen() self.app.next_screen()

View File

@ -17,4 +17,7 @@ from subiquitycore.controllers.network import NetworkController
class NetworkController(NetworkController): class NetworkController(NetworkController):
pass
def done(self):
self.app.base_model.configured("network")
super().done()

View File

@ -49,4 +49,5 @@ class ProxyController(BaseController):
self.model.proxy = proxy self.model.proxy = proxy
os.environ['http_proxy'] = os.environ['https_proxy'] = proxy os.environ['http_proxy'] = os.environ['https_proxy'] = proxy
self.signal.emit_signal('network-proxy-set') self.signal.emit_signal('network-proxy-set')
self.app.base_model.configured("proxy")
self.app.next_screen() self.app.next_screen()

View File

@ -148,7 +148,7 @@ class SnapListController(BaseController):
"SnapListController.done next_screen snaps_to_install=%s", "SnapListController.done next_screen snaps_to_install=%s",
snaps_to_install) snaps_to_install)
self.model.set_installed_list(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() self.app.next_screen()
def cancel(self, sender=None): def cancel(self, sender=None):

View File

@ -116,5 +116,5 @@ class SSHController(BaseController):
self.model.authorized_keys = result.get('authorized_keys', []) self.model.authorized_keys = result.get('authorized_keys', [])
self.model.pwauth = result.get('pwauth', True) self.model.pwauth = result.get('pwauth', True)
self.model.ssh_import_id = result.get('ssh_import_id', None) 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() self.app.next_screen()

View File

@ -48,6 +48,7 @@ class WelcomeController(BaseController):
log.debug("WelcomeController.done %s next_screen", code) log.debug("WelcomeController.done %s next_screen", code)
self.signal.emit_signal('l10n:language-selected', code) self.signal.emit_signal('l10n:language-selected', code)
self.model.switch_language(code) self.model.switch_language(code)
self.app.base_model.configured("locale")
self.app.next_screen() self.app.next_screen()
def cancel(self): def cancel(self):

View File

@ -13,6 +13,7 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
from collections import OrderedDict from collections import OrderedDict
import logging import logging
import os import os
@ -61,6 +62,25 @@ ff02::1 ip6-allnodes
ff02::2 ip6-allrouters 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: class SubiquityModel:
"""The overall model for subiquity.""" """The overall model for subiquity."""
@ -78,20 +98,23 @@ class SubiquityModel:
self.proxy = ProxyModel() self.proxy = ProxyModel()
self.mirror = MirrorModel() self.mirror = MirrorModel()
self.filesystem = FilesystemModel() 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.identity = IdentityModel()
self.ssh = SSHModel() self.ssh = SSHModel()
self.snaplist = SnapListModel() 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): def get_target_groups(self):
command = ['chroot', self.target, 'getent', 'group'] command = ['chroot', self.target, 'getent', 'group']
if self.root != '/': 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) log.debug("merging config from %s", model)
merge_config(config, model.render()) merge_config(config, model.render())

View File

@ -43,3 +43,4 @@ class TestSubiquityModel(unittest.TestCase):
model.config_path) model.config_path)
self.assertEqual(new_setting, read_setting) self.assertEqual(new_setting, read_setting)
loop.run_until_complete(t()) loop.run_until_complete(t())
loop.close()

View File

@ -106,7 +106,7 @@ class TestSubiquityModel(unittest.TestCase):
def test_writes_machine_id_media_info(self): def test_writes_machine_id_media_info(self):
model_no_proxy = SubiquityModel('test') model_no_proxy = SubiquityModel('test')
model_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: for model in model_no_proxy, model_proxy:
config = model.render('ident') config = model.render('ident')
self.assertConfigWritesFile(config, 'etc/machine-id') self.assertConfigWritesFile(config, 'etc/machine-id')