While working with Flask‘s SQLAlchemy extension I ran into the case where I wanted to obtain the host I was connected to combined with the username and password.
As I didn’t want to parse the URL I provided earlier to SQLAlchemy (and I didn’t have it available at that part of the code) I looked for a method to obtain it from SQLAlchemy.
It turns out this is not (or poorly) documented, but the Engine object has a attribute called url.
While working on DNSSEC for PCextreme’s Aurora DNS I had to convert a DNSKEY to a DS-record which could be set in the parent zone for proper delegation.
The foundation for Aurora DNS is PowerDNS together with Python 3.
The API for Aurora DNS has to return the DS-records so that a end-user can use these in the parent zone. I had the DNSKEY, but I didn’t have the DS-record so I had to calculate it using Python 3.
I eventually ended up with this Python code which you can find on my Github Gists page.
"""
Generate a DNSSEC DS record based on the incoming DNSKEY record
The DNSKEY can be found using for example 'dig':
$ dig DNSKEY secure.widodh.nl
The output can then be parsed with the following code to generate a DS record
for in the parent DNS zone
Author: Wido den Hollander
Many thanks to this blogpost: https://www.v13.gr/blog/?p=239
"""
import struct
import base64
import hashlib
DOMAIN = 'secure.widodh.nl'
DNSKEY = '257 3 8 AwEAAckZ+lfb0j6aHBW5AanV5A0V0IfF99vAKFZd6+fJfEChpZtjnItWDnJLPa3/LAFec/tUhLZ4jgmzaoEuX3EQQgI1V4kp9SYf8HMlFPP014eO+AnjkYFGLE2uqHPx/Tu7/pO3EyKwTXi5fMadROKuo/mfat5AEIhGjteGGO93DhnOa6kcqj5RHYJBh5OZ/GoZfbeYHK6Muur1T16hHiI12rYGoqJ6ZW5+njYprG6qwp6TZXxJyE7wF1JdD+Zhbjhf0Md4zMEysP22wBLghBaX6eDIBh/7jU7dw1Ob+I42YWk+X4NSiU3sRYPaq1R13JEK4zVqQtL++UVtgRPEbfj5RQ8='
def _calc_keyid(flags, protocol, algorithm, dnskey):
st = struct.pack('!HBB', int(flags), int(protocol), int(algorithm))
st += base64.b64decode(dnskey)
cnt = 0
for idx in range(len(st)):
s = struct.unpack('B', st[idx:idx+1])[0]
if (idx % 2) == 0:
cnt += s << 8
else:
cnt += s
return ((cnt & 0xFFFF) + (cnt >> 16)) & 0xFFFF
def _calc_ds(domain, flags, protocol, algorithm, dnskey):
if domain.endswith('.') is False:
domain += '.'
signature = bytes()
for i in domain.split('.'):
signature += struct.pack('B', len(i)) + i.encode()
signature += struct.pack('!HBB', int(flags), int(protocol), int(algorithm))
signature += base64.b64decode(dnskey)
return {
'sha1': hashlib.sha1(signature).hexdigest().upper(),
'sha256': hashlib.sha256(signature).hexdigest().upper(),
}
def dnskey_to_ds(domain, dnskey):
dnskeylist = dnskey.split(' ', 3)
flags = dnskeylist[0]
protocol = dnskeylist[1]
algorithm = dnskeylist[2]
key = dnskeylist[3].replace(' ', '')
keyid = _calc_keyid(flags, protocol, algorithm, key)
ds = _calc_ds(domain, flags, protocol, algorithm, key)
ret = list()
ret.append(str(keyid) + ' ' + str(algorithm) + ' ' + str(1) + ' '
+ ds['sha1'].lower())
ret.append(str(keyid) + ' ' + str(algorithm) + ' ' + str(2) + ' '
+ ds['sha256'].lower())
return ret
print(dnskey_to_ds(DOMAIN, DNSKEY))
One of the things we monitor of the Ceph cluster is it’s health. This can be OK, WARN or ERR. It speaks for itself that you always want to see OK, but things do go wrong. Disks fail, machines die, kernel panics happen. Stuff goes wrong.
I thought it was a cool idea to buy a used real traffic light which I could install at the office. OK would be green, WARN would be orange/amber and ERR would be red.
2nd hand Trafficlight
Some searching on the internet brought me to trafficlightshop.com. They sell used (Dutch) traffic lights. I bought a Vialis 2230 (The largest on the picture below).
For EUR 75,00 I got my hands on a original trafficlight!
Controlling the lights
When I got the trafficlight it was already equipped with LED lights which work on 230V. A 30cm cable (cut off) was sticking out with 4 wires in it:
Blue: Neutral
Green: Phase/Positive for Green
Yellow: Phase/Positive for Orange/Amber
Red: Phase/Positive for Red
It was easy. All I had to do was buy a add-on board for a Raspberry Pi so I could control the lights.
Solid State Relay
My search for a add-on board brought me to BitWizard.nl, they make all kinds of add-on boards for the Raspberry Pi.
One of them is a SSR (Solid State Relay) board which has 4 outputs. Their wiki explained that it was very simple to control the Relays using Python.
A quick test at my desk at home brought be to a working setup.
Addition components
After writing the code which controls the light it was time to buy some housing where I could install it in.
At Conrad I found the things I needed. A housing, some connectors and some cabling. A overview of my order:
This was needed since I would install it at the office and it needed to be safe. You don’t want somebody to get shocked by 230V. That’s kind of dangerous.
Bringing it together
It was time to start drilling and soldering! In my shed it looked like this:
And a few more pictures of building it. Took me about 3 hours to complete.
At the office
The next day it was time to install it at the office! Some drilling and the result:
Health OK: Green
Health WARN: Amber/Orange
Health ERR: Red
No picture! We can trigger a WARN state in Ceph without service interruptions, but not a ERR state.
The code
The Python code I wrote is all on Github. It’s just some Python code which polls our Ceph dashboard every second. If the status changes it also changes the traffic light.