anaconda/anaconda-40.22.3.13/pyanaconda/ui/tui/spokes/askrd.py

227 lines
7.6 KiB
Python
Raw Normal View History

2024-11-14 21:39:56 -08:00
# Ask Remote Desktop text spoke
#
# Asks the user if a text mode or remote desktop based access should be used.
#
# Copyright (C) 2024 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
import sys
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.ui.tui.spokes import NormalTUISpoke
from pyanaconda.core.constants import USERDP, USETEXT, QUIT_MESSAGE
from pyanaconda.core.i18n import N_, _
from pyanaconda.ui.tui import exception_msg_handler
from pyanaconda.core.util import execWithRedirect, ipmi_abort
from simpleline import App
from simpleline.event_loop.signals import ExceptionSignal
from simpleline.render.containers import ListColumnContainer
from simpleline.render.prompt import Prompt
from simpleline.render.screen import InputState
from simpleline.render.screen_handler import ScreenHandler
from simpleline.render.adv_widgets import YesNoDialog
from simpleline.render.widgets import TextWidget
def exception_msg_handler_and_exit(signal, data):
"""Display an exception and exit so that we don't end up in a loop."""
exception_msg_handler(signal, data)
sys.exit(1)
class AskRDSpoke(NormalTUISpoke):
"""
.. inheritance-diagram:: AskRDPSpoke
:parts: 3
"""
title = N_("RDP")
# This spoke is kinda standalone, not meant to be used with a hub
# We pass in some fake data just to make our parents happy
def __init__(self, data, storage=None, payload=None, message=""):
super().__init__(data, storage, payload)
self.input_required = True
self.initialize_start()
self._container = None
# The TUI hasn't been initialized with the message handlers yet. Add an
# exception message handler so that the TUI exits if anything goes wrong
# at this stage.
loop = App.get_event_loop()
loop.register_signal_handler(ExceptionSignal, exception_msg_handler_and_exit)
self._message = message
self._rdp_username = ""
self._rdp_password = ""
self._use_rd = False
self.initialize_done()
@property
def use_remote_desktop(self):
"""Should a remote desktop solution be used instead of text mode ?"""
return self._use_rd
@property
def rdp_username(self):
"""User provided RDP user name (if any)."""
return self._rdp_username
@property
def rdp_password(self):
"""User provided RDP password (if any)."""
return self._rdp_password
@property
def indirect(self):
return True
def refresh(self, args=None):
super().refresh(args)
self.window.add_with_separator(TextWidget(self._message))
self._container = ListColumnContainer(1, spacing=1)
# choices are
# USE RDP
self._container.add(TextWidget(_(USERDP)), self._use_rdp_callback)
# USE TEXT
self._container.add(TextWidget(_(USETEXT)), self._use_text_callback)
self.window.add_with_separator(self._container)
def _use_rdp_callback(self, data):
self._use_rd = True
new_rdp_spoke = RDPAuthSpoke(self.data)
ScreenHandler.push_screen_modal(new_rdp_spoke)
self._rdp_username = new_rdp_spoke._username
self._rdp_password = new_rdp_spoke._password
def _use_text_callback(self, data):
self._use_rd = False
def input(self, args, key):
"""Override input so that we can launch the RDP user name & password spoke"""
if self._container.process_user_input(key):
self.apply()
return InputState.PROCESSED_AND_CLOSE
else:
if key.lower() == Prompt.QUIT:
d = YesNoDialog(_(QUIT_MESSAGE))
ScreenHandler.push_screen_modal(d)
if d.answer:
ipmi_abort(scripts=self.data.scripts)
if conf.system.can_reboot:
execWithRedirect("systemctl", ["--no-wall", "reboot"])
else:
sys.exit(1)
else:
return super().input(args, key)
def apply(self):
pass
class RDPAuthSpoke(NormalTUISpoke):
"""
.. inheritance-diagram:: RDPAuthSpoke
:parts: 3
"""
def __init__(self, data, username=None, password=None):
super().__init__(data, storage=None, payload=None)
self.title = N_("RDP User name & Password")
if username is not None:
self._username = username
else:
self._username = ""
if password is not None:
self._password = password
else:
self._password = ""
@property
def indirect(self):
return True
@property
def completed(self):
return True # We're always complete
def refresh(self, args=None):
super().refresh(args)
self.window.add_with_separator(TextWidget(self.message))
@property
def message(self):
text = ""
if not self._username and not self._password:
text = _("Please provide RDP user name & password.")
elif self._username:
text = _("Please provide RDP password.")
else:
text = _("Please provide RDP user name.")
# if we want the password, add a note about typing it twice
if not self._password:
text = text + "\n" + _("You will have to type the password twice.")
return text
def prompt(self, args=None):
"""Override prompt as password typing is special."""
# first make sure username is set
if not self._username:
username = self.get_user_input(_("User name: "), False)
if username:
self._username = username
else:
self._print_error_and_redraw(_("User name not set!"))
return None
# next try to get the password
if not self._password:
p1 = self.get_user_input(_("Password: "), True)
p2 = self.get_user_input(_("Password (confirm): "), True)
if p1 != p2:
self._print_error_and_redraw(_("Passwords do not match!"))
return None
elif not p1:
self._print_error_and_redraw((_("The password must not be empty.")))
return None
elif 0 < len(p1) < 6:
self._print_error_and_redraw((_("The password must be at least "
"six characters long.")))
return None
else:
self._password = p1
# do we finally have everything ?
if self._username and self._password:
self.apply()
self.close()
# ruff: noqa: PLR1711
return None
def _print_error_and_redraw(self, msg):
print(msg)
self.redraw()
def apply(self):
pass