[PATCH rhel7-branch] Don't traceback if connection does not have read-only setting (#1158919)
by Radek Vykydal
Resolves: rhbz#1158919
caused by commit 7a9a7de0d6da52d504c70b012cfbe86285d1de83
---
pyanaconda/ui/gui/spokes/network.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index 24020cc..8e89331 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -430,7 +430,7 @@ class NetworkControlBox(GObject.GObject):
log.debug("network: GUI, connection %s found", uuid)
if self.dev_cfg(uuid=uuid):
continue
- if setting["connection"]["read-only"]:
+ if setting["connection"].get("read-only", False):
log.debug("network: GUI, not adding read-only connection %s", uuid)
continue
dev_cfg = DeviceConfiguration(con_uuid=uuid)
--
1.9.3
9 years, 5 months
[anaconda][f21-branch][PATCH] Include help content in the Anaconda tarball
by Martin Kolman
When creating the Anaconda tarball clone the Installation Guide
repository, run a help processing script (which is part of the repo)
that generates help content for Anaconda and then include it in the tarball.
Signed-off-by: Martin Kolman <mkolman(a)redhat.com>
---
Makefile.am | 25 ++++++++++++++++++++++---
data/help/en-US/Makefile.am | 4 ++--
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 37a05b5..f5f7ab2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,6 +47,8 @@ ARCHIVE_TAG = $(PACKAGE_NAME)-$(PACKAGE_VERSION)-$(PACKAGE_RELEASE)
TX_PULL_ARGS = -a --disable-overwrite
TX_PUSH_ARGS = -s
+INSTALLATION_GUIDE_REPO_URL = git://git.fedorahosted.org/git/docs/install-guide.git
+
tag:
@git tag -s -a -m "Tag as $(ARCHIVE_TAG)" $(ARCHIVE_TAG)
@echo "Tagged as $(ARCHIVE_TAG)"
@@ -62,11 +64,11 @@ po-empty:
exit 1 ; \
done
-scratch: po-empty
+scratch: po-empty get-help
$(MAKE) ARCHIVE_TAG=HEAD dist
git checkout -- $(srcdir)/po/$(PACKAGE_NAME).pot
-scratch-bumpver: po-empty
+scratch-bumpver: po-empty get-help
@opts="-n $(PACKAGE_NAME) -v $(PACKAGE_VERSION) -r $(PACKAGE_RELEASE) -b $(PACKAGE_BUGREPORT)" ; \
if [ ! -z "$(IGNORE)" ]; then \
opts="$${opts} -i $(IGNORE)" ; \
@@ -83,7 +85,7 @@ scratch-bumpver: po-empty
( cd $(srcdir) && scripts/makebumpver $${opts} ) || exit 1 ; \
$(MAKE) -C po $(PACKAGE_NAME).pot-update ;
-release:
+release: get-help
$(MAKE) dist && $(MAKE) tag && git checkout -- $(srcdir)/po/$(PACKAGE_NAME).pot
api:
@@ -188,3 +190,20 @@ runglade:
GLADE_CATALOG_SEARCH_PATH=$(srcdir)/widgets/glade \
GLADE_MODULE_SEARCH_PATH=$(builddir)/widgets/src/.libs \
glade ${GLADE_FILE}
+
+
+# Get content for the Anaconda built-in help system by cloning the
+# installation guide git repository and running the help processing
+# script (it is part of the repository).
+# Once the help content has been generated copy it to our help folder,
+# so that it can be included in the tarball.
+# Skip the git clone if the repository already exists but run git pull
+# to make sure it is up to date. We also clone the repository
+# without history as it si rather big (>400 MB!), which is quite
+# an overkill for <100 kB of help conent. :)
+get-help:
+ if [ ! -d "install-guide" ]; then \
+ git clone --depth=1 $(INSTALLATION_GUIDE_REPO_URL) ; \
+ fi ; \
+ ( cd install-guide && git pull --rebase && python prepare_anaconda_help_content.py )
+ cp -r install-guide/anaconda_help_content/* $(srcdir)/data/help
diff --git a/data/help/en-US/Makefile.am b/data/help/en-US/Makefile.am
index b7aa1bc..b97e343 100644
--- a/data/help/en-US/Makefile.am
+++ b/data/help/en-US/Makefile.am
@@ -17,7 +17,7 @@
#
# Author: Martin Kolman <mkolman(a)redhat.com>
-enplaceholderdir = $(datadir)/anaconda/help/en-US
-dist_enplaceholder_DATA = FedoraPlaceholder.html FedoraPlaceholderWithLinks.html RHEL7Placeholder.html RHEL7PlaceholderWithLinks.html
+enhelpcontentdir = $(datadir)/anaconda/help/en-US
+dist_enhelpcontent_DATA = *.html *.xml
MAINTAINERCLEANFILES = Makefile.in
--
1.9.3
9 years, 5 months
[master/f21-branch] Fix typo causing traceback when NTP is turned ON/OFF
by Vratislav Podzimek
ksdata has 'services' not 'service' attribute
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
pyanaconda/kickstart.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 9277c59..56d5f0f 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -1593,7 +1593,7 @@ class Timezone(commands.timezone.F18_Timezone):
ksdata.packages.packageList.append(NTP_PACKAGE)
self._added_chrony = True
- if self._disabled_chrony and NTP_SERVICE in ksdata.service.disabled:
+ if self._disabled_chrony and NTP_SERVICE in ksdata.services.disabled:
ksdata.services.disabled.remove(NTP_SERVICE)
self._disabled_chrony = False
--
1.9.3
9 years, 5 months
[f21/master] Add a placeholder for a product-specific logo
by David Shea
This adds a product-logo class to BaseStandalone that will be rendered
after the sidebar background and regular sidebar logo. The position and
content of the logo can be set using
/run/install/product/anaconda-gtk.css
---
data/anaconda-gtk.css | 13 +++++++++++++
widgets/src/BaseStandalone.c | 4 ++++
2 files changed, 17 insertions(+)
diff --git a/data/anaconda-gtk.css b/data/anaconda-gtk.css
index 36d299c..6cb6343 100644
--- a/data/anaconda-gtk.css
+++ b/data/anaconda-gtk.css
@@ -116,12 +116,18 @@
@define-color fedora #2f4265;
/* logo and sidebar classes for Fedora */
+
+/* The sidebar consists of three parts: a background, a logo, and a product logo,
+ * rendered in that order. The product logo is empty by default and is intended
+ * to be overridden by a stylesheet in product.img.
+ */
.logo-sidebar {
background-image: url('/usr/share/anaconda/pixmaps/sidebar-bg.png');
background-color: @fedora;
background-repeat: no-repeat;
}
+/* Add a logo to the sidebar */
.logo {
background-image: url('/usr/share/anaconda/pixmaps/sidebar-logo.png');
background-position: 50% 20px;
@@ -129,6 +135,13 @@
background-color: transparent;
}
+/* This is a placeholder to be filled by a product-specific logo. */
+.product-logo {
+ background-image: none;
+ background-color: transparent;
+}
+
+
AnacondaSpokeWindow #nav-box {
background-color: @fedora;
background-image: url('/usr/share/anaconda/pixmaps/topbar-bg.png');
diff --git a/widgets/src/BaseStandalone.c b/widgets/src/BaseStandalone.c
index 0ff1049..c822cf4 100644
--- a/widgets/src/BaseStandalone.c
+++ b/widgets/src/BaseStandalone.c
@@ -261,6 +261,10 @@ static gboolean anaconda_base_standalone_on_draw(GtkWidget *win, cairo_t *cr) {
gtk_render_background(context, cr, sidebar_x, 0, sidebar_width, get_sidebar_height(win));
gtk_style_context_remove_class(context, "logo");
+ gtk_style_context_add_class(context, "product-logo");
+ gtk_render_background(context, cr, sidebar_x, 0, sidebar_width, get_sidebar_height(win));
+ gtk_style_context_remove_class(context, "product-logo");
+
gtk_style_context_restore (context);
return TRUE; /* TRUE to avoid default draw handler */
--
1.9.3
9 years, 5 months
[PATCH] Add product.img support for arm templates
by Brian C. Lane
---
share/arm.tmpl | 8 ++++++++
share/live/arm.tmpl | 8 ++++++++
2 files changed, 16 insertions(+)
diff --git a/share/arm.tmpl b/share/arm.tmpl
index e2798b9..26ce990 100644
--- a/share/arm.tmpl
+++ b/share/arm.tmpl
@@ -6,6 +6,7 @@ DTBDIR="images/pxeboot/dtb"
BOOTDIR="boot"
KERNELDIR=PXEBOOTDIR
LIVEDIR="LiveOS"
+LORAXDIR="usr/share/lorax/"
# different platforms use different kernel load addresses.
# include a 'baseline' kernel for no 'flavor'.
@@ -114,6 +115,13 @@ mkdir ${KERNELDIR}
# add platform to treeinfo for Beaker support
treeinfo ${basearch} platforms ${platforms}
+# Create optional product.img and updates.img
+<% images=["product", "updates"] %>
+%for img in images:
+ %if exists("%s/%s/" % (LORAXDIR, img)):
+ installimg ${LORAXDIR}/${img}/ images/${img}.img
+ %endif
+%endfor
## FIXME: ARM may need some extra boot config
diff --git a/share/live/arm.tmpl b/share/live/arm.tmpl
index 4c41d51..4b0cd82 100644
--- a/share/live/arm.tmpl
+++ b/share/live/arm.tmpl
@@ -5,6 +5,7 @@ PXEBOOTDIR="images/pxeboot"
BOOTDIR="boot"
KERNELDIR=PXEBOOTDIR
LIVEDIR="LiveOS"
+LORAXDIR="usr/share/lorax/"
# different platforms use different kernel load addresses.
# include a 'baseline' kernel for no 'flavor'.
@@ -69,6 +70,13 @@ mkdir ${KERNELDIR}
%endif
%endfor
+# Create optional product.img and updates.img
+<% images=["product", "updates"] %>
+%for img in images:
+ %if exists("%s/%s/" % (LORAXDIR, img)):
+ installimg ${LORAXDIR}/${img}/ images/${img}.img
+ %endif
+%endfor
## FIXME: ARM may need some extra boot config
--
1.9.3
9 years, 5 months
[master/f21/rhel7-branch] Prevent tb on s390x when de-selecting a DASD and doing custom part. (#1158590)
by Samantha N. Bueno
Keep track of the list of DASDs in the custom spoke so that if we
de-select one upon re-visiting the storage spoke and try to remove it
from the list of devices we are operating upon, anaconda doesn't crash.
Resolves: rhbz#1158590
---
pyanaconda/ui/gui/spokes/custom.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index 9daf9d1..b4c6ad7 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -1002,6 +1002,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
self.__storage.devicetree.hide(disk)
self._devices = self.__storage.devices
+ self._dasd = self.__storage.dasd
def refresh(self):
self.clear_errors()
@@ -2147,6 +2148,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
self.storage.devicetree._devices = self.__storage.devicetree._devices
self.storage.devicetree._actions = self.__storage.devicetree._actions
self.storage.devicetree._hidden = self.__storage.devicetree._hidden
+ self.storage.devicetree.dasd = self.__storage.devicetree.dasd
self.storage.devicetree.names = self.__storage.devicetree.names
self.storage.roots = self.__storage.roots
--
1.9.3
9 years, 5 months
[anaconda f21/master] Revert "Revert productName repo name change (#1128474)"
by Brian C. Lane
This reverts commit 51f204b9694400b512d0e8cf33c4b409ac0fa0d4.
Yes, this is absurd. But this will be the last time I change this. The
rule will now be:
Include a repo in your installation environment that has an id
matching the lower case first part of your product name when split at
the '-' character.
If you don't do that closest mirror will not work.
For Fedora products this means including ONE repo with an id of
'fedora'.
---
pyanaconda/packaging/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/packaging/__init__.py b/pyanaconda/packaging/__init__.py
index c91838b..effb08a 100644
--- a/pyanaconda/packaging/__init__.py
+++ b/pyanaconda/packaging/__init__.py
@@ -646,7 +646,7 @@ class ArchivePayload(ImagePayload):
class PackagePayload(Payload):
""" A PackagePayload installs a set of packages onto the target system. """
- DEFAULT_REPOS = [productName.lower(), "rawhide"]
+ DEFAULT_REPOS = [productName.split('-')[0].lower(), "rawhide"]
def __init__(self, data):
if self.__class__ is PackagePayload:
--
1.9.3
9 years, 6 months
[blivet+anaconda] handling for unusable storage configs
by David Lehman
It is time to put to bed the notion that an OS installer must be able to
handle any imaginable garbage preexisting on system storage. The overall
idea is that there are some things we cannot handle in any reasonable way
without extensive UI. In those cases, the user must straighten things out
before proceeding.
The first patch is rendered mostly obsolete by the rest of the set, but it
follows how we handle the corresponding situation with md.
The second patch is intended to allow the use of ignoredisk (via kickstart)
to temporarily avoid dealing with a corrupt gpt disklabel.
There is no try/except around the storage resets in the storage spokes
because there is no reason to expect such a situation to arise anywhere
other than the initial scan or after a user-initiated re-scan.
It worked well for me in some testing with f21 for whatever that's worth.
Apparently I do not have the "QE knack".
9 years, 6 months
[f21/master 1/2] Wrap interruptible system calls in a loop (#1160041)
by David Shea
Some system calls are interrupted by the receipt of a signal, for us
most commonly a SIGCHLD caused by a process run from a different thread,
which causes the call to return -1 and set errno to EINTR, which python
converts into an OSError. Handle this by retrying the call.
---
anaconda | 6 +++---
pyanaconda/anaconda.py | 4 ++--
pyanaconda/bootloader.py | 22 +++++++++++-----------
pyanaconda/exception.py | 12 ++++++------
pyanaconda/install.py | 2 +-
pyanaconda/iutil.py | 23 +++++++++++++++++------
pyanaconda/kickstart.py | 6 +++---
pyanaconda/ntp.py | 3 ++-
pyanaconda/packaging/livepayload.py | 6 +++---
pyanaconda/simpleconfig.py | 4 ++--
pyanaconda/ui/lib/space.py | 2 +-
pyanaconda/users.py | 2 +-
pyanaconda/vnc.py | 8 ++++----
scripts/anaconda-yum | 8 ++++----
tests/gui/outside/__init__.py | 14 +++++++++++++-
15 files changed, 73 insertions(+), 49 deletions(-)
diff --git a/anaconda b/anaconda
index 667cf1f..ea5c077 100755
--- a/anaconda
+++ b/anaconda
@@ -892,11 +892,11 @@ if __name__ == "__main__":
# Attempt to create the pidfile
try:
# Set all of the read/write bits and let umask make it make sense
- pidfile = os.open(pidfile_path, os.O_WRONLY|os.O_CREAT|os.O_EXCL,
+ pidfile = iutil.eintr_retry_call(os.open, pidfile_path, os.O_WRONLY|os.O_CREAT|os.O_EXCL,
stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IWGRP|stat.S_IROTH|stat.S_IWOTH)
pidfile_created = True
- os.write(pidfile, "%s\n" % os.getpid())
- os.close(pidfile)
+ iutil.eintr_retry_call(os.write, pidfile, "%s\n" % os.getpid())
+ iutil.eintr_retry_call(os.close, pidfile)
except OSError as e:
# If the failure was anything other than EEXIST during the open call,
# just re-raise the exception
diff --git a/pyanaconda/anaconda.py b/pyanaconda/anaconda.py
index f44fd8f..57116bb 100644
--- a/pyanaconda/anaconda.py
+++ b/pyanaconda/anaconda.py
@@ -197,8 +197,8 @@ class Anaconda(object):
dump_text = exn.traceback_and_object_dump(self)
dump_text += threads
dump_text = dump_text.encode("utf-8")
- os.write(fd, dump_text)
- os.close(fd)
+ iutil.eintr_retry_call(os.write, fd, dump_text)
+ iutil.eintr_retry_call(os.close, fd)
# append to a given file
with open("/tmp/anaconda-tb-all.log", "a+") as f:
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
index a8f9130..d30a0f9 100644
--- a/pyanaconda/bootloader.py
+++ b/pyanaconda/bootloader.py
@@ -54,11 +54,11 @@ def get_boot_block(device, seek_blocks=0):
except StorageError:
return ""
block_size = device.partedDevice.sectorSize
- fd = os.open(device.path, os.O_RDONLY)
+ fd = iutil.eintr_retry_call(os.open, device.path, os.O_RDONLY)
if seek_blocks:
os.lseek(fd, seek_blocks * block_size, 0)
- block = os.read(fd, 512)
- os.close(fd)
+ block = iutil.eintr_retry_call(os.read, fd, 512)
+ iutil.eintr_retry_call(os.close, fd)
if not status:
try:
device.teardown(recursive=True)
@@ -923,7 +923,7 @@ class BootLoader(object):
def write_config_post(self):
try:
- os.chmod(iutil.getSysroot() + self.config_file, self.config_file_mode)
+ iutil.eintr_retry_call(os.chmod, iutil.getSysroot() + self.config_file, self.config_file_mode)
except OSError as e:
log.error("failed to set config file permissions: %s", e)
@@ -1320,12 +1320,12 @@ class GRUB(BootLoader):
"stage1dev": self.grub_device_name(stage1dev),
"stage2dev": self.grub_device_name(stage2dev)})
(pread, pwrite) = os.pipe()
- os.write(pwrite, cmd)
- os.close(pwrite)
+ iutil.eintr_retry_call(os.write, pwrite, cmd)
+ iutil.eintr_retry_call(os.close, pwrite)
args = ["--batch", "--no-floppy",
"--device-map=%s" % self.device_map_file]
rc = iutil.execInSysroot("grub", args, stdin=pread)
- os.close(pread)
+ iutil.eintr_retry_call(os.close, pread)
if rc:
raise BootLoaderError("boot loader install failed")
@@ -1515,12 +1515,12 @@ class GRUB2(GRUB):
raise RuntimeError("cannot encrypt empty password")
(pread, pwrite) = os.pipe()
- os.write(pwrite, "%s\n%s\n" % (self.password, self.password))
- os.close(pwrite)
+ iutil.eintr_retry_call(os.write, pwrite, "%s\n%s\n" % (self.password, self.password))
+ iutil.eintr_retry_call(os.close, pwrite)
buf = iutil.execWithCapture("grub2-mkpasswd-pbkdf2", [],
stdin=pread,
root=iutil.getSysroot())
- os.close(pread)
+ iutil.eintr_retry_call(os.close, pread)
self.encrypted_password = buf.split()[-1].strip()
if not self.encrypted_password.startswith("grub.pbkdf2."):
raise BootLoaderError("failed to encrypt boot loader password")
@@ -1541,7 +1541,7 @@ class GRUB2(GRUB):
header.write("%s\n" % password_line)
header.write("EOF\n")
header.close()
- os.chmod(users_file, 0o700)
+ iutil.eintr_retry_call(os.chmod, users_file, 0o700)
def write_config(self):
self.write_config_console(None)
diff --git a/pyanaconda/exception.py b/pyanaconda/exception.py
index 6a9b9cd..b8b8f4f 100644
--- a/pyanaconda/exception.py
+++ b/pyanaconda/exception.py
@@ -187,12 +187,12 @@ class AnacondaExceptionHandler(ExceptionHandler):
and self._intf_tty_num != 1:
iutil.vtActivate(1)
- os.open("/dev/console", os.O_RDWR) # reclaim stdin
- os.dup2(0, 1) # reclaim stdout
- os.dup2(0, 2) # reclaim stderr
- # ^
- # |
- # +------ dup2 is magic, I tells ya!
+ iutil.eintr_retry_call(os.open, "/dev/console", os.O_RDWR) # reclaim stdin
+ iutil.eintr_retry_call(os.dup2, 0, 1) # reclaim stdout
+ iutil.eintr_retry_call(os.dup2, 0, 2) # reclaim stderr
+ # ^
+ # |
+ # +------ dup2 is magic, I tells ya!
# bring back the echo
import termios
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
index 40ead97..f6501f9 100644
--- a/pyanaconda/install.py
+++ b/pyanaconda/install.py
@@ -50,7 +50,7 @@ def _writeKS(ksdata):
f.write(str(ksdata))
# Make it so only root can read - could have passwords
- os.chmod(path, 0o600)
+ iutil.eintr_retry_call(os.chmod, path, 0o600)
def doConfiguration(storage, payload, ksdata, instClass):
from pyanaconda.kickstart import runPostScripts
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 3f70860..bcd5b55 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -437,7 +437,7 @@ def _sigchld_handler(num=None, frame=None):
for child_pid in _forever_pids:
try:
- pid_result, status = os.waitpid(child_pid, os.WNOHANG)
+ pid_result, status = eintr_retry_call(os.waitpid, child_pid, os.WNOHANG)
except OSError as e:
if e.errno == errno.ECHILD:
continue
@@ -724,7 +724,7 @@ def dracut_eject(device):
f.write("eject %s\n" % (device,))
f.close()
- os.chmod(DRACUT_SHUTDOWN_EJECT, 0o755)
+ eintr_retry_call(os.chmod, DRACUT_SHUTDOWN_EJECT, 0o755)
log.info("Wrote dracut shutdown eject hook for %s", device)
except (IOError, OSError) as e:
log.error("Error writing dracut shutdown eject hook for %s: %s", device, e)
@@ -985,11 +985,11 @@ def chown_dir_tree(root, uid, gid, from_uid_only=None, from_gid_only=None):
return
# UID and GID matching or not required
- os.chown(path, uid, gid)
+ eintr_retry_call(os.chown, path, uid, gid)
if not from_uid_only and not from_gid_only:
# the easy way
- dir_tree_map(root, lambda path: os.chown(path, uid, gid))
+ dir_tree_map(root, lambda path: eintr_retry_call(os.chown, path, uid, gid))
else:
# conditional chown
dir_tree_map(root, lambda path: conditional_chown(path, uid, gid,
@@ -1184,9 +1184,20 @@ def ipmi_report(event):
# Sensor num - passed in event
# Event dir & type - always 0x0 for anaconda's purposes
# Event data 1, 2, 3 - 0x0 for now
- os.write(fd, "0x4 0x1F %#x 0x0 0x0 0x0 0x0\n" % event)
- os.close(fd)
+ eintr_retry_call(os.write, fd, "0x4 0x1F %#x 0x0 0x0 0x0 0x0\n" % event)
+ eintr_retry_call(os.close, fd)
execWithCapture("ipmitool", ["sel", "add", path])
os.remove(path)
+
+# Copied from python's subprocess.py
+def eintr_retry_call(func, *args):
+ """Retry an interruptible system call if interrupted."""
+ while True:
+ try:
+ return func(*args)
+ except (OSError, IOError) as e:
+ if e.errno == errno.EINTR:
+ continue
+ raise
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 9277c59..84818b9 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -95,9 +95,9 @@ class AnacondaKSScript(KSScript):
(fd, path) = tempfile.mkstemp("", "ks-script-", scriptRoot + "/tmp")
- os.write(fd, self.script)
- os.close(fd)
- os.chmod(path, 0o700)
+ iutil.eintr_retry_call(os.write, fd, self.script)
+ iutil.eintr_retry_call(os.close, fd)
+ iutil.eintr_retry_call(os.chmod, path, 0o700)
# Always log stdout/stderr from scripts. Using --log just lets you
# pick where it goes. The script will also be logged to program.log
diff --git a/pyanaconda/ntp.py b/pyanaconda/ntp.py
index f0c051b..40263ae 100644
--- a/pyanaconda/ntp.py
+++ b/pyanaconda/ntp.py
@@ -31,6 +31,7 @@ import ntplib
import socket
from pyanaconda import isys
+from pyanaconda import iutil
from pyanaconda.threads import threadMgr, AnacondaThread
from pyanaconda.constants import THREAD_SYNC_TIME_BASENAME
@@ -157,7 +158,7 @@ def save_servers_to_config(servers, conf_file_path=NTP_CONFIG_FILE,
stat = os.stat(conf_file_path)
# Use copy rather then move to get the correct selinux context
shutil.copy(temp_path, conf_file_path)
- os.chmod(conf_file_path, stat.st_mode)
+ iutil.eintr_retry_call(os.chmod, conf_file_path, stat.st_mode)
os.unlink(temp_path)
except OSError as oserr:
diff --git a/pyanaconda/packaging/livepayload.py b/pyanaconda/packaging/livepayload.py
index d6db00b..729d40c 100644
--- a/pyanaconda/packaging/livepayload.py
+++ b/pyanaconda/packaging/livepayload.py
@@ -80,7 +80,7 @@ class LiveImagePayload(ImagePayload):
if rc != 0:
raise PayloadInstallError("Failed to mount the install tree")
- source = os.statvfs(INSTALL_TREE)
+ source = iutil.eintr_retry_call(os.statvfs, INSTALL_TREE)
self.source_size = source.f_frsize * (source.f_blocks - source.f_bfree)
def preInstall(self, packages=None, groups=None):
@@ -97,7 +97,7 @@ class LiveImagePayload(ImagePayload):
while self.pct < 100:
dest_size = 0
for mnt in mountpoints:
- mnt_stat = os.statvfs(iutil.getSysroot()+mnt)
+ mnt_stat = iutil.eintr_retry_call(os.statvfs, iutil.getSysroot()+mnt)
dest_size += mnt_stat.f_frsize * (mnt_stat.f_blocks - mnt_stat.f_bfree)
if dest_size >= self._adj_size:
dest_size -= self._adj_size
@@ -349,7 +349,7 @@ class LiveImageKSPayload(LiveImagePayload):
blivet.util.mount(IMAGE_DIR+"/LiveOS/"+img_file, INSTALL_TREE,
fstype="auto", options="ro")
- source = os.statvfs(INSTALL_TREE)
+ source = iutil.eintr_retry_call(os.statvfs, INSTALL_TREE)
self.source_size = source.f_frsize * (source.f_blocks - source.f_bfree)
def install(self):
diff --git a/pyanaconda/simpleconfig.py b/pyanaconda/simpleconfig.py
index 53617c0..47b7a95 100644
--- a/pyanaconda/simpleconfig.py
+++ b/pyanaconda/simpleconfig.py
@@ -27,7 +27,7 @@ import shutil
import shlex
from pipes import _safechars
import tempfile
-from pyanaconda.iutil import upperASCII
+from pyanaconda.iutil import upperASCII, eintr_retry_call
def unquote(s):
return ' '.join(shlex.split(s))
@@ -121,7 +121,7 @@ class SimpleConfigFile(object):
else:
m = int('0100644', 8)
shutil.move(tmpf.name, filename)
- os.chmod(filename, m)
+ eintr_retry_call(os.chmod, filename, m)
else:
# write directly to the file
with open(filename, "w") as fobj:
diff --git a/pyanaconda/ui/lib/space.py b/pyanaconda/ui/lib/space.py
index 3251ba6..a133c8b 100644
--- a/pyanaconda/ui/lib/space.py
+++ b/pyanaconda/ui/lib/space.py
@@ -102,7 +102,7 @@ class DirInstallSpaceChecker(FileSystemSpaceChecker):
in the info bar at the bottom of a Hub.
"""
self.reset()
- stat = os.statvfs(iutil.getSysroot())
+ stat = iutil.eintr_retry_call(os.statvfs, iutil.getSysroot())
free = Size(stat.f_bsize * stat.f_bfree)
needed = self.payload.spaceRequired
log.info("fs space: %s needed: %s", free, needed)
diff --git a/pyanaconda/users.py b/pyanaconda/users.py
index 951c4e7..756a652 100644
--- a/pyanaconda/users.py
+++ b/pyanaconda/users.py
@@ -219,7 +219,7 @@ class Users:
def _finishChroot(self, childpid):
assert childpid > 0
try:
- status = os.waitpid(childpid, 0)[1]
+ status = iutil.eintr_retry_call(os.waitpid, childpid, 0)[1]
except OSError as e:
log.critical("exception from waitpid: %s %s", e.errno, e.strerror)
return False
diff --git a/pyanaconda/vnc.py b/pyanaconda/vnc.py
index a7e2072..a3a70a7 100644
--- a/pyanaconda/vnc.py
+++ b/pyanaconda/vnc.py
@@ -80,15 +80,15 @@ class VncServer:
"""Set the vnc server password. Output to file. """
r, w = os.pipe()
- os.write(w, "%s\n" % self.password)
+ iutil.eintr_retry_call(os.write, w, "%s\n" % self.password)
with open(self.pw_file, "w") as pw_file:
# the -f option makes sure vncpasswd does not ask for the password again
rc = iutil.execWithRedirect("vncpasswd", ["-f"],
stdin=r, stdout=pw_file, binary_output=True, log_output=False)
- os.close(r)
- os.close(w)
+ iutil.eintr_retry_call(os.close, r)
+ iutil.eintr_retry_call(os.close, w)
return rc
@@ -137,7 +137,7 @@ class VncServer:
def openlogfile(self):
try:
- fd = os.open(self.log_file, os.O_RDWR | os.O_CREAT)
+ fd = iutil.eintr_retry_call(os.open, self.log_file, os.O_RDWR | os.O_CREAT)
except OSError as e:
sys.stderr.write("error opening %s: %s\n", (self.log_file, e))
fd = None
diff --git a/scripts/anaconda-yum b/scripts/anaconda-yum
index 41a4309..9c6dce1 100755
--- a/scripts/anaconda-yum
+++ b/scripts/anaconda-yum
@@ -27,7 +27,7 @@ import rpm
import rpmUtils
import yum
from urlgrabber.grabber import URLGrabError
-from pyanaconda.iutil import xprogressive_delay
+from pyanaconda.iutil import xprogressive_delay, eintr_retry_call
YUM_PLUGINS = ["fastestmirror", "langpacks"]
@@ -156,7 +156,7 @@ def run_yum_transaction(release, arch, yum_conf, install_root, ts_file, script_l
yb.ts.clean()
# Write scriptlet output to a file to be logged later
- logfile = os.open(script_log, os.O_WRONLY|os.O_CREAT)
+ logfile = eintr_retry_call(os.open, script_log, os.O_WRONLY|os.O_CREAT)
yb.ts.ts.scriptFd = logfile
rpm.setLogFile(logfile)
@@ -183,7 +183,7 @@ def run_yum_transaction(release, arch, yum_conf, install_root, ts_file, script_l
print("INFO: transaction complete")
finally:
yb.ts.close()
- os.close(logfile)
+ eintr_retry_call(os.close, logfile)
except YumBaseError as e:
print("ERROR: transaction error: %s" % e)
finally:
@@ -277,7 +277,7 @@ class RPMCallback(object):
log_msg = msg_format % (txmbr.po,
self.completed_actions,
self.total_actions)
- os.write(self.install_log, log_msg+"\n")
+ eintr_retry_call(os.write, self.install_log, log_msg+"\n")
print("PROGRESS_INSTALL: %s" % progress_msg)
try:
diff --git a/tests/gui/outside/__init__.py b/tests/gui/outside/__init__.py
index a5f5144..5c0f6db 100644
--- a/tests/gui/outside/__init__.py
+++ b/tests/gui/outside/__init__.py
@@ -26,6 +26,18 @@ import os
import shutil
import subprocess
import tempfile
+import errno
+
+# Copied from python's subprocess.py
+def eintr_retry_call(func, *args):
+ """Retry an interruptible system call if interrupted."""
+ while True:
+ try:
+ return func(*args)
+ except (OSError, IOError) as e:
+ if e.errno == errno.EINTR:
+ continue
+ raise
class Creator(object):
"""A Creator subclass defines all the parameters for making a VM to run a
@@ -98,7 +110,7 @@ class Creator(object):
"""
for (drive, size) in self.drives:
(fd, diskimage) = tempfile.mkstemp(dir=self.tempdir)
- os.close(fd)
+ eintr_retry_call(os.close, fd)
subprocess.call(["/usr/bin/qemu-img", "create", "-f", "qcow2", diskimage, "%sG" % size],
stdout=open("/dev/null", "w"))
--
2.1.0
9 years, 6 months
[blivet:master] Factoring out MDRaidArrayDevice functionality
by Anne Mulhern
The question is, do the two subclasses make any kind of sense?
Also, assuming they do, what is the best solution to making sure
that the correct class gets constructed in the correct situation?
Would it be reasonable to go about this by defining __new__() in
MDRaidArrayDevice and using that method to select the appropriate subclass?
The appropriate subclass is decided by
a) RAID level
b) type of parent
mulhern (1):
Factor out MDRaidArrayDevice w/ type in ("mdcontainer",
"mdbiosraidarray")
blivet/devicelibs/mdraid.py | 2 +-
blivet/devices/__init__.py | 2 +-
blivet/devices/container.py | 18 +--
blivet/devices/md.py | 189 +++++++++++++++--------
tests/devicelibs_test/mdraid_interrogate_test.py | 4 +-
tests/devicelibs_test/mdraid_test.py | 1 -
tests/devices_test.py | 16 +-
7 files changed, 141 insertions(+), 91 deletions(-)
--
1.9.3
9 years, 6 months