Latest Publications

Language guessing game

I just wrote this last night. 10 points for the person who guesses which language it is. 20 if you can tell me what the result of these statements will be :)

VARIABLE found
: prime
    DUP 2 < IF
        DROP
        FALSE
        EXIT
    THEN
    DUP 4 < IF
        DROP
        TRUE
        EXIT
    THEN
    FALSE found !
    DUP 1 - 2 DO
        DUP I MOD NOT IF
            TRUE found !
        THEN
    LOOP
    DROP
    found @ NOT
;
VARIABLE current
: primes
    1 current !
    BEGIN
    DUP 0 > WHILE
        BEGIN
        current @ prime NOT WHILE
            1 current +!
        REPEAT
        current @
        SWAP
        1 -
        1 current +!
    REPEAT
    DROP
;
10 primes

Stop using mono!

Seriously, why are people still using mono? It’s hopeless, horrible and completely obsolete, given the alternatives that currently exist. Its successor, stereo, has been around for ages and even surround sound is not really a new invention. Good old mother nature has been doing multi-channel surround for millions of years. So please, for the love of all that’s holy, don’t inflict mono on your ears!

SSL pricing madness

All *.ubuntu-nl.org pages are reachable via https. This currently uses a self-signed CA certificate, signing the wildcard certificate (and some others as well). This is of course far from optimal, since all modern browsers warn that they don’t recognize the CA.

So how to solve this? Buy a wildcard certificate. Walking around in a bad neighbourhood and getting mugged repeatedly is probably cheaper. SSL certificate providers like to charge you through the nose for a wildcard certificate, and that’s definitely something Ubuntu NL or myself cannot afford at the moment. The cheapest wildcard I could find was godaddy at $180 a year. All the others charge between $500 and $1000 a year. Sigh.

The internet is broken!

Yesterday I used that phrase for the first time as explanation for a downtime problem. Looks silly for a professional sysadmin, but I can defend it :) Customers N and M, connecting to telco V had problems connecting to our service O, reachable via telco T. The route between V and T has AS path V-AT-AB-T and there were routing issues between AT and AB, making O unreachable for N and M. So for all intents and purposes: the internet was broken!

Now this kind of thing of course happens all the time on the internet, but this time it was funny because (freely quoting my colleague): “some people at N were running around like headless chickens”. I don’t know if they already have an explanation from their telco, but I guess not given that V is notoriously bad at these things. It took us about 20 minutes to get an answer from T, that’s pretty decent for a telco, given that communication went via a ticketing system and an outage like this causes more customers to call/mail/file a ticket.

Traincoding: making functions conditionally unavailable

In one of my projects, the codebase is shared between several instances. Some administrative code really should not be available in some read-only instances, such as the save() method on django objects, or some of the view functions. Of course it’s possible to write checks in each function or a decorator that does these checks, but I prefer to go one step further and make the code object unavailable, like what #ifdef in C does. Here is a simple decorator that does this:

def only_if(cond, callable=None):
    """Make a function conditionally unavailable by simply discarding its code object
       and returning another one that raises a NotImplementedError. Allow to
       override this callable with another one or an exception class."""
    def inner_decorator(f):
        # We need to return a callable, so here's a minimal one that raises NotImplementedError
        def default_callable(*args, **kwargs):
            if callable:
                raise callable
            raise NotImplementedError("Function %s is not available" % f.__name__)
        if cond:
            return f
        if callable and not (isinstance(callable, type) and issubclass(callable, Exception)):
            return callable
        return default_callable
    return inner_decorator

# Create another decorator that raises a 404 when cond evaluates to True
from django.http import Http404
raise_404_if = lambda cond: only_if(not cond, Http404)

# Examples:
some_condition = True

@only_if(some_condition)
def foo():
    print "foo called!"

@only_if(not some_condition)
def bar():
    # This will never be run
    print "bar called!"

@raise_404_if(True)
def baz():
    # This will never be run
    print "baz called!"

# This will print "foo called!"
foo()
# This will see the exception
try:
    bar()
except NotImplementedError:
    print "Apparently bar() does not exist"
# This will raise django.http.Http404
baz()

Django {% url %} tag with hostname

The Django {% url %} tag always gives you urls that only work on the same host. Not good enough for me, as parts of my project only work on certain hosts. The logic behind {% url %} can still create the correct path though, so why not reuse it?

Here’s a modified {% url %} called {% hosturl %}, that allows you to specify a base path. Usage:

{% hosturl http://other.host/other-path/ my.view.name arg1 arg2 %}

How to become an Ubuntu member, the easy way

I joined the Ubuntu community in 2004, shortly before the first version was released. Was co-founder of the dutch locoteam in that same year and became member in 2005. Since then I’ve been on many meetings of the community council, as a spectator and later as their secretary. I am currently part of the EMEA membership board, which is responsible for approving Ubuntu members in that region.

What I want to say is: I know what the hell I am talking about here, and if you want to become Ubuntu member, it’s good to read this page and listen to what I am saying :) Too many people show up to our meetings ill-prepared and that costs a lot of our valuable volunteer time. Yes, surprise, the membership boards are volunteers, like most of the Ubuntu community. They have become Ubuntu members by following this same procedure.

With that message out of the way, here’s the highway to Ubuntu membership. Just cruise along, try not to speed and watch out for any weird community managers who fancy waterfowl.

Update 2009-05-13: Emphasize the importance of working within a team

Step zero: learn what Ubuntu means

Ubuntu is not just a buch of software on a cd and some servers. The most important bit about the Ubuntu project is its unique and huge community. One of the many unique things (well, not unique anymore as more and more free software projects are adopting this) about the Ubuntu community is its code of conduct. Whenever you participate in the Ubuntu community, you are expected to follow this code which basically says: be respectful to each other. Read the code, sign it with GPG (manual) and become an ubuntero. In all the steps that follow below, you should always keep this all-important step in mind. Ubuntu is a community where everyone is welcome and where we all collaborate to make Ubuntu and its community better.

Step one: contribute to Ubuntu and its community

This is the easy bit. It will take more time than any of the other steps, but the beuaty is: you can do whatever you want! There are a lot of ways you can contribute to Ubuntu. Everybody can guess that it is possible to write code to help out the project, but that’s just one of the many ways. Here are some good ones, that I think should be done by more people:

  • Translate. Unless your native language is english, there will always be some things in Ubuntu that are not translated. If your english is good and you are not afraid of technical terms, translate some untranslated software and send your translations to its owner and/or the Ubuntu project. You will help many people near you and far away who do not speak english very well and want to use Ubuntu in their own language.
  • Support. Without users there will be no Ubuntu. Even though I like to think Ubuntu is the easiest-to-use operating system, people still need help with it. Hell, even if it really is the easiest to use operating system people will need help. Computers are just annoying things that never do exactly what you want. So help people and make them happy Ubuntu users. There are forums, mailinglists, irc channels, social network groups and most important: local events all over the world where new Ubuntu users meet experienced once and information and experience is shared.
  • Advocacy. Let people know Ubuntu exists. Explain its benefits, but don’t forget to tell about its downsides. `Sell’ Ubuntu as an alternative to proprietary software, explain about the benefits of open source and free software. Awareness is half the battle, when you can convince someone to give Ubuntu an honest try you’re almost there. Tell them about the warm and welcoming community and make that community grow!

Of course there are a lot of other ways (really, read that page too) to contribute to Ubuntu. As I said: do whatever you want to do and can do to make the Ubuntu community a happier place. But don’t go off and do things on your own, make sure you work with the rest of the community. The Ubuntu community is not just a bunch of people each doing their own thing, there are many teams focusing on all kinds of things. When you figure out what you want to do, find the team you can join and work with them. If there is no team yet for what you want (for instance a new LoCo team), make sure you work with related teams to get this set up. Other members are more than willing to get you started and make you feel right at home in our community.

So I lied a bit, you cannot really do whatever you want. But you didn’t really expect that either, did you? As long as you work with the community and for the community, you still have an awful lot of freedom though. For me, it is pretty close to doing exactly what I want and for most people it is not far away from that either.

Step two: documentation

Ok, this is the important one, well it is for me and my colleagues of the membership boards. You will probably not like this step but this is just something you must go through. It’s not as fun as a toothache, but less painful than a root canal. This is the bit that many people get wrong, so pay close attention and you’ll get it right. This makes the difference between being accepted in a 5-minute meeting and being rejected twice even though you do an awesome job.

By the way, did I say this is the important part? Good!

Whatever you do, document it! This is especially true for offline things that do not log themselves (such as forum posts, wiki edits and packaging work), but no less important for people who exclusively do things like editing those wiki pages. When you apply for Ubuntu membership, there are between four and eight people who will decide whether your actions so far have been a sustained and significant contribution to the Ubuntu community. The easier you make their job, the quicker you get accepted.

You will need to tell us about yourself. You do this by creating a page for yourself on the Ubuntu wiki that tells us who you are and what you do. Not just Ubuntu, we want to know our members so besidies saying what brought you to this community and why you like it, tell us about yourself as well.

Then tell us what you did so far. Give links to forum profiles, forum posts that you did, wikipages you wrote, launchpad information about yourself. When you do lots of promotional activities, make photos and publish them somewhere. When you do artwork or documentation, summarize what you did and link to things you are proud of. When you do packaging, tell us about your experience. Make sure we know what you did. Convince us that it has been a sustained and significant contribution.

And tell us about your plans. You have obviously tried to make a commitment and you want to be recognized for this. But your involvement with Ubuntu does not stop here! Why do you want to become Ubuntu member and what are you going to do in the future?

Okay, so that sucks. You will need to write that page, just deal with it. I hated it myself, and my wikipage definitely wasn’t the best. Still, I got accepted on my first try, because I did one thing right: there were people cheering for me! This is as important as the writing, if not more important. You can write down anything you want in your wikipage, but we must be sure it is true.

So get people to cheer for you and make them leave testimonials!

This makes all the difference in a meeting! Make people write their support for you on your wikipage and make them support you during meetings. When you do good work, you will have no problems in getting testimonials. But make sure you also get them from recognized Ubuntu members. This might make Ubuntu sound like a friends-only club, but that is definitely not true! Everyone is welcome, but it sure helps us decide a lot quicker if people we know and whose opinion we value highly tell us that they like what you are doing and should become an Ubuntu member.

Step 3: come to a meeting

With the easy (doing) and difficult (writing) bits out of the way, it is time to meet with one of the governance bodies that decide on Ubuntu membership. If you focus mostly on packaging, you should become a MOTU, and with that an Ubuntu member. For all other applicants (which is most of you), there are three regional membership boards: North & South America, Europe, Middle East and Africa and Asia and Oceania. These boards meet regularly on IRC, and in these meetings you can become Ubuntu member.

Put yourself on the agenda of a meeting for which you have time, you do not necessarily have to go to the board in your region if the schedule of another board fits your schedule better. Make sure you show up at the meeting (surprisingly enough, some get this bit wrong). Prepare a short summary of your wikipage (about 3 lines). You will be asked to introduce yourself, paste these three lines into the channel as introduction.

And then you wait, and wait… The board members will be reading your wikipage, launchpad profile and all the things you link to. We will ask you some questions about your work, make sure you answer them as correct as possible. This is not an exam, but we are trying to get to know you. This is also the point where we make people tell us about you. You did remember to bring some supporters, didn’t you? The more the better, especially people we know.

And then we vote. Each board member will say +1, 0 or -1 (or a creative variant if the situation requires it). There is hardly ever a non-unanymous vote, we all want the same from people. If you’ve prepared well, you will see all +1’s. If you’re ill-prepared, it’ll be -1’s. But the latter should not happen if you followed my advise.

Conclusion

It is really not that difficult to become Ubuntu member, and it of course should not be. The biggest hurdle in recent months is that the membership boards sometimes forget about meetings :) So if you contribute to the Ubuntu community and want to be recognized as Ubuntu member, come to the next meeting and see how it works. Then maybe apply for membership a few meetings after that. Good luck!

Changelog feeds, now for debian too

Since my Ubuntu changelog feeds are quite popular according to feedburner feed stats, I thought it would be a good idea to do some for Debian too. So here they are:

Enjoy!

Star Trek

Best. Star. Trek. Ever.

Just came back from the cinema, will go back there tomorrow to watch again. Won’t give any spoilers, but if you like star trek: go see it. If you don’t like star trek: go see it anyway, it’s that good.

Evolution vs sha256, or why my new key is useless

There’s again a bit of cryptographic related panicing going on at the moment. This time it’s not a bug in the Debian version of OpenSSL, but another attack on SHA-1 that appears to break it a bit worse than before. So now everybody is generating new gpg keys to move away from SHA-1 hashes. There’s one problem though: even when you generate a new gpg key that supports better hashing, your applications will still need to support the better hashing for it to be effective.

Given that gnupg is pretty unusable as a library, making everyone create library-ish wrappers around its command-line interface, it is very easy to get this wrong. So when I decide to generate a new gpg key as well (didn’t want to miss a good crypto panic :)), I tested it with evolution to see if this shiney new key would cause better hashes to be created. To my surprise, I found that gnupg as called by evolution still generates SHA-1 hashes even though I indicated in the key and in the gnupg config that I wanted better hashing. A quick look through the evolution and evolution-data-server source revealed the bug:

camel-cipher-context.h says:

43 typedef enum {
44     CAMEL_CIPHER_HASH_DEFAULT,
45     CAMEL_CIPHER_HASH_MD2,
46     CAMEL_CIPHER_HASH_MD5,
47     CAMEL_CIPHER_HASH_SHA1,
48     CAMEL_CIPHER_HASH_RIPEMD160,
49     CAMEL_CIPHER_HASH_TIGER192,
50     CAMEL_CIPHER_HASH_HAVAL5160
51 } CamelCipherHash;

With CAMEL_CIPHER_HASH_DEFAULT being treated the same as CAMEL_CIPHER_HASH_SHA1. So evolution doesn’t support the SHA-2 family of hashes. And worse, it doesn’t respect preferences set in the key or the gnupg config. Bug 304415 has been open for almost 4 years requesting improvement in this area, but nothing really happened so far.

So when it comes to e-mail, my shiny new key is still pretty damn useless.

Traincoding: SQL views for Django multi-table inheritance models

A django multi-table inheritance model works like this:

from django.db import models

class A(models.Model):
    foo = Models.IntegerField("foo")

class B(A):
    bar = Models.IntegerField("bar")

Which in SQL translates to:

CREATE TABLE `foo_a` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `foo` integer NOT NULL
)
;
CREATE TABLE `foo_b` (
    `a_ptr_id` integer NOT NULL PRIMARY KEY,
    `bar` integer NOT NULL
)
;
ALTER TABLE `foo_b` ADD CONSTRAINT a_ptr_id_refs_id_3d7a1a0e FOREIGN KEY (`a_ptr_id`) REFERENCES `foo_a` (`id`);
COMMIT;

In one of my django projects, I use multi-table inheritance an awful lot. It is an asset database that for instance enforces unique asset tags among a variety of assets. The data is used outside of django as well, where the required joins make code and sql less readable. Some models use fourr levels of inheritance, and thus up to 3 joins depending on the fields to retrieve.

SQL views to the rescue. It is of course simple to define a few views to overcome this problem, but that’s not as much fun as writing a ./manage.py command to do it for you :)

So, here is ./manage.py sqlviews, an extension that abuses some django internals to create CREATE VIEW statements for the models that need them. It even colors them like ./manage.py sqlall etc. do.

Karmic Koala changes feed

As always, I am providing an RSS feed of all published package uploads in Ubuntu. This is now updated for Ubuntu 9.10 “Karmic Koala” as well, subscribe now!

And some more:

Databases in 2010

Will we see this in the future? I hope (and think) not, but who knows :)

dennis@mosquito:~$ sudo apt-get install mysql-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package mysql-server is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
 oracle10g
E: Package mysql-server has no installation candidate
dennis@mosquito:~$

Gay marriage is wrong!

Just so we never forget, 10 reasons why gay marriage is horribly, horribly wrong!

Traincoding: dynamic content for tftp

When installing many machines via PXEboot kickstart/d-i installs, it is often useful to generate pxelinux.cfg files on demand with contents grabbed from a database. When I worked at the university of amsterdam, I had to set up a cluster where easy reinstalls were a requirement. Basically it meant reboot — reinstall, unless told otherwise. How to tell otherwise? pxelinux.cfg/mac-address-file. At that setup, these files were generated by a php script that lived behind a certain url that was called at the end of a d-i run. Removing the file means that the machine will be reinstalled at the next reboot.

In my current job we also want easy installs, and due to scale the php script approach will not do. The files need to be generated beforehand or on the fly, using information from a database. In my search for a solution to this problem, I decided to see how easy it would be to make atftpd call an external command to generate content. As it turns out: very easy! atftpd already has the option to use regular expressions to do filename mangling. At the same points in the code where this does its job, one can easliy do what I wanted. It is implemented in this patch.

The patch is against the debian package, here is how to apply it (jaunty version of atftpd):

$ apt-get source atftpd
$ wget -q -O- http://www.kaarsemaker.net/static/downloads/code/atftp.patch | patch -p0
$ cd atftp-0.7.dfsg
$ autoreconf # Needed because configure.ac is modified
$ dpkg-buildpackage -rfakeroot

If you do not use the debian package, make sure to autoreconf and to pass –enable-generated-content to ./configure.

The generated content feature can be used as follows:

  • Add the “–content-generator /path/to/executable” argument to the atftpd commandline (eg. in xinetd.conf or /etc/default/atftpd, depending on your setup).
  • Whenever a requested file cannot be found, atftpd will open a temporary file with tmpfile(3) and will execute your application, with its filenumber and the requested name as arguments (example: /usr/local/bin/tftp-generator 6 /var/lib/tftpboot/some_file)
  • Your application is now responsible for writing the content that atftpd should send to the given fd (6 in the example). If the content needs to be stored, your application also must do so itself.
  • If your application exists with a non-zero exitstatus or writes zero bytes, atftpd will treat that as “file not found”. If data is written and your application exits with code 0, the written data is sent to the client.

An example application can be found in the README.GENERATED file.