Archive for November, 2006

REST and Form Retrieval

Tuesday, November 21st, 2006

I have been converting a small Rails application to REST this past week and several issues have come to light surrounding HTML forms. I can’t seem to find a good solution to these problems. First, I want to tackle delivering of arbitrary forms to HTML clients.

In a simple application revolving around one resource, delivering a form to an HTML client (to query against that resource, for example) is a “classic” task. With REST, the single resource has straightforward URIs for all the classic CRUD operations. But the forms that facilitate the CRUD operations are much less clear. For example, if I wish to fetch the clown with ID 1, I can issue an HTTP request like this:

http://example.domain/clowns/1 (HTTP verb GET)

And to update the clown:

http://example.domain/clowns/1 (HTTP verb PUT, with form-encoded attributes)

But how do I deliver the editing form to the client? The first URL in the example only delivers the clown resource itself, not the form to edit the clown. One approach is to treat the form itself as a resource (see reference 2) and allow it to be RESTfully manipulated:

http://example.domain/clownEditForm (HTTP verb GET)

As clean as this looks from the URL perspective, it is ugly in Rails. The resource route mapping available in the recent Simply RESTful Edge Rails enhancements does not permit a second named resource using the same HTTP verb (GET) to use the same controller -so the ClownController couldn’t serve up this form and you would need an additional controller -yech. Another approach is to use a representational tweak via a view parameter:

http://example.domain/clowns/1?view=edit (HTTP verb GET)

In a similar vein, Rails supports view tweaks to the URL with an abbreviated syntax. So to fetch clown ID 1 represented for editing, I would use a URL like this:

http://example.domain/clowns/1;edit (HTTP verb GET)

OK, I can grasp what is going on here. But extending this model is not so easy. For example, what URL would I use for delivering an HTML form to find the closest clowns to a given address? The problem is that I am not delivering a special representation of a clown. In fact, there is no clown at all in this form -just an address field. And I’ll be damned if I am going to create a one-shot address resource (and controller) for this purpose. So where does this leave me? I’ve opted for representational tweaks to the collection resource:

http://example.domain/clowns;queryByAddressForm (HTTP verb GET)

And the corresponding routes.rb declaration:

map.resources :clowns, :collection => {:queryByAddressForm => :get}

Not very satisfactory, but workable.

A twist: what if I want to use this same HTML page for displaying the results of the query (without AJAX) and the query form itself? Now the concept of getting the form and getting the query results have blended into one. This construct is useful in HTML even if it is absurd for a web service or JSON/XML delivery. What to do? I went to this intentionally vague representation:

http://example.domain/clowns;queryByAddress (HTTP verb GET)

This HTTP request will return a page with the empty form at the top and the results (initially empty) at the bottom. The form submits with a GET to the same URL -but this time with a address parameter that causes results (and previous form values) to be included in the returned page:

http://example.domain/clowns;queryByAddress?address=3100+Edgewater+27514 (HTTP verb GET)

In a more general sense, this may be an acceptable paradigm: a GET to a query URL requesting HTML but without the necessary parameters is interpreted as a request for the form. Can I get an “Amen, Brother!” on that? Can I get some built-in Rails support?

At this point I am willing to settle. But I’m still not happy. Part of my problem may be that Rails has not yet made it truly easy to do REST 100% right. A more strictly RESTful approach could be implemented, but for now Edge Rails is using the KISS approach.

ip_conntrack_amanda on Fedora Core

Monday, November 20th, 2006

After working with my NFS server and successfully getting it to work nicely with iptables, I disabled an overly-permissive hole in the firewall of my NFS server -which is also my tape host for amanda. It turns out that amanda was also relying on that hole to backup networked clients. Instead of just opening the hole back up, I experimented a bit. What I found is not good.

First, some background. I have ports 10082 and 10083 opened on the server to support amrecover operation. On the clients, I have 10080 opened to allow the incoming backup requests to connect.

The ip_conntrack_amanda kernel module is supposed to allow the backup daemon running on the client (amandad) to establish a new TCP connection back to the server by marking the incoming packets as RELATED. It is apparently failing:

amandad: debug 1 pid 29550 ruid 33 euid 33: start at Mon Nov 20 09:05:11 2006
amandad: version 2.4.5p1
amandad: build: VERSION=”Amanda-2.4.5p1″
amandad: BUILT_DATE=”Fri Feb 10 21:44:52 EST 2006″
amandad: BUILT_MACH=”Linux hs20-bc1-6.build.redhat.com 2.6.9-22.18.bz155725.ELsmp #1 SMP Thu Nov 17 15:34:08 EST 2005 i686 i686 i386 GNU/Linux”
amandad: CC=”i386-redhat-linux-gcc”
amandad: CONFIGURE_COMMAND=”‘./configure’ ‘–build=i386-redhat-linux’ ‘–host=i386-redhat-linux’ ‘–target=i386-redhat-linux-gnu’ ‘–program-prefix=’ ‘–prefix=/usr’ ‘–exec-prefix=/usr’ ‘–bindir=/usr/bin’ ‘–sbindir=/usr/sbin’ ‘–sysconfdir=/etc’ ‘–datadir=/usr/share’ ‘–includedir=/usr/include’ ‘–libdir=/usr/lib’ ‘–libexecdir=/usr/lib/amanda’ ‘–localstatedir=/var/lib’ ‘–sharedstatedir=/usr/com’ ‘–mandir=/usr/share/man’ ‘–infodir=/usr/share/info’ ‘–enable-shared’ ‘–disable-dependency-tracking’ ‘–with-index-server=localhost’ ‘–with-tape-server=localhost’ ‘–with-config=DailySet1′ ‘–with-gnutar-listdir=/var/lib/amanda/gnutar-lists’ ‘–with-smbclient=/usr/bin/smbclient’ ‘–with-amandahosts’ ‘–with-user=amanda’ ‘–with-group=disk’ ‘–with-tmpdir=/var/log/amanda’ ‘–with-gnutar=/bin/tar’”
amandad: paths: bindir=”/usr/bin” sbindir=”/usr/sbin”
amandad: libexecdir=”/usr/lib/amanda” mandir=”/usr/share/man”
amandad: AMANDA_TMPDIR=”/var/log/amanda”
amandad: AMANDA_DBGDIR=”/var/log/amanda” CONFIG_DIR=”/etc/amanda”
amandad: DEV_PREFIX=”/dev/” RDEV_PREFIX=”/dev/r”
amandad: DUMP=”/sbin/dump” RESTORE=”/sbin/restore” VDUMP=UNDEF
amandad: VRESTORE=UNDEF XFSDUMP=UNDEF XFSRESTORE=UNDEF VXDUMP=UNDEF
amandad: VXRESTORE=UNDEF SAMBA_CLIENT=”/usr/bin/smbclient”
amandad: GNUTAR=”/bin/tar” COMPRESS_PATH=”/usr/bin/gzip”
amandad: UNCOMPRESS_PATH=”/usr/bin/gzip” LPRCMD=”/usr/bin/lpr”
amandad: MAILER=”/usr/bin/Mail”
amandad: listed_incr_dir=”/var/lib/amanda/gnutar-lists”
amandad: defs: DEFAULT_SERVER=”localhost” DEFAULT_CONFIG=”DailySet1″
amandad: DEFAULT_TAPE_SERVER=”localhost”
amandad: DEFAULT_TAPE_DEVICE=”/dev/null” HAVE_MMAP HAVE_SYSVSHM
amandad: LOCKING=POSIX_FCNTL SETPGRP_VOID DEBUG_CODE
amandad: AMANDA_DEBUG_DAYS=4 BSD_SECURITY USE_AMANDAHOSTS
amandad: CLIENT_LOGIN=”amanda” FORCE_USERID HAVE_GZIP
amandad: COMPRESS_SUFFIX=”.gz” COMPRESS_FAST_OPT=”–fast”
amandad: COMPRESS_BEST_OPT=”–best” UNCOMPRESS_OPT=”-dc”
amandad: time 0.001: got packet:
——–
Amanda 2.4 REQ HANDLE 000-30510709 SEQ 1164031511
SECURITY USER amanda
SERVICE noop
OPTIONS features=fffffeff9ffe7f;
——–

amandad: time 0.001: sending ack:
—-
Amanda 2.4 ACK HANDLE 000-30510709 SEQ 1164031511
—-

amandad: time 0.006: bsd security: remote host triumph.hapgoods.com user amanda local user amanda
amandad: time 0.007: amandahosts security check passed
amandad: time 0.007: running service “noop”
amandad: time 0.008: sending REP packet:
—-
Amanda 2.4 REP HANDLE 000-30510709 SEQ 1164031511
OPTIONS features=fffffeff9ffe7f;
—-

amandad: time 9.979: got packet:
—-
Amanda 2.4 REQ HANDLE 000-30510709 SEQ 1164031511
SECURITY USER amanda
SERVICE noop
OPTIONS features=fffffeff9ffe7f;
—-

amandad: time 9.979: it is not an ack
amandad: time 9.979: sending REP packet:
—-
Amanda 2.4 REP HANDLE 000-30510709 SEQ 1164031511
OPTIONS features=fffffeff9ffe7f;
—-

amandad: time 19.979: got packet:
—-
Amanda 2.4 REQ HANDLE 000-30510709 SEQ 1164031511
SECURITY USER amanda
SERVICE noop
OPTIONS features=fffffeff9ffe7f;
—-

amandad: time 19.979: it is not an ack
amandad: time 19.979: sending REP packet:
—-
Amanda 2.4 REP HANDLE 000-30510709 SEQ 1164031511
OPTIONS features=fffffeff9ffe7f;
—-

amandad: time 29.976: dgram_recv: timeout after 10 seconds
amandad: time 29.976: waiting for ack: timeout, retrying
amandad: time 39.977: dgram_recv: timeout after 10 seconds
amandad: time 39.977: waiting for ack: timeout, retrying
amandad: time 49.978: dgram_recv: timeout after 10 seconds
amandad: time 49.978: waiting for ack: timeout, retrying
amandad: time 59.980: dgram_recv: timeout after 10 seconds
amandad: time 59.980: waiting for ack: timeout, retrying
amandad: time 69.979: dgram_recv: timeout after 10 seconds
amandad: time 69.979: waiting for ack: timeout, giving up!
amandad: time 69.979: pid 29550 finish time Mon Nov 20 09:06:21 2006

On the client, the incoming request correctly spawns an amandad client who immediately attempts to respond to the incoming packet (@0.008). The client sends the response multiple times, but eventually gives up (@69.979).

On the server, the amcheck program logs this:

amcheck: debug 1 pid 5211 ruid 33 euid 0: start at Mon Nov 20 09:05:11 2006
amcheck: dgram_bind: socket bound to 0.0.0.0.626
amcheck: pid 5211 finish time Mon Nov 20 09:05:41 2006

Note how amcheck has bound to port 626 for incoming responses. Now the smoking gun, the iptables log on the tape server:

Nov 20 09:05:11 triumph kernel: Refused local request: IN=eth0 OUT= MAC=00:50:8b:64:23:37:00:08:c7:cf:32:df:08:00 xsrc=192.168.1.12 DST=192.168.1.30 LEN=78 TOS=0×00 PREC=0×00 TTL=64 ID=0 DF PROTO=UDP SPT=10080 DPT=626 LEN=58
Nov 20 09:05:11 triumph kernel: Refused local request: IN=eth0 OUT= MAC=00:50:8b:64:23:37:00:08:c7:cf:32:df:08:00 xsrc=192.168.1.12 DST=192.168.1.30 LEN=111 TOS=0×00 PREC=0×00 TTL=64 ID=0 DF PROTO=UDP SPT=10080 DPT=626 LEN=91

The firewall has blocked these response packets, despite ip_conntrack_iptables being loaded. I am correctly allowing RELATED packets through the firewall, but It Just Doesn’t Work. I gave up and opened the hole back up.

REST and GET on Forms

Friday, November 17th, 2006

Xanax onlineAdderall onlineLevitraviagra without prescriptionadderall onlineadderall without prescriptionPhentermine onlinetramadol onlinevalium online

I have been converting a small Rails application to REST this past week and several issues have come to light surrounding HTML forms.? I can’t seem to find a good solution to these problems.? In my last entry, I tackled the issue of delivering of arbitrary forms to HTML clients.? This entry focuses on the annoyances with using GET and Forms.

Unless you have been living in a cave for the past couple of years (Osama?), you have heard of REST.? It encourages exploitation of the full spectrum of inherent capabilities of the HTTP protocol to provide resource-centric services over the web.? Part of this exploitation centers on the HTTP verbs PUT, DELETE et. al. that are under-used.? Another focus is on the use of GET in non-traditional contexts like HTML forms.? The essence of this last recommendation is that GET should be used whenever there are no side-effects from the request.? And querying usually falls into this category, so we should be using HTTP GET to submit HTML forms that are used to build queries.? Sounds good, and it is trivial in Rails to implement.

REST and Form Retrieval

Friday, November 17th, 2006

XanaxAdderall onlineLevitra

I have been converting a small Rails application to REST this past week and several issues have come to light surrounding HTML forms.? I can’t seem to find a good solution to these problems.? First, I want to tackle delivering of arbitrary forms to HTML clients.

In a simple application revolving around one resource, delivering a form to an HTML client (to query against that resource, for example) is a “classic” task.? With REST, the single resource has straightforward URIs for all the classic CRUD operations.? But the forms that facilitate the CRUD operations are much less clear.? For example, if I wish to fetch the clown with ID 1, I can issue an HTTP request like this:

??? http://example.domain/clowns/1?? (HTTP verb GET)

And to update the clown:

??? http://example.domain/clowns/1?? (HTTP verb PUT, with form-encoded attributes)

But how do I deliver the editing form to the client?? The first URL in the example only delivers the clown resource itself, not the form to edit the clown.? One approach is to treat the form itself as a resource (see reference 2) and allow it to be RESTfully manipulated:

??? http://example.domain/clownEditForm?? (HTTP verb GET)

As clean as this looks from the URL perspective, it is ugly in Rails.? The resource route mapping available in the recent Simply RESTful Edge Rails enhancements does not permit a second named resource using the same HTTP verb (GET) to use the same controller -so the ClownController couldn’t serve up this form and you would need an additional controller -yech.? Another approach is to use a representational tweak via a view parameter:

??? http://example.domain/clowns/1?view=edit ? (HTTP verb GET)

In a similar vein, Rails supports view tweaks to the URL with an abbreviated syntax.? So to fetch clown ID 1 represented for editing, I would use a URL like this:

??? http://example.domain/clowns/1;edit ? (HTTP verb GET)

OK, I can grasp what is going on here.? But extending this model is not so easy.? For example, what URL would I use for delivering an HTML form to find the closest clowns to a given address?? The problem is that I am not delivering a special representation of a clown.? In fact, there is no clown at all in this form -just an address field.? And I’ll be damned if I am going to create a one-shot address resource (and controller) for this purpose.? So where does this leave me?? I’ve opted for representational tweaks to the collection resource:

??? http://example.domain/clowns;queryByAddressForm ? (HTTP verb GET)

And the corresponding routes.rb declaration:

??? map.resources :clowns, :collection => {:queryByAddressForm => :get}

Not very satisfactory, but workable.?

A twist: what if I want to use this same HTML page for displaying the results of the query (without AJAX) and the query form itself?? Now the concept of getting the form and getting the query results have blended into one.? This construct is useful in HTML even if it is absurd for a web service or JSON/XML delivery.? What to do?? I went to this intentionally vague representation:

??? http://example.domain/clowns;queryByAddress ? (HTTP verb GET)

This HTTP request will return a page with the empty form at the top and the results (initially empty) at the bottom.? The form submits with a GET to the same URL -but this time with a address parameter that causes results (and previous form values) to be included in the returned page:

??? http://example.domain/clowns;queryByAddress?address=3100+Edgewater+27514 ? (HTTP verb GET)

In a more general sense, this may be an acceptable paradigm: a GET to a query URL requesting HTML but without the necessary parameters is interpreted as a request for the form.? Can I get an “Amen, Brother!” on that?? Can I get some built-in Rails support?

At this point I am willing to settle.? But I’m still not happy.? Part of my problem may be that Rails has not yet made it truly easy to do REST 100% right.? A more strictly RESTful approach could be implemented, but for now Edge Rails is using the KISS approach.

A bit of spherical trignometry…

Thursday, November 16th, 2006
I needed to calculate the distance between two arbitrary points on the surface of the earth given by a latitude and longitude in decimal degrees and an altitude in meters.

 

p1 = [lat1, lon1, alt1]

p2 = [lat2, lon2, alt2]

First, the Pythagorean Theorem can be used to approximate the distance by assuming the points lie on a rectilinear grid.  But since our coordinates are angular measurements, we are only going to determine the angular distance between the two points -not the linear distance.  We’ll fix that later.  And we are going to delay including the vertical distance (alt1 - alt2) until later as well.

 

d = sqrt((lat1 - lat2)2 + (lon1 - lon2)2)

 

One complication of this formula is that it ignores the fact that the earth is round!  On a round earth, as you exceed 180 degrees longitude difference from your target, you actually start to get closer to the target.  So we need to be smart when we calculate the longitude delta and consider the “shortcut” around the “other” side of the world.  Mathematically, we need to always use the lesser of the delta longitude and the explement of the delta.

A practical example: here is a MySQL “order by” fragment embedded in Ruby that uses this approach to sort a table by angular distance from a given point (where @subject is the given point and the table rows are the candidates):

 

pow((latitude - #{@subject.latitude}),2) + pow( least( abs(longitude - #{@subject.longitude}), (360.0 - abs(longitude - #{@subject.longitude})) ), 2) asc

 

In this example, I didn’t bother taking the square root of the result because I am not interested in the angular distance between the points (yet), just the relative ordering of the points.  This Pythagorean angular distance ordering maps closely to the linear distance ordering (but see warning below) and thus allows us to inexpensively restrict the set of records retrieved from the database.

Unfortunately, the Pythagorean angular distance is inaccurate near the poles and over large distances.  Furthermore, the Pythagorean angular distance ordering is also subject to inaccuracies for points close to the poles (where large east/west angular distances translate into relatively small linear distances).  A more accurate and expensive calculation of the angular distance can be performed using the Haversine function (expressed in Ruby, where trigonometric methods take arguments in radians):

dlon = (other.longitude - self.longitude)*(Math::PI / 180.0)

dlat = (other.latitude - self.latitude)*(Math::PI / 180.0)

a = (Math.sin(dlat/2.0))**2.0 + Math.cos(self.latitude*(Math::PI / 180.0))*Math.cos(other.latitude*(Math::PI / 180.0))*(Math.sin(dlon/2.0))**2.0

c = 2 * Math.asin( [1.0, Math.sqrt(a)].min )

 

Its output, c, is known as the great circle angular distance: the smallest angle (measured from the center of the globe) that includes the two points.  It breaks down only with antipodal points (points on opposite sides of the globe) combined with less-than-perfect inverse sine function implementations.  For real-world (literally!) linear distance calculations, the arcsine error is probably dominated by the error introduced by estimating the radius of the earth.  Which brings us to the next step…

 

Whether you get the angular distance from the Pythagorean Theorem or the Haversine function, you probably will want to convert your great circle angular distance into a linear distance.  For an ideal sphere, this is trivial:

 

d = r * c

 

where r is the radius of the sphere (earth) and c is the great circle angle.  The trick is getting a reasonable estimate of the radius of the earth in light of the inconvenient fact that the earth is not a globe but rather something like an oblate spheroid (flattened sphere) whose radius varies over its surface.  For short distances, the variation is insignificant and we can get a good local radius estimate around our points of interest using this simple formula (again, expressed in Ruby code):

 

r = 6378km - 21km * Math.sin(self.latitude*(Math::PI / 180.0))

 

For a group of points, use a representative latitude (average, median or whatever) in the above formula.

Now that we have our radius, the linear distance along the surface of the earth can be calculated:

 

d’ = r * c

 

Finally, to include the vertical distance, we again use approximate with the Pythagorean theorem:

 

d = sqrt(d’2 + ((alt1 -alt2)/1000)2)

 

This yields the total distance in kilometers.  The contribution of the vertical distances to the overall distance is negligible in most practical cases (where the vertical distance is small relative to the “horizontal” distance).  It is also difficult to reconcile the line-of-sight distance that this formula introduces with the concept of distance along the surface of a sphere, but I’ve included this last step for completeness.

 

References:

  1. http://www.faqs.org/faqs/geography/infosystems-faq/
  2. http://mathforum.org/library/drmath/view/63015.html
  3. http://mathforum.org/library/drmath/view/51879.html

Crash!

Wednesday, November 15th, 2006

Today I feel lucky to be able to write this entry. Yesterday, I was involved in a dramatic head-on go-kart crash at a closing speed of well over 50 miles per hour. It happened like this…

A group of five friends went to G-Force Karts track in Richmond, as we have on many occasions in the past. This time, I was in a 270cc SuperKart (top speed over 40mph) leading everybody around the track on the first lap. At the same time, one of the guys in our group (DJ) had stalled his kart in the pits and was getting it restarted by the staff. When they got his kart started, he went roaring out of the pits -and turned the wrong way onto the track. The layout of the track includes a 180 degree hairpin turn nested in an alcove of the building. I and the other racers were out of DJ’s sight in the alcove maneuvering around the hairpin. I exited the hairpin and took the 90 degree left turn pedal-to-the-metal. DJ, trying to catch back up to the group, was also running full bore lining up for what was a 90 degree right turn. I came out of the turn and BAM!!!

My brain never had time to process the fact that there was another kart heading at me. I never put on the brakes, and neither did DJ. I’m not sure if I lost consciousness or not, but if so, it was only for a moment. I realized that DJ’s kart had ridden up on my steering column and that my right ankle hurt like hell. My right thigh and wrist also hurt and I was woozy. I could hear DJ moaning, and I was moaning too. I remember black dust on the track all around us -carbon from the brakes that was shaken off? Thankfully, the racers behind me were able to put on the brakes and avoid hitting the two of us.

After a couple of minutes of collecting my wits and making sure I wasn’t seriously hurt, I was hauled out of the kart by the staff. I quickly found that my ankle was not going to allow me to walk and that was the end of racing for the evening -a big DNF. Today, I am feeling the whiplash from the crash as much as I am suffering from my ankle. The steering wheel on my kart was bent -and I know what hit it. My nice, tight motorcycle helmet and the kart’s safety features (seat belt, crushable steering wheel, form-fitting seat, etc) saved me from a much nastier fate. On the down side, it did not look like the frame of the karts (tubular steel) deformed much at all -leaving much of the energy of the collision to be absorbed by the human occupants.

NB: If you’re thinking “What in the hell possessed DJ to go the wrong way around the track,” consider this: several years ago, the track DID run the other way around. And DJ probably raced it then. Next, perhaps as a result of the bi-directional history, the pit exit (see the map) is setup such that you can arguably consider either way correct -and there aren’t any obvious markings to indicate which direction to go at the exit of the pit. Finally, because all the other racers were out of sight when DJ had to make his decision, there was no context of other racers to make it clear which direction to go.

Upgrading MySQL from 4.x to 5.x

Wednesday, November 8th, 2006

As a result of upgrading from Fedora Core 4 to Fedora Core 5, mysql was upgraded to version 5.0.22.  And my privilege tables were all screwed up.  Originally, I had expected this behavior as it is documented in the release notes of FC5.  But I mistakenly believed the privilege table upgrade had been done as part of the FC4->FC5 process -mainly because when I tried to do:

[root@bmw ~]# mysql_fix_privilege_tables

I got a very non-descript error message.  Shame on me for assuming that meant that the upgrade had already been done.  Interestingly, there were no discernable errors in the normal operation of mysql.  I only noticed the problem when I began creating and manipulating the privileges table as a result of a new project I am working.  The problems manifested themselves as subtle warnings when I tried to grant permissions to full-blown errors when I tried to remove all permissions from a user.  The solution was to run the previous command but with the root password:

[root@bmw log]# mysql_fix_privilege_tables –verbose –password=Secret

This created/adjusted the privilege tables.  To be safe, I restarted the mysqld daemon and from then on, things began working as expected.

FC4-FC5 Upgrade

Wednesday, November 8th, 2006

I should be good at this now. I have done it three times. But last night’s upgrade of bmw from FC4 to FC5 did not go as smoothly as I had hoped. There are some extenuating circumstances: bmw runs a broader spectrum of software (including mysql, wordpress, trac, subversion, squirrelmail, dovecot and sendmail) than the other hosts. But in the end, my biggest problems boiled down to close-to-the-metal issues.  For starters, even before I began the ugprade, I ran into these self-inflicted annoyances

Proliant CD-ROM drive not connected

Solution: plug in the connector -I must has unplugged when last I was in the case.

Password-protected setup utility

Solution: temporarily throw switch 2-5 on the motherboard.

Remote Insight board in a non-recommended slot

Solution: shuffle around the RILOE and SmartArray 3200

Once fixed, the upgrade from CD-ROM completed without incident. But of course that only gets you to FC5 as it was on the day I made my CD-ROM images (last Spring).  So I immediately did a yum update.  That’s when the fun started.  I began getting some strange NMIs.  The kernel would announce the problem as it started up, but it would plow onward.  However, when hpsmhd started, it (wisely?) shut down the whole server.  Restarting seemed to make the problem go away, but it did come back occasionaly.   Baffling.  I never had a hardware problem with a Proliant like this before.  Perhaps related to my shuffling around the PCI cards? The other big (and remaining problem) was that my ThunderLAN NICs (both) occasionally stop working.  No errors that I can find (yet).  They just stop working.  I can bounce the interface with ifup/ifdown, but that does not fix the problem. I finally found that removing the tlan kernel module (rmmod tlan) and re-inserting it (modprobe tlan) fixes it.  But that obviously is not going to work in the long term.

I created bugzilla entry 214594 to document this issue.