Microsoft News Summary – 22 August 2014

Here’s the latest news from the Microsoft wires. More new services have popped up on Azure, mostly for devs, but the SQL AlwaysOn template should be a massive time saver.

Hyper-V

Azure

Security

OS Deployment

Office 365

Microsoft News Summary – 13 August 2014

Overnight, Microsoft released the August 2014 Update Rollup for WS2012 R2 and Windows 8. Lots of hotfixes!

Microsoft News Summary – 30 July 2014

The big news here for MSFT techies are the releases of update rollups for SysCtr 2012 SP1 and SysCtr 2012 R2. Please wait 1 month before deploying to avoid the inevitable issues (history indicates that I am probably right) and use that time to carefully review the installation instructions.

Microsoft News Summary – 28 July 2014

It was a quiet weekend. Note a useful scripts for health checking a Scale-Out File Server (SOFS) by Jose Barreto.

Microsoft News Summary – 24 July 2014

Very little for you today:

Microsoft News Summary-28 May 2014

It’s been a slow few days for news. Here’s what popped up overnight.

Microsoft News Summary-21 May 2014

I took a break from these posts last week while I was at TechEd, and then had work catch up to do this week. Let’s get back a rockin’. There is a distinct tendency towards cloud and automation in the news of the last week. That should be no surprise.

Script To Convert Hyper-V Virtual Machine From VHD To VHDX

Last year I wrote a script that would allow you to specify a virtual machine, and the script would:

  1. Shut down the VM if running
  2. Seek out any VHD files attached to any of the VM’s controllers
  3. Create VHDX files from those VHD files
  4. Replace the VHD files by attaching the VHDX files to the same controllers and locations in the VM settings
  5. Delete the VHD files

In my tests, the script had some issues. But that was nearly a year ago and it was on WS2012 in my lab. The script remained untouched until yesterday. I was chatting with my fellow Hyper-V MVP, Didier Van Hoye (aka @workinghardinit). He told me he was in the process of migrating VMs from an old W2008 R2 cluster to WS2012 and was going to be converting VHD files. Aha! This might be a time for a solution to speed up the process.

I sent the script over to Didier to have a look-see. Would it work. Well, Didier ran a series of tests this morning with guest OSs including W2003 R2 and WS2012. The tests ran flawlessly.

So … here is the script. FYI there are few things to note:

  • You might consider putting in a delay loop to test if the VM is actually shut down if you need to shut it down. Put a timeout of 3 minutes in that. The stop-vm cmdlet is async so it shouldn’t cause an issue as it is below, but you might want to take the extra step, just in case.
  • You might want to comment out the line Remove-VMHardDiskDrive $VHD for your test or pilot runs.
  • I do not support this script 🙂
  • Run the script and specify the VM name as a parameter.

CREDIT: A big thank you to Didier Van Hoye (aka @workinghardinit) for checking my work.

#—-

[CmdletBinding ()]
Param   (
        [Parameter(Mandatory=$True)]
        [string]$VMName
        )

#Disable error reporting – comment out the following line if you need to troubleshoot the script
$ErrorActionPreference = "SilentlyContinue"

cls

$VM = Get-VM $VMName
$VMStatus = $VM.State

if ($VM.VMid -ne $NULL)
{
    if ($VMStatus -eq "Running")
    {  
        #Shut down the VM if it is running
        Write-Host "Shutting down" $VMName
        Stop-VM $VMName  
    }

    #Get the disks in the VM
    $AllVHD = Get-VMHardDiskDrive $VMName

    if ($AllVHD -eq $NULL)
        {
        Write-Host "There are no virtual hard disks to convert"
        Exit
        }

    foreach ($VHD in $AllVHD)
    {
        #Get the VM path and create a VHDX file path
        [string]$VHDFile = Get-Item $VHD.Path
        $VHDFormat = (Get-VHD $VHDFile).VhdFormat
        if ($VHDFormat -eq "VHD")
            {
            [string]$VHDXFile = $VHDFile + "x"

            [string]$ControllerType = $VHD.ControllerType
            [string]$ControllerNumber = $VHD.ControllerNumber
            [string]$ControllerLocation = $VHD.ControllerLocation

            Write-Host "Converting: " $VHDFile "to" $VHDXFile
            Convert-VHD –Path $VHDFile –DestinationPath $VHDXFile
            Sleep 10

            #Reconfigure the Physical Sector Size of the VHDX file to 4 K
            Set-VHD -Path $VHDXFile -PhysicalSectorSizeBytes 4096
            Sleep 10

            #Remove the old VHD
            Write-Host "Removing $VHDFile from $VMName"
            Remove-VMHardDiskDrive $VHD
            Sleep 10
            #Replace the VHD with the VHDX
            Write-Host "Adding $VHDXFile to $VMName"
            Add-VMHardDiskDrive -VMName $VMName -Path $VHDXFile -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation

            #Danger Will Robinson – we are going to delete the original VHD – we hope you have a tested VM backup!
            Write-Host "Deleting $VHDFile"
            Remove-Item $VHDFile -Force
            }
        else
            {
            Write-Host "$VHDFile is already a VHDX file: skipping"
            }
    }

    if ($VMStatus -eq "Running")
    {  
        #Restart the VM if it was running before the conversion
        Write-Host "Starting" $VMName
        Start-VM $VMName  
        #Wait for 10 seconds
        Write-Host "Waiting for 10 seconds to verify the virtual machine …"
        Sleep 10
        $VMStatus = $VM.State
        if ($VMStatus -ne "Running")
        {
            #Something went wrong
            Write-Host "$VMName could not reboot – please restore the VM from backup"     
        }
    }

}
else
{
    Write-Host $VMName "does not exist on this host"
    Exit
}

Write-Host "Processing of $VMName has completed"

Build WS2012 R2 Storage Pools, Virtual Disks, And CSVs Using PowerShell

I’ve been building, tearing down, and rebuilding Storage Spaces in the lab over and over, and that will continue for the next few years Smile Rather than spend a significant percentage of my life clicking on wizards, I decided to script what I want done.

The below script will:

  • Build a storage pool from all available disks
  • Prep 2 storage tiers from SSD and HDD
  • Create 3 different virtual disks with different configs (customize to your heat’s content!)
  • Then run the PrepCSV function to turn those virtual disks into CSVs just the way I like them

How do I like a CSV?  I like them formatted Smile and the names consistent all the way: virtual disk, cluster resource name, volume label, and CSV mount point in C:ClusterStorage.  None of that “Cluster Disk (X)” or “Volume 1” BS for me, thank you.

It might be possible to clean up the stuff in the function.  This is what I have working – it works and that’s the main thing.  There’s a lot of steps to get disk ID so I can create and format a volume, and then bring the disk back so I can turn it into a CSV.

What’s missing?  I have not added code for adding the SOFS role or adding/configuring shares.  I’m not at that point yet in the lab.

Function PrepCSV ($CSVName)
{
#Rename the disk resource in FCM
(Get-ClusterResource | where {$_.name -like “*$CSVName)”}).Name = $CSVName

#Get the disk ID
Stop-ClusterResource $CSVName
$DiskID = (Get-VirtualDisk -FriendlyName $CSVName).UniqueId
Start-ClusterResource $CSVName

#Format the disk
Suspend-ClusterResource $CSVName
Get-disk -UniqueId $DiskID | New-Partition -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel “$CSVName” -Confirm:$false
Resume-ClusterResource $CSVName

#Bring the CSV online
Add-ClusterSharedVolume -Name $CSVName
$OldCSVName = ((Get-ClusterSharedVolume $CSVName).SharedVOlumeInfo).FriendlyVolumeName
Rename-Item $OldCSVName -NewName “C:ClusterStorage$CSVName”
}

# The following Storage Pool and Virtual Disk cmdlets taken from Bryan Matthew’s TechEd  …
# … Session at http://channel9.msdn.com/Events/TechEd/Europe/2013/MDC-B217#fbid=TFEWNjeU9XP

# Find all eligible disks
$disks = Get-PhysicalDisk |? {$_.CanPool -eq $true}

# Create a new Storage Pool
New-StoragePool -StorageSubSystemFriendlyName “Clustered Storage Spaces on Demo-FSC1” -FriendlyName “Demo-FSC1 Pool1” -PhysicalDisks $disks

# Define the Pool Storage Tiers
$ssd_tier = New-StorageTier -StoragePoolFriendlyName “Demo-FSC1 Pool1” -FriendlyName SSD_Tier -MediaType SSD
$hdd_tier = New-StorageTier -StoragePoolFriendlyName “Demo-FSC1 Pool1” -FriendlyName HDD_Tier -MediaType HDD

 

#Transfer ownership of Available Storage to current node to enable disk formatting

Move-ClusterGroup “Available Storage” -Node $env:COMPUTERNAME

 

# Creation of a 200 GB tiered virtual disk with 5 GB cache
New-VirtualDisk -StoragePoolFriendlyName “Demo-FSC1 Pool1” -FriendlyName CSV1 –StorageTiers @($ssd_tier, $hdd_tier) -StorageTierSizes @(50GB,150GB) -ResiliencySettingName Mirror -WriteCacheSize 5GB
PrepCSV CSV1

 

# Creation of a 200 GB non-tiered virtual disk with no cache

New-VirtualDisk -StoragePoolFriendlyName “Demo-FSC1 Pool1” -FriendlyName CSV2 -Size 200GB -ResiliencySettingName Mirror -WriteCacheSize 0
PrepCSV CSV2

 

# Creation of a 50 GB virtual disk on SSD only with 5 GB cache

New-VirtualDisk -StoragePoolFriendlyName “Demo-FSC1 Pool1” -FriendlyName CSV3 –StorageTiers @($ssd_tier) -StorageTierSizes @(50GB) -ResiliencySettingName Mirror -WriteCacheSize 5GB
PrepCSV CSV3

 

EDIT1:

This script broke if the cluster group, Available Storage, was active on another node.  This prevented formatting, which in turn prevented adding the virtual disks as CSVs.  Easy fix: move the Available Storage cluster group to the current machine (a node in the cluster).

 

Deploy Roles Or Features To Lots Of Servers At Once

I’m deploying a large cluster at the moment and I wanted to install the Failover Clustering feature to all the machines without logging, doing stuff, logging out, and repeating.  This snippet of PowerShell took me 45 seconds to put together.  The feature is installing on 8 machines (Demo-FS1 to Demo-FS8) while I’m writing this blog post Smile

For ($i = 1; $i -lt 9; $i++)
{
    Install-WindowsFeature -ComputerName Demo-FS$i Failover-Clustering, RSAT-Clustering
}

The variable $i starts at 1, is used as part of the computer name that is remotely being updated, and then incremented in the next loop iteration.  The loop ends after the 8th iteration, i.e. the 8th server is updated.

Aint automation be-yoot-eeful?