Projects

Just for fun

Home About PubKey

Something completely different: SNMP to MySQL

I'm helping to maintain a fleet of about 50 printers in a charity distributed over about 30 locations in the city. Now, they wanted to know how much the individual printers are utilized to get some numbers for an effort to reduce the number of printers.

So, what is more self-evident then using SNMP to query the total page counter on a daily base - or better on an hourly base since the printers are switched off at this or that time and those we at least get sometimes valid data.

Typical monitoring tools like Cacti or Zabbix are very good in drawing nice graphs but not so good in delivering absolute numbers. So I decided to write something on my own: query some devices for some SNMP data points and store the results in a database. Which devices and which data points and which combinations? Everything in the database too.

I looked for a SNMP library, first in Python, then in Java - since I'm quite familiar with these languages - but everything I found was rather complicated to use. Then I looked for something in C# and found ''SnmpSharpNet''. Still not that easy to use but much easier then what I found in Python or Java.

For that reason I started coding the little tool in C#. And what I did is working very well now. Configuration and error-handling is not perfect yet, but it is working. Enough for today.

BTW: I switched developing the code between Microsoft Visual Studio 2013 (on Windows) and Xamarin Studio (on the Mac) and run the tool on Linux. Works without any problem. Very nice!


namespace Snmp2Mysql
{


    class Program
    {
        static void Main(string[] args)
        {
            string dbConnStr = "SERVER=localhost;" +
                               "DATABASE=statsdb;" +
                               "UID=statsuser;" +
                               "PASSWORD=xxx;";
            DatabaseLink dbLink = new DatabaseLink(dbConnStr);
            using (DataCollector dc = dbLink.DataCollector)
            using (DeviceProvider dp = dbLink.DeviceProvider)
            {
                foreach (DeviceTuple dt in dp)
                {
                    // Console.WriteLine("dt: {0}, {1}", dt.DeviceAddress, dt.Community);

                    using (SnmpGetter snmpGetter = new SnmpGetter(dt.Community, dt.DeviceAddress))
                    {
                        using (DeviceDataItemProvider ddip = dt.DeviceDataItemProvider)
                        {
                            foreach (DeviceDataItemTuple ddit in dt.DeviceDataItemProvider)
                            {
                                // Console.WriteLine("  ddit: {0}, {1}", ddit.Id, ddit.Oid);
                                snmpGetter.AddOid(ddit.Id, ddit.Oid);
                            }
                        }

						try 
						{
                        	SnmpGetterResultProvider res = snmpGetter.Exec();
                        	foreach (SnmpGetterResult r in res)
                        	{
								// Console.WriteLine("{0} {1} {2} {3}: {4}", dt.Description, r.Index, r.Oid, r.Type, r.Value);
                            	dc.add((int)r.Index, r.Value);
                        	}
						} 
						catch (SnmpGetterException) {
							// Console.WriteLine ("{0}, no result: {1}", dt.Description, e.Message);
						}
                    }
                }
            }
        }
    }
}


CREATE TABLE `device_t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `address` varchar(45) NOT NULL,
  `community` varchar(45) NOT NULL,
  `period` int(11) NOT NULL,
  `description` varchar(123) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `address_UNIQUE` (`address`)

CREATE TABLE `dataitem_t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `oid` varchar(128) NOT NULL,
  `description` varchar(45) NOT NULL,
  `handling` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `oid_UNIQUE` (`oid`),
  UNIQUE KEY `description_UNIQUE` (`description`)

CREATE TABLE `devicedataitem_t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `device` int(11) NOT NULL,
  `dataitem` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `devicedataitem_uk_idx` (`device`,`dataitem`),
  KEY `device_fk_idx` (`device`),
  KEY `dataitem_fk_idx` (`dataitem`),
  CONSTRAINT `dataitem_fk` FOREIGN KEY (`dataitem`) REFERENCES `dataitem_t` (`id`),
  CONSTRAINT `device_fk` FOREIGN KEY (`device`) REFERENCES `device_t` (`id`)

CREATE TABLE `collecteddata_t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `devicedataitem` int(11) NOT NULL,
  `value` varchar(512) NOT NULL,
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `devicedataitem_fk_idx` (`devicedataitem`),
  CONSTRAINT `devicedataitem_fk` FOREIGN KEY (`devicedataitem`) REFERENCES `devicedataitem_t` (`id`)

And here are the sources: https://gitlab.com/wolutator/Snmp2Mysql.git I'm using GPL code from MySQL (the MySQL Connector for .NET), find it here http://dev.mysql.com/downloads/connector/net/ and the SNMP library from http://www.snmpsharpnet.com. Ah, evaluation of the data? Haven't thought about, maybe using some tricky SQL statement or an Excel pivot table. I'll come back about that.