diff options
| author | Martin Sivak <msivak@redhat.com> | 2012-09-12 15:23:58 +0200 |
|---|---|---|
| committer | Martin Sivak <msivak@redhat.com> | 2012-09-13 14:53:27 +0200 |
| commit | 4fc8c074b72222451a8098ff1f693c19b04da469 (patch) | |
| tree | 1f3ac86b7f89a1855e80c32d33ab92e9a32bd048 | |
| parent | de2567b9ea4e056b688379bb241386cfcbbc9585 (diff) | |
| download | anaconda-4fc8c074b72222451a8098ff1f693c19b04da469.tar.gz anaconda-4fc8c074b72222451a8098ff1f693c19b04da469.tar.xz anaconda-4fc8c074b72222451a8098ff1f693c19b04da469.zip | |
Make progress hub spokes possible and move the root password there
- Splits doInstall to doInstall and doConfiguration
- Updates text and gui mode to use doConfiguration
| -rw-r--r-- | pyanaconda/install.py | 67 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/categories/customization.py | 32 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/categories/user_settings.py | 32 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/hubs/__init__.py | 6 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/hubs/progress.glade | 58 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/hubs/progress.py | 85 | ||||
| -rw-r--r-- | pyanaconda/ui/gui/spokes/password.py | 8 | ||||
| -rw-r--r-- | pyanaconda/ui/tui/hubs/progress.py | 24 |
8 files changed, 253 insertions, 59 deletions
diff --git a/pyanaconda/install.py b/pyanaconda/install.py index 3db5ee05c..d401e2faf 100644 --- a/pyanaconda/install.py +++ b/pyanaconda/install.py @@ -42,6 +42,44 @@ def _writeKS(ksdata): # Make it so only root can read - could have passwords os.chmod(path, 0600) +def doConfiguration(storage, payload, ksdata, instClass): + from pyanaconda import progress + from pyanaconda.kickstart import runPostScripts + + progress.send_init(4) + + # Now run the execute methods of ksdata that require an installed system + # to be present first. + with progress_report(_("Configuring installed system")): + ksdata.authconfig.execute(storage, ksdata, instClass) + ksdata.selinux.execute(storage, ksdata, instClass) + ksdata.firstboot.execute(storage, ksdata, instClass) + ksdata.services.execute(storage, ksdata, instClass) + ksdata.keyboard.execute(storage, ksdata, instClass) + ksdata.timezone.execute(storage, ksdata, instClass) + ksdata.lang.execute(storage, ksdata, instClass) + + with progress_report(_("Writing network configuration")): + writeNetworkConf(storage, ksdata, instClass) + + # Creating users and groups requires some pre-configuration. + with progress_report(_("Creating users")): + u = Users() + createLuserConf(ROOT_PATH, algoname=getPassAlgo(ksdata.authconfig.authconfig)) + + ksdata.rootpw.execute(storage, ksdata, instClass, u) + ksdata.group.execute(storage, ksdata, instClass, u) + ksdata.user.execute(storage, ksdata, instClass, u) + + with progress_report(_("Running post install scripts")): + runPostScripts(ksdata.scripts) + + # Write the kickstart file to the installed system (or, copy the input + # kickstart file over if one exists). + _writeKS(ksdata) + + progress.send_complete() + def doInstall(storage, payload, ksdata, instClass): """Perform an installation. This method takes the ksdata as prepared by the UI (the first hub, in graphical mode) and applies it to the disk. @@ -56,8 +94,7 @@ def doInstall(storage, payload, ksdata, instClass): steps = len(storage.devicetree.findActions(type="create", object="format")) + \ len(storage.devicetree.findActions(type="resize", object="format")) + \ len(storage.devicetree.findActions(type="migrate", object="format")) - steps += 5 # packages setup, packages, bootloader, post install, - # configuring + steps += 4 # packages setup, packages, bootloader, post install progress.send_init(steps) # Do partitioning. @@ -85,30 +122,4 @@ def doInstall(storage, payload, ksdata, instClass): with progress_report(_("Installing bootloader")): writeBootLoader(storage, payload, instClass) - with progress_report(_("Configuring installed system")): - # Now run the execute methods of ksdata that require an installed system - # to be present first. - ksdata.authconfig.execute(storage, ksdata, instClass) - ksdata.selinux.execute(storage, ksdata, instClass) - ksdata.firstboot.execute(storage, ksdata, instClass) - ksdata.services.execute(storage, ksdata, instClass) - ksdata.keyboard.execute(storage, ksdata, instClass) - ksdata.timezone.execute(storage, ksdata, instClass) - ksdata.lang.execute(storage, ksdata, instClass) - - writeNetworkConf(storage, ksdata, instClass) - - # Creating users and groups requires some pre-configuration. - createLuserConf(ROOT_PATH, algoname=getPassAlgo(ksdata.authconfig.authconfig)) - u = Users() - ksdata.rootpw.execute(storage, ksdata, instClass, u) - ksdata.group.execute(storage, ksdata, instClass, u) - ksdata.user.execute(storage, ksdata, instClass, u) - - runPostScripts(ksdata.scripts) - - # Write the kickstart file to the installed system (or, copy the input - # kickstart file over if one exists). - _writeKS(ksdata) - progress.send_complete() diff --git a/pyanaconda/ui/gui/categories/customization.py b/pyanaconda/ui/gui/categories/customization.py new file mode 100644 index 000000000..68b422cb1 --- /dev/null +++ b/pyanaconda/ui/gui/categories/customization.py @@ -0,0 +1,32 @@ +# Localization category classes +# +# Copyright (C) 2011 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. +# +# Red Hat Author(s): Chris Lumens <clumens@redhat.com> +# Martin Sivak <msivak@redhat.com> +# + +N_ = lambda x: x + +from pyanaconda.ui.gui.categories import SpokeCategory +from pyanaconda.ui.gui.hubs.progress import ProgressHub + +__all__ = ["CustomizationCategory"] + +class CustomizationCategory(SpokeCategory): + displayOnHub = ProgressHub + title = N_("CUSTOMIZATION") diff --git a/pyanaconda/ui/gui/categories/user_settings.py b/pyanaconda/ui/gui/categories/user_settings.py new file mode 100644 index 000000000..b9838b849 --- /dev/null +++ b/pyanaconda/ui/gui/categories/user_settings.py @@ -0,0 +1,32 @@ +# Localization category classes +# +# Copyright (C) 2011 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. +# +# Red Hat Author(s): Chris Lumens <clumens@redhat.com> +# Martin Sivak <msivak@redhat.com> +# + +N_ = lambda x: x + +from pyanaconda.ui.gui.categories import SpokeCategory +from pyanaconda.ui.gui.hubs.progress import ProgressHub + +__all__ = ["UserSettingsCategory"] + +class UserSettingsCategory(SpokeCategory): + displayOnHub = ProgressHub + title = N_("USER SETTINGS") diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py index 4d8c6e36a..13f61926e 100644 --- a/pyanaconda/ui/gui/hubs/__init__.py +++ b/pyanaconda/ui/gui/hubs/__init__.py @@ -224,8 +224,12 @@ class Hub(GUIObject, common.Hub): self.window.set_info(Gtk.MessageType.WARNING, msg) + @property + def continuePossible(self): + return len(self._incompleteSpokes) == 0 and len(self._notReadySpokes) == 0 + def _updateContinueButton(self): - self.continueButton.set_sensitive(len(self._incompleteSpokes) == 0 and len(self._notReadySpokes) == 0) + self.continueButton.set_sensitive(self.continuePossible) def _update_spokes(self): from pyanaconda.ui.gui import communication diff --git a/pyanaconda/ui/gui/hubs/progress.glade b/pyanaconda/ui/gui/hubs/progress.glade index 036fcb40d..39a1532be 100644 --- a/pyanaconda/ui/gui/hubs/progress.glade +++ b/pyanaconda/ui/gui/hubs/progress.glade @@ -6,7 +6,7 @@ <property name="startup_id">filler</property> <property name="can_focus">False</property> <property name="startup_id">filler</property> - <property name="window_name">PERSONALIZATION</property> + <property name="window_name">CONFIGURATION</property> <child internal-child="main_box"> <object class="GtkBox" id="AnacondaHubWindow-main_box1"> <property name="can_focus">False</property> @@ -29,6 +29,7 @@ <property name="can_focus">False</property> <property name="yalign">0</property> <property name="xscale">0.5</property> + <property name="yscale">0.5</property> <child internal-child="action_area"> <object class="GtkBox" id="progressWindow-actionArea"> <property name="can_focus">False</property> @@ -111,6 +112,59 @@ <property name="show_tabs">False</property> <property name="show_border">False</property> <child> + <object class="GtkGrid" id="configurationGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="configurationLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">end</property> + <property name="label" translatable="yes">%s is now successfully installed on your system, but some configuration still needs to be done. +Finish it and then click the Finish configuration button please.</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="configureButton"> + <property name="label" translatable="yes">_Finish configuration</property> + <property name="use_action_appearance">False</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">end</property> + <property name="valign">end</property> + <property name="hexpand">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="_do_configuration" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> <object class="GtkGrid" id="rebootGrid"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -159,7 +213,7 @@ for you to use! Go ahead and reboot to start using it!</property> </child> </object> <packing> - <property name="position">1</property> + <property name="position">3</property> </packing> </child> <child type="tab"> diff --git a/pyanaconda/ui/gui/hubs/progress.py b/pyanaconda/ui/gui/hubs/progress.py index 4033d7bac..7dab0da61 100644 --- a/pyanaconda/ui/gui/hubs/progress.py +++ b/pyanaconda/ui/gui/hubs/progress.py @@ -49,8 +49,33 @@ class ProgressHub(Hub): self._totalSteps = 0 self._currentStep = 0 + self._configurationDone = False - def _update_progress(self): + def _do_configuration(self, widget = None, reenable_ransom = True): + from pyanaconda.install import doConfiguration + from pyanaconda.threads import threadMgr, AnacondaThread + + assert self._configurationDone == False + + self._configurationDone = True + + # Disable all personalization spokes + self.builder.get_object("progressWindow-scroll").set_sensitive(False) + + if reenable_ransom: + self._start_ransom_notes() + + self._progress_id = GLib.timeout_add(250, self._update_progress, self._configuration_done) + threadMgr.add(AnacondaThread(name="AnaConfigurationThread", target=doConfiguration, + args=(self.storage, self.payload, self.data, self.instclass))) + + def _start_ransom_notes(self): + # Adding this as a timeout below means it'll get called after 60 + # seconds, so we need to do the first call manually. + self._cycle_rnotes() + self._rnotes_id = GLib.timeout_add_seconds(60, self._cycle_rnotes) + + def _update_progress(self, callback = None): from pyanaconda import progress import Queue @@ -78,13 +103,8 @@ class ProgressHub(Hub): self._progress_bar_complete() q.task_done() - GLib.source_remove(self._rnotes_id) - - self._progressNotebook.set_current_page(0) - - # kickstart install, continue automatically if reboot or shutdown selected - if flags.automatedInstall and self.data.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: - self.continueButton.emit("clicked") + if callback: + callback() return False @@ -92,6 +112,31 @@ class ProgressHub(Hub): return True + + def _configuration_done(self): + # Configuration done, remove ransom notes timer + # and switch to the Reboot page + + GLib.source_remove(self._rnotes_id) + self._progressNotebook.set_current_page(1) + + # kickstart install, continue automatically if reboot or shutdown selected + if flags.automatedInstall and self.data.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: + self.continueButton.emit("clicked") + + + def _install_done(self): + # package installation done, check personalization spokes + # and start the configuration step if all is ready + if not self._inSpoke and self.continuePossible: + self._do_configuration(reenable_ransom = False) + + else: + # some mandatory spokes are not ready + # switch to configure and finish page + GLib.source_remove(self._rnotes_id) + self._progressNotebook.set_current_page(0) + def _get_rnotes(self): import glob @@ -130,6 +175,9 @@ class ProgressHub(Hub): self._progressLabel = self.builder.get_object("progressLabel") self._progressNotebook = self.builder.get_object("progressNotebook") + lbl = self.builder.get_object("configurationLabel") + lbl.set_text(lbl.get_text() % productName) + lbl = self.builder.get_object("rebootLabel") lbl.set_text(lbl.get_text() % productName) @@ -142,14 +190,14 @@ class ProgressHub(Hub): self._progressNotebook.append_page(img, None) # An infinite list of the page numbers containing ransom notes images. - self._rnotesPages = itertools.cycle(range(1, self._progressNotebook.get_n_pages()-1)) + self._rnotesPages = itertools.cycle(range(2, self._progressNotebook.get_n_pages()-2)) else: # Add a blank page to the notebook and we'll just cycle to that # over and over again. blank = Gtk.Box() blank.show() self._progressNotebook.append_page(blank, None) - self._rnotesPages = itertools.cycle([1]) + self._rnotesPages = itertools.cycle([2]) def refresh(self): from pyanaconda.install import doInstall @@ -157,15 +205,17 @@ class ProgressHub(Hub): Hub.refresh(self) - # Adding this as a timeout below means it'll get called after 60 - # seconds, so we need to do the first call manually. - self._cycle_rnotes() - - self._progress_id = GLib.timeout_add(250, self._update_progress) - self._rnotes_id = GLib.timeout_add_seconds(60, self._cycle_rnotes) + self._start_ransom_notes() + self._progress_id = GLib.timeout_add(250, self._update_progress, self._install_done) threadMgr.add(AnacondaThread(name="AnaInstallThread", target=doInstall, args=(self.storage, self.payload, self.data, self.instclass))) + def _updateContinueButton(self): + if self._configurationDone: + self.continueButton.set_sensitive(self.continuePossible) + else: + self.builder.get_object("configureButton").set_sensitive(self.continuePossible) + @property def continueButton(self): return self.builder.get_object("rebootButton") @@ -177,6 +227,9 @@ class ProgressHub(Hub): with gdk_threaded(): self._progressBar.set_fraction(0.0) + spinner = self.builder.get_object("progressSpinner") + spinner.start() + def _step_progress_bar(self): if not self._totalSteps: return diff --git a/pyanaconda/ui/gui/spokes/password.py b/pyanaconda/ui/gui/spokes/password.py index ac6e35364..672c44cf7 100644 --- a/pyanaconda/ui/gui/spokes/password.py +++ b/pyanaconda/ui/gui/spokes/password.py @@ -30,8 +30,7 @@ import pwquality import string from pyanaconda.ui.gui.spokes import NormalSpoke -# Need a new category I guess -from pyanaconda.ui.gui.categories.localization import LocalizationCategory +from pyanaconda.ui.gui.categories.user_settings import UserSettingsCategory #from _isys import isCapsLockEnabled __all__ = ["PasswordSpoke"] @@ -43,8 +42,7 @@ class PasswordSpoke(NormalSpoke): mainWidgetName = "passwordWindow" uiFile = "spokes/password.glade" - # update this category to something... new? - category = LocalizationCategory + category = UserSettingsCategory icon = "dialog-password-symbolic" title = N_("ROOT PASSWORD") @@ -164,4 +162,4 @@ class PasswordSpoke(NormalSpoke): self.window.clear_info() self.window.set_info(Gtk.MessageType.WARNING, self._error) self.pw.grab_focus() - self.window.show_all()
\ No newline at end of file + self.window.show_all() diff --git a/pyanaconda/ui/tui/hubs/progress.py b/pyanaconda/ui/tui/hubs/progress.py index cbf384dbd..e0a017600 100644 --- a/pyanaconda/ui/tui/hubs/progress.py +++ b/pyanaconda/ui/tui/hubs/progress.py @@ -80,11 +80,6 @@ class ProgressHub(TUIHub): # There shouldn't be any more progress updates, so return q.task_done() - # kickstart install, continue automatically if reboot or shutdown selected - if flags.automatedInstall and self.data.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: - # Just pretend like we got input, and our input doesn't care - # what it gets, it just quits. - self.input(None, None) if self._stepped: print('') @@ -94,7 +89,7 @@ class ProgressHub(TUIHub): return True def refresh(self, args): - from pyanaconda.install import doInstall + from pyanaconda.install import doInstall, doConfiguration from pyanaconda.threads import threadMgr, AnacondaThread # We print this here because we don't really use the window object @@ -105,7 +100,22 @@ class ProgressHub(TUIHub): self.instclass))) # This will run until we're all done with the install thread. - return self._update_progress() + self._update_progress() + + threadMgr.add(AnacondaThread(name="AnaConfigurationThread", target=doConfiguration, + args=(self.storage, self.payload, self.data, + self.instclass))) + + # This will run until we're all done with the configuration thread. + self._update_progress() + + # kickstart install, continue automatically if reboot or shutdown selected + if flags.automatedInstall and self.data.reboot.action in [KS_REBOOT, KS_SHUTDOWN]: + # Just pretend like we got input, and our input doesn't care + # what it gets, it just quits. + self.input(None, None) + + return True def prompt(self, args = None): return(_("\tInstallation complete. Press return to quit")) |
