Tuesday, August 7, 2012

PowerShell, Diskpart and Exchange (Oh my!)

Was given the opportunity to work a bit on an Exchange 2007 - 2010 migration.  I was asked if supplied a csv that contained Server and folders could the following be scripted:
  • Step 1 - Create a mount point to hold the drives (M:)
  • Step 2 - Create a series of folders on the above drive
  • Step 3 - Create a series of volumes to be used to hold the database and log files
After a bit of research, it seemed feasible using a combination of PowerShell and DiskPart.
It took me a few tries to get the hang of the necessary DiskPart commands to string together to pipe, my experience with disks has primarily been with the GUI, so I able to add a bit more to my command line toolbelt.

So once the DiskPart commands were figured out, all that needed to be done is run these on the (new)Exchange servers.  Enter Invoke-Command - you should be hearing cheering, whistling and much applause as this is darn near the most useful cmdlet in PowerShell V2.

Following is a script that could be used to create 100s of volumes.

############## Step 1 ##############            
# Create the mount point for the drives            
# We create a script block consisting of the commands we need to pipe to Diskpart            
$cmds = "`"Select Disk 2`"",            
        "`"create partition primary`"",            
        "`"assign letter=m`"",            
        "`"format fs = ntfs unit=64k quick label='Databases'`""            
$string = [string]::Join(",",$cmds)            
$sb = $ExecutionContext.InvokeCommand.NewScriptBlock("$string | DiskPart")            
            
# Iterate over the 6 Exchange Servers using Invoke-Command to run or            
# script block on each server            
1..6 | foreach {            
    Invoke-Command -ComputerName "ex10mbox-vp0$_" -ScriptBlock $sb            
}            
            
############## Step 2 ##############            
# Using a supplied CSV file, create our directories            
$folders = Import-Csv -Path C:\temp\BrentFolders.csv             
$folders | foreach {            
    $path = "\\$($_.server)\M$\$($_.folder)"            
    if(-not(Test-Path -Path $path)) {            
        New-Item -Path $path -ItemType Directory            
    }            
}            
            
############## Step 3 ##############            
# Create the 10 volumes that will be used to hold the individual database and log files.            
$disk = 3            
foreach ($folder in $folders) {            
    if($i -eq 13){$i=3}            
    $cmds = "`"select disk $disk`"",            
            "`"online disk`"",            
            "`"attributes disk clear readonly`"",            
            "`"convert mbr`"",            
            "`"create partition primary`"",            
            "`"assign mount=M:\$($folder.Folder)`"",            
            "`"format fs = ntfs unit=64k quick label=$($Folder.Folder)`""             
    $disk++            
    $string = [string]::Join(",",$cmds)            
    $sb = $ExecutionContext.InvokeCommand.NewScriptBlock("$string | DiskPart")            
    Invoke-Command -ComputerName $folder.Server -ScriptBlock $sb            
}            
This could also be utilzed for SQL Server rollouts, etc.

Enjoy!

1 comment:

Anonymous said...

Sweet