Wednesday, December 30, 2009

Ubuntu 9.10 and GeForce 7800 GT

Note: This issue seems to affect Ubuntu 9.04 Jaunty, and Ubuntu 9.10 Karmic, in both 32-bit and 64-bit versions. I've seen some anecdotal evidence that it affects earlier releases too.

I recently set out to install Ubuntu 9.10 on my aging old home PC: an Athlon64 3800+, 2 GB RAM, decent (at the time) Asus board. Most importantly, this machine has an NVidia GeForce 7800 GT video card. To my surprise (having installed Ubuntu on numerous other machines of various age), I had a myriad of problems with the install. The symptoms were as follows:

  • Installer would freeze with corrupt looking graphics if I tried to change certain options
  • If I took all defaults in the installer, I could get the OS installed, but it would lock up (again with corrupt looking graphics on screen) when selecting my user name in gdm when X started up

Googling around at length revealed others with similar problems, and the common element was the GeForce 7800 GT video card. Related links:

I don't really know what the root cause is here, but using the above info, here's a work-around: (This assumes you got the OS installed somehow, and are now at the point where you want to login, but cannot due to X locking up.)

  1. Get to a terminal either by recovery booting to the shell (netboot), or by hitting ctrl-alt-f1 at the graphical login screen.
  2. Add the NVidia ppa to get access to their newest drivers:
    sudo add-apt-repository ppa:nvidia-vdpau/ppa
    sudo apt-get update
  3. Remove any existing NVidia driver:
    sudo apt-get purge nvidia-glx-*
  4. Install the newest driver:
    sudo apt-get install nvidia-glx-195
  5. Configure the newly installed driver:
    sudo nvidia-xconfig
  6. Reboot and you should be good to go.

Thursday, December 17, 2009

EC2, fabric, and "err: stdin: is not a tty"

Recently, I've been using fabric to script up some deployments to EC2. My EC2 server is running the 32-bit Ubuntu Jaunty 9.04 server image provided by Alestic, but I suspect this issue applies across lots of different OS variants. Fabric seems to work well, but I was getting a nuisance message when running commands on my EC2 instance: err: stdin: is not a tty. You can even see the message in action in the output of this (very useful) intro to fabric that happens to show an EC2 example.

Some searching turned up that this is a result of a command in a .profile or .bashrc on the remove host expecting the shell to be interactive, which it is not with fabric.

In my case, the culprit was /root/.profile, in particular the command mesg n. To fix the message, I wrapped the mesg call in a check for an interactive tty:
if `tty -s`; then
    mesg n
fi

Monday, December 14, 2009

Scala Lift, Jetty 6, static content, and Virtual Directories

I have a simple web application written using the Lift framework. I am using Maven to build and test with, in the way recommended by various Lift docs (i.e. I use mvn jetty:run to launch the app). I ran into an issue when it came to serving static image content, however.

  • The app is called webapp
  • The app deploys to /webapp
  • Images are on local disk at /hdd/data/images (i.e. not in the .war)
  • Want to access images from /images (i.e. outside of the context root of the Lift app)
  • Needs to work when developing and running with Maven's jetty:run

The main issue was simply "how do I setup a virtual directory from http://server/images to /hdd/data/images on disk?" This seems trivial, but I had a really difficult time finding any straightforward docs on how to do it. My complicating requirement was that it had to work when developing with jetty:run. For "real" deployment, the images location will be manually configured, so whether this makes sense in production is not a factor here.

Long story short: you can configure the maven-jetty-plugin to load up additional "context handlers" at startup. Some decent info on this here. A context handler of type WebAppContext will do the job as far as acting like a virtual directory. Here's the config from pom.xml for the project:

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <configuration>
        <contextPath>/webapp</contextPath>
        <scanIntervalSeconds>0</scanIntervalSeconds>
        <contextHandlers>
            <!-- setup a simple webapp to serve our images -->
            <contextHandler implementation="org.mortbay.jetty.webapp.WebAppContext">
                <contextPath>/images</contextPath>
                <resourceBase>/hdd/data/images</resourceBase>
            </contextHandler>
        </contextHandlers>
    </configuration>
</plugin>

I make no claims about this being secure or the best way to do things, but after a lot of trial and error it does at least work.

Wednesday, November 4, 2009

Python: lambda, partial, and scopes

Python rarely surprises me, which is a good thing. Unfortunately, today I was surprised by how lambda works. It made me worry that I had no idea what I was doing at all. (And I guess I didn't!) A lambda captures a reference to any variables it closes over (vs. captuiring the value of those variables), so in a loop context you can get some bizarre effects.

It turns out this is well documented, but I'm writing this as a note to myself if nothing else.

def adder(x, y):
    return x + y

# make a list of functions with lambda that close over i and call adder()
fns = [lambda x: adder(x, i) for i in range(10)]

# call each of our new functions with a constant value
# expected output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]

[f(13) for f in fns]
# output: [22, 22, 22, 22, 22, 22, 22, 22, 22, 22]

# buh!?

The functions that are created in the list fns each capture a reference to the local variable i, but that reference is constantly being rebound to different values as we iterate through range(10). The last value i takes in range(10) is 9, so all of the functions end up being lambda x: adder(x, 9). Below are two "fixes".

Fix 1: capture the value of i as a default argument to the lambda. Hacky, but supposedly idiomatic for this sort of issue.

fns = [lambda x1, x2=i: adder(x1, x2) for i in range(10)]
[f(13) for f in fns]
# output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]

Fix 2: use functools.partial. I prefer this.

from functools import partial
fns = [partial(adder, i) for i in range(10)]
[f(13) for f in fns]
# output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]

In retrospect, this really shouldn't be surprising. I think the main issue here is that in these examples i is just a plain old integer, which, due to my Java background, I tend to think of as a primitive Java int that can only be passed by value. In Python, everything is just references until interpretation time. e.g.

foo = 42
def test():
    print foo
test() # outputs: 42

foo = 100
test() # outputs: 100 (!)

Monday, October 19, 2009

Installing VirtualBox Guest Additions on Ubuntu 9.04/9.10 Guest, Vista Host

Here are some notes on how I installed the VirtualBox 3.0.8 Guest Additions on a 32-bit Unbuntu Server (9.04 Jaunty Jackalope) guest running on a 32-bit Windows Vista host.

The Ubuntu server is a very bare-bones server install running only sshd, so as you'll see below, we have to install gcc and friends.

This info is adapted from a post in the VirtualBox forums.

  1. Mount VirtualBoxGuestAdditons.iso via Devices > Mount CD/DVD ROM > CD/DVD ROM Image...
  2. The .iso file should be located on the Windows host here: C:\PROGRA~1\Sun\VIRTUA~1\VBoxGuestAdditions.iso
  3. Install the Guest Additions on the Ubuntu guest (adapted from http://forums.virtualbox.org/viewtopic.php?p=29316):
    mount /cdrom; cd /cdrom
    sudo apt-get update
    sudo apt-get install build-essential linux-headers-`uname -r`
    sudo ./VBoxLinuxAdditions-x86.run
    cd ~; umount /cdrom
    
  4. Optional cleanup (I didn't bother since I'm using this box as a development server, and will need gcc et al.)
    sudo apt-get remove build-essential linux-headers-`uname -r`
    sudo apt-get autoremove
    sudo apt-get autoclean
    
  5. reboot the guest (possibly not necessary, but I did it)

The guest additions are now installed and running. Next step would be to actually do something with them. In my case, I wanted to mount the c:\ drive of the host (Vista) machine.

To share the entire Vista c:\ in the directory /mnt/c on the Ubuntu guest:
  1. On the host window, go to Devices > Shared folders...
  2. Add new shared folder: Folder Path = c:\, Folder Name = c, not Read-only, check Make Permanent
  3. Add the following line to /etc/fstab:
    c    /mnt/c    vboxsf    rw,gid=1000,uid=1000,auto    0    0
    
  4. Note: I've mounted this as my main user. If you've only created one user on your Ubuntu server, this should work. If in doubt, run id as the user you want to mount the Windows share as.
  5. Create the mountpoint: sudo mkdir /mnt/c
  6. Mount the share (this will happen automatically in the future): sudo mount /mnt/c

Update 28-Dec-2009: I just used this same procedure on Karmic 9.10 and it also seems to work fine there.

Friday, October 9, 2009

Installing PostgreSQL 8.4 on Ubuntu Jaunty (9.04)

Inaugural post!

Ubuntu 9.04 (Jaunty Jackalope) includes PostgreSQL 8.3 via the expected apt-get install postgresql. This is great, but PostgreSQL 8.4.1 has a number of nice features that I want (WITH queries, for example). At first I was just going to wait for Ubuntu 9.10, which is coming very shortly, but I am impatient. It turns out there is a pretty easy "Ubuntu way" to get PostgreSQL 8.4 installed on 9.04 without a lot of headaches (like building from source). The solution is using Ubuntu PPAs.

Add the custom PPA for PostgreSQL to /etc/apt/sources.list:

deb http://ppa.launchpad.net/pitti/postgresql/ubuntu jaunty main
deb-src http://ppa.launchpad.net/pitti/postgresql/ubuntu jaunty main

Get the key for these new sources:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8683D8A2

Update the package list:

sudo apt-get update

Install!

sudo apt-get install postgresql-8.4

PostgreSQL 8.4.1 will now be running, but on port 5433, not the standard 5432. I assume this was done so you can run 8.3 and 8.4 at the same time on Ubuntu 9.04. I only want 8.4.1, so I changed the port and restarted:

sudo sed -i.bak -e 's/port = 5433/port = 5432/' \
    /etc/postgresql/8.4/main/postgresql.conf

sudo /etc/init.d/postgresql-8.4 stop
sudo /etc/init.d/postgresql-8.4 start

These PPAs for PostgreSQL only exist because of Martin Pitt, who appears to be responsible for PostgreSQL on Ubuntu, so many thanks to him!