Quick and Dirty Scripting

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

Wednesday, November 28, 2007

 

Restoring A Database with transaction logs

I've been often asked to restore a database to another server and have all transactions logs applied to it up to a certain point. Using SQL Server 2005, you could setup Transaction Log shipping and it works very well, or you could copy the files over manually then apply them manually using SQL Server Enterprise Studio. Well I'm lazy so I came up with this simple script to do the work for me . . .

This script will ask for the database name to be restored as well as the directory where the transaction logs , drop any existing database of that name, restore the database and its transaction logs. It will not setup your database backups (full or transaction) nor will it replicate them over. I do have scripts for this but a tool like SyncBackSE works just as well. Oh this is a Windows batch script that utilizes osql which comes with SQL Server 2005.

@echo off

set BAKFILE=%1
set DBSNAME=%2
set LOGDIR=%3

IF NOT DEFINED BAKFILE (GOTO HELP)
IF NOT DEFINED DBSNAME (GOTO HELP)
IF NOT DEFINED LOGDIR (GOTO HELP)

echo Using the following variables to restore the database
echo Database Backup file - %BAKFILE%
echo Database Name - %DBSNAME%
echo Trans Log Directory - %LOGDIR%
choice /M "Do you want to continue"

IF ERRORLEVEL 2 ( GOTO END)

set DATADIR=d:\DATA
set SQL=%TMP%\restore.sql
set OUT=.\restore_results.txt

IF EXIST %SQL% ( del %SQL% )

IF NOT EXIST %BAKFILE% (
echo %BAKFILE does not exist. Must exit.
GOTO END
)

echo USE [MASTER] > %SQL%
echo GO >> %SQL%
echo ALTER DATABASE %DBS% SET SINGLE_USER WITH ROLLBACK_IMMEDIATE >> %SQL%
echo GO >> %SQL%
echo DROP DATABASE %DBS% >> %SQL%
echo GO >> %SQL%

echo RESTORE DATABASE [%DBSNAME%] > %SQL%
echo FROM DISK = '%BAKFILE%' >> %SQL%
echo WITH NORECOVERY >> %SQL%
echo GO >> %SQL%

for /f "tokens=* delims= " %%a in ('dir /b /a-d /od %LOGDIR%\*.trn') do (
echo RESTORE LOG [%DBSNAME%] >> %SQL%
echo FROM DISK = '%LOGDIR%\%%a' >> %SQL%
echo WITH NORECOVERY >> %SQL%
echo GO >> %SQL%
set LAST=%%a
)

echo RESTORE LOG [%DBSNAME%] >> %SQL%
echo FROM DISK = '%LOGDIR%\%LAST%' >> %SQL%
echo WITH RECOVERY >> %SQL%
echo GO >> %SQL%

osql -E -w 5000 -i %SQL% -o %OUT%
GOTO END

:HELP
echo.
echo Usage: restore_dbs.bat [BAKFILE] [DBSNAME] [LOG DIR]
echo.
echo.
echo BAKFILE - The full path to a recent backup file of the database
echo DBSNAME - Name of the new database
echo LOG DIR - The full path to a directory that contains all the recent tanslogs
echo *The LOG DIR should not contain any transaction logs older than BAKFILE
echo.
echo Eg: restore.bat d:\Backups\SampleDBS_backup_200705222201.bak SampleDBS d:\Temp
echo.

:END
IF EXIST %SQL% ( del %SQL% )

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: , ,


Wednesday, November 21, 2007

 

First post using Windows Live Writer

This is a posting using Microsoft Live Writer which means this will be a short post.

Just want to say Happy Thanksgiving!!!!

Brian


Wednesday, November 14, 2007

 

Creating a VM from a Template using Powershell

Yesterday, I posted that I was having issues creating a new VM from a template while using VMware's Powershell commands. It must have been the weather or something because today, it seems to be working without any issues. The following is how you can create a new VM from a template using Powershell. I did notice one interesting thing that I want to ask VMware about which I will mention at the end of this entry.

PS C:\Temp> $vc = Get-VIServer "vc.example.com"
There were one or more problems with the server certificate:

* The certificate's CN name does not match the passed value.

PS C:\Temp> $t = Get-Template -Server $vc
PS C:\Temp> $t[0]

Name Id
---- --
ESX3-WIN2K3SP2-ST... VirtualMachine-vm-23637

PS C:\Temp> $esx = Get-VMHost -Name "esx1.example.com"
PS C:\Temp> $esx

Name Id
---- --
esx1.example.com HostSystem-host-7523

PS C:\Temp> New-VM -Host $esx -Template $t[0]

cmdlet New-VM at command pipeline position 1
Supply values for the following parameters:
Name: vm-1

At this point, a Powershell progress bar appears and the progress of the deployment can be tracked.
The shell's focus is not returned until after the deployment is complete. The interesting thing is, that I can CTRL-C and cancel this Powershell command but the template continues to be deployed from within VirtualCenter. I am not sure how VMware will handle this situation but I would expect the deployment to be canceled once I cancel the Powershell command. I would love to hear any one else's thoughts on this matter as well.

Labels:


Tuesday, November 13, 2007

 

Creating a Virtual Machine with Powershell

Sorry for the delay in posting this week. I had out-of-town guests in all weekend so everything has been turned upside down. I would like to continue from last week and show how easy it is to create a new virtual machine with Powershell. Again you'll need the VMware Powershell management Snap-in before you have access to these commands.

To Create a Virtual Machine, you need to do the following:
1. Connect to your Virtual Center server -
2. Connect to the ESX Host where you want to create the VM -
3. Create the virtual machine -
4. If you want, you can specify options while you are creating the VM or you can use the Set-VM to modify the VM's specifications.

I tried to create a new VM from a template with the following steps, but I continually got an error while doing so. I guess this just goes to show that VMware is still developing this code and it has some ways to go.

1. Get all templates that VC knows about
2. Create new virtual machine from the first template
If someone could show me what I am doing wrong, that would be great.

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]