26
Aug 10
Things that make me feel girly
10
Aug 10
Canonical implementing userbase tracking
23
Jul 10
Singleton pattern in Python
Just came up with a simple pattern for singletons in Python using a class decorator:
def singleton(cls):
instances = {}
def instance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return instance
Little demo:
>>> @singleton ... class Foo(object): ... pass ... >>> f1 = Foo() >>> print id(f1) 3077430124 >>> f2 = Foo() >>> print ...
23
Jul 10
href.be services ported to GAE
The short URL service at http://href.be/ now runs on Google App Engine. It uses the latest version of Django and thanks to the App Engine it uses BigTable as its storage backend.
This migration will surely result in a better availability and responsiveness of the service!
While we ...
22
Jul 10
href.be tools
Just pushed some tools to the Python Package Index to integrate the http://href.be/ short URL service with your Python and/or Django software:
Also, the service API now offers click statistics for your shortened URL’s, so you can keep track of your outgoing links.
In ...
22
Jul 10
Python ternary operation
Python has no ternary operation, or has it? At least not directly, we had a discussion about possible solutions in the #python IRC channel on FreeNode and after some filddling I came up with this hack abusing the Python slicing magic:
class Ternary(object):
'''
Ternary-ish emulation, it looks like C-style ...
13
Jul 10
We're in this together
A song by Nine Inch Nails, called We’re In This Together. It reminds me of current times, so this one is for my lovely fiancé:
I've become impossible Holding on to when When everything seemed to matter more The two of us All used and beaten up Watching ...
08
Jul 10
Python and net-snmp
Some of you may know that i have a 19″ rack at home with some interesting hardware in it. Some of this hardware also provides a couple of hundreds of gigabytes of storage. But that system takes about 3 maybe 4 amps when it’s idling. Taken into account that 1 amp 24/7 costs me about 20 euros per month. So you can imagine that i don’t have all my equipment running 24/7.
Once in a while i use this system to put some files onto it and then i turn it off again. To be able to also do this remote i’ve bought myself an APC PDU (model AP9212) a couple of months ago. Since that time i always had an idea to automate a backup job which would perform the following steps for me:
- Turn on my storage system
- Mount the backup share
- Transfer the backup onto the share
- Unmount the backup share
- Send a shutdown command to my storage system
- Turn of my storage system
The day before yesterday i finally put my hands on this idea and started looking how i could get and set data to and from my PDU using SNMP. A while ago i already figured out the specific OID’s needed for this job.
and
.1.3.6.1.4.1.318.1.1.4.4.2.1.3.1 for the status of the first outlet (change the last digit to the corresponding port)
So i started searching and reading and found that the net-snmp package comes with python bindings. The small example for an snmpget looked simple enough so i started programming. Within the hour i had written a small script that reads the names and statuses of all 8 ports. (see example code at the bottom of this post)
Unfortunately my hopes were up and this was all the easy part and i was stupid enough to think that an snmpset wouldn’t be much harder, ok in the end maybe it wasn’t but getting there…..
Documentation for the net-snmp python bindings isn’t widely available i discovered you pretty much have to rely on the README provided with the net-snmp package. Searching for code examples is a quest without suitable results (it returns a lot of snmpget examples which i didn’t need).
And while trying different ways to get my code working and actually controlling a port on my PDU did take me several hours. I ran into all sorts of errors for example when i used the following piece of code trying to get it to work:
1 2 | infovar = netsnmp.Varbind(".1.3.6.1.4.1.318.1.1.4.4.2.1.3.5", "1") netsnmp.snmpset(infovar, Version = 1, DestHost='192.168.2.3', Community='writecommunity') |
i got this error:
ok so diving into the README once again i changed the first line to:
1 | infovar = netsnmp.Varbind(".1.3.6.1.4.1.318.1.1.4.4.2.1.3.5", "0", "1", "INTEGER") |
now my code actually ran but nothing happened on my PDU… i thought. I started inspecting my network traffic because i was curious what actually was being sent to my PDU. I made a pcap file with tcpdump and inspected it with wireshark and that showed me the response from the PDU:
Ok, so it was clear that somehow snmp couldn’t find this OID and wasn’t able to write a value to it. But how is that possible? i’m certain that my OID is right. So a lot of trying, searching, cursing and more cursing later i started digging in the net-snmp package.
In this package i found a unittest for the python snmp bindings so i’ve decided to enable the snmp daemon on my server and run this unittest and to my big suprise this worked including the snmpset method. And when i dug through the unittest code i found nothing really different from my code.
After careful reading the code over and over again i suddenly realised that they put a value in sysDescription.0 but their varbind looked like this:
1 | netsnmp.Varbind("sysDescription", "0", "a new description") |
and i realised that they split up sysDescription.0 in the varbind call so what if i do the same thing? so i started an snmpwalk to look at the values again and i made my varbind look like this:
1 | netsnmp.Varbind("enterprises", "318.1.1.4.4.2.1.3.5", "1", "INTEGER") |
and when i ran my code again i saw that port 5 which i was testing on suddenly turned on i started cheering because this was the thing i was looking for, my code was working. (i added INTEGER into the call because without it it was still producing an error).
I hope that with this post i save some of you the same trouble i had to undergo. I can now continue writing my backupscript, i can now perform the first and last task now the ones that lie in between
The SNMP Get example (reading the names and statuses of port 1 through
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import netsnmp HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' for i in range(1,9): info = ".1.3.6.1.4.1.318.1.1.4.4.2.1.4.%i" % (i) control = ".1.3.6.1.4.1.318.1.1.4.4.2.1.3.%i" % (i) infovar = netsnmp.Varbind(info) infores = netsnmp.snmpget(infovar, Version = 1, DestHost = '192.168.2.3', Community='readcommunity') controlvar = netsnmp.Varbind(control) controlres = netsnmp.snmpget(controlvar, Version = 1, DestHost = '192.168.2.3', Community='readcommunity') if controlres[0] == '1': print HEADER + infores[0] + ' ... ' + OKGREEN + 'On' + ENDC elif controlres[0] == '2': print HEADER + infores[0] + ' ... ' + OKBLUE + 'Off' + ENDC elif controlres[0] == '3': print HEADER + infores[0] + ' ... ' + WARNING + 'Rebooting' + ENDC else: print HEADER + infores[0] + ' ... ' + FAIL + 'Error' + ENDC |
The SNMP set example (setting port 5 to status On)
1 2 3 4 5 6 7 8 9 10 11 | import netsnmp HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' var = netsnmp.Varbind('enterprises', '318.1.1.4.4.2.1.3.5', '1', 'INTEGER') res = netsnmp.snmpset(var, Version = 1, DestHost='192.168.2.3', Community='writecommunity') |
Use code at your own risk, i only posted it to provide an example of how it can be done. Also the ip address of my PDU and community string have been changed, change to your needs if you want to try it. If you have any questions, comments or compliments please leave a comment below.
07
Jul 10
Blog Live
Hi,
I’ve just installed my new blog, soon i will add some posts with things that i come across and/or keep me busy during my daily life
17
Jun 10