<?xml version="1.0" encoding="utf-8"?>

<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Hozer Central</title>
<subtitle type="html"><![CDATA[
Beware the Johnnies, they will hoze you.
]]></subtitle>
<id>http://jason.koelker.net/blog/index.atom</id>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog" />
<link rel="self" type="text/xml" href="http://jason.koelker.net/blog/index.atom" />

<author>
<name>Jason Kölker</name>
<uri>http://jason.koelker.net/blog/index.atom</uri>
<email>jason@koelker.net</email>
</author>
<rights>Copyright 2006 Jason Kölker.  This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License</rights>
<generator uri="http://pyblosxom.sourceforge.net/" version="1.3.2 2/13/2006">
PyBlosxom http://pyblosxom.sourceforge.net/ 1.3.2 2/13/2006
</generator>

<updated>2007-10-29T23:35:13Z</updated>
<!-- icon?  logo?  -->

<entry>
<title type="html">Sorting a python list of dictionaries</title>
<category term="" />
<id>http://jason.koelker.net/blog/2007/10/29/Sorting_a_python_list_of_dictionaries</id>
<updated>2007-10-29T23:35:13Z</updated>
<published>2007-10-29T23:35:13Z</published>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog/Sorting_a_python_list_of_dictionaries" />
<content type="html">
&lt;p&gt;Lately I&apos;ve been using lists of dictionaries a lot to store data to be processed sequentially.  More often than not, the data gets loaded into the list in an ordered state, but I needed a way to force it to be ordered by a key of the dictionary.  Luckily the sort() list function takes as an argument a function to do the comparison for me.  Since the comparison is just a simple is this key less than another key I made my first venture into lambda functions:&lt;/p&gt;

&lt;pre&gt;
l = [ {&quot;name&quot;: &quot;1234&quot;, &quot;attribute1&quot;: &quot;this is an attribute&quot;, &quot;attribute2&quot;: &quot;this is another&quot;},
        {&quot;name&quot;: &quot;4325&quot;, &quot;attribute1&quot;: &quot;this is an attribute&quot;, &quot;attribute2&quot;: &quot;this is another&quot;},
        {&quot;name&quot;: &quot;3145&quot;, &quot;attribute1&quot;: &quot;this is an attribute&quot;, &quot;attribute2&quot;: &quot;this is another&quot;} ]

l.sort( lambda x, y: cmp( x[&quot;name&quot;], y[&quot;name&quot;] ) )
&lt;/pre&gt;

&lt;p&gt;Ok, so i&apos;ll stop lying.  The list of dictionaries is a list of Networker NSR Client entries.  Each Networker entries is a dictionary relating to the &lt;em&gt;attribute: value;&lt;/em&gt; of a Networker client.  I need to sort this list so when we have multiple clients for the same server, they appear together when I process them.  Using a lambda function as the function to pass to sort() accomplishes this since the lambda function is only calling the cmp() function on the 2 &lt;em&gt;name&lt;/em&gt; attributes of 2 clients. &lt;/p&gt;

&lt;p&gt;Quick, easy and reliable.  Happy Hacking!&lt;/p&gt;</content>
</entry>

<entry>
<title type="html">nsradmin: or how I stopped clicking and learned to love the cli</title>
<category term="" />
<id>http://jason.koelker.net/blog/2007/02/06/nsradmin__or_how_I_stopped_clicking_and_learned_to_love_the_cli</id>
<updated>2007-02-07T04:34:10Z</updated>
<published>2007-02-07T04:34:10Z</published>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog/nsradmin__or_how_I_stopped_clicking_and_learned_to_love_the_cli" />
<content type="html">
&lt;p&gt;Recently on the &lt;a href=&quot;http://listserv.temple.edu/archives/networker.html&quot;&gt;Networker Mailing List&lt;/a&gt;, a windows admin was venturing into the promised land of cli access to &lt;a href=&quot;http://software.emc.com/products/software_az/networker.htm&quot;&gt;networker&lt;/a&gt; and wanted some points in the right direction.  Since I typed it up, I figure I&apos;ll post it here as well so I can find it next time someone asks.&lt;/p&gt;

&lt;p&gt;In nsradmin you set a query and then act on it.  A query is any set of
key and value pairs (attributes).  To set the query you use the `.` or
`print` command.  The benefit of `print` being that it sets the current
query and then prints out the attributes returned by that query.
Examples are probably easier to understand than theory.&lt;/p&gt;

&lt;p&gt;(As I don&apos;t have a networker installation to access at the moment all
the example output is from memory, the exact output of the various
commands may vary)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To print a client&apos;s config:
&lt;pre&gt;
nsradmin&gt; print type: nsr client; name: client.example.org
&lt;/pre&gt;
&lt;p&gt;
This sets the query to any resources that match the named attributes.
Here we are using the `type` attribute to restrict to `nsr client` and
the `name` attribute to restrict the query to only those matching
`client.example.org`.  Since we used the `print` command, the results of
the query are immediately displayed.  The exact same output can be
achieved by using:
&lt;/p&gt;
&lt;pre&gt;
nsradmin&gt; . type: nsr client; name: client.example.org
Current query set.
nsradmin&gt; print
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;To update a client&apos;s config:
&lt;pre&gt;
nsradmin&gt; . type: nsr client; name: client.example.org
Current query set.
nsradmin&gt; update aliases: &quot;www.example.org&quot;
&lt;/pre&gt;
&lt;p&gt;
First the query is set with the `.` command, and then the resources
modified are updated.  &lt;strong&gt;IMPORTANT: if you set a query that returns more
than one resource you will update all those resources! Be careful with
your queries and be as restrictive as possible.&lt;/strong&gt;  Doing something like:
&lt;/p&gt;
&lt;pre&gt;
nsradmin&gt; . type: nsr client; schedule: default
Current query set.
nsradmin&gt; update aliases: &quot;bad.example.org&quot;
&lt;/pre&gt;
&lt;p&gt;
Will set the alias for every client with the `default` schedule.  Many a
first time nsradmin adventurer have made mistakes like this.
&lt;/p&gt;
&lt;p&gt;
You could just as well use `print` instead of `.`, and I in fact
recommend it as a safeguard to accidentally having to stay up for days
fixing client configs. ;)
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Deleting a group:
&lt;pre&gt;
nsradmin&gt; delete type: nsr group; name: MyGroup
&amp;lt;output of query&amp;gt;
Delete? yes
&lt;/pre&gt;
&lt;p&gt;
You could also split this out using the `.` command to set the query and
then the `delete` command to act upon the query.
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
If you can, I would recommend setting up a linux box (or installing
cygwin) and installing the Networker man pages.  The syntax of nsradmin
is very well documented in the &lt;a href=&quot;http://www.informatik.uni-bremen.de/t/manual/software1/Solstice_BackUp/informix/cluhelp/nsr_res.htm&quot;&gt;nsr_resource&lt;/a&gt; man page.&lt;/p&gt;</content>
</entry>

<entry>
<title type="html">SLES9, NetApp, and multipathd Howto</title>
<category term="" />
<id>http://jason.koelker.net/blog/2007/01/17/SLES9__NetApp__and_multipathd_Howto</id>
<updated>2007-01-18T03:36:40Z</updated>
<published>2007-01-18T03:36:40Z</published>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog/SLES9__NetApp__and_multipathd_Howto" />
<content type="html">
&lt;p&gt;
Setting up multipathd on SLES9 is a hozer.  

&lt;/p&gt;
&lt;p&gt;
&lt;h2&gt;Material List&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;NetApp FAS3020 (2 in cluster)&lt;/li&gt;
    &lt;li&gt;QLA2422 HBA (2 per server)&lt;/li&gt;
    &lt;li&gt;Switching Fabric of some sort (2)&lt;/li&gt;
    &lt;li&gt;Target to bang head against (1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;h2&gt;Software List&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;SLES9 SP3&lt;/li&gt;
    &lt;li&gt;multipath-tools-0.4.5-020 (from novell&apos;s update site stock will work too)&lt;/li&gt;
    &lt;li&gt;NetApp Linux Host Utils 3.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;h2&gt;multipath.conf&lt;/h2&gt;
Take a look at the examples in /usr/share/doc/packages/multipath-tools.  Although multipath will work without a configuration file, you will be limited to accessing the luns by their &lt;a href=&quot;http://en.wikipedia.org/wiki/WWID&quot;&gt;WWID&lt;/a&gt;.  My &lt;strike&gt;expert&lt;/strike&gt; recommendation is that at least the &lt;strong&gt;multipaths&lt;/strong&gt;, &lt;strong&gt;devices&lt;/strong&gt;, and &lt;strong&gt;devnode_blacklist&lt;/strong&gt; be included.

&lt;p&gt;
&lt;h3&gt;devnode_blacklist&lt;/h3&gt;
This section lists devices to be excluded from multipath (with regex matching).  If the server boots from local &lt;a href=&quot;http://en.wikipedia.org/wiki/SCSI&quot;&gt;SCSI&lt;/a&gt; disks, including those disks would be wise. Something along the lines of:
&lt;pre&gt;
devnode_blacklist {
  devnode &quot;^sda$&quot;
  devnode &quot;^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*&quot;
  devnode &quot;^hd[a-z]&quot;
  devnode &quot;^cciss!c[0-9]d[0-9]*&quot;
}
&lt;/pre&gt;
&lt;strong&gt;NOTE&lt;/strong&gt;: It is important that any devnode starting with &lt;em&gt;sd&lt;/em&gt; will need to be terminated with a &lt;em&gt;$&lt;/em&gt;.  &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUNS&lt;/a&gt; can (and probaby will) be named &lt;em&gt;sda[a-z][a-z]&lt;/em&gt;. 
&lt;/p&gt;

&lt;p&gt;
&lt;h3&gt;multipaths&lt;/h3&gt;
This is were you map your &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUNS&lt;/a&gt; to a friendly name that you can work with, such as:
&lt;pre&gt;
multipaths {
  multipath {
    wwid 360a9800043336a414c3a3954725a7869
    alias  my-lun0
  }
  multipath {
    wwid 360a9800043336a414c4a395871437a71
    alias  my-lun1
  }
}
&lt;/pre&gt;
Whoa, your saying to yourself, how do you figure out your WWID?  If you run &lt;code&gt;multipath -d -v2 -l&lt;/code&gt; you will get something like:
&lt;pre&gt;
360a9800043336a414c3a3954725a7869
[size=100 GB][features=&quot;1 queue_if_no_path&quot;][hwhandler=&quot;0&quot;]
\_ round-robin 0 [active]
 \_ 2:0:1:1  sdas 66:192 [active][ready]
 \_ 1:0:1:1  sdq  65:0   [active][ready]
\_ round-robin 0 [enabled]
 \_ 2:0:0:1  sdal 66:80  [active][ready]
 \_ 1:0:0:1  sdj  8:144  [active][ready]

360a9800043336a414c4a395871437a71
[size=100 GB][features=&quot;1 queue_if_no_path&quot;][hwhandler=&quot;0&quot;]
\_ round-robin 0 [active]
 \_ 2:0:1:0  sdar 66:176 [active][ready]
 \_ 1:0:1:0  sdp  8:240  [active][ready]
\_ round-robin 0 [enabled]
 \_ 2:0:0:0  sdad 65:208 [active][ready]
 \_ 1:0:0:0  sdb  8:16   [active][ready]
&lt;/pre&gt;
The import part here is to look at the common LUN ID each path has.  For the &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUN&lt;/a&gt; with &lt;a href=&quot;http://en.wikipedia.org/wiki/WWID&quot;&gt;WWID&lt;/a&gt; 360a9800043336a414c4a395871437a71 you can see that it is LUN ID 0 in the group since all SCSI paths end in 0.
&lt;/p&gt;

&lt;p&gt;
&lt;h3&gt;devices&lt;/h3&gt;
With the devices section you define devices and options for them.  Since we have a clustered NetApp, this is the section that will tell multipath which path to prefer since you can access a &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUN&lt;/a&gt; via either filer head end (although they will bitch about it every now and again if you have autosupport turned on and are accessing a &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUN&lt;/a&gt; via the &quot;wrong&quot; head end).  Your section should look something like:
&lt;pre&gt;
devices {
  device {
    vendor  &quot;NETAPP&quot;
    product  &quot;LUN&quot;
    path_grouping_policy  group_by_prio
    getuid_callout  &quot;/sbin/scsi_id -g -u -s /block/%n&quot;
    prio_callout  &quot;/opt/netapp/santools/mpath_prio_ontap /dev/%n&quot;
    features  &quot;1 queue_if_no_path&quot;
    path_checker  readsector0
    failback  immediate
  }  
}
&lt;/pre&gt;
Most importantly are the &lt;strong&gt;path_grouping_policy&lt;/strong&gt; and &lt;strong&gt;prio_callout&lt;/strong&gt;.  By setting  &lt;strong&gt;path_grouping_policy&lt;/strong&gt; to &lt;em&gt;group_by_prio&lt;/em&gt; paths to the &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUN&lt;/a&gt; will be grouped via their priority as determined by which head end you are accessing the &lt;a href=&quot;http://en.wikipedia.org/wiki/LUN&quot;&gt;LUN&lt;/a&gt; through.  The &lt;strong&gt;prio_callout&lt;/strong&gt; entry tells multipath how to ask netapp what priority each path has.
&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;h2&gt;Starting Multipathd&lt;/h2&gt;
You can now start everything up with:
&lt;pre&gt;
# /etc/init.d/boot.multipath start
# /etc/init.d/multipathd start
&lt;/pre&gt;
And add them to start on boot:
&lt;pre&gt;
# insserv boot.multipath multipathd
&lt;/pre&gt;
The multipath devices can now be used in &lt;code&gt;/dev/disk/by-name&lt;/code&gt;.  To check everything out you can run &lt;code&gt;multipath -d -v2 -ll&lt;/code&gt; and see the priority and grouping of the paths:
&lt;pre&gt;
my-lun0 (360a9800043336a414c3a3954725a7869)
[size=100 GB][features=&quot;1 queue_if_no_path&quot;][hwhandler=&quot;0&quot;]
\_ round-robin 0 [prio=8][active]
 \_ 2:0:1:1  sdas 66:192 [active][ready]
 \_ 1:0:1:1  sdq  65:0   [active][ready]
\_ round-robin 0 [prio=2][enabled]
 \_ 2:0:0:1  sdal 66:80  [active][ready]
 \_ 1:0:0:1  sdj  8:144  [active][ready]

my-lun1 (360a9800043336a414c4a395871437a71)
[size=100 GB][features=&quot;1 queue_if_no_path&quot;][hwhandler=&quot;0&quot;]
\_ round-robin 0 [prio=8][active]
 \_ 2:0:1:0  sdar 66:176 [active][ready]
 \_ 1:0:1:0  sdp  8:240  [active][ready]
\_ round-robin 0 [prio=2][enabled]
 \_ 2:0:0:0  sdad 65:208 [active][ready]
 \_ 1:0:0:0  sdb  8:16   [active][ready]
&lt;/pre&gt;
You can see that now you not only get the &lt;a href=&quot;http://en.wikipedia.org/wiki/WWID&quot;&gt;WWID&lt;/a&gt; but now also the alias.
&lt;/p&gt;

&lt;p&gt;
&lt;h2&gt;Rebooting&lt;/h2&gt;
You may find that after rebooting your devices do not appear in &lt;code&gt;/dev/disk/by-name&lt;/code&gt;.  Run! The sky is falling! The streets will flow with the blood of the non-believers!  Just kidding.  What is happening is &lt;code&gt;/etc/init.d/boot.multipath&lt;/code&gt; is being run too early.  I&apos;m still looking for the &quot;correct&quot; solution, but I have found that by editing &lt;code&gt;/etc/init.d/multipathd&lt;/code&gt; to call it prior to the start of &lt;em&gt;multipathd&lt;/em&gt; works.  Here is my diff to the file:
&lt;pre&gt;
--- multipathd.old      2007-01-17 21:35:41.091274231 -0600
+++ multipathd  2007-01-17 21:35:05.591133859 -0600
@@ -55,6 +55,7 @@
 case &quot;$1&quot; in
     start)
        echo -n &quot;Starting multipathd&quot;
+       /etc/init.d/boot.multipath start
 
        modprobe dm-multipath
&lt;/pre&gt;
&lt;/p&gt;</content>
</entry>

<entry>
<title type="html">Colbert Prefers FORTRAN 77 to Objective C</title>
<category term="" />
<id>http://jason.koelker.net/blog/2007/01/13/Colbert_Prefers_FORTRAN_77_to_Objective_C</id>
<updated>2007-01-14T02:24:09Z</updated>
<published>2007-01-14T02:24:09Z</published>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog/Colbert_Prefers_FORTRAN_77_to_Objective_C" />
<content type="html">
&lt;p&gt;
&lt;a href=&quot;http://www.youtube.com/watch?v=gGXwtkXOjZw&quot;&gt;This&lt;/a&gt; is just awsomely funny.
&lt;/p&gt;</content>
</entry>

<entry>
<title type="html">Patching rm to avoid rm -fr /</title>
<category term="" />
<id>http://jason.koelker.net/blog/2007/01/13/Patching_rm_to_avoid_rm__fr__</id>
<updated>2007-01-13T07:22:37Z</updated>
<published>2007-01-13T07:22:37Z</published>
<link rel="alternate" type="text/html" href="http://jason.koelker.net/blog/Patching_rm_to_avoid_rm__fr__" />
<content type="html">
&lt;p&gt;Have you ever accidentally deleted all of /?  Of course you haven&apos;t you read the man page and know what the -f flag does.  You don&apos;t just blindly include it whenever you need to delete something.&lt;/p&gt;

&lt;p&gt;I ran across &lt;a href=&quot;http://ubuntuforums.org/showthread.php?p=2006215&quot;&gt;this&lt;/a&gt; post on the &lt;a href=&quot;http://ubuntuforums.org&quot;&gt;Ubuntu Forums&lt;/a&gt; and my heart just sank.  No longer are the days when Unix/Linux users actually understand what they are doing.  Nowadays users tend to just blinding paste anything they find from &lt;a href=&quot;http://www.google.com&quot;&gt;Google&lt;/a&gt; into a terminal.&lt;/p&gt;

&lt;p&gt;This &lt;a href=&quot;http://www.ubuntu.com&quot;&gt;Ubuntu&lt;/a&gt; user had an excellent idea.  Let us write a patch to rm to prevent it from deleting all of / without asking when you pass it the -rf flags.  This was one of those &lt;a href=&quot;http://en.wikipedia.org/wiki/Lewis_Black&quot;&gt;Lewis Black&lt;/a&gt; moments for me. I had to reply.&lt;/p&gt;

&lt;p&gt;But I can&apos;t just reply like all the other ramrods suggesting to alias `rm -i` to `rm` in bash.  I actually wrote the patch.&lt;/p&gt;

&lt;p&gt;Ladies and Gentlemen, I present to you the --idiot (-I) flag to rm:
&lt;pre&gt;
diff -Naur coreutils-5.97.orig/src/remove.h coreutils-5.97/src/remove.h
--- coreutils-5.97.orig/src/remove.h    2005-05-14 02:58:37.000000000 -0500
+++ coreutils-5.97/src/remove.h 2007-01-13 00:15:13.268298115 -0600
@@ -33,6 +33,9 @@
   /* If true, recursively remove directories.  */
   bool recursive;
 
+  /* If true, the user is an idiot. */
+  bool idiot;
+
   /* Pointer to the device and inode numbers of `/&apos;, when --recursive.
      Otherwise NULL.  */
   struct dev_ino *root_dev_ino;
diff -Naur coreutils-5.97.orig/src/rm.c coreutils-5.97/src/rm.c
--- coreutils-5.97.orig/src/rm.c        2005-08-29 16:13:32.000000000 -0500
+++ coreutils-5.97/src/rm.c     2007-01-13 00:17:38.396568504 -0600
@@ -80,6 +80,7 @@
   {&quot;directory&quot;, no_argument, NULL, &apos;d&apos;},
   {&quot;force&quot;, no_argument, NULL, &apos;f&apos;},
   {&quot;interactive&quot;, no_argument, NULL, &apos;i&apos;},
+  {&quot;idiot&quot;, no_argument, NULL, &apos;I&apos;},
 
   {&quot;no-preserve-root&quot;, no_argument, NULL, NO_PRESERVE_ROOT},
   {&quot;preserve-root&quot;, no_argument, NULL, PRESERVE_ROOT},
@@ -142,6 +143,7 @@
                            supports `unlink&apos; for nonempty directories)\n\
   -f, --force           ignore nonexistent files, never prompt\n\
   -i, --interactive     prompt before any removal\n\
+  -I, --idiot           let the ramrod who can&apos;t read the man page use -rf\n\ 
 &quot;), stdout);
       fputs (_(&quot;\
       --no-preserve-root do not treat `/&apos; specially (the default)\n\
@@ -183,6 +185,7 @@
   x-&gt;ignore_missing_files = false;
   x-&gt;interactive = false;
   x-&gt;recursive = false;
+  x-&gt;idiot = true;
   x-&gt;root_dev_ino = NULL;
   x-&gt;stdin_tty = isatty (STDIN_FILENO);
   x-&gt;verbose = false;
@@ -209,7 +212,7 @@
 
   rm_option_init (&amp;amp;x);
 
-  while ((c = getopt_long (argc, argv, &quot;dfirvR&quot;, long_opts, NULL)) != -1)
+  while ((c = getopt_long (argc, argv, &quot;dfiIrvR&quot;, long_opts, NULL)) != -1)
     {
       switch (c)
        {
@@ -227,6 +230,10 @@
          x.ignore_missing_files = false;
          break;
 
+    case &apos;I&apos;:
+      x.idiot = false;
+      break;
+
        case &apos;r&apos;:
        case &apos;R&apos;:
          x.recursive = true;
@@ -275,6 +282,11 @@
        error (EXIT_FAILURE, errno, _(&quot;failed to get attributes of %s&quot;),
               quote (&quot;/&quot;));
     }
+  
+  if (x.recursive &amp;amp; x.ignore_missing_files &amp;amp; !x.interactive &amp;amp; x.idiot)
+  {
+      error (EXIT_FAILURE, 0, &quot;You are an idiot. Rerun with the --idiot flag.&quot;);
+  }
 
   {
     size_t n_files = argc - optind;
&lt;/pre&gt;
I&apos;ve also uploaded the the file &lt;a href=&quot;http://jason.koelker.net/files/idiot.patch.txt&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;
</content>
</entry>
</feed>
