diff --git a/Modules/Get-VMmaxIOPS.psm1 b/Modules/Get-VMmaxIOPS.psm1 new file mode 100644 index 0000000..8ef86e3 --- /dev/null +++ b/Modules/Get-VMmaxIOPS.psm1 @@ -0,0 +1,85 @@ +function Get-VMmaxIOPS { +<# + + .SYNOPSIS + Report VM Disk IOPS of VMs + + .DESCRIPTION + This Function will Create a VM Disk IOPS Report + + .Example + Get-VM TST* | Get-VMmaxIOPS -Minutes 60 | FT -Autosize + + .Example + $SampleVMs = Get-VM "TST*" + Get-VMmaxIOPS -VMs $SampleVMs -Minutes 60 + + .PARAMETER VMs + Specify the VMs + + .PARAMETER Minutes + Specify the Minutes to report (10080 is one Week) + + .Notes + NAME: Get-VMmaxIOPS.ps1 + LASTEDIT: 08/23/2016 + VERSION: 1.1 + KEYWORDS: VMware, vSphere, ESXi, IOPS + + .Link + http://mycloudrevolution.com/ + +#Requires PS -Version 4.0 +#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory=$true, ValueFromPipeline=$True, Position=0)] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] + $VMs, + [Parameter(Mandatory=$false, Position=1)] + [int] $Minutes = 30 +) + +Process { + + #region: Global Definitions + [int]$TimeRange = "-" + $Minutes + #endregion + + #region: Creating Metrics + Write-Debug "Starting to Create Metrics..." + $metrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average" + $start = (Get-Date).AddMinutes($TimeRange) + $stats = Get-Stat -Stat $metrics -Entity $VMs -Start $start + #endregion + + #region: Creating HD-Tab + Write-Debug "Starting to Create HD-Tab..." + $hdTab = @{} + foreach($hd in (Get-Harddisk -VM $VMs)){ + $controllerKey = $hd.Extensiondata.ControllerKey + $controller = $hd.Parent.Extensiondata.Config.Hardware.Device | where{$_.Key -eq $controllerKey} + $hdTab[$hd.Parent.Name + "/scsi" + $controller.BusNumber + ":" + $hd.Extensiondata.UnitNumber] = $hd.FileName.Split(']')[0].TrimStart('[') + } + #endregion + + #region: Creating Reports + Write-Debug "Starting to Process IOPS Report..." + $reportPerf = @() + $reportPerf = $stats | Group-Object -Property {$_.Entity.Name},Instance | %{ + New-Object PSObject -Property @{ + VM = $_.Values[0] + Disk = $_.Values[1] + IOPSMax = ($_.Group | ` + Group-Object -Property Timestamp | ` + %{$_.Group[0].Value + $_.Group[1].Value} | ` + Measure-Object -Maximum).Maximum + Datastore = $hdTab[$_.Values[0] + "/"+ $_.Values[1]] + } + } + $reportPerf | Select-Object VM, Disk, Datastore, IOPSMax + #endregion + } +} \ No newline at end of file diff --git a/Modules/Start-UNMAP.psm1 b/Modules/Start-UNMAP.psm1 new file mode 100644 index 0000000..a8e9896 --- /dev/null +++ b/Modules/Start-UNMAP.psm1 @@ -0,0 +1,99 @@ +function Start-UNMAP { +<# + .SYNOPSIS + Process SCSI UNMAP on VMware Datastores + + .DESCRIPTION + This Function will process SCSI UNMAP on VMware Datastores via ESXCLI -V2 + + .Example + Start-UNMAP -ClusterName myCluster -DSWildcard *RAID5* + + .Example + Start-UNMAP -ClusterName myCluster -DSWildcard *RAID5* -Verbose -WhatIf + + .Notes + NAME: Start-UNMAP.psm1 + AUTHOR: Markus Kraus + LASTEDIT: 23.09.2016 + VERSION: 1.0 + KEYWORDS: VMware, vSphere, ESXi, SCSI, VAAI, UNMAP + + .Link + http://mycloudrevolution.com/ + + #Requires PS -Version 4.0 + #Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} + #> + + [CmdletBinding(SupportsShouldProcess = $true,ConfirmImpact='High')] + param( + [Parameter(Mandatory=$true, Position=0)] + [String]$ClusterName, + [Parameter(Mandatory=$true, Position=1)] + [String]$DSWildcard + ) + Process { + $Validate = $true + #region: PowerCLI Session Timeout + Write-Verbose "Set Session Timeout ..." + $initialTimeout = (Get-PowerCLIConfiguration -Scope Session).WebOperationTimeoutSeconds + Set-PowerCLIConfiguration -Scope Session -WebOperationTimeoutSeconds -1 -Confirm:$False | Out-Null + #endregion + + #region: Get Cluster + $Cluster = Get-Cluster -Name $ClusterName -ErrorAction SilentlyContinue + Write-Verbose "vSphere Cluster: $Cluster" + if (!$Cluster){Write-Error "No Cluster found!"; $Validate = $false} + #endregion + + #region: Get Hosts + $ClusterHosts = $Cluster | Get-VMHost -ErrorAction SilentlyContinue | where {$_.ConnectionState -eq "Connected" -and $_.PowerState -eq "PoweredOn"} + Write-Verbose "vSphere Cluster Hosts: $ClusterHosts" + if (!$ClusterHosts){Write-Error "No Hosts found!"; $Validate = $false} + #endregion + + #region: Get Datastores + $ClusterDataStores = $Cluster | Get-Datastore -ErrorAction SilentlyContinue | where {$_.Name -like $DSWildcard -and $_.State -eq "Available" -and $_.Accessible -eq "True"} + Write-Verbose "vSphere Cluster Datastores: $ClusterDataStores" + if (!$ClusterDataStores){Write-Error "No Datastores found!"; $Validate = $false} + #endregion + + #region: Process Datastores + if ($Validate -eq $true) { + Write-Verbose "Starting Loop..." + foreach ($ClusterDataStore in $ClusterDataStores) { + Write-Verbose "vSphere Datastore to Process: $ClusterDataStore" + $myHost = $ClusterHosts[(Get-Random -Maximum ($ClusterHosts).count)] + Write-Verbose "vSphere Host to Process: $myHost" + $esxcli2 = $myHost | Get-ESXCLI -V2 + $arguments = $esxcli2.storage.vmfs.unmap.CreateArgs() + $arguments.volumelabel = $ClusterDataStore + $arguments.reclaimunit = "256" + if ($PSCmdlet.ShouldProcess( $ClusterDataStore,"Starting UNMAP on $myHost")) { + $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() + try { + Write-Output "Starting UNMAP for $ClusterDataStore on $myHost..." + $esxcli2.storage.vmfs.unmap.Invoke($arguments) + } + catch { + Write-Output "A Error occured: " "" $error[0] "" + } + $stopwatch.Stop() + Write-Output "UNMAP duration: $($stopwatch.Elapsed.Minutes)" + } + + } + } + else { + Write-Error "Validation Failed. Processing Loop Skipped!" + } + #endregion + + #region: Revert PowerCLI Session Timeout + Write-Verbose "Revert Session Timeout ..." + Set-PowerCLIConfiguration -Scope Session -WebOperationTimeoutSeconds $initialTimeout -Confirm:$False | Out-Null + #endregion + } + +}