September 02, 2010
It's over a month since I've posted anything here. Sorry about that. For the first half of August I was in Italy. The first week, I was speaking at a conference in Pisa and after that we spent a few days in Rome and Venice. I took more than a few photos and they're slowly making their way onto my Flickr page. They should all be up there in a week or so (although, having said that, I still haven't sorted out the photos from last year's holiday in the Baltic).
Rather pleased with the way this photo of the Colosseum came out. But given a half-decent camera, an ancient monument and the Italian flair for lighting there probably wasn't much that could go wrong.
Not quite sure what happened to the rest of August though...
September 02, 2010 05:46 PM
September 01, 2010
Update: The big animated GIFs are killing the alternate webserver I use to host them. If you don’t see the images below, wait a bit and try again …
Unicode provides lots of fun block characters. But can we use them to improve on the traditional ASCII spinner and progress bar?
This is what I settled for in my recent addition to guestfish:

Here’s a traditional ASCII progress bar for comparison:

The problem with Unicode is not with the completeness of the fonts, but with consistency and rendering. Characters that belong to the same logical group just vary in size or consistency, like the circular spinner used here:

The rendering of fonts doesn’t appear to be very well tuned for block characters. The light grey dither in the following bar should not be split into two like this:

Unicode characters themselves are not arranged logically (check out Xah Lee’s description of Unicode arrows). Thus it was very hard to find anything which points in all 8 directions, with many characters pointing only in say 3 or 4 out of 8 directions (eg. NE, E, SE and nothing else .. wtf?). In fact the only usable one was this arrow:

Here are some other attempts:




Want to try making your own? Here is the little C program that I used to make the animations above.
PS. If you are going to use UTF-8 in your program, make sure you’re running in a UTF-8 locale, and provide a simple ASCII fallback.
September 01, 2010 08:11 PM
August 31, 2010
Systems management is very easy.
- Start with a blank slate.
- Write on the slate.
- Demonstrate that, in the event of the slate being wiped clean, you can reproduce the contents of the slate in full.
- Wipe the slate clean.
- See 3.
August 31, 2010 11:28 PM
August 30, 2010
The idea behind this script is you create a template VM, and when you need a new VM, you duplicate the disk image and use the script to put final values into configuration files. This script will take a disk image containing a configuration file like:
HOSTNAME=@HOSTNAME@
and edit it to:
HOSTNAME=yourhost.example.com
#!/usr/bin/python
image = "disk.img"
root_filesystem = "/dev/vg_template/lv_root"
filename = "/etc/sysconfig/network"
pattern = "@HOSTNAME@"
replacement = "yourhost.example.com"
import tempfile
import os
import fileinput
import shutil
import guestfs
g = guestfs.GuestFS ()
g.add_drive (image)
g.launch ()
g.mount_options ("", root_filesystem, "/")
tmpdir = tempfile.mkdtemp ()
tmpfile = os.path.join (tmpdir, "file")
g.download (filename, tmpfile)
for line in fileinput.FileInput (tmpfile, inplace=1):
line = line.replace (pattern, replacement)
print line,
g.upload (tmpfile, filename)
g.umount_all ()
g.sync ()
shutil.rmtree (tmpdir)
If you have to make many changes to a VM image, don’t run this script repeatedly. Instead, duplicate the download ... upload section of the code as required.
August 30, 2010 10:02 PM
August 28, 2010
August 27, 2010
August 25, 2010
I uploaded some distro-independent Linux/x86-64 binaries of libguestfs, guestfish, guestmount and the virt-* tools. Be sure to read the README file first.
These are a little experimental and I’d welcome feedback. I got them to work fine on Debian 5.0 after upgrading glibc and Perl, but YMMV.
Update: OpenSUSE 11.3 working.
The version of KVM supplied is too old (doesn’t support virtio-serial) so I had to compile qemu from git and drop the following qemu wrapper in place:
#!/bin/sh -
qemudir=/home/rjones/d/qemu
exec $qemudir/x86_64-softmmu/qemu-system-x86_64 -L $qemudir/pc-bios "$@"
The next problem which had me confused for a very long time was that qemu kept aborting while allocating memory. After trying things like adding swap, playing with overcommit settings and so on, it turned out that SUSE uses some really silly, and very small default ulimits for virtual memory. You have to do:
ulimit -Hv unlimited
ulimit -Sv unlimited
ulimit -Hm unlimited
ulimit -Sm unlimited
Update: Ubuntu 10.04 working.
As with SUSE, the version of KVM shipped by Ubuntu is too old to support virtio-serial. All I had to do was replace it with qemu from git and the same qemu wrapper above.
After that guestfish works fine.
If you need the Perl tools, then you have to upgrade Perl to 5.12.1, install hivex, and link libpcre.so.0 -> libpcre.so.3.
August 25, 2010 04:43 PM
August 24, 2010
I do all my development on VMWares, as they are cheap and easy to setup and mimic the real deployment environment. I've always used NAT networking on my vmwares rather than put them on the network as standalone bridged items, however, recently I was asked to "share" my latest code on the network. My host hacks didn't get translated so I needed to to forward the port 80 traffic from the Mac to
August 24, 2010 02:17 PM
Given the recent developments on the opensolaris front, there is again the issue of what OS do people run on their existing sparc hardware ? And I wonder if now is a good time to consider bringing up the CentOS on Sparc conversations again.
I have some hardware that can be used for the builds and I know there is enough contributed / contribute-able resources around to setup some development instances as well. However, the real issue is : is there much desire out there to have CentOS running on these machines ?
Even though I don't have any equipment in production running off Sparc anymore, I know there are quite a few people who do. And it looks like Oracle wants to put these people in a position where they either run a paid for supported Solaris or nothing at all. If we can do something to create an option, that would be awesome. And given the huge commitment to open source that the CentOS upstream has, doing it here on this platform makes the most sense since efforts put in will stay in an open source model, with equal opportunity for anyone to join the effort and continue it. Knowing that there is no vendor preferences or vendor isolation / ownership issues being involved.
CentOS also makes for a good choice since the porting and development effort would need to only really be done at one point - when a major new release is announced upstream - and from that point on, its a case of maintaining the builds for the lifespan. Considering that the lifespan for a CentOS release would be 7 years or more, it makes the effort even more worthwhile.
Usual suspects still hold true : long life, stable releases, documentation that is shared with the i386/x86_64 world for most parts, userspace support in the regular media, a clueful community and an awesome infrastructure setup etc.
Maybe we can sync up with the Fedora-sparc guys and see if there is any synergy there. I know that they have been getting ready for a new release soon.
Something to think about.
- KB
August 24, 2010 11:04 AM
August 23, 2010
Cronjobs are one of those necessary evils of any decent sized Unix setup,
they provide often essential pieces of a sites data flows but are often
treated as second class citizens. While I've already mentioned my Cron
commandments I'm always looking for improvements in the
rest of my cron tool set and, with Vladimir Vuksan's cronologger, I may have
found another piece of the puzzle.
The concept is simple, you add a command to the front of your crontabs
and it invokes your actual cron command. This wrapper script collects the
stdout, stderr and some other details such as exit code and run time. The
backend is a couchdb data store and the simple reporting pages are written
in PHP, and are easy to work through, crib and base your own reports
from. Having all this cron information also helps provide a talking point
with development, it's easy to show progress and imbue a sense of actually
getting somewhere when the number of cronjobs
with errors drops each day, rather than the systems team mentioning that
their email boxes are a little emptier since the last release.
While our initial tests seem positive there are a couple of reports and
tweaks to the command line data injector that we want for our local usage.
The biggest problem with the project may well be that the idea is so
obviously correct that we end up re-implementing it in something a little
more suitable for our environment. Maybe a Python command line client and
Perl Template Toolkit driven reports to replace the PHP. But that's a
possibility for later - for now cronologger is a great 80% solver.
August 23, 2010 09:49 PM
August 19, 2010
We’ve had to change the way libguestfs boots its appliance, so now the appliance will be an ext2 filesystem from an ordinary drive, instead of an initrd.
The problem is that we need to create the ext2 filesystem on the fly, and we can’t use libguestfs to do this (which would be way easier than the method I’m about to describe).
However e2fsprogs comes with a low-level library for manipulating ext2 filesystem images, and it is just about possible to use this to make an ext2 filesystem and put files and directories on to it.
The documentation on libext2fs is very light on detail, but I have written some example code:
http://www.annexia.org/tmp/ext2fs_test.c
Compile and run this with:
$ gcc -Wall test.c -o test -lext2fs -lcom_err
$ ./test
$ guestfish -a /tmp/test.img -m /dev/sda
><fs> ll /
drwxr-xr-x 4 500 500 1024 Aug 19 12:08 .
dr-xr-xr-x 20 root root 0 Aug 19 12:09 ..
-rw-r--r-- 1 root root 100000 Aug 19 12:08 hello
drwx------ 2 root root 12288 Aug 19 12:08 lost+found
drwxr-xr-x 2 root root 1024 Aug 19 12:08 mydir
><fs> ll /mydir/
total 3
drwxr-xr-x 2 root root 1024 Aug 19 12:08 .
drwxr-xr-x 4 500 500 1024 Aug 19 12:08 ..
-rw-r--r-- 1 root root 99 Aug 19 12:08 file_in_mydir
><fs> cat /mydir/file_in_mydir
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
It’s also advisable to read about how ext2 works internally.
August 19, 2010 11:11 AM
Firstly, you'll need to get your web server up and running with https, you'll need
your certificate and key set up, happily theres already loads of posts about that,
so I won't cover it here!
The second area of pain is that djangos development runserver doesn't support HTTPS,
which is irksome but apparently there are ways around it!
The django-weave project
go into detail about it. I'm lucky
August 19, 2010 11:25 AM
August 18, 2010
August 17, 2010
We rewrote the inspection code in C (originally it was Perl). One advantage to this is you can inspect unknown OS images from any language binding, not just Perl.
Another is that it makes the guestfish -i option both smarter and faster. The following will only work in the latest development version, 1.5.3:
$ guestfish -i -d Debian5x64 --ro
Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.
Type: 'help' for a list of commands
'man' to read the manual
'quit' to quit the shell
Operating system: squeeze/sid
/dev/mapper/debian5x64-root mounted on /
/dev/vda1 mounted on /boot
/dev/mapper/debian5x64-home mounted on /home
/dev/mapper/debian5x64-tmp mounted on /tmp
/dev/mapper/debian5x64-usr mounted on /usr
/dev/mapper/debian5x64-var mounted on /var
><fs>
The inspection API is documented in the main manual.
We are also maintaining two stable branches by backporting only conservative bug fixes. libguestfs 1.2.11 is the latest old stable version along the 1.2 branch, and libguestfs 1.4.2 is the latest stable version along the 1.4 branch. (If you want to start using libguestfs and you don’t want the bleeding edge, use 1.4.x).
August 17, 2010 06:34 PM
August 14, 2010
There's a question I see quite a lot at StackOverflow and the Django Users group regarding aggregation in Django. It goes like this: I know how to annotate a max/min value for a related item on each item in a queryset. But how do I get the actual related item itself?
I wish this was easier than it actually is. The problem is that in the underlying SQL, annotating the value is a simple aggregation query on the related item, whereas getting the entire object means moving to a complicated dependent subquery.
To illustrate, take these models:
class Blog(models.Model):
name = models.CharField(max_length=64)
class Entry(models.Model):
blog = models.ForeignKey(Blog)
added = models.DateTimeField(auto_now_add=True)
text = models.TextField()
Getting the date of the latest Entry for each Blog is simple:
blogs = Blog.objects.annotate(Max('entry__added'))
and the underlying SQL is just as simple:
SELECT blog.id, blog.name, MAX(entry.added)
FROM blog_blog blog
JOIN blog_entry entry on entry.blog_id = blog.id
GROUP BY blog.id
But that doesn't work if you want the whole Entry object. You need to do something much more complicated:
SELECT blog.id, blog.name, entry.id, entry.added, entry.text
FROM blog_blog blog, blog_entry entry
WHERE entry.id = (
SELECT e2.id FROM blog_entry e2
WHERE e2.blog_id = blog.id
ORDER BY e2.added
LIMIT 1
);
and currently there's no support for this in the Django ORM.
Now, you could just pass the above query to the .raw queryset method in Django 1.2: Blog.objects.raw('SELECT...'), and perhaps surprisingly, this will work, in that the extra fields from the Entry model will be appended to each Blog instance. If you needed the actual Entry instance - say if you had some extra methods on the Entry model that you needed to run with each one - you would have to iterate through the queryset and instantiate new Entry objects with the fields from each Blog.
Also note there's another gotcha with raw querysets, which is that they are re-executed every time you slice them or access one of their members - so it's probably best to cast them to a plain list first.
There is another approach which gets you the items related in the normal Django way, so that you can do entry_instance.blog. It does this in two queries, with a bit of Python processing in the meantime.
from django.db.models import Max
blogs = Blog.objects.annotate(Max('entry__added'))
values = tuple([(blog.id, blog.max__entry__added) for blog in blogs])
entries = Entry.objects.extra(where=['(blog_id, added) IN %s' % (values,)])
blog_dict = dict([(b.id, b) for b in blogs])
entries = list(entries)
for entry in entries:
entry._blog_cache = blog_dict[entry.blog_id]
Here we do a standard annotate query to get the added values for each relevant Entry. Then we can do an extra query to get the actual Entries associated with each (blog_id, max_entry) tuple (note we can't use the params argument for the values list, unfortunately, as it will get double-quoted). Finally, we can re-associate each Entry with its Blog - I've done it that way round to fit in with the standard ForeignKey and its automatic mapping of entry._blog_cache to entry.blog, and since we're only interested in one entry per blog it shouldn't matter whether we have to iterate through blogs or entries.
Again, it's a shame we have to drop to raw SQL for the middle step here. The query depends on matching multiple values for each row, and although it would be possible to do this by iterating through and adding Q objects for each row, it would be an absolutely horrible query. At least we're using extra here, which is arguably better than the raw we used in the first attempt above.
August 14, 2010 08:18 PM
August 09, 2010
I am fairly frequently asked for tips on getting less junk email. There’s quite a few things you can do that will cut the amount of junk you get, or at least let you get an idea of where it came from.
- Don’t have a catchall account, only ever accept mail for real mailboxes.
- Use as few generic or role addresses as you can. sales@, info@, help@ etc will all draw in unwanted junk.
- Delete or disable legacy mailboxes, don’t alias them to another user’s mailbox.
- Use different email aliases for different sites. So I might have martin-slashdot@ for Slashdot, martin-elreg@ for The Register, martin-dominos@ for Dominos etc etc. If mails arrives to these addresses, and it’s not from that specific organisation, then something has leaked when it shouldn’t have.
- Once you’ve finished with a particular site, remove the alias.
- Don’t be afraid to pick up the phone. If you get email you didn’t want from a company, call them to get yourself removed. Where you’ve had no contact with a company before, tell them politely that they are breaking the law by sending you unsolicited email.
- Understand the difference between spam and UCE. With spam it is rarely worth your time tracking down the sender, UCE may well be.
- Don’t click on unsubscribe links in spam messages. Do click on unsubscribe links in UCE messages. With the latter, if the unsubscribe isn’t instant (“It may take up to 10 days….”) then blacklist the sender.
And, of course, if junk mail really is a big problem for you, consider using a commercial anti-spam and anti-virus filtering service to get rid of it. Obviously I would recommend antibodyMX, but there are plenty of other providers out there.
August 09, 2010 06:45 PM
August 07, 2010
A few years ago I wrote a literate FORTH compiler and tutorial called JONESFORTH. It’s a good way, I think, to understand the power and limitations of FORTH, and a good way to learn a completely different and mind-blowing programming language.
If you’ve not heard of FORTH before, cogitate on this: It is possible to write a FORTH program in 2,000 lines. A program which will boot and provide an entire development environment (inc. editor, compiler etc) on bare hardware.
Anyhow, I just uploaded my semi-private CVS repository to git. You can find it here:
http://git.annexia.org/?p=jonesforth.git;a=summary
The original tutorial is in two parts:
August 07, 2010 10:35 PM
August 04, 2010
This is a USB Entropy Key, cost £42 inc VAT and delivery from a company up in Lancashire.

usb 2-1: new full speed USB device using uhci_hcd and address 2
usb 2-1: New USB device found, idVendor=20df, idProduct=0001
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-1: Product: Entropy Key
usb 2-1: Manufacturer: Simtec Electronics
usb 2-1: SerialNumber: M/xxx
I can report that it works fine in Fedora 13 with the open source daemon provided. The entropy can be collected in a file, passed to egd, but by default it is added to the kernel entropy pool for use by /dev/random and things like ASLR.
I love how overengineered (yet cheap) this thing is. From the documentation:
“The Entropy Key uses P-N semiconductor junctions reverse biased with a high enough voltage to bring them near to, but not beyond, breakdown in order to generate noise. In other words, it has a pair of devices that are wired up in such a way that as a high potential is applied across them, where electrons do not normally flow in this direction and would be blocked, the high voltage compresses the semiconduction gap sufficiently that the occasional stray electron will quantum tunnel through the P-N junction. (This is sometimes referred to as avalanche noise.) When this happens is unpredictable, and the occurrence of these events is what the Entropy Key measures.
These noise generators are then coupled to a 72MHz ARM Cortex-M3 CPU on the device. This processor samples the generators at a high frequency, forming a stream of random bytes. These streams of bytes are then analyzed using Ueli Maurer’s universal test for random bit generators whereby the amount of entropy in the streams is estimated rather conservatively. The streams are also exclusive-ORed together and that stream’s entropy is estimated in the same manner. If the raw streams appear to have severely reduced entropy then it indicates a fault in that generator, if the third stream has low entropy then it indicates that the generators have correlated and are not independently gathering entropy. Any of those three states are considered a failure mode and will result in the eKey locking itself out of the host, returning only an error code instead of generating entropy packets.
The two raw streams are then processed further in a de-biasing process invented by John von Neumann. Their entropy is estimated after the de-biasing process has been performed. Again, if the estimated entropy in the streams is seen to vary too wildly at this stage, the Entropy Key will lock itself out. The processed streams are then mixed into a pool made with a secure hashing function. Once at least 50% more (estimated) entropy has been mixed into the pool than it could possibly hold it is finalised and another pool initialised. Once enough pools have been processed to fill 20000 bits, the totality is subjected to the tests stipulated in FIPS 140-2. These tests produce a PASS/FAIL indicator for the block. On its own, this is not useful, since a perfectly random block could quite plausibly fail the tests. The Entropy Key therefore keeps running statistics on the FIPS 140-2 tests and will lock itself out if the ratio of failed blocks to passed blocks rises above a conservative estimate of the statistical likelihood of failure.
Once the block has been analysed, regardless of its PASS/FAIL indication, it is chopped up into 32 byte packets and these are handed off to the protocol handler in the device. Through this process therefore, each 256 bit block of data handed to the host was formed from somewhere in the region of between 3000 and 5000 bits read from the generators.”
August 04, 2010 10:24 AM
August 03, 2010
In this video from the OCaml Users Conference back in April, Xavier Leroy explains the 8 new features in OCaml 3.12. As I said elsewhere, none of the features are earth-shattering, but they make a great programming language that little bit nicer.
The bit where he discusses the new features starts at around 11 mins 50 seconds in.
Direct link to the video site (also requires flash)
Thanks to Sylvain Le Gall for organizing this.
August 03, 2010 06:50 PM
August 02, 2010
July 31, 2010
Update: As Jake pointed out in the comments you obviously need zero MQ installed for this example to work. Just ‘brew install zeromq’ or ‘port install zmq’ on OS X, or use your Linux package manager.
I couldn’t find may examples of zeroMQ usage in Ruby so here is a basic sender/consumer I made to test it. First install the ‘zmq’ gem:
gem install zmq --no-ri --no-rdoc
Now start a worker, you can start as many as you want:
Now stick some messages on the queue:
You should get messages distributed to all the worker processes you started up. Pretty simple!
July 31, 2010 11:58 PM
July 30, 2010
July 29, 2010
At the time of the European election last year, there was some debate in the blogosphere about the Green Party's attitude to science. Holfordwatch picked up on a report which said that the Greens supported the continued use of "alternative medicine" in the NHS. Rational people, of course, gave up all idea of voting for them.
To their credit, the Greens responded to this by clarifying (and, actually, seeming to completely drop) some of these policies. In this Q&A in the Guardian, their press officer, Scott Redding, was asked:
If the balance of evidence suggests that a treatment does not perform any better than placebo, should it be supported by the NHS?
He replied:
The short answer is No. Our policy is that any medicine or treatment available on the NHS should be backed up by scientific evidence. Some new treatments, and some currently available on the NHS, will pass this test, others will not.
Of course, you might well think that it doesn't matter what the Green Party thinks on this as they'll never have the power to enact their policies. And you'd be right to think that.
But they do have an MP now. Caroline Lucas is the MP for Brighton Pavilion. And whilst she's not exactly driving government policy, she does have the same ways to make her views known as all other MPs, including signing Early Day Motions.
So, given the clear direction indicated by Scott Redding, it's disappointing to see the she has signed one of David Tredinnick's
nonsense EDMs on homeopathy (as
discussed previously on this blog).
On one hand, the Greens clearly say that they won't support medical treatments without scientific evidence to support them. And then their first ever MP goes and gives her support to something that is on a the same level as witchcraft. If I was one of the enlightened people who voted for her back in May, I'd be feeling pretty pissed off about now.
I had hoped that, at least, the Green Party would prove themselves to be above the lies and spin that characterise so much of British politics. I'm really disappointed to see those hopes dashed.
Update: Lucas has received a lot of comment over this on Twitter in the last few hours. She has posted what I can only assume is supposed to be
an explanation for her actions:
EDM is about lack of BMA's consultation & argues that local NHS better placed to know patient needs, based on objective clinical assessment
It's nonsense of course. Tredinnick is a well-known parliamentary advocate for homeopathy. His EDM is purely about supporting the provision of quackery on the NHS. Tredinnick is deliberately inventing scientific controversy where none exists. The science is settled. Homeopathy does not work.
If patients have been told that homeopathy is worth investigating, then their doctors should make it clear to them that they have been misled. Doctors should not be encouraging this delusion.
July 29, 2010 08:03 PM
July 26, 2010
So I arranged to take my car in Saturday to have the bit-of-plastic-on-the-driver’s-door fitted. I turn up, chap at the desk expected me and was very helpful.
Him> Ahh yes, part’s right here, shouldn’t take a mo to fit, I’ll just get some tools.
Me> Super thanks.
<fx>fiddling with the door happens</fx>
Him> Just going to make a phonecall, this isn’t looking how I expected
Me> It doesn’t look like a door with a well understood piece of plastic missing, I didn’t say.
Me> Uhh, sure.
<fx>phone call happens</fx>
Him> Sorry, but it looks like I can’t fit this part.
Me> You can’t fit this part.
Him> No, I think the inside door panel needs to be removed.
Me> The inside door panel needs to be removed, you think.
Him> Yes, and I’m not qualified.
Me> You’re not qualified. Super. Thanks.
I still have a hole in my door.
Meanwhile, 75cm toward the rear of my car….
You may recall that Renault Romford mistakenly did work I didn’t ask them to do, then insisted I pay for said work or I couldn’t have my car back. I decided to take them up on their offer to simply undo the work and put back the faulty door mechanism and then give me a full refund.
Me> I’ve decided to take you up on your offer to simply undo the work and put back the faulty door mechanism and then give me a full refund.
Renault Romford> We can’t, we’ve thrown the old parts away.
Me> You’ve thrown the old parts away. Can I have a refund?
Renault Romford> I’ll need to call customer services for you….
I’ve had no call from Renault UK Customer services today, I left messages, Yvonne’s been a bit busy.
Still, nice to know I’m dealing with a reputable professional company, and not some east-end railway-arch crook.
July 26, 2010 09:47 PM
Section 47 of the Government Response to the Science and Technology Committee's Evidence Check on homeopathy:
We note the Committee’s view that allowing for the provision of homeopathy may risk seeming to endorse it, and we will keep the position under review. However, we do not believe that this risk amounts to a risk to patient trust, choice or safety, nor do we believe that the risk is significant enough for the Department to take the unusual step of removing PCTs’ flexibility to make their own decisions. We believe that providing appropriate information for commissioners, clinicians and the public, and ensuring a strong ethical code for clinicians, remain the most effective ways to ensure quality outcomes, patient satisfaction and the appropriate use of NHS funding.
So basically no change. Our new government is just as capable of ignoring scientific evidence as the old one. And the NHS will continue to squander millions on sugar pills.
I expect I'll come back and fill this in with some more detail when I've calmed down a little.
July 26, 2010 02:24 PM
July 25, 2010
Here are the slides from my talk at Europython 2010, Advanced Django ORM Techniques.
The talk is mainly a summary of the query optimisation tricks I've previously talked about on this blog, although I did begin by explaining briefly how models, fields and relationships work behind the scenes - I'll write some of that up here at some point.
I'll also be posting a longer review of Europython here, hopefully in the next few days.
July 25, 2010 08:15 PM
July 22, 2010
July 21, 2010
Two people asked me in about as many days if libguestfs supports encrypted VMs, so with the help of LUKS I added this feature.
A typical session in guestfish looks like this:
$ guestfish --ro -a encrypted.img
><fs> run
><fs> list-devices
/dev/vda
><fs> list-partitions
/dev/vda1
/dev/vda2
><fs> vfs-type /dev/vda2
crypto_LUKS
><fs> luks-open /dev/vda2 luksdev
Enter key or passphrase ("key"):
><fs> vgscan
><fs> vg-activate-all true
><fs> vgs
vg_f13x64encrypted
><fs> lvs
/dev/vg_f13x64encrypted/lv_root
/dev/vg_f13x64encrypted/lv_swap
><fs> mount /dev/vg_f13x64encrypted/lv_root /
><fs> ll /
total 132
dr-xr-xr-x. 24 root root 4096 Jul 21 12:01 .
dr-xr-xr-x 20 root root 0 Jul 21 20:06 ..
drwx------. 3 root root 4096 Jul 21 11:59 .dbus
drwx------. 2 root root 4096 Jul 21 12:00 .pulse
-rw-------. 1 root root 256 Jul 21 12:00 .pulse-cookie
dr-xr-xr-x. 2 root root 4096 May 13 03:03 bin
Since it’s a little clumsy to use in guestfish at the moment, I hope we can add some convenience commands in a future release.
PS. WTF are dbus and pulseaudio doing creating those files and directories under /?
July 21, 2010 08:11 PM
My nearly-four-years-old Renault Clio was due a bit of tender loving care. The rear door lock had stopped being able to lock the doors, a small piece of plastic fell off the front driver’s side door and, the one that tipped it, the driver side wing mirror was shattered; someone hit it in a car park – thanks!
I booked my car in to Renault Romford, dropped it in before work, and waited for a call back letting me know what everything was going to cost. The call arrived and the suggested shopping list was a little longer than I expected.
- Rear engine mount starting to split – £103.00
- Front disks and pads should be replaced – £245.60
- Coolant and brake fluid drain and refill – £49.99
- Air conditioning service – £79.99
- Replacing the bit of plastic that fell off – £7.76
- Replacing the mirror – £27.87
- Replacing the rear door handle – £365.68 – wait, what?
I totally accept that most of the stuff in that list falls under the categories of “normal wear and tear” and “you broke it”, but things like a door handle should reasonably last the lifetime of the car. It’s not like it’s even the most commonly used door. Had this been the driver’s door, I might have grumbled a bit but understood.
I asked Renault Romford to replace the glass, replace the bit of plastic and service the aircon, explaining that I would sort out the brakes etc next month and would call Renault UK Customer services to talk to them about the rear door handle.
Renault UK customers service have still not contacted me, despite Tweets, emails and a telephone message asking them to do so.
I got a call yesterday saying my car was ready to be picked up, and that I owed them some £450.00. I was confused. They’d changed the rear door lock, despite me very explicitly saying that I was going to talk to Renault customer services about it. Opinions were exchanged, we agreed this was most likely a misunderstanding.
I went to pick up my car this morning. The car would not be released to me unless I paid in full. In other words, I have paid hundreds of pounds for parts and work I didn’t ask to be done.
Insult to injury? Hell, yes. The didn’t replace the tiny piece of plastic that fell off the front door, one of the three things I did very specifically ask them to fix.
THERE’S A HOLE IN MY DOOR, DEAR RENAULT. And I’m hundreds of pounds out of pocket.
July 21, 2010 08:50 AM
July 19, 2010
July 18, 2010
July 17, 2010
Rumors of my disappearance into a void are somewhat overrated.
I was invited to talk at the London Java Community on DevOps, I decided for that community it'd be good to have some examples with some code in. Fortunately my previous employers have open-sourced some of the frameworks used including their version of feature switches and a handy log configuration servlet.
It was good to catch up with old colleagues from ThoughtWorks, the London DevOps community and also meet new people.
The slides and talk are my own work, and do not represent the opinions of my employer...
July 17, 2010 06:08 PM
After someone asked me a question about “balloons” (in the virtualization sense) today, I noticed that there is not very much documentation around. This post explains what the KVM virtio_balloon driver is all about.
First of all, what is a balloon driver if you’ve never even heard of the concept? It’s a way to give or take RAM from a guest. (In theory at least), if your guest needs more RAM, you can use the balloon driver to give it more RAM. Or if the host needs to take RAM away from guests, it can do so. All of this is done without needing to pause or reboot the guest.
You might think that this would work as a RAM “hot add” feature, rather like hot adding disks to a guest. Although RAM hot add would (IMHO) be much better, currently this is not how ballooning works.
What we have is a kernel driver inside the guest called virtio_balloon. This driver acts like a kind of weird process, either expanding its own memory usage or shrinking down to nearly nothing, as in the diagrams below:


When the balloon driver expands, normal applications running in the guest suddenly have a lot less memory and the guest does the usual things it does when there’s not much memory, including swapping stuff out and starting up the OOM killer. (The balloon itself is non-swappable and un-killable in case you were wondering).
So what’s the point of a kernel driver which wastes memory? There are two points: Firstly, the driver communicates with the host (over the virtio channel), and the host gives it instructions (“expand to this size”, “shrink down now”). The guest cooperates, but doesn’t directly control the balloon.
Secondly, memory pages in the balloon are unmapped from the guest and handed back to the host, so the host can hand them out to other guests. It’s like the guest’s memory has a chunk missing from it:

Libvirt has two settings you can control called currentMemory and maxMemory (“memory” in the libvirt XML):

maxMemory (or just <memory>) is the memory allocated at boot time to a guest. KVM and Xen guests currently cannot exceed this. currentMemory controls what memory you’re requesting to give to the guest’s applications. The balloon fills the rest of the memory and gives it back to the host for the host to use elsewhere.
You can adjust this manually for your guests, either by editing the XML, or by using the virsh setmem command.
July 17, 2010 02:33 PM
July 16, 2010
I had to build a fresh set of rpms for the area_cli tools, and decided it was also a good time to rebase some of my local personal build tools to rhel6beta2 since its there and I need to do some tests with it anyway.
Firstly, there are a couple of cool things with rhel6 beta2 - rpmdevtools is included by default, which helps gets things started and helps a bit in managing spec files etc.
What isnt so cool is that the newer rpm in el6beta creates packages which then cause issues with some of the older CentOS releases. eg. this areca_cli package built on el6beta2/x86_64 for target i686 caused this to happen with yum:
Downloading Packages:
areca_cli-1.83_091103-1.e 100% |=========================| 493 kB 00:00
Running rpm_check_debug
ERROR with rpm_check_debug vs depsolve:
rpmlib(FileDigests) is needed by areca_cli
rpmlib(PayloadIsXz) is needed by areca_cli
Complete!
(1, [u'Please report this error in https://bugzilla.redhat.com/enter_bug.cgi?product=Red%20Hat%20Enterprise%20Linux%205&component=yum'])
Which causes the package to not install. This is on a CentOS-5.2 machine. And I need to maintain that at CentOS-5.2 due to various issues ( no, machine is not available on the internet, and only hosts a single app in production ). Trying the install on a CentOS-5.3 machine I get the exact same issue. Upgrading rpm to 4.4.2.3-18.el5 ( the version in 5.4 and 5.5 ) makes no difference.
On the other hand, builds run on CentOS-5 have no problems installing on EL6Beta. So for the time being it looks like all buildhosts and all build stuff will need to stay on EL5. Specially since that allows you to target CentOS-3 and CentOS-4 as well.
- KB
Note: yeah, I see that url pointing at bugzilla isnt idea. I'll look into plumbing in a bugs.centos.org reference instead.
July 16, 2010 04:09 PM
Earlier this year, I created a petition on the (then) government's petition web site. The petition called for the government to fully implement the recommendations of the House of Commons Science and Technology Committee's Evidence Check on Homeopathy - basically calling on the government to stop wasting money on homeopathy.
The petition was due to be open for signatures for a year. In retrospect, that was probably a mistake as no matter who was in government, they would have made up their mind about the issue long before the petition closed.
But since the general election everything has changed. All of the petitions were closed to new signatures during the election campaign and they didn't re-open once the new government was in place. Instead the web site explained that the new government was considering the best way to proceed with the site. The front page of the site now says:
With a new Government in place a review is taking place of online services, including e-petitions. We are committed to improving the e-petitions process and are looking at ways of ensuring that it functions as part of a cohesive approach to public debate and transparent government. A full announcement on how we plan to use these and other services across Government will be made as soon as this important work is completed.
It goes on to say:
Existing e-petitions, submitted to the previous administration, will not be carried forward to the new administration as part of this process. E-petitions that were live at the time of the election announcement on 6 April, when the e-petitions system was suspended, will therefore not be reopened for signatures. We are issuing responses to petitions that had exceeded the 500 signatures threshold as of 6 April 2010 and these can be viewed on the
HMG e-petitions responses page.
So my petition has been closed. In the three or four months that it was open, over 1,600 people signed it. That means that we can expect some kind of response from the government, although it's not there yet and there's no indication of when we will receive it.
Thanks to everyone who signed the petition. Perhaps in this new cuts-driven regime removing finding for magic water on the NHS is an obvious way to save a few million quid.
July 16, 2010 09:33 AM
July 15, 2010
July 14, 2010
July 13, 2010
Being part of an oncall rota is pretty much a certainty if you work in the systems or operations team at any IT orientated company. Stuff needs to be working 24 hours a day, 7 days a week and therefore you need someone available to apply duct tape and staples when things go wrong out of normal working hours. It continually amazes me, therefore, that so many companies get the management and organisation of their rota badly wrong, sometimes to the point of it being a significant factor in staff moving on.
As someone who’s participated in oncall rotas at all levels, here’s how I think one should be organised:
- Sysadmins should only participate in the rota after they have completed their probationary period. Think of the goal of the probation period as being getting someone up to speed so they can participate.
- Each oncall shift should last one week, and rotate at 2.00pm on Tuesday. If you run a late shift, i.e. 11.00am to 8.00pm, make the person on that shift also be oncall. Get all the unsociable hours out of the way in one lump.
- The bare minimum gap between oncall shifts should be 5 weeks. If your rota is shorter than this, then you don’t have enough qualified staff to cope with holidays, illness, paternity/maternity leave etc anyway.
- The oncall shift should be mapped at least 3 months into the future. Staff should be free to swap oncall weeks providing that no-one is ever oncall two weeks in a row, and that all swaps are cleared with their line manager.
- Issue the oncaller with a good quality mobile phone and 3G capable laptop. The phone should not be a smartphone, the aim should be for maximum battery life and talk time. The laptop should be more like a netbook than a desktop replacement, should come with a spare battery, and should dual boot to Windows and a useful Linux desktop distro. These days I’d shell out for a nice big SSD to stick in it too. Make sure there are no restrictions on international calling and no data caps for the phone and 3G card.
- Don’t give the direct number of the oncall phone. Instead, use an answering service as filter. During office hours, the answering service should redirect enquiries to the regular helpdesk/support number. Out of hours, the answering service should accept calls, take details and then pass these on to the oncall number. Additionally this service should text and email call details so there’s a record.
- Pay a fixed daily amount for being oncall. Pay 1.5 times this amount for being oncall on weekend days. Pay 2 times this amount for being oncall on a public holiday. Where someone is oncall on a public holiday, add one day to their holiday allowance.
- Pay a per-incident fee when oncall is used. Each oncall use should be tracked in your ticketing system. Make using oncall a business cost, thus giving the business a reason to make sure oncall is not used trivially, and a reason to make sure problems are fixed permanently and not just temporarily alleviated.
- When the oncall person has dealt with out of hours issues, don’t expect them in at the regular time the next day. Expect them to use their judgement to make sure they are suitably rested. You do not want an overly tired oncaller dealing with problems on production systems.
- The person oncall should never be taking on “out of hours” work. Want a database dumped and reloaded? Want a disk unmounted and fscked overnight when a server’s not busy? All those things can be done, but not by the oncall person. That person is there to respond to problems, not to perform routine or planned maintenance.
- Make it very clear that abuse of oncall is unacceptable. Oncall is there to fix customer or service affecting problems, not to help someone with Excel.
- Have a clear demarcation between production and testing/development/QA systems. The latter group are not oncall’s responsibility to fix.
- If you have offices around the world, have a “follow the sun” oncall system, get your offices to cover each other.
- Have realistic expectations of oncall response times. If you need to guarantee that problems are attended to within 20-30 minutes then you should be running an overnight shift, not oncall.
- Expect a daily report summarising the previous 24 hour oncall period, even if that report is “Nothing to report”. The weekend period could be lumped together on the Monday.
- Have a weekly oncall handover meeting between the outgoing and incoming oncall staff.
- During the day, have a junior or trainee sysadmin be oncall. It’s good practice for them.
Doing all of the above shows that you take oncall seriously, and you appreciate the impact being oncall has on someone’s life. Your oncall staff are the people who salvage the business’s reputation when the midden hits the windmill at some unworldly hour of the night. Keeping them happy and making them feel valued and respected can only be to the business’s benefit.
July 13, 2010 07:01 PM
Update: I was going to post an HTML5 video here, but WordPress strips the <video> element. Here’s the direct link to the video file (Motion JPEG format, should play in most places):
video, now with shadows
Another one from the Blender book:






This is really an animation, but I’ve no idea how to stitch all 50 frames together into a movie yet.
July 13, 2010 12:10 PM

I used to be a proper expert on Blender. I even went (in fact, I was invited and flown out to1) the Blender Users Conference in 2000. Since I’ve not used Blender in about 8 years, it’s quite hard to remember all the commands now, but I did make it through the “cup tutorial” from an old (paper) copy of the Blender Book (alternative free Blender manual).
Blender is like “vi”. And I mean that in both a good and a bad way … It’s incredibly powerful once you know how to use it, but damn hard to learn (or relearn in my case).
I’ll give potential users two tips: 1. The Fedora package is currently broken. If you hit “Space” and you don’t see a menu, it’s broken for you too. 2. Don’t even try using Blender without a full size keyboard with a keypad and a 3 button mouse. Really, don’t even begin. It’s just not possible. Laptop? Forget it or plug in an external keyboard and 3 button mouse.
1 That was back in the days when they had VC money …
July 13, 2010 10:39 AM
July 12, 2010
Sniper: Ghost Warrior is a standard first-person shooter based on the Chrome 4 engine. The marketing suggests this game is aimed at those who prefer stealth and strategy over outright shoot’em’up action. After a brief, optional, training run you are dropped into the action, sniper rifle in hand.
Visually I find the game very odd. Environments are very rich indeed and this game features some of the best foliage I have seen in a PC game. Certainly better than Just Cause 2, somewhat better than Crysis, and yet, at the same time, you look at scenery such as buildings and vehicles and are disappointed. There’s none of the beautiful detail that JC2 set the standard for.
As you start the game, it’s all pretty obvious, move from point A to point B, perhaps shooting some baddies on the way. You quickly realise just how tightly scripted the game is, and how shallow some of the segments are, and you very quickly feel hemmed in by the tiny (I’ve been playing JC2) sections of world you can explore.
It’s when you start to move around that the worst part of the game makes itself obvious. You are a sniper, wearing a ghillie suit and moving slowly and quietly around in dense jungle foliage. Bullets will start pocking around you, you won’t have a clue where from bar a very vague red arrow in the middle of your screen. What’s happened is that you’ve tripped over some enemy AI who’s managed to pick you out from a distance of about 150 meters.
You won’t be able to see him, but he’ll cheerfully keep shooting at you, not often hitting, until you stand up so your head is out of the undergrowth and eventually work out where he is. By this time you’ll have moved enough that more eagle-eyed AI join in. You die, you get to do it again. It’s very very dull.
At this point you’ll realise that the sniping system is confusing and not very good. Other than the target’s movement there are no real visual clues as to why the bullet mark is where it is. It feels a bit random and sterile.
You’re not always just sniping, there are some sections of standard let-rip-on-full-auto. You’re a fully trained, fit, agile sniper clearing out an oil rig. Yet you somehow cannot make it over a knee-high rail to go down some stairs. Eventually you’ll realise there’s a small panel you have to shoot to make a section of the rail disappear. You’ll check your calendar to make sure it’s not 5 years ago.
The bullet camera is a straight ripoff, accidental or intentional, I don’t know, of that given to us by Sniper Elite back in 2005. Given the choice between the two games, I’d suggest picking up Sniper Elite and playing that instead.
If you’re really intent on buying this game, I’d just wait a bit. It’ll be reduced in price quickly enough as it really is fairly poor.
July 12, 2010 06:38 PM
Recently, I needed some more presentation logic in my html templates than django templating language would allow, so I looked into getting Django 1.2 and Jinja2 playing nicely.
The main caveat is I also use the admin and have legacy parts of the site that still use the old django templates. So I was hoping to do both and it turned out to be easy! I can even review the context in the Django
July 12, 2010 12:01 PM