Monday, June 29, 2009

Eucalyptus - AWS Workalike

I keep rediscovering Eucalyptus, an project aiming to be a clone of Amazon Web Services. I need to give them a real test run...

Sunday, June 28, 2009

Custom Exception, Converting enum to String

There has to be a better way to do this...

I've got a custom exception with its own types, etc. It started out like this:
public class MyException : Exception
{
public MyException() : base()
{
}

public MyException( String message ) : base( message )
{
}
}

Nothing fancy there, right? At least I can now filter my catches appropriately.

Well, what if I want to use an enum to define the kinds of failures? Like so:

public enum ExceptionType
{
ScrewedUpA,
ScrewedUpB
}

So far, so good.

Until I want to call it thus:

MyException ex = new MyException( MyException.ExceptionType.ScrewedUpA );
throw ex;

Okay, so we add a constructor which takes a MyException.ExceptionType:
public MyException( ExceptionType exType ) 
{}

That's all very nice, but then what? We need some kind of message, right?

Getting the string from the enum isn't that hard. The enum is represented as an int, the type has fields we can query. The field we're interested in will be offset from the enum's int by one (the first field designates the type of the enum).

We'd need to call the constructor with the String signature, which means using the this object. However, the only place this works is in the function signature. Given all of that, this is what I ended up with:
public class MyException : Exception
{
public MyException() : base()
{
}

public MyException( String message ) : base( message )
{
}

public MyException( ExceptionType exType ) :
this (exType.GetType().GetFields()[(int)exType + 1].Name)
{}

public enum ExceptionType
{
ScrewedUpA,
ScrewedUpB
}
}

If there's a better way to do this, I'd like to know. Thanks.

Friday, June 26, 2009

OpenNMS and Windows Monitoring

Now that OpenNMS has discovered my network, how can I get even more out of it?

My first thought was to extend OpenNMS to accommodate what I'm looking for. That's a lot like work, so I've installed and enabled SNMP on one of my Windows 2003 servers.

A little searching turned up this set of instructions for configuring SNMP (because MS' instructions are atrocious. A "configuring snmp" section should do more than tell you what configuring it would get you, if they were planning on being so gracious as to tell you how to do it).

It's under the properties for the service. That's a great place for it - no sarcasm intended. Of course, there's only a couple of other services that do that, so I don't look there.

Anyway...

I configured the community name, and set the destination to the FQDN of the OpenNMS server. Restarted the service, and ta-da! OpenNMS started receiving messages. And complaining about them.

Checked the Security tab, and added the OpenNMS server to the list of "Accept SNMP packets from these hosts" list.

There's a section in the OpenNMS admin section for configuring what IP addresses will be sending traps, and what community name they send. I left it at v1.

It started working after that.

I'm not entirely thrilled with this as a solution. It is known to be pretty insecure. Let's see what kind of data comes through...and I'm just not getting the point. There doesn't seem to be anything new. Maybe SNMP is just too smart for me. Ah well.

Update: I did a little configuration with evntwin.exe, and started forwarding various W3SVC events to OpenNMS. That was all around kludgey, and not really worth the effort.

I still like OpenNMS as a lightweight inventory and monitoring system, though.

Backing up VMWare ESX 3.5

I'd been whining about the troubles I had getting the various parts of a VMWare backup script working. Well, I've got something that appears to fill the bill.

The end result is that I have a backup local to the host, so I can restore very quickly, and as many past snapshots as my Windows server can hold.

The first thing you need to do is open up the firewall:
esxcfg-firewall --enableService smbClient

Note that in order for everything to work, I have to use the FQDN to the server. Otherwise, I'd get an error regarding broadcasts.

Here's the main script:
#!/bin/sh

VMCONFIGLIST=`/usr/bin/vmware-cmd -l`
TODAY=`date +%Y%m%d`
BACKUPBASE=/vmfs/volumes/`hostname`\:raid0/backups

USER=root
PASSWORD=nunyabidnz

WINUSER=NA/meh
WINPW=blah
WINDEST='//server01.example.com/backups'

if [ ! -d ${BACKUPBASE} ]
then
echo "Backup directory ${BACKUPBASE} does not exist."
echo "Exiting"
# no, I don't want to create it. If there's a problem with the path,
# there's no telling where these backups will end up.
exit
fi

echo "Back up for ${TODAY}"
echo "Backup directory ${BACKUPBASE}"

for VM in ${VMCONFIGLIST}
do
# set up the variables for this loop
VMDIR=`dirname ${VM}`
echo "Looking for ${VMNAME} in ${VMDIR}"

# if the config file doesn't exist, we can't do anything
if [ ! -f ${VM} ]
then
echo " * Did not find ${VM}."
echo " * Skipping"
continue
fi

# get the VM name from the config file
VMNAME=`cat ${VM} | awk '/displayName =/ {print $3}' | sed 's/\"//g'`

DESTDIR=${BACKUPBASE}/${VMNAME}

TARNAME=${VMNAME}.${TODAY}.tgz

# the work begins here
# all the configurable stuff should be above this line

echo " - Backing up ${VMNAME}"
echo " - file ${VM}"

# vcbMounter bombs out if the directory already exists
if [ -d ${DESTDIR} ]
then
echo " - deleting directory ${DESTDIR}"
rm -Rf ${DESTDIR}
fi

# create the backup
echo " - Starting vcb..."
/usr/sbin/vcbMounter -h `hostname` -t fullvm -u ${USER} -p ${PASSWORD} -r ${DESTDIR} -a Name:${VMNAME}

# check vcbMounter's return
if [ "$?" -ne "0" ]
then
echo " - Error backing up VM ${VMNAME}"
continue
else
echo " - Successful backup of ${VMNAME}"
fi

# compress it

echo " - Archiving backup to tarfile ${BACKUPBASE}/${TARNAME}"
echo " - to tarfile $TARNAME"
# --force-local to ignore the ":" in the path
tar -C ${BACKUPBASE} --force-local -czf ${BACKUPBASE}/${TARNAME} ${DESTDIR}
echo " - Compression completed"

echo " - Copying to ${WINDEST}"
/usr/bin/smbclient -c "prompt off; put ${BACKUPBASE}/${TARNAME} ${TARNAME}" -U ${WINUSER} ${WINDEST} ${WINPW}

echo "Cleaning up .tgz"
rm -f ${BACKUPBASE}/${TARNAME}

echo " --- ${VMNAME} complete --- "
done

Any suggestions for improvements (how about an occasional function , Mr. Goon? Or check the return from smbclient? Hmmm?) are welcome.

MSDeploy, First Looksies

Microsoft has a tool which promises to simplify IIS deployments, known as MSDeploy.

I had a little trouble finding documentation, but I finally found a link pointing here.

Update: Dinked around with it a little, and it is looking pretty darn cool. Heavily slanted towards IIS7, it looks like it works reasonably well with IIS6.

Thursday, June 25, 2009

NirCmd?

Was reading about something else, and NirCmd came up. It is a command line utility, with a bunch of functionality. Very lightweight, no install necessary.

I haven't looked at it, yet. Just bookmarking...

Update:Meh. I like that it is really small, and I have a copy of it on my thumbdrive, but it ain't all that.

Tuesday, June 23, 2009

MSProject Server Doesn't Exist?

Well, I installed MSProject Server onto a node of the web farm, and ran into a snag. When I tried to administer it via shared services, I got this error:
The Project Application Service doesn't exist or is stopped. Start the Project Application Service.

Checked the service, it was running according to the MOSS UI. Services MMC showed the other services as running. Nothing interesting in the event log.

Searched around, and found others with this problem. The most common suggested fix was
stsadm -o provisionservice -action start -servicetype "Microsoft.Office.Project.Server.Administration.ProjectApplicationService, Microsoft.Office.Project.Server.Administration, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C" -servicename ProjectApplicationService

Well, that didn't do it.

The solution? I could about kick myself. MSProject server needs to be installed on all nodes of the farm. It even says it in the instructions. Dumbass me...

Monday, June 22, 2009

vmware-cmd Not Working

I'm still working on those VM backups. I got everything started okay on the first node. It wasn't until the second node that I ran into other problems. Of course.

Attempting to run vmware-cmd resulted in the following:

Can't locate VMware/VmPerl.pm in @INC (@INC contains: blib/arch -Iblib/lib -I/usr/lib/perl5/5.6.0/i386-linux -I/usr/lib/perl5/5.6.0 -I. /usr/lib/perl5/5.8.0/i386-linux-thread-multi /usr/lib/perl5/5.8.0 /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.0 /usr/lib/perl5/vendor_perl/5.8.0 /usr/lib/perl5/vendor_perl /usr/lib/perl5/5.8.0/i386-linux-thread-multi /usr/lib/perl5/5.8.0 . blib/arch blib/lib /usr/lib/perl5/5.6.0/i386-linux /usr/lib/perl5/5.6.0 .) at /usr/bin/vmware-cmd line 133.
/usr/bin/vmware-cmd requires the VMware::VmPerl Perl libraries to be installed.
Check that your installation did not encounter errors.

According to some stuff I found, this can be caused by clock-skew when the server is installed. Of course, I don't care about why it happened (just good to know). How to fix it?
# vmware-config.pl

Please specify a port for remote console connections to use [902]

Stopping xinetd: [ OK ]
Starting xinetd: [ OK ]
Configuring the VMware VmPerl Scripting API.

Building the VMware VmPerl Scripting API.

Using compiler "/usr/bin/gcc". Use environment variable CC to override.

Installing the VMware VmPerl Scripting API.

The installation of the VMware VmPerl Scripting API succeeded.

The configuration of VMware ESX Server 3.5.0 build-123630 for this running
kernel completed successfully.
And that cleared it up.

smbclient Woes on ESX

I'm writing a backup script for our ESX hosts, and I ran into a problem connecting to the Windows server.

After opening the firewall with
esxcfg-firewall -e smbclient

I still got an error attempting to connect to the Windows machine:

[root@ESX backups]# smbclient -U DOM\\adminusers //server01/backups password
Packet send failed to 10.4.136.255(137) ERRNO=Operation not permitted
Connection to server01 failed

Okay, so the firewall is blocking broadcasts (that ".255" at the end). The solution was to negate the need for the broadcast. smbclient was unable to resolve the IP address given just the hostname of "server01", and was attempting a netbios broadcast (I think).

The solution was to use the FQDN to server:

[root@ESX backups]# smbclient -U DOM\\adminuser //server01.example.com/backups password
Domain=[DOM] OS=[Windows Server (R) 2008 Enterprise 6001 Service Pack 1] Server=[Windows Server (R) 2008 Enterprise 6.0]
smb: \>

Friday, June 19, 2009

OpenNMS as a Windows Service

[I've updated this some, to correct errors and be more thorough]

I'm doing some testing with OpenNMS, to see if it is at least good enough. So far, it is.

One of the complications is that it is a java app. This would be fine, except it doesn't ship with a means of running it as a Windows service. All in all, it wasn't too bad. I got it running on Windows 2003 Server - I haven't tried 2008, yet.

All of this assumes that you have OpenNMS itself working.

I started with the instructions here, using "Method One".

The abbreviated version of those instructions is that inside the downloaded .zip file, there's a file structure which looks like the one in your OpenNMS directory.

Unzip that to someplace other than your OpenNMS directory - I know how you people are - so we can make some changes.

Delete the ./src directory. If you're reading this, you aren't using that.

In the ./bin directory, there's a bunch of batch files. I renamed them "WrapperInstall.bat", "WrapperStart.bat", etc., because that's just easier to keep track of.

In ./conf, there's a file named wrapper.conf. Try using this one, but double-check the directory names....

#********************************************************************
# Wrapper License Properties (Ignored by Community Edition)
#********************************************************************
# Include file problems can be debugged by removing the first '#'
# from the following line:
##include.debug
#include ../conf/wrapper-license.conf
#include ../conf/wrapper-license-%WRAPPER_HOST_NAME%.conf

#********************************************************************
# Wrapper Java Properties
#********************************************************************
wrapper.java.command=C:\Program Files\Java\jdk1.6.0_14\bin\java
wrapper.java.additional.1=-Xmx256m
wrapper.java.additional.2=-Dopennms.home="C:/PROGRA~1/OpenNMS"

wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
wrapper.app.parameter.1= org.opennms.bootstrap.Bootstrap
wrapper.app.parameter.2= start

wrapper.java.classpath.1=C:/Program Files/Java/jdk1.6.0_14/lib/tools.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../lib/opennms_bootstrap.jar

wrapper.java.library.path.1=../lib

wrapper.java.additional.auto_bits=TRUE

#********************************************************************
# Wrapper Logging Properties
#********************************************************************

wrapper.console.format=PM
wrapper.console.loglevel=WARN
wrapper.logfile=../logs/wrapper.log
wrapper.logfile.format=LPTM
wrapper.logfile.loglevel=INFO

wrapper.logfile.maxsize=0
wrapper.logfile.maxfiles=0

wrapper.syslog.loglevel=NONE

#********************************************************************
# Wrapper Windows Properties
#********************************************************************

wrapper.console.title=OpenNMS

#********************************************************************
# Wrapper Windows NT/2000/XP Service Properties
#********************************************************************

wrapper.ntservice.name=opennms

wrapper.ntservice.displayname=OpenNMS
wrapper.ntservice.description=Network Management System

wrapper.ntservice.starttype=AUTO_START
wrapper.ntservice.interactive=false

Copy all of the wrapper files into their corresponding OpenNMS directories. If the destination directory doesn't exist (./conf), create it.

Almost there...

Go into the ./bin directory of your OpenNMS installation, and double-click the WrapperInstall.bat file.

Now, you should be able to click on WrapperStart.bat (you did rename it, right?), or go into the Services MMC and start it from there.

Finding Event Log Messages With Powershell

Wooo! Big update!

Actually, I just don't want to lose this...
get-eventlog -ComputerName dalmobdev08 -logname application | where-object {$_.Message -match "corrupt"} | select-object -First 10


Finds event log entries with the word "corrupt" in the message.

Wednesday, June 17, 2009

Crypto Provider Library

I'm going to need some encryption love soon, but I know better than to trust my own code for it.

Here's something I found for C#.

Tuesday, June 16, 2009

MSBuild Powershell Extension

Haven't tested it, or even downloaded it. Just saving it, for now.

Allows embedding Powershell scripts into MSBuild files.

Here's a page that has some other ideas, and disses the embedded approach.

Update: I decided I didn't really like the approach. I'm kind of down using MSBuild for anything other than building, anyway.

Wednesday, June 10, 2009

Listing Add/Remove Programs with Powershell, redux

Man, I barely get the thing posted, and already there's complaints about having to install stuff.

Okay, fine:

$target = "somecomputer"

$arp_key = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
$type = [Microsoft.Win32.RegistryHive]::LocalMachine
$hive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $target)

$regkey = $hive.OpenSubKey($arp_key)

foreach( $subkey_name in $regkey.GetSubKeyNames() )
{
$subkey = $hive.OpenSubKey( $arp_key + "\" + $subkey_name )
$display_name = $subkey.GetValue( "DisplayName" )
$display_version = $subkey.GetValue( "DisplayVersion" )

if( $display_name -ne [string].Empty )
{
write-host @($display_name + " (" + $display_version + ")")
}

# foreach( $val_name in $subkey.GetValueNames() )
# {
# write-host "name: " $val_name -nonewline */
# write-host "value: " $subkey.GetValue( $val_name )
# }
}


No installation required. It is rather naive - if there is no display name, then it is skipped. If you've got a better version, please let me know. This one feels icky, to me.

I left in a chunk, remarked out, to show how to get to the other values.

Listing Add/Remove Programs with Powershell

Shamelessly stole this from here, which apparently stole it from someplace else...

First, run this:
set-content RegProgs.mof @'
#pragma namespace("\\\\.\\root\\cimv2")
instance of __Win32Provider as $Instprov
{
Name ="RegProv" ;
ClsID = "{fe9af5c0-d3b6-11ce-a5b6-00aa00680c3f}" ;
};
instance of __InstanceProviderRegistration
{
Provider =$InstProv;
SupportsPut =TRUE;
SupportsGet =TRUE;
SupportsDelete =FALSE;
SupportsEnumeration = TRUE;
};

[dynamic, provider("RegProv"),
ProviderClsid("{fe9af5c0-d3b6-11ce-a5b6-00aa00680c3f}"),ClassContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")]
class win32reg_arp
{
[key]
string ProdID;
[PropertyContext("DisplayName")]
string DisplayName;
[PropertyContext("Publisher")]
string Publisher;
[PropertyContext("DisplayVersion")]
string Version;
};

'@

It will create a file named "RegProgs.mof". This file is used by mofcomp.exe, which "compiler parses a file containing MOF statements and adds the classes and class instances defined in the file to the WMI repository. The following code example shows how to run the MOF compiler on a file." (Source)

Run:
mofcomp.exe RegProgs.mof

This will compile and add it to the local WMI repository.

Then, from PowerShell, you can
Get-WmiObject win32reg_arp

The .mof needs to be installed on any machine which you wish to scan.

Update: I have a non-.mof version here.

Tuesday, June 2, 2009

Dev, Staging, and Production

There's a pretty good chance you know this, but I want to make sure that the other goons in the world have a plethora of results when they query "why should I have separate environments?"

If you are responsible for any kind of development group, there's some things that they need in order to do their job, while at the same time protecting them from themselves. One of those things is their own environment (development), distinct from the environment which everyone else is using (production). It isn't completely necessary, but incredibly useful, for there to be an intermediate environment (staging).

The production environment is the Ivory Tower, where only the Blessed Code may enter (to be cursed by the users). There may be some diagnostics utilities installed, but they should rarely be invoked. Generally, if you're having to think too hard about production, you've already done something wrong.

The development environment is the Wild West. You want your developers to go a little crazy and experiment. That's how they come up with really cool ideas, and where they find out that most of those ideas are entirely unworkable.

Staging is the Suburbs. It's pretty nice there, the streets are clean, the lawns are mowed. Things are very predictable, but not particularly uptight.

Yes, but why do we need all three?

They are serving three different purposes.

Production is what your users/customers see. They shouldn't be bothered by anything. If there's a change, it should be seamless and make things better. It should be fast and stable. Troubleshooting, testing, developing - all of these things interfere with that experience.

Staging is "production for developers". It, too, should be very predictable. It doesn't actually serve any purpose to the end user so mistakes are acceptable. Not desirable, but acceptable. Developers have the opportunity to troubleshoot and test, mostly to their heart's content. The whole point is to give developers a place to do these things without impacting production, therefore it should always be as close a duplicate to production as possible.

Development is for developers. Broken links, bad data, ugly pages: all of these are just hunky-dory here. It should have a lot of the characteristics of production - the
closer it matches, the easier it will be to deploy to staging. At the same time, it isn't unusual to tear it up.

They each have to be managed differently, but I'll save that for another post.