One of my most hated interview questions use to be “How many IPs in this subnet?”

I use to hate this question. I was reading a post on Reddit about some guy that went through the programming interview at Facebook and it made me remember the simple interview question I always hated answering. It always went something like this

How many usable IPs in a /24

Ok that is an easy one.. 256-2=254 not a big deal.. next!

Then they would ask

How many usable IPs in a /28

That is what usually made me say “Networking is not really my strong point” Well got that one wrong.. So I went out to fix this many many years ago. Well there’s an easy step you can do in your head.

All subnets going up are half of the one below it. So your /24 would have 256 IPs in it. So it would go like this

/25 = 128
/26 = 64
/27 = 32
/28 = 16

So there was my answer 16 IPs and 14 are usable. Its really that easy to figure out. Anything between /24 and /32 is easy to figure out if you can easily do the math in your head like that. You can do the oppsite if they give you a /29

/32 = 1
/31 = 2
/30 = 4
/29 = 8

Now there is also a little math formula you can use also.

So back to our question.. If we want to know how many usably IPs in a /28. We would go like

2^(32-28) - 2

Which would be

(2^4) - 2 = 14

That broken down is like saying

(2*2*2*2) - 2 = 14

When you toss exponents in it gets a bit rough but its easier if they tell you.. So how many in a /20

(2^(32-20)) = 4096

We won’t worry about usable in this case because it depends how you will subnet it off.

MongoDB: Remove an arbiter from a replica set

This isn’t really a straight forward task. From what I know in 1.7 there is a command but that is development only. So I’m running 1.6 and to see the config for my replica set I run

rs.conf();

I get the following output

> rs.conf();
{
        "_id" : "core",
        "version" : 3,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "mongo1.domain.com:27017"
                },
                {
                        "_id" : 1,
                        "host" : "mongo2.domain.com"
                },
                {
                        "_id" : 2,
                        "host" : "mgmt1.domain.com",
                        "arbiterOnly" : true
                }
        ]
}

Now I have two members to my replica set plus my arbiter. So I want to remove that so I can add another one. So I run the following

> use admin;
> cfg = rs.conf();
> cfg.members.splice(2,1);
> cfg['version'] = 4
> db.runCommand({replSetReconfig: cfg});

Then it will be removed. You can see my version was at 3 so I upped it to 4 so mongo will know there was a change. Now if I check the config I get the following

> rs.conf()
{
        "_id" : "core",
        "version" : 4,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "mongo1.domain.com:27017"
                },
                {
                        "_id" : 1,
                        "host" : "mongo2.domain.com"
                }
        ]
}

Install Chromium on Fedora

This is an easy one

Create the following file

/etc/yum.repos.d/chromium.repo

With the following contents

[fedora-chromium]
name=Chromium web browser and deps
baseurl=http://repos.fedorapeople.org/repos/spot/chromium/fedora-$releasever/$basearch/
enabled=1
gpgcheck=0

Then run the following

yum update
yum install chromium

Get Django-NonRel working with VirtualEnv

MongoDB is getting a lot of press recently. I stumbled across a pretty interesting project called Django-nonrel. This is an attempt to build non-relational databases right into mongodb. Before you could always use a 3rd party ORM or just use pymongo right in Django but then you were missing out on all the nice apps the community has created. So the goal of this project is to make it so you can keep on using those. Now as of writing this joins are not working but from what I know they are working on it.

So lets start off by creating a virtualenv environment. I will call my project photoblog

virtualenv photoblog

Now lets activate our virtualenv

source ./photoblog/bin/activate

Now we can install Django-nonrel

wget http://bitbucket.org/wkornewald/django-nonrel/get/tip.zip
unzip tip.zip
cd django-nonrel
python setup.py build
python setup.py install

Now lets install pymongo

pip install pymongo

Now lets install the djangotoolbox

wget http://bitbucket.org/wkornewald/djangotoolbox/get/tip.zip
unzip tip.zip
cd djangotoolbox
python setup.py build
python setup.py install

Now we have to download and install the django-mongo-engine

wget --no-check-certificate https://github.com/aparo/django-mongodb-engine/zipball/master
unzip aparo-django-mongodb-engine*
cd aparo-django-mongodb-engine*
python setup.py build
python setup.py install

So now lets create the Django project

cd ~/photoblog
django-admin.py startproject photoblog
cd photoblog

Now the only thing you really have to change to get a basic site up and running is the following file

settings.py

So edit that and find the block that looks like

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': '',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

And you want it to look something like

DATABASES = {
    'default': {
        'ENGINE': 'django_mongodb_engine.mongodb', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'photoblog',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '27017',                      # Set to empty string for default. Not used with sqlite3.
    }
}

Then you want to add the following to your INSTALLED_APPS

djangotoolbox

Now you can sync the db to set it all up!

cd ~/photoblog/photoblog
chmod +x manage.py
./manage.py syncdb

You are all set!

Change get_absolute_url for the user object in Django

I completely overlooked this in the docs. So if you are here you either didn’t look in the docs or overlooked it also.

I was doing something like this

return (user.get_absolute_url(), (), {})

Now that sends the user to

/user/username/

I wanted the user to go to

/u/username/

So in your settings.py file just do this

ABSOLUTE_URL_OVERRIDES = {
    'auth.user': lambda o: "/u/%s/" % o.username,
}

Tether your android phone to Fedora

I just dumped my IPhone for an EVO. I wanted it to tether my laptop. I know i can tether using IPhone if I jailbroke it. Why tether on AT&T’s awful network.

So I wrote a simple script for the EVO (should work on most androup 2.x phones also)

The first thing you want to is enable usb debugging mode on your phone

Settings -> Applications -> Development -> USB Debugging

Now you can download the following file as root

http://zcentric.com/tether.sh

Then run it

sh tether.sh

Then on your phone run the azilink application and start the service. Then you can run

service android-tether start

You should be all nice an tethered to your phone using your USB cable.

WSGI Holygrail run multiple versions of Python on same webserver

One issue hosting providers have is the issue with clients needing to run different version of python. One client might need python 2.4 and others might need 2.5. So in comes uWSGI

So this blog post will go over how to install uWSGI on RedHat 5 and making a uWSGI server for both python 2.4 and 2.5 at the same time for different hosts.

So the first thing you want to do is download the source

wget http://projects.unbit.it/downloads/uwsgi-0.9.6.tar.gz
tar zxfv uwsgi-0.9.6.tar.gz
cd uwsgi-0.9.6

Now make the 2.4 version

make -f Makefile.Py24
mv uwsgi uwsgi24

Now make the 2.5 version

make -f Makefile.Py25
mv uwsgi uwsgi25

Now you have two binaries compiled to run 2.4 and 2.5 for python

So now you run the binaries

./uwsgi -s 127.0.0.1:3031 --pythonpath /tmp/multi/ -w django_wsgi

This will run a uWSGI server for a django app that is in /tmp/multi with a django_wsgi.py file.

You can then run

./uwsgi25 -s 127.0.0.1:3032 --pythonpath /tmp/multi/ -w django_wsgi

At the same time and they play nicely.

My django_wsgi.py file looks like

import os
import sys
sys.path.append('/tmp/multi')
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Gitosis with wildcard support

At OpenSky I wanted a way to put config files into git. I started using gitosis for the git server. This was all great but for each new server I had to add the following

servers/host.domain.com

Now that just stinks if you want to do it for a lot of servers. By default gitosis does not support wildcards. So we can’t use servers/* and anything pushing to git@ip:servers/hostn.domain.com.git would be accepted. I found the following patch online. I then forked gitosis to on GitHub to support this and updated the README file. So you can follow it there.

http://github.com/mzupan/gitosis

Setup DRBD for master/master

At my job at OpenSky we have a common NFS share that is failed over to a slave nfs node if the master dies. It was setup so that the slave would just rsync from the master. This was done to save time. Not that I have some time, I decided to finally setup drbd on the two nodes to keep the files always in sync.

So below are my nodes with hostnames/ips and drive information

Node1
host: nfs1.domain.com
ip: 192.168.1.46
partition: /dev/sdb1

Node2
host: nfs2.domain.com
ip: 192.168.1.47
partition: /dev/sdb1

So once drbd is installed setup the following file

/etc/drbd.conf

To look something like this. You will want to change a few things in red. Put this file on both nodes.

global {
  usage-count yes;
}
common {
  protocol C;
}
resource nfs {
  meta-disk internal;
  device     /dev/drbd1;
  syncer {
    verify-alg sha1;
  }
  net {
    allow-two-primaries;
  }
  on nfs1.domain.com {
    disk       /dev/sdb1;
    address    192.168.1.46:7789;
  }
  on nfs2.domain.com {
    disk       /dev/sdb1;
    address    192.168.1.47:7789;
  }
}

I choose to use protocol C. You can see the following protocols below. Also the on nfs1.domain.com has to match the output of a hostname command

http://www.drbd.org/users-guide/s-replication-protocols.html

Now on both nodes you want to init the drbd partition. Make sure this is a blank partition. It will wipe out everything that is one it. I called my resource nfs. If you changed it the commands will be a bit different based on what name you gave your resource

drbdadm create-md nfs

You should get an output like

initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.
success

Now make sure drbd can be run on startup and start it up now

chkconfig drbd on
service drbd start

Once you start drbd on both nodes it will connect to both. If you just start one and not the other.. the other will wait for the second node to come alive.

You can now make a filesystem. Make sure it is a filesystem for clustering. I recommend ocfs2 but gfs2 also works.

Find the real MongoDB command for pyMongo

I am in the middle of writing a MongoDB plugin for cacti using pymongo and ran into a little issue.

In the Mongo shell this works

> db.stats()
{
        "collections" : 19,
        "objects" : 145971,
        "dataSize" : 64785380,
        "storageSize" : 129544960,
        "numExtents" : 75,
        "indexes" : 69,
        "indexSize" : 25403392,
        "ok" : 1
}

So in pymongo I tried

info = db.command("stats")

Then I got the following traceback

Traceback (most recent call last):
  File "./get_mongodb_stats.py", line 68, in 
    main(sys.argv[1:])
  File "./get_mongodb_stats.py", line 39, in main
    get_stats(host, port)
  File "./get_mongodb_stats.py", line 57, in get_stats
    info = db.command("stats")
  File "/usr/lib/python2.6/site-packages/pymongo/database.py", line 306, in command
    (command, result["errmsg"]))

Then I remembered a nice part about the mongoshell. You can run the command without the () and see the function

> db.stats
function () {
    return this.runCommand({dbstats:1});
}

So you do this in pymongo

info = db.command("dbstats")

« Previous PageNext Page »