@@ -151,6 +151,8 @@ EXTRA_OBJECTS=\
LDIRT += $(EXTRA_OBJECTS)
+JSON_SCHEMAS=xfs_healthmon.schema.json
+
#
# Tracing flags:
# -DMEM_DEBUG all zone memory use
@@ -174,7 +176,7 @@ LTLIBS = $(LIBPTHREAD) $(LIBRT)
# don't try linking xfs_repair with a debug libxfs.
DEBUG = -DNDEBUG
-default: ltdepend $(LTLIBRARY) $(EXTRA_OBJECTS)
+default: ltdepend $(LTLIBRARY) $(EXTRA_OBJECTS) $(JSON_SCHEMAS)
%dummy.o: %dummy.cpp
@echo " [CXXD] $@"
@@ -196,14 +198,16 @@ MAKECXXDEP := $(MAKEDEPEND) $(CXXFLAGS)
include $(BUILDRULES)
install: default
- $(INSTALL) -m 755 -d $(PKG_INC_DIR)
+ $(INSTALL) -m 755 -d $(PKG_DATA_DIR)
+ $(INSTALL) -m 644 $(JSON_SCHEMAS) $(PKG_DATA_DIR)
install-headers: $(addsuffix -hdrs, $(PKGHFILES))
%-hdrs:
$(Q)$(LN_S) -f $(CURDIR)/$* $(TOPDIR)/include/xfs/$*
-install-dev: install
+install-dev: default
+ $(INSTALL) -m 755 -d $(PKG_INC_DIR)
$(INSTALL) -m 644 $(PKGHFILES) $(PKG_INC_DIR)
# We need to install the headers before building the dependencies. If we
@@ -129,6 +129,7 @@ xfs_scrubbed: xfs_scrubbed.in $(builddefs)
$(Q)$(SED) -e "s|@sbindir@|$(PKG_SBIN_DIR)|g" \
-e "s|@scrub_svcname@|$(scrub_svcname)|g" \
-e "s|@pkg_version@|$(PKG_VERSION)|g" \
+ -e "s|@pkg_data_dir@|$(PKG_DATA_DIR)|g" \
< $< > $@
$(Q)chmod a+x $@
@@ -18,6 +18,52 @@ import ctypes
import gc
from concurrent.futures import ProcessPoolExecutor
+try:
+ # Not all systems will have this json schema validation libarary,
+ # so we make it optional.
+ import jsonschema
+
+ def init_validation(args):
+ '''Initialize event json validation.'''
+ try:
+ with open(args.event_schema) as fp:
+ schema_js = json.load(fp)
+ except Exception as e:
+ print(f"{args.event_schema}: {e}", file = sys.stderr)
+ return
+
+ try:
+ vcls = jsonschema.validators.validator_for(schema_js)
+ vcls.check_schema(schema_js)
+ validator = vcls(schema_js)
+ except jsonschema.exceptions.SchemaError as e:
+ print(f"{args.event_schema}: invalid event data, {e.message}",
+ file = sys.stderr)
+ return
+ except Exception as e:
+ print(f"{args.event_schema}: {e}", file = sys.stderr)
+ return
+
+ def v(i):
+ e = jsonschema.exceptions.best_match(validator.iter_errors(i))
+ if e:
+ print(f"{printf_prefix}: {e.message}",
+ file = sys.stderr)
+ return False
+ return True
+
+ return v
+
+except:
+ def init_validation(args):
+ if args.require_validation:
+ print("JSON schema validation not available.",
+ file = sys.stderr)
+ return
+
+ return lambda instance: True
+
+validator_fn = None
debug = False
log = False
everything = False
@@ -177,6 +223,12 @@ def handle_event(event):
global log
+ # Ignore any event that doesn't pass our schema. This program must
+ # not try to handle a newer kernel that say things that it is not
+ # prepared to handle.
+ if not validator_fn(event):
+ return
+
stringify_timestamp(event)
if log:
log_event(event)
@@ -225,6 +277,7 @@ def main():
global printf_prefix
global everything
global debug_fast
+ global validator_fn
parser = argparse.ArgumentParser( \
description = "XFS filesystem health monitoring demon.")
@@ -240,6 +293,11 @@ def main():
help = 'XFS filesystem mountpoint to target.')
parser.add_argument('--debug-fast', action = 'store_true', \
help = argparse.SUPPRESS)
+ parser.add_argument('--require-validation', action = 'store_true', \
+ help = argparse.SUPPRESS)
+ parser.add_argument('--event-schema', type = str, \
+ default = '@pkg_data_dir@/xfs_healthmon.schema.json', \
+ help = argparse.SUPPRESS)
args = parser.parse_args()
if args.V:
@@ -250,6 +308,10 @@ def main():
parser.error("the following arguments are required: mountpoint")
return 1
+ validator_fn = init_validation(args)
+ if not validator_fn:
+ return 1
+
if args.debug:
debug = True
if args.log: