Easy 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