Skip to content

Commit

Permalink
Improve install space required estimation (#1224048)
Browse files Browse the repository at this point in the history
The problem was that 35% add is not enough on the smaller installations.
That result in crash on RPM transaction check. RPM required more space
than we have.
This problem was consulted with RPM team and this is result.
The RPM rounding size of files to fragment size (default 4KiB) for
better estimation also they are required package header size * 4 for RPM
DB.

We don't have header size or file size in the installation so I'm trying
to simulate worst case scenario for file rounding and using 2KiB for
every file to get something like RPM DB space required.
Also 10% is add to all this as a safeguard.

Seems as stable assumption right now.
+
Improved logging for packaging.

Resolves: rhbz#1224048
  • Loading branch information
jkonecny12 committed Oct 27, 2015
1 parent 1780943 commit 6f7b160
Showing 1 changed file with 33 additions and 11 deletions.
44 changes: 33 additions & 11 deletions pyanaconda/packaging/dnfpayload.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
'/tmp/product/anaconda.repos.d']
YUM_REPOS_DIR = "/etc/yum.repos.d/"

# Bonus to required free space which depends on block size and rpm database size estimation.
# Every file could be aligned to fragment size so 4KiB * number_of_files should be a worst
# case scenario. 2KiB for RPM DB was acquired by testing.
# 6KiB = 4K(max default fragment size) + 2K(rpm db could be taken for a header file)
BONUS_SIZE_ON_FILE = Size("6 KiB")

_DNF_INSTALLER_LANGPACK_CONF = DNF_PLUGINCONF_DIR + "/langpacks.conf"
_DNF_TARGET_LANGPACK_CONF = "/etc/dnf/plugins/langpacks.conf"

Expand Down Expand Up @@ -115,8 +121,9 @@ def reasonable_mpoint(mpoint):
# for root we need to take in count both download and install size
if ((key != root_mpoint and val > requested)
or val > requested_root) and reasonable_mpoint(key)}
log.debug('Estimated size: download %s & install %s - df: %s', requested,
(requested_root - requested), df)
log.debug('Input mount points: %s', df)
log.debug('Estimated size: download %s & install %s', requested,
(requested_root - requested))
log.info('Sufficient mountpoints found: %s', sufficients)

if not len(sufficients):
Expand Down Expand Up @@ -555,23 +562,38 @@ def spaceRequired(self):
if key.startswith('/') and ((root_mpoint + new_key) not in valid_points):
valid_points[root_mpoint + new_key] = val.format.freeSpaceEstimate(val.size)

m_points = _pick_mpoint(valid_points, download_size, size)
if not m_points or m_points == root_mpoint:
m_point = _pick_mpoint(valid_points, download_size, size)
if not m_point or m_point == root_mpoint:
# download and install to the same mount point
size = size + download_size
log.debug("Instalation space required %s for mpoints %s", size, m_points)
log.debug("Install + download space required %s", size)
else:
log.debug("Download space required %s for mpoint %s (non-chroot)", download_size, m_point)
log.debug("Installation space required %s", size)
return size

def _spaceRequired(self):
transaction = self._base.transaction
if transaction is None:
return Size("3000 MB")

size = sum(tsi.installed.installsize for tsi in transaction)
# add 35% to account for the fact that the above method is laughably
# inaccurate:
size *= 1.35
return Size(size)
size = 0
files_nm = 0
for tsi in transaction:
# space taken by all files installed by the packages
size += tsi.installed.installsize
# number of files installed on the system
files_nm += len(tsi.installed.files)

# append bonus size depending on number of files
bonus_size = files_nm * BONUS_SIZE_ON_FILE
size = Size(size)
# add another 10% as safeguard
total_space = (size + bonus_size) * 1.1
log.debug("Size from DNF: %s", size)
log.debug("Bonus size %s by number of files %s", bonus_size, files_nm)
log.debug("Total size required %s", total_space)
return total_space

def _isGroupVisible(self, grpid):
grp = self._base.comps.group_by_pattern(grpid)
Expand Down Expand Up @@ -688,7 +710,7 @@ def install(self):
_failure_limbo()

pkgs_to_download = self._base.transaction.install_set
log.info('Downloading packages.')
log.info('Downloading packages to %s.', self._download_location)
progressQ.send_message(_('Downloading packages'))
progress = DownloadProgress()
try:
Expand Down

0 comments on commit 6f7b160

Please sign in to comment.