20140528

The Importance of umask

This is subtle and covered in countless other places.  However, for the sake of it, this is a brief illustration of umask and its (non-)interaction with the "SGID" bit.  This can be especially relevant when setting up something like a Subversion server, with user access done via SSH.

I have created a directory called test.  It's empty, and owned by me and under the group svn (my default group).

admin@svnsrv:~/test$ ls -al
total 8
drwxr-xr-x 2 admin svn 4096 May 28 15:10 .
drwxr-xr-x 3 admin svn 4096 May 28 15:10 ..

I decide to use a different group, and I set the SGID bit so that all files and directories created under "test" will get the same group ID.  I also give group write permission.

admin@svnsrv:~/test$ chgrp sshusers .
admin@svnsrv:~/test$ chmod g+ws .
admin@svnsrv:~/test$ ls -al
total 8
drwxrwsr-x 2 admin sshusers 4096 May 28 15:10 .
drwxr-xr-x 3 admin svn      4096 May 28 15:10 ..

Now we can try making another directory.

admin@svnsrv:~/test$ mkdir foo
admin@svnsrv:~/test$ ls -la
total 12
drwxrwsr-x 3 admin sshusers 4096 May 28 15:10 .
drwxr-xr-x 3 admin svn      4096 May 28 15:10 ..
drwxr-sr-x 2 admin sshusers 4096 May 28 15:10 foo

As you can see, foo inherited the correct group ID, but did not inherit group write permission.  This is where umask comes in.  We first look at our current umask, and then set a new one:

admin@svnsrv:~/test$ umask
0022
admin@svnsrv:~/test$ umask 0002
admin@svnsrv:~/test$ mkdir bar
admin@svnsrv:~/test$ ls -la
total 16
drwxrwsr-x 4 admin sshusers 4096 May 28 15:10 .
drwxr-xr-x 3 admin svn      4096 May 28 15:10 ..
drwxrwsr-x 2 admin sshusers 4096 May 28 15:10 bar
drwxr-sr-x 2 admin sshusers 4096 May 28 15:10 foo
admin@svnsrv:~/test$ umask
0002

The latest directory was created with the right permissions.  It is important to note that permissions do not inherit (to the best of my knowledge), whereas ownership does.

umask itself is designed to mask out permission bits, so it is the logical negation of the permissions we want to ultimately allow.  This does not imply that files will be created with mode 775; rather, that if a file is created with 664, a mask of 002 will retain 664 whereas a mask of 022 will reduce permissions to 644.  Likewise, a file created 700 will retain 700 with both of these example umasks.  It is, exactly, a mask: applied as a logical AND (NOT mask).  It is not a mathematical subtraction.  As an exercise to the reader, look through this Wikipedia article for more info on permissions and then work out some examples by hand, applying masks using AND (NOT mask):

http://en.wikipedia.org/wiki/File_system_permissions#Symbolic_notation

And on that note, consider this final command and its result:

admin@svnsrv:~/test$ touch baz
admin@svnsrv:~/test$ ls -la
total 16
drwxrwsr-x 4 admin sshusers 4096 May 28 15:14 .
drwxr-xr-x 3 admin svn      4096 May 28 15:10 ..
drwxrwsr-x 2 admin sshusers 4096 May 28 15:10 bar
-rw-rw-r-- 1 admin sshusers    0 May 28 15:14 baz
drwxr-sr-x 2 admin sshusers 4096 May 28 15:10 foo

See?  No execute bits on that file, even though the umask is still 0002.

N.B. The initial zero is code for "octal."  In case you didn't realize we were using octal notation here...  In the big paragraph above, the modes themselves would be properly represented as 0775 etc.


20140527

ProxMox 3.x RAID-1 Transfiguration

Proxmox 3.2 RAID-1 Conversion - GPT Mode - With Bonus Features!

The latest Proxmox can install as GPT.  Not sure if we have any say in the matter.  BUT, in case you had a die-hard need to convert your Proxmox server to RAID-1, this is a cleaned-up set of instructions.  YMMV, make sure you backup your data, check your particular partition configuration, and READ CAREFULLY.  Also it is important to note that gdisk and sgdisk will be your friend, fdisk and sfdisk will not.

Basis: http://boffblog.wordpress.com/2013/08/22/how-to-install-proxmox-ve-3-0-on-software-raid/

EDIT and RAID-5 NOTE:
This site describes some changes you need to make to get RAID-5 working.  The below is good for RAID-1 only.  The important distinctions come with the initramfs modules.  I'll try to put together another post that sums all this up....or you can just go here:




Notes:
It is necessary to either have a valid license or to manually configure apt to use another set of repositories.  Otherwise, mdadm will not be available.  Details at:
https://pve.proxmox.com/wiki/Package_repositories

Instructions:

  • Duplicate partition info onto new drive:
    • sgdisk -b sda-part.txt /dev/sda
    • sgdisk -l sda-part.txt /dev/sdb
  • Configure partition types as RAID members:
    • sgdisk -t 2:fd00 -t 3:fd00 /dev/sdb
    • NOTE:  partition 1 must be type EF02 to support GRUB.  DO NOT TOUCH THIS PARTITION!
  • Create RAIDs:
    • boot
      • mdadm --create /dev/md0 -l 1 -n 2 missing /dev/sdb2
    • root
      • mdadm --create /dev/md1 -l 1 -n 2 missing /dev/sdb3
  • Copy /boot
    • mkfs.ext3 /dev/md0
    • mount /dev/md0 /mnt
    • rsync -avsHAXS /boot/ /mnt/
    • ## Update fstab with new boot mount: /dev/md0 (don’t use UUID)
    • reboot
  • Configure mdadm.conf
    • mdadm -D --brief /dev/md0 >> /etc/mdadm/mdadm.conf
    • mdadm -D --brief /dev/md1 >> /etc/mdadm/mdadm.conf
  • Update GRUB & initramfs
    • echo 'GRUB_DISABLE_LINUX_UUID=true' >> /etc/default/grub
    • echo 'GRUB_PRELOAD_MODULES="raid dmraid"' >> /etc/default/grub
    • echo raid1 >> /etc/modules
    • echo raid1 >> /etc/initramfs-tools/modules
    • grub-install /dev/sda
    • grub-install /dev/sdb
    • update-grub
    • update-initramfs -u
  • Convert BOOT partition to RAID-1
    • sgdisk -t 2:fd00 /dev/sda
    • mdadm --add /dev/md0 /dev/sda2
  • Migrate all logical extents to /dev/md1
    • pvcreate /dev/md1
    • vgextend pve /dev/md1
    • pvmove /dev/sda3 /dev/md1
    • …. wait a long time ….
    • vgreduce pve /dev/sda3
    • pvremove /dev/sda3
  • Convert sda3 to RAID
    • sgdisk -t 3:fd00 /dev/sda
    • mdadm --add /dev/md1 /dev/sda3
    • …. wait a long time ….
  • Reboot for final test - everything should work!
  • Configure monitoring, device scans, emails, etc
  • Configure SMART
  • SUCCESS!!

Now you have a server that can tell you a little sooner that it might die, and have a better chance of recovering from said-death.

Why This Works:
Ordinarily, pv-moving from one partition to another of the exact same size doesn’t work, except (in our case) when the partition isn’t actually 100% in use.  As it turns out, Proxmox leaves a little extra at the end, maybe for snapshots, and consequently we can move from our original PV to one that is 1 LE smaller without issue.

Using the above technique, it should be perfectly possible to migrate to a different array configuration, such as RAID-5 or RAID-6, if you have the drives for it.  Just make sure that you load the appropriate modules into GRUB and initramfs.  All other commands should be similar, and of course there will be more of them (because there will be more drives to configure).


Why You Might Want This:

Software RAID is not officially supported by Proxmox, so you are on your own there.  BUT, if you do trust mdadm (and who doesn't?), you can have your RAID and use it, too.  There are no hardware adapters to buy, or to fail, or to curse at when they fail to read the metadata from one or more of your disks during some random reboot.  If you are very concerned about data integrity, then you should be looking at ZFS-backed iSCSI stores instead of mucking around underneath Proxmox's hood.  That said, having this all running RAID-1 does make recovery a heck of a lot easier, and especially if you couple it with a ZFS iSCSI store for all your actual VM data.

And remember:  RAID is NOT a backup solution.  If you treat it like a backup solution, you have no one but yourself to blame when all your data gets toasted after a multi-drive failure, fool!

20140301

.pyc "Bad magic number" solution

I am reporting this solution here for convenience.  Without going into specifics, the issue I had related to a Myth NetVision plugin.

I ran into an issue with a project that included only a .pyc file.  The file was compiled with Python 2.6, but the system standard Python was 2.7.  To make matters worse, several other .py files required 2.7, making reverting to 2.6 rather impossible.  The original source was not provided even in the sources; I suspect this was due to a license constraint.

The solution was to recompile the .py with 2.7.  However, to obtain the .py with going to the maintainers, I used a Python decompiler.  The following commands are what I used:
pip install unpyclib
python -m unpyclib.application -Dq path/to/file.pyc
Recompiling was as simple as moving the new source file into the directory along side the original .pyc, and deleting the .pyc before running the appropriate script (as root, due to permissions requirements).

References:
http://stackoverflow.com/questions/5287253/is-it-possible-to-decompile-a-compiled-pyc-file-into-a-py-file

Alternative Decompilers (untried):
http://stackoverflow.com/questions/5287253/is-it-possible-to-decompile-a-compiled-pyc-file-into-a-py-file
https://github.com/wibiti/uncompyle2

20131130

STUNned... when a useful feature burns your ass

So I've been doing some experimentation with Asterisk.  I have deployed a couple of servers so far, one at work and one at home, both pure testing environments.  Yeah, don't worry, I have horribly miserable-to-type (i.e. strong) passwords on all my test accounts.  Anyway, I kept running into a small problem with my home box.

It all started with intermittent audio.  It was an issue I kept experiencing on my desktop clients, on my phone clients (such as CSipSimple and ZoIPer), but strangely not on my tablet.  Basically, sometimes the audio would work, and sometimes it wouldn't.  Now, I was simply calling a test extension, one which would play "Hello, world!" over and over again.  On occasion the audio would kick in part way through the sequence.  Usually it would either work or, more often, be absent altogether.

The SIP registration was fine.  The receive calls even worked, to the right client.  The legacy version of desktop ZoIPer, for instance, seemed to handle things well, but the newer version kept having issues.  I toyed with the sound card settings.  I tried removing bluetooth from the equation (which is probably just as well, as I keep having BT connectivity issues with my headset - probably an adapter problem).  I even tried connecting to my work server.

The work server worked fine.

While considering whether or not it could be an issue with my bleeding-edge release of Asterisk (which I had to compile to get Google Voice/Chat integration working correctly, at least in version 11), another observation finally struck me.  Earlier in the evening, as I watched the SIP debug packets fly by, I noticed that the client IP was not always a local address.  In fact, it had no reason not to be local, the server and the client were in the same subnet!  STUN support, as it appears, was part of the culprit.  Given that I don't know nearly enough about STUN, ICE, or SIP to really speak authoritatively about this stuff, I'll give it my best guess:  the client was using STUN and finding its external IP, which it was relaying to Asterisk during part of the call.  At other times it was using its well-known internal IP.  The server, consequently, tried talking to an unregistered IP and decided it wasn't such a good idea.

Intermittently.

Anyway, disabling STUN in the clients seemed to work well.  Especially with the newer desktop version of ZoIPer.  In my Asterisk config I had once issued an externaddr directive in sip.conf, but ended up commenting it out as my server currently lives on a dynamic IP.  I will eventually try to fix that, one way or another.  Disabling STUN is, naturally, not an ideal solution.  Things should work regardless and the client ought, in my opinion, to be smart enough to figure out when it does and doesn't need STUN.  Or maybe Asterisk is really missing that externaddr directive and isn't telling the client the right thing to do.

In either case, I'm just happy to finally have working clients.  Now to pick out a FXO/FXS card...

20130905

Can't mount or fsck OCFS2, using CMAN...what you probably shouldn't ever do (but I did)

It's late.  You have only one node of a two-node cluster left, and you're using cman, pacemaker, and OCFS2.  The node gets rebooted.  Suddenly, and for no apparent reason, you can't mount your OCFS2 drives.  You can do fsck.ocfs2 -n, but the act of actually clearing the drive is just going nowhere.  You wait precious minutes.  What is wrong?

Checking the logs, you see that your stonith mechanisms are failing.  Strange, they used to work before.  But now they're not, and cman wants to fence the other node that you know is really, really, really fucking dead.  What to do?  Hmm.. can't tell it to unfence the node, because no commands I try seem to make it actually agree to those behests.

Desperation sets in.  You have to fsck the damn things.  You've rebooted a dozen times.  Carefully brought everything back up, and still it sits there, mocking you, not scanning a goddamn thing.  What did I do?  I installed a null stonith device (stonith:null) in pacemaker, and gave it the dead node in the hostlist.  On the next round of fencing attempts that cman made, pacemaker failed at the original stonith and succeeded at the null device (expectedly).  Suddenly cman was happy, and the world rejoiced, and the file system scans flew forth with verbose triumph.  Moments later everything was mounted and life continued as though nothing bad ever happened.

Now I have to figure out why my stonith device failed in the first place.  That pisses me off.

20130822

Die-hard iSCSI SAN and Client Implementation Notes

Building out my next SAN and client

The goal here is a die-hard data access and integrity.

SAN Access Mechanisms

AOE - a no-go at this time

My testing to date (2013-08-21) has shown that AoE under vblade migrates well, but does not handle a failed node well.  Data corruption generally happens if writes are active, and there are cases I have encountered (especially during periods of heavy load) where the client fails to talk to the surviving node if that node is not already the primary (more below on that).  In other words, if the primary SAN target node fails, the secondary will come up, but the client might not use it (or might use it for a few seconds before things get borked).   I am actively investigating this and other related issues with guidance from the AoE maintainer.  At this time I cannot use it for what I want to use it for.  Pity, it's damn fast.

iSCSI - Server Setup

Ubuntu 12.04 has a 3.2 kernel and sports the LIO target suite.  In initial testing it worked well, though it will be interesting to see how it performs under more realistic loads.  My next test will involve physical machines to exercise iSCSI responsiveness over real hardware and jumbo-frames.

The Pacemaker (Heartbeat) resource agent for iSCSILogialUnit suffers from a bug in LIO, whereby if the underlying device/target is receiving writes the logical unit cannot be shut down.  This can cause a SAN node to get fenced for failure to shut down the resource when ordered to standby or migrate.  It can be reliably reproduced.  This post details what needs to be done to fix the issue.  These modifications can be applied with this patch fragment:



--- old/iSCSILogicalUnit 2013-08-21 16:13:20.000000000 -0400
+++ new/iSCSILogicalUnit 2013-08-21 16:12:56.000000000 -0400
@@ -365,6 +365,11 @@
   done
   ;;
      lio)
+               # First stop the TPGs for the given device.
+               for TPG in /sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/*/enable; do
+                       echo 0 > "${TPG}"
+               done
+
                if [ -n "${OCF_RESKEY_allowed_initiators}" ]; then
                        for initiator in ${OCF_RESKEY_allowed_initiators}; do
                                ocf_run lio_node --dellunacl=${OCF_RESKEY_target_iqn} 1 \
@@ -373,6 +378,15 @@
                fi
   ocf_run lio_node --dellun=${OCF_RESKEY_target_iqn} 1 ${OCF_RESKEY_lun} || exit $OCF_ERR_GENERIC
   ocf_run tcm_node --freedev=iblock_${OCF_RESKEY_lio_iblock}/${OCF_RESOURCE_INSTANCE} || exit $OCF_ERR_GENERIC
+
+               # Now that the LUN is down, reenable the TPGs...
+               # This is a guess, so we'll gonna have to test with multiple LUNs per target
+               # to make sure we are doing the right thing here.
+               for TPG in /sys/kernel/config/target/iscsi/${OCF_RESKEY_target_iqn}/*/enable; do
+                       echo 1 > "${TPG}"
+               done
+
+
  esac
     fi


Basically, go through all TPGs for a given target, disable them, nuke the logical unit, and then re-enable them.  This has only been tested with one LUN.  It may screw things up for multiple LUNs.  Hopefully not, but you have been warned.  If I get around to testing, I'll update this post.  My setups always involve one LUN per target.

iSCSI - Pacemaker Setup

On the SERVER...  I group the target's virtual IP, iSCSITarget, and iSCSILogicalUnit together for simplicity (and because they can't exist without each other).  LIO requires the IP be up before it will build a portal to it.  
group g_iscsisrv-o1 p_ipaddr-o1 p_iscsitarget-o1 p_iscsilun-o1
Each target gets its own IP.  I'm using ocf:heartbeat:IPaddr2 for the resource agent.  The iSCSITarget primitives each have unique tids.  Other than that, LIO ignores parameters that iet and tgt care about, so configuration is pretty short.  Make sure to use implementation="lio" absolutely everywhere when specifying the iSCSITarget and iSCSILogicalUnit primitives.

On the CLIENT...  The ocf:heartbeat:iscsi resource agent needs this parameter to not break connections to the target when the conditions are right:
try_recovery="true"
Without it, a failed node or a migration will occasionally cause the connection to fail completely, which is not what you want when failover without noticeable interruption is your goal.

SAN Components

DRBD

Ubuntu 12.04 ships with 8.3.11, but the DRBD git repo has 8.3.15 and 8.4.3.  In the midst of debugging Pacemaker bug, I migrated to 8.4.3.  It works fine, and appears to be quite stable.  Make sure that you're using the 8.4.3 resource agent, or else things like dual-primary will fail (if everything is installed to standard locations, you should be fine).

Though it's not absolutely necessary, I am running my DRBD resources in dual-primary.  The allow-two-primaries option seems to shave a few seconds off the recovery, since all we have to migrate are the iSCSI target resources.  LIO migrates very quickly, so the most of the waiting appears to be cluster-management-related (waiting to make sure the node is really down, making sure it's fenced, etc).  We could probably get it faster with a little more work.

Pacemaker, Corosync

Without the need for OCFS2 on the SAN, I build the cluster suite from the sources using Corosync 2.3.1 and Pacemaker 1.1.10 + latest changes from git.  It's very near bleeding-edge, but it's also working very well at the moment.  Building the cluster requires a host of other packages.  I will detail the exact build requirements and sequence in another post; I wrote a script that does pretty much an automated install.  The important thing is to make sure you don't have any competing libraries/headers in the way, or parts of the build will break.  Luckily it breaks during the build and not during execution.  (libqb, I am looking at YOU!)

ZFS

I did not do any additional experimentation with this on the sandbox cluster, but it is worth noting that in my most recent experiences I have shifted to using drive UUIDs instead of any other available device addressing mechanisms.  The problem I ran into (several times) involved the array not loading on reboot, or (worse) the vdevs not appearing after reboot.  Since I the vdevs are the underlying devices for DRBD, it's rather imperative that they be present on reboot.  It appears to be a semi-remaining issue in ZoL, though it's less so in recent releases.

Testing and Results

For testing I created a cluster of four nodes, all virtual, with external/libvirt as the STONITH device.  The nodes, c6 thru c9, were configured thus:
  • c6 and c7 - SAN targets, synced with each other via DRBD
  • c8 - AoE test client
  • c9 - AoE and iSCSI test client

Server/Target

All test batches included migration tests (moving the target resource from one node to another), failover tests (manually fencing a node so that its partner takes over), single-primary tests (migration/failover when one node has primary and the other node has secondary), and dual-primary tests (migration/failover when both nodes are allowed to be primary).

Between tests, the DRBD stores were allowed to fully resync.  During some long-term tests, resync happened while client file system access continued.  

Client/Initiator

Two operations were tested: dbench and data transfer and verification.

dbench is fairly cut-and-dry.  It was set to run for upwards of 5000 seconds with 3 clients, while the SAN target nodes (c6 and c7) were subjected to migrations and fencing.

The data transfer and verification tests were more interesting, as they signaled corruption issues.  For sake of having options, I created three sets of files with dd if=/dev/urandom.  The first set was 400 1-meg files.  The second set was 40 10-meg files.  The last set was 4 100-meg files.  Random data was chosen to ensure that no compression features would interfere with the transfer, and also to provide useful data for verification.  SHA-512 sums were generated for every file.  As the files were done in three batches, three sum files were generated.  For each test, a selected batch of files was copied to the target via either rsync or cp, while migrations/failovers were being performed.  The batch was then checked for corruption by validating against the appropriate sums file.  Between tests, the target's copy of the data was deleted.  Occasionally the target store was reformatted to ensure that the file system was working correctly (especially after failed failover tests).

Results - AoE

AoE performed extremely well with transfer rates and migration, but failed during verification tests on failover testing.  This is interesting because it suggests the mechanism that AoE is using to push its writes to disk is buffering somewhere along the way.  vblade is forcibly terminated during migration, yet no corruption occurred throughout those tests.  

Failover reliably demonstrated corruption; the fencing of a node practically guaranteed that 2-4 files would fail their SHA-512 sums.  This can be fixed by using the "-s" option, but I find that to be rather unattractive.  Yet it may be the only option.

Another issue: during a failover, the client might fail to communicate with the new target.  Migration didn't seem to suffer from this.  Yet on failover, aoe-debug sometimes reported both aoetgts receiving packets even though one was dead and one was living.   More often than not, aoe would start talking to the remaining node, only to stop a few seconds later and never again resume.  I've spent a good deal of time examining the code, but at this time it's a bit too complex to make any in-roads.  At best, I've have intermittent success at generating the failure case.

One other point of interest regarding AoE: the failover is a bit slow, regrettably.  This appears due to a hard-coded 10-second time limit before scorning a target.  I might add a module-parameter for this, and/or see about a better logic-flow for dealing with suspected-failed targets.

Results - iSCSI

iSCSI performed, well, like iSCSI with regard to transfer rates - slower than AoE.  My biggest fear with iSCSI is resource contention when multiple processes are accessing the store.  Once the major issues involving the resource agent and the initiator were solved, migration worked like a charm.  During failover testing, no corruption was observed and the remaining node picked up the target almost immediately.  I will probably deploy with allow-two-primaries enabled.









20130815

AoE, DRBD...coping strategies

This is a stream of consciousness...

DRBD - Upgrade Paths

When dealing with pre-compiled packages, upgrading from source can be hazardous.  Make sure of the following things:
  • DO make sure you have the correct kernel for the version of DRBD you want to use.
    • The 8.3 series won't compile in kernel 3.10, and possibly others.  It does compile in 3.2.  It appears that changes to procfs has made some of the relevant code in 8.3 out-of-date.
    • The 8.4 series will compile in kernel 3.2.  It comes with 3.10, so therefore must also build successfully there.
  • DO make sure you build the tools AND the module.
  • DO configure the tools to use the CORRECT paths.
    • These will depend on the distro and the original configure args used.  Deduce or look into the package sources for their build scripts.
    • Ubuntu has drbdadm in /sbin, the helper scripts in /usr/lib, the configs in /etc, and the state in /var/lib.
    • If you do not have the correct paths, things will break in unexpected ways and you might have a resource that continually tries to connect and then fails with some strange error (such as a protocol error or a mysterious "peer closed connection" on both sides).
  • DO be careful when installing the 8.3 kernel under Ubuntu 12.04, it doesn't seem to copy to where it needs to go - hand-copy if necessary (and it does seem necessary).
  • DO shut down Pacemaker on the upgrade node before upgrading.  Reboots may be necessary.  Module unloading/reloading is the minimum required.
  • DO reconnect the upgraded DRBD devices to their peers BEFORE bringing Pacemaker back into the mix.  If there is something amiss with your upgrade, you'll rather it simply fail the upgrade node than for that node and its cluster friends to start fencing one another.  Pacemaker won't care if a slave connects as long as it doesn't change the status quo (i.e. no auto master-seizure).  If everything is gold, you should be able to either start Pacemaker as is (it should see the resources and just go with it) or shut down DRBD and let Pacemaker bring it back up when it starts.
  • It's probably a better idea to upgrade DRBD before upgrading the kernel, so that you are only changing one major variable at a time.  In upgrading the kernel from 3.2 to 3.10, I ran into situations were things were subtly broken and the good node was getting fenced by the upgrading node for no good reason.
  • I have found, thus far, that wiping the metadata in the upgrade to 8.4 was not necessary, but it has been noted as a solution in certain circumstances.  This requires a full resync when done.
  • 8.3 and 8.4 WILL communicate with one another if you've done everything right.  If you haven't, they won't, but they will sorta seem like they should...blame yourself and go back through your DRBD install and double-check everything.
  • 8.4 WILL read 8.3's configuration scripts.  Update them when things are stable to the 8.4 syntax.
  • Pulling the source from GIT is a fun and easy way to obtain it.  Plus you can have the latest and greatest or any of the previously tagged releases.
  • And finally, WRITE DOWN the configure string you used on the upgrade node.  You'll want to replicate it exactly on the other node, especially if you pulled the source from git.
    • Even an rsync-copy doesn't guarantee that the source won't want to rebuild.  Plus if you end up switching to a newer or older revision, stuffing the configure command line into a little shell script makes rebuilding less error-prone.

AoE

This site is useful: http://support.coraid.com/support/linux/
To build in Ubuntu:
make install INSTDIR=/lib/modules/`uname -r`/kernel/drivers/block/aoe

Oh, where do I begin?  Things I have issue with and would like to do something about:
  • Absolutely no security at all in this protocol.  Security via hiding the data on a dedicated switch is not an answer, especially when you don't have said dedicated-switch to use.  VLANs are a joke.  Routability be damned, this protocol is more than vulnerable to any number of local area attacks, which are equally likely from a compromised node as they are for a routable protocol over the Internet.
    • I'd like to see the header or payload enhanced with a cryptographic sequence, at the very least.
      • The sequence could be a pair of 32-bit numbers, representing (1) the number that is the expected sequence number, and (2) the number that will be the next sequence number.
      • Providing these two numbers means that the number source can be anything, including random generation, making sequence prediction difficult (no predictable plaintext).
      • This could, at the very least, provide defense from replay attacks and give the target and the initiator something to identify each other with.
      • Extensions to this could allow for more robust initiator security, whereby a shared-secret is used to guarantee a target/initiator is who they say they are, in lieu of MAC filtering (which is pointless in the modern world of spoofable MACs.
  • vblade is, from the looks of things, "as good as it gets."  No other projects appear to be among the living.  Most stuff died back in '07 and '10 (if you're lucky).  Even vblade doesn't get much love from the looks of it.
    • Let's get at least a version number in there somewhere, so that I don't feel like an idiot for typing "vblade --version."
    • Figure out why the "announce" that vblade does falls on deaf ears.  If the initiator transmits a packet, and the recipient has died and "failed over" to another node, why does the initiator not care about this?  (update: evidently it does not fall on deaf ears, but it comes close.  In certain circumstances it works, others it doesn't.)
    • aoe-stat could dump out more info, like the MAC it was expecting to connect to. (update: This info was hidden away in a sysfs file called "debug")
    • The driver doesn't appear to try hard when it comes to reconnecting to a perceived-failed device.  The 12-page super-spec doesn't give any real guidance on how the initiator should behave, or how a target should respond, to any situation other than one in which everything works.  (How wonderfully optimistic!)  (update: OK so maybe I didn't read the whole spec line-for-line...)
  • Driver error detection and recovery appears to be nonexistent.  Again, very optimistic.  Plus, with two vblades running on two separate servers, only one server's MAC is being seen.  Why is this?!  Oh yeah, and that page about revalidating the device by removing and re-probing the driver?  Not gonna happen while the damn device is mounted somewhere.  PUNT!  (update: the mechanisms are evidently far more complex than I originally believed.  I must now examine the code carefully to understand them.  I have already encountered one test case that failed spectacularly.)
  • aoe-discover does dick when it thinks it knows where its devices are.  aoe-flush -a does nothing useful.  I hate that I have to look through their scripts just to find command line options.  Anyway, you CAN perform an aoe-flush e#.# and get it to forget about individual devices.  Then do the aoe-discover and things will work...if aoe-flush ever successfully returns.
  • If you aoe-flush a device that has moved to a new home, your mount is screwed.  Even if it hasn't moved to a new home, you're screwed.  Once the device is borked, the mount is lost.  This makes changing the MAC of the target a requirement if you want to failover to a secondary node.  (update: aoe-flush is not what we need.  The issue is deeper than that.)

At this point, I am strongly considering moving my resources back to iSCSI, and hoping that LIO can handle the load.

UPDATE: I've taken a different tact and thought to ask some useful questions.  Given the answers, there is perchance still hope for using AoE on my cluster.  We shall soon see.  Time, nonetheless, is running out (and I don't mean to imply my patience...I mean time, like REAL TIME).