Quick and Dirty Scripting

A blog that focuses on automating system administration tasks for Linux, Windows, and VMware ESX

Sunday, January 6, 2008

 

Powershell and XML Configuration Files

 

One of the things that I almost always create when I am developing a script is a configuration file. Utilizing XML for a configuration file format is very easy with Powershell.  The first thing that you need to do is to layout your XML file. I typically don't create a DTD or verify the XML schema because well, only my scripts will be using the XML configuration file.  Not completely within spec, but I've learn to live with it. The XML does need to be well formed with proper closing brackets, root node, etc in order for Powershell to read the XML but that is the only restriction.

The most common XML file that I create includes a list of servers and some attribute about those servers. A simple  example that of a test application that is made up of three web servers and a database server. The way that I would create the XML would be as follows:

<test_app_servers>
    <dbs server="vm-dbs1" dbsname="eut"/>
    <web dir="d$\inetpub\wwwroot">
        <server>vm-test1</server>
        <server>vm-test2</server>
        <server>vm-test3</server>
    </web></test_app_servers>

Now the important part, how does Powershell read the XML.  The code is very straight forward. You use the get-content command and cast the file as XML.  The command is:

$cfgFile = ".\test_app_config.xml"
$root = "test_app_servers"
$cfg = [xml] ( gc $cfgFile )

Now once you have the configuration saved in the variable $cfg then how do you use it?  Powershell stores the information in a tree format so it is easy to get at. Some samples of how to get at the data include:

$strDbsName = $cfg.$root.dbs.dbsname

$strDbsServer = $cfg.$root.dbs.server

$strWebDir = $cfg.$root.web.dir

$cfg.$root.web.server | % {
        $strWebServer = $_
        "Content of
\\$strWebServer\$strWebDir"
        dir
\\$strWebServer\$strWebDir

}

And that is all you should need to know in order to utilize XML as a configuration file with Powershell

Labels: ,


Thursday, December 27, 2007

 

Update to VMware's Powershell Toolkit

 

Just wanted to throw this out there for anyone using VMware's Powershell toolkit. They released a new CTP on 12/26. The file version is 68764.  They've added a bunch of new commands such as Get-Inventory, New/Get-OSCustomizationSpec, Add-VMHost, Move-Datacenter, Move-Cluster, Find-EntityViews, etc . .

I need to find some time to play with these new commands. I do know that the base Get-VIServer and Get-VMHost do work with ESX 3.5 which is nice to see as well.

Until I have more scripts to share. . .

Labels: ,


Monday, November 26, 2007

 

VMware's Very Cool Get-Stat Command

 

Today I want to briefly show  you the power of the VMware's Get-State command.  With it you can grab statistics on any VI entity - ESX Host, Virtual Machine, or Resource Pool.  To use it, all you need to do is supply the entity you want to monitor and which statistics do you want to grab (common, CPU, memory, disk, or network). So let's get some stats on an ESX host.

 $vc = Get-VIServer "vc1.example.com"

$esx = Get-VIHost "esx1.example.com"

Get-Stat $esx -Memory -maxsamples 3 -realtime

MetricId             Timestamp                                     Value Unit
---------            ----------                                    ----- ----
mem.vmmemctl.average 11/26/2007 1:52:2...                              0 KB
mem.vmmemctl.average 11/26/2007 1:52:0...                              0 KB
mem.vmmemctl.average 11/26/2007 1:51:4...                              0 KB

Value       : 21.49
Timestamp   : 11/26/2007 1:52:20 PM
MetricId    : mem.usage.average
Unit        : %
Description : Memory usage as percentage of total configured or available memory
Entity      : VMware.VimAutomation.Client20.VMHostImpl

Value       : 21.49
Timestamp   : 11/26/2007 1:52:00 PM
MetricId    : mem.usage.average
Unit        : %
Description : Memory usage as percentage of total configured or available memory
Entity      : VMware.VimAutomation.Client20.VMHostImpl

Value       : 21.49
Timestamp   : 11/26/2007 1:51:40 PM
MetricId    : mem.usage.average
Unit        : %
Description : Memory usage as percentage of total configured or available memory
Entity      : VMware.VimAutomation.Client20.VMHostImpl

mem.active.average   11/26/2007 1:52:2...                          78988 KB
mem.active.average   11/26/2007 1:52:0...                          78988 KB
mem.active.average   11/26/2007 1:51:4...                          78988 KB
mem.granted.average  11/26/2007 1:52:2...                        2097504 KB
mem.granted.average  11/26/2007 1:52:0...                        2097504 KB
mem.granted.average  11/26/2007 1:51:4...                        2097504 KB

Get-Stat $esx -common -maxsamples 1 -realtime

MetricId             Timestamp                                     Value Unit
---------            ----------                                    ----- ----
cpu.usage.average    11/26/2007 2:05:4...                           4.86 %

Value       : 297
Timestamp   : 11/26/2007 2:05:40 PM
MetricId    : cpu.usagemhz.average
Unit        : MHz
Description : CPU usage in MHz over the collected interval. For hosts this can be represented on a per Virtual Machine
              basis as a stacked graph
Entity      : VMware.VimAutomation.Client20.VMHostImpl

mem.usage.average    11/26/2007 2:05:4...                          21.48 %

Value       : 105
Timestamp   : 11/26/2007 2:05:40 PM
MetricId    : disk.usage.average
Unit        : KBps
Description : Aggregated storage performance statistics. For hosts this can be represented on a per Virtual Machine bas
              is as a stacked graph
Entity      : VMware.VimAutomation.Client20.VMHostImpl

And finally,

$stats = Get-Stat $esx -common -maxsamples 1 -realtime

$stats. GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

Since the object returned to you is an array,this allows you to store and manipulate the return results - like

$stats[2]

MetricId             Timestamp                                     Value Unit
---------            ----------                                    ----- ----
mem.usage.average    11/26/2007 2:07:0...                          21.48 %

or $stats[2].Value

21.48

These values can then be piped into a table or graph to display the results.

Next week, I want to go back to something basic in Powershell - XML configuration. Powershell makes parsing XML documents very easy and I want to show how you can use this to create XML configuration files.

Labels: , ,


Monday, November 5, 2007

 

PowerShell and VMware Managment

I know that I just blogged yesterday about sending emails with PowerShell, BASH, and VBScript, but I got a chance today to install VMware's PSSnapin for Powershell. From the looks of this beta, its going to be a very powerful product that almost anyone can write scripts for. What an example.

I wrote a script in Perl using VMware's Perl SDK to display any VM Snapshot that a supplied VirtualCenter knows about. The code to do this in Perl is as follows:

use strict;
use warnings;
use Getopt::Long;
use VMware::VIRuntime;
use Term::ReadKey;

my %opts = (server => undef, username => undef,);

GetOptions (\%opts,"server=s", "username=s");

if( !defined ($opts{server} && $opts{username}) ) {
help();
exit (1);
}

ReadMode('noecho');
print "Enter $opts{username}\'s password: ";
my $password = ReadLine(0);
chomp $password;
ReadMode('normal');

# login
my $url = "https://" . $opts{server}. "/sdk/vimService";
Vim::login(service_url => $url, user_name => $opts{username}, password => $password);

# get VirtualMachine views for all powered on VM's
my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine');

# snapshot each VM
my $i;
foreach (@$vm_views) {
if( defined $_->snapshot ) {
print "-------------------------------------------------------------\n";
print $_->name . " has at least one snapshot defined . . . \n";
foreach $i (0 .. $#{$_->snapshot->rootSnapshotList} ) {
print "\t" . $_->snapshot->rootSnapshotList->[$i]->name . " @ " . $_->snapshot->rootSnapshotList->[$i]->createTime . "\n";
}
print "-------------------------------------------------------------\n";
}
}

# logout
Vim::logout();

sub help {
my $help_text = <<'END'; USAGE: query_snapshot.pl --server --user

Example:
query_snapshot.pl --server vc1 --user administrator

END
print $help_text;
}

Now using Powershell and the VMware Snapin:

Add-PSSnapin VMware.VimAutomation.Core
Get-VIServer vc1.example.com
Get-VM | % { $_.Name; Get-Snapshots $_ }

That's it. Everything is provided for you like Authentication, handling XML returned by VirutalCenter's Web Services, etc . . . The Perl SDK is very powerful as well, but you have to do a lot more coding to get things done. With the PowerShell snapin, the script is all of three lines. Now the snapin is only in beta testing right now so things can change in the future.

Labels: ,


Sunday, November 4, 2007

 

Sending email via a Script

One of the most basic tasks that any system administrator needs to accomplish while writing scripts is to send e-mail. Typically this is to send results of script itself or of some event.

The easiest way to send email is if you are using Linux. Almost all Linux servers have the mail command installed by default. This command can be used by a BASH script to send your mail. The problem with the mail program is that it doesn't send attachments. To send attachments, you'll need mutt. Mutt can be installed via apt-get or yum or via tar balls, on all Linux systems. To send an email via Mutt, you simply need to have the following line in your script


mutt -s $subject -c $ccpt_list -a $attachfile $rcpt_list < $email

The variables defined include:
1. A subject ($subject)
2. A receipt list ($rcpt_list). This is defined in BASH as rcpt_list=someone@company.com.
3. The body of the email is stored in the variable/file $email. $email is a file on the server that is piped into the Mutt command. It is defined as email=/tmp/email.tmp echo Hello World >> $email
4. OPTIONAL: An attach file. The variable $attachefile holds the path location of the file to attache
5. OPTIONAL: An CC list of email address.
--

Over in the Microsoft world, there isn't a command line mail program built into any Windows server, but VBScript is. All that you need to send email via VBScript is the following:

Const SMTP_SERVER = "SMTP mail server address"
Const SMTP_PORT = 25

Set objMessage = CreateObject("CDO.Message")
objMessage.Sender = sSender 'Email address of sender
objMessage.To = sRecipients 'Comma separate list of people who will receive the email
objMessage.Subject = sSubject 'The subject of the email
objMessage.Textbody = sBody 'The body of the email.

'This is optional. sAttachment is the fully qualified path to the file to attach
objMessage.AddAttachment sAttachment

objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SMTP_SERVER
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTP_PORT
objMessage.Configuration.Fields.Update

objMessage.send
---

With Powershell just being released from Microsoft, you can write a function to send email and include that function in all scripts that need to send email. The function could look something like this:

function send-email($s,$b,$to) {
$from = "send@company.com"; //Who will be sending the email
$domain = "smtp.company.com"; //SMTP server to send the message

$mail = new-object System.Net.Mail.MailMessage;

for($i=0; $i -lt $to.Length; $i++) {
$mail.To.Add($to[$i]);
}
$mail.From = new-object System.Net.Mail.MailAddress($from);
$mail.Subject = $s;
$mail.Body = $b;

$smtp = new-object System.Net.Mail.SmtpClient($domain);
$smtp.Send($mail);
}

To call this function, you just need to do the following:

$SUBJECT="This is the subject";
$EMAILADDR=@("person1@company.com","person2@company.com");
$BODY="Hello World";
send-email -s $SUBJECT -b $BODY -to $EMAILADDR

Sending email is pretty easy and I know that there are a lot of places on the Web that already so you how to send email. Hopefully, though we can build off this to build much more complex scripts. I received an email from VMware concerning their Powershell interface to ESX. I am planning on next week to show how to write some simple scripts to manage an ESX build out with Powershell and we'll be using the send-email functions.

Well this ends my first real blog post. I hope someone out there finds these scripts/functions useful and I will write more next week.

Labels: , , , ,


Archives

October 2007   November 2007   December 2007   January 2008   February 2008   April 2008   July 2008  

View Brian Denicola's profile on LinkedIn

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]