VMware Cloud Community
yonish
Contributor
Contributor

NetApp and VMware powercli to recover fast vm (mount snapshot)

Screen Shot 2014-06-02 at 17.47.04.pngEasy tool to internal team.

The main advantage of mounting a read/write snapshot is very easy and fast recovery.

The machine can up and running in less than a min as described below

This will do following : restore vm by date with easy gui

1. poweroff or shutdown a vm

2. create vol snapshot

3. delete vm

4. create igroup with wwn

5. map snapshot to a lun (lun clone) and to a igroup

6. register the vm and poweron

7.svmotion to the original datastore

8. unmount datastore and unmap lun

9.delete lun

The time till full recovery is only between phase 1-6.

Phase 7-9 will be done in the background while the vm is up and running.

<PastedGraphic-1.png>

function button ($App_title,$button_variable1, $button_variable2) {#, $TF) {

###################Load Assembly for creating form & button######

[void][System.Reflection.Assembly]::LoadWithPartialName( “System.Windows.Forms”)

[void][System.Reflection.Assembly]::LoadWithPartialName( “Microsoft.VisualBasic”)

$form = New-Object “System.Windows.Forms.Form”;

$form.Width = 500;

$form.Height = 150;

$form.Text = $App_title;

$form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen;

##############Define text label1

$textLabel1 = New-Object “System.Windows.Forms.Label”;

$textLabel1.Left = 25;

$textLabel1.Top = 15;

$textLabel1.Text = $button_variable1;

##############Define text label2

$textLabel2 = New-Object “System.Windows.Forms.Label”;

$textLabel2.Left = 25;

$textLabel2.Top = 50;

$textLabel2.Text = $button_variable2;

##############Define text label3

#$textLabel3 = New-Object “System.Windows.Forms.Label”;

#$textLabel3.Left = 25;

#$textLabel3.Top = 85;

#$textLabel3.Text = $TF;

############Define text box1 for input

$textBox1 = New-Object “System.Windows.Forms.TextBox”;

$textBox1.Left = 150;

$textBox1.Top = 10;

$textBox1.width = 200;

############Define text box2 for input

$textBox2 = New-Object “System.Windows.Forms.TextBox”;

$textBox2.Left = 150;

$textBox2.Top = 50;

$textBox2.width = 200;

############Define text box3 for input

#$textBox3 = New-Object “System.Windows.Forms.TextBox”;

#$textBox3.Left = 150;

#$textBox3.Top = 90;

#$textBox3.width = 200;

#############Define default values for the input boxes

$defaultValue = “”

$textBox1.Text = $defaultValue;

$textBox2.Text = $defaultValue;

#$textBox3.Text = $defaultValue;

#############define OK button/“execute restore”;

$button = New-Object “System.Windows.Forms.Button”;

$button.Left = 360;

$button.Top = 85;

$button.Width = 100;

$button.Text = “execute restore”;

############# This is when you have to close the form after getting values

$eventHandler = [System.EventHandler]{

$textBox1.Text;

$textBox2.Text;

$textBox23.Text;

$form.Close();};

$button.Add_Click($eventHandler) ;

#############Add controls to all the above objects defined

$form.Controls.Add($button);

$form.Controls.Add($textLabel1);

$form.Controls.Add($textLabel2);

#$form.Controls.Add($textLabel3);

$form.Controls.Add($textBox1);

$form.Controls.Add($textBox2);

#$form.Controls.Add($textBox3);

$ret = $form.ShowDialog();

return $textBox1.Text, $textBox2.Text #, $textBox3.Text

}

$return= button “Restore VM” "VM_Name" "Days to recover” # “Target Folder3”

$return[0]

$return[1]

#$return[2]

#Get-Process $return[0],$return[1]

$snapins = @("VMware.VimAutomation.Core")

foreach ($snapin in $snapins){

  try {

  Write-Host "Trying to load snapin $snapin"

  Add-PSSnapin $snapin -ErrorAction Stop

  Write-Host "$Snapin loaded"

  }

  catch {

  Write-Host "$snapin was already loaded or cannot be loaded"

  }

}

$creds = Get-VICredentialStoreItem -file C:\sc\vc_store.creds

Connect-VIServer -Server $creds.host -User $creds.User -Password $creds.Password

Import-Module dataontap

$netapp_controller=“ip”

$narootpasswd = “password"

$password = ConvertTo-SecureString $narootpasswd -AsPlainText -Force

$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root",$password

Connect-NaController "$netapp_controller" -Credential $cred

$number_days_to_resotre=$return[1]

$Date = Get-Date

$Date = $Date.adddays(-"$number_days_to_resotre")

$Date2Str = $Date.ToString("M/dd/yyy")

$vm_to_restore=$return[0]

$original_ds=Get-Datastore -vm $vm_to_restore

$original_vol=Get-NaVol | where {$_.name -match $original_ds}

$original_lun_path=Get-NaLun | where {$_.path -match "$original_ds"}

$lun_temp_mounted=($original_lun_path.path+"_restore.lun")

$Date = Get-Date

$Date2Str1 = $Date.ToString("dd_MM_yyy_hh_mm")

ForEach($vm_to_stop in $vm_to_stop)

{

$vm_to_stop=get-vm "$vm_to_restore"

$vm_view = $vm_to_stop | get-view

$vmtoolsstatus = $vm_view.summary.guest.toolsRunningStatus

Write-Host “VM $vm_to_stop tools status is $Vmtoolsstatus”

if ($vmtoolsstatus -eq “guestToolsRunning”)

{

Shutdown-VMGuest -VM $vm_to_stop -Confirm:$false

}

else

{

stop-vm -VM $vm_to_stop -Confirm:$false

}

}

New-NaSnapshot -SnapName ($vm_to_restore+"_$Date2Str1") -TargetName "$original_vol" # netapp

$vm_to_delete= Get-VM "$vm_to_restore"| where {$_.PowerState -eq "PoweredOff"}

$vm_to_delete | Remove-VM -DeletePermanently -Confirm:$false

$parentSnapshot_to_mount=Get-NaSnapshot -TargetName $original_vol | where {$_.name -match "Job1"} | where {$_.Created -match "$Date2Str"}

#Get-NaSnapshot -TargetName $original_vol | where {$_.name -match "Job1"} | where {$_.Created -match "$Date2Str"}

New-NaLunClone -ParentPath "$original_lun_path" -ClonePath $lun_temp_mounted -ParentSnapshot "$parentSnapshot_to_mount" -Unreserved:$true

#igroup esx57

New-NaIgroup esx57_restore_temp -Protocol fcp vmware

Get-NaIgroup esx57_restore_temp | Set-NaIgroup -Key alua -value yes

Add-NaIgroupInitiator esx57_restore_temp 21:00:00:1b:32:8b:68:3f

#Add-NaIgroupInitiator esx57_restore_temp 21:00:00:24:ff:4c:7e:6e

#Add-NaIgroupInitiator esx57_restore_temp 21:00:00:24:ff:4c:7e:6f

Add-NaLunMap $lun_temp_mounted -InitiatorGroup esx57_restore_temp -ID "100"

#Get-VM $vm_to_restore | Shutdown-VMGuest -Confirm:$false

Get-Cluster -Name “cluster1” | Get-VMHost | Get-VMHostStorage -RescanAllHba

$TargetVMCenterHost=“vm_host"

$TargetVMCenterDatastoreName="restore1"

$TargetLUNNo="100"

$scsilun= "L" + $TargetLUNNo

$scsi= Get-ScsiLun -VmHost $TargetVMCenterHost -LunType disk | Where{ $_.RuntimeName -match "$scsilun" }

$scsiCname= $scsi.CanonicalName

#Create a list of unbound scsi devices

$hostView= get-vmhost -name $TargetVMCenterHost | get-view

$dsView= get-view $hostView.ConfigManager.DatastoreSystem

$unBound= $dsView.QueryUnresolvedVmfsVolumes()

#Loop thru unbound scsi devices and resignature applicable device.

foreach

($ub in $UnBound) {

$extPaths= @()

$Extents= $ub.Extent;

foreach

($ex in $Extents) {

$extPaths= $extPaths + $ex.DevicePath

}

#Only resignature desired LUN No.

IF ($extPaths -match $scsiCname)

{

$res = New-Object VMware.Vim.HostUnresolvedVmfsResignatureSpec

$res.ExtentDevicePath = $extPaths

$dsView.ResignatureUnresolvedVmfsVolume($res)

}

}

#Find and rename new datastore.

$NewDatastore= Get-Datastore -VmHost $TargetVMCenterHost | Where{ $_.Name -like "snap-*$ProdVol0" }

Set-Datastore $NewDatastore -Name $TargetVMCenterDatastoreName

####

#$vm_to_restore=$vm_to_restore

$esxhost= Get-VMHost vm_host

dir vmstores:\vc_ip@443\datacenter_name\$TargetVMCenterDatastoreName\$vm_to_restore\*.vmx |

% {New-VM -Host $esxhost -VMFilePath $_.DatastoreFullPath}

###start and svmotion

Get-VM $vm_to_restore | Start-VM

Get-VM $vm_to_restore | Move-VM -Datastore $original_ds

# if to check if datastore is not used some how

##

Function Get-DatastoreMountInfo {

  [CmdletBinding()]

  Param (

  [Parameter(ValueFromPipeline=$true)]

  $Datastore

  )

  Process {

  $AllInfo = @()

  if (-not $Datastore) {

  $Datastore = Get-Datastore

  }

  Foreach ($ds in $Datastore) {

  if ($ds.ExtensionData.info.Vmfs) {

  $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].diskname

  if ($ds.ExtensionData.Host) {

  $attachedHosts = $ds.ExtensionData.Host

  Foreach ($VMHost in $attachedHosts) {

  $hostview = Get-View $VMHost.Key

  $hostviewDSState = $VMHost.MountInfo.Mounted

  $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

  $devices = $StorageSys.StorageDeviceInfo.ScsiLun

  Foreach ($device in $devices) {

  $Info = "" | Select Datastore, VMHost, Lun, Mounted, State

  if ($device.canonicalName -eq $hostviewDSDiskName) {

  $hostviewDSAttachState = ""

  if ($device.operationalState[0] -eq "ok") {

  $hostviewDSAttachState = "Attached"

  } elseif ($device.operationalState[0] -eq "off") {

  $hostviewDSAttachState = "Detached"

  } else {

  $hostviewDSAttachState = $device.operationalstate[0]

  }

  $Info.Datastore = $ds.Name

  $Info.Lun = $hostviewDSDiskName

  $Info.VMHost = $hostview.Name

  $Info.Mounted = $HostViewDSState

  $Info.State = $hostviewDSAttachState

  $AllInfo += $Info

  }

  }

  }

  }

  }

  }

  $AllInfo

  }

}

Function Detach-Datastore {

  [CmdletBinding()]

  Param (

  [Parameter(ValueFromPipeline=$true)]

  $Datastore

  )

  Process {

  if (-not $Datastore) {

  Write-Host "No Datastore defined as input"

  Exit

  }

  Foreach ($ds in $Datastore) {

  $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

  if ($ds.ExtensionData.Host) {

  $attachedHosts = $ds.ExtensionData.Host

  Foreach ($VMHost in $attachedHosts) {

  $hostview = Get-View $VMHost.Key

  $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

  $devices = $StorageSys.StorageDeviceInfo.ScsiLun

  Foreach ($device in $devices) {

  if ($device.canonicalName -eq $hostviewDSDiskName) {

  $LunUUID = $Device.Uuid

  Write-Host "Detaching LUN $($Device.CanonicalName) from host $($hostview.Name)..."

  $StorageSys.DetachScsiLun($LunUUID);

  }

  }

  }

  }

  }

  }

}

Function Unmount-Datastore {

  [CmdletBinding()]

  Param (

  [Parameter(ValueFromPipeline=$true)]

  $Datastore

  )

  Process {

  if (-not $Datastore) {

  Write-Host "No Datastore defined as input"

  Exit

  }

  Foreach ($ds in $Datastore) {

  $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

  if ($ds.ExtensionData.Host) {

  $attachedHosts = $ds.ExtensionData.Host

  Foreach ($VMHost in $attachedHosts) {

  $hostview = Get-View $VMHost.Key

  $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

  Write-Host "Unmounting VMFS Datastore $($DS.Name) from host $($hostview.Name)..."

  $StorageSys.UnmountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);

  }

  }

  }

  }

}

Function Mount-Datastore {

  [CmdletBinding()]

  Param (

  [Parameter(ValueFromPipeline=$true)]

  $Datastore

  )

  Process {

  if (-not $Datastore) {

  Write-Host "No Datastore defined as input"

  Exit

  }

  Foreach ($ds in $Datastore) {

  $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

  if ($ds.ExtensionData.Host) {

  $attachedHosts = $ds.ExtensionData.Host

  Foreach ($VMHost in $attachedHosts) {

  $hostview = Get-View $VMHost.Key

  $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

  Write-Host "Mounting VMFS Datastore $($DS.Name) on host $($hostview.Name)..."

  $StorageSys.MountVmfsVolume($DS.ExtensionData.Info.vmfs.uuid);

  }

  }

  }

  }

}

Function Attach-Datastore {

  [CmdletBinding()]

  Param (

  [Parameter(ValueFromPipeline=$true)]

  $Datastore

  )

  Process {

  if (-not $Datastore) {

  Write-Host "No Datastore defined as input"

  Exit

  }

  Foreach ($ds in $Datastore) {

  $hostviewDSDiskName = $ds.ExtensionData.Info.vmfs.extent[0].Diskname

  if ($ds.ExtensionData.Host) {

  $attachedHosts = $ds.ExtensionData.Host

  Foreach ($VMHost in $attachedHosts) {

  $hostview = Get-View $VMHost.Key

  $StorageSys = Get-View $HostView.ConfigManager.StorageSystem

  $devices = $StorageSys.StorageDeviceInfo.ScsiLun

  Foreach ($device in $devices) {

  if ($device.canonicalName -eq $hostviewDSDiskName) {

  $LunUUID = $Device.Uuid

  Write-Host "Attaching LUN $($Device.CanonicalName) to host $($hostview.Name)..."

  $StorageSys.AttachScsiLun($LunUUID);

  }

  }

  }

  }

  }

  }

}

#

#Get-Datastore | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize

#

#Get-Datastore IX2ISCSI01 | Unmount-Datastore

#

#Get-Datastore IX2ISCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize

#

#Get-Datastore IX2iSCSI01 | Mount-Datastore

#

#Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize

#

#Get-Datastore IX2iSCSI01 | Detach-Datastore

#

#Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize

#

#Get-Datastore IX2iSCSI01 | Attach-datastore

#

#Get-Datastore IX2iSCSI01 | Get-DatastoreMountInfo | Sort Datastore, VMHost | FT -AutoSize

#

Get-Datastore restore1 | Unmount-Datastore

sleep 15

#Remove-Datastore -Datastore $TargetVMCenterDatastoreName -VMHost vm_host -Confirm$:false # may be foreach

#netapp

Get-NaLunMap $lun_temp_mounted | Remove-NaLunMap

Get-Cluster -Name "cluster1" | Get-VMHost | Get-VMHostStorage -RescanAllHba

Get-NaLun $lun_temp_mounted | remove-nalun -confirm:$false

# delete igroup —> later on

Best regards,

Yoni Shperling

Reply
0 Kudos
0 Replies