Wednesday, May 26, 2010

We have a winner!


In the early part of 2010, we started a contest for a new GNU Mailman logo. Our old logo, donated by the Dragon de Monsyne had served us well for many years, but it felt like we needed a refresh. Besides, we wanted a nice scalable graphic that we could use in many more situations. So we solicited entries and then conducted a poll. Today I am very pleased to announce the winner!

By better than 2-to-1, this submission by Andrija Arsic was voted as best logo by the Mailman community. Congratulations Andrija!

While we have yet to re-brand the website and software to include the new logo, we'll start using it immediately. If you'd like to help with any redesign, please contact us at mailman-developers@python.org.

A little bit about Andrija: originally from Trstenik, Serbia and now studying IT technology in Belgrade, Andrija is a self-employed, part-time graphic designer, specialising in the fields of corporate identity (logo) design, web design, print design and branding with the majority of his time spent designing and implementing marketing promotions for businesses such as logos, websites, letterhead, business cards, packaging and more. I'm glad that he also contributes to free software, as I think his winning logo is spectacular.

My thanks and appreciation to all the artists who contributed logos to the contest. All the designs are very nice, and in their own way, capture the spirit of GNU Mailman.

Monday, May 24, 2010

From Python package to Ubuntu package in 3-ish easy steps

My friend Tim is working on a very cool Bazaar-backed wiki project and he asked me to package it up for Ubuntu. I'm getting pretty good at packaging Python projects, but I always like the practice because each time it gets a little smoother. This one I managed to package in about 10 minutes so I thought I'd outline the very easy process.

First of all, you want to have a good setup.py, and if you like to cargo cult, you can start with this one. I highly recommend using Distribute instead of setuptools, and in fact the former is what Ubuntu gives you by default. I really like adding the distribute_setup.py which gives you nice features like being able to do python setup.py test and many other things. See lines 18 and 19 in the above referenced setup.py file.

The next thing you'll want is Andrew Straw's fine stdeb package, which you can get on Ubuntu with sudo apt-get install python-stdeb. This package is going to bootstrap your debian/ directory from your setup.py file. It's not perfectly suited to the task (yet, Andrew assures me :), but we can make it work!

These days, I host all of my packages in Bazaar on Launchpad, which is going to make some of the following steps really easy. If you use a different hosting site or a different version control system, you will have to build your Ubuntu package using more traditional means. That's okay, once you have your debian/ directory, it'll be fairly easy (but not as easy as described here ). If you do use Bazaar, you'll just want to make sure you have the bzr-builddeb. Just do sudo apt-get install bzr-builddeb on Ubuntu and you should get everything you need.

Okay, so now you have the requisite packages, and a setup.py, let's build us a deb and upload it to our personal package archive so everyone on Debian and Ubuntu can easily try it out.

First, let's create the debian directory. Here's the first little icky bit:

% python setup.py --command-packages=stdeb.command sdist_dsc

Notice that this leaves us with a deb_dist/ directory, not the debian/ directory we want. The latter is in there, just buried a bit. Let's dig it out:

% mv deb_dist/wikkid-0.1/debian .
% rm -rf deb_dist
% bzr add debian
% bzr commit -m'Debianize'

Note that "wikkid-0.1" will be replaced by the name of your package. In order to build the .deb package, you need an "orig.tar.gz" file. Packaging sort of assumes that you've got an original upstream tarball somewhere and you're just adding the necessary Debian goo to package the thing. In this case, we don't have an upstream tarball, although we could easily create one, and upload it to the Cheeseshop or Launchpad or wherever. However, that just slows us down so let's skip that for now! (Aside: if you do have an upstream tarball somewhere, you'll want to add a debian/watch which points to it; that'll eliminate the need to do the next step, by downloading the tarball instead).

Let's create the tarball right now and copy it to where the following step will expect it:

% python setup.py sdist
% mv dist/Wikkid-0.1.tar.gz ../wikkid_0.1.orig.tar.gz

Here's the second icky bit. Building a Debian source package imposes a very specific naming convention on the tarball. Wikkid's setup.py happens to build a tarball with an incompatible name, while the sdist command leaves it in a place where the next step can't find it. The rename just gets everything into the proper place. YMMV.

Now we can build the Debian source package. It's the source package that we'll upload to our Launchpad PPA. Launchpad will then automatically (if we've done everything right) build the binary package from the uploaded source package, from which Ubuntu and Debian users can easily install.

Oops! Before we do this, please edit your debian/changelog file and change unstable to lucid. You should also change the version number by adding a ~ppa1 to the end of it. Yeah, more ickiness.

Alright now we're ready to build our source package:

% bzr bd -S

Now let's upload it (assuming you've enabled a PPA):

% cd ..
% dput ppa:barry/python wikkid_0.1-1~ppa1_source.changes

That's it! If you've done everything successfully, you'll have the package in your PPA in 5 minutes or so. Then anybody who's added your PPA can just apt-get install wikkid (or whatever your package is called).

I do hope to work with the appropriate developers to make some of the ickiness go away. Please do contact me if you want to help!

Addendum (2010-06-10)

Let's say you publish your tarball on the Cheeseshop or Launchpad, and you don't want to have to build a different tarball locally in order to package it. Here's what I think works:

Create a debian/watch file that points to the download location you publish to. If your package is not yet available in Debian or Ubuntu, then use this command to build your source package:

bzr bd -S -- -sa

The bit at the end tells the Debian packaging primitives to include your tarball when your source package is uploaded. The debian/watch file is used to download your published tarball and automatically renamed to the required .orig.tar.gz name. When you dput your package, your tarball will be uploaded too, and everything should build properly.

Oh, and don't forget to look carefully at the lintian output. Try to make this as clean as possible. The Debian and Ubuntu packaging guides can help here.

Addendum 2 (2010-06-10)

Andrew Straw has added a debianize command to his stdeb package, which makes things much nicer. With this you can create the debian/ directory right next to your setup.py. AFAIK, this version of stdeb isn't released yet, so you need to install his git head in a virtualenv, and it has a few minor buglets, but it does seem like the best-of-breed solution. I'll post another article with a more detailed follow up later.

Sunday, May 23, 2010

Gentoo No More

Today I finally swapped my last Gentoo server for an Ubuntu 10.04 LTS server. Gentoo has served me well over these many years, but with my emerge updates growing to several pages (meaning, I was waaaay behind on updates with almost no hope of catching up) it was long past time to switch. I'd moved my internal server over to Ubuntu during the Karmic cycle, but that was a much easier switch. This one was tougher because I had several interdependent externally facing services: web, mail, sftp, and Mailman.

The real trick to making this go smoothly was to set up a virtual machine in which to install, configure and progressively deploy the new services. My primary desktop machine is a honkin' big i7-920 quad-core Dell with 12GB of RAM, so it's perfectly suited for running lots of VMs. In fact, I have several Ubuntu, Debian and even Windows VMs that I use during my normal development of Ubuntu and Python. However, once I had the new server ready to go, I wanted to be able to quickly swap it into the real hardware. So I purchased a 160GB IDE drive (since the h/w it was going into was too old to support SATA, but still perfectly good for a simple Linux server!) and a USB drive enclosure. I dropped the new disk into the enclosure, mounted it on the Ubuntu desktop and created a virtual machine using the USB drive as its virtio storage.

It was then a pretty simple matter of installing Ubuntu 10.04 on this USB drive-backed VM, giving the VM an IP address on my local network, and installing all the services I wanted. I could even register the VM with Landscape to easily keep it up-to-date as I took my sweet time doing the conversion. There were a few tricking things to keep in mind:

  • I use a port forwarding border router to forward packets from my static external IP address to the appropriate server on my internal network. As I prepared to move each service, I first shut the service off on the old server, twiddled the port forwarding to point to a bogus IP, then tested the new service internally before pointing the real port forward to the new service. This way for example, I had reasonably good confidence that my SMTP server was configured properly before loosing the fire hose of the intarwebs on it.
  • I host several domains on my server so of course my Apache uses NameVirtualHosts. The big downside here is that the physical IP address is used, so I had to edit all the configs over to the temporary IP address of the VM, then back again to the original IP of the server, once the switch was completed.
  • My old server used a fairly straightforward iptables configuration, but in Ubuntu, UFW seems to be the norm. Again, I use IP addresses in the configuration, so these had to be changed twice during the migration.
  • /etc/hosts and /etc/hostname both had to be tweaked after the move since while living in a VM, the host was called something different than when in its final destination. Landscape also had to be reconfigured (see landscape-config(8)).
You get the picture. All in all, just tedious if not very difficult. One oddness was that when the machine was a Gentoo box, the ethernet port was eth0 but after the conversion to Ubuntu, it became eth1. Once I figured that out, it was easy to fix networking. There were a few other little things like updates to my internal DNS, pointing my backup server to the new locations of the web and Mailman data on the new server (Ubuntu is more FHS-compliant than my ancient Gentoo layout), and I'm sure a few other little things I forgot to take notes on.

Still, the big lesson here was that by bouncing the services to a USB-drive backed VM, I was able to fairly easy drop the new disk into the old server for a quick and seamless migration to an entirely new operating system.