Merge pull request #45 from CanonicalLtd/patch-queue-async
Add progress show final bits
This commit is contained in:
commit
3bb2a79c2e
|
@ -65,8 +65,6 @@ class FilesystemController(ControllerPolicy):
|
|||
log.info("Rendering preserved config for post install")
|
||||
preserved_actions = [preserve_action(a) for a in actions]
|
||||
curtin_write_preserved_actions(actions=preserved_actions)
|
||||
|
||||
self.signal.emit_signal('installprogress:do-initial-install')
|
||||
self.signal.emit_signal('identity:show')
|
||||
|
||||
# Filesystem/Disk partition -----------------------------------------------
|
||||
|
|
|
@ -17,9 +17,10 @@ import logging
|
|||
from tornado.gen import coroutine
|
||||
import subiquity.utils as utils
|
||||
from subiquity.models import InstallProgressModel
|
||||
from subiquity.ui.views import ProgressView, ProgressOutput
|
||||
from subiquity.ui.views import ProgressView
|
||||
from subiquity.controller import ControllerPolicy
|
||||
from subiquity.curtin import (CURTIN_CONFIGS,
|
||||
curtin_reboot,
|
||||
curtin_install_cmd,
|
||||
curtin_write_postinst_config)
|
||||
|
||||
|
@ -27,65 +28,75 @@ log = logging.getLogger("subiquity.controller.installprogress")
|
|||
|
||||
|
||||
class InstallProgressController(ControllerPolicy):
|
||||
KIRBY = ["(>'-')>",
|
||||
"<('-'<)",
|
||||
"<('-')>",
|
||||
"(>'-')>",
|
||||
"<('-'<)",
|
||||
"<('-')>",
|
||||
"(>'-')>",
|
||||
"<('-'<)",
|
||||
"<('-')>",
|
||||
"(>'-')>",
|
||||
"<('-'<)"]
|
||||
|
||||
def __init__(self, common):
|
||||
super().__init__(common)
|
||||
self.model = InstallProgressModel()
|
||||
self.progress_output_w = ProgressOutput(self.signal, "Waiting...")
|
||||
|
||||
def install_progress_status(self, data):
|
||||
self.progress_output_w.set_text(data)
|
||||
self.signal.emit_signal('refresh')
|
||||
self.progress_view = None
|
||||
self.is_complete = False
|
||||
self.alarm = None
|
||||
self.kirby_pos = 0
|
||||
|
||||
@coroutine
|
||||
def curtin_dispatch(self, postconfig):
|
||||
''' one time curtin dispatch requires the use of
|
||||
the preserved storage config which allows executing
|
||||
in-target commands by remounting up the configured
|
||||
storage.
|
||||
'''
|
||||
write_fd = self.loop.watch_pipe(self.install_progress_status)
|
||||
def curtin_install(self, postconfig):
|
||||
self.signal.emit_signal('installprogress:show')
|
||||
|
||||
log.debug('Curtin Install: calling curtin with '
|
||||
'storage/net/postinstall config')
|
||||
|
||||
log.debug('writing out postinst config')
|
||||
curtin_write_postinst_config(postconfig)
|
||||
configs = [CURTIN_CONFIGS['preserved'], CURTIN_CONFIGS['postinstall']]
|
||||
curtin_cmd = curtin_install_cmd(configs)
|
||||
log.debug('Curtin postinstall install cmd: {}'.format(curtin_cmd))
|
||||
if self.opts.dry_run:
|
||||
log.debug("Install Progress: Curtin dispatch dry-run")
|
||||
result = yield utils.run_command_async('cat /var/log/syslog',
|
||||
write_fd)
|
||||
else:
|
||||
try:
|
||||
result = yield utils.run_command_async(" ".join(curtin_cmd),
|
||||
write_fd)
|
||||
except:
|
||||
log.error("Problem with curtin dispatch run")
|
||||
raise Exception("Problem with curtin dispatch run")
|
||||
|
||||
return result
|
||||
|
||||
@coroutine
|
||||
def initial_install(self):
|
||||
log.debug('Initial Install: calling curtin with storage/net config')
|
||||
write_fd = self.loop.watch_pipe(self.install_progress_status)
|
||||
|
||||
configs = [CURTIN_CONFIGS['network'], CURTIN_CONFIGS['storage']]
|
||||
configs = [CURTIN_CONFIGS['network'],
|
||||
CURTIN_CONFIGS['storage'],
|
||||
CURTIN_CONFIGS['postinstall']]
|
||||
curtin_cmd = curtin_install_cmd(configs)
|
||||
|
||||
log.debug('Curtin install cmd: {}'.format(curtin_cmd))
|
||||
if self.opts.dry_run:
|
||||
log.debug("Filesystem: this is a dry-run")
|
||||
result = yield utils.run_command_async('cat /var/log/syslog',
|
||||
write_fd)
|
||||
result = yield utils.run_command_async('cat /var/log/syslog')
|
||||
self.is_complete = True
|
||||
else:
|
||||
log.debug("filesystem: this is the *real* thing")
|
||||
result = yield utils.run_command_async(" ".join(curtin_cmd))
|
||||
if result['status'] > 0:
|
||||
log.error("Problem with curtin "
|
||||
"install: {}".format(result))
|
||||
raise Exception("Problem with curtin install")
|
||||
self.is_complete = True
|
||||
|
||||
def progress_indicator(self, *args, **kwargs):
|
||||
if self.is_complete:
|
||||
self.progress_view.text.set_text(
|
||||
"Finished install!")
|
||||
self.ui.set_footer("", 100)
|
||||
self.progress_view.show_finished_button()
|
||||
self.loop.remove_alarm(self.alarm)
|
||||
else:
|
||||
try:
|
||||
log.debug("filesystem: this is the *real* thing")
|
||||
result = yield utils.run_command_async(" ".join(curtin_cmd),
|
||||
write_fd)
|
||||
except:
|
||||
log.error("Problem with initial curtin install")
|
||||
raise Exception("Problem with initial curtin install")
|
||||
return result
|
||||
cur_kirby = self.KIRBY[self.kirby_pos]
|
||||
except IndexError:
|
||||
self.kirby_pos = 0
|
||||
cur_kirby = self.KIRBY[self.kirby_pos]
|
||||
self.progress_view.text.set_text(
|
||||
"Still installing, watch kirby dance, {}".format(
|
||||
cur_kirby))
|
||||
self.alarm = self.loop.set_alarm_in(0.3, self.progress_indicator)
|
||||
self.kirby_pos += 1
|
||||
|
||||
def reboot(self):
|
||||
curtin_reboot()
|
||||
|
||||
@coroutine
|
||||
def show_progress(self):
|
||||
|
@ -96,7 +107,8 @@ class InstallProgressController(ControllerPolicy):
|
|||
footer = ("Thank you for using Ubuntu!")
|
||||
self.ui.set_header(title, excerpt)
|
||||
self.ui.set_footer(footer, 90)
|
||||
self.ui.set_body(ProgressView(self.signal, self.progress_output_w))
|
||||
self.progress_view = ProgressView(self.signal)
|
||||
self.ui.set_body(self.progress_view)
|
||||
|
||||
if self.opts.dry_run:
|
||||
banner = [
|
||||
|
@ -107,5 +119,8 @@ class InstallProgressController(ControllerPolicy):
|
|||
"",
|
||||
"Press (Q) to Quit."
|
||||
]
|
||||
self.install_progress_status("\n".join(banner))
|
||||
self.ui.set_footer(footer, 100)
|
||||
self.progress_view.text.set_text("\n".join(banner))
|
||||
else:
|
||||
self.alarm = self.loop.set_alarm_in(0.3, self.progress_indicator)
|
||||
|
||||
self.ui.set_footer(footer, 90)
|
||||
|
|
|
@ -28,15 +28,15 @@ class InstallProgressModel(ModelPolicy):
|
|||
prev_signal = None
|
||||
|
||||
signals = [
|
||||
("Initial install routine",
|
||||
'installprogress:do-initial-install',
|
||||
'initial_install'),
|
||||
("Run once curtin commands",
|
||||
'installprogress:curtin-dispatch',
|
||||
'curtin_dispatch'),
|
||||
("Run curtin",
|
||||
'installprogress:curtin-install',
|
||||
'curtin_install'),
|
||||
("Install progress final view",
|
||||
'installprogress:show',
|
||||
'show_progress')
|
||||
'show_progress'),
|
||||
("Reboot curtin",
|
||||
"installprogress:curtin-reboot",
|
||||
"reboot")
|
||||
]
|
||||
|
||||
installprogress_menu = []
|
||||
|
|
|
@ -22,6 +22,6 @@ from .ceph import CephDiskView # NOQA
|
|||
from .iscsi import IscsiDiskView # NOQA
|
||||
from .network import NetworkView # NOQA
|
||||
from .installpath import InstallpathView # NOQA
|
||||
from .installprogress import ProgressOutput, ProgressView # NOQA
|
||||
from .installprogress import ProgressView # NOQA
|
||||
from .welcome import WelcomeView # NOQA
|
||||
from .identity import IdentityView # NOQA
|
||||
|
|
|
@ -108,8 +108,7 @@ class IdentityView(ViewPolicy):
|
|||
}
|
||||
|
||||
log.debug("User input: {}".format(result))
|
||||
self.signal.emit_signal('installprogress:curtin-dispatch', result)
|
||||
self.signal.emit_signal('installprogress:show')
|
||||
self.signal.emit_signal('installprogress:curtin-install', result)
|
||||
|
||||
def cancel(self, button):
|
||||
self.signal.emit_signal("quit")
|
||||
|
|
|
@ -15,32 +15,40 @@
|
|||
|
||||
import logging
|
||||
from urwid import (Text, Filler,
|
||||
ListBox, BoxAdapter)
|
||||
Pile)
|
||||
from subiquity.view import ViewPolicy
|
||||
from subiquity.ui.utils import Color, Padding
|
||||
from subiquity.ui.buttons import confirm_btn
|
||||
from subiquity.ui.utils import Padding, Color
|
||||
|
||||
log = logging.getLogger("subiquity.ui.views.installprogress")
|
||||
|
||||
|
||||
class ProgressOutput(ViewPolicy):
|
||||
def __init__(self, signal, txt):
|
||||
self.signal = signal
|
||||
self.txt = Text(txt)
|
||||
flr = Filler(Color.info_minor(self.txt),
|
||||
valign="top")
|
||||
super().__init__(BoxAdapter(flr, height=20))
|
||||
|
||||
def set_text(self, data):
|
||||
self.txt.set_text(data)
|
||||
|
||||
|
||||
class ProgressView(ViewPolicy):
|
||||
def __init__(self, signal, output_w):
|
||||
def __init__(self, signal):
|
||||
"""
|
||||
:param output_w: Filler widget to display updated status text
|
||||
"""
|
||||
self.signal = signal
|
||||
self.text = Text("Wait for it ...", align="center")
|
||||
self.body = [
|
||||
Padding.center_79(output_w)
|
||||
Padding.center_79(self.text)
|
||||
]
|
||||
super().__init__(ListBox(self.body))
|
||||
self.pile = Pile(self.body)
|
||||
super().__init__(Filler(self.pile, valign="middle"))
|
||||
|
||||
def show_finished_button(self):
|
||||
w = Padding.center_20(
|
||||
Color.button(confirm_btn(label="Reboot now",
|
||||
on_press=self.reboot),
|
||||
focus_map='button focus'))
|
||||
|
||||
self.pile.contents.append((w, self.pile.options()))
|
||||
self.pile.focus_position = 1
|
||||
|
||||
def keypress(self, size, key):
|
||||
super().keypress(size, key)
|
||||
if key in ['q', 'Q']:
|
||||
self.signal.emit_signal('installprogress:curtin-reboot')
|
||||
|
||||
def reboot(self, btn):
|
||||
self.signal.emit_signal('installprogress:curtin-reboot')
|
||||
|
|
|
@ -25,15 +25,14 @@ log = logging.getLogger("subiquity.utils")
|
|||
SYS_CLASS_NET = "/sys/class/net/"
|
||||
|
||||
|
||||
def run_command_async(cmd, write_fd, timeout=None):
|
||||
def run_command_async(cmd, timeout=None):
|
||||
log.debug('calling Async command: {}'.format(cmd))
|
||||
return Async.pool.submit(run_command, cmd, write_fd, timeout)
|
||||
return Async.pool.submit(run_command, cmd, timeout)
|
||||
|
||||
|
||||
def run_command(command, write_fd, timeout=None):
|
||||
def run_command(command, timeout=None):
|
||||
""" Execute command through system shell
|
||||
:param command: command to run
|
||||
:param write_fd: writable_fd for output updates
|
||||
:param timeout: (optional) use 'timeout' to limit time. default 300
|
||||
:type command: str
|
||||
:returns: {status: returncode, output: stdout, err: stderr}
|
||||
|
@ -52,7 +51,7 @@ def run_command(command, write_fd, timeout=None):
|
|||
try:
|
||||
log.debug('trying Popen...')
|
||||
p = Popen(command, shell=True,
|
||||
stdout=write_fd, stderr=PIPE,
|
||||
stdout=PIPE, stderr=PIPE,
|
||||
bufsize=-1, env=cmd_env, close_fds=True)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
|
|
Loading…
Reference in New Issue