Home > PowerCLI, Powershell > SRM for free with PowerCLI – Part 2: iSCSI

SRM for free with PowerCLI – Part 2: iSCSI

My previous post talked about the design of BR and how to script a simple and scalable recovery process for getting as many VMs as you need from a primary site to a BR site when using NFS storage.

When using iSCSI storage it is slightly more complicated as you can’t use one of the benefits of NFS in presenting a read only datastore to ESX hosts in your BR site and having your VMs in the inventory and ready to just power on.

The manual steps would be:

Break the storage mirror.
Rescan the storage on the ESX hosts in the recovery site to pick up the now-visible LUN.
Browse the LUN for all .vmx files and add them into the inventory
Power on the VMs and answer the UUID question that they have moved.

Thanks LucD who has two great versions of a function for importing .VMX files, much better than the old community extension method.

The function is very powerful so it’s worth keeping as a link for using elsewhere.

I’ve cut down the function to make it easier for this implementation and put in a folder option so you can select which blue folder the VMs should be added to. I’ve left the NFS NetApp .snapshot file path checker as its one line and makes it easy to also use for NFS.
Here we go:

Title:         VM-iSCSIBR.ps1
Description:   Connects to vCenter.
               Rescans HBAs
               Browse datastore and all all .vmx files to inventory in a specified folder.
               Folder name must be unique in vCenter
               Power on VMs
               Answers UUID question to say VM was Moved.
               Can be Run as Scheduled Task
Usage:         .\VM-iSCSIBR.ps1

function Register-VMX {
         param($dsNames = $null,$folderName = $null,$clusterName = $null)

         function Get-Usage{
            Write-Host "Parameters incorrect" -ForegroundColor red
            Write-Host "Register-VMX -dsName -foldername -clusterName "
            Write-Host "dsName       : datastore names"
            Write-Host "folderName   : folder name to place VMs"
            Write-Host "clusterName  : name of cluster to place VMs"
         if($dsName -eq $null -or $clusterName -eq $null -or $folderName -eq $null){
		$ESXname = Get-Cluster $clusterName | Get-VMHost | select -First 1
		$folder = Get-View (Get-Folder $folderName)
		$pool = Get-View (Get-Cluster -Name $clusterName | Get-ResourcePool -Name "Resources").ID
		$ds = Get-Datastore $dsName | Get-View
		$dsBrowser = Get-View $ds.Browser
		$datastorepath = "[" + $ds.Summary.Name + "]"

		$searchspec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
		$searchSpec.matchpattern = "*.vmx"

		Write-Host "Searching in path" $datastorepath

		$task = Get-View ($dsBrowser.SearchDatastoreSubFolders_Task($datastorePath, $searchSpec))
		while ($task.Info.State -eq "running" -or $task.Info.State -eq "queued"){
			sleep 5
		if($task.info.result -ne $null){
			foreach ($file in $task.info.Result){
				if($file.FolderPath -match ".snapshot"){continue}
				$found = $FALSE
				foreach($vmx in $vms){
					if(($file.FolderPath + $file.File[0].Path) -eq $vmx){
						Write-Host "`tVM is registered"
						$found = $TRUE
				if (-not $found -and $task.Info.Result[0].File -ne $null){
					$vmx = $file.FolderPath + $file.File[0].Path
					$params = @($vmx,$null,$FALSE,$pool.MoRef,$null)
					Write-Host "Registering" $vmx
					$folder.GetType().GetMethod("RegisterVM_Task").Invoke($folder, $params)
$cluster = "NYC_PROD1" 				# BR site Cluster "
$datastores = "nyc_lonvm1" 			# Datastores to add .vmx files from
$vmfolder = "BR-LondonAppServers"	# Folder where BR VMs are to be placed - Must be unique in VC
$vcserver = "vcenter.local"			# vCenter Server

# Connect to VC
Connect-VIServer -Server $vcserver

# Rescan all HBAs in BR site
Get-Cluster $cluster | Get-VMHost | Get-VMHostStorage -RescanAllHba

# Get discovered datastores
$datastores = get-datastore snap*$datastorefind*

foreach($datastore in $datastores)
	#Register all .vmx Files as VMs on the datastore
	Register-VMX -dsNames $Datastore.Name -folderName $vmfolder -clusterName $cluster
# All VMs are now added to folder
$vms = get-vm -Location (get-folder $vmfolder)

# Disconnect Networking FOR TESTING ONLY
#$vms | get-networkadapter | Set-NetworkAdapter -StartConnected:$false -Confirm:$false

# Power on VMs even with questions pending
$vms | Start-VM -RunAsync

# Answer Question to Keep UUID in Loop until Question is answered
$qMsgUuidMoved = "msg.uuid.altered:"
$choiceMove = 2

ForEach ($vm in $vms)
      $vmview = $vm | Get-View
      if($vmview.Runtime.Question -ne $null -and $vmview.Runtime.Question.Text.StartsWith($qMsgUuidMoved))
         $vmview.AnswerVM($vmview.Runtime.Question.Id, $choiceMove)
   until ($vmview.Runtime.PowerState -ne "poweredoff")

# Disconnect from VC Server
Disconnect-VIServer -Confirm:$False

Time limit is exhausted. Please reload the CAPTCHA.