-
Notifications
You must be signed in to change notification settings - Fork 12
Replace homecooked cache #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
itkovian
wants to merge
17
commits into
hpcugent:master
Choose a base branch
from
itkovian:replace-homecooked-cache
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
cc22aca
Replace existing cache code with diskcache calls
itkovian 08c2c17
add diskcache as a dependency
itkovian aacd343
fix: headers
itkovian aceccfb
fix: catch corrupted cache file
itkovian a21a63f
fix: revert catch
itkovian 8db2db0
fix: remove cache tree when corrupt
itkovian e27a5f0
fix: no longer able to test for value decoding errors
itkovian 431bdf6
fix: use logging instead of fancylogger
itkovian b6a7c6e
fix: logging
itkovian 389049b
parent b6a7c6eff62c731855b72532c9ab8df3eca21426
itkovian 5c98c91
bump: version to 2.3.0
itkovian 7168c08
fix: remove py2/py3 import
itkovian 2074256
fix: replace is_string with isinstance
itkovian e57a060
fix: log exceptions and reraise
itkovian 749cec9
fix: reraise instead of raising an empty exception
itkovian f815747
fix: indentation
itkovian 4f9a89e
fix: lazy string interpolation
itkovian File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
@author: Luis Fernando Muñoz Mejías (Ghent University) | ||
""" | ||
|
||
import logging | ||
import operator | ||
import os | ||
import pwd | ||
|
@@ -50,12 +51,10 @@ | |
import time | ||
|
||
from vsc.utils.cache import FileCache | ||
from vsc.utils.fancylogger import getLogger | ||
|
||
log = getLogger(__name__) | ||
|
||
NAGIOS_CACHE_DIR = '/var/cache' | ||
NAGIOS_CACHE_FILENAME_TEMPLATE = '%s.nagios.json.gz' | ||
NAGIOS_CACHE_FILENAME_TEMPLATE = '%s.nagios' | ||
|
||
NAGIOS_OK = 'OK' | ||
NAGIOS_WARNING = 'WARNING' | ||
|
@@ -87,7 +86,7 @@ def _real_exit(message, code, metrics=''): | |
metrics = '|%s' % message[1] | ||
if len(msg) > NAGIOS_MAX_MESSAGE_LENGTH: | ||
# log long message but print truncated message | ||
log.info("Nagios report %s: %s%s", exit_text, msg, metrics) | ||
logging.info("Nagios report %s: %s%s", exit_text, msg, metrics) | ||
msg = msg[:NAGIOS_MAX_MESSAGE_LENGTH-3] + '...' | ||
|
||
print("%s %s%s" % (exit_text, msg, metrics)) | ||
|
@@ -151,16 +150,17 @@ def __init__(self, nrange): | |
@param nrange: nrange in [@][start:][end] format. If it is not a string, it is converted to | ||
string and that string should allow conversion to float. | ||
""" | ||
self.log = getLogger(self.__class__.__name__, fname=False) | ||
|
||
if not isinstance(nrange, str): | ||
newnrange = str(nrange) | ||
self.log.debug("nrange %s of type %s, converting to string (%s)", str(nrange), type(nrange), newnrange) | ||
logging.debug("nrange %s of type %s, converting to string (%s)", str(nrange), type(nrange), newnrange) | ||
try: | ||
float(newnrange) | ||
except ValueError: | ||
self.log.raiseException("nrange %s (type %s) is not valid after conversion to string (newnrange %s)" % | ||
(str(nrange), type(nrange), newnrange)) | ||
logging.exception( | ||
"nrange %s (type %s) is not valid after conversion to string (newnrange %s)", | ||
str(nrange), type(nrange), newnrange | ||
) | ||
raise | ||
nrange = newnrange | ||
|
||
self.range_fn = self.parse(nrange) | ||
|
@@ -173,7 +173,7 @@ def parse(self, nrange): | |
r = reg.search(nrange) | ||
if r: | ||
res = r.groupdict() | ||
self.log.debug("parse: nrange %s gave %s", nrange, res) | ||
logging.debug("parse: nrange %s gave %s", nrange, res) | ||
|
||
start_txt = res['start'] | ||
if start_txt is None: | ||
|
@@ -184,26 +184,30 @@ def parse(self, nrange): | |
try: | ||
start = float(start_txt) | ||
except ValueError: | ||
self.log.raiseException("Invalid start txt value %s" % start_txt) | ||
logging.exception("Invalid start txt value %s", start_txt) | ||
raise | ||
|
||
end = res['end'] | ||
if end is not None: | ||
try: | ||
end = float(end) | ||
except ValueError: | ||
self.log.raiseException("Invalid end value %s" % end) | ||
logging.exception("Invalid end value %s", end) | ||
raise | ||
|
||
neg = res['neg'] is not None | ||
self.log.debug("parse: start %s end %s neg %s", start, end, neg) | ||
logging.debug("parse: start %s end %s neg %s", start, end, neg) | ||
else: | ||
self.log.raiseException('parse: invalid nrange %s.' % nrange) | ||
logging.exception('parse: invalid nrange %s.', nrange) | ||
raise | ||
|
||
def range_fn(test): | ||
# test inside nrange? | ||
try: | ||
test = float(test) | ||
except ValueError: | ||
self.log.raiseException("range_fn: can't convert test %s (type %s) to float" % (test, type(test))) | ||
logging.exception("range_fn: can't convert test %s (type %s) to float", test, type(test)) | ||
raise | ||
|
||
start_res = True # default: -inf < test | ||
if start is not None: | ||
|
@@ -219,7 +223,7 @@ def range_fn(test): | |
if neg: | ||
tmp_res = operator.not_(tmp_res) | ||
|
||
self.log.debug("range_fn: test %s start_res %s end_res %s result %s (neg %s)", | ||
logging.debug("range_fn: test %s start_res %s end_res %s result %s (neg %s)", | ||
test, start_res, end_res, tmp_res, neg) | ||
return tmp_res | ||
|
||
|
@@ -261,27 +265,27 @@ def __init__(self, header, filename, threshold, nagios_username="nagios", world_ | |
|
||
self.nagios_username = nagios_username | ||
|
||
self.log = getLogger(self.__class__.__name__, fname=False) | ||
|
||
def report_and_exit(self): | ||
"""Unzips the cache file and reads the JSON data back in, prints the data and exits accordingly. | ||
"""Reads the cache, prints the data and exits accordingly. | ||
|
||
If the cache data is too old (now - cache timestamp > self.threshold), a critical exit is produced. | ||
""" | ||
try: | ||
nagios_cache = FileCache(self.filename, True) | ||
nagios_cache = FileCache(self.filename) | ||
except (IOError, OSError): | ||
self.log.critical("Error opening file %s for reading", self.filename) | ||
unknown_exit("%s nagios gzipped JSON file unavailable (%s)" % (self.header, self.filename)) | ||
logging.critical("Error opening file %s for reading", self.filename) | ||
unknown_exit("%s nagios cache unavailable (%s)" % (self.header, self.filename)) | ||
|
||
(timestamp, ((nagios_exit_code, nagios_exit_string), nagios_message)) = nagios_cache.load('nagios') | ||
(_, nagios_exit_info) = nagios_cache.load('nagios') | ||
|
||
if nagios_exit_info is None: | ||
unknown_exit("%s nagios exit info expired" % self.header) | ||
|
||
((nagios_exit_code, nagios_exit_string), nagios_message) = nagios_exit_info | ||
|
||
print("%s %s" % (nagios_exit_string, nagios_message)) | ||
sys.exit(nagios_exit_code) | ||
|
||
if self.threshold <= 0 or time.time() - timestamp < self.threshold: | ||
self.log.info("Nagios check cache file %s contents delivered: %s", self.filename, nagios_message) | ||
print("%s %s" % (nagios_exit_string, nagios_message)) | ||
sys.exit(nagios_exit_code) | ||
else: | ||
unknown_exit("%s gzipped JSON file too old (timestamp = %s)" % (self.header, time.ctime(timestamp))) | ||
|
||
def cache(self, nagios_exit, nagios_message): | ||
"""Store the result in the cache file with a timestamp. | ||
|
@@ -294,28 +298,38 @@ def cache(self, nagios_exit, nagios_message): | |
""" | ||
try: | ||
nagios_cache = FileCache(self.filename) | ||
nagios_cache.update('nagios', (nagios_exit, nagios_message), 0) # always update | ||
nagios_cache.update('nagios', (nagios_exit, nagios_message), threshold=self.threshold) | ||
nagios_cache.close() | ||
self.log.info("Wrote nagios check cache file %s at about %s", self.filename, time.ctime(time.time())) | ||
logging.info("Wrote nagios check cache file %s at about %s", self.filename, time.ctime(time.time())) | ||
except (IOError, OSError): | ||
# raising an error is ok, since we usually do this as the very last thing in the script | ||
self.log.raiseException("Cannot save to the nagios gzipped JSON file (%s)" % self.filename) | ||
logging.error("Cannot save to the nagios cache (%s)", self.filename) | ||
raise | ||
|
||
try: | ||
p = pwd.getpwnam(self.nagios_username) | ||
if self.world_readable: | ||
os.chmod(self.filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH) | ||
os.chmod( | ||
self.filename, | ||
stat.S_IRUSR | stat.S_IWUSR | | ||
stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | | ||
stat.S_IXUSR | stat.S_IXGRP | ||
) | ||
else: | ||
os.chmod(self.filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP) | ||
os.chmod( | ||
self.filename, | ||
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXUSR | stat.S_IXGRP | ||
) | ||
|
||
# only change owner/group when run as root | ||
if os.geteuid() == 0: | ||
os.chown(self.filename, p.pw_uid, p.pw_gid) | ||
else: | ||
self.log.warn("Not running as root: Cannot chown the nagios check file %s to %s", | ||
logging.warning("Not running as root: Cannot chown the nagios check file %s to %s", | ||
self.filename, self.nagios_username) | ||
except (OSError, FileNotFoundError): | ||
self.log.raiseException("Cannot chown the nagios check file %s to the nagios user" % (self.filename)) | ||
logging.error("Cannot chown the nagios check file %s to the nagios user", self.filename) | ||
raise | ||
|
||
return True | ||
|
||
|
@@ -441,7 +455,7 @@ def __init__(self, **kwargs): | |
self._final = None | ||
self._final_state = None | ||
|
||
self._threshold = 0 | ||
self._threshold = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the implication of this? |
||
self._report_and_exit = False | ||
|
||
self._world_readable = False | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this do if threshold is None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then it will not set an expiration time on the key.