[master] UTC/localtime HW clock heuristic
by Vratislav Podzimek
PATCH [1/2] is just a minor change without any significant result.
PATCH [2/2] adds a heuristic to guess wheter HW clock uses UTC or local
time by searching for bootable NTFS partitions. It adds two threads, but
these are really lightweight and just handle the potential long storage
initialization.
Vratislav Podzimek (2):
Return bool value from the GRUB.has_windows method
Set system time from HW clock and guess if it is UTC
anaconda | 11 ++++++++-
pyanaconda/bootloader.py | 2 +-
pyanaconda/kickstart.py | 7 ------
pyanaconda/timezone.py | 38 ++++++++++++++++++++++++++++++
pyanaconda/ui/gui/spokes/datetime_spoke.py | 20 ++++++++++++++++
5 files changed, 69 insertions(+), 9 deletions(-)
--
1.7.11.7
10 years, 11 months
[PATCH] Language Support spoke
by Radek Vykydal
Kickstart command lang is extended with --addsupport option for
specifying additional (to ksdata.lang.lang) language support to be
installed (ksdata.lang.addsupport).
In the spoke GUI, ksdata.lang.lang (system lang) is selected and
grayed-out (insensitive).
Selected (using checkbox) languages are displayed in bold, the list is
searchable in the same way as the welcome spoke list. Currently only
available translations for installer (the same as in welcome spoke) are
in the list.
screencast:
http://rvykydal.fedorapeople.org/langsupport.ogg
11 years
[python-meh] [PATCH] Reword the 'Debug' button waring
by Vratislav Podzimek
Getting to tty1 happens only in Anaconda running a non-live installation, so we
should just warn user it may happen. Also the GUI is now on tty7, but in any
case there is no point in getting back to tty7 manually, because until the
debugging session is finished the GUI is frozen.
---
ui/exception-dialog.glade | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/ui/exception-dialog.glade b/ui/exception-dialog.glade
index 9ae497b..0bed126 100644
--- a/ui/exception-dialog.glade
+++ b/ui/exception-dialog.glade
@@ -87,11 +87,9 @@ report the bug below or quit the program.</property>
<child>
<object class="GtkButton" id="reportButton">
<property name="label" translatable="yes">_Report Bug</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="use_action_appearance">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_report_clicked" swapped="no"/>
</object>
@@ -104,11 +102,9 @@ report the bug below or quit the program.</property>
<child>
<object class="GtkButton" id="quitButton">
<property name="label" translatable="yes">_Quit</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="use_action_appearance">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_quit_clicked" swapped="no"/>
</object>
@@ -186,13 +182,13 @@ report the bug below or quit the program.</property>
<object class="GtkBox" id="bottomBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="spacing">4</property>
+ <property name="spacing">6</property>
<child>
<object class="GtkLabel" id="warningLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0.89999997615814209</property>
- <property name="label" translatable="yes">'Debug' will take you to tty1. Press Ctrl + Alt + F6 to return.</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">'Debug' may take you to tty1.</property>
<attributes>
<attribute name="style" value="italic"/>
<attribute name="scale" value="0.80000000000000004"/>
@@ -207,11 +203,9 @@ report the bug below or quit the program.</property>
<child>
<object class="GtkButton" id="debugButton">
<property name="label" translatable="yes">_Debug</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="use_action_appearance">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_debug_clicked" swapped="no"/>
</object>
--
1.7.11.7
11 years, 1 month
[master] Exception handling related patches
by Vratislav Podzimek
These are patches that fix and enhance behaviour of exception handling
in some specific cases.
PATCH 1/3 adds the code that moves exception handling in text mode to the main
thread even if an exception appears in a non-main thread. This is needed for
various reasons and it is implemented using the asynchronous message handling in
text mode. The basic idea is described in the commit message. And it needs a
patch for python-meh that is being proposed so that we can tell python-meh to
use our raw_input instead of the standard one that doesn't work with threads.
PATCH 2/3 only adds some logging that becomes really handy in case exception
handling doesn't work as expected.
PATCH 3/3 fixes the issue with the rescue mode. It adds some needed pieces to
the RescueInterface, moves the creation of its instance to a better place and
adds a class for exception handling interface correclty shutting down snack
before running the exception handler.
Vratislav Podzimek (3):
Run exception handling in the main thread also in TUI
Add logging to exception handling
Make exception handling in the rescue mode work
anaconda | 8 ++--
pyanaconda/exception.py | 85 ++++++++++++++++++++++++++----------
pyanaconda/rescue.py | 25 +++++++++--
pyanaconda/ui/tui/__init__.py | 27 +++++++++++-
pyanaconda/ui/tui/simpleline/base.py | 36 +++++++++++----
5 files changed, 141 insertions(+), 40 deletions(-)
--
1.7.11.7
11 years, 1 month
[PATCH 1/3] Add execReadlines utility
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
Add a function to read the output from an executable and act on it in
real time. It uses a Thread and a Queue to process the command's stdout
without blocking and yield's the lines back to the caller so that it can
be used like this:
for line in execReadlines("command", [args]):
print line
---
pyanaconda/iutil.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 66 insertions(+), 4 deletions(-)
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 1f75ad9..d2a02e0 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -21,15 +21,15 @@
#
import glob
-import os, string, stat, sys
-import shutil
-import signal
+import os
+import stat
import os.path
import errno
import subprocess
-import threading
import re
import unicodedata
+from threading import Thread
+from Queue import Queue, Empty
from flags import flags
from constants import *
@@ -134,6 +134,68 @@ def execWithCapture(command, argv, stdin=None, stderr=None, root='/',
argv = [command] + argv
return _run_program(argv, stdin=stdin, root=root)[1]
+def execReadlines(command, argv, stdin=None, root='/', env_prune=[]):
+ """ Execute an external command and return the line output of the command
+ in real-time.
+
+ @param command The command to run
+ @param argv The argument list
+ @param stdin The file object to read stdin from.
+ @param stdout Optional file object to redirect stdout and stderr to.
+ @param stderr not used
+ @param root The directory to chroot to before running command.
+ @param env_prune environment variable to remove before execution
+
+ Output from the file is not logged to program.log
+ This returns a generator with the lines from the command until it has finished
+ """
+ if env_prune is None:
+ env_prune = []
+
+ # Return the lines from stdout via a Queue
+ def queue_lines(out, queue):
+ for line in iter(out.readline, b''):
+ queue.put(line.strip())
+ out.close()
+
+ def chroot():
+ if root and root != '/':
+ os.chroot(root)
+
+ argv = [command] + argv
+ with program_log_lock:
+ program_log.info("Running... %s" % " ".join(argv))
+
+ env = augmentEnv()
+ for var in env_prune:
+ env.pop(var, None)
+ try:
+ proc = subprocess.Popen(argv,
+ stdin=stdin,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ bufsize=1,
+ preexec_fn=chroot, cwd=root, env=env)
+ except OSError as e:
+ program_log.error("Error running %s: %s" % (argv[0], e.strerror))
+ raise
+
+ q = Queue()
+ t = Thread(target=queue_lines, args=(proc.stdout, q))
+ t.daemon = True # thread dies with the program
+ t.start()
+
+ while True:
+ try:
+ line = q.get(timeout=.1)
+ yield line
+ q.task_done()
+ except Empty:
+ if proc.poll() is not None:
+ break
+ q.join()
+
+
## Run a shell.
def execConsole():
try:
--
1.8.1.4
11 years, 1 month
[PATCH] Add a factory class for our various communications queues.
by Chris Lumens
There's no good reason to have multiple places where we define message
constants and helper functions, when we could just create a class that does
all the hard work for us.
---
pyanaconda/install.py | 12 +++---
pyanaconda/packaging/livepayload.py | 8 ++--
pyanaconda/packaging/yumpayload.py | 20 +++++-----
pyanaconda/progress.py | 42 +++++---------------
pyanaconda/queue.py | 76 ++++++++++++++++++++++++++++++++++++
pyanaconda/ui/communication.py | 48 ++++-------------------
pyanaconda/ui/gui/hubs/__init__.py | 10 ++---
pyanaconda/ui/gui/hubs/progress.py | 14 +++----
pyanaconda/ui/gui/spokes/custom.py | 4 +-
pyanaconda/ui/gui/spokes/network.py | 4 +-
pyanaconda/ui/gui/spokes/software.py | 29 ++++++--------
pyanaconda/ui/gui/spokes/source.py | 34 +++++++---------
pyanaconda/ui/gui/spokes/storage.py | 23 +++++------
pyanaconda/ui/tui/hubs/progress.py | 12 +++---
pyanaconda/ui/tui/simpleline/base.py | 8 ++--
15 files changed, 177 insertions(+), 167 deletions(-)
create mode 100644 pyanaconda/queue.py
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
index 08b3966..4b4adaf 100644
--- a/pyanaconda/install.py
+++ b/pyanaconda/install.py
@@ -23,7 +23,7 @@
from pyanaconda.constants import ROOT_PATH
from blivet import turnOnFilesystems
from pyanaconda.bootloader import writeBootLoader
-from pyanaconda.progress import progress_report
+from pyanaconda.progress import progress_report, progressQ
from pyanaconda.users import createLuserConf, getPassAlgo, Users
from pyanaconda import flags
from pyanaconda import timezone
@@ -49,10 +49,9 @@ def _writeKS(ksdata):
os.chmod(path, 0600)
def doConfiguration(storage, payload, ksdata, instClass):
- from pyanaconda import progress
from pyanaconda.kickstart import runPostScripts
- progress.send_init(5)
+ progressQ.send_init(5)
# Now run the execute methods of ksdata that require an installed system
# to be present first.
@@ -90,7 +89,7 @@ def doConfiguration(storage, payload, ksdata, instClass):
# kickstart file over if one exists).
_writeKS(ksdata)
- progress.send_complete()
+ progressQ.send_complete()
def doInstall(storage, payload, ksdata, instClass):
"""Perform an installation. This method takes the ksdata as prepared by
@@ -98,7 +97,6 @@ def doInstall(storage, payload, ksdata, instClass):
The two main tasks for this are putting filesystems onto disks and
installing packages onto those filesystems.
"""
- from pyanaconda import progress
from pyanaconda.kickstart import runPostScripts
# First save system time to HW clock.
@@ -110,7 +108,7 @@ def doInstall(storage, payload, ksdata, instClass):
steps = len(storage.devicetree.findActions(type="create", object="format")) + \
len(storage.devicetree.findActions(type="resize", object="format"))
steps += 5 # pre setup phase, packages setup, packages, bootloader, post install
- progress.send_init(steps)
+ progressQ.send_init(steps)
with progress_report(_("Setting up the installation environment")):
ksdata.addons.setup(storage, ksdata, instClass)
@@ -142,4 +140,4 @@ def doInstall(storage, payload, ksdata, instClass):
with progress_report(_("Installing bootloader")):
writeBootLoader(storage, payload, instClass, ksdata)
- progress.send_complete()
+ progressQ.send_complete()
diff --git a/pyanaconda/packaging/livepayload.py b/pyanaconda/packaging/livepayload.py
index 676a18b..1fdfff2 100644
--- a/pyanaconda/packaging/livepayload.py
+++ b/pyanaconda/packaging/livepayload.py
@@ -45,7 +45,7 @@ import logging
log = logging.getLogger("anaconda")
from pyanaconda.errors import *
-from pyanaconda import progress
+from pyanaconda.progress import progressQ
from blivet.size import Size
import blivet.util
from pyanaconda.threads import threadMgr, AnacondaThread
@@ -69,7 +69,7 @@ class LiveImagePayload(ImagePayload):
def preInstall(self, packages=None, groups=None):
""" Perform pre-installation tasks. """
super(LiveImagePayload, self).preInstall(packages=packages, groups=groups)
- progress.send_message(_("Installing software") + (" %d%%") % (0,))
+ progressQ.send_message(_("Installing software") + (" %d%%") % (0,))
def progress(self):
"""Monitor the amount of disk space used on the target and source and
@@ -87,7 +87,7 @@ class LiveImagePayload(ImagePayload):
with self.pct_lock:
self.pct = int(100 * dest_size / source_size)
- progress.send_message(_("Installing software") + (" %d%%") % (min(100,self.pct),))
+ progressQ.send_message(_("Installing software") + (" %d%%") % (min(100,self.pct),))
sleep(0.777)
def install(self):
@@ -127,7 +127,7 @@ class LiveImagePayload(ImagePayload):
def postInstall(self):
""" Perform post-installation tasks. """
- progress.send_message(_("Performing post-installation setup tasks"))
+ progressQ.send_message(_("Performing post-installation setup tasks"))
blivet.util.umount(INSTALL_TREE)
super(LiveImagePayload, self).postInstall()
diff --git a/pyanaconda/packaging/yumpayload.py b/pyanaconda/packaging/yumpayload.py
index 4fc6177..ecd5598 100644
--- a/pyanaconda/packaging/yumpayload.py
+++ b/pyanaconda/packaging/yumpayload.py
@@ -85,7 +85,7 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
from pyanaconda.errors import *
from pyanaconda.packaging import NoSuchGroup, NoSuchPackage
-import pyanaconda.progress as progress
+from pyanaconda.progress import progressQ
from pyanaconda.localization import expand_langs
import itertools
@@ -1261,7 +1261,7 @@ reposdir=%s
# still continue for a bit before the quit message is processed.
# Doing a sys.exit also ensures the running thread quits before
# it can do anything else.
- progress.send_quit(1)
+ progressQ.send_quit(1)
sys.exit(1)
def _applyYumSelections(self):
@@ -1387,7 +1387,7 @@ reposdir=%s
def preInstall(self, packages=None, groups=None):
""" Perform pre-installation tasks. """
super(YumPayload, self).preInstall()
- progress.send_message(_("Starting package installation process"))
+ progressQ.send_message(_("Starting package installation process"))
self._requiredPackages = packages
self._requiredGroups = groups
@@ -1406,7 +1406,7 @@ reposdir=%s
self.checkSoftwareSelection()
except DependencyError as e:
if errorHandler.cb(e) == ERROR_RAISE:
- progress.send_quit(1)
+ progressQ.send_quit(1)
sys.exit(1)
# doPreInstall
@@ -1500,7 +1500,7 @@ reposdir=%s
self._yum.ts.setFlags(rpm.RPMTRANS_FLAG_TEST)
log.info("running transaction")
- progress.send_step()
+ progressQ.send_step()
try:
self._yum.runTransaction(cb=rpmcb)
except PackageSackError as e:
@@ -1512,7 +1512,7 @@ reposdir=%s
log.error("error [2] running transaction: %s" % e)
exn = PayloadInstallError(self._transactionErrors(e.errors))
if errorHandler.cb(exn) == ERROR_RAISE:
- progress.send_quit(1)
+ progressQ.send_quit(1)
sys.exit(1)
except YumBaseError as e:
log.error("error [3] running transaction: %s" % e)
@@ -1523,7 +1523,7 @@ reposdir=%s
raise exn
else:
log.info("transaction complete")
- progress.send_step()
+ progressQ.send_step()
finally:
self._yum.ts.close()
iutil.resetRpmDb()
@@ -1623,7 +1623,7 @@ class RPMCallback(object):
""" Yum install callback. """
if event == rpm.RPMCALLBACK_TRANS_START:
if amount == 6:
- progress.send_message(_("Preparing transaction from installation source"))
+ progressQ.send_message(_("Preparing transaction from installation source"))
self.total_actions = total
self.completed_actions = 0
elif event == rpm.RPMCALLBACK_TRANS_PROGRESS:
@@ -1663,7 +1663,7 @@ class RPMCallback(object):
self.install_log.write(log_msg+"\n")
self.install_log.flush()
- progress.send_message(progress_msg)
+ progressQ.send_message(progress_msg)
self.package_file = None
repo = self._yum.repos.getRepo(txmbr.po.repoid)
@@ -1719,7 +1719,7 @@ class RPMCallback(object):
# take a very long time. So when it closes the last package, just
# display the message.
if self.completed_actions == self.total_actions:
- progress.send_message(_("Performing post-installation setup tasks"))
+ progressQ.send_message(_("Performing post-installation setup tasks"))
elif event == rpm.RPMCALLBACK_UNINST_START:
# update status that we're cleaning up %key
#progress.set_text(_("Cleaning up %s" % key))
diff --git a/pyanaconda/progress.py b/pyanaconda/progress.py
index 433d205..c29b355 100644
--- a/pyanaconda/progress.py
+++ b/pyanaconda/progress.py
@@ -24,6 +24,8 @@ log = logging.getLogger("anaconda")
from contextlib import contextmanager
import Queue
+from pyanaconda.queue import QueueFactory
+
# A queue to be used for communicating progress information between a subthread
# doing all the hard work and the main thread that does the GTK updates. This
# queue should have elements of the following format pushed into it:
@@ -31,44 +33,20 @@ import Queue
# (PROGRESS_CODE_*, [arguments])
#
# Arguments vary based on the code given. See below.
-progressQ = Queue.Queue()
-
-# Arguments:
-#
-# _INIT - [num_steps]
-# _STEP - []
-# _MESSAGE - [string]
-# _COMPLETE - []
-# _QUIT - [exit_code]
-PROGRESS_CODE_INIT = 0
-PROGRESS_CODE_STEP = 1
-PROGRESS_CODE_MESSAGE = 2
-PROGRESS_CODE_COMPLETE = 3
-PROGRESS_CODE_QUIT = 4
-
-# Convenience methods to put things into the queue without the user having to
-# know the details of the queue.
-def send_init(n_steps):
- progressQ.put((PROGRESS_CODE_INIT, [n_steps]))
-
-def send_step():
- progressQ.put((PROGRESS_CODE_STEP, []))
-
-def send_message(message):
- progressQ.put((PROGRESS_CODE_MESSAGE, [message]))
-
-def send_complete():
- progressQ.put((PROGRESS_CODE_COMPLETE, []))
+progressQ = QueueFactory("progress")
-def send_quit(code):
- progressQ.put((PROGRESS_CODE_QUIT, [code]))
+progressQ.addMessage("init", 1) # num_steps
+progressQ.addMessage("step", 0)
+progressQ.addMessage("message", 1) # message
+progressQ.addMessage("complete", 0)
+progressQ.addMessage("quit", 1) # exit_code
# Surround a block of code with progress updating. Before the code runs, the
# message is updated so the user can tell what's about to take so long.
# Afterwards, the progress bar is updated to reflect that the task is done.
@contextmanager
def progress_report(message):
- send_message(message)
+ progressQ.send_message(message)
log.info(message)
yield
- send_step()
+ progressQ.send_step()
diff --git a/pyanaconda/queue.py b/pyanaconda/queue.py
new file mode 100644
index 0000000..67a2aeb
--- /dev/null
+++ b/pyanaconda/queue.py
@@ -0,0 +1,76 @@
+#
+# queue.py: factory for creating communications channels
+#
+# Copyright (C) 2013 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Chris Lumens <clumens(a)redhat.com>
+
+import Queue
+
+class QueueFactory(object):
+ """Constructs a new object wrapping a Queue.Queue, complete with constants
+ and sending functions for each type of message that can be put into the
+ queue.
+
+ Creating a new object using this class is done like so:
+
+ q = QueueFactory("progress")
+
+ And then adding messages to it is done like so:
+
+ q.addMessage("init", 0)
+ q.addMessage("step", 1)
+
+ The first call will create a new constant named PROGRESS_CODE_INIT and a
+ method named send_init that takes zero arguments. The second call will
+ create a new constant named PROGRESS_CODE_STEP and a method named send_step
+ that takes one argument.
+
+ Reusing names within the same class is not allowed.
+ """
+ def __init__(self, name):
+ self.name = name
+
+ self.__counter = 0
+ self.__names = []
+
+ self.q = Queue.Queue()
+
+ def _makeMethod(self, constant, methodName, argc):
+ def __method(*args):
+ if len(args) != argc:
+ raise TypeError("%s() takes exactly %d arguments (%d given)" % (methodName, argc, len(args)))
+
+ self._q.put((constant, args))
+
+ __method.__name__ = methodName
+ return __method
+
+ def addMessage(self, name, argc):
+ if name in self.__names:
+ raise AttributeError("%s queue already has a message named %s" % (self.name, name))
+
+ # Add a constant.
+ const_name = self.name.upper() + "_CODE_" + name.upper()
+ setattr(self, const_name, self.__counter)
+ self.__counter += 1
+
+ # Add a convenience method for putting things into the queue.
+ method_name = "send_" + name.lower()
+ method = self._makeMethod(getattr(self, const_name), method_name, argc)
+ setattr(self, method_name, method)
+
+ self.__names.append(name)
diff --git a/pyanaconda/ui/communication.py b/pyanaconda/ui/communication.py
index 6c4565b..655a54e 100644
--- a/pyanaconda/ui/communication.py
+++ b/pyanaconda/ui/communication.py
@@ -20,6 +20,8 @@
import Queue
+from pyanaconda.queue import QueueFactory
+
# A queue to be used for communicating information from a spoke back to its
# hub. This information includes things like marking spokes as ready and
# updating the status line to tell the user why a spoke is not yet available.
@@ -30,44 +32,10 @@ import Queue
# Arguments vary based on the code given, but the first argument must always
# be the name of the class of the spoke to be acted upon. See below for more
# details.
-hubQ = Queue.Queue()
-
-# Arguments:
-#
-# _READY - [spoke_name, justUpdate]
-# _NOT_READY - [spoke_name]
-# _MESSAGE - [spoke_name, string]
-# _INPUT - [string]
-# _EXCEPTION - [exc]
-HUB_CODE_READY = 0
-HUB_CODE_NOT_READY = 1
-HUB_CODE_MESSAGE = 2
-HUB_CODE_INPUT = 3
-HUB_CODE_EXCEPTION = 4
-
-# Convenience methods to put things into the queue without the user having to
-# know the details of the queue.
-def send_ready(spoke, justUpdate=False):
- """Tell the hub that a spoke given by the name "spoke" has become ready,
- and that it should be made sensitive on the hub. Some processing may
- also occur after a spoke has become ready. However, if the justUpdate
- parameter is True, no processing will occur.
- """
- hubQ.put((HUB_CODE_READY, [spoke, justUpdate]))
-
-def send_not_ready(spoke):
- hubQ.put((HUB_CODE_NOT_READY, [spoke]))
-
-def send_message(spoke, msg):
- hubQ.put((HUB_CODE_MESSAGE, [spoke, msg]))
-
-def send_input(data):
- """This message represents an async input string from the user."""
- hubQ.put((HUB_CODE_INPUT, [data]))
+hubQ = QueueFactory("hub")
-def send_exception(exception):
- """This message contains the exception which happened somewhere,
- usually used to report thread failures to the main thread so
- python-meh can handle it properly.
- """
- hubQ.put((HUB_CODE_EXCEPTION, [exception]))
+hubQ.addMessage("ready", 2) # spoke_name, justUpdate
+hubQ.addMessage("not_ready", 1) # spoke_name
+hubQ.addMessage("message", 2) # spoke_name, string
+hubQ.addMessage("input", 1) # string
+hubQ.addMessage("exception", 1) # exception
diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
index 75e0309..446f168 100644
--- a/pyanaconda/ui/gui/hubs/__init__.py
+++ b/pyanaconda/ui/gui/hubs/__init__.py
@@ -282,10 +282,10 @@ class Hub(GUIObject, common.Hub):
self.continueButton.set_sensitive(self.continuePossible)
def _update_spokes(self):
- from pyanaconda.ui import communication
+ from pyanaconda.ui.communication import hubQ
import Queue
- q = communication.hubQ
+ q = hubQ.q
# Grab all messages that may have appeared since last time this method ran.
while True:
@@ -301,7 +301,7 @@ class Hub(GUIObject, common.Hub):
q.task_done()
continue
- if code == communication.HUB_CODE_NOT_READY:
+ if code == hubQ.HUB_CODE_NOT_READY:
self._updateCompleteness(spoke)
if spoke not in self._notReadySpokes:
@@ -309,7 +309,7 @@ class Hub(GUIObject, common.Hub):
self._updateContinueButton()
log.info("spoke is not ready: %s" % spoke)
- elif code == communication.HUB_CODE_READY:
+ elif code == hubQ.HUB_CODE_READY:
self._updateCompleteness(spoke)
if spoke in self._notReadySpokes:
@@ -336,7 +336,7 @@ class Hub(GUIObject, common.Hub):
elif self._autoContinue and q.empty():
# enqueue the emit to the Gtk message queue
gtk_call_once(self.continueButton.emit, "clicked")
- elif code == communication.HUB_CODE_MESSAGE:
+ elif code == hubQ.HUB_CODE_MESSAGE:
spoke.selector.set_property("status", args[1])
log.info("setting %s status to: %s" % (spoke, args[1]))
diff --git a/pyanaconda/ui/gui/hubs/progress.py b/pyanaconda/ui/gui/hubs/progress.py
index a1da2fd..3cf2a44 100644
--- a/pyanaconda/ui/gui/hubs/progress.py
+++ b/pyanaconda/ui/gui/hubs/progress.py
@@ -78,10 +78,10 @@ class ProgressHub(Hub):
self._rnotes_id = GLib.timeout_add_seconds(60, self._cycle_rnotes)
def _update_progress(self, callback = None):
- from pyanaconda import progress
+ from pyanaconda.progress import progressQ
import Queue
- q = progress.progressQ
+ q = progressQ.q
# Grab all messages may have appeared since last time this method ran.
while True:
@@ -92,13 +92,13 @@ class ProgressHub(Hub):
except Queue.Empty:
break
- if code == progress.PROGRESS_CODE_INIT:
+ if code == progressQ.PROGRESS_CODE_INIT:
self._init_progress_bar(args[0])
- elif code == progress.PROGRESS_CODE_STEP:
+ elif code == progressQ.PROGRESS_CODE_STEP:
self._step_progress_bar()
- elif code == progress.PROGRESS_CODE_MESSAGE:
+ elif code == progressQ.PROGRESS_CODE_MESSAGE:
self._update_progress_message(args[0])
- elif code == progress.PROGRESS_CODE_COMPLETE:
+ elif code == progressQ.PROGRESS_CODE_COMPLETE:
# There shouldn't be any more progress bar updates, so return False
# to indicate this method should be removed from the idle loop. Also,
# stop the rnotes cycling and display the finished message.
@@ -109,7 +109,7 @@ class ProgressHub(Hub):
callback()
return False
- elif code == progress.PROGRESS_CODE_QUIT:
+ elif code == progressQ.PROGRESS_CODE_QUIT:
sys.exit(args[0])
q.task_done()
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index a8fda8c..d41a232 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -71,7 +71,7 @@ from blivet.errors import MDRaidError
from blivet.devicelibs import mdraid
from blivet.devices import LUKSDevice
-from pyanaconda.ui import communication
+from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.gui import GUIObject
from pyanaconda.ui.gui.spokes import NormalSpoke
from pyanaconda.ui.gui.spokes.storage import StorageChecker
@@ -482,7 +482,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
StorageChecker.errors = []
StorageChecker.run(self)
- communication.send_ready("StorageSpoke", justUpdate=True)
+ hubQ.send_ready("StorageSpoke", True)
@property
def indirect(self):
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index ec5e076..2133915 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -35,7 +35,7 @@ from gi.repository import Gtk, AnacondaWidgets
from pyanaconda.flags import flags
from pyanaconda import constants
-from pyanaconda.ui import communication
+from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.gui import GUIObject
from pyanaconda.ui.gui.spokes import NormalSpoke, StandaloneSpoke
from pyanaconda.ui.gui.categories.software import SoftwareCategory
@@ -1204,7 +1204,7 @@ class NetworkSpoke(NormalSpoke):
gtk_call_once(self._update_status)
def _update_status(self):
- communication.send_message(self.__class__.__name__, self.status)
+ hubQ.send_message(self.__class__.__name__, self.status)
def _update_hostname(self):
if self.network_control_box.hostname == network.DEFAULT_HOSTNAME:
diff --git a/pyanaconda/ui/gui/spokes/software.py b/pyanaconda/ui/gui/spokes/software.py
index 5c51301..e9cf708 100644
--- a/pyanaconda/ui/gui/spokes/software.py
+++ b/pyanaconda/ui/gui/spokes/software.py
@@ -28,7 +28,7 @@ from pyanaconda.packaging import MetadataError
from pyanaconda.threads import threadMgr, AnacondaThread
from pyanaconda import constants
-from pyanaconda.ui import communication
+from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.gui.spokes import NormalSpoke
from pyanaconda.ui.gui.spokes.lib.detailederror import DetailedErrorDialog
from pyanaconda.ui.gui.utils import enlightbox, gtk_action_wait
@@ -87,8 +87,8 @@ class SoftwareSelectionSpoke(NormalSpoke):
self._origAddons = addons
self._origEnvironment = self.environment
- communication.send_not_ready(self.__class__.__name__)
- communication.send_not_ready("SourceSpoke")
+ hubQ.send_not_ready(self.__class__.__name__)
+ hubQ.send_not_ready("SourceSpoke")
threadMgr.add(AnacondaThread(name=constants.THREAD_CHECK_SOFTWARE,
target=self.checkSoftwareSelection))
@@ -98,21 +98,19 @@ class SoftwareSelectionSpoke(NormalSpoke):
def checkSoftwareSelection(self):
from pyanaconda.packaging import DependencyError
- communication.send_message(self.__class__.__name__,
- _("Checking software dependencies..."))
+ hubQ.send_message(self.__class__.__name__, _("Checking software dependencies..."))
try:
self.payload.checkSoftwareSelection()
except DependencyError as e:
self._errorMsgs = "\n".join(sorted(e.message))
- communication.send_message(self.__class__.__name__,
- _("Error checking software dependencies"))
+ hubQ.send_message(self.__class__.__name__, _("Error checking software dependencies"))
self._tx_id = None
else:
self._errorMsgs = None
self._tx_id = self.payload.txID
finally:
- communication.send_ready(self.__class__.__name__)
- communication.send_ready("SourceSpoke")
+ hubQ.send_ready(self.__class__.__name__, False)
+ hubQ.send_ready("SourceSpoke", False)
@property
def completed(self):
@@ -173,11 +171,11 @@ class SoftwareSelectionSpoke(NormalSpoke):
target=self._initialize))
def _initialize(self):
- communication.send_message(self.__class__.__name__, _("Downloading package metadata..."))
+ hubQ.send_message(self.__class__.__name__, _("Downloading package metadata..."))
threadMgr.wait(constants.THREAD_PAYLOAD)
- communication.send_message(self.__class__.__name__, _("Downloading group metadata..."))
+ hubQ.send_message(self.__class__.__name__, _("Downloading group metadata..."))
# we have no way to select environments with kickstart right now
# so don't try.
@@ -193,8 +191,8 @@ class SoftwareSelectionSpoke(NormalSpoke):
self.payload.environments
self.payload.groups
except MetadataError:
- communication.send_message(self.__class__.__name__,
- _("No installation source available"))
+ hubQ.send_message(self.__class__.__name__,
+ _("No installation source available"))
return
# And then having done all that slow downloading, we need to do the first
@@ -206,7 +204,7 @@ class SoftwareSelectionSpoke(NormalSpoke):
self.payload.release()
- communication.send_ready(self.__class__.__name__)
+ hubQ.send_ready(self.__class__.__name__, False)
# If packages were provided by an input kickstart file (or some other means),
# we should do dependency solving here.
@@ -218,8 +216,7 @@ class SoftwareSelectionSpoke(NormalSpoke):
self.refresh()
return True
except MetadataError:
- communication.send_message(self.__class__.__name__,
- _("No installation source available"))
+ hubQ.send_message(self.__class__.__name__, _("No installation source available"))
return False
def refresh(self):
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 71f47e0..f7a2103 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -34,7 +34,7 @@ from gi.repository import AnacondaWidgets, GLib, Gtk
from pyanaconda.flags import flags
from pyanaconda.image import opticalInstallMedia, potentialHdisoSources
-from pyanaconda.ui import communication
+from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.gui import GUIObject
from pyanaconda.ui.gui.spokes import NormalSpoke
from pyanaconda.ui.gui.categories.software import SoftwareCategory
@@ -405,10 +405,9 @@ class SourceSpoke(NormalSpoke):
return True
def getRepoMetadata(self):
- communication.send_not_ready("SoftwareSelectionSpoke")
- communication.send_not_ready(self.__class__.__name__)
- communication.send_message(self.__class__.__name__,
- _(BASEREPO_SETUP_MESSAGE))
+ hubQ.send_not_ready("SoftwareSelectionSpoke")
+ hubQ.send_not_ready(self.__class__.__name__)
+ hubQ.send_message(self.__class__.__name__, _(BASEREPO_SETUP_MESSAGE))
# this sleep is lame, but without it the message above doesn't seem
# to get processed by the hub in time, and is never shown.
# FIXME this should get removed when we figure out how to ensure
@@ -420,22 +419,19 @@ class SourceSpoke(NormalSpoke):
except PayloadError as e:
log.error("PayloadError: %s" % (e,))
self._error = True
- communication.send_message(self.__class__.__name__,
- _("Failed to set up installation source"))
+ hubQ.send_message(self.__class__.__name__, _("Failed to set up installation source"))
if not self.data.method.proxy:
gtk_call_once(self.set_warning, _("Failed to set up installation source; check the repo url"))
else:
gtk_call_once(self.set_warning, _("Failed to set up installation source; check the repo url and proxy settings"))
else:
self._error = False
- communication.send_message(self.__class__.__name__,
- _(METADATA_DOWNLOAD_MESSAGE))
+ hubQ.send_message(self.__class__.__name__, _(METADATA_DOWNLOAD_MESSAGE))
self.payload.gatherRepoMetadata()
self.payload.release()
if not self.payload.baseRepo:
- communication.send_message(self.__class__.__name__,
- _(METADATA_ERROR_MESSAGE))
- communication.send_ready(self.__class__.__name__)
+ hubQ.send_message(self.__class__.__name__, _(METADATA_ERROR_MESSAGE))
+ hubQ.send_ready(self.__class__.__name__, False)
self._error = True
gtk_call_once(self.set_warning, _("Failed to set up installation source; check the repo url"))
else:
@@ -448,12 +444,12 @@ class SourceSpoke(NormalSpoke):
e = self.payload.environments
g = self.payload.groups
except MetadataError:
- communication.send_message("SoftwareSelectionSpoke",
- _("No installation source available"))
+ hubQ.send_message("SoftwareSelectionSpoke",
+ _("No installation source available"))
else:
- communication.send_ready("SoftwareSelectionSpoke")
+ hubQ.send_ready("SoftwareSelectionSpoke", False)
finally:
- communication.send_ready(self.__class__.__name__)
+ hubQ.send_ready(self.__class__.__name__, False)
@property
def completed(self):
@@ -549,11 +545,11 @@ class SourceSpoke(NormalSpoke):
def _initialize(self):
from pyanaconda.threads import threadMgr
- communication.send_message(self.__class__.__name__, _("Probing storage..."))
+ hubQ.send_message(self.__class__.__name__, _("Probing storage..."))
threadMgr.wait(constants.THREAD_STORAGE)
- communication.send_message(self.__class__.__name__, _(METADATA_DOWNLOAD_MESSAGE))
+ hubQ.send_message(self.__class__.__name__, _(METADATA_DOWNLOAD_MESSAGE))
threadMgr.wait(constants.THREAD_PAYLOAD)
@@ -592,7 +588,7 @@ class SourceSpoke(NormalSpoke):
# FIXME
self._ready = True
- communication.send_ready(self.__class__.__name__)
+ hubQ.send_ready(self.__class__.__name__, False)
def refresh(self):
NormalSpoke.refresh(self)
diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py
index fac660a..22cab62 100644
--- a/pyanaconda/ui/gui/spokes/storage.py
+++ b/pyanaconda/ui/gui/spokes/storage.py
@@ -40,7 +40,7 @@
from gi.repository import Gdk, GLib, Gtk
from gi.repository import AnacondaWidgets
-from pyanaconda.ui import communication
+from pyanaconda.ui.communication import hubQ
from pyanaconda.ui.lib.disks import getDisks, isLocalDisk, size_str
from pyanaconda.ui.gui import GUIObject
from pyanaconda.ui.gui.spokes import NormalSpoke
@@ -287,16 +287,15 @@ class StorageChecker(object):
_mainSpokeClass = "StorageSpoke"
def run(self):
- communication.send_not_ready(self._mainSpokeClass)
+ hubQ.send_not_ready(self._mainSpokeClass)
threadMgr.add(AnacondaThread(name=constants.THREAD_CHECK_STORAGE,
target=self.checkStorage))
def checkStorage(self):
- communication.send_message(self._mainSpokeClass,
- _("Checking storage configuration..."))
+ hubQ.send_message(self._mainSpokeClass, _("Checking storage configuration..."))
(StorageChecker.errors,
StorageChecker.warnings) = self.storage.sanityCheck()
- communication.send_ready(self._mainSpokeClass, justUpdate=True)
+ hubQ.send_ready(self._mainSpokeClass, True)
for e in StorageChecker.errors:
log.error(e)
for w in StorageChecker.warnings:
@@ -381,16 +380,14 @@ class StorageSpoke(NormalSpoke, StorageChecker):
def _doExecute(self):
self._ready = False
- communication.send_not_ready(self.__class__.__name__)
- communication.send_message(self.__class__.__name__,
- _("Saving storage configuration..."))
+ hubQ.send_not_ready(self.__class__.__name__)
+ hubQ.send_message(self.__class__.__name__, _("Saving storage configuration..."))
try:
doKickstartStorage(self.storage, self.data, self.instclass)
except StorageError as e:
log.error("storage configuration failed: %s" % e)
StorageChecker.errors = str(e).split("\n")
- communication.send_message(self.__class__.__name__,
- _("Failed to save storage configuration..."))
+ hubQ.send_message(self.__class__.__name__, _("Failed to save storage configuration..."))
self.data.ignoredisk.drives = []
self.data.ignoredisk.onlyuse = []
self.storage.config.update(self.data)
@@ -406,7 +403,7 @@ class StorageSpoke(NormalSpoke, StorageChecker):
self.run()
finally:
self._ready = True
- communication.send_ready(self.__class__.__name__, justUpdate=True)
+ hubQ.send_ready(self.__class__.__name__, False)
@property
def completed(self):
@@ -586,7 +583,7 @@ class StorageSpoke(NormalSpoke, StorageChecker):
self._update_summary()
def _initialize(self):
- communication.send_message(self.__class__.__name__, _("Probing storage..."))
+ hubQ.send_message(self.__class__.__name__, _("Probing storage..."))
threadMgr.wait(constants.THREAD_STORAGE)
threadMgr.wait(constants.THREAD_CUSTOM_STORAGE_INIT)
@@ -603,7 +600,7 @@ class StorageSpoke(NormalSpoke, StorageChecker):
self._add_disk_overview(disk, self.local_disks_box)
self._ready = True
- communication.send_ready(self.__class__.__name__)
+ hubQ.send_ready(self.__class__.__name__, False)
def _update_summary(self):
""" Update the summary based on the UI. """
diff --git a/pyanaconda/ui/tui/hubs/progress.py b/pyanaconda/ui/tui/hubs/progress.py
index 3e22619..a7d8c1b 100644
--- a/pyanaconda/ui/tui/hubs/progress.py
+++ b/pyanaconda/ui/tui/hubs/progress.py
@@ -44,10 +44,10 @@ class ProgressHub(TUIHub):
def _update_progress(self):
"""Handle progress updates from install thread."""
- from pyanaconda import progress
+ from pyanaconda.progress import progressQ
import Queue
- q = progress.progressQ
+ q = progressQ.q
# Grab all messages may have appeared since last time this method ran.
while True:
@@ -65,10 +65,10 @@ class ProgressHub(TUIHub):
finally:
self.app.process_events()
- if code == progress.PROGRESS_CODE_INIT:
+ if code == progressQ.PROGRESS_CODE_INIT:
# Text mode doesn't have a finite progress bar
pass
- elif code == progress.PROGRESS_CODE_STEP:
+ elif code == progressQ.PROGRESS_CODE_STEP:
# Instead of updating a progress bar, we just print a pip
# but print it without a new line.
sys.stdout.write('.')
@@ -76,14 +76,14 @@ class ProgressHub(TUIHub):
# Use _stepped as an indication to if we need a newline before
# the next message
self._stepped = True
- elif code == progress.PROGRESS_CODE_MESSAGE:
+ elif code == progressQ.PROGRESS_CODE_MESSAGE:
# This should already be translated
if self._stepped:
# Get a new line in case we've done a step before
self._stepped = False
print('')
print(args[0])
- elif code == progress.PROGRESS_CODE_COMPLETE:
+ elif code == progressQ.PROGRESS_CODE_COMPLETE:
# There shouldn't be any more progress updates, so return
q.task_done()
diff --git a/pyanaconda/ui/tui/simpleline/base.py b/pyanaconda/ui/tui/simpleline/base.py
index a8e588e..7faa8a4 100644
--- a/pyanaconda/ui/tui/simpleline/base.py
+++ b/pyanaconda/ui/tui/simpleline/base.py
@@ -25,7 +25,7 @@ import readline
import Queue
import getpass
from pyanaconda.threads import threadMgr, AnacondaThread
-from pyanaconda.ui.communication import HUB_CODE_EXCEPTION, HUB_CODE_INPUT
+from pyanaconda.ui.communication import hubQ
from pyanaconda import constants
import gettext
@@ -33,7 +33,7 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
N_ = lambda x: x
def send_exception(queue, ex):
- queue.put((HUB_CODE_EXCEPTION, [ex]))
+ queue.put((hubQ.HUB_CODE_EXCEPTION, [ex]))
class ExitMainLoop(Exception):
@@ -148,7 +148,7 @@ class App(object):
else:
data = raw_input(prompt)
- queue.put((HUB_CODE_INPUT, [data]))
+ queue.put((hubQ.HUB_CODE_INPUT, [data]))
def switch_screen(self, ui, args = None):
"""Schedules a screen to replace the current one.
@@ -401,7 +401,7 @@ class App(object):
args=(self.queue, prompt, hidden))
input_thread.daemon = True
threadMgr.add(input_thread)
- event = self.process_events(return_at=HUB_CODE_INPUT)
+ event = self.process_events(return_at=hubQ.HUB_CODE_INPUT)
return event[1][0] # return the user input
def input(self, args, key):
--
1.8.1.2
11 years, 1 month
[PATCH] fix version query and add one to the log file
by Mark Hamzy
Fix "lorax -V" and add a "version is ???" to the log file so we can easily know
what version of lorax is used to build an iso.
---
src/pylorax/__init__.py | 4 ++++
src/pylorax/buildstamp.py | 8 +-------
src/sbin/lorax | 12 +++++++-----
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/pylorax/__init__.py b/src/pylorax/__init__.py
index 069628e..295ae53 100644
--- a/src/pylorax/__init__.py
+++ b/src/pylorax/__init__.py
@@ -142,6 +142,8 @@ class Lorax(BaseLoraxClass):
assert self._configured
+ from pylorax.version import num as vernum
+
if domacboot:
try:
runcmd(["rpm", "-q", "hfsplus-tools"])
@@ -161,6 +163,8 @@ class Lorax(BaseLoraxClass):
self.init_stream_logging()
self.init_file_logging(logdir)
+
+ logger.debug("version is {0}".format (vernum))
logger.debug("using work directory {0.workdir}".format(self))
logger.debug("using log directory {0}".format(logdir))
diff --git a/src/pylorax/buildstamp.py b/src/pylorax/buildstamp.py
index 6953a6c..fbc7ff9 100644
--- a/src/pylorax/buildstamp.py
+++ b/src/pylorax/buildstamp.py
@@ -38,13 +38,7 @@ class BuildStamp(object):
self.uuid = "{0}.{1}".format(now, buildarch)
def write(self, outfile):
- # get lorax version
- try:
- import pylorax.version
- except ImportError:
- vernum = "devel"
- else:
- vernum = pylorax.version.num
+ from pylorax.version import num as vernum
logger.info("writing .buildstamp file")
with open(outfile, "w") as fobj:
diff --git a/src/sbin/lorax b/src/sbin/lorax
index d831b97..61b518f 100755
--- a/src/sbin/lorax
+++ b/src/sbin/lorax
@@ -76,7 +76,9 @@ def setup_logging(opts):
def main(args):
- version = "{0} 0.1".format(os.path.basename(args[0]))
+ from pylorax.version import num as vernum
+
+ version = "{0}-{1}".format(os.path.basename(args[0]), vernum)
usage = "%prog -p PRODUCT -v VERSION -r RELEASE -s REPOSITORY OUTPUTDIR"
parser = OptionParser(usage=usage)
@@ -136,15 +138,15 @@ def main(args):
# parse the arguments
opts, args = parser.parse_args()
+ if opts.showver:
+ print(version)
+ sys.exit(0)
+
try:
outputdir = os.path.abspath(args[0])
except IndexError:
parser.error("missing one or more required arguments")
- if opts.showver:
- print(version)
- sys.exit(0)
-
# check for the required arguments
if not opts.product or not opts.version or not opts.release \
or not opts.source or not outputdir:
--
1.8.1.4
11 years, 1 month
[PATCH 1/3] Move custom storage setup into its own thread.
by Chris Lumens
Instantiating all those device formats can result in lengthy processes like
loading kernel modules, some of which are very large. This results in lag
between when the user leaves the welcome spoke and the hub being displayed.
In my thoroughly unscientific testing on one computer, this knocks about two
seconds off the amount of time between the welcome screen and the hub.
---
pyanaconda/ui/gui/spokes/custom.py | 18 +++++++++++++-----
pyanaconda/ui/gui/spokes/storage.py | 1 +
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index b20f3eb..368b742 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -45,7 +45,7 @@ import re
from pykickstart.constants import *
from pyanaconda.product import productName, productVersion
-from pyanaconda.threads import threadMgr
+from pyanaconda.threads import AnacondaThread, threadMgr
from blivet import devicefactory
from blivet.formats import device_formats
@@ -79,7 +79,7 @@ from pyanaconda.ui.gui.spokes.lib.passphrase import PassphraseDialog
from pyanaconda.ui.gui.spokes.lib.accordion import *
from pyanaconda.ui.gui.spokes.lib.refresh import RefreshDialog
from pyanaconda.ui.gui.spokes.lib.summary import ActionSummaryDialog
-from pyanaconda.ui.gui.utils import setViewportBackground
+from pyanaconda.ui.gui.utils import setViewportBackground, gtk_thread_wait
from pyanaconda.ui.gui.categories.storage import StorageCategory
from gi.repository import Gtk
@@ -518,8 +518,16 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
# Populate the list of valid filesystem types from the format classes.
# Unfortunately, we have to narrow them down a little bit more because
# this list will include things like PVs and RAID members.
- fsCombo = self.builder.get_object("fileSystemTypeCombo")
- fsCombo.remove_all()
+ self.fsCombo = self.builder.get_object("fileSystemTypeCombo")
+ self.fsCombo.remove_all()
+
+ threadMgr.add(AnacondaThread(name="AnaCustomStorageInit", target=self._initialize))
+
+ def _initialize(self):
+ @gtk_thread_wait
+ def gtk_action(name):
+ self.fsCombo.append_text(name)
+
self._fs_types = []
for cls in device_formats.itervalues():
obj = cls()
@@ -530,7 +538,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
(isinstance(obj, FS) or
obj.type in ["biosboot", "prepboot", "swap"]))
if supported_fs:
- fsCombo.append_text(obj.name)
+ gtk_action(obj.name)
self._fs_types.append(obj.name)
@property
diff --git a/pyanaconda/ui/gui/spokes/storage.py b/pyanaconda/ui/gui/spokes/storage.py
index 1b474f0..17bfbeb 100644
--- a/pyanaconda/ui/gui/spokes/storage.py
+++ b/pyanaconda/ui/gui/spokes/storage.py
@@ -561,6 +561,7 @@ class StorageSpoke(NormalSpoke, StorageChecker):
communication.send_message(self.__class__.__name__, _("Probing storage..."))
threadMgr.wait("AnaStorageThread")
+ threadMgr.wait("AnaCustomStorageInit")
self.disks = getDisks(self.storage.devicetree)
--
1.8.1.2
11 years, 1 month
[PATCH] Move addon infrastructure to pykickstart
by Martin Sivak
---
anaconda.spec.in | 2 +-
pyanaconda/addons.py | 120 ------------------------------------------------
pyanaconda/kickstart.py | 32 ++-----------
3 files changed, 5 insertions(+), 149 deletions(-)
diff --git a/anaconda.spec.in b/anaconda.spec.in
index 6e4bb25..e4f7e15 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -21,7 +21,7 @@ Source0: %{name}-%{version}.tar.bz2
%define gconfversion 2.28.1
%define intltoolver 0.31.2-3
%define libnlver 1.0
-%define pykickstartver 1.99.26
+%define pykickstartver 1.99.27
%define yumver 3.4.3-32
%define partedver 1.8.1
%define pypartedver 2.5-2
diff --git a/pyanaconda/addons.py b/pyanaconda/addons.py
index 96eb813..2568d7b 100644
--- a/pyanaconda/addons.py
+++ b/pyanaconda/addons.py
@@ -18,12 +18,7 @@
#
# Red Hat Author(s): Martin Sivak <msivak(a)redhat.com>
#
-
-__all__ = ["AddonSection", "AddonRegistry", "AddonData", "collect_addon_paths"]
-
import os
-from pykickstart.sections import Section
-from pykickstart.options import KSOptionParser
def collect_addon_paths(toplevel_addon_paths, ui_subdir="gui"):
"""This method looks into the directories present
@@ -61,118 +56,3 @@ def collect_addon_paths(toplevel_addon_paths, ui_subdir="gui"):
module_paths["categories"].append(("%s.%s.categories.%%s" % (addon_id, ui_subdir), addon_category_path))
return module_paths
-
-class AddonRegistry(object):
- """This class represents the ksdata.addons object and
- maintains the ids and data structures for loaded
- addons.
-
- It acts as a proxy during kickstart save.
- """
-
- def __init__(self, dictionary):
- self.__dict__ = dictionary
-
- def __str__(self):
- return reduce(lambda acc,(id, addon): acc + str(addon),
- self.__dict__.iteritems(), "")
-
- # pylint: disable-msg=C0103
- def execute(self, storage, ksdata, instClass, users):
- """This method calls execute on all the registered addons."""
- for k, v in self.__dict__.iteritems():
- if hasattr(v, "execute"):
- v.execute(storage, ksdata, instClass, users)
-
- def setup(self, storage, ksdata, instClass):
- """This method calls setup on all the registered addons."""
- for k, v in self.__dict__.iteritems():
- if hasattr(v, "setup"):
- v.setup(storage, ksdata, instClass)
-
-
-class AddonData(object):
- """This is a common parent class for loading and storing
- 3rd party data to kickstart. It is instantiated by
- kickstart parser and stored as ksdata.addons.<name>
- to be used in the user interfaces.
-
- The mandatory method handle_line receives all lines
- from the corresponding addon section in kickstart and
- the mandatory __str__ implementation is responsible for
- returning the proper kickstart text (to be placed into
- the %addon section) back.
-
- There is also a mandatory method execute, which should
- make all the described changes to the installed system.
- """
-
- def __init__(self, name):
- self.name = name
- self.content = ""
-
- def __str__(self):
- return "%%addon %s\n%s%%end\n" % (self.name, self.content)
-
- # pylint: disable-msg=C0103
- def setup(self, storage, ksdata, instClass):
- """Make the changes to the install system.
-
- This method is called before the installation
- is started and directly from spokes. It must be possible
- to call it multiple times without breaking the environment."""
- pass
-
- def execute(self, storage, ksdata, instClass, users):
- """Make the changes to the underlying system.
-
- This method is called only once in the post-install
- setup phase.
- """
- pass
-
- def handle_line(self, line):
- """Process one kickstart line."""
- self.content += line
-
- def finalize(self):
- """No additional data will come.
-
- Addon should check if all mandatory attributes were populated.
- """
- pass
-
-class AddonSection(Section):
- sectionOpen = "%addon"
-
- def __init__(self, *args, **kwargs):
- Section.__init__(self, *args, **kwargs)
- self.addon_id = None
-
- def handleLine(self, line):
- if not self.handler:
- return
-
- if not self.addon_id:
- return
-
- addon = getattr(self.handler.addons, self.addon_id)
- addon.handle_line(line)
-
- def handleHeader(self, lineno, args):
- """Process the arguments to the %addon header."""
- Section.handleHeader(self, lineno, args)
- op = KSOptionParser(version=self.version)
- (_opts, extra) = op.parse_args(args=args[1:], lineno=lineno)
- self.addon_id = extra[0]
-
- # if the addon is not registered, create dummy placeholder for it
- if self.addon_id and not hasattr(self.handler.addons, self.addon_id):
- setattr(self.handler.addons, self.addon_id, AddonData(self.addon_id))
-
- def finalize(self):
- """Let addon know no additional data will come."""
- Section.finalize()
-
- addon = getattr(self.handler.addons, self.addon_id)
- addon.finalize()
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 9060c58..b685bf6 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -56,7 +56,8 @@ from pyanaconda.simpleconfig import SimpleConfigFile
from pyanaconda.users import getPassAlgo
from pyanaconda.desktop import Desktop
from .ui.common import collect
-from .addons import AddonSection, AddonData, AddonRegistry, collect_addon_paths
+from .addons import collect_addon_paths
+from pykickstart.addons import AddonSection
from pykickstart.base import KickstartCommand
from pykickstart.constants import *
@@ -1422,35 +1423,10 @@ dataMap = {
superclass = returnClassForVersion()
class AnacondaKSHandler(superclass):
- AddonClassType = AddonData
-
- def __init__ (self, addon_paths = [], commandUpdates=commandMap, dataUpdates=dataMap):
- superclass.__init__(self, commandUpdates=commandUpdates, dataUpdates=dataUpdates)
+ def __init__ (self, addonPaths = [], commandUpdates=commandMap, dataUpdates=dataMap):
+ superclass.__init__(self, addonPaths = addonPaths, commandUpdates=commandUpdates, dataUpdates=dataUpdates)
self.onPart = {}
- # collect all kickstart addons for anaconda to addons dictionary
- # which maps addon_id to it's own data structure based on BaseData
- # with execute method
- addons = {}
-
- # collect all AddonData subclasses from
- # for p in addon_paths: <p>/<plugin id>/ks/*.(py|so)
- # and register them under <plugin id> name
- for module_name, path in addon_paths:
- addon_id = os.path.basename(os.path.dirname(os.path.abspath(path)))
- if not os.path.isdir(path):
- continue
-
- classes = collect(module_name, path, lambda cls: issubclass(cls, self.AddonClassType))
- if classes:
- addons[addon_id] = classes[0](name = addon_id)
-
- # Prepare the structure to track configured spokes
- self.configured_spokes = SpokeRegistry()
-
- # Prepare the final structures for 3rd party addons
- self.addons = AddonRegistry(addons)
-
def __str__(self):
return superclass.__str__(self) + "\n" + str(self.addons)
--
1.7.11.7
11 years, 1 month
[python-meh] [trivial PATCH] Tell ABRT we are reporting a Python excetion
by Vratislav Podzimek
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
meh/handler.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/meh/handler.py b/meh/handler.py
index 6427656..20f5bad 100644
--- a/meh/handler.py
+++ b/meh/handler.py
@@ -239,6 +239,9 @@ class ExceptionHandler(object):
#skip files we cannot read
continue
+ # tell ABRT this is a Python exception report
+ params["analyzer"] = "Python"
+
signature = report.createPythonUnhandledExceptionSignature(**params)
# We don't want to automatically quit here since the user may wish to
--
1.7.11.7
11 years, 1 month