Thursday, September 15, 2016

Instant VM restore

This script is used to instantly restore a virtual machine from a netapp flexcloned volume

###################################################
#$filercreds is defined in profile.ps1 if you dont have it in your profile.ps1 - uncomment the following
##Run this part once
#read-host -AsSecureString | ConvertFrom-SecureString | out-file c:\filerpassword.txt

##Add this part to your profile.ps1
#$filerpassword = cat C:\filerpassword.txt | ConvertTo-SecureString
#$Filercreds = New-Object -TypeName System.Management.Automation.PScredential -argumentlist "admin" , $filerpassword
#################################################


Connect-VIServer vserver1,vserver2
$RecoveryVM = read-host "Enter the name of the VM that you want to do an instant restore"

$sanityCheck = read-host "By proceeding you will be removing" $RecoveryVM "from the invenotry and then mounting and running the VM from a flexclone - the script will then migrate the VM from the flexclone and overwrite the old production volume and dismount the flexclone - Proceed (Y/N)"
If ($sanityCheck -like "*N*")
    {write-host "exiting"
     pause
     exit }

$recoveryVM = get-vm | Where-Object {$_.name -like $RecoveryVM}
$recoveryhost = get-vm $recoveryvm | get-vmhost
$RecoveryVMParentStorage = get-vm $RecoveryVM | get-datastore | Where-object {($_.name -notlike "*swap*") -and ($_.name -notlike "*srm*") -and ($_.name -notlike "*page*")}

If ($RecoveryVMParentStorage.count -gt 1)
    { Write-host "Attached disks span more than 1 netapp volume - you'll have to do a manual restore using SMVI"
      Pause
      exit
    }

get-vm $recoveryvm | Shutdown-VMGuest -Confirm:$false

$i = 0
do{
    $i++
    Write-host "waiting for shutdown to complete"
    sleep 1
    $powerstate = get-vm $RecoveryVM
    if ($i -gt 120){
    write-host "VM is not shutting down gracefully - performing power off"
      get-vm $RecoveryVM | stop-vm -Confirm:$false
                    }
    }until($powerstate.powerstate -like "*off*")


remove-vm $recoveryvm -Confirm:$false  

# Connect to the appropriate filer
            if ($RecoveryVMParentStorage -like "*filera*"){
                 Connect-NcController namefilera -Credential $Filercreds -Vserver filera1              
                }
            if ($RecoveryVMParentStorage -like "*filerb*"){
                 Connect-NcController namefilerb -Credential $Filercreds -Vserver filerb1                
                }

$NetappVols = get-ncvol $RecoveryVMParentStorage.name

foreach ($netappvol in $NetappVols){
$AllNetavols = get-ncvol $netappvol | Get-NcSnapshot
}


# Create a list box containing all snapshots from the volume - Partially plagerised from https://technet.microsoft.com/en-us/library/ff730949.aspx

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a snapshot to clone"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")
    {$x=$objListBox.SelectedItem;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Add_Click({$x=$objListBox.SelectedItem;$objForm.Close()})
$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Available Snapshots for $NetappVols.name :"
$objForm.Controls.Add($objLabel)

$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(260,20)
$objListBox.Height = 80


foreach ($AllNetavol in $AllNetavols){
[void] $objListBox.Items.Add($AllNetavol.name )
}

$objForm.Controls.Add($objListBox)

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()



# get the flexclone as selected by the user
$Flexclone = get-ncvol $netappvol | get-ncsnapshot | Where-object {$_.name -like $objListBox.SelectedItem}

$FlexcloneVolname = $netappvol.name+"FC_InstantRestore"

#Check if the volume is already present - if it is warn the user and exit
if (Get-Datastore | Where-Object {$_.name -like $FlexcloneVolname}) {
        Clear
        write-host "*** Error*** The volume" $FlexcloneVolname "already exists - check there are no VMs running on it , unmount it and rerun the script"
        Pause
        exit
}
   

# spawn the flexcloned volume from the snapshot
get-ncvol $netappvol | New-NcVolClone -CloneVolume $FlexcloneVolname -ParentSnapshot $Flexclone

# figure out which host to attach the export to , Create the export , attach the export
$recoveryhostIP = $recoveryhost | Get-VMHostNetworkAdapter
$exportIPS = $recoveryhostIP.ip | Where-Object {$_ -cmatch $RecoveryVMParentStorage.remotehost.Split(".")[2]}
Get-Ncvol $FlexcloneVolname | Mount-NcVol -JunctionPath "/$FlexcloneVolname"
Add-NcNfsExport -Path /$FlexcloneVolname -ReadWrite @($exportIPS) -Root @($exportIPS)
Sleep 30
New-Datastore -VMHost $recoveryhost -Name $FlexcloneVolname  -Path /$FlexcloneVolname -NfsHost $RecoveryVMParentStorage.remotehost -Nfs

# Set up Search for .VMX Files in Datastore (partially plagerised from http://www.wooditwork.com/2011/08/11/adding-vmx-files-to-vcenter-inventory-with-powercli-gets-even-easier/)
   $ds = Get-Datastore -Name $FlexcloneVolname | %{Get-View $_.Id}
   $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
   $SearchSpec.matchpattern = "*.vmx"
   $dsBrowser = Get-View $ds.browser
   $DatastorePath = "[" + $ds.Summary.Name + "]"

   # Find all .VMX file paths in Datastore, filtering out ones with .snapshot (Useful for NetApp NFS)
   $VMXfile = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {($_.FolderPath -notmatch ".snapshot") -and ($_.folderpath -cmatch $RecoveryVM.name)} | %{$_.FolderPath + ($_.File | select Path).Path}

   #Register the .vmx Files
   New-VM -VMFilePath $VMXFile -VMHost $recoveryhost -Location $recoveryVM.Folder -ResourcePool $RecoveryVM.ResourcePool -RunAsync
 

#Wait until the VM has been registered on the vcentre server
            do {
                Write-host "confirming that " $recoveryvm "is registered on vcentre server before continuing -"
                $VMwaiter = get-vm $recoveryvm -erroraction silentlycontinue
                Sleep 5
                }
                until ($VMwaiter)

# start the VM up and answer the VM startup question
        get-vm $RecoveryVM | start-vm  -Confirm:$false -ErrorAction SilentlyContinue
            Sleep 20
        get-vm $RecoveryVM | Get-VMQuestion | Set-VMQuestion -Option button.uuid.copiedTheVM -Confirm:$false -ErrorAction SilentlyContinue



Write-host "VM has been started on flexclone Volume - beginning Storage vmotion to" $recoveryVMparentstorage " you can begin using the VM now"

#svmotion the VM back to the original location
  get-vm $RecoveryVM | move-vm -Datastore $RecoveryVMParentStorage -DiskStorageFormat Thin -VMotionPriority High
 


#Wait for the VM to complete svmotion
    do {
        $VMwaiter = get-vm $recoveryvm | get-datastore | Where-object {($_.name -notlike "*swap*") -and ($_.name -notlike "*srm*")}
        Write-host  "waiting for VM to complete svmotioning"
        sleep 10
        }
        until ($vmwaiter -like $RecoveryVMParentStorage)


#Trigger a SIS on the original volume
start-ncsis -path $netappvol -scan

#cleanup + remove recovery volume from ESXi Host and export & Volume from filer
Remove-Datastore -VMHost $recoveryhost -Datastore $FlexcloneVolname -Confirm:$false
#Determine the export policy Name - if its default then abort
$exportpolicyName = Get-NcVol $FlexcloneVolname |  select @{n="PolicyName"; E={ $_.VolumeExportAttributes.policy}}
 If ($exportpolicyName.policyname -notlike "*Default*"){
  remove-ncnfsexport -paths /$FlexcloneVolname -Confirm:$false
  Dismount-NcVol -Name $FlexcloneVolname -Confirm:$false
  set-ncvol $FlexcloneVolname -Offline -Confirm:$false
  Remove-NcVol $FlexcloneVolname -confirm:$false
  get-ncexportpolicy | Where-object {$_.PolicyName -like $exportpolicyname.policyname} | Remove-NcExportPolicy -Confirm:$false
    }

 Else{
 write-host "Trying to modify Default policy - Aborting"
 Pause
 }











Monday, August 25, 2014

Find the ILO IP of a HP ESXi Server through the CLI

Find the ILO IP of a HP ESXi Server through the CLI

cd /opt/hp/tools

./hponcfg -w /tmp/ilo_config.txt

Open /tmp/ilo_config.txt

Wednesday, January 29, 2014


Neatened version of snapshot reporting scrip 

import-module dataontap
$HourlyResultsTooMany= @()
$HourlyResultsTooFew= @()
$HourlyResultsNone= @()

$filers = "filer1,filer2,filer3,filer4,filer5,filer6"
$filers | foreach-object {
    #write-host $_
    connect-nacontroller $_
    $vmvols = get-NaVol | Where-Object { ($_.name -like "*vmnfs*" -or $_.name -like "*vmwaredata*") -and -not ($_.name -like "*m" -or $_.name -like "*m2" -or $_.name -like "*page" -or $_.name -like "*srmph"  -or $_.name -like "*swap" -or $_.name -like "*sw" -or $_.name -like "*vdi*" -or $_.name -like "*NonProd" -or $_.name -like "*filer1syslog"  -or $_.name -like "*filer2vdisys"  -or $_.name -like "*filer40*") }
    $vmvolc = $vmvols | measure-object
    if ($vmvolc.count -gt 0) {
        $vmvols | ForEach-Object {
            $vmsnaps = Get-NaSnapshot $_.name | Where-Object { ($_.name -like "smvi*") -and ($_.name -like "*hourly*") -and ($_.name -notlike "*appsercvr*")} | measure-object
            write-host "volume: " $_.name " Snapshots: " $vmsnaps.count
             if ($vmsnaps.Count -eq 0) {
                   
                      $HourlyResultsNone += New-Object psobject -Property @{
                                           
                                            'Volume' = $_.name
                   
                                       }

                    } 
             if ($vmsnaps.Count -ge 25 ) {
                   
                     $HourlyResultsTooMany += New-Object psobject -Property @{
                            
                                            'Volume' = $_.name
                                            'No Of Snapshots' = $vmsnaps.count
                                            }                   
                       }
             if ($vmsnaps.Count -lt 24 ) {
                   
                     $HourlyResultsTooFew += New-Object psobject -Property @{
                            
                                            'Volume' = $_.name
                                            'No Of Snapshots' = $vmsnaps.count
                                        }
                    }
        }
    }
}
If ( $DailyResultsNone.count -ge 0) {
                    Send-MailMessage -From "someone@companyname.ie" -To "someone@companyname.ie" -Subject 'Hourly Snapshot Alert , Some Volumes do not have any Hourly snapshots' -Body ( $HourlyResultsNone | Out-String )
                     }

If ( $DailyResultsTooFew.count -ge 0) {
                     Send-MailMessage -From "someone@companyname.ie" -To "someone@companyname.ie" -Subject 'Hourly Snapshot Alert , Some Volumes do not have enough Hourly snapshots' -Body ( $HourlyResultsTooFew | Out-String )
                     }
                   
If ( $DailyResultsTooMany.count -ge 0) {
                     Send-MailMessage -From "someone@companyname.ie" -To "someone@companyname.ie" -Subject 'Hourly Snapshot Alert , Some Volumes have too many Hourly snapshots' -Body ( $HourlyResultsTooMany | Out-String )
                     }

Thursday, January 23, 2014

Find volumes without autodelete or autosize enabled

powershell script to loop through each of the filers looking for any VMnfs volume which did not have the autosize enabled and was not able to autogrow


import-module dataontap
$results= @()
$filers = "Filer1","Filer2","Filer3","Filer4","Filer5","Filer6"
$filers | foreach-object {
    write-host $_
    connect-nacontroller $_
    $vmvols = get-NaVol | Where-Object { ($_.name -like "*vmnfs*" -or $_.name -like "*vmwaredata*" -or $_.name -like "*VDI*" ) -and -not ($_.name -like "*m" -or $_.name -like "*m2" -or $_.name -like "*page" -or $_.name -like "*srmph"  -or $_.name -like "*swap" -or $_.name -like "*sw" -or $_.name -like "*vdi*" -or $_.name -like "*NonProd" -or $_.name -like "*filer1vmnfsvolsyslog"  -or $_.name -like "*filer2vmnfsvolvdisys"  -or $_.name -like "*filer3vmnfsvol0*") }
    foreach ($volume in $vmvols) {
        $VolumeName=$volume.name
        $volumeSize=$volume.SizeTotal
        $VolumeSizeAvailable=$volume.SizeAvailable
        $autogrow = Get-NaVolAutosize -name $volume
        $AutogrowEnabled = $autogrow.isenabled
        $SnapshotAutodelete = Get-nasnapshotautodelete $volume
        }

        If  (($AutogrowEnabled -notlike "true" ) -or ($SnapshotAutodelete[4].OptionValue -notlike "on") )
        {

       
        $results += New-Object psobject -Property @{
                                       
                                        'Volume' = $volume
                                        'AutogrowEnabled' = $autogrowEnabled
                                        'SnapshotAutodelete' = $SnapshotAutodelete[4].OptionValue
                                       }
       }
}


Friday, October 11, 2013

WMI Filter for applying GPO to all instances of internet explorer where the version is less than 9.0

Create WMI filter -
SELECT * FROM CIM_DataFile WHERE Filename = 'iexplore' AND Path = '\\Program Files\\Internet Explorer\\' AND version <'9.0'

Thursday, July 25, 2013

Powershell script to age out Netapp snapshots

I had a an incident where i had to recreate the SMVI jobs on one of our Filers , we have a requirement to keep 26 days of backups online.
As always space was at a premium so What i wanted to do was to delete the old version of the SMVI
Snapshot each time after the new snapshot was taken...

so i created a script which loops through decreasing the value of the number of backups we want to keep

$days = -26
for ($loops = 26;$loops -ge 0; $loops --)
 {
  $BackupstoKeep = (get-date).adddays($days)
  Connect-nacontroller "Filer1"
  Get-Navol | Get-NaSnapshot | where-object { $_.name -like "smvi_*" -and $_.created -lt $Backupstokeep }  | remove-nasnapshot
  Connect-nacontroller "Filer2"
  Get-Navol | Get-NaSnapshot | where-object { $_.name -like "smvi_*" -and $_.created -lt $Backupstokeep }  | remove-nasnapshot
  $days++
 
Start-sleep 86400
}

Wednesday, July 10, 2013

Enable SSH on all hosts and set the policy to automatic

(in a non production lab obviously)

First , have a look at the current state of the SSH service on all of the hosts


Get-VMHost | Get-VMHostService | Where {$_.label -like "SSH"} | select VMhost , running , policy , Label

Then start the SSH service on each of your hosts 


Get-VMHost | Get-VMHostService | Where {$_.label -like "SSH"} | Start-VMHostService

Then ensure that it starts up each time on startup

Get-VMHost | Get-VMHostService | Where {$_.label -like "SSH"} | Set-VMHostService -Policy Automatic