Take II: [master/rhel7-branch] Auto-load ks.cfg if OEMDRV volume available. (#1057271)
by Samantha N. Bueno
This checks if there are any OEMDRV labelled storage volumes available--
if yes, load a ks.cfg file from that.
This should only happen if a user has not manually specified a ks=
option themselves.
Additionally, this checks for a boot arg inst.ks=none, to explicitly
disable autoloading of ks.cfg from any detected OEMDRV volumes.
Resolves: rhbz#1057271
---
dracut/kickstart-genrules.sh | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dracut/kickstart-genrules.sh b/dracut/kickstart-genrules.sh
index 3b83d6c..b5823f9 100755
--- a/dracut/kickstart-genrules.sh
+++ b/dracut/kickstart-genrules.sh
@@ -24,4 +24,10 @@ case "${kickstart%%:*}" in
bd) # bd:<dev>:<path> - biospart (TODO... if anyone uses this anymore)
warn "inst.ks: can't get kickstart - biospart (bd:) isn't supported yet"
;;
+ "")
+ if [ -z "$kickstart" -a $(getarg ks= inst.ks=) != "none" ]; then
+ when_diskdev_appears $(disk_to_dev_path LABEL=OEMDRV) \
+ fetch-kickstart-disk \$env{DEVNAME} "/ks.cfg"
+ fi
+ ;;
esac
--
1.9.3
8 years, 10 months
[PATCH python-meh] Run pylint as part of "make ci".
by Chris Lumens
Also, use sys.exit instead of os._exit to make sure pocketlint's atexit
handler runs.
---
Makefile | 2 +-
tests/pylint/runpylint.py | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index a59aff2..8df17e7 100644
--- a/Makefile
+++ b/Makefile
@@ -84,6 +84,6 @@ bumpver: potfile
sed -i "s/Version: $(VERSION)/Version: $$NEWVERSION/" python-meh.spec ; \
sed -i "s/version='$(VERSION)'/version='$$NEWVERSION'/" setup.py
-ci: test
+ci: check test
.PHONY: clean install tag archive local
diff --git a/tests/pylint/runpylint.py b/tests/pylint/runpylint.py
index 2fbdb5c..146d04a 100755
--- a/tests/pylint/runpylint.py
+++ b/tests/pylint/runpylint.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
-import os
+import sys
from pocketlint import PocketLintConfig, PocketLinter
@@ -16,5 +16,4 @@ if __name__ == "__main__":
conf = MehLintConfig()
linter = PocketLinter(conf)
rc = linter.run()
- os._exit(rc)
-
+ sys.exit(rc)
--
2.4.3
8 years, 10 months
[master][blivet] Add CONTRIBUTING file to blivet.
by Samantha N. Bueno
This contains patch submission guidelines for blivet, which are based
on the kernel patch submission guidelines.
---
CONTRIBUTING | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 268 insertions(+)
create mode 100644 CONTRIBUTING
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..281e301
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,268 @@
+0. Thanks to the kernel patch submission guidelines, which were used as a
+ framework for creating this document.
+
+ https://www.kernel.org/doc/Documentation/SubmittingPatches
+
+I. Source
+=========
+
+A) Obtain a current source tree.
+If you do not have a repository with the current source handy, use git to obtain
+one. All installer-related projects can be found on the RH Installer project
+page:
+
+ http://github.com/rhinstaller/
+
+Additional help for working within the codebase and testing changes can be found
+on the Fedoraproject wiki:
+
+ https://fedoraproject.org/wiki/Anaconda/Contribute#Helping_with_Anaconda_...
+
+
+II. Commits
+===========
+ - Considerations when composing your commit message
+ - Special formatting (e.g. for RHEL patches)
+ - Etiquette: when you should split a patch
+
+A) Describe your changes clearly.
+Describe your problem. Whether your patch is a one-line bug fix or 5000 lines
+of a new feature, there must be an underlying problem that motivated you to do
+this work. Convince the reviewer that there is a problem worth fixing and that
+it makes sense for them to read past the first paragraph.
+
+Describe user-visible impact. Straight up crashes and lockups are pretty
+convincing, but not all bugs are that blatant. Even if the problem was spotted
+during code review, describe the impact you think it can have on users.
+
+Once the problem is established, describe what you are actually doing about it
+in technical detail. It's important to describe the change in plain English for
+the reviewer to verify that the code is behaving as you intend it to.
+
+Solve only one problem per patch. If your description starts to get long,
+that's a sign that you probably need to split up your patch.
+
+When you submit or resubmit a patch or patch series, include the complete patch
+description and justification for it. Don't just say that this is version N of
+the patch (series). Don't expect the reviewers to refer back to earlier patch
+versions or referenced URLs to find the patch description and put that into the
+patch.
+In other words, the patch (series) and its description should be self-contained.
+
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz" instead of
+"[This patch] makes xyzzy do frotz" or "[I] changed xyzzy to do frotz", as if
+you are giving orders to the codebase to change its behaviour.
+
+B) Special considerations for RHEL bugs.
+If you are submitting a patch for any rhel-branch, the last line of your commit
+message must identify the bugzilla bug # it fixes, using the "Resolves" or
+"Related" keyword, e.g.:
+
+ Resolves: rhbz#1111111
+ or
+ Related: rhbz#1234567
+
+Use "Resolves" if the patch fixes the core issue which caused the bug.
+Use "Related" if the patch fixes an ancillary issue that is related to, but
+might not actually fix the bug.
+
+C) Tracking other history in the commit log.
+In order to easily reference various items related to any patch (set), other
+information should be included in your commit message (after adequately
+describing the problem and your fix). This includes:
+ * GitHub issue, for easy reference back to any scheduled/task list items.
+ Add a line(s):
+ resolves #77
+ or
+ resolves rhinstaller/blivet#14
+
+D) Separate your changes.
+Separate each _logical change_ into a separate patch.
+
+For example, if your changes include both bug fixes and new functionality in a
+single area, separate those changes into two or more patches. If your changes
+include an API update, and new code which uses that new API, separate those into
+two patches.
+
+On the other hand, if you make a single change to numerous files, group those
+changes into a single patch. Thus a single logical change is contained within a
+single patch. The point to remember is that each patch should make an easily
+understood change that can be verified by reviewers.
+
+If one patch depends on another patch in order for a change to be complete, that
+is OK. Simply note "this patch depends on patch X" in your patch description.
+
+When dividing your change into a series of patches, it is preferred that you
+ensure that the project builds and runs properly after each patch in the series.
+Developers using "git bisect" to track down a problem can end up splitting your
+patch series at any point; they will not thank you if you introduce bugs in the
+middle.
+
+E) Style-check your changes.
+Make sure that the style of your code matches that of the surrounding code.
+
+F) Tests and sanity checking.
+Prior to submitting any patch for review, make sure it runs through pylint
+cleanly. The pylint test can be found in tests/pylint/runpylint.sh
+
+Additionally, creating test files and making sure your changes pass new tests --
+and do not break existing tests -- is crucial. Run "make test" to run the test
+suite.
+
+
+III. Submitting Patches
+=======================
+ - Acceptable formats for patch submission
+ - Email guidelines
+ - Pull Request guidelines
+
+A) Acceptable patch formats.
+GitHub pull requests are accepted. In fact, they are the preferred format.
+
+Patches can also be sent to anaconda-patches(a)lists.fedorahosted.org, provided
+they are formatted appropriately (see section III.C).
+
+B) GitHub pull request guidelines
+Labels are used extensively on pull requests in GitHub. Labels make it very easy
+to visually filter a list of pull requests. Labels that we use include:
+ * rhelX-branch -- Any RHEL pull requests should be tagged with the
+ appropriate RHEL branch label (e.g. rhel6-branch, rhel7-branch)
+ * fXY-branch -- Any Fedora pull requests should be tagged with the
+ appropriate Fedora branch label (e.g. f22-branch)
+ * Python 3 check -- If a pull request introduces changes which need to be
+ verified as Python 3 compatible, set this label. (Or someone who reviews
+ your pull request might set this.)
+ * ACK -- Once somebody has reviewed your pull request, they will set the ACK
+ label if your patch is approved.
+ * NACK -- If somebody has reviewed your pull request and disapproves with
+ the patch, they will set the NACK label.
+
+If submitting a patch against multiple branches (e.g. master, rhel7-branch),
+submit the original pull request against master branch. Use labels to tag the
+request for each branch it is intended for.
+
+After approval, merge your commit to master branch. You will have to manually
+cherry pick it to any other branches. Use "git cherry-pick -x $commit" to do
+this, so there is a reference back to the original commit.
+
+C) Email guidelines.
+ i. What to include in your subjects.
+ It is common convention to prefix your subject line with
+ [$project][$branches]. This makes it clear which project the patches are
+ for and which branches the patches are intended for.
+
+ This also applies to lone patches that do not include a cover letter.
+ Examples:
+ Subject: [blivet][master] Move the Blivet class into its own module
+ Subject: [blivet][master/rhel7-branch] Do not unhide devices with hidden
+ parents (#1158643)
+
+ It is common convention to prefix path subject lines with [PATCH]. This
+ makes clear that the message is a patch.
+
+ ii. No MIME, no links, no compression, no attachments. Just plain text.
+ The developers need to be able to read and comment on the changes you are
+ submitting. It is important for a developer to be able to "quote" your
+ changes, using standard e-mail tools, so that they may comment on specific
+ portions of your code.
+
+ For this reason, all patches should be submitting e-mail "inline". WARNING:
+ Be wary of your editor's word-wrap corrupting your patch, if you choose to
+ cut-n-paste your patch.
+
+ Do not attach the patch as a MIME attachment, compressed or not.
+
+ iii. E-mail size.
+ Large changes are not appropriate for mailing listss. If your patch,
+ uncompressed, exceeds 300 kB in size, it is preferred that you store your
+ patch on a server and provide instead a URL (link) pointing to your patch.
+ But note that if your patch exceeds 300 kB, it almost certainly needs to be
+ broken up anyway.
+
+ iv. Canonical patch format.
+ This section describes how the patch itself should be formatted. Note that,
+ if you have your patches are stored in a git repository, proper patch
+ formatting can be had with "git format-patch". The tools cannot create the
+ necessary text, though, so read the instructions anyway.
+
+ Cover letter subject should include the component, the relevant branches,
+ and the relevant bugzilla bug # (if applicable).
+
+ Some examples of the canonical patch subject line:
+ Subject: [PATCH 1/4][blivet][f22-branch] summary phrase (#9999999)
+ Subject: [PATCH 1/3][blivet][master] Split X out of class Y into new
+ class Z
+
+ The canonical patch message body contains the following:
+ - A "from" line specifying the patch's original author.
+ - An empty line.
+ - The body of the explanation, which will be copied to the permanent
+ changelog to describe this patch.
+ - A marker line containing simply "---".
+ - Any additional comments not suitable for the changelog.
+ - The actual patch (diff output).
+
+ The "summary phrase" in the email's Subject should concisely describe the
+ patch which the email contains in no more than 70-75 characters. The
+ "summary phrase" should not be a filename. Do not use the same "summary
+ phrase" for every patch in a whole patch series (where a "patch series" is
+ an ordered sequence of multiple, related patches). Bear in mind that the
+ "summary phrase" of your email will be the only thing that people may
+ quickly see when they are scanning through patches.
+
+ Tags enclosed in square brackets are not considered part of the "summary
+ phrase", but describe how the patch should be treated. Common tags might
+ include the patch number/total, e.g. if there are four patches in a series,
+ they may be numbered like this: 1/4, 2/4, 3/4, 4/4.
+
+ The "from" line must be the very first line in the message body, and has the
+ form:
+ From: Original Author <author(a)example.com>
+
+ The "from" line specifies who will be credited as the author of the patch in
+ the permanent changelog. If the "from" line is missing, then the "From:"
+ line from the email header will be used to determine the patch author in the
+ changelog.
+
+ Special note to back-porters: It is generally useful when cherry-picking a
+ commit from master onto another branch to use the -x option. This option
+ tells git to insert a note indicating the original commit id, and is often
+ useful.
+
+
+IV. The review process
+======================
+ - What to expect, and when.
+ - Behavioral conduct.
+
+A) Respond to review comments.
+Your patch will almost certainly get comments from reviewers on ways in which
+the patch can be improved. You must respond to those comments; ignoring
+reviewers is a good way to get ignored in return. Comments or questions that do
+not result in a code change should almost certainly bring about a comment or
+changelog entry so that the next reviewer better understands what is going on.
+
+Be sure to tell the reviewers what changes you are making and to thank them for
+their time. Code review is a tiring and time-consuming process, and reviewers
+sometimes get grumpy. Even in that case, though, respond politely and address
+the problems they have pointed out.
+
+It is important to understand that patches must sometimes go through several
+iterations of review before being approved. Not all patches will be accepted
+either. It is important that you do not take any criticism personally. Patch
+review is an objective and rational critique only of the content of the patch
+itself.
+
+B) Don't get discouraged - or impatient.
+After you have submitted your change, be patient and wait. Reviewers are busy
+people and may not get to your patch right away.
+
+You should receive comments within a week or so; if that does not happen, make
+sure that you have sent your patches to the right place. Wait for a minimum of
+one week before resubmitting or pinging reviewers - possibly longer during busy
+times like Fedora release stabilization.
+
+Note that there is a minimum review period of 24 hours for any patch. The
+purpose of this rule is to ensure that all interested parties have an
+opportunity to review every patch. When posting a patch before or after a
+holiday break it is important to extend this period as appropriate.
--
1.9.3
8 years, 10 months
[anaconda][rhel7-branch][PATCH] Add support for autostep and --autoscreenshot (#1234896)
by Martin Kolman
Add the missing support for the autostep [--autoscreenshot]
kickstart command to Anaconda. If just autostep is specified, Anaconda will
iterate over all active spokes just before leaving a hub.
If the --autoscreenshot option specified, it will also take a screenshot of
all hubs and of each spoke.
Also turn the take-screenshot code into a proper function that can
be called when auto-screenshotting and remove the old copy-screenshot
post-script (the last batch of screenshots is taken after the
postscripts have run, so screenshot copying is now handled
elsewhere).
Resolves: rhbz#1234896
Signed-off-by: Martin Kolman <mkolman(a)redhat.com>
---
pyanaconda/constants.py | 4 +
pyanaconda/iutil.py | 27 ++++++
pyanaconda/ui/gui/__init__.py | 179 +++++++++++++++++++++++++++++++----
pyanaconda/ui/gui/hubs/__init__.py | 46 ++++++++-
pyanaconda/ui/gui/spokes/__init__.py | 9 ++
pyanaconda/ui/gui/spokes/welcome.py | 5 +-
6 files changed, 250 insertions(+), 20 deletions(-)
diff --git a/pyanaconda/constants.py b/pyanaconda/constants.py
index 807bf0d..d9ee11f 100644
--- a/pyanaconda/constants.py
+++ b/pyanaconda/constants.py
@@ -154,6 +154,10 @@ PW_ASCII_CHARS = string.digits + string.ascii_letters + string.punctuation + " "
# Recognizing a tarfile
TAR_SUFFIX = (".tar", ".tbz", ".tgz", ".txz", ".tar.bz2", "tar.gz", "tar.xz")
+# screenshots
+SCREENSHOTS_DIRECTORY = "/tmp/anaconda-screenshots"
+SCREENSHOTS_TARGET_DIRECTORY = "/root/anaconda-screenshots"
+
# cmdline arguments that append instead of overwrite
CMDLINE_APPEND = ["modprobe.blacklist"]
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index c827431..9136406 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -27,6 +27,7 @@ import os.path
import errno
import subprocess
import unicodedata
+import shutil
import string
import tempfile
import types
@@ -36,6 +37,7 @@ import signal
from pyanaconda.flags import flags
from pyanaconda.constants import DRACUT_SHUTDOWN_EJECT, TRANSLATIONS_UPDATE_DIR, UNSUPPORTED_HW
+from pyanaconda.constants import SCREENSHOTS_DIRECTORY, SCREENSHOTS_TARGET_DIRECTORY
from pyanaconda.regexes import URL_PARSE
from pyanaconda.i18n import _
@@ -1191,3 +1193,28 @@ def get_platform_groupid():
def parent_dir(directory):
"""Return the parent's path"""
return "/".join(os.path.normpath(directory).split("/")[:-1])
+
+def sysroot_path(path):
+ """Make the given relative or absolute path "sysrooted"
+ :param str path: path to be sysrooted
+ :returns: sysrooted path
+ :rtype: str
+ """
+ return os.path.join(getSysroot(), path.lstrip(os.path.sep))
+
+def save_screenshots():
+ """Save screenshots to the installed system"""
+ if not os.path.exists(SCREENSHOTS_DIRECTORY):
+ # there are no screenshots to copy
+ return
+ target_path = sysroot_path(SCREENSHOTS_TARGET_DIRECTORY)
+ log.info("saving screenshots taken during the installation to: %s" % target_path)
+ try:
+ # create the screenshots directory
+ mkdirChain(target_path)
+ # copy all screenshots
+ for filename in os.listdir(SCREENSHOTS_DIRECTORY):
+ shutil.copy(os.path.join(SCREENSHOTS_DIRECTORY, filename), target_path)
+
+ except OSError:
+ log.exception("saving screenshots to installed system failed")
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
index 9251949..8ffc723 100644
--- a/pyanaconda/ui/gui/__init__.py
+++ b/pyanaconda/ui/gui/__init__.py
@@ -27,10 +27,10 @@ from gi.repository import Gdk, Gtk, AnacondaWidgets, Keybinder, GdkPixbuf, GLib,
from pyanaconda.i18n import _
from pyanaconda.constants import IPMI_ABORTED
-from pyanaconda import product, iutil
+from pyanaconda import product, iutil, constants
from pyanaconda.ui import UserInterface, common
-from pyanaconda.ui.gui.utils import gtk_action_wait, unbusyCursor
+from pyanaconda.ui.gui.utils import gtk_action_wait, gtk_call_once, unbusyCursor
from pyanaconda import ihelp
import os.path
@@ -109,7 +109,7 @@ class GUIObject(common.UIObject):
helpFile = None
translationDomain = "anaconda"
- screenshots_directory = "/tmp/anaconda-screenshots"
+ handles_autostep = False
def __init__(self, data):
"""Create a new UIObject instance, including loading its uiFile and
@@ -156,6 +156,12 @@ class GUIObject(common.UIObject):
Keybinder.init()
Keybinder.bind("<Shift>Print", self._handlePrntScreen, [])
+ self._automaticEntry = False
+ self._autostepRunning = False
+ self._autostepDone = False
+ self._autostepDoneCallback = None
+ self._lastAutostepSpoke = False
+
def _findUIFile(self):
path = os.environ.get("UIPATH", "./:/tmp/updates/:/tmp/updates/ui/:/usr/share/anaconda/ui/")
dirs = path.split(":")
@@ -171,28 +177,128 @@ class GUIObject(common.UIObject):
raise IOError("Could not load UI file '%s' for object '%s'" % (self.uiFile, self))
def _handlePrntScreen(self, *args, **kwargs):
- global _screenshotIndex
global _last_screenshot_timestamp
# as a single press of the assigned key generates
# multiple callbacks, we need to skip additional
# callbacks for some time once a screenshot is taken
if (time.time() - _last_screenshot_timestamp) >= SCREENSHOT_DELAY:
- # Make sure the screenshot directory exists.
- if not os.access(self.screenshots_directory, os.W_OK):
- os.makedirs(self.screenshots_directory)
-
- fn = os.path.join(self.screenshots_directory,
- "screenshot-%04d.png" % _screenshotIndex)
- root_window = Gdk.get_default_root_window()
- pixbuf = Gdk.pixbuf_get_from_window(root_window, 0, 0,
- root_window.get_width(),
- root_window.get_height())
- pixbuf.savev(fn, 'png', [], [])
- log.info("screenshot nr. %d taken", _screenshotIndex)
- _screenshotIndex += 1
+ self.take_screenshot()
# start counting from the time the screenshot operation is done
_last_screenshot_timestamp = time.time()
+ def take_screenshot(self, name=None):
+ """Take a screenshot of the whole screen (works even with multiple displays)
+
+ :param name: optional name for the screenshot that will be appended to the filename,
+ after the standard prefix & screenshot number
+ :type name: str or NoneType
+ """
+ global _screenshotIndex
+ # Make sure the screenshot directory exists.
+ iutil.mkdirChain(constants.SCREENSHOTS_DIRECTORY)
+
+ if name is None:
+ screenshot_filename = "screenshot-%04d.png" % _screenshotIndex
+ else:
+ screenshot_filename = "screenshot-%04d-%s.png" % (_screenshotIndex, name)
+
+ fn = os.path.join(constants.SCREENSHOTS_DIRECTORY, screenshot_filename)
+
+ root_window = self.main_window.get_window()
+ pixbuf = Gdk.pixbuf_get_from_window(root_window, 0, 0,
+ root_window.get_width(),
+ root_window.get_height())
+ pixbuf.savev(fn, 'png', [], [])
+ log.info("%s taken", screenshot_filename)
+ _screenshotIndex += 1
+
+ @property
+ def automaticEntry(self):
+ """Report if the given GUIObject has been displayed under automatic control
+
+ This is needed for example for installations with an incomplete kickstart,
+ as we need to differentiate the automatic screenshot pass from the user
+ entering a spoke to manually configure things. We also need to skip applying
+ changes if the spoke is entered automatically.
+ """
+ return self._automaticEntry
+
+ @automaticEntry.setter
+ def automaticEntry(self, value):
+ self._automaticEntry = value
+
+ @property
+ def autostepRunning(self):
+ """Report if the GUIObject is currently running autostep"""
+ return self._autostepRunning
+
+ @autostepRunning.setter
+ def autostepRunning(self, value):
+ self._autostepRunning = value
+
+ @property
+ def autostepDone(self):
+ """Report if autostep for this GUIObject has been finished"""
+ return self._autostepDone
+
+ @autostepDone.setter
+ def autostepDone(self, value):
+ self._autostepDone = value
+
+ @property
+ def autostepDoneCallback(self):
+ """A callback to be run once autostep has been finished"""
+ return self._autostepDoneCallback
+
+ @autostepDoneCallback.setter
+ def autostepDoneCallback(self, callback):
+ self._autostepDoneCallback = callback
+
+ @property
+ def lastAutostepSpoke(self):
+ """Indicates if the screen is the last spoke to be processed on a hub"""
+ return self._lastAutostepSpoke
+
+ @lastAutostepSpoke.setter
+ def lastAutostepSpoke(self, value):
+ self._lastAutostepSpoke = value
+
+ def autostep(self):
+ """Autostep through this graphical object and through
+ any graphical objects managed by it (such as through spokes for a hub)
+ """
+ # report that autostep is running to prevent another from starting
+ self.autostepRunning = True
+ # take a screenshot of the current graphical object
+ if self.data.autostep.autoscreenshot:
+ # as autostep is triggered just before leaving a screen,
+ # we can safely take a screenshot of the "parent" object at once
+ # without using idle_add
+ self.take_screenshot(self.__class__.__name__)
+ self._doAutostep()
+ # done
+ self.autostepRunning = False
+ self.autostepDone = True
+ self._doPostAutostep()
+
+ # run the autostep-done callback (if any)
+ if self.autostepDoneCallback:
+ self.autostepDoneCallback(self)
+
+ def _doPostAutostep(self):
+ """To be overridden by the given GUIObject sub-class with custom code
+ that brings the GUI from the autostepping mode back to the normal mode.
+ This usually means to "click" the continue button or its equivalent.
+ """
+ pass
+
+ def _doAutostep(self):
+ """To be overridden by the given GUIObject sub-class with customized
+ autostepping code - if needed
+ (this is for example used to step through spokes in a hub)
+ """
+ pass
+
@property
def window(self):
"""Return the object out of the GtkBuilder representation
@@ -410,6 +516,27 @@ class MainWindow(Gtk.Window):
"""
self._setVisibleChild(spoke)
+ # autostep through the spoke if required
+ if spoke.automaticEntry:
+ # we need to use idle_add here to give GTK time to render the spoke
+ gtk_call_once(self._autostep_spoke, spoke)
+
+ def _autostep_spoke(self, spoke):
+ """Step through a spoke and make a screenshot if required.
+ If this is the last spoke to be autostepped on a hub return to
+ the hub so that we can proceed to the next one.
+ """
+ # it might be possible that autostep is specified, but autoscreenshot isn't
+ if spoke.data.autostep.autoscreenshot:
+ spoke.take_screenshot(spoke.__class__.__name__)
+
+ if spoke.autostepDoneCallback:
+ spoke.autostepDoneCallback(spoke)
+
+ # if this is the last spoke then return to hub
+ if spoke.lastAutostepSpoke:
+ self.returnToHub()
+
def returnToHub(self):
"""Exit a spoke and return to a hub."""
self._setVisibleChild(self._current_action)
@@ -753,11 +880,29 @@ class GraphicalUserInterface(UserInterface):
### SIGNAL HANDLING METHODS
###
def _on_continue_clicked(self, win, user_data=None):
+ # Autostep needs to be triggered just before switching to the next screen
+ # (or before quiting the installation if there are no more screens) to be consistent
+ # in both fully automatic kickstart installation and for installation with an incomplete
+ # kickstart. Therefore we basically "hook" the continue-clicked signal, start autostepping
+ # and ignore any other continue-clicked signals until autostep is done.
+ # Once autostep finishes, it emits the appropriate continue-clicked signal itself,
+ # switching to the next screen (if any).
+ if self.data.autostep.seen and self._currentAction.handles_autostep:
+ if self._currentAction.autostepRunning:
+ log.debug("ignoring the continue-clicked signal - autostep is running")
+ return
+ elif not self._currentAction.autostepDone:
+ self._currentAction.autostep()
+ return
+
if not win.get_may_continue():
return
# If we're on the last screen, clicking Continue quits.
if len(self._actions) == 1:
+ # save the screenshots to the installed system before killing Anaconda
+ # (the kickstart post scripts run to early, so we need to copy the screenshots now)
+ iutil.save_screenshots()
Gtk.main_quit()
return
diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
index ab68893..bb65329 100644
--- a/pyanaconda/ui/gui/hubs/__init__.py
+++ b/pyanaconda/ui/gui/hubs/__init__.py
@@ -27,7 +27,7 @@ from pyanaconda.product import distributionText
from pyanaconda.ui import common
from pyanaconda.ui.gui import GUIObject
-from pyanaconda.ui.gui.utils import gtk_call_once, escape_markup
+from pyanaconda.ui.gui.utils import gtk_call_once, fire_gtk_action, escape_markup
import logging
log = logging.getLogger("anaconda")
@@ -54,6 +54,8 @@ class Hub(GUIObject, common.Hub):
additional standalone screens either before or after them.
"""
+ handles_autostep = True
+
def __init__(self, data, storage, payload, instclass):
"""Create a new Hub instance.
@@ -91,6 +93,9 @@ class Hub(GUIObject, common.Hub):
self._checker = None
+ self._spokesToStepIn = []
+ self._spokeAutostepIndex = 0
+
def _createBox(self):
from gi.repository import Gtk, AnacondaWidgets
from pyanaconda.ui.gui.utils import setViewportBackground
@@ -353,6 +358,11 @@ class Hub(GUIObject, common.Hub):
def spoke_done(self, spoke):
spoke.visitedSinceApplied = True
+ # don't apply any actions if the spoke was visited automatically
+ if spoke.automaticEntry:
+ spoke.automaticEntry = False
+ return
+
# Don't take visitedSinceApplied into account here. It will always be
# True from the line above.
if spoke.changed and (not spoke.skipTo or (spoke.skipTo and spoke.applyOnSkip)):
@@ -384,3 +394,37 @@ class Hub(GUIObject, common.Hub):
else:
self.main_window.returnToHub()
+ def _doAutostep(self):
+ """Autostep through all spokes managed by this hub"""
+ log.info("autostepping through all spokes on hub %s", self.__class__.__name__)
+ # created a list of all spokes in reverse alphabetic order, we will pop() from it when
+ # processing all the spokes so the screenshots will actually be in alphabetic order
+ self._spokesToStepIn = list(reversed(sorted(self._spokes.values(), key=lambda x: x.__class__.__name__)))
+ # we can't just loop over all the spokes due to the asynchronous nature of GtkStack, so we start by
+ # autostepping to the first spoke, this will trigger a callback that steps to the next spoke,
+ # until we run out of unvisited spokes
+ self._autostepSpoke()
+
+ def _autostepSpoke(self):
+ if self._spokesToStepIn:
+ spoke = self._spokesToStepIn.pop()
+ self._spokeAutostepIndex += 1
+ log.debug("stepping to spoke %s (%d/%d)", spoke.__class__.__name__, self._spokeAutostepIndex, len(self._spokes))
+ spoke.automaticEntry = True
+ spoke.autostepDoneCallback = lambda x: self._autostepSpoke()
+ # this is the last spoke, tell it to return to hub once the screenshot is taken
+ if self._spokesToStepIn == []:
+ spoke.lastAutostepSpoke = True
+ #fire_gtk_action(self._on_spoke_clicked, None, None, spoke)
+ fire_gtk_action(self._on_spoke_clicked, None, None, spoke)
+ else:
+ log.info("autostep for hub %s finished", self.__class__.__name__)
+ gtk_call_once(self._doPostAutostep)
+
+ def _doPostAutostep(self):
+ if self._spokesToStepIn:
+ # there are still spokes that need to be stepped in
+ return
+ # we are done, re-emit the continue clicked signal we "consumed" previously
+ # so that the Anaconda GUI can switch to the next screen (or quit)
+ self.window.emit("continue-clicked")
diff --git a/pyanaconda/ui/gui/spokes/__init__.py b/pyanaconda/ui/gui/spokes/__init__.py
index 1227d44..17866ee 100644
--- a/pyanaconda/ui/gui/spokes/__init__.py
+++ b/pyanaconda/ui/gui/spokes/__init__.py
@@ -21,6 +21,7 @@
from pyanaconda.ui import common
from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.utils import gtk_call_once
from pyanaconda import ihelp
__all__ = ["StandaloneSpoke", "NormalSpoke"]
@@ -28,6 +29,9 @@ __all__ = ["StandaloneSpoke", "NormalSpoke"]
# Inherit abstract methods from common.StandaloneSpoke
# pylint: disable=abstract-method
class StandaloneSpoke(GUIObject, common.StandaloneSpoke):
+
+ handles_autostep = True
+
def __init__(self, data, storage, payload, instclass):
GUIObject.__init__(self, data)
common.StandaloneSpoke.__init__(self, storage, payload, instclass)
@@ -38,6 +42,11 @@ class StandaloneSpoke(GUIObject, common.StandaloneSpoke):
def _on_continue_clicked(self, win, user_data=None):
self.apply()
+ def _doPostAutostep(self):
+ # we are done, re-emit the continue clicked signal we "consumed" previously
+ # so that the Anaconda GUI can switch to the next screen
+ gtk_call_once(self.window.emit, "continue-clicked")
+
# Inherit abstract methods from common.NormalSpoke
# pylint: disable=abstract-method
class NormalSpoke(GUIObject, common.NormalSpoke):
diff --git a/pyanaconda/ui/gui/spokes/welcome.py b/pyanaconda/ui/gui/spokes/welcome.py
index 91b2b3a..028ad43 100644
--- a/pyanaconda/ui/gui/spokes/welcome.py
+++ b/pyanaconda/ui/gui/spokes/welcome.py
@@ -314,8 +314,9 @@ class WelcomeLanguageSpoke(LangLocaleHandler, StandaloneSpoke):
# Override the default in StandaloneSpoke so we can display the beta
# warning dialog first.
def _on_continue_clicked(self, window, user_data=None):
- # Don't display the betanag dialog if this is the final release.
- if not isFinal:
+ # Don't display the betanag dialog if this is the final release or
+ # when autostep has been requested as betanag breaks the autostep logic.
+ if not isFinal and not self.data.autostep.seen:
dlg = self.builder.get_object("betaWarnDialog")
with self.main_window.enlightbox(dlg):
rc = dlg.run()
--
2.4.3
8 years, 10 months
New: [rhinstaller/anaconda/pulls/257 master] Early disk snapshot
by dashea
This is the port of the early disk snapshot stuff we implemented for the Fedora 22 on the *f22-branch*. Turns out a better and reliable solution for a number of bugs these changes fixed and prevented won't be available any time soon so I'm porting this to the master branch to prevent serious regressions.
There have been some conflicts, basically all caused by the fixes for kickstart autopart missing passphrase and by changes done for the s390 stuff moved from blivet to libblockdev.
--
To view this pull request on github, visit https://github.com/rhinstaller/anaconda/pull/257
8 years, 10 months