summaryrefslogtreecommitdiffstats
path: root/py/mock/plugins
diff options
context:
space:
mode:
authorMichael E Brown <mebrown@michaels-house.net>2007-11-30 11:51:25 -0600
committerMichael E Brown <mebrown@michaels-house.net>2007-11-30 11:51:25 -0600
commit97f06be255f9a20613c66510e05f68372af7215f (patch)
tree2d57f70b6889bd351f3efac9f32ae806faa53aee /py/mock/plugins
parent96dd05c47ed25102fe92a1c7810d12716083e05e (diff)
downloadmock-97f06be255f9a20613c66510e05f68372af7215f.tar.gz
mock-97f06be255f9a20613c66510e05f68372af7215f.tar.xz
mock-97f06be255f9a20613c66510e05f68372af7215f.zip
move things around so that we can run mock.py from the build tree instead of having to install it.
Diffstat (limited to 'py/mock/plugins')
-rw-r--r--py/mock/plugins/bind_mount.py39
-rw-r--r--py/mock/plugins/ccache.py73
-rw-r--r--py/mock/plugins/root_cache.py93
-rw-r--r--py/mock/plugins/yum_cache.py94
4 files changed, 299 insertions, 0 deletions
diff --git a/py/mock/plugins/bind_mount.py b/py/mock/plugins/bind_mount.py
new file mode 100644
index 0000000..e010f92
--- /dev/null
+++ b/py/mock/plugins/bind_mount.py
@@ -0,0 +1,39 @@
+# vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0:
+# License: GPL2 or later see COPYING
+# Written by Michael Brown
+# Copyright (C) 2007 Michael E Brown <mebrown@michaels-house.net>
+
+# python library imports
+import logging
+import os
+
+# our imports
+from mock.trace_decorator import traceLog
+import mock.util
+
+# set up logging, module options
+moduleLog = logging.getLogger("mock")
+requires_api_version = "1.0"
+
+# plugin entry point
+def init(rootObj, conf):
+ bind = BindMount(rootObj, conf)
+
+# classes
+class BindMount(object):
+ """bind mount dirs from host into chroot"""
+ @traceLog(moduleLog)
+ def __init__(self, rootObj, conf):
+ self.rootObj = rootObj
+ self.bind_opts = conf
+ self.rootdir = rootObj.rootdir
+ rootObj.bindMountObj = self
+ rootObj.addHook("preinit", self._bindMountPreInitHook)
+ for srcdir, destdir in self.bind_opts['dirs']:
+ rootObj.umountCmds.append('umount -n %s/%s' % (rootObj.rootdir, destdir))
+ rootObj.mountCmds.append('mount -n --bind %s %s/%s' % (srcdir, rootObj.rootdir, destdir))
+
+ @traceLog(moduleLog)
+ def _bindMountPreInitHook(self):
+ for srcdir, destdir in self.bind_opts['dirs']:
+ mock.util.mkdirIfAbsent("%s/%s" % (self.rootObj.rootdir, destdir))
diff --git a/py/mock/plugins/ccache.py b/py/mock/plugins/ccache.py
new file mode 100644
index 0000000..27ec405
--- /dev/null
+++ b/py/mock/plugins/ccache.py
@@ -0,0 +1,73 @@
+# vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0:
+# License: GPL2 or later see COPYING
+# Written by Michael Brown
+# Copyright (C) 2007 Michael E Brown <mebrown@michaels-house.net>
+
+# python library imports
+import logging
+import os
+
+# our imports
+from mock.trace_decorator import traceLog
+import mock.util
+
+# set up logging, module options
+moduleLog = logging.getLogger("mock")
+requires_api_version = "1.0"
+
+# plugin entry point
+def init(rootObj, conf):
+ ccache = CCache(rootObj, conf)
+
+# classes
+class CCache(object):
+ """enables ccache in buildroot/rpmbuild"""
+ @traceLog(moduleLog)
+ def __init__(self, rootObj, conf):
+ self.rootObj = rootObj
+ self.ccache_opts = conf
+ self.ccachePath = self.ccache_opts['dir'] % self.ccache_opts
+ self.rootdir = rootObj.rootdir
+ rootObj.ccacheObj = self
+ rootObj.preExistingDeps = rootObj.preExistingDeps + " ccache "
+ rootObj.addHook("prebuild", self._ccacheBuildHook)
+ rootObj.addHook("preinit", self._ccachePreInitHook)
+ rootObj.umountCmds.append('umount -n %s/tmp/ccache' % rootObj.rootdir)
+ rootObj.mountCmds.append('mount -n --bind %s %s/tmp/ccache' % (self.ccachePath, rootObj.rootdir))
+
+ # =============
+ # 'Private' API
+ # =============
+ # set the max size before we actually use it during a build.
+ # ccache itself manages size and settings.
+ @traceLog(moduleLog)
+ def _ccacheBuildHook(self):
+ self.rootObj.doChroot("ccache -M %s" % self.ccache_opts['max_cache_size'])
+
+ # basic idea here is that we add 'cc', 'gcc', 'g++' shell scripts to
+ # to /tmp/ccache, which is bind-mounted from a shared location.
+ # we then add this to the front of the path.
+ # we also set a few admin variables used by ccache to find the shared
+ # cache.
+ @traceLog(moduleLog)
+ def _ccachePreInitHook(self):
+ mock.util.mkdirIfAbsent(os.path.join(self.rootdir, 'tmp/ccache'))
+ mock.util.mkdirIfAbsent(self.ccachePath)
+ os.environ['PATH'] = "/tmp/ccache:%s" % (os.environ['PATH'])
+ os.environ['CCACHE_DIR'] = "/tmp/ccache"
+ os.environ['CCACHE_UMASK'] = "002"
+ for i in ("cc", "gcc", "gcc296", "gcc32", "gcc33", "gcc34",
+ "g++", "c++", "c++32", "c++33", "c++34", "g++296", "g++32", "g++33", "g++34",
+ "g++-libstdc++-so_7",):
+ forceLink("/usr/bin/ccache", os.path.join(self.ccachePath, "%s" % i))
+ forceLink("/usr/bin/ccache", os.path.join(self.ccachePath, "x86_64-redhat-linux-%s" % i))
+ forceLink("/usr/bin/ccache", os.path.join(self.ccachePath, "i386-redhat-linux-%s" % i))
+
+@traceLog(moduleLog)
+def forceLink( existing, linkname ):
+ try:
+ os.unlink(linkname)
+ except OSError:
+ pass
+
+ os.symlink(existing, linkname)
diff --git a/py/mock/plugins/root_cache.py b/py/mock/plugins/root_cache.py
new file mode 100644
index 0000000..8ed2492
--- /dev/null
+++ b/py/mock/plugins/root_cache.py
@@ -0,0 +1,93 @@
+# vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0:
+# License: GPL2 or later see COPYING
+# Written by Michael Brown
+# Copyright (C) 2007 Michael E Brown <mebrown@michaels-house.net>
+
+# python library imports
+import fcntl
+import logging
+import os
+import time
+
+# our imports
+from mock.trace_decorator import traceLog
+import mock.util
+
+# set up logging, module options
+moduleLog = logging.getLogger("mock")
+requires_api_version = "1.0"
+
+# plugin entry point
+def init(rootObj, conf):
+ rootCache = RootCache(rootObj, conf)
+
+# classes
+class RootCache(object):
+ """caches root environment in a tarball"""
+ @traceLog(moduleLog)
+ def __init__(self, rootObj, conf):
+ self.rootObj = rootObj
+ self.root_cache_opts = conf
+ self.rootSharedCachePath = self.root_cache_opts['dir'] % self.root_cache_opts
+ self.rootCacheFile = os.path.join(self.rootSharedCachePath, "cache.tar.gz")
+ self.rootCacheLock = None
+ self.state = rootObj.state
+ self.rootdir = rootObj.rootdir
+ rootObj.rootCacheObj = self
+ rootObj.addHook("preinit", self._rootCachePreInitHook)
+ rootObj.addHook("postinit", self._rootCachePostInitHook)
+
+ # =============
+ # 'Private' API
+ # =============
+ @traceLog(moduleLog)
+ def _rootCacheLock(self, shared=1):
+ lockType = fcntl.LOCK_EX
+ if shared: lockType = fcntl.LOCK_SH
+ try:
+ fcntl.lockf(self.rootCacheLock.fileno(), lockType | fcntl.LOCK_NB)
+ except IOError, e:
+ oldState = self.state()
+ self.state("Waiting for rootcache lock")
+ fcntl.lockf(self.rootCacheLock.fileno(), lockType)
+ self.state(oldState)
+
+ @traceLog(moduleLog)
+ def _rootCacheUnlock(self):
+ fcntl.lockf(self.rootCacheLock.fileno(), fcntl.LOCK_UN)
+
+ @traceLog(moduleLog)
+ def _rootCachePreInitHook(self):
+ moduleLog.info("enabled root cache")
+ mock.util.mkdirIfAbsent(self.rootSharedCachePath)
+ # lock so others dont accidentally use root cache while we operate on it.
+ if self.rootCacheLock is None:
+ self.rootCacheLock = open(os.path.join(self.rootSharedCachePath, "rootcache.lock"), "a+")
+
+ # check cache age:
+ try:
+ statinfo = os.stat(self.rootCacheFile)
+ file_age_days = (time.time() - statinfo.st_ctime) / (60 * 60 * 24)
+ if file_age_days > self.root_cache_opts['max_age_days']:
+ os.unlink(self.rootCacheFile)
+ except OSError:
+ pass
+
+ # optimization: dont unpack root cache if chroot was not cleaned
+ if os.path.exists(self.rootCacheFile) and self.rootObj.chrootWasCleaned:
+ self.state("unpacking cache")
+ self._rootCacheLock()
+ mock.util.do("tar xzf %s -C %s" % (self.rootCacheFile, self.rootdir))
+ self._rootCacheUnlock()
+ self.chroot_setup_cmd = "update"
+ self.rootObj.chrootWasCleaned = False
+
+ @traceLog(moduleLog)
+ def _rootCachePostInitHook(self):
+ # never rebuild cache unless it was a clean build.
+ if self.rootObj.chrootWasCleaned:
+ self.state("creating cache")
+ self._rootCacheLock(shared=0)
+ mock.util.do("tar czf %s -C %s ." % (self.rootCacheFile, self.rootdir))
+ self._rootCacheUnlock()
+
diff --git a/py/mock/plugins/yum_cache.py b/py/mock/plugins/yum_cache.py
new file mode 100644
index 0000000..5a4abc3
--- /dev/null
+++ b/py/mock/plugins/yum_cache.py
@@ -0,0 +1,94 @@
+# vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0:
+# License: GPL2 or later see COPYING
+# Written by Michael Brown
+# Copyright (C) 2007 Michael E Brown <mebrown@michaels-house.net>
+
+# python library imports
+import logging
+import fcntl
+import time
+import os
+
+# our imports
+from mock.trace_decorator import traceLog
+import mock.util
+
+# set up logging, module options
+moduleLog = logging.getLogger("mock")
+requires_api_version = "1.0"
+
+# plugin entry point
+def init(rootObj, conf):
+ yumCache = YumCache(rootObj, conf)
+
+# classes
+class YumCache(object):
+ """caches root environment in a tarball"""
+ @traceLog(moduleLog)
+ def __init__(self, rootObj, conf):
+ self.rootObj = rootObj
+ self.yum_cache_opts = conf
+ self.yumSharedCachePath = self.yum_cache_opts['dir'] % self.yum_cache_opts
+ self.state = rootObj.state
+ self.rootdir = rootObj.rootdir
+ self.online = rootObj.online
+ rootObj.yum_cacheObj = self
+ rootObj.addHook("preyum", self._yumCachePreYumHook)
+ rootObj.addHook("postyum", self._yumCachePostYumHook)
+ rootObj.addHook("preinit", self._yumCachePreInitHook)
+ rootObj.umountCmds.append('umount -n %s/var/cache/yum' % rootObj.rootdir)
+ rootObj.mountCmds.append('mount -n --bind %s %s/var/cache/yum' % (self.yumSharedCachePath, rootObj.rootdir))
+
+ # =============
+ # 'Private' API
+ # =============
+ # lock the shared yum cache (when enabled) before any access
+ # by yum, and prior to cleaning it. This prevents simultaneous access from
+ # screwing things up. This can possibly happen, eg. when running multiple
+ # mock instances with --uniqueext=
+ @traceLog(moduleLog)
+ def _yumCachePreYumHook(self):
+ try:
+ fcntl.lockf(self.yumCacheLock.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
+ except IOError, e:
+ oldState = self.state()
+ self.state("Waiting for yumcache lock")
+ fcntl.lockf(self.yumCacheLock.fileno(), fcntl.LOCK_EX)
+ self.state(oldState)
+
+ @traceLog(moduleLog)
+ def _yumCachePostYumHook(self):
+ fcntl.lockf(self.yumCacheLock.fileno(), fcntl.LOCK_UN)
+
+ @traceLog(moduleLog)
+ def _yumCachePreInitHook(self):
+ moduleLog.info("enabled yum cache")
+ mock.util.mkdirIfAbsent(os.path.join(self.rootdir, 'var/cache/yum'))
+ mock.util.mkdirIfAbsent(self.yumSharedCachePath)
+
+ # lock so others dont accidentally use yum cache while we operate on it.
+ self.yumCacheLock = open(os.path.join(self.yumSharedCachePath, "yumcache.lock"), "a+")
+ self._yumCachePreYumHook()
+
+ if self.online:
+ self.state("cleaning yum metadata")
+ for (dirpath, dirnames, filenames) in os.walk(self.yumSharedCachePath):
+ for filename in filenames:
+ fullPath = os.path.join(dirpath, filename)
+ statinfo = os.stat(fullPath)
+ file_age_days = (time.time() - statinfo.st_ctime) / (60 * 60 * 24)
+ # prune repodata so yum redownloads.
+ # prevents certain errors where yum gets stuck due to bad metadata
+ for ext in (".sqllite", ".xml", ".bz2", ".gz"):
+ if filename.endswith(ext) and file_age_days > self.yum_cache_opts['max_metadata_age_days']:
+ os.unlink(fullPath)
+ fullPath = None
+ break
+
+ if fullPath is None: continue
+ if file_age_days > self.yum_cache_opts['max_age_days']:
+ os.unlink(fullPath)
+ continue
+
+ self._yumCachePostYumHook()
+