Merge pull request #404 from mwhudson/install-from-pool

configure curtin to be able to install packages from pool during installation
This commit is contained in:
Michael Hudson-Doyle 2018-12-13 13:51:16 +13:00 committed by GitHub
commit 56cd0a60a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 136 additions and 15 deletions

View File

@ -19,6 +19,8 @@ import os
import subprocess
import sys
import platform
import time
import traceback
import urwid
import yaml
@ -27,6 +29,11 @@ from systemd import journal
from subiquitycore import utils
from subiquitycore.controller import BaseController
from subiquitycore.tasksequence import (
BackgroundTask,
TaskSequence,
TaskWatcher,
)
from subiquity.ui.views.installprogress import ProgressView
@ -41,6 +48,56 @@ class InstallState:
ERROR = -1
class WaitForCurtinEventsTask(BackgroundTask):
def __init__(self, controller):
self.controller = controller
self.waited = 0.0
def start(self):
pass
def _bg_run(self):
while self.controller._event_indent and self.waited < 5.0:
time.sleep(0.1)
self.waited += 0.1
log.debug("waited %s seconds for events to drain", self.waited)
def end(self, observer, fut):
# Will raise if command failed:
fut.result()
self.controller._install_event_start("final system configuration")
observer.task_succeeded()
class InstallTask(BackgroundTask):
def __init__(self, controller, step_name, func, *args, **kw):
self.controller = controller
self.step_name = step_name
self.func = func
self.args = args
self.kw = kw
def __repr__(self):
return "InstallTask(%r, *%r, **%r)" % (self.func, self.args, self.kw)
def start(self):
self.controller._install_event_start(self.step_name)
def _bg_run(self):
self.func(*self.args, **self.kw)
def end(self, observer, fut):
# Will raise if command failed:
fut.result()
self.controller._install_event_finish()
observer.task_succeeded()
def cancel(self):
pass
class InstallProgressController(BaseController):
signals = [
('installprogress:filesystem-config-done', 'filesystem_config_done'),
@ -99,6 +156,18 @@ class InstallProgressController(BaseController):
elif event['SYSLOG_IDENTIFIER'] == self._log_syslog_identifier:
self.curtin_log(event)
def _install_event_start(self, message):
log.debug("_install_event_start %s", message)
self.footer_description.set_text(message)
self.progress_view.add_event(self._event_indent + message)
self._event_indent += " "
self.footer_spinner.start()
def _install_event_finish(self):
self._event_indent = self._event_indent[:-2]
log.debug("_install_event_finish %r", self._event_indent)
self.footer_spinner.stop()
def curtin_event(self, event):
e = {}
for k, v in event.items():
@ -109,15 +178,9 @@ class InstallProgressController(BaseController):
if event_type not in ['start', 'finish']:
return
if event_type == 'start':
message = event.get("CURTIN_MESSAGE", "??")
if not self.progress_view_showing:
self.footer_description.set_text(message)
self.progress_view.add_event(self._event_indent + message)
self._event_indent += " "
self.footer_spinner.start()
self._install_event_start(event.get("CURTIN_MESSAGE", "??"))
if event_type == 'finish':
self._event_indent = self._event_indent[:-2]
self.footer_spinner.stop()
self._install_event_finish()
def curtin_log(self, event):
self.progress_view.add_log_line(event['MESSAGE'])
@ -209,13 +272,57 @@ class InstallProgressController(BaseController):
def cancel(self):
pass
def _bg_cleanup_apt(self):
if self.opts.dry_run:
cmd = [
"sleep", "2",
]
else:
os.unlink(
os.path.join(
self.base_model.target, "etc/apt/sources.list.d/iso.list"))
cmd = [
sys.executable, "-m", "curtin", "in-target", "-t", "/target",
"--", "apt-get", "update",
]
self._bg_run_command_logged(cmd)
def postinstall_configuration(self):
# If we need to do anything that takes time here (like running
# dpkg-reconfigure maas-rack-controller, for example...) we
# should switch to doing that work in a background thread.
self.configure_cloud_init()
self.copy_logs_to_target()
class w(TaskWatcher):
def __init__(self, controller):
self.controller = controller
def task_complete(self, stage):
pass
def task_error(self, stage, info):
if isinstance(info, tuple):
tb = traceback.format_exception(*info)
self.controller.curtin_error("".join(tb))
else:
self.controller.curtin_error()
def tasks_finished(self):
self.controller.loop.set_alarm_in(
0.0,
lambda loop, ud: self.controller.postinstall_complete())
tasks = [
('drain', WaitForCurtinEventsTask(self)),
('cloud-init', InstallTask(
self, "configuring cloud-init",
self.base_model.configure_cloud_init)),
('cleanup', InstallTask(
self, "cleaning up apt configuration",
self._bg_cleanup_apt)),
]
ts = TaskSequence(self.run_in_bg, tasks, w(self))
ts.run()
def postinstall_complete(self):
self._install_event_finish()
self.ui.set_header(_("Installation complete!"))
self.progress_view.set_status(_("Finished install!"))
self.progress_view.show_complete()
@ -223,9 +330,6 @@ class InstallProgressController(BaseController):
if self.answers['reboot']:
self.reboot()
def configure_cloud_init(self):
self.base_model.configure_cloud_init()
def copy_logs_to_target(self):
if self.opts.dry_run:
return

View File

@ -148,6 +148,23 @@ class SubiquityModel:
'primary': [{'arches': ["default"],
'uri': self.mirror.mirror}],
'preserve_sources_list': False,
'sources': {
'iso.list': {
'source':
'deb file:///run/cdrom $RELEASE main restricted',
},
},
},
'curthooks_commands': {
'000-setup-tmpfs': [
'mount', '-t', 'tmpfs', 'tmpfs',
os.path.join(self.target, 'run')],
'001-create-run-cdrom': [
'mkdir', '-p', os.path.join(self.target, 'run', 'cdrom')],
'002-mount-run-cdrom': [
'mount', '--bind', '/cdrom',
os.path.join(self.target, 'run', 'cdrom')],
},
'install': {