[rrd-users] Holt-Winters interactive simulator

Darryl Lewis Lewis.Darryl at abc.net.au
Wed Mar 21 01:42:45 CET 2007


Apart from python (because I don't know it, I'm a shell and perl user), fantastic!

Do you have this somewhere for download? I think the email proggies may have messed it up a bit

-----Original Message-----
From: rrd-users-bounces at lists.oetiker.ch
[mailto:rrd-users-bounces at lists.oetiker.ch]On Behalf Of Sven Ulland
Sent: Wednesday, 21 March 2007 3:31 AM
To: rrd-users at lists.oetiker.ch
Subject: [rrd-users] Holt-Winters interactive simulator


This is a quick GUI hack that you can use to fiddle about with
parameters for RRDtool's built-in aberrant behaviour detection. It is
a hack indeed, but it might be usable for some. It uses python
together with gtk2 and glade, and should work on any recent system
with that software installed. It uses fake time progression to speed
up the graphing and you can change input values in realtime.

The script [1] is simple to modify, and modifications are encouraged.
A bad quality screenshot [2] has been included in case you'd rather
see what it looks like before trying.

Sven


[1] The script.

#!/usr/bin/env python
#
# Author:  Sven Ulland <svengiu at ifig.uio.no> (remove every 'g')
# License: Public domain
#
# This is a quick hack to test and play with the Holt-Winters aberrant
# behaviour detection implementation in RRDtool. It simply reads a user
# input value and updates a given RRD file with that value. The RRD is then
# graphed and displayed on the screen. Since RRDtool currently does not
# support subsecond intervals, we fake time progression by incrementing an
# integer in stead of reading the actual unix time on the system.
#
# To run this program, you need an RRD file. The defaults are set up to
# simulate a HW period of 30 seconds, so the RRD file should reflect this.
# An example:
#   $ rrdtool create sim.rrd \
#     --step 1 \
#     DS:sim:GAUGE:5:0:400 \
#     RRA:AVERAGE:0.5:1:400 \
#     RRA:HWPREDICT:30:0.1:0.1:30
#
# The input value automation is a simple sine generator that fits the sine
# period to the period speficied in the script (default 30 seconds).
#
# Usage is pretty straight-forward. Let the simplator run for a few periods
# with slight noise to have the HW algo adapt to the input signal. Then
# fiddle around with the input level slider or the noise slider to see how
# resistant the adaption is to aberrant behaviour.
#
# This script should work out of the box on any recent OS that supports
# Python 2.4, GTK2, and Python bindings for GTK2 and Glade2. This should do
# the trick on Debian-based Linux distributions:
#
#   # apt-get install python-glade2 python-gtk2
#
# To execute this, simply run the following:
#
#   $ python rrdsim.py
#

import sys
import commands
import math
import random
import zlib
import base64

GRAPH_MIN = 0
GRAPH_MAX = 100
AUTO_MIN = 20
AUTO_MAX = 80
PERIOD = 30.    # seconds
RRDTOOLPATH = "rrdtool"
RRDPATH = "sim.rrd"
GRAPHPATH = "plot.png"
GLADEPATH = "sim.glade"

# You might want to tweak this one, depending on how fast
# your computer is, and how fast you want the graph to move.
# A 100 ms interval would result in 10 updates per second.
TIMER_INTERVAL = 100    # milliseconds

# This is the GTK glade file that defines the user
# interface. This file will be decoded and written to the
# working directory when the script is run. It is simply run
# through base64.b64decode() and then zlib.compress()
GLADE_UI = """
eJztWVtP4zgUfoZf4cnjatsmRTOgqu2IgQxUCy1qA4gnyyQm8da1s7ZT6P76PUkKtMVt09WO2N3
hAeEk37n4nO9cpLa/Pk04mlKlmRQdx6u7DtKGiIhwKWjHEdL52kXtT7XaLzU0kRFtoVwAnmrd/f
an08FJcHflo5iTiNaYMFQ9kJCi0d0o8C+RkxiTthqN4nM9FnJC61LF5XOtWXfrkYmc7v5+e0VB/
uqRRTE1KORE645zZsa3TETy0UEs6jiPxdkDWYTaqZIpVWaGBJmAz1Om2T2nTjdQGW03nr/aoIYZ
ACKjiNCcGAJiHWdGtdMdDk/R+S3SbJLBB6m26JmlYO8s+A3f9vqng1scDK4u/Bv/YrNYeQucSs0
MxP9FA74ajPCJ3w/84WYFkBHCne53wvWWmyqq2Z+kCEsFdES1UXKGH5lJcEoUFaZKOCMaSkUMja
qA9Zil2BA9vicKJyy3UMGzQiolMd1BJs/OHH12+poiIC4+7/UD3B8ML4+3pCpWZMrMrNRwNjy+6
QV3uWBwjm/9UbBZ+EGGmcZS4AlJq4QmUzEV4WzDDTWLBeHL2XJQAoXLqeo4YGpeIRgcTxP8AoFq
Mhhowx5YSHLSYcNyHUGS/Yq8z+iSKNR03UPkHbSabqvpobPLwGlAQYLVMGE8yu3D+U15nn+TT2V
xJvfyqSzNAlm9PG3wRE4kRIPKTFtDYZPRKQmZiJ2uu4h9Bs9vsff2Cr0JEKu8A8uPZfDgJnu22o
2gNhT9I4PQOt3PR96iLYtAQlmcmFeJ5pejLRJrI2XBPhEOlIAb1z9vQc4qI59SEq3E0KbPgmo3y
tjmR8jFGJJhlQXR6G2iLEAKvghLW7FAHxjnFiA8PDsy50FjToTtvLh5ofYUqN20E2KXbG0mtUVg
DaP3Fty2V+XNKCR8zumpzs+YZEY6c4GtvD5YzcxOJb0Gb6TkhqXWwdsTaWYQp1PKK2gKicBFd61
sO1LkEU8Jz6q7W6DzKV0O6Hw4w3yvYovFzOi37LZhszSCyQlWOAtnpaHrq9PjwMcng37Q618Prk
cV1DABy5x1Aq8RINHvmTaTYsK7yEWeC3/w3+rz0tgpwxLC0InB3tLwWWAaXoHtMoDcw9bB0fMAs
vpwnxkDKlJYbzQGzsAt1jpiw1b35jD3xv1SxRtFOSWaVvRnBb2jR15zyaOFxlsme6H52rK/tgHb
wBuasA2+phGXbi5NhZdOvL2fnSQ0HH8rIlc2tTB/MQ/l5s72T3YpX+QPKDc4KbL0Q3oVJ/eUW+1
XaSjAqUxEVHEmql8a2MjoQ9l/hv5Fz/9uWY/XJfx5zQ2hh42rd6DQsGl1D5kIpdBMG2pdjje1fV
iJ86KSar2xpXo2Mo75am9bJRx+Qe1Sugdeq/kOpVs1XGXt2tFrivf/vfR5//GlT0im6b936+vn7
n1sfe+y9UFn2rT2/dwrxZa6+QE7RWHxY534GdeJIvV/e5/wDj/2iXfbJ5YjvvDh9SUc3/zM8Reb
P1vs
"""

try:
        import pygtk
        pygtk.require("2.0")
except:
        # Some distributions come with GTK2, but not pyGTK
        pass
try:
        import gtk
        import gtk.glade
        import gobject
except:
        sys.stderr.write("Error: Install pyGTK or GTKv2.\n")
        sys.exit(1)

def autovalue(timestamp):
        timeoffset = timestamp % PERIOD
        return ( (GRAPH_MAX - GRAPH_MIN)/2 ) + \
                ( (AUTO_MAX - AUTO_MIN)/2 ) * \
                math.sin(timeoffset * (2. / PERIOD * math.pi))

class rrdgui:
        def __init__(self):
                self.vscale_auto_drag = False
                self.value = 0
                self.timestamp = int(commands.getoutput("%s last %s" % \
                                (RRDTOOLPATH, RRDPATH)))

                # Decode the glade UI and write to file.
                try:
                        f = open(GLADEPATH, 'w')
                        f.write(zlib.decompress(base64.b64decode(GLADE_UI)))
                        f.close()
                except IOError:
                        sys.stderr.write("Could not open \"%s\" for writing. Check permissions." % GLADEPATH)
                        sys.exit(1)

                windowname = "window1"
                self.wTree = gtk.glade.XML (GLADEPATH, windowname)
                dic = {
                        "on_window1_graph_destroy": (gtk.main_quit),
                        "on_vscale_auto_button_press_event": \
                                        self.on_vscale_auto_button_press_event,
                        "on_vscale_auto_button_release_event": \
                                        self.on_vscale_auto_button_release_event
                }
                self.wTree.signal_autoconnect (dic)

                # Create a timer that signals every second.
                gobject.timeout_add(TIMER_INTERVAL, self.timer_exec)

                # Set the input vscale to zero.
                self.wTree.get_widget("vscale_auto").set_value(autovalue(self.timestamp))

                return

        #
        # GTK callback functions
        #
        def on_vscale_auto_button_press_event(self, widget, foo):
                self.vscale_auto_drag = True
        def on_vscale_auto_button_release_event(self, widget, foo):
                self.vscale_auto_drag = False

        # Timer signal
        def timer_exec(self):
                self.timestamp += 1     # Fake time progression
                try:
                        if not self.wTree.get_widget("checkbutton_auto").get_active() \
                                        or self.vscale_auto_drag:
                                # Automation disabled or slider is dragged manually.
                                self.value = int(self.wTree.get_widget("vscale_auto").get_value())
                        else:
                                # Automation enabled and slider is inactive.
                                self.value = autovalue(self.timestamp)
                                self.wTree.get_widget("vscale_auto").set_value(self.value)
                except AttributeError:
                        return True

                if self.wTree.get_widget("checkbutton_noise").get_active():
                        # Add noise
                        noise_magnitude = int(self.wTree.get_widget("vscale_noise").get_value())
                        try:
                                self.value += random.randrange(-noise_magnitude, noise_magnitude, 1)
                        except ValueError:
                                pass

                output = commands.getoutput("%s updatev %s %s:%s" % \
                                (RRDTOOLPATH, RRDPATH, self.timestamp, self.value) )
                commands.getstatusoutput(\
                        "%s graph %s " % (RRDTOOLPATH, GRAPHPATH) + \
                        "--end %s --start end-200s " % self.timestamp + \
                        "-w 500 -h 200 " + \
                        "-l %d -u %d -r " % (GRAPH_MIN, GRAPH_MAX) + \
                        "DEF:vsim=%s:sim:AVERAGE " % RRDPATH + \
                        "DEF:pred=%s:sim:HWPREDICT " % RRDPATH + \
                        "DEF:dev=%s:sim:DEVPREDICT " % RRDPATH + \
                        "DEF:season=%s:sim:SEASONAL " % RRDPATH + \
                        "DEF:devseason=%s:sim:DEVSEASONAL " % RRDPATH + \
                        "DEF:fail=%s:sim:FAILURES " % RRDPATH + \
                        "CDEF:dev_lower=pred,dev,2,*,- " + \
                        "CDEF:dev_upper=pred,dev,2,*,+ " + \
                        "TICK:fail#ffccff:1.0:\"Failures\" " + \
                        "LINE1:dev_lower#66ff66:\"Dev\" " + \
                        "LINE1:dev_upper#66ff66 " \
                        "LINE1:vsim#000000 " )

                self.img = self.wTree.get_widget("image_graph")
                self.img.set_from_file(GRAPHPATH)
                self.img.show()

                # Must return True to reset timer.
                return True

def main():
        try:
                f = open(RRDPATH)
                f.close()
        except IOError:
                sys.stderr.write("Could not read RRD file \"%s\"\n" % RRDPATH)
                sys.exit(1)

        app = rrdgui()
        gtk.main()

if __name__ == '__main__':
        main()
#EOF

[2] The bad quality screenshot.
This is a small screenshot of the application, in case you don't have
the appropriate software installed to run it and you're contemplating
whether it's worth the trouble to test it out. To decode the shot,
copy the entire block of text into a file "foo.txt", and run python
from the same directory. In the python shell, run
>>> import base64
>>> open('shot.png','w').write(base64.b64decode(open('foo.txt').read()))
..which will write the screenshot to 'shot.png'.

What you're looking at is a normal RRD graph showing the input value
(black), along with confidence bands (green) and a failure indication
color (light purple). Two sliders control the input value and noise
level, respectively. Two checkbuttons control the sine automation,
and enables/disables noise. The graph display is updated 10 times per
second to simulate time progression.

iVBORw0KGgoAAAANSUhEUgAAAQQAAAB3BAMAAAAX5yPiAAAAMFBMVEVtZFvMgzuYk4++j2
Kxl3zYlU6xrqyY4pDmvZHQzMnV7MzD/sP54Orx6unw8u/9//w3dYQ1AAATZElEQVRo3sVb
XYwb13VerxIlKurCi7UK9CHFlinYLmDLWqwEOA8y6kgJICBrd6tusX1QwE4cOjREsm9+lW
obUF+KEaVMPKpmJsiDBHPB+tHA+sGuUAiwQNoUu2FDhveSIIopKOfOLPaBArXiTM+5984P
JXPJlRfwHc5wzsxw5sz5+e45517OzCyf/maXmZlDJ9fe+waW5eXTJ5bPIQ/PzZw8d/Ikcr
E27XqZL2vvra+tr6+trfOjl9f2cwdY119eX18/B5u1d87N/OjvEokfre2j/csvq7+t/mLt
3fO/+Ld/fHn9vb++fHl9/d2XL//2MjIydTsJ67mTf//OL5+fn1n6B8f5+X5Y2Lp67eI7Pz
j5ryvPKmeX3j2dOXv2B3/2wxNXf6b+99Wj+2RhedU6Of/czNKfOs6rc9O3oxf/qXpVfXfp
4stHLr6xdOLqG9/97pGzf3mt8xdXL35/H7dZev7M8vz8fOP0/PzMM8/rxqtzR48enXKdu7
h8/NyJmbm/nf/294/PPX/o0LcPHTpz/MTfnD5x6Jm5o3Nzq6urE++CLCyfWQIWll5FKawu
zy+trh6dm3aVbVVs+R2XgmOra0exTbgDXDB3aH5peRnlsAy2IH47bcMn4tPhNqtz8MQ5fk
QwMQ9nYOHH9mx4h6Wlpbn5+efm5p6b+daZb6YdP3780LcOweb4TNYwTMMw9MaUK7YeLGIP
9uWOqeNpg9+q0cDNuLXRqNOGTj5oNkpGqUlqMznT2U/zfM/j347rOnx1XMd3XaDjl9E9Vs
exDfYnKiGknp0lpCtYYA6lU6z74XU8E8y02W+OKQbwcGyWsEAKcJJOXukUTCCrzBm/OE7P
tIl6ZMYgJedY70UuBeAGbk6nWr+yMfnFGCGUIQuMjV0JskDZsa5DSO3ZhIlSMEZkt3cjjz
8V2AfO+IOFrOAmUmVjTaGn2/gD/uYOYSAFC2/YYIZJ/5hyOY5b4QnhkxkNGcEHExAxiTGH
TIxZGUoBpXGflCgBTqQt0E43oZSPOHuqweFMc7OBh8A+iYmN0VCSyLEzbkUpGDbLaLpOsL
GSsAXH6XYXCn/4SWVia7VIpdyCRsot0oo1UoHj5RZsCJ6vtMRlFb6W5T4cqzjoEdTUsg1C
S9prYBAATci7mlxcZJYfNM8faSHpAgI43rizY8lHEQnPQlsw3882wBpuZjkuWCgghJsYC8
P9PmQCC1+EJEM12Y4BUqCEaK850haEHqnlP1XzJl5RjkuBe4RZz34AltDIEmELgUnlPCdY
AG5jCw2PIwlSazPPGXquw2DTZvDx2m2nzc+2o4v5guSjLyQ1dAQ0MeOa0WgSdu2twBaIcC
7r6UQ9WShxKXCnbJr1lQZpEj3LcYH7EBw3n5aFyRzFbIEKgDZ08AjS3MpKXKDg1N1Egj2l
LexPCvDGyMLN14AFlALYQhahiVB7VmEXwLvFp1IJd/GzX7IekeVK5c7hclmS5crnaPxcCm
iO14RTGhy1uouLzlin3BcJrToiz742IgUQA7CwBbhASWOFUVCExYI+6KAUMei042Rfi9kC
gqMDHqG/jorQDO4RJg3w/aDMsao+IYVbt2LmaIAU6llwytJWtiSjJiKgIRcCARv17eE+yC
FzOqoVI127cOHzjY88NwrtbHYdcIGbI+UewYI+zprSyCdJoaO2R6SgKv7u7oeC4C+LUnir
AT3+lvAIi3ejPdM4IEV4Xkq14rfqq4Uvdv2PZR+BTxPoSCjRXxcegaZAABeIlTkQe+xrqp
0ckcKdjaK/e2uTmyMhso8AW2jWs4RyaAJTYJ1ZxbmQeFogiJGVSl1LaYVKSFbuqKniZqtZ
LMKB1ueocpRCtocekSVRHmFjvJCwDgAXvD5Nf6aNKKLW/sR/uFmM9ZRGYwVt4f0sj5qsIK
JiRu6lg8CFgdXXtBiHilrjuLARhCzYU2o57KY0jo5ZgwYBg5nLH4Q5DqyBHZNCP6Xe4R6y
y82RIC6UDP2tRom09RUKtpC1MDblQWfu2EsSGIZPjwsesy1b08Jgg/VVtVAxYG9XAkMDu6
n3sxwXcsIWGHNEXKyYByEFf1QKYApq107DzsOPpS0Y9SYPX0lTX5HoyLMsw3Ty3ksHo4i+
HleEqt5c0AJNcJ1jNwW4UCJaXgRuXAn2bIJaXv5gzHGgjUrhP9SQBYLvWwd0XMEIui6c0u
Km4CQKzgXygvDu1qjj75Os36hHuFBu1VMpXdVwv7lJMF5gFOOFHMYL73NoyhpgCgyCe8AF
L3kAuDBotAf1ESn8+oOqoIsYOzLwCIrxAmRj+orII4J4wbG83NfXwyBpu7VE1Ee4nesbd1
Q3tAXuEczEeAFtocnjBZEEYiozzIdZ00jbD9nX6n5Vi7pKr/Omc1sNgYFIdIQ+gjRRCpSb
Y5Ax57xjQfA/kka4+yF76ZrT0fQoBVHfNG+rPLnYvc9jgoaIF9AWbuZ4vGCgKfAOe6xH7E
cKg7TtO/0oYnA76UeBIj7inTVIoYRSgIQusAX+eAa4YIa24H49FsAEQ2Nw1d/4UhEYM6DA
GShCRE2aUeJSQFMg3WSSHAgu9AqchVAKgz/KgRQEuRvLKVews94S2ZTFTaGzUGARLox4Op
YSpiYrdeU2hAypG8Gh+vVS+XZKwMRdiB9k4KZjyIKpjOwjwBTsJOQRoUe0R99sP+SgoGEH
HR60v/RBClYkBcYj6C2IHSGCfisAaCaT+4NQhIgV+qEt2L/y/TvJZMACPKrBAJp0XuLQRb
yAETQvJB0MLoj+oR9KoQ9SKLfrfP/hpg9P0nW7aegrGL5uZSnPpkRXDduccwC4YOsKpAx9
Mwgf7KLrlmmHn/SLHjyqh7ZwzQRboBhB12QEzeui+8OFLpf1drUtzw4WgWr7A9NETAxDaA
2l4Pdd2UmgR2TBIxq8vlDPkli8YJqxPmKS5KlPichdt1WLDYFEO/R91fKkFdgd8aP+wr9j
ch+wUMOEDqWg8cxae71JeR/hUOJ0kgk2tTkOFhoLC8mAhY6qDBJZv6dBF2V1dMFCNyWsoa
/vcikI6oHGKzp2Sdc1jJoa2aCnRNYQFypT4kIjk0ipmQtIVFM3qkr1dkoBQKgktBtV7QbP
HqppAQV1836rVS7Xb/AfN29yXKgTbUgyWF8QsaPBa6n24vS44A6smqLy192GLPpTDXSw3R
5o259+ZlWlFD6ti+9+Oy4FX+PRuk1uEpIBaGqslFgsXmBTKQIEjyxsmzsNiyshZW0XBmmI
WfuF2rYeKqKjS0VYu9wW7ouf17GIDFGT3mysoC3kiYwXZNlvGlzYTpnp9sDqWAAAnQU9mU
i/2El4WaBS1WMdM70t374TSKEopCDqC56N5T3opjSQQlRxM0UWwabDhR0lkc4p+Z7jDBYK
egL8qJDElLCXAEvvObWOLhChY/MQgaVvFT23vGvf4vUF7zofAwIpEGEL2aaoNQVl9GlwYV
vZNlKWDNE893GR2R1NnHSF9vup32+AFG71H4S2wLspvUkyFG0hHJuCIBrrC1Pgws7iTi89
HjVCFvw+FUnEdYhZyw8+usUvGyxidQ+ipmtDcpaVmqLWlDO5KfQOTxcv7MB9EuNzCLujSI
64FDq2yqUAiugv4kEXckqsuOnEyPB4gSvC5CM2Haw7TsaFVo20iBGWJnGAohUWEqDVahmZ
QSASlFUNpEDK5eKd/7mZhoO1FhWKAIWgImQfAQCNHWUmCR6xOAkXOPa741GjXvfjUqgtqM
1P/Ed3P+xvFEUHinEbKEJ3ezr0lHXuEVhroiKMn6LuOMg/yYI/woIbZ6HewWDl4S2/v/l/
aYxkXIcrghqnf/wBAVuQURN5svQ51hy33b370a4d5dfIQhW7iod3fZbEZNsuuLxLhp7yyn
kesgh0FKO1CA7ReMRYXOiCezt7xAt2LThrY+1Rs3sADw/LnlOwNc+1ZVhg3zeABRwxlpk1
mALbWxFu3CH2koJnh1LgirD52d0y/BClAF02T92gs75yqkEYH5sSgwEQQzOMF/ZWhBew4O
6piFgEg6tkgYeUwAI+irPwPZTCNYMX/QzeRdmJ5J5l8EHW385/tRTiLZICSsCW6QOw4GCV
w3Z5KoPJ/b3zPIiPsimQTXw84slMoVwrlBMXWi1lQh5Rux2SWqVV5RBDmmUgVa3cUAA50B
ikIiBwy5UEOlKeRyRjingSF3a6iRvZpOhK94gm6nZI1oASZ4tl3ntDh9EOpfCf3CPel7Gj
qLjtNUi4bfo72/lhVtEnQUc9UkS37YvQ3X9Y5iMEbl9FRQgpXPopzylzOH8hG45TsrHm2E
3ld3byTlrP5ieZY4iO4BKeLc5yFlSbs8DEwJCJiuBVlqjcNTpOOer5tJPI7XRzPaWnmBOy
DLsbkrbp1cXZIuCCV7WJjdVIjgsMcaFJStr1UBFjxyN2rCH0Cl2W39m2PMVL+pNxIZQCzd
X52YefcCnU3YLrB1Lg5sgrbrwSTxG3mUkfx4XhYWAhP1SABS8BHu4tTs4yujEW7LRgYfdD
bgtdO4MsMJFZ3/vzHkVzpBKa0EifwIVBQ/E9Ne8p2YwydVIbwwUAI0E8eCRswXZFGVxAEw
I004JsCsfHeB4x4upV5fbiZ4sXasrCIk8NQG6tifWFajIkWwsFrVIpk7ubrTL8Wr1duLtZ
RlzgLFw6hRW3+usSF9ASOk/gwo7SVYYXEoVaIT99feFTKyKrGscFHkGjFH79+yKXgugjzv
dYMFoL6EjkpJQRRQxryZ3CMD9MOzt5d2pFdGL3ECxgjQtZuG9ru8VbvhyhM+5hN9U4mxH1
BTlvaRQXBp0MCCKTdxS/lp++ALdthaTX4bbAY0egvrypPdjY+BjTBWkLTdIbkqzwiGCoNI
4L3Vn42k7lWcLp5KavL3SsiOxpmuO5Tc91y0PPu/9R+mGx6PG4QNoCqRMjOzrHzRqNlMfO
DNhDCoM4yUcldj8UtuDZ1zc3dn1eZ5UeUWqUyIqMoDGmhFA+roidpy30xEjUpf9lMHmg/5
0Pi7zEwQJboA3SMEui1gQg0U2Ozl/Y8b9+46PnG76QAjKzW/QDRXBcqJMSV4QlTCExggut
mhxcqOyn7hhMcRLHiYp40oR9jBcIQEuzSCpMKOISsgCf14mcQgGMHR7FhZ2nrTvGSC6FzV
AKEDigIqQUXkFbYFR4hIyfR+cvdA9AEdX2YxNJihvIgrAFjB3rrJEVM3qonDwQN8cjX98c
PS4FNyaFh8Wwm7py/gOuiLfQI6JZjDFccPIjc5OeqgzpVU0MNmAte+LIxqbPggj6FEDTTY
8Zsr4g4yYuBS+BvO+ZY08rlKD6EErhgRgMcETsCFJ448fxAjARuODM5gGNnG3rAHAhJEem
VrEgagL9XzpPSqK+QLDkJuIFRcn3IUZQ/ANsj2IsBLM4rpzqEebcOxXLI2hXsZOapqkLSe
2wpi1o8Zb5mu1OdKvUT2LQRK6clxU3bgq9pGMyPj/W5SU4MZOXf2hsH3RGyJ6kvJpEZKsS
3qn1X7KPuIfmSK6cCmpNwimowRWFaQUTE4bFL9sj/AydcI7tV5OS8CIyOj9kLYkLl87jwN
Cl84zPAMbyD48XPJ7ToChkaT74iBkO4cehE0jxkZNkg/nPzHH1hukYmSCzZqR95ZVmUHGT
AxIsmmLcpmJGNd8OQRIowLaYnws0k0eeJOXVNOJBihSO1eqLdmI2tIWStAUx65MXwkRiR8
VkbubiPXHLF/gM5SxgvGQojzxJyqs56NNwSjTwBWTNztpKl0R5BNiCmAfNTYHwS/nEYibL
LrGFicnQwRxjoZ5ASiNkMBdbyDT4IRclVVKLLJng85qgj2CM3Pse4x7BTSHSPOMYyn/lsq
ALC3Ub2qk4MkIGTMrLh4FqWSCacIIZSOGnODZ15ZVwviMVr8FG5qaz8CHhw4byXeWkczZC
yten8heBHVInJlRx76CPIJcCp6RiNjnRQ064Sw8fU0bIiSM9hrIRkgXug0s71CATanGi9+
NDpQ0dlI5T6sWMnsSCk8hSWnCImHDu/Oo7x5QXKaVjeBB2wYYxPYQ6id5dCiiYIR/N6ccS
BzQiGq81/eGF23Q2ceRIt9tNqUdmKev91du5jHI4aTz+34aIj8BN4mRcYYGIaGihvLQpuk
QbnlzCCfFyTrzlsBc+/fxY90im2y1kurmU5zhvvn0sk1hUn/x/RfggAWPtETLmP+EyDB2J
MvA2AHtkoffuGaNJSmfO5GR9oTW74Jh2JmHr6V7vxSSlvX9+O1cwF3vw2wAXXBraXPhaLJ
KDfOowDiWRWFwa+gb/srcuz68Q8rv3lldEfYGwcnn0Xx/srh65RLQ8DhVxptrYKUQuEHOg
wD9IzBx/t7QELNRhK3ABYyw68kcbSqLbyLcL7WwYaCSAcYfGYRjNgEWcOQFmxEwB0HHr+D
MrlNWfe0bM7rJkHd55/A8r8qHR241ahXjhtrCH8ERwLobUwW8DU4Ce8n9X50AKW7gV0MSc
GHQxFuMhtoCGXWkZqNo2jXeDNLw6wodhrKOUEpGmQPqP3jgD+oetGBhKfwMNUivwSgZbNM
dn8T8z+G8Y/O+P8FUqMEN+7dEmXxG71OHxFUHdiMfgX4bgW52ZSTzWlGgviR++UeArEe6L
o8GSDL/ie+KiZHiTr2rwqB8mZv4ftA6DEAE8l1QAAAAASUVORK5CYII=

_______________________________________________
rrd-users mailing list
rrd-users at lists.oetiker.ch
https://lists.oetiker.ch/cgi-bin/listinfo/rrd-users

==============================================================================
The information contained in this email and any attachment is confidential and
may contain legally privileged or copyright material.   It is intended only for
the use of the addressee(s).  If you are not the intended recipient of this
email, you are not permitted to disseminate, distribute or copy this email or
any attachments.  If you have received this message in error, please notify the
sender immediately and delete this email from your system.  The ABC does not
represent or warrant that this transmission is secure or virus free.   Before
opening any attachment you should check for viruses.  The ABC's liability is
limited to resupplying any email and attachments
==============================================================================



More information about the rrd-users mailing list