split "Reboot" controller out of InstallProgress controller

this means late commands run before copying logs to the target and
waiting for the user to click restart
This commit is contained in:
Michael Hudson-Doyle 2020-04-24 14:46:32 +12:00
parent 88165ce5fd
commit dd1969f89b
4 changed files with 85 additions and 36 deletions

View File

@ -24,6 +24,7 @@ from .package import PackageController
from .proxy import ProxyController
from .mirror import MirrorController
from .network import NetworkController
from .reboot import RebootController
from .refresh import RefreshController
from ..controller import RepeatedController
from .reporting import ReportingController
@ -46,6 +47,7 @@ __all__ = [
'MirrorController',
'NetworkController',
'RefreshController',
'RebootController',
'RepeatedController',
'ReportingController',
'SnapListController',

View File

@ -18,10 +18,8 @@ import contextlib
import datetime
import logging
import os
import platform
import re
import shutil
import subprocess
import sys
import tempfile
import traceback
@ -43,7 +41,6 @@ from subiquitycore.context import Status
from subiquitycore.utils import (
arun_command,
astart_command,
run_command,
)
from subiquity.controller import SubiquityController
@ -322,18 +319,13 @@ class InstallProgressController(SubiquityController):
await self.run_unattended_upgrades(context)
self.progress_view.update_done()
await self.copy_logs_to_target(context)
except Exception:
self.curtin_error()
if not self.interactive():
raise
async def move_on(self):
await asyncio.wait(
{self.reboot_clicked.wait(), self.install_task})
self.app.reboot_on_exit = True
if not self.opts.dry_run and platform.machine() == 's390x':
run_command(["chreipl", "/target/boot"])
await self.install_task
self.app.next_screen()
async def drain_curtin_events(self, context):
@ -442,25 +434,6 @@ class InstallProgressController(SubiquityController):
'--stop-only',
]), check=True)
@install_step("copying logs to installed system")
async def copy_logs_to_target(self, context):
if self.opts.dry_run and 'copy-logs-fail' in self.app.debug_flags:
raise PermissionError()
target_logs = self.tpath('var/log/installer')
if self.opts.dry_run:
os.makedirs(target_logs, exist_ok=True)
else:
await arun_command(
['cp', '-aT', '/var/log/installer', target_logs])
journal_txt = os.path.join(target_logs, 'installer-journal.txt')
try:
with open(journal_txt, 'w') as output:
await arun_command(
['journalctl', '-b'],
stdout=output, stderr=subprocess.STDOUT)
except Exception:
log.exception("saving journal failed")
async def _click_reboot(self):
if self.unattended_upgrades_ctx is not None:
await self.stop_unattended_upgrades()

View File

@ -0,0 +1,79 @@
# Copyright 2020 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 os
import platform
import subprocess
from subiquitycore.async_helpers import schedule_task
from subiquitycore.utils import arun_command, run_command
from subiquity.controller import SubiquityController
log = logging.getLogger("subiquity.controllers.restart")
class RebootController(SubiquityController):
def __init__(self, app):
super().__init__(app)
self.context.set('hidden', True)
def interactive(self):
return self.app.interactive()
async def copy_logs_to_target(self):
with self.context.child("copy_logs_to_target"):
if self.opts.dry_run and 'copy-logs-fail' in self.app.debug_flags:
raise PermissionError()
target_logs = os.path.join(
self.app.base_model.target, 'var/log/installer')
if self.opts.dry_run:
os.makedirs(target_logs, exist_ok=True)
else:
await arun_command(
['cp', '-aT', '/var/log/installer', target_logs])
journal_txt = os.path.join(target_logs, 'installer-journal.txt')
try:
with open(journal_txt, 'w') as output:
await arun_command(
['journalctl', '-b'],
stdout=output, stderr=subprocess.STDOUT)
except Exception:
log.exception("saving journal failed")
def reboot(self):
if self.opts.dry_run:
self.app.exit()
else:
if platform.machine() == 's390x':
run_command(["chreipl", "/target/boot"])
run_command(["/sbin/reboot"])
async def apply_autoinstall_config(self):
await self.copy_logs_to_target()
self.reboot()
async def _run(self):
await self.copy_logs_to_target()
await self.app.controllers.InstallProgress.reboot_clicked.wait()
self.reboot()
def start_ui(self):
schedule_task(self._run())
def cancel(self):
pass

View File

@ -35,7 +35,6 @@ from subiquitycore.async_helpers import (
)
from subiquitycore.controller import Skip
from subiquitycore.core import Application
from subiquitycore.utils import run_command
from subiquity.controllers.error import (
ErrorReportKind,
@ -116,6 +115,7 @@ class Subiquity(Application):
"SnapList",
"InstallProgress",
"Late",
"Reboot",
]
def __init__(self, opts, block_log_dir):
@ -151,13 +151,6 @@ class Subiquity(Application):
self.note_data_for_apport("UsingAnswers", str(bool(self.answers)))
self.install_confirmed = False
self.reboot_on_exit = False
def exit(self):
if self.reboot_on_exit and not self.opts.dry_run:
run_command(["/sbin/reboot"])
else:
super().exit()
def restart(self, remove_last_screen=True):
if remove_last_screen:
@ -259,6 +252,8 @@ class Subiquity(Application):
InstallProgress = getattr(self.controllers, "InstallProgress", None)
if InstallProgress is None:
return False
if context.get('hidden', False):
return False
controller = context.get('controller')
if controller is None or controller.interactive():
return False