Wednesday, June 25, 2014

Netbooting my iMac G3

I recently inherited an iMac G3 from a friend moving away and wanted to get Debian Wheezy on it via network boot. Here's how. My original resource was This post distills those instructions to the bare minimum.

Preparing a Netboot Server

Fully automatic netboot requires a TFTP server to provide a boot image and a BOOTP server to advertise the image's availability. The Open Firmware boot command allows us to directly specify a TFTP server address and image, so we can skip the BOOTP part. So we'll just need a TFTP server with the right Debian netboot image.

I'm using a Debian wheezy installation in a virtual machine for my tftpd server.

Setting up tftpd

Most guides suggest using the "tftpd-hpa" package. The version in Debian wheezy seems to be broken, so I'm going for "tftpd". Run:
sudo apt-get install tftpd tftp
sudo mkdir /srv/tftpd

Next edit /etc/inetd.conf. Find the line specifying the command to start the tftpd server as "/usr/sbin/in.tftpd /srv/tftp" and add an argument "-s" before the directory name; that section of the line should read "/usr/sbin/in.tftpd -s /srv/tftp". This tells tftpd that when it receives a request for an absolute path like "/vmlinuz", it should serve the file "/srv/tftp/vmlinuz" instead of indicating that access is denied for the real absolute path, which is important to make the standard Debian netboot image work without modification.

Finally restart inetd:
sudo service openbsd-inetd restart

Preparing the Debian netboot image

Next we need to download the contents of the powerpc netboot image folder to /srv/tftpd. For wheezy, here's the command:
lftp -c mirror /srv/tftp

Let's test and see if we can download something:
tftp> get boot.msg
tftp> exit

If the "get boot.msg" command terminates, you've set tftp up correctly.

Netbooting the Mac

Boot the Mac, holding Command-Option-O-F. At the Open Firmware prompt, enter:
boot enet:<your tftpd server ip address>, yaboot

Once you get to the yaboot prompt, hit enter. From there you should be in the standard Debian installer.

Monday, February 10, 2014

Yet another Mac SSH SOCKS proxy script

Comcast hasn't been handling video streaming very well lately, so I thought I'd try through a VPN. I've already got a private server with SSH access and unlimited bandwidth. SSH has a flag to present a SOCKS proxy to the client machine and forward through the connection and a SOCKS client is built in to the OS X networking stack, so we'll give that a try. I found one or two scripts to establish a the proxy with SSH and configure OS X to use it, but they don't handle error conditions very nicely and require me to enter an admin password twice - once to establish the connection, and once to break it down. Here's my entry in the genre, followed by a description of how it works.

Launching SSH

We can launch the proxy with:

ssh -ND 1080 $host
'-N' keeps the connection open without running a command; '-D 1080' configures the SOCKS proxy on port 1080. Ideally we want to try to start the SSH tunnel first so that if it can't connect we don't bother to prompt for an admin password and enable, then disable, the proxy configuration. We'll need to keep the SSH connection open while we complete the subsequent configuration steps, so we want to launch it as a background subprocess. That's pretty easy to do with python's subprocess module:
import subprocess, sys
host = sys.argv[1]
ssh = subprocess.Popen(['ssh', '-ND', '1080', host])
# configure OS X to use the proxy here...
However, that doesn't give us any way to know when it has successfully connected and we can move on. We need ssh to print something out upon a successful connection, and we need our script to look for that output. Let's use the ssh LocalCommand option, which runs a command in your shell once the connection has been established. We'll just echo a string we can look for from the script.
import subprocess, sys
host = sys.argv[1]
ssh = subprocess.Popen([
    'ssh', '-ND', '1080',

    # Have ssh print 'connected' after successful connection
    '-o', 'PermitLocalCommand=yes',
    '-o', "LocalCommand=echo connected",



if ssh.stdout.readline() == "connected\n":
    # configure OS X to use the proxy here...

Configuring OS X to use the proxy

It's easy enough to configure use of a SOCKS proxy from Network Preferences, but it takes a few clicks. Let's use the networksetup tool on the command line instead. Initially we need to point it to localhost at the right port:

sudo networksetup -setsocksfirewallproxy Wi-Fi localhost 1080
Subsequently, we can turn it on:
sudo networksetup -setsocksfirewallproxystate Wi-Fi on
and off:
sudo networksetup -setsocksfirewallproxystate Wi-Fi off
For our implementation in python we could just call each of those commands with Popen as above. But if there's a long time between turning the proxy configuration on and turning it off, sudo will ask for our password both times. We can do better. Let's launch a root privilege shell with with "sudo -s" and send it commands:
proxy_command_base = ['networksetup', '-setsocksfirewallproxystate', 'Wi-Fi']
admin_shell = subprocess.Popen(
        ['sudo', '-s'],
        # Line buffered so we're sure the shell gets our commands immediately.

admin_shell.stdin.write(' '.join(proxy_command_base + ['on']) + \
        " && echo 'SOCKS proxy via %s on. CTRL-C to turn off.'\n" % host)


admin_shell.stdin.write(' '.join(proxy_command_base + ['off']) + \
        ' && echo "SOCKS proxy off."\n')

No matter how long the SSH connection stays open, when it terminates we'll still be able to turn off the proxy configuration without authenticating again.

We still need to handle clean termination of the connection, however. Let's allow the user to disable the proxy by sending our script SIGINT, eg. pressing CTRL-C. When we press CTRL-C, the shell sends SIGINT to each process in the current process group. That'll include our python interpreter, the ssh process, and the privileged shell. We want ssh to respond by terminating, but we want the other two processes to stay alive so we can turn the proxy configuration off. We can keep our script alive by catching the KeyboardInterrupt exception:

    # configure proxy here

# SIGINT will have killed ssh; carry on to clean up SOCKS config.
except KeyboardInterrupt:

# disable proxy configuration here
Finally, we need to stop the privileged shell from exiting. We'll use the preexec_fn option of the Popen object to remap SIGINT so that it's ignored in the subprocess:
admin_shell = subprocess.Popen(
        ['sudo', '-s'],

        # Line buffered so we're sure the shell gets our commands immediately.


        # Don't let SIGINT (ctrl-c) kill the shell - we need to use it to clean up.
        preexec_fn = lambda: signal.signal(signal.SIGINT, signal.SIG_IGN)
That's about it. Comments welcome.

Saturday, November 9, 2013

USB and Network device issues under Linux on a newer Gigabyte motherboard

Was just helping a friend install Linux on a machine with a 970A-D3 Gigabyte motherboard. A few tips for others going down that path:

1. The motherboard supports UEFI,  but Windows was installed with BIOS emulation. We needed to install Linux in BIOS mode as well to get a compatible partitioning scheme, but the USB device we were using booted in EFI mode by default (for those distros that supported it). Using the F12 boot device menu on boot allowed us to select to boot the USB device in non-EFI mode.

2. Only some of the USB ports seemed to work for booting from USB or for use in linux once booted. We saw errors like:
usb 3-1: device descriptor read/64, error -32
Enabling the "IOMMU Controller" option in the motherboard configuration fixed this.

3. The built in ethernet device appeared to be available, but refused to connect to any network. the IOMMU Controller option fixed this too.

Tuesday, October 22, 2013

Python segfault with OS X 10.9 Mavericks

If you're using python from's mac installer and you've just upgraded to Mavericks, you'll find that the interactive console segfaults after the second command you type:

Python 3.3.2 (v3.3.2:d047928ae3f6, May 13 2013, 13:52:24) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1
>>> 2
[1]    1851 segmentation fault  python3

The root cause is this bug:

Though it looks like the issue has been resolved in the source, the fix hasn't made it to the downloadable builds as of this writing. The fix is to use either Apple's included version of Python 2.7.5, or to use python from homebrew.

You'll want to uninstall the existing version of python.  Instructions for that are here. In my case I wanted to remove all versions, so the commands were:

sudo rm -rf /Library/Frameworks/Python.framework
cd /usr/local/bin; 
ls -l . | grep '../Library/Frameworks/Python.framework' | awk '{print $9}' | sudo xargs rm

At this point /usr/bin/python should be the only remaining version in your path and will point to the Apple supplied Python 2.7.5. If you're happy with that, you can stop here!

Note that site packages are within /Library/Frameworks/Python.framework, so any that you've got installed will need to be replaced. To get a decent python package manager back, do:

sudo easy_install pip

If you want Python 3, install it with homebrew.

Monday, October 21, 2013

Partitioned Backup Retention

I manage some servers on Amazon EC2, and recently I've been rewriting our backup scripts. Previously we had shell scripts that made a tarball, encrypted it via openssl, and dumped it in a directory. Old backups were cleaned up with a find command, and then the whole directory was synced to s3 with s3sync. Our retention policy was simply to keep the last month's daily backups, mostly because this was easy to do with find. S3 storage is cheap but definitely not free, so we'd like to do a bit better.


I set out to find a new rotation scheme based on the following assumptions:
  1. The density of backup points as a function of age should be exponential, with many more recent backups than older backups.
  2. Backups will be triggered regularly, but might be skipped due to downtime, script failure, etc. As such, our rotation scheme should simply take a set of dates and return a list of those to delete. No special marking of backups to retain longer should be required when they are made.
  3. No incremental backups.
  4. Keep as few backups as possible while still covering a month.

Existing Options

Taking a quick look at wikipedia's backup rotation scheme page, we find a few existing options:

First In, First Out is what we were using previously, and fails on point 1 above.

Grandfather-father-son accomplishes most of what I'm looking for, but the most obvious way to use it and keep a month's backups would require more storage than I'd like - 24 hourly backups, 7 daily, 4 weekly. I tried to figure how to use the Python GrandFatherSon module to keep a more sparse set, but couldn't quite figure out what it was doing.

Tower of Hanoi is formulated for use rotating removable media. I'm looking for something similar, but that fits better with point 2 above.

A New Scheme

I make backups every hour. Just after I make a backup, I gather the datestamps of all the backups I've got stored on s3 and pass them to the rotation function. It returns a set of datestamps of backups that should be deleted.

As configuration for the rotation function, select a set of retention targets, or approximate ages around which backups should be kept. I selected 1 day, 7 days and 28 days.

The rotation function partitions the set of existing backup dates it is passed into groups between retention targets. In my case, there is a group made between now and 1 day ago, a group between 1 and 7 days old, and a group between 7 and 28 days old. Then delete all but the oldest and newest backup within each such group. As a special case, delete all but the youngest backup older than the last retention target.


The plot above shows the resulting distribution of backups over time, with the retention targets shown as the blue lines.

We cover a month with 8 backups.


A script with the rotation function (using my retention targets) and a program to visualize the results with matplotlib are on github. CC0 license.


Initially I kept only the oldest backup in each group. This resulted in big gaps when a backup aged into a new group where it was deleted as an older one was still present, while the younger group now had no backup.

For similar reasons, it is important to keep one backup older than the oldest retention target.

Sunday, September 23, 2012

Sins of a Solar Empire Trinity (Steam) on Mac with Wineskin

Sins of a Solar Empire runs beautifully under wine on Mac, but wasn't easy to get installed. Here's what worked for me.

Install Wineskin

I tried to install vanilla wine from homebrew first, but that is rather difficult right now because it doesn't compile well under llvm, and one of its dependencies needs some difficult to discover flags to build correctly.

Once you've got Wineskin, run it and install the latest wrapper and engine (I got things working with WS91.5.13). Create a new blank wrapper.

Install Steam

Fire up your new wrapper (located in your home directory under Applications/Wineskin). This should launch the wineskin app. After you've installed some things, it will prompt you to select an exe to run when launched, and it will be harder to get to the Wineskin control panel for the wrapper. You can always get to it by right clicking the wrapper .app, clicking "view package contents" and then launching the contained

At some point wine will offer to install mono and gecko. Not sure if both are needed, but I installed both and it worked.

Go to advanced -> tools -> winetricks and install the one for steam. I tried just installing steam from the windows .msi without using winetricks and the steam client was pretty messed up - no text because of missing fonts, etc. That route seemed to work fine using the WS91.4.1 engine, but I wanted to use the latest.

Download Sins via Steam

Everything here should work normally, until the app is downloaded and ready to launch. Gets through the DirectX setup and the Visual c++ redistributable runs but freezes. Just quit out of everything and start it up again and it should skip that bit the next time. Now you'll get to the stardock activation screen. This is where stuff breaks down - the register button doesn't do anything.

Getting Activation to Work

Update: supposedly activation tool included with the most recent Steam version works, per
For whatever reason the version of the activation tool provided with Sins doesn't work. However, we can get another. We'll take the one from Stardock's Stardock Central app.

Installing Stardock Central

 Download the installer here:
That installer didn't seem to run properly through wineskin's install software tool. So we need to copy the installer into our wrapper and then run it from the command line. Open up the wrapper with "view package contents" and drop the installer into the drive_c folder there. Now, fire up the Wineskin app for your wrapper and go to Advanced -> Tools -> Command Line. Change to the top level of C with:
cd \
And then run the Stardock Central installer with 

Copying the Activation executable

Now once again view package contents on your app. Navigate to 
drive_c/users/<your user name>/Local Settings/Application Data/Stardock/Stardock Central

Make sure you don't have any of the Wineskin apps open, and then copy sdActivate and Activate.lng, and paste those into
drive_c/Program Files/Steam/steamapps/common/Sins of a Solar Empire Trinity/

Now fire up your wrapper again, launch Sins from steam again, and this time you should get a different activation window that actually works!

Windowing and Video Configuration

You probably want to run in full screen mode, so configure that from the for your wrapper -> Set Screen Options. Choose the override radio button, and then the fullscreen button.

I'm running an early unibody MacBook Pro and found that I had to turn down the graphics settings in Sins to make it run smoothly.


Friday, May 20, 2011

PyWSClient Release 1

A while back at work we needed a client to exercise our SOAP web services. For a while we used the SOA Client firefox plugin, and we also looked at the soapUI eclipse plugin. Neither quite did it for us - soapUI had a terrible interface and SOA Client produced messages that were not WS-I Basic profile compliant, so our server side choked on them.

I was also looking for an excuse to learn PySide, so I wrote my own. It is about 150 lines of python code, and makes use of the suds soap client for python and of course PySide to draw the GUI. Suds was super cool, as it built up a object representation of the service interface for me to dynamically build the needed inputs for each service. The whole thing is rather alpha at the moment - no real error messages if you do anything wrong, default window sizing is off, etc. - but it does work (at least for me). So in the open source spirit of release early, release often I'm putting it out there if anyone wants it. No license - public domain.

 - Select a WSDL address and sections for each call with fields for the parameters are provided
 - Supports HTTP Basic authentication
 - Shows the SOAP response text as well as the XML for the request and response

You can directly run the .py script if you have suds and Qt and PySide installed. I've also built a Mac .app (built it on Snow Leopard, so likely won't work for anything below that) that you can get from the DMG download. Feel free to comment or email me if it is useful to you or if you have any suggestions / patches.

.py file:

DMG for Mac (22 MB):