Bash: Turn a string into an array

I needed to turn a string into an array to loop through it. It is pretty simple

SOLR_CORES="core1,core2,core3"
declare -a CORES
CORES=(`echo $SOLR_CORES | tr ',' ' '`)       

for CORE in ${CORES[@]}
do
    stuff here
done

MySQL to MongoDB Migration Example

There’s a lot of buzz right no for noSQL solutions and one of the big ones is MongoDB. I was lucky enough to be sent to MongoNYC conference a month or so ago and it opened my eyes to why noSQL is the way to go for most web applications. As the web is more and more based on user contributions our databases are getting more writes put into them which doesn’t scale well in MySQL.

So Photoblog was suffering from slow database performance. The only way to solve this problem was scale up the hardware running it. Now that costs a lot of money so my idea was lets switch from MySQL to MongoDB! So below is an example of how I took 2 tables and made them into one collection in MongoDB.

So an example of our two tables in MySQL

members


CREATE TABLE `members` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL DEFAULT '',
  `password` varchar(255) NOT NULL DEFAULT '',
  `email` varchar(60) NOT NULL DEFAULT '',
  KEY `email` (`email`),
  KEY `username_2` (`username`),
)

friends


CREATE TABLE `friends_ng` (
  `userLink` mediumint(8) NOT NULL,
  `friendLink` mediumint(8) NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '0',
  `reason` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `timestamp` int(15) NOT NULL,
  `start` tinyint(1) NOT NULL DEFAULT '0',
  KEY `friendLink` (`friendLink`,`userLink`,`status`),
  KEY `userLink` (`userLink`)
)

Now friends was a bit de-rationalized in the first place that is why i have the start column. I found this to be faster then having it completely rational.

So now the fun part is turning it into a MongoDB document to add to our user collection. For those not up to speed with MongoDB you can think of a collection in MongoDB like a table in MySQL and a document as a row. A document in MongoDB is made up of a json array.

So here is what we want to end up with. This is an example taken from my username document.


{
        "_id" : ObjectId("4c21058b7f8b9acf39020000"),
        "email" : "mike@zcentric.com",
        "friends" : [
                ObjectId("4c21058b7f8b9acf39000000"),
                ObjectId("4c21058b7f8b9acf39030000")
        ],
        "friends_pending" : [ ],
        "password" : ".........",
       "username" : "mikezupan",
}

So there are a few differences here.

  • What are those _id’s?
  • Why add friends and friends_pending?

Well _id’s in MongoDB are like unique values for referencing your document. Think of them as an auto-incrementing primary key in MySQL. Well except they aren’t auto-incremented they are more random.

Friends and friends_pending are now in the user object for easy look ups and they are a reference to the friends _id. My friends_pending is empty since I have no friends pending.

So now on to the fun stuff with pulling out data.

So a common query is list all the friends you have. I decided to do this in 2 queries since its a pretty cheap query for my dataset. There are a lot of ways of making a document better where you can do it in a single query but I like this way.

I will be doing this via the MongoDB shell but its the same for any MongoDB driver.

So lets first pull out the user based on username. Usually I’ll set their _id object in a session so I can pull out the user with that.

var u = db.users.findOne({'username': 'mikezupan'})

Now lets find all the users friends

db.users.find({'_id': {'$in': u['friends']}})

It is as simple as that! Have fun with MongoDB, I know I am in my free time.

MongoDB Nagios plugin created

I have created a MongoDB plugin for Nagios. I also put it in a GitHub project so if you want to make changes you can easily fork the project and push changes right to my project

http://github.com/mzupan/nagios-plugin-mongodb

Simulate network latency

I’ve been creating Nagios plugins for MongoDB and I needed to stimulate some network latency for testing my connect test. I wanted to simulate a 2 second connection lag so I ran the following command

tc qdisc add dev eth0 root netem delay 1000ms

When you are done you can delete it like

tc qdisc del root dev eth0

I am sure there is a better tc command you can run to get better results but this worked.

Setup MongoDB master/slave replication

I am recently getting into MongoDB. Thanks to my company (OpenSky) sending me to MongoNYC event. I am also tasked with setting up infrastructure to run MongoDB. So we are starting off with a simple master/slave MongoDB setup.

I always thought MySQL was easy to setup replication on but MongoDB proves it just gets easier. This will expect you are using the official MongoDB provided RPMs from their repository.

So the first thing we want to do is install the -stable branch on both nodes

yum install mongo-stable-server

Now that you have it installed lets edit the init.d script. As of writing this, they do not make use of a sysconfig script.

/etc/init.d/mongod

Now find the following line

OPTIONS=" -f /etc/mongod.conf"

For the master you want to make it look like

OPTIONS=" -f /etc/mongod.conf --master"

For the slave you want to do this

OPTIONS=" -f /etc/mongod.conf --slave --source 10.0.0.1"

10.0.0.1 is the IP address of the master server.

Now start mongod on both servers and run chkconfig to make sure it loads on restart

chkconfig mongod on
service mongod start

Now on the master run the following command to get into the Mongo Shell

mongo

Now in the mongo shell run

db.runCommand("ismaster");

You should get something like this if everything is setup correctly

> db.runCommand("ismaster");
{ "ismaster" : 1, "msg" : "not paired", "ok" : 1 }

Now lets insert something into the master server. By default you connect to the test database and this is not replicated so you must switch to a new database. In Mongo, you don’t have to create a database, just use it and it will create it.

> use zcentric
switched to db zcentric
> db.users.insert({'username': 'mzupan', 'full_name': 'Mike Zupan'});
> db.users.find({})
{ "_id" : ObjectId("4c05431becb442845873ec05"), "username" : "mzupan", "full_name" : "Mike Zupan" }

Now on the slave run

> use zcentric
switched to db zcentric
> db.users.find({})
{ "_id" : ObjectId("4c05431becb442845873ec05"), "username" : "mzupan", "full_name" : "Mike Zupan" }

So You see it works nicely! Have fun with Mongo.. I am

Django fix for ‘User’ object has no attribute ‘backend

I was trying to auto login a user if I had their user object and was getting this error when I just called something like

login(request, user)

Well this is due to Django wanting to make sure you auth the user first. If you want to bypass this you can just use the following before login

user.backend = 'django.contrib.auth.backends.ModelBackend'

This might not be the best solution but it works

MySQL Database size

I found a nice query on the mysql mailing list for getting the total size of each database.

SELECT table_schema "Data Base Name", sum( data_length + index_length ) / 1024 / 1024 "Data Base Size in MB", sum( data_free )/ 1024 / 1024 "Free Space in MB" FROM information_schema.TABLES GROUP BY table_schema;

Reason #4 on why Django is great

Middleware!

I can’t tell you how great middleware is in Django. It makes life so easy! Here is a good example. Django doesn’t handle ajax errors very good. It prints them to the client. Sure I can use firebug but I mainly use chrome now and don’t like to touch firefox anymore. So I wrote a bit of middleware to only print out errors in all ajax requests if the app was in DEBUG mode.


from django.conf import settings

import traceback

class AjaxErrorMiddleware:
    def process_exception(self, request, exception):
        if request.META.has_key('HTTP_X_REQUESTED_WITH') and settings.DEBUG:
            print traceback.format_exc()

I have added this to my Github project also for all my middleware. You just load it by adding it to your middleware section in your settings.py

Reason #3 on why Django is great

Making custom model fields are a great thing to save a lot of time. If you need a lot of custom validation around your modelforms and don’t want to do a lot of copy and pasting then create a custom model field.

For example, I have the need for a user to input a lot of hostnames and domains and got sick of doing custom validation in each model form I created. So I created a model field for it.

So here it is


class HostnameField(models.CharField):
    def clean(self, value):
        value = super(HostnameField, self).clean(value)

        import re
        regex = re.compile("^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$")
        r = regex.search(string)
        if len(r.groups()) == 0:
            raise models.ValidationError("You need to enter a valid hostname/domain")

        return value

The regex might not be the best, but it seems to cover all the use cases I tried on it.

Install all needed RPMS for a rpmbuild

Ever had this happen?

[mzupan@laptop SPECS]$ rpmbuild -ba php.spec
cat: /usr/include/httpd/.mmn: No such file or directory
error: Failed build dependencies:
        curl-devel >= 7.9 is needed by php-5.2.11-2.fc12.src
        db4-devel is needed by php-5.2.11-2.fc12.src
        gmp-devel is needed by php-5.2.11-2.fc12.src
        expat-devel is needed by php-5.2.11-2.fc12.src
        httpd-devel >= 2.0.46-1 is needed by php-5.2.11-2.fc12.src
        sqlite-devel >= 3.0.0 is needed by php-5.2.11-2.fc12.src
        readline-devel is needed by php-5.2.11-2.fc12.src
        libc-client-devel is needed by php-5.2.11-2.fc12.src
        postgresql-devel is needed by php-5.2.11-2.fc12.src
        unixODBC-devel is needed by php-5.2.11-2.fc12.src
        net-snmp-devel is needed by php-5.2.11-2.fc12.src
        libxslt-devel >= 1.0.18-1 is needed by php-5.2.11-2.fc12.src
        libXpm-devel is needed by php-5.2.11-2.fc12.src
        t1lib-devel is needed by php-5.2.11-2.fc12.src
        libmcrypt-devel is needed by php-5.2.11-2.fc12.src
        mhash-devel is needed by php-5.2.11-2.fc12.src
        libtidy-devel is needed by php-5.2.11-2.fc12.src
        freetds-devel is needed by php-5.2.11-2.fc12.src
        aspell-devel >= 0.50.0 is needed by php-5.2.11-2.fc12.src
        recode-devel is needed by php-5.2.11-2.fc12.src
        libevent-devel >= 1.4.12 is needed by php-5.2.11-2.fc12.src

Well the boring way is doing this

yum -y install libevent-devel recode-devel aspell-devel ...

That can be extremely painful. So lets do this


sudo yum install `rpmbuild -ba php.spec 2>&1 | grep needed | awk {' print $1 '}`

« Previous PageNext Page »