## blog.schmitouille.net ## PowerCLI Toolbox - r3 Import-Module VMware.VimAutomation.Core Add-Type -AssemblyName System.Windows.Forms [System.Windows.Forms.Application]::EnableVisualStyles() $fileExpl = New-Object System.Windows.Forms.SaveFileDialog $fileExpl.ValidateNames = $true $fileExpl.CreatePrompt = $false $fileExpl.OverwritePrompt = $true $fileExpl.RestoreDirectory = $false $fileExpl.InitialDirectory = "$env:userprofile" function menu { Write-Host "PowerCLI Toolbox release 3 - Main Menu" -ForegroundColor "Green" Write-Host "Logged on"$status.Name"as"$status.User`r`n Write-Host "Your last choice was:"$mode -ForegroundColor "Magenta"`r`n Write-Host "Choose an option."`r`n Write-Host "Hosts" -ForegroundColor "Yellow" Write-Host "1: Retrieve information about a specific vSphere host" Write-Host "2: Retrieve vSphere hosts version" Write-Host "3: Retrieve vSphere hosts based on uptime" Write-Host "4: Retrieve vSphere hosts based on CPU usage" Write-Host "5: Retrieve vSphere hosts based on RAM usage" Write-Host "6: Retrieve vSphere hosts with abnormal state"`r`n Write-Host "Virtual Machines" -ForegroundColor "Yellow" Write-Host "7: Retrieve virtual machines based on their name" Write-Host "8: Retrieve virtual machines based on number of virtual CPUs" Write-Host "9: Retrieve virtual machines based on RAM quantity" Write-Host "10: Retrieve virtual machines based on datastore usage" Write-Host "11: Retrieve virtual machines with KO VMware tools" Write-Host "12: Retrieve virtual machines with abnormal state"`r`n Write-Host "Datastores" -ForegroundColor "Yellow" Write-Host "13: Retrieve datastores under a specified free space threshold" Write-Host "14: Retrieve orphan virtual disk files" Write-Host "15: Retrieve datastores VMFS version"`r`n Write-Host "Snapshots" -ForegroundColor "Yellow" Write-Host "16: Retrieve snapshots older than a specified number of days"`r`n Write-Host "Any other value: Quit"`r`n $mode = Read-Host "Your choice" switch($mode){ "1" { specinfo } "2" { version } "3" { uptime } "4" { cpucharge } "5" { ramusage } "6" { vsabnormal } "7" { nameft } "8" { cputhres } "9" { ramthres } "10" { storethres } "11" { kotools } "12" { vmabnormal } "13" { dsfs } "14" { orphans } "15" { vmfsver } "16" { oldsnaps } } } function specinfo { clear Write-Host "Please input the server FQDN to retrieve some of its specs." -ForegroundColor "Cyan" $vsphere = Read-Host $vspecs = Get-VMHost $vsphere if ($?){ $gbramt = [math]::Round($vspecs.MemoryTotalGB,0) $gbramu = [math]::Round($vspecs.MemoryUsageGB,0) $vms = Get-VM -Location $vsphere $dss = Get-Datastore -RelatedObject $vsphere Write-Host "`r`nHardware Server Specs for"$vspecs.Name -ForegroundColor "Yellow" Write-Host "Model:"$vspecs.Model Write-Host "CPU Model:"$vspecs.ProcessorType Write-Host "No. cores:"$vspecs.NumCpu Write-Host "Total CPU frequency (MHz):"$vspecs.CpuTotalMhz Write-Host "Total RAM available (GB):"$gbramt Write-Host "Used RAM (GB):"$gbramu Write-Host "`r`nVMware Server Information for"$vspecs.Name -ForegroundColor "Yellow" Write-Host "Running vSphere version"$vspecs.Version"build"$vspecs.Build Write-Host "Power state:"$vspecs.PowerState.ToString().SubString(7,2) Write-Host "Connection state:"$vspecs.ConnectionState Read-Host -Prompt "`r`nPress Enter to continue." Write-Host "VM Information for"$vspecs.Name -ForegroundColor "Yellow" Write-Host "No. of VMs running on host:"$vms.Count`r`n foreach($vm in $vms){ Write-Host "Name:"$vm.Name"- No. CPU:"$vm.NumCpu"- RAM (GB):"$vm.MemoryGB } Read-Host -Prompt "`r`nPress Enter to continue." Write-Host "Storage Information for"$vspecs.Name -ForegroundColor "Yellow" Write-Host "No. of datastores attached to host:"$dss.Count`r`n foreach($ds in $dss){ $maxgb = [math]::Round($ds.CapacityGB,0) $freegb = [math]::Round($ds.FreeSpaceGB,0) $ratio = [math]::Round($freegb/$maxgb*100,1) Write-Host "Name:"$ds.Name"- Capacity (GB):"$maxgb" - Free (GB): "$freegb" - % free: "$ratio } Read-Host -Prompt "`r`nPress Enter to continue." clear } else { Write-Host "Couldn't retrieve $vsphere server information." -ForegroundColor "Red" } menu } function version { clear $global:tempfile = "$env:temp\temp-vspherevers.csv" $dump = "Server Name,Version,Build" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all hosts on $vcenter...`r`n" -ForegroundColor "Cyan" $vspheres = Get-VMHost foreach($vsphere in $vspheres){ Write-Host "Host:"$vsphere.Name"- Version:"$vsphere.Version"- Build:"$vsphere.Build $dump = $vsphere.Name+","+$vsphere.Version+","+$vsphere.Build Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function uptime { clear $global:tempfile = "$env:temp\temp-uptime.csv" $dump = "Host,Uptime (days)" $today = Get-Date Add-Content -Value $dump -Path $tempfile Write-Host "Retrieve vSphere hosts that have been up for between X and Y days" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $vspheres = Get-VMHost foreach($vsphere in $vspheres){ $nodays = ($today - $vsphere.ExtensionData.Runtime.BootTime).Days if($nodays -ge $xlimit -and $nodays -le $ylimit){ Write-Host "Host:"$vsphere.Name"- Uptime:"$nodays "days" $dump = $vsphere.name+","+$nodays Add-Content -Value $dump -Path $tempfile } } csvexport clear menu } function cpucharge { clear $global:tempfile = "$env:temp\temp-cpucharge.csv" $dump = "Host,UsedMHz,TotalMHz,Ratio" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving vSphere hosts that use between X and Y % of their CPU" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $hosts = Get-VMHost | Where-Object { ($_.CpuUsageMhz/$_.CpuTotalMhz)*100 -ge $xlimit -and ($_.CpuUsageMhz/$_.CpuTotalMhz)*100 -le $ylimit } foreach($vsphere in $hosts){ $ratio = [math]::Round(($vsphere.CpuUsageMhz/$vsphere.CpuTotalMhz)*100,1) Write-Host "Host:"$vsphere.Name"- CPU Usage (MHz):"$vsphere.CpuUsageMhz"- CPU Capacity (MHz):"$vsphere.CpuTotalMhz" - % usage:" $ratio $dump = $vsphere.Name+","+$vsphere.CpuUsageMhz+","+$vsphere.CpuTotalMhz+","+$ratio Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function ramusage { clear $global:tempfile = "$env:temp\temp-ramusage.csv" $dump = "Host,UsedRAM,TotalRAM,Ratio" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving vSphere hosts that use between X and Y % of their RAM" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $hosts = Get-VMHost | Where-Object { ($_.MemoryUsageGB/$_.MemoryTotalGB)*100 -ge $xlimit -and ($_.MemoryUsageGB/$_.MemoryTotalGB)*100 -le $ylimit } foreach($vsphere in $hosts){ $ratio = [math]::Round(($vsphere.MemoryUsageGB/$vsphere.MemoryTotalGB)*100,1) $usedGB = [math]::Round($vsphere.MemoryUsageGB,1) $totalGB = [math]::Round($vsphere.MemoryTotalGB,1) Write-Host "Host:"$vsphere.Name"- RAM Usage (GB):"$usedGB" - Total RAM (GB): "$totalGB" - % usage:" $ratio $dump = $vsphere.Name+","+$usedGB+","+$totalGB+","+$ratio Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function vsabnormal { clear $global:tempfile = "$env:temp\temp-vsabnormal.csv" $dump = "Host,Alarm,Timestamp" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all vSphere hosts that aren't on a green status..." -ForegroundColor "Cyan" Write-Host "Keep in mind that timestamps are UTC based." $hostnotok = Get-VMHost | Where-Object { $_.ExtensionData.OverallStatus -ne "green" } if($hostnotok -eq $null) { Write-Host "`r`nAll vSphere hosts are running in their normal state." } else { foreach($host in $hostnotok){ $hostalarm = $host.ExtensionData.TriggeredAlarmState Write-Host "`r`nAlarms for"$host.Name -ForegroundColor "Yellow" foreach($alarm in $hostalarm){ Write-Host (Get-AlarmDefinition -id $alarm.Alarm).Name"- Triggered On:"$alarm.Time $dump = $host.VMHost.Name+","+(Get-AlarmDefinition -id $alarm.Alarm).Name+","+$alarm.Time Add-Content -Value $dump -Path $tempfile } } } csvexport clear menu } function nameft { clear $global:tempfile = "$env:temp\temp-nameft.csv" $dump = "VM,Host" Add-Content -Value $dump -Path $tempfile Write-Host "Please input a string to look for in the virtual machine name. * wildcards can be used." -ForegroundColor "Cyan" $ft = Read-Host Write-Host "`r`n" $vms = Get-VM | Where-Object { $_.Name -like $ft } foreach($vm in $vms){ Write-Host "Name:"$vm.Name"- Host:"$vm.VMHost.Name $dump = $vm.Name+","+$vm.VMHost.Name Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function cputhres { clear $global:tempfile = "$env:temp\temp-cputhres.csv" $dump = "VM,No. CPUs,Host" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieve virtual machines that have between X and Y virtual CPUs" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $vms = Get-VM | Where-Object { $_.NumCpu -ge $xlimit -and $_.NumCpu -le $ylimit } foreach($vm in $vms){ Write-Host "Name:"$vm.Name"- No. vCPU:"$vm.NumCpu"- Host:"$vm.VMHost.Name $dump = $vm.Name+","+$vm.NumCpu+","+$vm.VMHost.Name Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function ramthres { clear $global:tempfile = "$env:temp\temp-ramthres.csv" $dump = "VM,RAM (GB),Host" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieve virtual machines that have between X and Y GB of RAM" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $vms = Get-VM | Where-Object { $_.MemoryGB -ge $xlimit -and $_.MemoryGB -le $ylimit } foreach($vm in $vms){ Write-Host "Name:"$vm.Name"- RAM (GB):"$vm.MemoryGB"- Host:"$vm.VMHost.Name $dump = $vm.Name+","+$vm.MemoryGB+","+$vm.VMHost.Name Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function storethres { clear $global:tempfile = "$env:temp\temp-storethres.csv" $dump = "VM,Space Provisioned (GB),Host" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieve virtual machines that use between X and Y GB on their datastores" [uint16]$xlimit = Read-Host "X" [uint16]$ylimit = Read-Host "Y" Write-Host "`r`nProcessing.`r`n" -ForegroundColor "Cyan" $vms = Get-VM | Where-Object { $_.ProvisionedSpaceGB -ge $xlimit -and $_.ProvisionedSpaceGB -le $ylimit } foreach($vm in $vms){ $spacegb = [math]::Round($vm.ProvisionedSpaceGB,1) Write-Host "Name:"$vm.Name"- RAM (GB):"$spacegb" - Host:"$vm.VMHost.Name $dump = $vm.Name+","+$spacegb+","+$vm.VMHost.Name Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function kotools { clear $global:tempfile = "$env:temp\temp-toolstatus.csv" $dump = "VM,OS,Tools Status" Add-Content -Value $dump -Path $tempfile Write-Host "Parsing all VMware tools statuses...`r`n" -ForegroundColor "Cyan" $vms = Get-VM Write-Host "The following machines have outdated VMware tools." -ForegroundColor "Yellow" foreach($vm in $vms){ if ($VM.ExtensionData.Guest.ToolsStatus -eq 'toolsOld'){ Write-Host "Name:"$vm.Name"- Guest OS:"$vm.Guest.OSFullName $dump = $vm.Name+","+$vm.Guest.OSFullName+",Tools not up to date" Add-Content -Value $dump -Path $tempfile } } Write-Host "`r`nThe following machines don't currently run VMware tools." -ForegroundColor "Yellow" foreach($vm in $vms){ if ($VM.ExtensionData.Guest.ToolsStatus -like 'toolsNot*'){ Write-Host "Name:"$vm.Name"- Guest OS:"$vm.Guest.OSFullName $dump = $vm.Name+","+$vm.Guest.OSFullName+",Tools not working or installed" Add-Content -Value $dump -Path $tempfile } } csvexport clear menu } function vmabnormal { clear $global:tempfile = "$env:temp\temp-abnormal.csv" $dump = "VM,Host,Alarm,Timestamp" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all virtual machines that aren't on a green status..." -ForegroundColor "Cyan" Write-Host "Keep in mind that timestamps are UTC based." $vmnotok = Get-VM | Where-Object { $_.ExtensionData.OverallStatus -ne "green" } if($hostnotok -eq $null) { Write-Host "`r`nAll virtual machines are running in their normal state." } else { foreach($vm in $vmnotok){ $vmalarm = $vm.ExtensionData.TriggeredAlarmState Write-Host "`r`nAlarms for"$vm.Name -ForegroundColor "Yellow" foreach($alarm in $vmalarm){ Write-Host (Get-AlarmDefinition -id $alarm.Alarm).Name"- Triggered On:"$alarm.Time $dump = $vm.Name+","+$vm.VMHost.Name+","+(Get-AlarmDefinition -id $alarm.Alarm).Name+","+$alarm.Time Add-Content -Value $dump -Path $tempfile } } } csvexport clear menu } function dsfs { clear $global:tempfile = "$env:temp\temp-dsfs.csv" $dump = "Datastore Name,Capacity,Free,%" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all datastores on $vcenter..." -ForegroundColor "Cyan" $dslist = Get-Datastore Write-Host "Done.`r`n" [uint16]$limit = Read-Host "% free space limit" Write-Host "" foreach($ds in $dslist){ $maxgb = [math]::Round($ds.CapacityGB,0) $freegb = [math]::Round($ds.FreeSpaceGB,0) $ratio = [math]::Round($freegb/$maxgb*100,0) if($ratio -le $limit) { Write-Host "Name:"$ds.Name"- Capacity (GB):"$maxgb" - Free (GB): "$freegb" - % free: "$ratio $dump = $ds.Name+","+$maxgb+","+$freegb+","+$ratio Add-Content -Value $dump -Path $tempfile } } csvexport clear menu } function orphans { $vmdkds=@() $vmdkvm=@() clear Write-Host "Parsing all datastores and VMDKs. This might take a while.`r`n" -ForegroundColor "Cyan" $dslist = Get-View -ViewType Datastore | select Name foreach($ds in $dslist) { $vmdks = Get-HardDisk -Datastore $ds.Name foreach($vmdk in $vmdks) { $vmdkfilename = @{Filename = $vmdk.Filename} $vmdkentry = New-Object PSObject -Property $vmdkfilename $vmdkds+=$vmdkentry } } $vmlist = Get-View -ViewType VirtualMachine | select Name foreach($vm in $vmlist) { $vmdks = Get-HardDisk -VM $vm.Name foreach($vmdk in $vmdks) { $vmdkfilename = @{Filename = $vmdk.Filename} $vmdkentry = New-Object PSObject -Property $vmdkfilename $vmdkvm+=$vmdkentry } } Write-Host "Done. Now processing. Please wait.`r`n" -ForegroundColor "Cyan" Compare-Object $vmdkvm $vmdkds -Property Filename | Where-Object { $_.SideIndicator -eq "=>" } | foreach-object { Write-Host $_.InputObject } Read-Host -Prompt "`r`nPress Enter to continue." clear menu } function vmfsver { clear $global:tempfile = "$env:temp\temp-vmfsver.csv" $dump = "Datastore Name,Version" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all datastores on $vcenter..." -ForegroundColor "Cyan" $dslist = Get-Datastore | Where-Object { $_.Type -eq "VMFS" } Write-Host "Done.`r`n" foreach ($ds in $dslist){ Write-Host "Datastore:"$ds.Name"- VMFS Version:"$ds.FileSystemVersion $dump = $ds.Name+","+$ds.FileSystemVersion Add-Content -Value $dump -Path $tempfile } csvexport clear menu } function oldsnaps { clear $snapcount = 0 $today = Get-Date $global:tempfile = "$env:temp\temp-oldsnaps.csv" $dump = "VM,Snapshot Name,Date,Size (GB)" Add-Content -Value $dump -Path $tempfile Write-Host "Retrieving all virtual machines on $vcenter...`r`n" -ForegroundColor "Cyan" $vms = Get-VM [uint16]$limit = Read-Host "Retrieve snapshots older than X days" Write-Host "`r`nRetrieving and filtering all snapshots...`r`n" -ForegroundColor "Cyan" foreach($vm in $vms){ $snaps = Get-Snapshot $vm foreach($snap in $snaps){ if($snap.Created -lt $today.AddDays(-$limit)) { $snapcount++ if($snap.IsCurrent -eq $true) { Write-Host "This is the current snapshot for this VM." -ForegroundColor "Red" } $size = [math]::Round($snap.SizeGB,0) Write-Host "VM:"$vm.Name Write-Host "Snapshot Name:"$snap.Name Write-Host "Created On:"$snap.Created Write-Host "Size (GB):"$size`r`n $dump = $vm.Name+","+$snap.Name+","+$snap.Created+","+$size Add-Content -Value $dump -Path $tempfile } } } if($snapcount -eq 0){ Write-Host "There are no snapshots older than $limit days." -ForegroundColor "Yellow" } csvexport clear menu } function csvexport { $exportyn = Read-Host "`r`nWould you like to export the data in a CSV file ? (y/n)" if($exportyn -eq "y"){ $fileExpl.DefaultExt = "csv" $fileExpl.Filter = "Comma-separated values file (*.csv)|*.csv" $fileExpl.Title = "Export data to CSV file" $fileExpl.Filename = "" $fileExpl.ShowDialog() | out-null if ($fileExpl.Filename -ne "") { Copy-Item $global:tempfile -Destination $fileExpl.Filename if ($?){ Remove-Item $global:tempfile ; Write-Host "Exported successfully to"$fileExpl.Filename -ForegroundColor "Green" } else { Write-Host "There was an issue exporting the data in a CSV file." -ForegroundColor "Red" } } else { Remove-Item $global:tempfile ; Write-Host "Aborted data export." -ForegroundColor "Red" } } else { Remove-Item $global:tempfile } Read-Host -Prompt "`r`nPress Enter to continue." } clear $originaltitle = $host.ui.RawUI.WindowTitle $host.ui.RawUI.WindowTitle = "PowerCLI Toolbox r3" $mode = "None." Write-Host "PowerCLI Toolbox r3" Write-Host "===================`r`n" $vcenter = Read-Host "vCenter to connect to" $status = Connect-VIServer $vcenter if($?){ clear menu Write-Host "Disconnecting." Disconnect-VIServer $vCenter -Confirm:$false | Out-Null } Write-Host "Bye." $host.ui.RawUI.WindowTitle = $originaltitle