Tuesday, November 27, 2012

IPMI SOL, newer AMI BIOS, and CentOS 6

SOL means "serial over LAN", but there are some similarities to the more popular interpretation. Here's the combination to get everything working with newer American Megatrends Inc. BIOSs.  First, set up the BIOS by enabling the "Serial Port for Out-of-Band Management/Windows Emergency Management Services (EMS)":
You don't need to customize anything in the Settings, but here's a screenshot anyway:
CentOS (well, and Redhat) 6 changed the configuration of serial ports from using /etc/inittab to using files in /etc/init.  So, create a /etc/init/ttyS1.conf that contains:
# ttyS1 - agetty
#
# This service maintains a agetty on ttyS1.

stop on runlevel [S016]
start on runlevel [23]

respawn
exec agetty /dev/ttyS1 19200 vt102
Do a "initctl start ttyS1" to start the getty.  Add ttyS1 to /etc/sercuretty if you want to allow root logins on that port (that bit didn't change).  You should then be able to use ipmitool for all your SOL needs.

Device br0 does not seem to be present, delaying initialization.

I recently received this error on a CentOS Linux machine handed off to me. A bit of a head scratcher. Getting on the console and running ifup by hand looked like:
# bash -x ./ifup-eth ifcfg-br0
+ . /etc/init.d/functions
++ TEXTDOMAIN=initscripts
++ umask 022
++ PATH=/sbin:/usr/sbin:/bin:/usr/bin
++ export PATH
++ '[' -z '' ']'
++ COLUMNS=80
++ '[' -z '' ']'
+++ /sbin/consoletype
++ CONSOLETYPE=pty
[...] The interesting part showed up a little later:
+ CONFIG=ifcfg-ifcfg-br0
+ '[' -f ifcfg-ifcfg-br0 ']'
+ CONFIG=ifcfg-br0
+ '[' -f ifcfg-br0 ']'
+ return
+ source_config
+ CONFIG=ifcfg-br0
+ DEVNAME=br0
+ . /etc/sysconfig/network-scripts/ifcfg-br0
++ DEVICE=br0
++ ONBOOT=yes
++ TYPE=bridge
++ BOOTPROTO=static
++ IPADDR=128.117.26.2
++ NETMASK=255.255.255.0
++ NM_CONTROLLED=no
+ '[' -r keys-br0 ']'
The eagle-eyed will have already spotted the error, the following helps the rest of us:
+ alias=
+ '[' 1 -eq 0 ']'
+ return 2
+ '[' -n '' ']'
+ '[' bridge = Bridge ']'
+ '[' bridge = Tap ']'
+ is_available br0
+ '[' -z br0 ']'
+ '[' -d /sys/class/net/br0 ']'
+ '[' -n '' ']'
++ modprobe -c
++ awk 'BEGIN { alias = ""; }
$1 == "alias" && $2 == "br0" { alias = $3; }
$1 == "install" { install[$2] = $3; }
END {
    cmd = install[alias];
    print alias;
    if (alias == "" || alias == "off" || cmd == "/bin/true" || cmd == ":")
        exit 1;
    exit 0;
}'
+ alias=
+ '[' 1 -eq 0 ']'
+ return 2
+ '[' -n '' ']'
+ net_log 'Device br0 does not seem to be present, delaying initialization.'
+ local 'message=Device br0 does not seem to be present, delaying initialization.'
+ local level=
+ local name=
+ '[' -z 'Device br0 does not seem to be present, delaying initialization.' ']'
+ '[' -z '' ']'
+ level=err
+ '[' -z '' ']'
+ name=./ifup-eth
+ echo Device br0 does not seem to be present, delaying initialization.
Device br0 does not seem to be present, delaying initialization.
+ '[' -x /usr/bin/logger ']'
+ /usr/bin/logger -p daemon.err -t ./ifup-eth 'Device br0 does not seem to be present, delaying initialization.'
+ return 0
+ exit 1
See the obvious "bridge = Bridge"? Well, maybe not if you're not at one with such things. Nonetheless, it takes a capital 'B' Bridge in /etc/sysconfig/network-scripts/ifcfg-br0

"Abyss" watch instructions translation

I saw a co-worker's "Abyss" watch from ThinkGeek and had to have one.  I ordered from Amazon, and here are the instructions for setting the time:
Note the completely made-up words.  Happily, the reverse side had instructions in Mandarin, and I have easy access to a native speaker/reader.  The instructions really are: tap face eight times and hold for three seconds to set the hours.  Hope this helps someone and hope that more companies employ better translators, or at least use google translate.

Friday, November 9, 2012

dd and the power of programming

I recently needed to extract part of a large (~8GB) file. The canonical method is to use dd. On a Linux system, the performance was abysmal. Here is the straight dd result.
# dd if=one.img of=two.img bs=1 skip=32768 count=8587192319
8587192319 bytes (8.6 GB) copied, 12442.3 s, 690 kB/s
That's 3.45 hours for those keeping track at home. Using /dev/shm helped.
# dd if=/dev/shm/one.img of=/dev/shm/two.img bs=1 skip=32768 count=8587192319
8587192319 bytes (8.6 GB) copied, 6232.88 s, 1.4 MB/s
That helped, but it's still 1.73 hours. Okay, so we all know the 1 byte block size is killing the performance. We also all know 8587192319 = 41809 205391, so let's bump up the block size.
# dd if=one.img of=two.img bs=205391 skip=32768 count=41809
9054+1 records in
9054+1 records out
1859682304 bytes (1.9 GB) copied, 1.59914 s, 1.2 GB/s
Clearly, much faster but also wrong: it should copy 8.6 GB. Let's reverse the numbers and try again.
# dd if=one.img of=two.img bs=41809 skip=32768 count=205391
172688+1 records in
172688+1 records out
7219937280 bytes (7.2 GB) copied, 29.4616 s, 245 MB/s
Closer, but still wrong. Something is wrong with dd's math. So, I wrote a Java program that takes an input file name, an output file name, and pairs of skip/write values. Here is the result.
# time java Chopper one.img two.img 32768 8587192319
Skipped 32768 bytes.
Writing 8587192319 bytes.

real    0m10.656s
user    0m1.744s
sys     0m8.933s
So, 10.7 seconds versus 3.45 hours. Here's the program.
/*
** Argrments: input file, output file, pairs of skip/write bytes
*/

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Chopper
{
    private static void readAndWrite (FileInputStream in, FileOutputStream out,
        long length)
    {
        /*
        ** Keep this sized to fit in an int for the read below.  Besides, 8K
        ** is a typical disk block size.
        */
        final long BUFFSIZE = 8192;
        byte buffer[] = new byte[(int) BUFFSIZE];

        for (;;)
        {
            int read = 0;
            int count = (int) (BUFFSIZE > length ? length : BUFFSIZE);

            try
            {
                read = in.read (buffer, 0, count);
                out.write (buffer, 0, read);
            }
            catch (IOException IOE)
            {
                System.out.println (IOE);
                return;
            }

            length -= read;

            if (length <= 0)
                break;
        }
    }

    public static void main (String args[])
    {
        FileInputStream in = null;
        FileOutputStream out = null;

        try
        {
            in = new FileInputStream (args[0]);
            out = new FileOutputStream (args[1]);
        }
        catch (IOException IOE)
        {
            System.out.println (IOE);
            return;
        }

        int i = 2;

        while (i < args.length)
        {
            try
            {
                long skipped = in.skip (Long.parseLong (args[i++]));
                System.out.println ("Skipped " + skipped + " bytes.");
            }
            catch (IOException IOE)
            {
                System.out.println (IOE);
                return;
            }

            long write = Long.parseLong (args[i++]);

            System.out.println ("Writing " + write + " bytes.");
            readAndWrite (in, out, write);
        }
    }
}

Monday, October 15, 2012

Reverse chronological package installs in OS X

pkgutil --pkgs | xargs -n 1 pkgutil --pkg-info | gawk '{printf("%s%s",$0,(NR%5==0)?"\n":"\0")}' | sort -n -k 6 | tr "\0" "\n" | gawk '/install-time/ {print $0 " " strftime("(%c)",$2); next}{print}'

Wednesday, October 3, 2012

Time(less) machine

Geez, I hate upgrading OSs.  No one gets it right, and we all collectively spend inordinate amounts of time dealing with the fallout.  Think of all the time (read: money) wasted on such headaches.  Most recently for me, the Time Machine backup program broke on an upgrade to 10.7.5.  Backups were estimated to have MAX_INT hours remaining.  It appears there is a conflict between Spotlight and Time Machine -- two programs from the same vendor.  One has to disable Spotlight via
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
and the run Time Machine. One might also have to reboot between the two.  After Time Machine runs, re-enable with
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
Running a dtruss on the backupd process shows a lot of
psynch_cvwait(0x7FE29969CE98, 0x28D0100028E00, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x28F0100029000, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2900100029100, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2910100029200, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2920100029300, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2930100029400, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2950100029600, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2960100029700, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2980100029900, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x29A0100029B00, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x29B0100029C00, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2940100029500, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2970100029800, 0x0)   = -1 Err#316
psynch_cvwait(0x7FE29969CE98, 0x2990100029A00, 0x0)   = -1 Err#316
So, there appears to be a threading issue here somewhere, but without the Time Machine source, it's difficult to track down.

Updates.  Doing a "sudo mdutil -i off /" appears to do approximately the same thing as the launchctl, but immediately, though I'm not convinced it's exactly the same thing.  And it appears one of Apple's recent updates fixed the problem -- let's hope they added a regression test for this.

Thursday, September 20, 2012

Mail unread menu and 5.3

Another thing that broke on an OSX upgrade was mail unread menu (http://loganrockmore.com/mailunreadmenu/) which I really like.  So with a little help from http://stib.posterous.com/how-to-fix-unsupported-plugins-after-upgradin I was able to write the following script (though you can cut and paste them directly into a Terminal (Applications -> Utilities -> Terminal) window).
#! /bin/sh

a=`defaults read /Applications/Mail.app/Contents/Info PluginCompatibilityUUID`
b=`defaults read /System/Library/Frameworks/Message.framework/Resources/Info PluginCompatibilityUUID`

for i in ~/Library/Mail/Bundles*/MailUnreadMenu.mailbundle/Contents/Info.plist
do
    echo "$i"
    echo "${i%%.plist}"

    defaults write "${i%%.plist}" SupportedPluginCompatibilityUUIDs -array-add "$a";
    defaults write "${i%%.plist}" SupportedPluginCompatibilityUUIDs -array-add "$b";
    plutil -convert xml1 "$i"
done
Then a
mv ~/Library/Mail/Bundles\ \(Disabled\)/MailUnreadMenu.mailbundle/ ~/Library/Mail/Bundles
Made things right again.