]> git.ipfire.org Git - oddments/collecty.git/commitdiff
conntrack: Add graph templates
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 May 2015 11:00:23 +0000 (11:00 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 19 May 2015 11:00:23 +0000 (11:00 +0000)
src/collecty/plugins/base.py
src/collecty/plugins/conntrack.py

index 6a88ae864005603bee7de6647b6db1634a7e69cd..a2c10552fa8a95de863f4f70a667bc5fe2283648 100644 (file)
@@ -204,21 +204,21 @@ class Plugin(threading.Thread):
 
                        return object
 
-       def get_template(self, template_name):
+       def get_template(self, template_name, object_id):
                for template in self.templates:
                        if not template.name == template_name:
                                continue
 
-                       return template(self)
+                       return template(self, object_id)
 
        def generate_graph(self, template_name, object_id="default", **kwargs):
-               template = self.get_template(template_name)
+               template = self.get_template(template_name, object_id=object_id)
                if not template:
                        raise RuntimeError("Could not find template %s" % template_name)
 
                time_start = time.time()
 
-               graph = template.generate_graph(object_id=object_id, **kwargs)
+               graph = template.generate_graph(**kwargs)
 
                duration = time.time() - time_start
                self.log.debug(_("Generated graph %s in %.1fms") \
@@ -406,9 +406,15 @@ class GraphTemplate(object):
        height = GRAPH_DEFAULT_HEIGHT
        width  = GRAPH_DEFAULT_WIDTH
 
-       def __init__(self, plugin):
+       def __init__(self, plugin, object_id):
                self.plugin = plugin
 
+               # Get all required RRD objects
+               self.object_id = object_id
+
+               # Get the main object
+               self.object = self.get_object(self.object_id)
+
        def __repr__(self):
                return "<%s>" % self.__class__.__name__
 
@@ -462,26 +468,29 @@ class GraphTemplate(object):
 
                return args
 
-       def get_object_table(self, object_id):
+       def get_object(self, *args, **kwargs):
+               return self.plugin.get_object(*args, **kwargs)
+
+       def get_object_table(self):
                return {
-                       "file" : self.plugin.get_object(object_id),
+                       "file" : self.object,
                }
 
-       def get_object_files(self, object_id):
+       def get_object_files(self):
                files = {}
 
-               for id, obj in self.get_object_table(object_id).items():
+               for id, obj in self.get_object_table().items():
                        files[id] = obj.file
 
                return files
 
-       def generate_graph(self, object_id, interval=None, **kwargs):
+       def generate_graph(self, interval=None, **kwargs):
                args = self._make_command_line(interval, **kwargs)
 
                self.log.info(_("Generating graph %s") % self)
                self.log.debug("  args: %s" % args)
 
-               object_files = self.get_object_files(object_id)
+               object_files = self.get_object_files()
 
                for item in self.rrd_graph:
                        try:
@@ -489,6 +498,8 @@ class GraphTemplate(object):
                        except TypeError:
                                args.append(item)
 
+                       self.log.debug("  %s" % args[-1])
+
                return self.write_graph(*args)
 
        def write_graph(self, *args):
index 0cef77b4732da3320778df91cdc815697e675b69..cbfece99c3526af35dffce0c9ea0d8252d2667d0 100644 (file)
@@ -23,6 +23,8 @@ import os
 
 import base
 
+from ..i18n import _
+
 CONNTRACK_FILE = "/proc/net/nf_conntrack"
 
 class ConntrackTable(object):
@@ -124,6 +126,265 @@ class ConntrackTable(object):
                                                pass
 
 
+class ConntrackLayer3ProtocolsGraphTemplate(base.GraphTemplate):
+       name = "conntrack-layer3-protocols"
+
+       protocols = ConntrackTable._layer3_protocols
+
+       protocol_colours = {
+               "ipv6"  : "#cc0033",
+               "ipv4"  : "#cccc33",
+       }
+
+       protocol_descriptions = {
+               "ipv6"  : _("IPv6"),
+               "ipv4"  : _("IPv4"),
+               "other" : _("Other"),
+       }
+
+       @property
+       def graph_title(self):
+               return _("Connections by Layer 3 Protocols")
+
+       @property
+       def graph_vertical_label(self):
+               return _("Number of open connections")
+
+       def get_object_table(self, object_id):
+               return {
+                       "file" : self.plugin.get_object("layer3-protocols"),
+               }
+
+       @property
+       def rrd_graph(self):
+               args = []
+
+               for proto in reversed(self.protocols):
+                       i = {
+                               "colour"      : self.protocol_colours.get(proto, "#000000"),
+                               "description" : self.protocol_descriptions.get(proto, proto),
+                               "proto"       : proto,
+                               "type"        : type,
+
+                               "legend_min"  : "%10s\: %%8.0lf" % _("Minimum"),
+                               "legend_max"  : "%10s\: %%8.0lf" % _("Maximum"),
+                               "legend_avg"  : "%10s\: %%8.0lf" % _("Average"),
+                               "legend_cur"  : "%10s\: %%8.0lf" % _("Current"),
+                       }
+
+                       args += [
+                               "DEF:%(proto)s=%%(file)s:%(proto)s:AVERAGE" % i,
+                               "AREA:%(proto)s%(colour)s:%(description)-15s:STACK" % i,
+                               "VDEF:%(proto)s_cur=%(proto)s,LAST" % i,
+                               "GPRINT:%(proto)s_cur:%(legend_cur)s" % i,
+                               "VDEF:%(proto)s_avg=%(proto)s,AVERAGE" % i,
+                               "GPRINT:%(proto)s_avg:%(legend_avg)s" % i,
+                               "VDEF:%(proto)s_min=%(proto)s,MINIMUM" % i,
+                               "GPRINT:%(proto)s_min:%(legend_min)s" % i,
+                               "VDEF:%(proto)s_max=%(proto)s,MAXIMUM" % i,
+                               "GPRINT:%(proto)s_max:%(legend_max)s\\n" % i,
+                       ]
+
+               return args
+
+       @property
+       def rrd_graph_args(self):
+               return [
+                       "--legend-direction=bottomup",
+               ]
+
+
+class ConntrackLayer4ProtocolsGraphTemplate(ConntrackLayer3ProtocolsGraphTemplate):
+       name = "conntrack-layer4-protocols"
+
+       protocol_colours = {
+               "tcp"     : "#336600",
+               "udp"     : "#666633",
+               "icmp"    : "#336666",
+               "igmp"    : "#666699",
+               "udplite" : "#3366cc",
+               "sctp"    : "#6666ff",
+               "dccp"    : "#33cc00",
+       }
+
+       protocol_descriptions = {
+               "tcp"     : _("TCP"),
+               "udp"     : _("UDP"),
+               "icmp"    : _("ICMP"),
+               "igmp"    : _("IGMP"),
+               "udplite" : _("UDP Lite"),
+               "sctp"    : _("SCTP"),
+               "dccp"    : _("DCCP"),
+               "other"   : _("Other"),
+       }
+
+       protocol_sortorder = {
+               "tcp"     : 1,
+               "udp"     : 2,
+               "icmp"    : 3,
+               "igmp"    : 4,
+               "udplite" : 5,
+               "sctp"    : 6,
+               "dccp"    : 7,
+       }
+
+       @property
+       def graph_title(self):
+               return _("Connections by IP Protocols")
+
+       @property
+       def protocols(self):
+               return sorted(ConntrackTable._layer4_protocols,
+                       key=lambda x: self.protocol_sortorder.get(x, 99))
+
+       def get_object_table(self, object_id):
+               return {
+                       "file" : self.plugin.get_object("layer4-protocols"),
+               }
+
+
+
+class ConntrackProtocolWithStatesGraphTemplate(base.GraphTemplate):
+       name = "conntrack-protocol-states"
+
+       lower_limit = 0
+
+       states_colours = {
+               "dccp" : {
+                       "CLOSEREQ"          : "#000000",
+                       "CLOSING"           : "#111111",
+                       "IGNORE"            : "#222222",
+                       "INVALID"           : "#333333",
+                       "NONE"              : "#444444",
+                       "OPEN"              : "#555555",
+                       "PARTOPEN"          : "#666666",
+                       "REQUEST"           : "#777777",
+                       "RESPOND"           : "#888888",
+                       "TIME_WAIT"         : "#999999",
+               },
+               "sctp" : {
+                       "CLOSED"            : "#000000",
+                       "COOKIE_ECHOED"     : "#111111",
+                       "COOKIE_WAIT"       : "#222222",
+                       "ESTABLISHED"       : "#333333",
+                       "NONE"              : "#444444",
+                       "SHUTDOWN_ACK_SENT" : "#555555",
+                       "SHUTDOWN_RECD"     : "#666666",
+                       "SHUTDOWN_SENT"     : "#777777",
+               },
+               "tcp" : {
+                       "CLOSE"             : "#ffffff",
+                       "CLOSE_WAIT"        : "#999999",
+                       "ESTABLISHED"       : "#000000",
+                       "FIN_WAIT"          : "#888888",
+                       "LAST_ACK"          : "#777777",
+                       "NONE"              : "#000000",
+                       "SYN_RECV"          : "#111111",
+                       "SYN_SENT"          : "#222222",
+                       "SYN_SENT2"         : "#333333",
+                       "TIME_WAIT"         : "#444444",
+               },
+       }
+
+       states_descriptions = {
+               "dccp" : {},
+               "sctp" : {},
+               "tcp"  : {},
+       }
+
+       states_sortorder = {
+               "dccp" : {
+                       "CLOSEREQ"          : 0,
+                       "CLOSING"           : 0,
+                       "IGNORE"            : 0,
+                       "INVALID"           : 0,
+                       "NONE"              : 0,
+                       "OPEN"              : 0,
+                       "PARTOPEN"          : 0,
+                       "REQUEST"           : 0,
+                       "RESPOND"           : 0,
+                       "TIME_WAIT"         : 0,
+               },
+               "sctp" : {
+                       "CLOSED"            : 0,
+                       "COOKIE_ECHOED"     : 0,
+                       "COOKIE_WAIT"       : 0,
+                       "ESTABLISHED"       : 0,
+                       "NONE"              : 0,
+                       "SHUTDOWN_ACK_SENT" : 0,
+                       "SHUTDOWN_RECD"     : 0,
+                       "SHUTDOWN_SENT"     : 0,
+               },
+               "tcp" : {
+                       "CLOSE"             : 9,
+                       "CLOSE_WAIT"        : 8,
+                       "ESTABLISHED"       : 1,
+                       "FIN_WAIT"          : 6,
+                       "LAST_ACK"          : 7,
+                       "NONE"              : 10,
+                       "SYN_RECV"          : 2,
+                       "SYN_SENT"          : 3,
+                       "SYN_SENT2"         : 4,
+                       "TIME_WAIT"         : 5,
+               },
+       }
+
+       @property
+       def graph_title(self):
+               return _("Protocol States of all %s connections") % self.protocol.upper()
+
+       @property
+       def graph_vertical_label(self):
+               return _("Number of open connections")
+
+       @property
+       def protocol(self):
+               return self.object.protocol
+
+       @property
+       def states(self):
+               return sorted(ConntrackTable._stateful_layer4_protocols[self.protocol],
+                       key=lambda x: self.states_sortorder[self.protocol].get(x, 99))
+
+       @property
+       def rrd_graph(self):
+               args = []
+
+               for state in reversed(self.states):
+                       i = {
+                               "colour"      : self.states_colours[self.protocol].get(state, "#000000"),
+                               "description" : self.states_descriptions[self.protocol].get(state, state),
+                               "proto"       : self.protocol,
+                               "state"       : state,
+
+                               "legend_min"  : "%10s\: %%8.0lf" % _("Minimum"),
+                               "legend_max"  : "%10s\: %%8.0lf" % _("Maximum"),
+                               "legend_avg"  : "%10s\: %%8.0lf" % _("Average"),
+                               "legend_cur"  : "%10s\: %%8.0lf" % _("Current"),
+                       }
+
+                       args += [
+                               "DEF:%(state)s=%%(file)s:%(state)s:AVERAGE" % i,
+                               "AREA:%(state)s%(colour)s:%(description)-15s:STACK" % i,
+                               "VDEF:%(state)s_cur=%(state)s,LAST" % i,
+                               "GPRINT:%(state)s_cur:%(legend_cur)s" % i,
+                               "VDEF:%(state)s_avg=%(state)s,AVERAGE" % i,
+                               "GPRINT:%(state)s_avg:%(legend_avg)s" % i,
+                               "VDEF:%(state)s_min=%(state)s,MINIMUM" % i,
+                               "GPRINT:%(state)s_min:%(legend_min)s" % i,
+                               "VDEF:%(state)s_max=%(state)s,MAXIMUM" % i,
+                               "GPRINT:%(state)s_max:%(legend_max)s\\n" % i,
+                       ]
+
+               return args
+
+       @property
+       def rrd_graph_args(self):
+               return [
+                       "--legend-direction=bottomup",
+               ]
+
+
 class ConntrackObject(base.Object):
        protocol = None
 
@@ -210,7 +471,11 @@ class ConntrackPlugin(base.Plugin):
        name = "conntrack"
        description = "Conntrack Plugin"
 
-       templates = []
+       templates = [
+               ConntrackLayer3ProtocolsGraphTemplate,
+               ConntrackLayer4ProtocolsGraphTemplate,
+               ConntrackProtocolWithStatesGraphTemplate,
+       ]
 
        @property
        def objects(self):