Skip to content

Commit 389049b

Browse files
committed
parent b6a7c6e
author Andy Georges <[email protected]> 1674744933 +0100 committer Andy Georges <[email protected]> 1677589584 +0100 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEsRL1Gh5rbMUbS7S8e6TNo671utAFAmP9/FAACgkQe6TNo671 utCySA//ZFeuoh5ZG3son8CXs0jZvfQBnxlnP0M3e4HbGi/KBINO95TB8TLjIbQ/ ypvzEiHDeUIUsJn69ef645DGvNkop9H+1IepTh73WRNw/z13KBPjV/X7XoMUk4iZ 7scmeHHbA6FH6KP4hgI5XCslGQKn6obucaCZgDE8e1bZldD8NuJxgQXapJvK0gQ/ xJwarkZQ+4OTKxxRtCyWac33Ftx2z6mCbtdERae5KRuq+8oUOI1SG1q9kp+MGITa 6L5GEED/7fsurfLEo0GRD9dHxlHd7RMO6GziCaIjcDeipFDP2bFM7x5uM0B9Nw2g dxO3gz7WG8YZF9vKtYuN1Sas1yGTLYBB5TjcI6lXhyCtQy2NVAeeAjbjCqr9dbzV n03oA9PdTojGq5dhXPwrkR17fXyoxiND7JI9ibdxL/yaGCZPJN0NgCHyZl5CnhOC o7qR3nhVZoJ9HalVzZnbjJcYjECWBYKYuRZoicclf56gvp6QvC/bDESQBBpe8SbF qIqc7SLQ+gddE8ajFRwiBeWU3UX9t/XPWpEvixvI4dXaZIpFydQGLsYQ3/9OehPv z0IzWp648H5hXfmYk3zpe25QfjGDj23OzwqHlNkr7KdReXck/2HhhDHL2Fw/h4jB CpYOlt05wLZlPnLt35sKomirx6yIOFU5rfkUdTU/0Ris90ZQWtI= =pjru -----END PGP SIGNATURE----- test: fixes and refactoring to work with DiskCache
1 parent b6a7c6e commit 389049b

File tree

7 files changed

+108
-122
lines changed

7 files changed

+108
-122
lines changed

lib/vsc/utils/cache.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@
2929
@author: Andy Georges (Ghent University)
3030
"""
3131
import diskcache as dc
32-
import logging
33-
import shutil
3432
import time
3533

3634

37-
class FileCache(object):
35+
class FileCache(dc.Cache):
3836
"""File cache with a timestamp safety.
3937
4038
Wrapper around diskcache to retain the old API until all usage can be replaced.
@@ -67,17 +65,12 @@ def __init__(self, filename, retain_old=True, raise_unpickable=False):
6765
"""
6866
del raise_unpickable
6967

70-
self.retain_old = retain_old # this is no longer used
68+
super().__init__(filename)
7169

72-
self.filename = filename
73-
try:
74-
self.cache = dc.Cache(filename)
75-
except:
76-
shutil.rmtree(filename)
77-
self.cache = dc.Cache(filename)
70+
self.retain_old = retain_old # this is no longer used
7871

7972
if not retain_old:
80-
self.cache.clear()
73+
self.clear()
8174

8275
def update(self, key, data, threshold=None):
8376
"""Update the given data if the existing data is older than the given threshold.
@@ -90,11 +83,13 @@ def update(self, key, data, threshold=None):
9083
@param data: whatever needs to be stored
9184
@param threshold: time in seconds
9285
"""
93-
old, old_timestamp = self.cache.get(key, default=(None, None))
9486
now = time.time()
87+
stored = self.set(key=key, value=(now, data), expire=threshold)
9588

96-
if not old or now - old_timestamp > threshold:
97-
self.cache[key] = (data, now)
89+
if stored:
90+
return (now, data)
91+
else:
92+
return (None, None)
9893

9994
def load(self, key):
10095
"""Load the stored data for the given key along with the timestamp it was stored.
@@ -103,7 +98,7 @@ def load(self, key):
10398
10499
@returns: (timestamp, data) if there is data for the given key, None otherwise.
105100
"""
106-
return self.cache.get(key, default=None)
101+
return self.get(key, default=(None, None))
107102

108103
@DeprecationWarning
109104
def retain(self):
@@ -115,8 +110,3 @@ def discard(self):
115110
"""Discard non-updated data on close."""
116111
self.retain_old = False
117112

118-
def close(self):
119-
"""Close the cache."""
120-
self.cache.close()
121-
122-
logging.info('closing the file cache at %s', self.filename)

lib/vsc/utils/nagios.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -260,24 +260,26 @@ def __init__(self, header, filename, threshold, nagios_username="nagios", world_
260260
self.nagios_username = nagios_username
261261

262262
def report_and_exit(self):
263-
"""Unzips the cache file and reads the JSON data back in, prints the data and exits accordingly.
263+
"""Reads the cache, prints the data and exits accordingly.
264264
265265
If the cache data is too old (now - cache timestamp > self.threshold), a critical exit is produced.
266266
"""
267267
try:
268-
nagios_cache = FileCache(self.filename, True)
268+
nagios_cache = FileCache(self.filename)
269269
except (IOError, OSError):
270270
logging.critical("Error opening file %s for reading", self.filename)
271-
unknown_exit("%s nagios gzipped JSON file unavailable (%s)" % (self.header, self.filename))
271+
unknown_exit("%s nagios cache unavailable (%s)" % (self.header, self.filename))
272272

273-
(timestamp, ((nagios_exit_code, nagios_exit_string), nagios_message)) = nagios_cache.load('nagios')
273+
(_, nagios_exit_info) = nagios_cache.load('nagios')
274+
275+
if nagios_exit_info is None:
276+
unknown_exit("%s nagios exit info expired" % self.header)
277+
278+
((nagios_exit_code, nagios_exit_string), nagios_message) = nagios_exit_info
279+
280+
print("%s %s" % (nagios_exit_string, nagios_message))
281+
sys.exit(nagios_exit_code)
274282

275-
if self.threshold <= 0 or time.time() - timestamp < self.threshold:
276-
logging.info("Nagios check cache file %s contents delivered: %s", self.filename, nagios_message)
277-
print("%s %s" % (nagios_exit_string, nagios_message))
278-
sys.exit(nagios_exit_code)
279-
else:
280-
unknown_exit("%s gzipped JSON file too old (timestamp = %s)" % (self.header, time.ctime(timestamp)))
281283

282284
def cache(self, nagios_exit, nagios_message):
283285
"""Store the result in the cache file with a timestamp.
@@ -290,29 +292,37 @@ def cache(self, nagios_exit, nagios_message):
290292
"""
291293
try:
292294
nagios_cache = FileCache(self.filename)
293-
nagios_cache.update('nagios', (nagios_exit, nagios_message), 0) # always update
295+
nagios_cache.update('nagios', (nagios_exit, nagios_message), threshold=self.threshold)
294296
nagios_cache.close()
295297
logging.info("Wrote nagios check cache file %s at about %s", self.filename, time.ctime(time.time()))
296298
except (IOError, OSError):
297299
# raising an error is ok, since we usually do this as the very last thing in the script
298-
logging.error("Cannot save to the nagios gzipped JSON file (%s)" % self.filename)
300+
logging.error("Cannot save to the nagios cache (%s)", self.filename)
299301
raise Exception()
300302

301303
try:
302304
p = pwd.getpwnam(self.nagios_username)
303305
if self.world_readable:
304-
os.chmod(self.filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)
306+
os.chmod(
307+
self.filename,
308+
stat.S_IRUSR | stat.S_IWUSR |
309+
stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH |
310+
stat.S_IXUSR | stat.S_IXGRP
311+
)
305312
else:
306-
os.chmod(self.filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP)
313+
os.chmod(
314+
self.filename,
315+
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXUSR | stat.S_IXGRP
316+
)
307317

308318
# only change owner/group when run as root
309319
if os.geteuid() == 0:
310320
os.chown(self.filename, p.pw_uid, p.pw_gid)
311321
else:
312322
logging.warning("Not running as root: Cannot chown the nagios check file %s to %s",
313323
self.filename, self.nagios_username)
314-
except (OSError, FileNotFoundErrorExc):
315-
logging.error("Cannot chown the nagios check file %s to the nagios user" % (self.filename))
324+
except (OSError, FileNotFoundError):
325+
logging.error("Cannot chown the nagios check file %s to the nagios user", self.filename)
316326
raise Exception()
317327

318328
return True
@@ -439,7 +449,7 @@ def __init__(self, **kwargs):
439449
self._final = None
440450
self._final_state = None
441451

442-
self._threshold = 0
452+
self._threshold = None
443453
self._report_and_exit = False
444454

445455
self._world_readable = False

lib/vsc/utils/script_tools.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
from copy import deepcopy
3838

3939
import logging
40-
from vsc.utils import fancylogger
4140
from vsc.utils.availability import proceed_on_ha_service
4241
from vsc.utils.generaloption import SimpleOption
4342
from vsc.utils.lock import lock_or_bork, release_or_bork, LOCKFILE_DIR, LOCKFILE_FILENAME_TEMPLATE
@@ -138,8 +137,6 @@ def __init__(self, options, run_prologue=True, excepthook=None, **kwargs):
138137
else:
139138
sys.excepthook = excepthook
140139

141-
self.log = fancylogger.getLogger()
142-
143140
def prologue(self):
144141
"""Checks the options given for settings and takes appropriate action.
145142
@@ -160,7 +157,7 @@ def prologue(self):
160157

161158
# check for HA host
162159
if self.options.ha and not proceed_on_ha_service(self.options.ha):
163-
self.log.warning("Not running on the target host %s in the HA setup. Stopping.", self.options.ha)
160+
logging.warning("Not running on the target host %s in the HA setup. Stopping.", self.options.ha)
164161
self.nagios_reporter.ok("Not running on the HA master.")
165162
sys.exit(NAGIOS_EXIT_OK)
166163

@@ -169,7 +166,7 @@ def prologue(self):
169166
threshold=self.options.nagios_check_interval_threshold * 2)
170167
lock_or_bork(self.lockfile, self.nagios_reporter)
171168

172-
self.log.info("%s has started", _script_name(sys.argv[0]))
169+
logging.info("%s has started", _script_name(sys.argv[0]))
173170

174171
def _epilogue(self):
175172
if not self.options.disable_locking and not self.options.dry_run:
@@ -184,7 +181,7 @@ def epilogue(self, nagios_message, nagios_thresholds=None):
184181

185182
nagios_thresholds['message'] = nagios_message
186183
self.nagios_reporter._eval_and_exit(**nagios_thresholds)
187-
self.log.info("%s has finished", _script_name(sys.argv[0])) # may not be reached
184+
logging.info("%s has finished", _script_name(sys.argv[0])) # may not be reached
188185

189186
def ok(self, nagios_message):
190187
"""Run at the end of a script and force an OK exit."""
@@ -221,8 +218,8 @@ def critical_exception_handler(self, tp, value, traceback):
221218
222219
This function is meant to be used as sys.excepthook
223220
"""
224-
self.log.exception("unhandled exception detected: %s - %s", tp, value)
225-
self.log.debug("traceback %s", traceback)
221+
logging.exception("unhandled exception detected: %s - %s", tp, value)
222+
logging.debug("traceback %s", traceback)
226223
message = "Script failure: %s - %s" % (tp, value)
227224
self.critical(message)
228225

test/cache.py

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import sys
3939
import random
4040

41+
from pathlib import PurePath
4142
from vsc.install.testing import TestCase
4243
from vsc.utils.cache import FileCache
4344

@@ -61,9 +62,7 @@ def test_contents(self):
6162
data, threshold = get_rand_data()
6263

6364
# create a tempfilename
64-
(handle, filename) = tempfile.mkstemp(dir='/tmp')
65-
os.unlink(filename)
66-
os.close(handle)
65+
filename = PurePath("/tmp") / next(tempfile._get_candidate_names())
6766
cache = FileCache(filename)
6867
for (key, value) in data.items():
6968
cache.update(key, value, threshold)
@@ -72,45 +71,31 @@ def test_contents(self):
7271
for key in data.keys():
7372
info = cache.load(key)
7473
self.assertFalse(info is None)
75-
(ts, value) = info
74+
ts, value = info
7675
self.assertTrue(value == data[key])
7776
self.assertTrue(ts <= now)
7877

7978
def test_save_and_load(self):
8079
"""Check if the loaded data is the same as the saved data."""
8180
# test with random data
8281
data, threshold = get_rand_data()
83-
tempdir = tempfile.mkdtemp()
84-
# create a tempfilename
85-
(handle, filename) = tempfile.mkstemp(dir=tempdir)
86-
os.close(handle)
87-
shutil.rmtree(tempdir)
82+
83+
filename = PurePath("/tmp") / next(tempfile._get_candidate_names())
8884
cache = FileCache(filename)
85+
8986
for (key, value) in data.items():
9087
cache.update(key, value, threshold)
9188
cache.close()
9289

9390
now = time.time()
9491
new_cache = FileCache(filename)
9592
for key in data.keys():
96-
info = cache.load(key)
93+
info = new_cache.load(key)
9794
self.assertTrue(info is not None)
9895
(ts, value) = info
9996
self.assertTrue(value == data[key])
10097
self.assertTrue(ts <= now)
10198
new_cache.close()
10299

103-
shutil.rmtree(tempdir)
104-
105-
def test_corrupt_cache(self):
106-
"""Test to see if we can handle a corrupt cache file"""
107-
tempdir = tempfile.mkdtemp()
108-
109-
# create a bollocks cache file
110-
with open(os.path.join(tempdir, "cache.db", "w")) as f:
111-
f.write("blabla")
112-
113-
# this should clear the cache and create a new one
114-
FileCache(tempdir)
100+
shutil.rmtree(filename)
115101

116-
shutil.rmtree(tempdir)

0 commit comments

Comments
 (0)