On Tue, 2015-07-28 at 17:03 +0200, Martin Kolman wrote:
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 | 172 +++++++++++++++++++++++++++++++----
pyanaconda/ui/gui/hubs/__init__.py | 55 +++++++++++
pyanaconda/ui/gui/spokes/__init__.py | 9 ++
pyanaconda/ui/gui/spokes/welcome.py | 5 +-
6 files changed, 253 insertions(+), 19 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..57baf90 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..2169aad 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,14 @@ class GUIObject(common.UIObject):
Keybinder.init()
Keybinder.bind("<Shift>Print", self._handlePrntScreen, [])
+ self._automaticEntry = False
+ self._autostepRunning = False
+ self._autostepDone = False
+ self._autostepDoneCallback = None
+
+ # this indicates if the screen is the last spoke to be processed for a hub
+ 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 +179,119 @@ 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
I meant my comment about the
properties to be replaced by public
attributes for all these properties that do nothing in their
getters/setters. If you agree that these all could be changed to public
attributes, please change them (there's no need to send v3 just because
of this change).
Otherwise the new version looks good to me.
--
Vratislav Podzimek
Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic