move most of the work of computing live session ssh info to server
This commit is contained in:
parent
b8eb88f7ce
commit
d1e43eb27e
|
@ -50,7 +50,7 @@ from subiquity.common.types import (
|
|||
from subiquity.journald import journald_listen
|
||||
from subiquity.ui.frame import SubiquityUI
|
||||
from subiquity.ui.views.error import ErrorReportStretchy
|
||||
from subiquity.ui.views.help import HelpMenu
|
||||
from subiquity.ui.views.help import HelpMenu, ssh_help_texts
|
||||
from subiquity.ui.views.installprogress import (
|
||||
InstallConfirmation,
|
||||
)
|
||||
|
@ -283,12 +283,11 @@ class SubiquityClient(TuiApplication):
|
|||
self.interactive = status.interactive
|
||||
if self.interactive:
|
||||
if self.opts.ssh:
|
||||
from subiquity.ui.views.help import (
|
||||
ssh_help_texts, get_installer_password)
|
||||
from subiquitycore.ssh import get_ips_standalone
|
||||
texts = ssh_help_texts(
|
||||
get_ips_standalone(),
|
||||
get_installer_password(self.opts.dry_run))
|
||||
ssh_info = self.client.meta.ssh_info.GET()
|
||||
if ssh_info is None:
|
||||
print("no ssh?")
|
||||
return
|
||||
texts = ssh_help_texts(ssh_info)
|
||||
for line in texts:
|
||||
if hasattr(line, 'text'):
|
||||
if line.text.startswith('installer@'):
|
||||
|
|
|
@ -31,10 +31,10 @@ class WelcomeController(SubiquityTuiController):
|
|||
i18n.switch_language(language)
|
||||
serial = self.app.opts.run_on_serial
|
||||
if serial:
|
||||
ips = await self.app.client.network.global_addresses.GET()
|
||||
ssh_info = await self.app.client.meta.ssh_info.GET()
|
||||
else:
|
||||
ips = None
|
||||
return WelcomeView(self, language, serial, ips)
|
||||
ssh_info = None
|
||||
return WelcomeView(self, language, serial, ssh_info)
|
||||
|
||||
def run_answers(self):
|
||||
if 'lang' in self.answers:
|
||||
|
|
|
@ -36,6 +36,7 @@ from subiquity.common.types import (
|
|||
SnapListResponse,
|
||||
SnapSelection,
|
||||
SSHData,
|
||||
LiveSessionSSHInfo,
|
||||
StorageResponse,
|
||||
ZdevInfo,
|
||||
)
|
||||
|
@ -67,6 +68,10 @@ class API:
|
|||
class restart:
|
||||
def POST() -> None:
|
||||
"""Restart the server process."""
|
||||
|
||||
class ssh_info:
|
||||
def GET() -> Optional[LiveSessionSSHInfo]: ...
|
||||
|
||||
class errors:
|
||||
class wait:
|
||||
def GET(error_ref: ErrorReportRef) -> ErrorReportRef:
|
||||
|
|
|
@ -79,6 +79,13 @@ class ApplicationStatus:
|
|||
event_syslog_id: str
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class LiveSessionSSHInfo:
|
||||
username: str
|
||||
password: str
|
||||
ips: List[str]
|
||||
|
||||
|
||||
class RefreshCheckState(enum.Enum):
|
||||
UNKNOWN = enum.auto()
|
||||
AVAILABLE = enum.auto()
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
|
@ -51,6 +52,7 @@ from subiquity.common.types import (
|
|||
ApplicationState,
|
||||
ApplicationStatus,
|
||||
ErrorReportRef,
|
||||
LiveSessionSSHInfo,
|
||||
)
|
||||
from subiquity.server.controller import SubiquityController
|
||||
from subiquity.models.subiquity import SubiquityModel
|
||||
|
@ -65,6 +67,23 @@ from subiquitycore.snapd import (
|
|||
log = logging.getLogger('subiquity.server.server')
|
||||
|
||||
|
||||
def get_installer_password(dry_run=False):
|
||||
if dry_run:
|
||||
fp = io.StringIO('installer:rAnd0Mpass')
|
||||
else:
|
||||
try:
|
||||
fp = open("/var/log/cloud-init-output.log")
|
||||
except FileNotFoundError:
|
||||
fp = io.StringIO('')
|
||||
|
||||
with fp:
|
||||
for line in fp:
|
||||
if line.startswith("installer:"):
|
||||
return line[len("installer:"):].strip()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class MetaController:
|
||||
|
||||
def __init__(self, app):
|
||||
|
@ -98,6 +117,20 @@ class MetaController:
|
|||
if controller.endpoint in endpoints:
|
||||
controller.configured()
|
||||
|
||||
async def ssh_info_GET(self) -> Optional[LiveSessionSSHInfo]:
|
||||
password = get_installer_password(self.app.opts.dry_run)
|
||||
if password is None:
|
||||
return None
|
||||
ips = []
|
||||
for dev in self.app.base_model.network.get_all_netdevs():
|
||||
ips.extend(map(str, dev.actual_global_ip_addresses))
|
||||
if not ips:
|
||||
return None
|
||||
return LiveSessionSSHInfo(
|
||||
username='installer',
|
||||
password=password,
|
||||
ips=ips)
|
||||
|
||||
|
||||
class SubiquityServer(Application):
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
import logging
|
||||
import os
|
||||
import io
|
||||
|
||||
from urwid import (
|
||||
connect_signal,
|
||||
|
@ -25,7 +24,6 @@ from urwid import (
|
|||
Text,
|
||||
)
|
||||
|
||||
from subiquitycore.async_helpers import schedule_task
|
||||
from subiquitycore.lsb_release import lsb_release
|
||||
from subiquitycore.ssh import host_key_info
|
||||
from subiquitycore.ui.buttons import (
|
||||
|
@ -110,7 +108,7 @@ To connect, SSH to any of these addresses:
|
|||
""")
|
||||
|
||||
SSH_HELP_ONE_ADDRESSES = _("""
|
||||
To connect, SSH to installer@{ip}.
|
||||
To connect, SSH to {username}@{ip}.
|
||||
""")
|
||||
|
||||
SSH_HELP_EPILOGUE = _("""
|
||||
|
@ -128,24 +126,24 @@ been set.
|
|||
""")
|
||||
|
||||
|
||||
def ssh_help_texts(ips, password):
|
||||
def ssh_help_texts(ssh_info):
|
||||
|
||||
texts = [_(SSH_HELP_PROLOGUE), ""]
|
||||
|
||||
if len(ips) > 0:
|
||||
if len(ips) > 1:
|
||||
if len(ssh_info.ips) > 0:
|
||||
if len(ssh_info.ips) > 1:
|
||||
texts.append(rewrap(_(SSH_HELP_MULTIPLE_ADDRESSES)))
|
||||
texts.append("")
|
||||
for ip in ips:
|
||||
for ip in ssh_info.ips:
|
||||
texts.append(Text(
|
||||
"installer@" + str(ip), align='center'))
|
||||
"{}@{}".format(ssh_info.username, ip), align='center'))
|
||||
else:
|
||||
texts.append(_(SSH_HELP_ONE_ADDRESSES).format(
|
||||
ip=str(ips[0])))
|
||||
username=ssh_info.username, ip=str(ssh_info.ips[0])))
|
||||
texts.append("")
|
||||
texts.append(
|
||||
rewrap(_(SSH_HELP_EPILOGUE).format(
|
||||
password=password)))
|
||||
password=ssh_info.password)))
|
||||
texts.append("")
|
||||
texts.append(Text(host_key_info()))
|
||||
else:
|
||||
|
@ -241,30 +239,6 @@ def menu_item(text, on_press=None):
|
|||
return Color.frame_button(icon)
|
||||
|
||||
|
||||
async def get_global_addresses(app):
|
||||
return await app.wait_with_text_dialog(
|
||||
app.client.network.global_addresses.GET(),
|
||||
_("Getting network info"),
|
||||
can_cancel=True)
|
||||
|
||||
|
||||
def get_installer_password(dry_run=False):
|
||||
if dry_run:
|
||||
fp = io.StringIO('installer:rAnd0Mpass')
|
||||
else:
|
||||
try:
|
||||
fp = open("/var/log/cloud-init-output.log")
|
||||
except FileNotFoundError:
|
||||
fp = io.StringIO('')
|
||||
|
||||
with fp:
|
||||
for line in fp:
|
||||
if line.startswith("installer:"):
|
||||
return line[len("installer:"):].strip()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class OpenHelpMenu(WidgetWrap):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
@ -282,7 +256,7 @@ class OpenHelpMenu(WidgetWrap):
|
|||
drop_to_shell,
|
||||
keys,
|
||||
}
|
||||
if self.parent.ssh_password is not None:
|
||||
if self.parent.ssh_info is not None:
|
||||
ssh_help = menu_item(
|
||||
_("Help on SSH access"), on_press=self.parent.ssh_help)
|
||||
buttons.add(ssh_help)
|
||||
|
@ -324,7 +298,7 @@ class OpenHelpMenu(WidgetWrap):
|
|||
about,
|
||||
]
|
||||
|
||||
if self.parent.ssh_password is not None:
|
||||
if self.parent.ssh_info is not None:
|
||||
entries.append(ssh_help)
|
||||
|
||||
if self.parent.app.opts.run_on_serial:
|
||||
|
@ -379,17 +353,20 @@ class HelpMenu(PopUpLauncher):
|
|||
def __init__(self, app):
|
||||
self.app = app
|
||||
self.btn = header_btn(_("Help"), on_press=self._open)
|
||||
self.ssh_password = None
|
||||
self.ssh_info = None
|
||||
self.current_help = None
|
||||
super().__init__(self.btn)
|
||||
|
||||
def _open(self, sender):
|
||||
log.debug("open help menu")
|
||||
async def _get_ssh_info(self):
|
||||
self.ssh_info = await self.app.wait_with_text_dialog(
|
||||
self.app.client.meta.ssh_info.GET(), "Getting SSH info")
|
||||
self.open_pop_up()
|
||||
|
||||
def _open(self, sender):
|
||||
log.debug("open help menu")
|
||||
self.app.aio_loop.create_task(self._get_ssh_info())
|
||||
|
||||
def create_pop_up(self):
|
||||
if self.ssh_password is None:
|
||||
self.ssh_password = get_installer_password(self.app.opts.dry_run)
|
||||
self._menu = OpenHelpMenu(self)
|
||||
return self._menu
|
||||
|
||||
|
@ -435,10 +412,8 @@ class HelpMenu(PopUpLauncher):
|
|||
_("About the installer"),
|
||||
template.format(**info)))
|
||||
|
||||
async def _ssh_help(self):
|
||||
texts = ssh_help_texts(
|
||||
await get_global_addresses(self.app),
|
||||
self.ssh_password)
|
||||
def ssh_help(self, sender=None):
|
||||
texts = ssh_help_texts(self.ssh_info)
|
||||
|
||||
self._show_overlay(
|
||||
SimpleTextStretchy(
|
||||
|
@ -447,9 +422,6 @@ class HelpMenu(PopUpLauncher):
|
|||
*texts,
|
||||
))
|
||||
|
||||
def ssh_help(self, sender=None):
|
||||
schedule_task(self._ssh_help())
|
||||
|
||||
def show_local(self, local_title, local_doc):
|
||||
|
||||
def cb(sender=None):
|
||||
|
|
|
@ -30,10 +30,6 @@ from subiquitycore.ui.utils import button_pile, rewrap, screen
|
|||
from subiquitycore.screen import is_linux_tty
|
||||
from subiquitycore.view import BaseView
|
||||
|
||||
from subiquity.ui.views.help import (
|
||||
get_installer_password,
|
||||
)
|
||||
|
||||
log = logging.getLogger("subiquity.views.welcome")
|
||||
|
||||
|
||||
|
@ -85,11 +81,11 @@ def get_languages():
|
|||
class WelcomeView(BaseView):
|
||||
title = "Willkommen! Bienvenue! Welcome! Добро пожаловать! Welkom!"
|
||||
|
||||
def __init__(self, controller, cur_lang, serial, ips):
|
||||
def __init__(self, controller, cur_lang, serial, ssh_info):
|
||||
self.controller = controller
|
||||
self.cur_lang = cur_lang
|
||||
if serial and not controller.app.rich_mode:
|
||||
s = self.make_serial_choices(ips)
|
||||
s = self.make_serial_choices(ssh_info)
|
||||
self.title = "Welcome!"
|
||||
else:
|
||||
s = self.make_language_choices()
|
||||
|
@ -119,8 +115,7 @@ class WelcomeView(BaseView):
|
|||
lb, buttons=None, narrow_rows=True,
|
||||
excerpt=_("Use UP, DOWN and ENTER keys to select your language."))
|
||||
|
||||
def make_serial_choices(self, ips):
|
||||
ssh_password = get_installer_password(self.controller.opts.dry_run)
|
||||
def make_serial_choices(self, ssh_info):
|
||||
btns = [
|
||||
other_btn(
|
||||
label="Switch to rich mode",
|
||||
|
@ -135,13 +130,13 @@ class WelcomeView(BaseView):
|
|||
Text(rewrap(SERIAL_TEXT)),
|
||||
Text(""),
|
||||
]
|
||||
if ssh_password and ips:
|
||||
if ssh_info:
|
||||
widgets.append(Text(rewrap(SSH_TEXT)))
|
||||
widgets.append(Text(""))
|
||||
btns.insert(1, other_btn(
|
||||
label="View SSH instructions",
|
||||
on_press=self.ssh_help,
|
||||
user_arg=ssh_password))
|
||||
user_arg=ssh_info))
|
||||
widgets.extend([
|
||||
button_pile(btns),
|
||||
])
|
||||
|
@ -154,9 +149,9 @@ class WelcomeView(BaseView):
|
|||
self.controller.ui.set_header(self.title)
|
||||
self._w = self.make_language_choices()
|
||||
|
||||
def ssh_help(self, sender, password):
|
||||
def ssh_help(self, sender, ssh_info):
|
||||
menu = self.controller.app.help_menu
|
||||
menu.ssh_password = password
|
||||
menu.ssh_info = ssh_info
|
||||
menu.ssh_help()
|
||||
|
||||
def choose_language(self, sender, code):
|
||||
|
|
Loading…
Reference in New Issue