<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>blog@insidesystems.net</title>
    <link>http://blog.insidesystems.net/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Improving Network Reliability on FreeBSD</title>
      <description>&lt;p&gt;If you didn&amp;#8217;t notice it during the FreeBSD 7.0/6.3 release, FreeBSD got a great new tool from OpenBSD.  The &lt;a href="http://www.freebsd.org/doc/en/books/handbook/network-aggregation.html"&gt;lagg&lt;/a&gt; device.&lt;/p&gt;


	&lt;p&gt;This device allows you to setup links with failover, or to combine them using &lt;span class="caps"&gt;LACP&lt;/span&gt;, and the operation is dead simple.  Here&amp;#8217;s an example rc.conf, that just does a basic link failover:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
cloned_interfaces="lagg0" 
ifconfig_bge0="up" 
ifconfig_bge1="up" 
ifconfig_lagg0="laggproto failover laggport bge1 laggport bge0 192.168.1.5 netmask 255.255.255.0" 
&lt;/code&gt;
&lt;/pre&gt;

Or if you use 802.1q trunks
&lt;pre&gt;
&lt;code&gt;
cloned_interfaces="lagg0 vlan0" 
ifconfig_em0="up" 
ifconfig_em1="up" 
ifconfig_lagg0="laggproto failover laggport em0 laggport em1" 
ifconfig_vlan0="vlan 22 vlandev lagg0 192.168.1.5 netmask 255.255.255.0" 
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The only downside of this, at all, is you need to write a quick nagios plugin to check for dead links, but fortunately, that&amp;#8217;s easy enough to do as well.&lt;/p&gt;


	&lt;p&gt;Note: We don&amp;#8217;t currently use &lt;span class="caps"&gt;LACP&lt;/span&gt;, because we&amp;#8217;ve had some issues with it losing connectivity altogether, after alternating link failures.&lt;/p&gt;Example ifconfig output from a successful lagg setup:
&lt;pre&gt;
&lt;code&gt;
em0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=19b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4&amp;gt;
    ether 00:15:17:73:61:f4
    media: Ethernet 100baseTX &amp;lt;full-duplex&amp;gt;
    status: active
    lagg: laggdev lagg0
em4: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=19b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4&amp;gt;
    ether 00:15:17:73:61:f4
    media: Ethernet 100baseTX &amp;lt;full-duplex&amp;gt;
    status: active
    lagg: laggdev lagg0
lagg0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=19b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4&amp;gt;
    ether 00:15:17:73:61:f4
    inet 192.168.1.52 netmask 0xffffff00 broadcast 192.168.1.255
    media: Ethernet autoselect
    status: active
    laggproto failover
    laggport: em4 flags=0&amp;lt;&amp;gt;
    laggport: em0 flags=5&amp;lt;MASTER,ACTIVE&amp;gt;

&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Example ifconfig output from a successful vlan and lagg combination:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
bge0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=9b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM&amp;gt;
    ether 00:11:0a:30:21:04
    media: Ethernet autoselect (1000baseTX &amp;lt;full-duplex&amp;gt;)
    status: active
    lagg: laggdev lagg0
bge1: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=9b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM&amp;gt;
    ether 00:11:0a:30:21:04
    media: Ethernet autoselect (1000baseTX &amp;lt;full-duplex&amp;gt;)
    status: active
    lagg: laggdev lagg0
lagg0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=9b&amp;lt;RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM&amp;gt;
    ether 00:11:0a:30:21:04
    media: Ethernet autoselect
    status: active
    laggproto failover
    laggport: bge0 flags=0&amp;lt;&amp;gt;
    laggport: bge1 flags=5&amp;lt;MASTER,ACTIVE&amp;gt;
vlan0: flags=8843&amp;lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&amp;gt; metric 0 mtu 1500
    options=3&amp;lt;RXCSUM,TXCSUM&amp;gt;
    ether 00:11:0a:30:21:04
    inet 192.168.1.145 netmask 0xffffff00 broadcast 192.168.1.255
    media: Ethernet autoselect
    status: active
    vlan: 22 parent interface: lagg0
&lt;/code&gt;
&lt;/pre&gt;</description>
      <pubDate>Fri, 27 Jun 2008 16:05:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4b5f53ed-3dc4-454e-b9db-b8977ef9f80e</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2008/06/27/improving-network-reliability-on-freebsd</link>
      <category>FreeBSD</category>
      <category>Networking</category>
      <category>freebsd</category>
      <category>lagg</category>
      <category>lacp</category>
      <category>link</category>
      <category>aggregation</category>
      <category>vlan</category>
      <category>network</category>
    </item>
    <item>
      <title>Monitoring iLO2 with Nagios</title>
      <description>&lt;p&gt;We have a whole bunch of HP servers, purchased in large part for their excellent &lt;a href="http://h18004.www1.hp.com/products/servers/management/iloadv2/index.html"&gt;Lights-Out&lt;/a&gt; management software.  We wanted to have Nagios monitor some basic things, like the status of the fans, internal temperatures, power supplies, and VRMs.&lt;/p&gt;


	&lt;p&gt;Fortunately, that turned out to be pretty easy.&lt;/p&gt;&lt;p&gt;The first step was to download the HP Lights-Out &lt;span class="caps"&gt;XML&lt;/span&gt; Perl Scripting Sample for Linux.  I did this even though I don&amp;#8217;t use Linux as a platform.  The resulting file contains a bunch of sample &lt;span class="caps"&gt;XML&lt;/span&gt; scripts for accomplishing various goals, and a perl script (locfg.pl) that submits them to an iLO2 processor.&lt;/p&gt;


	&lt;p&gt;I then used locfg.pl to submit the following &lt;span class="caps"&gt;XML&lt;/span&gt; to each of our servers, in order to create a user with no substantial privileges.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
&amp;lt;RIBCL VERSION="2.0"&amp;gt;
  &amp;lt;LOGIN USER_LOGIN="adminuser" PASSWORD="adminpass"&amp;gt;
  &amp;lt;USER_INFO MODE="write"&amp;gt;
    &amp;lt;ADD_USER 
      USER_NAME="Nagios Monitor" 
      USER_LOGIN="nagiosuser" 
      PASSWORD="nagiospass"&amp;gt;
      &amp;lt;ADMIN_PRIV value ="N"/&amp;gt;
      &amp;lt;REMOTE_CONS_PRIV value ="N"/&amp;gt;
      &amp;lt;RESET_SERVER_PRIV value ="N"/&amp;gt;
      &amp;lt;VIRTUAL_MEDIA_PRIV value ="N"/&amp;gt;
      &amp;lt;CONFIG_ILO_PRIV value="N"/&amp;gt;
    &amp;lt;/ADD_USER&amp;gt;
  &amp;lt;/USER_INFO&amp;gt;
  &amp;lt;/LOGIN&amp;gt;
&amp;lt;/RIBCL&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;This script allowed me to quickly create unprivileged users on each of the iLO2 consoles.&lt;/p&gt;


	&lt;p&gt;Armed with an unprivileged user, I set about writing the actual plugin, and ended up with this:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
#!/usr/bin/env ruby
require 'optparse'
require 'socket'
require 'openssl'
require 'rexml/document'

# Command Line Options
options = {
  :server =&amp;gt; nil
}

opts = OptionParser.new do |opt|
  opt.banner = "Usage: #{$0}  [options]" 
  opt.on('-s', '--server HOSTNAME', String, "Hostname or IP of the server to query") { |i| options[:server] = i }
end
opts.parse!(ARGV)

if not options[:server]
  $stderr.puts "Server must be specified" 
  exit!
end

# iLO XML
xml_start = &amp;lt;&amp;lt;EOF
&amp;lt;RIBCL VERSION="2.22"&amp;gt;
  &amp;lt;LOGIN USER_LOGIN="nagiosuser" PASSWORD="nagiospass"&amp;gt;
EOF

xml_end = &amp;lt;&amp;lt;EOF
  &amp;lt;/LOGIN&amp;gt;
&amp;lt;/RIBCL&amp;gt;
EOF

xml_emhealth = &amp;lt;&amp;lt;EOF
&amp;lt;SERVER_INFO MODE="read"&amp;gt;
  &amp;lt;GET_EMBEDDED_HEALTH /&amp;gt;
&amp;lt;/SERVER_INFO&amp;gt;
EOF

error_cnt = 0
error_msg = ''
error_summary = ''

s = TCPsocket.open(options[:server], 443)
ssl = OpenSSL::SSL::SSLSocket.new(s, OpenSSL::SSL::SSLContext.new)
ssl.sync
ssl.connect
ssl.write("&amp;lt;?xml version=\"1.0\"?&amp;gt;\r\n")
ssl.write(xml_start)
ssl.write(xml_emhealth)
ssl.write(xml_end)
ssl.flush
res = ssl.readlines

ssl.close
s.close

doc = REXML::Document.new(res.to_s.match(/&amp;lt;GET_EMBEDDED_HEALTH_DATA&amp;gt;.*&amp;lt;\/GET_EMBEDDED_HEALTH_DATA&amp;gt;/m).to_s)

if ! doc.elements["GET_EMBEDDED_HEALTH_DATA"]
  error_cnt += 1
  error_msg += "Unable to fetch embedded health data\n" 
end

doc.root.elements["FANS"].each_element('//FAN') { |mod|
  if mod.elements["STATUS"].attributes['VALUE'] != 'Ok'
    error_cnt += 1
    error_msg += "#{mod.elements['LABEL'].attributes['VALUE']} - #{mod.elements['ZONE'].attributes['VALUE']} - #{mod.elements['STATUS'].attributes['VALUE']}\n" 
    error_summary += "#{mod.elements['LABEL'].attributes['VALUE']}." 
  end
}

doc.root.elements["TEMPERATURE"].each_element('//TEMP') { |mod|
  if mod.elements["STATUS"].attributes['VALUE'] != 'Ok' and mod.elements["STATUS"].attributes['VALUE'] != 'n/a'
    error_cnt += 1
    error_msg += "#{mod.elements['LABEL'].attributes['VALUE']} - #{mod.elements['LOCATION'].attributes['VALUE']} - #{mod.elements['STATUS'].attributes['VALUE']} - #{mod.elements['CURRENTREADING'].attributes['VALUE']} #{mod.elements['CURRENTREADING'].attributes['UNIT']} (Caution/Critical: #{mod.elements['CAUTION'].attributes['VALUE']}/#{mod.elements['CRITICAL'].attributes['VALUE']})\n" 
    error_summary += "#{mod.elements['LABEL'].attributes['VALUE']}." 
  end
}

doc.root.elements["VRM"].each_element('//MODULE') { |mod|
  if mod.elements["STATUS"].attributes['VALUE'] != 'Ok'
    error_cnt += 1
    error_msg += "#{mod.elements['LABEL'].attributes['VALUE']} - #{mod.elements['STATUS'].attributes['VALUE']}\n" 
    error_summary += "#{mod.elements['LABEL'].attributes['VALUE']}." 
  end
}

doc.root.elements["POWER_SUPPLIES"].each_element('//SUPPLY') { |mod|
  if mod.elements["STATUS"].attributes['VALUE'] != 'Ok'
    error_cnt += 1
    error_msg += "#{mod.elements['LABEL'].attributes['VALUE']} - #{mod.elements['STATUS'].attributes['VALUE']}\n" 
    error_summary += "#{mod.elements['LABEL'].attributes['VALUE']}." 
  end
}

if error_cnt == 0
  puts "OK: 0 problems" 
  rc=0
else
  puts "Critical: #{error_cnt} problems. #{error_summary}" 
  puts error_msg
  rc=2
end

exit rc
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Now having that in place, I simply added all of the iLO2 hosts to a hostgroup, and added a service to check that group using the script, and all my fans, power supplies and such are now monitored without any operating-system level overhead.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Sep 2007 08:21:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:2a56f074-881c-4f4f-af36-91961aa2c1fe</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/09/05/monitoring-ilo2-with-nagios</link>
      <category>FreeBSD</category>
      <category>Off-Topic</category>
      <category>System Administration</category>
    </item>
    <item>
      <title>QS, AppleScript and moving windows</title>
      <description>&lt;p&gt;&lt;span class="caps"&gt;A 15&lt;/span&gt;&amp;#8221; laptop has a relatively small display, so I find myself routinely wanting to put a window all the way to one edge or the other, to help maximize the use of this.&lt;/p&gt;


	&lt;p&gt;I decided that this should be simple, something along the lines of ^⌥⌘&amp;larr; to slam a window to the left edge of my screen and so on.&lt;/p&gt;


	&lt;p&gt;There were a few hitches, but I did it as follows:&lt;/p&gt;&lt;p&gt;First I made some scripts:&lt;/p&gt;


move_left
&lt;pre&gt;
&lt;code&gt;
tell application "Finder" 
    set {disp_x1, disp_y1, disp_x2, disp_y2} to bounds of window of desktop
end tell

tell application "System Events" 
    set frontmostApplication to name of the first process whose frontmost is true

    tell process frontmostApplication
        tell window 1
            set {x1, y1} to position
            set position to {disp_x1, y1}
        end tell
    end tell
end tell
&lt;/code&gt;
&lt;/pre&gt;

move_right
&lt;pre&gt;
&lt;code&gt;
tell application "Finder" 
    set {disp_x1, disp_y1, disp_x2, disp_y2} to bounds of window of desktop
end tell

tell application "System Events" 
    set frontmostApplication to name of the first process whose frontmost is true

    tell process frontmostApplication
        tell window 1
            set {x1, y1} to position
            set {x_off, y_off} to size

            set position to {disp_x2 - x_off, y1}
        end tell
    end tell
end tell
&lt;/code&gt;
&lt;/pre&gt;

move up
&lt;pre&gt;&lt;code&gt;
tell application "Finder" 
    set {disp_x1, disp_y1, disp_x2, disp_y2} to bounds of window of desktop
end tell

tell application "System Events" 
    set frontmostApplication to name of the first process whose frontmost is true

    set disp_y1 to disp_y1 + 22

    tell process frontmostApplication
        tell window 1
            set {x1, y1} to position

            set position to {x1, disp_y1}
        end tell
    end tell
end tell
&lt;/code&gt;
&lt;/pre&gt;

move down
&lt;pre&gt;
&lt;code&gt;
tell application "Finder" 
    set {disp_x1, disp_y1, disp_x2, disp_y2} to bounds of window of desktop
end tell

tell application "System Events" 
    set frontmostApplication to name of the first process whose frontmost is true

    tell process frontmostApplication
        tell window 1
            set {x1, y1} to position
            set {x_off, y_off} to size

            set position to {x1, disp_y2 - y_off}
        end tell
    end tell
end tell
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;And at the suggestion of Alex L.&lt;/p&gt;


move center
&lt;pre&gt;
&lt;code&gt;
tell application "Finder" 
    set {disp_x1, disp_y1, disp_x2, disp_y2} to bounds of window of desktop
end tell

tell application "System Events" 
    set frontmostApplication to name of the first process whose frontmost is true

    set disp_y1 to disp_y1 + 22

    tell process frontmostApplication
        tell window 1
            set {x1, y1} to position
            set {x_off, y_off} to size

            set position to {disp_x1 + (disp_x2 - x_off) / 2, disp_y1 + (disp_y2 - y_off) / 2}
        end tell
    end tell
end tell
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;I added these to QS hotkeys, and  used the same technique to make windows do incremental moves as well.&lt;/p&gt;


	&lt;p&gt;Credit to the MacNN Forums, who helped me find a useful answer in &lt;a href="http://forums.macnn.com/79/developer-center/345599/moving-windows-with-qs-and-applescript/"&gt;this thread&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Follow-up: Zachary Cohen wrote a correction: 
&lt;em&gt;Seems like a cool little article, but you need to make sure that Access for assistive devices is turned on. You do this by going to &amp;#8220;System Preferences&amp;#8221; then selecting the &amp;#8220;Universal Access&amp;#8221; from the options. Then click the click the checkbox at the bottom &amp;#8220;Enable access for assistive devices&amp;#8221; then these scripts should work. &lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 20 Aug 2007 02:53:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:7ddf7bb3-9e73-43bb-a292-6df566fbef07</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/08/20/qs-applescript-and-moving-windows</link>
      <category>Off-Topic</category>
      <category>OS X</category>
    </item>
    <item>
      <title>Growl, Mail.app and AppleScript</title>
      <description>&lt;p&gt;I wanted a simple system that would notify me whenever I received an e-mail from somebody &amp;#8220;important&amp;#8221;, but not for every new message that hit my inbox.&lt;/p&gt;


	&lt;p&gt;I tried GrowlMail and Mail.Appetizer, but found them both unsatisfactory.  I finally decided that what I really wanted was a growl message to appear for messages from selected recipients.  Something with the name and the subject of the e-mail, like this:&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.insidesystems.net/files/growl.png"&gt;&lt;/p&gt;


	&lt;p&gt;Fortunately, it turned out to be reasonably simple.&lt;/p&gt;&lt;p&gt;First, I opened up Address Book, and made sure that the important people were all listed in appropriate groups and correct e-mail addresses.&lt;/p&gt;


	&lt;p&gt;Having done that, I opened Mail.app, and added a rule:&lt;/p&gt;


&lt;blockquote&gt;
Description: Growl&lt;br/&gt;
&lt;br/&gt;
If any of the following conditions are met:&lt;br/&gt;
Sender is member of Group: Clients&lt;br/&gt;
Sender is member of Group: Family&lt;br/&gt;
Sender is member of Group: InsideSystems&lt;br/&gt;
&lt;br/&gt;
Perform the following actions:&lt;br/&gt;
Run AppleScript: ~/Library/Scripts/Applications/Mail/MailScript.scpt&lt;br/&gt;
&lt;/blockquote&gt;

but ho, you say, that script does not exist!  Never fear, then I loaded up Script Editor and created MailScript.scpt as follows:
&lt;pre&gt;
&lt;code&gt;
on perform_mail_action(info)

    tell application "Mail" 

        set selectedMessages to |SelectedMessages| of info
        set theRule to |Rule| of info

        repeat with eachMessage in selectedMessages
            set theSubject to subject of eachMessage
            set theSender to sender of eachMessage

            tell application "GrowlHelperApp" 

                set the allNotificationsList to ¬
                    {"New Mail"}

                set the enabledNotificationsList to ¬
                    {"New Mail"}

                register as application ¬
                    "MailScript" all notifications allNotificationsList ¬
                    default notifications enabledNotificationsList ¬
                    icon of application "Mail" 

                notify with name ¬
                    "New Mail" title ¬
                    "New Mail from " &amp;#38; theSender description ¬
                    theSubject application name "MailScript" 

            end tell

        end repeat
    end tell
end perform_mail_action
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Now, this was the first time I ever did anything in AppleScript, so it&amp;#8217;s quite possible there is a much better way to do all of this.  As it stands, I simply glued together some sample code from Growl and some sample code from &lt;a href="http://www.macosxhints.com/article.php?story=20030116071118239"&gt;this hint&lt;/a&gt; on the excellent &lt;a href="http://www.macosxhints.com"&gt;MacOSXHints.com&lt;/a&gt;, and it appears to work as desired.&lt;/p&gt;


	&lt;p&gt;Finally, I went into the growl prefpane, and set the priority and stickiness, so that these messages would stay on my screen even if I happened to be otherwise occupied when they came in.&lt;/p&gt;


	&lt;p&gt;Voila!  Nothing spectacularly complex, but it&amp;#8217;s a nice example of what I like about Apple.  Everything&amp;#8217;s easy to use out of the box, but when I dreamed up a random feature, I was able to implement it in a short period of time, despite having never even used their glue language before.&lt;/p&gt;


	&lt;p&gt;Hopefully somebody else would like this feature too!&lt;/p&gt;</description>
      <pubDate>Fri, 17 Aug 2007 14:55:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:74a15967-64c7-433a-a416-8f1c880d31be</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/08/17/growl-mail-app-and-applescript</link>
      <category>E-Mail</category>
      <category>Off-Topic</category>
      <category>OS X</category>
    </item>
    <item>
      <title>PostgreSQL scaling on 6.2 and 7.0</title>
      <description>&lt;p&gt;My previous posts have documented the utterly insane lack of scalability of PostgreSQL (at least according to that particular metric) on FreeBSD 6.2.&lt;/p&gt;


	&lt;p&gt;I ran the same test, on the same machine, using 7.0 with the 4BSD and the &lt;span class="caps"&gt;ULE&lt;/span&gt; schedulers.  Postgres was tuned as in the previous posts, and &lt;span class="caps"&gt;WITNESS&lt;/span&gt;, INVARIANTS and all malloc debugging options were off.&lt;/p&gt;


	&lt;p&gt;Results:
&lt;img src="http://blog.insidesystems.net/files/postgres-fbsd-62-70ule-704b.png"&gt;&lt;/p&gt;


	&lt;p&gt;Hopefully nobody will extrapolate this to mean more than it really does (it&amp;#8217;s just one test, but it&amp;#8217;s one that happens to matter to me.)&lt;/p&gt;</description>
      <pubDate>Wed, 11 Apr 2007 18:40:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:2357eb5b-6e89-4e5f-8cba-2c3d7778ebb3</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/04/11/postgresql-scaling-on-6-2-and-7-0</link>
      <category>FreeBSD</category>
      <category>System Administration</category>
      <category>PostgreSQL</category>
    </item>
    <item>
      <title>More is better?</title>
      <description>&lt;p&gt;Not always.  I did some more tests, and confirmed that this particular workload actually gets slower as you add more than 2 cores.&lt;/p&gt;


&lt;code&gt;
&lt;pre&gt;
sysbench --num-threads=${i} --test=oltp --pgsql-user=bench --pgsql-db=bench --db-driver=pgsql --max-time=60 --max-requests=0 --oltp-read-only=on run
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;Here&amp;#8217;s the results, with the tests run on absolutely identical hardware.  (HP &lt;span class="caps"&gt;DL360&lt;/span&gt;, 2.00 GHz &lt;span class="caps"&gt;E5335&lt;/span&gt; Xeon, 10K &lt;span class="caps"&gt;RPM SAS&lt;/span&gt; drives, 10 GB of &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.insidesystems.net/files/postgres-fbsd62-v2.png"&gt;&lt;/p&gt;


	&lt;p&gt;I know 6.2 isn&amp;#8217;t the greatest for &lt;span class="caps"&gt;SMP&lt;/span&gt;, but I was still surprised to learn that we could get significantly lower overall performance by adding more processors.&lt;/p&gt;


	&lt;p&gt;I tried to test 7.0, but the 7.0 installer didn&amp;#8217;t seem to recognize the iLO virtual keyboard tonight.  Maybe tomorrow will go better.&lt;/p&gt;</description>
      <pubDate>Wed, 11 Apr 2007 03:55:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:f1fc3bec-3daf-4d4d-a525-6e48cd2829a5</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/04/11/more-is-better</link>
      <category>FreeBSD</category>
      <category>System Administration</category>
      <category>PostgreSQL</category>
    </item>
    <item>
      <title>What did I do wrong?</title>
      <description>&lt;p&gt;I&amp;#8217;m hoping that somebody will look at this and say &amp;#8220;hey, dummy, you did this all wrong.&amp;#8221;  I&amp;#8217;m hoping that, because the results are shocking.&lt;/p&gt;


	&lt;p&gt;There have been a buzz about FreeBSD&amp;#8217;s &lt;span class="caps"&gt;SMP&lt;/span&gt; performance compared to Linux&amp;#8217;s, particularly a particular 8-core &lt;span class="caps"&gt;SMP&lt;/span&gt; test, using FreeBSD 7.0, sysbench, and mysql.  A number of people mentioned that there were known problems with this test and PostgreSQL, so I decided to see how bad the problems were.&lt;/p&gt;&lt;p&gt;The results are so shocking, that my first thought was that I must have done something wrong.&lt;/p&gt;


	&lt;p&gt;The hardware:&lt;/p&gt;


	&lt;p&gt;Machine 1:&lt;br/&gt;
&lt;span class="caps"&gt;HP DL360 G5&lt;/span&gt;&lt;br/&gt;
1 5140 (dual core) 2.33 GHz (1333 &lt;span class="caps"&gt;FSB&lt;/span&gt;) Xeon&lt;br/&gt;
4 &lt;span class="caps"&gt;GB RAM&lt;/span&gt;&lt;br/&gt;
2 15K &lt;span class="caps"&gt;RPM SAS&lt;/span&gt; hard drives, running as mirrors through an e400i drive array&lt;/p&gt;


	&lt;p&gt;Machine 2:&lt;br/&gt;
&lt;span class="caps"&gt;HP DL360 G5&lt;/span&gt;&lt;br/&gt;
2 &lt;span class="caps"&gt;E5335&lt;/span&gt; (quad core) 2.33 GHz (1333 &lt;span class="caps"&gt;FSB&lt;/span&gt;) Xeons&lt;br/&gt;
10 &lt;span class="caps"&gt;GB RAM&lt;/span&gt;&lt;br/&gt;
2 10K &lt;span class="caps"&gt;RPM SAS&lt;/span&gt; hard drives, running as mirrors through an e400i drive array&lt;/p&gt;


	&lt;p&gt;Operating System:
Both machines are running FreeBSD 6.2-p3.  After all, I wanted to see what performance levels to expect with production-quality software, not the 7.0 sweetness.&lt;/p&gt;


	&lt;p&gt;Kernel:
Both are running identically configured &lt;span class="caps"&gt;SMP&lt;/span&gt;-enabled amd64 kernels.&lt;/p&gt;


sysctl.conf:  both have the following
&lt;code&gt;
&lt;pre&gt;
kern.ipc.shmmax=2147483647
kern.ipc.shmall=524288
kern.ipc.semmsl=512
kern.ipc.semmap=256
kern.ipc.somaxconn=2048
kern.maxfiles=65536
vfs.read_max=32
&lt;/pre&gt;
&lt;/code&gt;

loader.conf: both have the following
&lt;code&gt;
&lt;pre&gt;
kern.ipc.semmni=256
kern.ipc.semmns=2048
&lt;/pre&gt;
&lt;/code&gt;

postgresql.conf: both have the following settings changed
&lt;code&gt;
&lt;pre&gt;
shared_buffers = 1GB                 
work_mem = 64MB
maintenance_work_mem = 32MB
max_fsm_pages = 204800   
random_page_cost = 3.0
effective_cache_size = 512MB
update_process_title = off
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;Both drive arrays are partitioned identically, and postgres was installed as the only running application in each case.&lt;/p&gt;


The test was run as follows:
&lt;code&gt;
&lt;pre&gt;
sysbench --num-threads=${i} --test=oltp --pgsql-user=bench --pgsql-db=bench --db-driver=pgsql --max-time=120 --max-requests=0 --oltp-read-only=on run
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;And yet here are the results:&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.insidesystems.net/files/sysctl-pgsq-amd64-wtf.png"&gt;&lt;/p&gt;


	&lt;p&gt;Yes, the 8-core, 10GB machine is massively slower than the 2-core 4GB machine.&lt;/p&gt;


	&lt;p&gt;This can&amp;#8217;t be right, can it?&lt;/p&gt;


Followup: I ran this single-cpu test:
&lt;code&gt;
&lt;pre&gt;
openssl speed rsa
&lt;/pre&gt;
&lt;/code&gt;

1&amp;#215;2-Core 2.33GHz 5140 Xeon
&lt;code&gt;
&lt;pre&gt;
                  sign    verify    sign/s verify/s
rsa  512 bits   0.0003s   0.0000s   3905.9  45028.8
rsa 1024 bits   0.0009s   0.0001s   1164.6  18787.2
rsa 2048 bits   0.0049s   0.0002s    205.2   6332.2
rsa 4096 bits   0.0320s   0.0005s     31.2   1917.9

&lt;/pre&gt;
&lt;/code&gt;

2&amp;#215;4-Core 2.33 GHz &lt;span class="caps"&gt;E5335&lt;/span&gt; Xeon
&lt;code&gt;
&lt;pre&gt;
rsa  512 bits   0.0003s   0.0000s   3381.1  38972.0
rsa 1024 bits   0.0010s   0.0001s   1003.5  15991.7
rsa 2048 bits   0.0057s   0.0002s    176.7   5481.7
rsa 4096 bits   0.0373s   0.0006s     26.8   1638.6
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;I wanted to see if this was simply one algorithm, or if other algorithms showed the same sort of slowdown, so I ran the following:&lt;/p&gt;


&lt;code&gt;
&lt;pre&gt;
openssl speed md5 sha1 aes-256-cbc
&lt;/pre&gt;
&lt;/code&gt;

The 2-core machine:
&lt;code&gt;
&lt;pre&gt;
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
md5              14172.75k    45816.42k   114118.73k   182293.03k   220175.36k
sha1             14901.45k    42795.69k    97387.27k   143547.69k   166264.67k
aes-256 cbc      91518.54k    94159.65k    93817.92k    92696.25k    93907.24k
&lt;/pre&gt;
&lt;/code&gt;

The 8-core machine:
&lt;code&gt;
&lt;pre&gt;
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
md5              12305.58k    39149.96k    97745.88k   155771.63k   188252.02k
sha1             12740.06k    36648.90k    83318.76k   122733.05k   142119.67k
aes-256 cbc      78109.56k    80589.95k    81222.08k    81406.47k    81401.94k
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;The 8-core is a little slower than the 2-core again, but not by the enormous levels we see on the pgsql sysbench.&lt;/p&gt;


	&lt;p&gt;When running &lt;span class="caps"&gt;RSA&lt;/span&gt; across multiple threads, the results are closer to what one would expect.  The command I used to do this:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
openssl speed rsa -multi N
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;&lt;img src="http://blog.insidesystems.net/files/amd64-normal.png"&gt;&lt;/p&gt;


	&lt;p&gt;And now I&amp;#8217;m left with the question:  Did I screw something up, or is this what Kris Kennaway was talking about when he wrote &lt;a href="http://lists.freebsd.org/pipermail/freebsd-performance/2007-February/002510.html"&gt;this message&lt;/a&gt;?&lt;/p&gt;


	&lt;p&gt;I must admit, that while I expected the performance to fall off, it never occurred to me that an 8-core system could be slower than a 2-core system right out of the gate.&lt;/p&gt;</description>
      <pubDate>Mon, 09 Apr 2007 21:09:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:bea24221-58d2-4935-a45f-d92dfc38ca49</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/04/09/what-did-i-do-wrong</link>
      <category>Databases</category>
      <category>FreeBSD</category>
      <category>System Administration</category>
      <category>PostgreSQL</category>
    </item>
    <item>
      <title>Unscientific 15K v 10K SAS Drive Comparison</title>
      <description>&lt;p&gt;We&amp;#8217;ve been buying a lot of new machines today, and almost all of them come with &lt;span class="caps"&gt;SAS&lt;/span&gt; drives.  We bought 10K &lt;span class="caps"&gt;SAS&lt;/span&gt; drives for obviously performance-neutral applications, and 15K &lt;span class="caps"&gt;SAS&lt;/span&gt; drives for performance-critical applications, but what exactly did we get for an extra $200/drive?&lt;/p&gt;


	&lt;p&gt;I decided to do some wildly unscientific tests, using two HP DL360s, one with mirrored 10K &lt;span class="caps"&gt;RPM&lt;/span&gt; drives, the other with mirrored 15K &lt;span class="caps"&gt;RPM&lt;/span&gt; drives, both running FreeBSD 6.2/AMD64.  Both machines are equipped with P400i drive controllers.&lt;/p&gt;10K &lt;span class="caps"&gt;SAS&lt;/span&gt; drives
&lt;code&gt;
&lt;pre&gt;
# diskinfo -t /dev/da0
/dev/da0
        512             # sectorsize
        73372631040     # mediasize in bytes (68G)
        143305920       # mediasize in sectors
        17562           # Cylinders according to firmware.
        255             # Heads according to firmware.
        32              # Sectors according to firmware.

Seek times:
        Full stroke:      250 iter in   1.016654 sec =    4.067 msec
        Half stroke:      250 iter in   0.955639 sec =    3.823 msec
        Quarter stroke:   500 iter in   1.960625 sec =    3.921 msec
        Short forward:    400 iter in   1.444117 sec =    3.610 msec
        Short backward:   400 iter in   1.457452 sec =    3.644 msec
        Seq outer:       2048 iter in   2.067837 sec =    1.010 msec
        Seq inner:       2048 iter in   2.069040 sec =    1.010 msec
Transfer rates:
        outside:       102400 kbytes in   2.078970 sec =    49255 kbytes/sec
        middle:        102400 kbytes in   2.598712 sec =    39404 kbytes/sec
        inside:        102400 kbytes in   3.115841 sec =    32864 kbytes/sec
&lt;/pre&gt;
&lt;/code&gt;

15K &lt;span class="caps"&gt;SAS&lt;/span&gt; Drives
&lt;code&gt;
&lt;pre&gt;
#  diskinfo -t /dev/da0
/dev/da0
        512             # sectorsize
        73372631040     # mediasize in bytes (68G)
        143305920       # mediasize in sectors
        17562           # Cylinders according to firmware.
        255             # Heads according to firmware.
        32              # Sectors according to firmware.

Seek times:
        Full stroke:      250 iter in   0.723955 sec =    2.896 msec
        Half stroke:      250 iter in   0.756001 sec =    3.024 msec
        Quarter stroke:   500 iter in   1.255116 sec =    2.510 msec
        Short forward:    400 iter in   0.680525 sec =    1.701 msec
        Short backward:   400 iter in   0.878597 sec =    2.196 msec
        Seq outer:       2048 iter in   2.055020 sec =    1.003 msec
        Seq inner:       2048 iter in   2.062749 sec =    1.007 msec
Transfer rates:
        outside:       102400 kbytes in   1.331560 sec =    76902 kbytes/sec
        middle:        102400 kbytes in   1.848040 sec =    55410 kbytes/sec
        inside:        102400 kbytes in   1.652754 sec =    61957 kbytes/sec
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;So far, so good.  As expected, the results are faster for all the tasks that require seeking, and sequential transfer rates are considerably higher as well.  I think I like these tiny lil drives.&lt;/p&gt;


	&lt;p&gt;Now let&amp;#8217;s try some bonnie, with some big files.  Let&amp;#8217;s try &lt;code&gt; bonnie++ -d /usr/home -u root -s 16g -n 256:65536:65536:16&lt;/code&gt;&lt;/p&gt;


10K &lt;span class="caps"&gt;SAS&lt;/span&gt; mirror
&lt;code&gt;
&lt;pre&gt;
Version 1.93c       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
anemone.insides 16G   379  99 49303  13 14526   9   621  98 30751   7 423.1  94
Latency             22409us     394ms    1414ms   37000us     142ms     121ms
Version 1.93c       ------Sequential Create------ --------Random Create--------
anemone.insidesyste -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files:max:min        /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
 256:65536:65536/16   540  14   661  47 32500  63   588  15   117   8  8358  64
Latency              3045ms     175ms     506ms    2631ms    1841ms     946ms
1.93c,1.93c,anemone.insidesystems.net,1,1176110507,16G,,379,99,49303,13,14526,9,621,98,30751,7,423.1,94,256,65536,65536,,16,540,14,661,47,32500,63,588,15,117,8,8358,64,22409us,394ms,1414ms,37000us,142ms,121ms,3045ms,175ms,506ms,2631ms,1841ms,946ms
&lt;/pre&gt;
&lt;/code&gt;

15k &lt;span class="caps"&gt;SAS&lt;/span&gt; mirror
&lt;code&gt;
&lt;pre&gt;
Version 1.93c       ------Sequential Output------ --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
noname.insidesy 16G   444  99 77857  19 22512   6   613  94 85113  15 490.1  15
Latency             20163us    2910ms     296ms     274ms     114ms   51627us
Version 1.93c       ------Sequential Create------ --------Random Create--------
noname.insidesystem -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
files:max:min        /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
 256:65536:65536/16  1013  19   845  13 44078  86   959  18   103   3 13215  94
Latency              2763ms     800ms   57543us    2798ms    1805ms     259ms
1.93c,1.93c,noname.insidesystems.net,1,1176153578,16G,,444,99,77857,19,22512,6,613,94,85113,15,490.1,15,256,65536,65536,,16,1013,19,845,13,44078,86,959,18,103,3,13215,94,20163us,2910ms,296ms,274ms,114ms,51627us,2763ms,800ms,57543us,2798ms,1805ms,259ms
&lt;/pre&gt;
&lt;/code&gt;

	&lt;p&gt;And with that, I was reasonably satisfied that we weren&amp;#8217;t wasting money when we bought the 15K &lt;span class="caps"&gt;SAS&lt;/span&gt; drives.&lt;/p&gt;</description>
      <pubDate>Mon, 09 Apr 2007 16:50:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:64377c54-59b3-4769-833d-924cf7a409af</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/04/09/unscientific-15k-v-10k-sas-drive-comparison</link>
      <category>FreeBSD</category>
      <category>System Administration</category>
    </item>
    <item>
      <title>DELETE FROM important WHERE overly broad condition;</title>
      <description>&lt;p&gt;A client had an interesting problem.  They had a critical PostgreSQL database, and they accidentally ran an overly broad delete on a table.&lt;/p&gt;


	&lt;p&gt;And their newest backup was two weeks old.&lt;/p&gt;


	&lt;p&gt;Could we help?  Of course we could help.&lt;/p&gt;&lt;p&gt;The procedure used was as follows:&lt;/p&gt;


	&lt;p&gt;1) Stop the database.&lt;/p&gt;


	&lt;p&gt;2) Backup the database files to a secure location.&lt;/p&gt;


	&lt;p&gt;3) Make a second copy of the database files, to a new, empty postgresql instance.&lt;/p&gt;


	&lt;p&gt;4) Now if you have a dump prior to the error, and xlogs for the entire time period, you can do a Point-In-Time Recovery, with a properly configured recovery.conf.  Unfortunately we didn&amp;#8217;t have that.  We had a two-week old dump and 6 hours of xlogs.&lt;/p&gt;


	&lt;p&gt;5) Try to determine an approximate transaction ID of the mistake.  We did this by looking at timestamps of files on the newest pg_clog file, finding one that happened before the mistake, and then multiplying it&amp;#8217;s name by 1048576.&lt;/p&gt;


	&lt;p&gt;6) Then we used that xid with &lt;a href="http://www.postgresql.org/docs/current/static/app-pgresetxlog.html"&gt;pg_resetxlog&lt;/a&gt;, on the secondary database that we had created.  It worked, and we had a view of the data.  We then played a bit, to find an xid that was acceptably close to the point of failure.&lt;/p&gt;


	&lt;p&gt;7) From there, we just did a straight &lt;span class="caps"&gt;SQL COPY&lt;/span&gt;, to get the data from the db server we had just setup onto the original database, and to get it loaded.&lt;/p&gt;


	&lt;p&gt;It wasn&amp;#8217;t the most elegant solution, but it worked beautifully, and the client was pleased.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s to hoping you never need this information!&lt;/p&gt;</description>
      <pubDate>Tue, 13 Mar 2007 23:20:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:a692a8c8-35c8-4c18-a571-876210c20ca3</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/03/13/delete-from-important-where-overly-broad-condition</link>
      <category>Databases</category>
      <category>System Administration</category>
      <category>PostgreSQL</category>
    </item>
    <item>
      <title>FreeBSD, PHP and Pecl</title>
      <description>&lt;p&gt;I was helping move a legacy &lt;span class="caps"&gt;PHP&lt;/span&gt; app to a new server, and found it needed a &lt;span class="caps"&gt;PECL&lt;/span&gt; extension (dbx).&lt;/p&gt;


	&lt;p&gt;After installing &lt;span class="caps"&gt;PEAR&lt;/span&gt;, I got the following error:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
[root@machine php]# pecl install something

Fatal error: Call to undefined function preg_match() in /usr/local/share/pear/PEAR/Frontend/CLI.php on line 70
&lt;/code&gt;
&lt;/pre&gt;&lt;p&gt;It turns out that the problem is that within FreeBSD&amp;#8217;s installation of &lt;span class="caps"&gt;PECL&lt;/span&gt;, it calls &lt;span class="caps"&gt;PHP&lt;/span&gt; from the command line with the -n flag.  a.k.a. &amp;#8212;no-php-ini&lt;/p&gt;


	&lt;p&gt;This prevents /usr/local/etc/php/extensions.ini from getting loaded, and thus there is no &lt;span class="caps"&gt;PCRE&lt;/span&gt; support.&lt;/p&gt;


	&lt;p&gt;You can work around it by removing &amp;#8220;-n&amp;#8221; from inside the pecl script.&lt;/p&gt;</description>
      <pubDate>Tue, 27 Feb 2007 21:55:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:e1633eb1-7fbb-4ea9-af87-8e183f6ad67f</guid>
      <author>Kevin Way</author>
      <link>http://blog.insidesystems.net/articles/2007/02/27/freebsd-php-and-pecl</link>
      <category>FreeBSD</category>
      <category>System Administration</category>
      <category>PHP</category>
    </item>
  </channel>
</rss>
