Equallogic Storage – VSS Backup – Clearing Orphaned Snapshots via PowerShell

I have been using Veeam Backup & Replication now for a few months with very positive results, however our Equallogic storage does suffer occasionally from orphaned snapshots due to issues with the VSS writer when running multiple jobs that run at the same time.

At the start I had been clearing the “offline” snapshots manually when these issues occurred, as to ensure that the snapshots did not borrow space and ultimately consume the entire available space. Then I thought, why am I doing this? surely a SCOM monitor or automated task could clear these snapshots for me.

The below script requires the Group Management IP address and the name of the Hyper-V (assumed) cluster you have your storage connected to. The script connects to a random host within the cluster and registers the Equallogic PowerShell tools, then imports the tools to the machine running the shell before connecting to the storage and finding / removing all snapshots in an Offline state. It can of course be modified to include credentials or to look for other characteristics but this suits my environment as I tend not to use the snapshot features of the storage with the exception of the backup process:

$GrpAddr = "YOUR MANAGEMENT IP ADDRESS"
$AvailableNodes = Get-ClusterNode -Cluster YOUR CLUSTER NAME | ForEach-Object {Write-Output $($_.Name)}
$HyperVNode = Get-Random $AvailableNodes
$HvHost = New-PSSession -ComputerName $HyperVNode
Invoke-Command -Session $HvHost -ScriptBlock {Import-Module "c:\program files\EqualLogic\bin\EqlPSTools.dll"}
Import-PSSession -Session $HvHost -Module EqlPSTools
Connect-EqlGroup -GroupAddress $GrpAddr -Credential (Get-Credential) -AllowClobber
Get-EqlSnapshot | Where-Object {$_.isOnline -eq $false} | Remove-EqlSnapshot
Remove-PSSession $HvHost

Machine AD Auto Renaming – MDT/SCCM Deployment

I have seen a lot of scripts around for automatically generating the next available computer name for use with SCCM during the deployment stage, however I was looking for something that would read from Active Directory and find out if any gaps existed such as where an old machine was retired and then use the next sequence number. Example:

LT-DEMO-1000
LT-DEMO-1002
LT-DEMO-1003

Given that in the above example LT-DEMO-1001 is available.

Our existing SCCM/MDT solution already auto creates PC names based on their location, machine type and the last four digits of their serial number. I wanted to add functionality to take this information, query active directory and rename the machine using the next truly available name in our naming sequence. I created the below script based on a minimum sequence value of 1000 and an upper value of 1999, the original machine type and location/dept. in my naming convention is extracted and then the machine is renamed using the next number available:

$DC = $env:LOGONSERVER.Substring(2)
$ADPowerShell = New-PSSession -ComputerName $DC
Invoke-Command -Session $ADPowerShell -scriptblock {import-module ActiveDirectory}
Import-PSSession -Session $ADPowerShell -Module ActiveDirectory -AllowClobber -ErrorAction Stop
$TypeLocation = $env:COMPUTERNAME.Substring(0,$env:COMPUTERNAME.Length-4)
$UsedNumbers = Get-ADComputer -Filter * -Properties Name | Where-Object {$_.Name -like ("$TypeLocation" + "*")} | ForEach-Object {Write-Output $($_.Name.Substring($_.Name.length-4,4))}
$NextNumber = 1000
$values = 1000..1999
Do
{
$values[$NextNumber]
$NextNumber ++
} Until ($UsedNumbers.Contains("$NextNumber") -eq $false)
$ComputerName = ("$TypeLocation" + "$NextNumber")
Exit-PSSession
Rename-Computer -ComputerName $env:COMPUTERNAME -NewName $ComputerName -Restart

Obviously the script has to be run with an account with rights to rename the computer object in Active Directory. Note that this script can be run inside the Windows environment and not the task sequence.

UPDATE – 28/11/2014

After many hours of testing, I have modified the original rename script to run inside the task sequence.

The script requires sufficient rights to connect to a named domain controller via PowerShell and rename the workstation. For security purposes I am opting obviously not to embed the password in clear text so a secondary script is run to generate a text file with a secure string password first and uploaded to a file share.

It works by passing the local machine variables through to a PS session on your DC, finding the next available computer name and then issuing a rename-computer command to the machine being imaged. In order to achieve this the script also disables and re-enables the local Windows firewall on the machine being build in order for the WMI command to be issued from the DC.

To deploy the script, add it to a package, distribute it and then insert a Run PowerShell Script command within your task sequence (setting the execution policy to bypass) as per the screenshot below:

Machine Rename Task Sequence Command

Export Credential Script (run this to export the password to a secure string in a file on your file server share):

Script Download Link – https://gallery.technet.microsoft.com/scriptcenter/SCCM-MDT-Computer-Auto-7969a373

$key = (1..16)
$securepass = Read-Host -AsSecureString -Prompt "Please enter the required account password" | ConvertFrom-SecureString -Key $Key
$encrypted = $securepass | Out-File -FilePath '\\fileserver\yourshare\Required.txt'

Machine Rename Task Sequence Script:

$Username = 'yourdomain\useraccount'
$encrypted = Get-Content -Path '\\fileserver\yourshare\Required.txt'
$key = (1..16)
$Password = $encrypted | ConvertTo-SecureString -Key $key
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Password
$DC = "YourDomainControllerName"
$ADPowerShell = New-PSSession -ComputerName $DC -Credential $Credentials
$CurrentName = $env:COMPUTERNAME
netsh advfirewall set allprofiles state off
Invoke-Command -Session $ADPowerShell -scriptblock {
	import-module ActiveDirectory
	$clientname = $($args[0])
	$Username = 'yourdomain\useraccount'
	$encrypted = Get-Content -Path '\\fileserver\yourshare\Required.txt'
	$key = (1..16)
	$password = $encrypted | ConvertTo-SecureString -Key $key
	$DomainCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Password
	$TypeLocation = $ClientName.Substring(0, $ClientName.Length - 4)
	$UsedNumbers = Get-ADComputer -Filter * -Properties Name | Where-Object { $_.Name -like ("$TypeLocation" + "*") } | ForEach-Object { Write-Output $($_.Name.Substring($_.Name.length - 4, 4)) }
	$values = 1000..1999
	$adcheck = 0
	Do
	{
		# Set beginning of sequence number
		$NextNumber = 1000
		# Increment active directory check flag
		$adcheck++
		Do
		{
			$values[$NextNumber]
			$NextNumber++
		}
		Until ($UsedNumbers.Contains("$NextNumber") -eq $false)
		$ComputerName = ("$TypeLocation" + "$NextNumber")
		start-sleep -Seconds 2
	}
	while ($adcheck -le 3)
	Rename-Computer -ComputerName $ClientName -NewName $ComputerName -DomainCredential $DomainCredentials
	Exit-PSSession
} -ArgumentList $CurrentName
Remove-PSSession $ADPowerShell
# Re-enable the local firewall
netsh advfirewall set allprofiles state on