q2java and qwpython on GitHub

Quite some time ago I worked on a couple interesting projects, q2java which embedded Java into a Quake2 server and then allowed for games to be written in Java; and qwpython, which wrapped up the QuakeWorld dedicated server engine as a Python module and came with a QuakeC -> Python translator, so existing QW games like CTF could be converted to Python and hacked on from there.

Some time back I had created Subversion repositories of the various releases of those packages (didn't really know or use VCSes back then), and had them on an Apache mod_svn server. Well, SVN is kind of a PITA, and I'd like to not have to keep that server config going, so I looked at converting those repos to something else.

First tried hgsvn, which has worked pretty decently for smaller or simpler repos, but something in the q2java one make it crap out.

Next tried the hg convert extension, which worked better, but only when using a local SVN URL (like file://...), and then didn't manage to pick up the tags correctly.

Decided to give Git a try, first with Converting a Subversion repository to Git (in seven steps). It worked, but was kind of a nasty process for a Git newbie to wade through. The tags still didn't seem quite right.

Finally, realized GitHub has its own Subversion import built right into the website, and gave that a try. Very very nice, made importing the svn repo a breeze, and seems to have gotten the tags just right. Only took two steps: enter the svn URL, fill in a translation table of svn userids to git authors. I'd recommend this highly for anyone looking to move off svn. See the q2java and qwpython results here.

PyCon 2012

Headed off for PyCon 2012 tomorrow. Last one I was at was 2007 in Dallas, can't believe it's been 5 years. Looking forward to seeing some cool stuff, and maybe playing some games in the evening.

Debian GNU/kFreeBSD in a FreeBSD Jail - part 2

Previously I wrote about getting Debian GNU/kFreeBSD working in a jail. I've worked on it a bit more, polishing things up so I've got it working pretty seamlessly with my existing ezjail FreeBSD jails, so everything starts automatically, and you can use the ezjail commands to stop/restart the jail.

Here are a few more notes about how things got setup for my jail I named debian:

Kernel Modules

In /boot/loader.conf, I added these lines:

fdescfs_load="YES"
linprocfs_load="YES"
linsysfs_load="YES"
tmpfs_load="YES"

Mounting Filesystems

Created /etc/fstab.debian and populated with:

linproc     /jails/debian/proc      linprocfs       rw 0 0
linsys      /jails/debian/sys       linsysfs        rw 0 0
tmpfs       /jails/debian/lib/init/rw   tmpfs       rw 0 0

ezjail Config

Created /usr/local/etc/ezjail/debian with these contents:

export jail_debian_hostname="debian"
export jail_debian_ip="127.0.0.6"
export jail_debian_interface="lo0"
export jail_debian_rootdir="/jails/debian"
export jail_debian_mount_enable="YES"
export jail_debian_devfs_enable="YES"
export jail_debian_devfs_ruleset="devfsrules_jail"
export jail_debian_fdescfs_enable="YES"
export jail_debian_exec_start="/etc/init.d/rc 3"
export jail_debian_flags="-l -u root"

I also tried adding an IPv6 address to the jail, and that seems to work OK

So you can now stop/start with jail with

service ezjail.sh stop debian
service ezjail.sh start debian

Connect to the jail console

If you create a symlink for login (so that from the jail's POV there's a /usr/bin/login, like there would be on a FreeBSD jail)

cd /jails/debian/usr/bin/
ln -s ../../bin/login .

then you can use the ezjail-admin command to get a console in the jail, with:

ezjail-admin console debian

Otherwise, I've been using my own script to get a console (which assumes bash is installed in the jail), named /usr/local/sbin/jlogin

#!/bin/sh
#
# log into a jail, running bash
#
JID=`jls | grep " $1 " | awk '{print $1}'`
exec jexec $JID env -i PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin TERM=$TERM EDITOR=$EDITOR LANG=$LANG HOME=/root bash -l

That runs as:

jlogin debian

Debian GNU/kFreeBSD in a FreeBSD Jail

I've been a FreeBSD user for quite some time, going back to 3.3 or so, and for the last serveral years have also been working a lot with Ubuntu Linux. So when I ran across Debian GNU/kFreeBSD, which provides a Debian environment on top of a FreeBSD kernel, I was somewhat intrigued. It got even more interesting when I found a tutorial on setting up GNU/kFreeBSD in a jail. The notion of having a Debian environment on my home FreeBSD server without having to get something like VirtualBox running was just too good to pass up.

I got it running fairly decently, but along the way ran into some small problems - and thought I'd jot down what they were and what the fixes were.

FreeBSD Update

At first, I was using FreeBSD 8.2-RELEASE, and used debootstrap to install Debian Squeeze, as the tutorial showed. Once inside the jail, things sort of worked, but most commands, aptitude especially, would die with:

User defined signal 1

It turns out you need a newer kernel than 8.2 to run kFreeBSD in a chroot, as is mentioned in the FAQ. I upgraded my FreeBSD kernel/world to 8.3-PRERELEASE (2012-02-22), and the "signal 1" problem went away.

Debian Update

The next problem was that aptitude would still die, with:

Uncaught exception: Unable to read from stdin: Operation not permitted

After reading about this bug in cwidget, it seemed an upgrade to Wheezy was needed to fix the problem - and sure enough that problem went away.

kbdcontrol and /dev/console

The upgrade to Wheezy didn't go entirely smoothly, mainly due to the kbdcontrol package (required by sysvinit) being unable to access /dev/console in the jail. I wasn't worried about keeping things in the jail isolated for security reasons, so I went ahead and added /dev/console on-the-fly to the running jail by running outside the jail:

devfs -m /jails/debian/dev rule add path 'console*' unhide
devfs -m /jails/debian/dev rule applyset

After that, the kbdcontrol package was able to be upgraded, and I seem to have a Wheezy FreeBSD jail now. Very cool.

UPDATE: A followup talks more about the actual file changes made to run as an ezjail

VM Serial Console part 2

Fooling around a bit more with accessing a VM's serial console from a KVM hypervisor with

virsh console mymachine

I found one thing that doesn't carry over from the host to the VM is the terminal window size, so if you try to use something like vim through the console connection, it seems to assume a 80x25 or so window, and when vim exits your console is all screwed up.

It looks like a serial connection doesn't have an out-of-band way of passing that info the way telnet or ssh does, so you have set it manually. You can discover your settings on the host machine with

stty size

which should show something like:

60 142

on the VM, the same command probably shows

0 0

zero rows and columns, no wonder it's confused. Fix it by setting the VM to have the same rows and columns as the host with something like:

stty rows 60 columns 142

and you're in business.

Enabling VM serial console on stock Ubuntu 10.04 server

So I've been running Ubuntu 10.04 server virtual machines on a host running KVM as the hypervisor, and thought I should take a look at accessing the VM's console from the host, in case there's a problem with the networking on the VM.

The hosts's VM libvirt definition shows a serial port and console defined with

<serial type='pty'>
  <source path='/dev/pts/1'/>
  <target port='0'/>
  <alias name='serial0'/>
</serial>
<console type='pty' tty='/dev/pts/1'>
  <source path='/dev/pts/1'/>
  <target type='serial' port='0'/>
  <alias name='serial0'/>
</console>

and within the stock Ubuntu 10.04 server VM, dmesg | grep ttyS0 shows:

[    0.174722] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
[    0.175027] 00:05: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A

So the virtual hardware is all setup on both ends, but ps aux | grep ttyS0 doesn't show anything

We need to have a process listening to that port. To do that, create a file named /etc/init/ttyS0.conf with these contents:

# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]

respawn
exec /sbin/getty -L 38400 ttyS0 xterm-color

and then run

initctl start ttyS0

back in the host machine run virsh list to find the name or id number of your VM, and then

virsh console <your-vm-name-or-number>

to connect, hit return and you should see a login prompt.

Customizing cloned Ubuntu VMs

I was playing with creating and cloning Ubuntu virtual machines the other day, and got to the point where I had a nicely setup reference image that I could just copy to fire up additional VMs that would be in a pretty usable state.

There are a few things within a cloned VM that you'd want to change if you were going to keep the new instance around, such as the hostname, SSH host keys, and disk UUIDs. I threw together a simple shell script to take care of these things automatically.

#!/bin/sh
#
# Updates for cloned Ubuntu VM
#

#
# Some initial settings cloned from the master
#
ROOT=/dev/vda1
SWAP=/dev/vdb1
LONG_HOSTNAME=ubuntu.local
SHORT_HOSTNAME=ubuntu

if [ -z $1 ]
then
    echo "Usage: $0 <new-hostname>"
    exit 1
fi

# 
# Update hostname
#
shorthost=`echo $1 | cut -d . -f 1`
echo $1 >/etc/hostname
hostname $1
sed -i -e "s/$LONG_HOSTNAME/$1/g" /etc/hosts
sed -i -e "s/$SHORT_HOSTNAME/$shorthost/g" /etc/hosts

#
# Generate new SSH host keys
#
rm /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-server

#
# Change root partition UUID
#
OLD_UUID=`blkid -o value $ROOT | head -n 1`
NEW_UUID=`uuidgen`
tune2fs -U $NEW_UUID $ROOT
sed -i -e "s/$OLD_UUID/$NEW_UUID/g" /etc/fstab /boot/grub/grub.cfg

#
# Change swap partition UUID
#
OLD_UUID=`blkid -o value $SWAP | head -n 1`
NEW_UUID=`uuidgen`
swapoff $SWAP
mkswap -U $NEW_UUID $SWAP
swapon $SWAP
sed -i -e "s/$OLD_UUID/$NEW_UUID/g" /etc/fstab

#
# Remove udev lines forcing new MAC address to probably show up as eth1
#
sed -i -e "/PCI device/d"     /etc/udev/rules.d/70-persistent-net.rules
sed -i -e "/SUBSYSTEM==/d" /etc/udev/rules.d/70-persistent-net.rules

echo "UUID and hostname updated, udev nic lines removed,  be sure to reboot"

I'd then run it on the cloned machine with something like

update_clone.sh mynewmachine.foobar.com

This somewhat particular to my specific master VM, in that it's expecting one disk dedicated to root and one disk dedicated to swap, and the VM was created with ubuntu.local as the hostname. Hopefully though it'll give some ideas about what to look for and how to script those changes.

WTF!, when did those files get deleted ?!

A guy I work with recently showed me a bad situation he had with iPhoto, some family videos had gone missing from his harddisk. The thumbnails were in iPhoto, but when he clicked on them, they wouldn't play because the files were gone. He had Time Machine backups, but they were gone even in the oldest copies. Apparently the files had been deleted quite a while ago.

This got me thinking about a huge problem with backups - you can be very diligent about keeping them, but if you have no idea that something's missing they don't do you much good.

What you need is something that would alert you of unexpected deletions. Thinking about my friend's experience, I whipped together a small shell script that would be run periodically to take an inventory of the iPhoto originals, and if something was removed compared to the last run, it would place a file on my desktop that hopefully I'd notice, listing a diff of the changes.

I saved this on my disk as /Users/barryp/bin/inventory_iphoto.sh

#!/bin/bash
#
# Check if anything has been deleted from the iPhoto Originals
# folder, and if so, place a file on the Desktop listing what's
# gone missing
#

CHECK_FILE=~/Library/Logs/com.diskcompare.inventory_iphoto.txt

find ~/Pictures/iPhoto\ Library/Originals -type f | sort >$CHECK_FILE.new
if [ -e $CHECK_FILE ]
then
    diff -u $CHECK_FILE $CHECK_FILE.new >$CHECK_FILE.diff
    grep '^-/' $CHECK_FILE.diff >$CHECK_FILE.gone
    if [ -s $CHECK_FILE.gone ]
    then
        mv $CHECK_FILE.diff "$HOME/Desktop/DELETED iPhoto files-`date "+%Y-%m-%d %H%M%S"`.txt"
    else
        rm $CHECK_FILE.diff
    fi
    rm $CHECK_FILE.gone
fi
mv $CHECK_FILE.new $CHECK_FILE

and made it executable with

chmod +x /Users/barryp/bin/inventory_iphoto.sh

Other than the directory name to check, there's nothing iPhoto or even Mac specific about this, it could be easily adapted for other uses.

You can run the script manually too anytime you want, and you can test this out by running once, editing ~/Library/Logs/com.diskcompare.inventory_iphoto.txt to add a line (starting with a /), and then running the script again to make sure a diff file pops up on your desktop showing how the line you manually added is gone in the updated inventory.

Next, I setup the Mac to run this once a day or so, by creating a launchd job saved as /Users/barryp/Library/LaunchAgents/com.diskcompare.inventory_iphoto.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.diskcompare.inventory_iphoto</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/barryp/bin/inventory_photo.sh</string>
    </array>
    <key>StartInterval</key>
    <integer>86400</integer>
</dict>
</plist>

(You'll have to change the path to the script to suit your setup, unfortunately it doesn't seem you can use tilde expansion in a launchd job)

and then activated it in launchd with this command at the command prompt:

launchctl load ~/Library/LaunchAgents/com.diskcompare.inventory_iphoto.plist

Fortunately my friend found a really old harddisk that happened to have his missing videos on it, but he's even more lucky to have noticed the problem in the first place.

With a periodic inventory as described above, hopefully a person would become aware of a problem with in a day or two, in plenty of time get the files out of a backup system.

Make sure virtualization is enabled in the BIOS

I just wasted a fair amount of time on a RedHat 6.1 box being setup to be a hypervisor with KVM, trying to figure how why when I ran virsh version it was telling me among other things

internal error Cannot find suitable emulator for x86_64

All the appropriate packages such as qemu-kvm were installed, but it just didn't seem to want to work. Finally as I was about to try reinstalling RHEL, I remoted into the actual console and saw:

kvm: disabled by bios

Doh!, and looking back in /var/log/messages the same thing was buried deep within all the boot noise. While trying to figure this out I managed to just be looking for virt or qemu in the logs and somehow didn't search for kvm. Enabled virtualization in the BIOS and everything's gravy now.

So there you go, if you're Googling that first error message and get lots of other nonsense, look for the message about the BIOS.

iPXE on OpenBSD

I got a chance to try Enhanced PXE booting with iPXE on an OpenBSD box and found a couple things that don't work...

Firstly the stock DHCP daemon does not support if statements in the configuration, so this bit to keep iPXE from being told to load iPXE (a loop) didn't work

if exists user-class and option user-class = "iPXE" {
    filename "http://10.0.0.1/pxelinux.0";
    } 
else {
    filename "undionly.kpxe";
    }

To get it to work I had to follow the alternate advice on the chainloading documentation about Breaking the loop with an embedded script.

However, recompiling udnionly.kpxe on OpenBSD 4.9 failed, with the error:

net/fcels.c: In function 'fc_els_prli_detect':
net/fcels.c:1108: internal compiler error: Segmentation fault: 11
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
gmake: *** [bin/fcels.o] Error 1

(this was GCC 4.2.1). FreeBSD 8.2 also has the same version of GCC and comes up with the same error.

I ended up using an Ubuntu 10.04.3 box, which I believe was GCC 4.4.x, and that worked fine.