Who’s On Phirst

Official blog of Phurnace Software.

Archive >> July 2009

Posted by: Wesley Willard on

At this year's No Fluff Just Stuff conference, presenter Matthew McCullough, the managing partner of Ambient Ideas, LLC, gave an interesting talk on Open Source Debugging Tools, which touched on usage of freely-available tools such as cURL. cURL is a command-line tool which supports file transfer operations for a variety of protocols (HTTP, HTTPS, FTP, SFTP, SCP, etc.) and can be used for a variety of useful tasks, such as retrieving the real source page of a web site:
curl -i -H Accept:text/xml http://www.phurnace.com

You can also determine your public IP (useful for those running behind a firewall/router) with the command:
curl -q http://checkip.dyndns.org

This command will return an HTML page with your public IP address embedded.

Okay, here's an example of how you can use cURL to take advantage of Google's mail feed to obtain information about your unread e-mail, without ever using the web browser. In this example, I will show how to take the output from the mail feed, parse it with a Groovy script, and then send a text message to your cell phone number.

First the script:


#!/bin/sh
rm -f /tmp/unread.txt

export PHONE_NUMBER=5555555555
export JAVA_HOME=/usr/lib/jvm/java-6-sun

curl -K .pwd https://mail.google.com/mail/feed/atom/unread > /tmp/unread.xml 

groovy -classpath /home/admin/jars/postgresql-8.4-701.jdbc4.jar \
    /home/admin/bin/Feed.groovy /tmp/unread.xml if [ -e /tmp/unread.txt ]; then echo "Sending notification of unread mail " `date` cat /tmp/unread.txt | mail -s "Unread" $PHONE_NUMBER@txt.att.net fi
This shell script uses a script written in Groovy to parse the curl output. There is nothing particularly fancy about it. It does depend on the -K option to curl to pass in the username and password credentials. This is a more secure method than passing them directly on the command line, or worse, including them in the script itself. If the output file from the Groovy script exists after its execution, the contents are emailed to the cell phone number's text message address. Ideally, this script will run as a cron job, checking the mail feed at a specified interval.

Before you run the script, set up a database called 'mail', with one table 'processed_mail'. The table schema is:

 Column  |          Type          | Modifiers 
---------+------------------------+-----------
 issued  | character varying(100) | not null
 author  | character varying(100) | 
 summary | character varying(255) | 
Indexes:

    "processed_mail_pkey" PRIMARY KEY, btree (issued)

The Groovy script is documented, but in a nutshell, here's what it does:
  • Connect to the database. I am using PostgreSQL in this case, but any database will do.
  • Set up a namespace for accessing the XML elements
  • Create an output file
  • Process each entry the XML file that is passed in as the first argument
  • For each entry, check to see if it has been processed, i.e. it is in the database
  • If it has not been processed, add an entry to the database, and output to the file
  • After processing the unread entries, delete any entries in the database which were not in the unread list
  • Delete the output file if it is empty

import groovy.util.*
import groovy.sql.*;

//
// Setup a database connection
// using Postgres
//
def DB='jdbc:postgresql://localhost/mail'
def USER='postgres'
def PASSWORD='mypassword'
def DRIVER='org.postgresql.Driver'

Class.forName(DRIVER)
def sql = Sql.newInstance(DB,USER,PASSWORD)
assert sql

//
// The XML that comes back needs a namespace
//
def ns = new groovy.xml.Namespace("http://purl.org/atom/ns#")

//
// Process each unread email
// If the unread email has not been processed then
// add an entry to the database
//
def processEntry = { it, outputFile ->
    //
    // Look for an aleady processed entry
    // If found then get out
    //
    def found = false
    def issued = it[ns.issued].text()
    sql.eachRow("select * from processed_mail where issued=${issued}") {
        found = true 
    }
    if (found) {
       return
    }

    //
    // Add the entry and output for the email text
    // 
    println "Issued on " + issued
    def author = it[ns.author][ns.name].text()
    def summary = it[ns.summary].text()
    println "Date: " + issued
    println "From: " + author 
    println summary 
    sql.execute(
    "insert into processed_mail (issued, author, summary) values(${issued}, ${author}, ${summary})")
    outputFile.append("From:  " + author + "\n")
    outputFile.append("Date:  " + issued + "\n")
    outputFile.append("Summary: " + summary  + "\n")
}

//
// Search in the list of entries for the 
// issued date passed in
//
def searchUnread = { dbIssued, entries ->
    def itFound = false
    entries.each {
        def xmlIssued = it[ns.issued].text()
        if (dbIssued.equals(xmlIssued)) {
            itFound = true
            return
        }
    }
    itFound;
}

//
// Process each row in the processed table
// If there is no entry in the list of unread email
// then delete the database row to prevent further processing
//
def cleanupDatabase = { dbIt, entries ->
    def dbIssued = dbIt.issued
    def entryFound = searchUnread(dbIssued, entries)
    if (! entryFound) {
        println "Deleting entry for " + dbIssued
        sql.execute("delete from processed_mail where issued=${dbIssued}")
    }
}

//
// Main body of code
//
def newFile = new File(args[0])
if (newFile.length() == 0) {
   println "Empty new file"
   System.exit(0)
}

//
// Create the output file
//
def output=new File("/tmp/unread.txt")

//
// Parse the input file
//
def parser = new XmlParser()
def feed = parser.parse(newFile)

//
// Gather the entries 
//
def xmlEntries = feed[ns.entry]

//
// Process each entry and output if 
// it has not already been processed
//
xmlEntries.each { processEntry(it, output) }

//
// Clean up the database
//
sql.eachRow("select * from processed_mail") { cleanupDatabase(it, xmlEntries) } 

//
// If the output file is empty then delete
//
if (output.length() == 0) {
   output.delete()
   println "Deleted empty file"
}

This mail feed utility illustrates the usefulness of the combination of a common system utility and a modern script language. This script could be modified to include finer-grained decisions about the destinations of the mail notifications.

Both cURL and Groovy are available on Windows, Linux, and other platforms, so this example can be tried out in almost any environment.

In Untagged 
Comment (0) Read More...


Posted by: Larry Warnock on

Every recent issue of every IT publication has discussed ways to reduce spending.  Especially in this tough economy, but quite frankly, this should be a constant priority for IT management.  We are hosting a webinar on this very topic.  Forrester analyst, Evelyn Hubbert, will be our guest speaker.  Please join us.  She has experience from across a wide range of industries and talks each week with some of the most innovative IT leaders around.  Evelyn will share her latest findings on how People, Process and Technology can make a difference.   

She will point out some of the new skills that are needed in IT as well as the need for automation across all functions of the data center as a key cost savings area.  We see large companies using automation tools to quickly improve operational efficiency while reducing costs.  It is worth taking a look.  Please join our webinar on July 30th or view the on-demand replay afterwards for some thoughtful insights from Forrester Research and Phurnace.  It will only cost you 40 minutes of time, but could save you hundreds of thousands of dollars in IT.  

In phurnaceData Center Automation
Comment (0) Read More...


Posted by: Daniel Nelson on

At the beginning of March this year, I got to spend a couple of days at the BMC Lexington campus prototyping our BladeLogic integration with some of their product, architecture, and development folks. Other than the four feet of snow, it was a great experience meeting the guys there as well as seeing what Phurnace can do with a product like BladeLogic. Together we can do lots of neat things that today just aren’t possible with either product alone. Recently one of our customers brought up an interesting use case that reminded me of one of the BladeLogic features.

In BladeLogic, you can setup heuristic rules to evaluate a task, decision, etc, and then take the appropriate action based on the rule. It’s a pretty rich interface, with full support for all first-order logic. This is pretty cool in its own right. But as they were showing the product to us, I kept thinking that if we combine this with the Phurnace data model for configurations, we can do some very amazing stuff.

For example, one of the things that scares the pants off IT operations guys is there being inadvertent changes to security or tuning settings. Both of those result in big fires and lots of unwanted attention. The problem is that sometimes they get packages to deploy that aren’t as sensitive to those requirements as they should be. Or, even worse, they get an app that HAS TO BE configured in a way that violates their policy in order to work – a hard-coded port, for example. See, the problem is the system administrators know what their environment needs for things like performance and security, and the devs know what the application needs for configuration and deployment, but the melding of those two bases of knowledge is always nasty, and often explosive.

So, watching the BMC guys take us through BladeLogic, I was thinking that this would be a great way to solve that problem. Have the SAs program in their tuning and security requirements actually in the heuristic engine, and then when Phurnace provides the data model for the configuration of the application, run a check to see if it violates any of those policies. The heuristics don’t have to be explicit – they can be a range of options, or settings, or what have you. They can be as complex or as simple as desired. But the important point here is that this check is now done programmatically, in an automated fashion, with no heartache or lost time. Good things happen when you combine good data with good process.

In BladeLogic
Comment (0) Read More...


Posted by: Pete Pickerill on

In our quest to better support AIX 5L V5.3 as both a server and client platform for Phurnace Deliver, we recently got a new piece of hardware, an IBM Power 520 Express. I am the one that usually sets up any new hardware, so the job of installing and configuring AIX fell to me. I soon found that AIX is a completely different animal than Linux. The majority of my previous *nix experience has been with Red Hat. Those of you with more Unix or AIX experience than I are probably laughing at my predicament. The more charitable among you (or those of you that also started in bash on Linux) may feel a pang of pity as you remember your first days trying to navigate the Korn shell. Where’s my auto-complete? Why isn’t the up key working? I can’t use the arrows to get to my typo? No wget? No vim? No samba? No sudo? My god…I can’t even SSH or SCP! Thankfully the good folks at IBM have provided a couple of downloadable content packs to ease the transition from Red Hat to AIX: The AIX Toolbox for Linux Applications and The IBM AIX Expansion Pack.

The IBM AIX Expansion Pack features a bunch of optional packages, most of which I didn’t need. I was able to find the following packages that have been very useful: OpenSSH & OpenSSL for AIX; several versions of the Java SDK for AIX (32-bit & 64-bit); Firefox 2.0 for AIX.

But The AIX Toolbox for Linux Applications made me feel like I had clicked together my little ruby Converse clad heels and said “There’s no Desktop like Gnome. There’s no Desktop like Gnome.” It was chock full of useful Linux applications, libraries, and utilities that made my transition to AIX much smoother. You can get a full alphabetical list here. This is where you’ll find things like wget, diffutils, alternative shells (hooray bash!), Gnome, vnc and a ton of other really useful stuff. So if you’re used to Linux and find yourself working in AIX, check out both offerings. It will save you a boat load of time.

In AIX
Comment (0) Read More...