1"""
2Look through ZFS logs to find latest scrub and its output.
3Note that ZFS doesn't normally produce logs in /var/log, so for this to
4work, we must set up a cron job to dump `zpool iostat` into a file (hourly is
5best):
6 `zpool iostat > /var/log/zpool.log && zpool status >> /var/log/zpool.log`
7
8The file gets overwritten every hour, so if more than one scrub occurs
9between logparse runs, it will only get the latest one.
10
11TODO: add feature to specify pools to check in config file
12TODO: set critical value for scrub data repair
13"""
14
15import re
16import sys, traceback
17
18from logparse.formatting import *
19from logparse.util import readlog
20from logparse.config import prefs
21from logparse.load_parsers import Parser
22
23class Zfs(Parser):
24
25 def __init__(self):
26 super().__init__()
27 self.name = "zfs"
28 self.info = "Look through ZFS logs to find latest scrub and its output"
29
30 def parse_log(self):
31
32 logger.debug("Starting zfs section")
33 section = Section("zfs")
34
35 zfslog = readlog(prefs.get("logs", "zfs"))
36
37 logger.debug("Analysing zpool log")
38 pool = re.search('.*---\n(\w*)', zfslog).group(1)
39 scrub = re.search(".* scrub repaired (\d+\s*\w+) in .* with (\d+) "
40 "errors on (\w+)\s+(\w+)\s+(\d+)\s+(\d{1,2}:\d{2}):"
41 "\d+\s+(\d{4})", zfslog)
42 logger.debug("Found groups {0}".format(scrub.groups()))
43 iostat = re.search('.*---\n\w*\s*(\S*)\s*(\S*)\s', zfslog)
44 scrubrepairs = scruberrors = scrubdate = None
45 alloc = iostat.group(1)
46 free = iostat.group(2)
47
48 try:
49 scrubrepairs = scrub.group(1)
50 scruberrors = scrub.group(2)
51 scrubdate = ' '.join(scrub.groups()[2:-1])
52 except Exception as e:
53 logger.debug("Error getting scrub data: " + str(e))
54 traceback.print_exc(limit=2, file=sys.stdout)
55
56 if (scrubdate != None):
57 scrub_data = Data("Scrub of " + pool + " on " + scrubdate)
58 scrub_data.items = [scrubrepairs + " repaired",
59 scruberrors + " errors", alloc + " used", free + " free"]
60 else:
61 scrub_data = Data(pool)
62 scrub_data.items = [alloc + " used", free + " free"]
63
64 section.append_data(scrub_data)
65
66 logger.info("Finished zfs section")
67 return section