Category Archives: Programming

Making VM cloning simpler v2

In my last post I wrote about a procedure that I use to help me to locate VM IP address after creation. You can read about the problem here.

The problem with my solution is that you need to take the networking control away from Libvirt, creating the bridge with hand, configuring dnsmasq, etc. So, I looked at the code and I made libvirt do it for me. Here is the commit.

Basically, this adds an option to network config inside libvirt to setup forwarders for dnsmasq. This allows you to use the last one as the nameserver for your host machine (using 127.0.0.1 in your resolv.conf). Every time a VM boots up, it receives an IP address from dnsmasq and gets its FQDN mapped to its IP address (something like a dnsupdate, but this happens internally because the same daemon provides both services).

You have to setup the domain and the forwarders options to get this working.

This new feature is documented and will appear in a future release of libvirt.

Post to Twitter

Another couple of notes about MongoDB

I forgot to mention another couple of thoughts about MongoDB in my last post. 

  1. MongoDB is fast, but there is no magic. When I first implemented it, I didn’t take care of indexes. I thought: “MongoDB is fast, I’ll setup indexes later.” Big mistake! Without indexes the performance was horrible. I have to rollback my deployment in production. 
  2. Padding. When you insert documents in your database, MongoDB adds them next to each other. If your document grows (for example, if you have an array and you add an element), Mongo must move the document to a new place. Document growing implies two tasks: document movement and indexes update (of course). If you add elements to a lot of documents at once, there is a lot of work, locking, reads that have to wait, etc. To avoid this, there is something called Padding. When Mongo detects that documents tend to grow, it adds extra space to them. So, when you insert a new element, movement won’t be needed. This padding is calculated using the padding factor, which is clearly explained in the official documentation. In my case, to be sure that performance will be good, I force padding after my first bulk import. I did it running “db.runCommand ( { compact: ‘collection’, paddingFactor: 1.1 } )“. That command adds a padding of 10% of each document and compacts the collection (eliminating wasted space).

Have a look at the log file, by default MongoDB writes a lot of interesting information there. For example, if you see update log entries with nmoves:1, that means that the update operation required the document to be moved.

Post to Twitter

A couple of notes from my first steps with MongoDB

I’m starting the process of migration from MySQL to MongoDB. I’ve heard and tried a lot of interesting things and it’s worth the migration. Async writes sounds very interesting for my app and schemaless is fantastic (goodbye “alter table” and migration scripts). I faced two problems, the first one is documented, the second not (or I wasn’t able to find it).

  1. Multi-key indexes only supports one array field. Mongo supports array fields, an special type in the document (record in the SQL world) that holds a list of items of any type. You can use them in an index, but only one at a time.
  2. Writing aggressively to indexed fields kills performance. I have a huge collection with more than 10M of documents (rows in the SQL world). In my applications I iterate over the docs every minute to do some processing and then I write the results to a field of the same doc. This field was part of an index (it’s an array).  I have to remove it from the index. After that, processing time was reduced from more than 1 minute to less than 10 seconds. It looks like the index update locks the table, blocking read operations too. I’m waiting for a confirmation from the mailing list about this.

Post to Twitter

Qué hace alguien que usa software propietario en éste caso?

Hoy estaba programando una aplicación en Python usando Twisted. Tenía un bug que me llevó un rato encontrar porque estaba en la librería, no en mi aplicación. Era un simple error en una función de una clase, la cuál rescribí en una clase derivada, cortando y pegando. Fue simple de resolver, porque tenía el código ahí. Y si no lo tenía? Por eso pregunto que hace un tipo que labura con una librería cerrada en éstos casos. Para encontrar el problema, edité el código del módulo de Python, le puse un par de prints y al rato ya sabía que pasaba. Si hubiera sido cerrada, seguramente estaría todavía vueltas…

Por cierto, ya reporté el bug: http://twistedmatrix.com/trac/ticket/6212

Post to Twitter

My two commits to the Linux Kernel

Four years ago I had nothing to do and started to read some pieces of the kernel code. I read about the BLK, a feature that kernel developers have been trying to remove the last years (I’m not sure if they have finished). My small contribution to that task was this two patches that I sent at the end of 2007.  It’s not a big thing but it required some understanding of the kernel internals or I would have broken something 🙂

commit 1

commit 2

 

BLK or the Big Kernel Lock is a basic locking mechanism introduced in the kernel when SMP support was included. It’s a global lock, lock_kernel() and unlock_kernel() are the functions to use it. This lock is bad because is global, if the networking code wants to protect something calls it. If the filesystem code wants to protect other fs related data calls it too. Two unrelated data structures are protected and two code paths are blocked without any sense. Was an easy implementation in the first years of SMP support, but it had been spreading without control. In the last years, kernel developers have been trying to remove it. New kernel code has independent locks and block the data structures, so unrelated code paths are not blocked.

 

Post to Twitter

About the “_s” in the LDAP library (Python and others)

If you have coded using LDAP libraries you should have noticed about functions that ends with and without “_s”. That “s” means synchronous: the functions return when the operation is finished. The functions without the “s” are asynchronous: the functions return instantaneously without waiting for the end of the operation. The idea behind async functions is that you can call several LDAP functions to do different things and then you can pick the results when you need them,  without blocking the program.

I’m writing this post because you should be careful using these functions. Today I was writing a small Python script to modify some object from a DIT and I lost 30 minutes trying to figure out why the script wasn’t working. I was using the function “bind()” and then “search_s()”. The second didn’t return anything but If I searched using the command line tools with the same parameters I got the objects. What was the problem? I missed the “_s” at the end of “bind()”. I was using the async version so I was calling “search_s()” before the end of the bind operation. 🙁

Post to Twitter

Netlink Echo (ex Netlink ping): Un ejemplo para entender Netlink

Hice un upgrade de mi viejo módulo de Netlink ping. Primero lo renombré a Netlink Echo que encaja mejor a lo que hace. Después le hice unos cambios por que la API de netlink del kernel cambió desde la primera vez que lo armé con kernel 2.4. Está probado con el kernel 2.6.31 y funciona sin problemas.

Lo que publico acá es un módulo de kernel y su respectiva herramienta de userspace. La idea es mandar un mensaje de texto al kernel y que el kernel devuelva el mismo mensaje. Por eso el nombre Netlink Echo.

Netlink es un mecanismo que provee el kernel para comunicarse con él. Distintos subsitemas del kernel (Networkin en general, Udev, SCSI, etc) lo usan para que podamos configurarlos y pasarle parámetros. Netlink es un tipo de socket y se utilizan las mismas funciones que en otro tipos de socket: connect, bind(), send(), recv().

Les dejo el link del ejemplo en GitHUB, espero que les sirva. Más informacion “man 7 netlink”.

Post to Twitter