summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-07-18 14:22:11 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-07-18 14:22:11 -0400
commit827d0a83b8c9148598c23cb550862c0cf50b5a23 (patch)
tree9f8f09b3d8414c98b82e2a960c6d7a4d881c8766 /src
parent20794ebf60a9cc63d762b047ba24a2ad5c6a115f (diff)
downloadbcfg2-827d0a83b8c9148598c23cb550862c0cf50b5a23.tar.gz
bcfg2-827d0a83b8c9148598c23cb550862c0cf50b5a23.tar.bz2
bcfg2-827d0a83b8c9148598c23cb550862c0cf50b5a23.zip
Packages: added lock to yum cache update
Diffstat (limited to 'src')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Packages/Yum.py13
-rwxr-xr-xsrc/sbin/bcfg2-yum-helper32
2 files changed, 45 insertions, 0 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
index 7c950a435..7a90f4f2e 100644
--- a/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
+++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py
@@ -53,11 +53,13 @@ The Yum Backend
import os
import re
import sys
+import time
import copy
import errno
import socket
import logging
import lxml.etree
+from lockfile import FileLock
from subprocess import Popen, PIPE
import Bcfg2.Server.Plugin
# pylint: disable=W0622
@@ -864,6 +866,17 @@ class YumCollection(Collection):
if not self.use_yum:
return Collection.complete(self, packagelist)
+ lock = FileLock(os.path.join(self.cachefile, "lock"))
+ slept = 0
+ while lock.is_locked():
+ if slept > 30:
+ self.logger.warning("Packages: Timeout waiting for yum cache "
+ "to release its lock")
+ return set(), set()
+ self.logger.debug("Packages: Yum cache is locked, waiting...")
+ time.sleep(3)
+ slept += 3
+
if packagelist:
try:
result = self.call_helper(
diff --git a/src/sbin/bcfg2-yum-helper b/src/sbin/bcfg2-yum-helper
index 414606abb..1f22c0ff9 100755
--- a/src/sbin/bcfg2-yum-helper
+++ b/src/sbin/bcfg2-yum-helper
@@ -10,6 +10,8 @@ import sys
import yum
import logging
import Bcfg2.Logger
+from Bcfg2.Compat import wraps
+from lockfile import FileLock, LockTimeout
from optparse import OptionParser
try:
import json
@@ -192,6 +194,27 @@ class DepSolver(YumHelper):
return list(packages), list(unknown)
+def acquire_lock(func):
+ """ decorator for CacheManager methods that gets and release a
+ lock while the method runs """
+ @wraps(func)
+ def inner(self, *args, **kwargs):
+ self.logger.debug("Acquiring lock at %s" % self.lockfile)
+ while not self.lock.i_am_locking():
+ try:
+ self.lock.acquire(timeout=60) # wait up to 60 seconds
+ except LockTimeout:
+ self.lock.break_lock()
+ self.lock.acquire()
+ try:
+ func(self, *args, **kwargs)
+ finally:
+ self.lock.release()
+ self.logger.debug("Released lock at %s" % self.lockfile)
+
+ return inner
+
+
class CacheManager(YumHelper):
""" Yum cache manager. Unlike :class:`DepSolver`, this can write
to the yum cache, and so is used for operations that muck with the
@@ -199,6 +222,14 @@ class CacheManager(YumHelper):
either DepSolver or CacheManager, but for consistency I've put it
here.) """
+ def __init__(self, cfgfile, verbose=1):
+ YumHelper.__init__(self, cfgfile, verbose=verbose)
+ self.lockfile = \
+ os.path.join(os.path.dirname(self.yumbase.conf.config_file_path),
+ "lock")
+ self.lock = FileLock(self.lockfile)
+
+ @acquire_lock
def clean_cache(self):
""" clean the yum cache """
for mdtype in ["Headers", "Packages", "Sqlite", "Metadata",
@@ -211,6 +242,7 @@ class CacheManager(YumHelper):
if not msg.startswith("0 "):
self.logger.info(msg)
+ @acquire_lock
def populate_cache(self):
""" populate the yum cache """
for repo in self.yumbase.repos.findRepos('*'):