From 265e39e0384b19553b3b966db844fa60aa6212a3 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Mon, 2 Apr 2012 11:42:52 +0200 Subject: [PATCH] updated shorewall-accounting_ to v1.3 * renamed plugin file from "shorewall_accounting" to "shorewall-accounting_" * CAUTION: rename your symlinks and plugin config section! * added optional SHOREWALL_BIN environment variable * improved labels for rules (don't mask dots) --- ...ewall-accounting => shorewall-accounting_} | 87 +++++++++++++------ 1 file changed, 59 insertions(+), 28 deletions(-) rename plugins/network/{shorewall-accounting => shorewall-accounting_} (56%) diff --git a/plugins/network/shorewall-accounting b/plugins/network/shorewall-accounting_ similarity index 56% rename from plugins/network/shorewall-accounting rename to plugins/network/shorewall-accounting_ index a44e63f4..9f6f9f21 100755 --- a/plugins/network/shorewall-accounting +++ b/plugins/network/shorewall-accounting_ @@ -1,5 +1,5 @@ #!/usr/bin/python -# shorewall_accounting v1.2 +# shorewall_accounting v1.3 # # A munin plugin for tracking traffic as recorded by shorewall accounting rules. # See "man shorewall-accounting" for all possible accounting rules. @@ -7,31 +7,44 @@ # See http://atlee.ca/blog/2006/01/20/munin-shorewall/ for a description of # the original script by Chris AtLee. # -# Copyright 2010 Lars Kruse +# Copyright 2010-2012 Lars Kruse # Copyright 2006 Chris AtLee # # Original publication: http://atlee.ca/blog/2006/01/20/munin-shorewall/ -# Released under the GPL v3 +# Released under the GPL v3 or later # # You can use symlinks of this script according to the following pattern: -# shorewall_accounting_prot: use only rules with a specific protocol -# shorewall_accounting_in: use only rules with a specific input interface -# shorewall_accounting_out: use only rules with a specific output interface -# shorewall_accounting_source: use only rules with a specific source IP -# shorewall_accounting_destination: use only rules with a specific destination IP -# shorewall_accounting_details: use only rules with specific details (e.g. a port) +# shorewall-accounting_prot: use only rules with a specific protocol +# shorewall-accounting_in: use only rules with a specific input interface +# shorewall-accounting_out: use only rules with a specific output interface +# shorewall-accounting_source: use only rules with a specific source IP +# shorewall-accounting_destination: use only rules with a specific destination IP +# shorewall-accounting_details: use only rules with specific details (e.g. a port) # # Here "specific" means: non-default (e.g. a protocol was specified). # Combinations are allowed: -# shorewall_accounting_prot_in_source: use only rules with a specific protocol, input interface and source IP +# shorewall-accounting_prot_in_source: use only rules with a specific protocol, input interface and source IP # +# Environment variables: +# SHOREWALL_BIN - defaults to /sbin/shorewall +# +# Changelog: +# v1.3 - 2012/04/02 +# * renamed plugin file from "shorewall_accounting" to "shorewall-accounting_" +# * CAUTION: rename your symlinks and plugin config section! +# * added optional SHOREWALL_BIN environment variable +# * improved labels for rules (don't mask dots) +# +#%# family=auto +#%# capabilities=autoconf import sys import os import commands import re -PLUGIN_BASE_NAME = "shorewall_accounting" +PLUGIN_BASE_NAME = "shorewall-accounting" +SHOREWALL_BIN = os.environ.get("SHOREWALL_BIN", "/sbin/shorewall") ACCOUNTING_LINE_EXP = re.compile(r"^\s*\d+\s+(\d+)\s+(?P\w+)\s+(?P[\w-]+)\s+(?P[\w*]+)\s+(?P[\w*]+)\s+(?P[\w./+-]+)\s+(?P[\w./+-]+)\s*(?P
.*)\s*$") KEY_ORDER = ["prot", "in", "out", "source", "destination", "details"] FILTER_PATTERNS = { @@ -52,7 +65,7 @@ REPLACE_PATTERNS = { } -def get_accounting_rule_fieldname(regdict): +def get_accounting_rule_fieldname_and_label(regdict): items = [] # filter and clean all requested keys for key in KEY_ORDER: @@ -64,8 +77,10 @@ def get_accounting_rule_fieldname(regdict): result = "_".join(items) # clean the fieldname: http://munin-monitoring.org/wiki/notes_on_datasource_names result = re.sub(r"^[^A-Za-z_]", "_", result) - result = re.sub(r"[^A-Za-z0-9_]", "_", result) - return result + fieldname = re.sub(r"[^A-Za-z0-9_]", "_", result) + # keep dots (for IP addresses) + label = re.sub(r"[^A-Za-z0-9_\.]", "_", result) + return fieldname, label def is_wanted(regdict, filter_list): for item in filter_list: @@ -78,9 +93,11 @@ def is_wanted(regdict, filter_list): return True def get_bytes_by_chain(filter_list): - status, output = commands.getstatusoutput("shorewall -x show accounting") + status, output = commands.getstatusoutput("'%s' -x show accounting" \ + % SHOREWALL_BIN) if status != 0: - raise OSError("Error running command (%s)[%i]: %s" % (trafficCmd, status, output)) + raise OSError("Error running command (%s)[%i]: %s" % (SHOREWALL_BIN, + status, output)) chains = {} for line in output.splitlines(): m = ACCOUNTING_LINE_EXP.match(line) @@ -88,20 +105,22 @@ def get_bytes_by_chain(filter_list): # check if this line was filtered if not is_wanted(m.groupdict(), filter_list): continue - target = get_accounting_rule_fieldname(m.groupdict()) + fieldname, label = get_accounting_rule_fieldname_and_label(m.groupdict()) bytes = int(m.group(1)) - if target in chains: - chains[target] += bytes + if fieldname in chains: + chains[fieldname][1] += bytes else: - chains[target] = bytes + chains[fieldname] = [label, bytes] retval = [] names = chains.keys() names.sort() for name in names: - retval.append((name, chains[name])) + retval.append((name, chains[name][0], chains[name][1])) return retval +# extract the filters from the symlink's name +# (e.g. "shorewall-accounting_in_out_details" -> in, out, details) call_name = os.path.basename(sys.argv[0]) if call_name.startswith(PLUGIN_BASE_NAME): suffix = call_name[len(PLUGIN_BASE_NAME):] @@ -113,19 +132,31 @@ else: if len(sys.argv) > 1: if sys.argv[1] == "autoconf": - print "yes" - sys.exit(0) + status, output = commands.getstatusoutput("'%s' -x show accounting" \ + % SHOREWALL_BIN) + if (status != 0) or not output: + print "no" + else: + print "yes" elif sys.argv[1] == "config": - print "graph_title Shorewall accounting" + if not filter_list: + title_addon = "all" + else: + title_addon = " / ".join(filter_list) + print "graph_title Shorewall accounting: %s" % title_addon print "graph_category network" print "graph_vlabel bits per ${graph_period}" - for chain, bytes in get_bytes_by_chain(filter_list): + for chain, label, bytes in get_bytes_by_chain(filter_list): + label = " ".join([item for item in label.split("_") + if not item.lower().startswith("all")]) + if not label: + label = "all" print "%s.min 0" % chain print "%s.type DERIVE" % chain - print "%s.label %s" % (chain, chain) + print "%s.label %s" % (chain, label) print "%s.cdef %s,8,*" % (chain, chain) - sys.exit(0) + sys.exit(0) -for chain, bytes in get_bytes_by_chain(filter_list): +for chain, label, bytes in get_bytes_by_chain(filter_list): print "%s.value %i" % (chain, bytes)