# -*- coding: utf-8 -*-
"""Module for parsing retention.dat file."""
from __future__ import absolute_import
from pynag.Utils import bytes2str
import pynag.Parsers.main
import re
# TODO: Raise more specific errors in this class
from pynag.Parsers.errors import ParserError
class RetentionDat(object):
""" Easy way to parse the content of retention.dat
After calling parse() contents of retention.dat are kept in self.data
Example Usage::
r = retention()
r.parse()
print r
print r.data['info']
"""
def __init__(self, filename=None, cfg_file=None):
""" Initilize a new instance of retention.dat
Args (you only need to provide one of these):
filename: path to your retention.dat file
cfg_file: path to your nagios.cfg file, path to retention.dat will
be looked up in this file
"""
# If filename is not provided, lets try to discover it from
# nagios.cfg
if filename is None:
main_config = pynag.Parsers.main.MainConfig(cfg_file)
filename = main_config.get("state_retention_file")
self.filename = filename
self.data = None
def parse(self):
""" Parses your status.dat file and stores in a dictionary under self.data
Returns:
None
Raises:
:py:class:`ParserError`: if problem arises while reading status.dat
:py:class:`ParserError`: if status.dat is not found
:py:class:`IOError`: if status.dat cannot be read
"""
self.data = {}
status = {} # Holds all attributes of a single item
key = None # if within definition, store everything before =
value = None # if within definition, store everything after =
if not self.filename:
raise ParserError("status.dat file not found")
lines = open(self.filename, 'rb').readlines()
meta_type_begin_pattern = re.compile(r"^[a-zA-Z0-9]+ \{$")
for sequence_no, line in enumerate(lines):
line = bytes2str(line)
line_num = sequence_no + 1
# Cleanup and line skips
line = line.strip()
if line == "":
pass
elif line[0] == "#" or line[0] == ';':
pass
elif meta_type_begin_pattern.match(line):
status = {}
status['meta'] = {}
status['meta']['type'] = line.split("{")[0].strip()
elif line == "}":
# Status definition has finished, lets add it to
# self.data
if status['meta']['type'] not in self.data:
self.data[status['meta']['type']] = []
self.data[status['meta']['type']].append(status)
else:
tmp = line.split("=", 1)
if len(tmp) == 2:
(key, value) = line.split("=", 1)
status[key] = value
elif key == "long_plugin_output":
# special hack for long_output support. We get here if:
# * line does not contain {
# * line does not contain }
# * line does not contain =
# * last line parsed started with long_plugin_output=
status[key] += "\n" + line
else:
raise ParserError("Error on %s:%s: Could not parse line: %s" % (self.filename, line_num, line))
def __setitem__(self, key, item):
self.data[key] = item
def __getitem__(self, key):
return self.data[key]
def __str__(self):
if not self.data:
self.parse()
str_buffer = "# Generated by pynag"
for datatype, datalist in self.data.items():
for item in datalist:
str_buffer += "%s {\n" % datatype
for attr, value in item.items():
str_buffer += "%s=%s\n" % (attr, value)
str_buffer += "}\n"
return str_buffer