Pandemonium Illusion

Entries from April 2008

Server Uptime Monitoring with Python

April 21, 2008 · No Comments

We had a black out over the weekend, while I was away, so I decided to add a few more tools to keep me informed. See, when the power goes out the server can’t exactly let me know that it’s down, can it?

Fortunately, I have a slice at SliceHost which never goes down, so I decided to use that to monitor our in-house server. I put together a simple python script to do the job. It simply queries the HTTP Headers of the home page of each of our sites and emails me and sends a TXT to my cellphone if it gets anything other than a 200 status code.

The script itself is run by a cron demon every 15 minutes, but it won’t overwhelm my phone because I have a built-in Message Delay in the script.


#! /usr/bin/env python

import httplib
from urlparse import urlparse
from datetime import datetime, timedelta
import os, platform, time

# Modify your settings here
SITES = ( “http://www.site.com”, ) # Sites to monitor
MAIL_FROM = “admin@site.com”
MAIL_TO = ["Twoway.*********@messaging.nextel.com","ben@site.com"]
MESSAGE_DELAY = 24 * 60 # The time between alerts in minutes
LOCK_FILE = “remote_mon_lock” # Lock file used for alert staggering

def send_alert(status, site):
“”"
Send an email alert to MAIL_TO if the status is not 200
Use a Lock File to ensure that message don’t get sent more
frequently than the MESSAGE_DELAY, to prevent large TXT bills.
“”"
if status != 200:
if not os.path.exists(LOCK_FILE):
old_mod_date = datetime.now() - timedelta(minutes=MESSAGE_DELAY + 1)
old_timestamp = time.mktime(old_mod_date.timetuple())
f = open(LOCK_FILE, ‘w’)
f.close()
os.utime(LOCK_FILE, (old_timestamp, old_timestamp))

mod_date = datetime.fromtimestamp(os.path.getmtime(LOCK_FILE))
next_send_time = mod_date + timedelta(minutes=MESSAGE_DELAY)
if datetime.now() > next_send_time:
import smtplib
s = smtplib.SMTP()
s.connect()
s.sendmail(MAIL_FROM, MAIL_TO, “%s - %s” % (str(status), site))
s.close()
os.utime(LOCK_FILE, None)

for site in SITES:
url = urlparse(site)
error = “”
try:
conn = httplib.HTTPConnection(url[1])
# Use a HEAD request to get the status code
conn.request(”HEAD”, url[2])
status = conn.getresponse()
error = status.status
print “%d : %s : %s” % (status.status, site, datetime.now())
except:
print “Connection Failed : %s : %s” % (site, datetime.now())
error = “Connection Failed”

send_alert(error, site)

Categories: Uncategorized

Nginx SSL passphrase at startup

April 21, 2008 · No Comments

I’m using nginx to serve all my media files and it is also a proxy to my apache server. I’ve been using SSL encryption for specific sections of the site, using nginx’s built in SSL support:

server {

listen 443;
server_name host.com;

access_log /var/log/nginx/register/host.access.log;

# SSL
ssl on;
ssl_certificate /home/jamstooks/ssl_certs/2008_cert/host.com.crt;
ssl_certificate_key /home/jamstooks/ssl_certs/2008_cert/host.com.key;

# Register
location ^~ /register/ {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;

proxy_set_header Host register.host.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

client_max_body_size 10m;
client_body_buffer_size 128k;

proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;

proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}

# Redirect everything else
location / {
rewrite ^(.*) http://www.host.com$1 permanent;
}

}

When I boot up Nginx it requests the passphrase for the encrypted certificate key. This is a huge problem though when there are unexpected shutdowns because the Nginx process won’t restart.

However, the problem is not with Nginx, but with the certificate itself. Because it is encrypted, Nginx can’t use it unless it until it has the pass-phrase. So, the easiest way to solve this is to provide Nginx with a decrypted version of the certificate key. The only issue is that you need to tie down the permissions on the file so that no one can access it at use it to impersonate you.

Apache details the process here:

# Remove the encryption from the RSA private key (while keeping a backup copy of the original file):

$ cp server.key server.key.org
$ openssl rsa -in server.key.org -out server.key

# Make sure the server.key file is only readable by root:

$ chmod 400 server.key

Categories: webdev
Tagged: , , ,

Less is More

April 18, 2008 · No Comments

I’m a firm believer that this saying holds true ALL THE TIME.

But in this case I’m just thinking about the `less` command. It’s just better than `more`.

So, if you’re using Linux and the bash shell put the following in your .bashrc file:

alias more=’less’

Categories: Uncategorized
Tagged: ,

ModelMultipleChoiceField save fails

April 2, 2008 · No Comments

I’ve been banging my head today trying to get a MultipleChoiceField or a ModelMultipleChoiceField to save correctly. I was finding that no matter which widgets I used, or which field types I was using, it was failing. I wouldn’t get any errors, and all the data would be saved except for my ManyToMany relationship.

So, after much ado creating custom widgets and scouring the web for advice, I found that I should have just read the ModelForm Documentation. There it was, under ‘The save() method”:

Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.

I had been using save(commit=false) and hadn’t been using save_m2m(). That’ll teach me to read the documentation!

Categories: django · webdev