Merge remote-tracking branch 'refs/remotes/vmware/master'

This commit is contained in:
praveenmathamsetty
2016-12-02 08:22:25 +05:30
17 changed files with 2006 additions and 168 deletions

202
Modules/Backup-VCSA.psm1 Normal file
View File

@@ -0,0 +1,202 @@
Function Backup-VCSAToFile {
<#
.NOTES
===========================================================================
Created by: Brian Graf
Date: October 30, 2016
Organization: VMware
Blog: www.vtagion.com
Twitter: @vBrianGraf
===========================================================================
.SYNOPSIS
This function will allow you to create a full or partial backup of your
VCSA appliance. (vSphere 6.5 and higher)
.DESCRIPTION
Use this function to backup your VCSA to a remote location
.EXAMPLE
[VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword = "VMw@re123"
$Comment = "First API Backup"
$LocationType = "FTP"
$location = "10.144.99.5/vcsabackup-$((Get-Date).ToString('yyyy-MM-dd-hh-mm'))"
$LocationUser = "admin"
[VMware.VimAutomation.Cis.Core.Types.V1.Secret]$locationPassword = "VMw@re123"
PS C:\> Backup-VCSAToFile -BackupPassword $BackupPassword -LocationType $LocationType -Location $location -LocationUser $LocationUser -LocationPassword $locationPassword -Comment "This is a demo" -ShowProgress -FullBackup
.NOTES
Credit goes to @AlanRenouf for sharing the base of this function with me which I was able to take and make more robust as well as add in progress indicators
You must be connected to the CisService for this to work, if you are not connected, the function will prompt you for your credentials
If a -LocationType is not chosen, the function will default to FTP.
The destination location for a backup must be an empty folder (easiest to use the get-date cmdlet in the location)
-ShowProgress will give you a progressbar as well as updates in the console
-SeatBackup will only backup the config whereas -Fullbackup grabs the historical data as well
#>
param (
[Parameter(ParameterSetName=FullBackup)]
[switch]$FullBackup,
[Parameter(ParameterSetName=SeatBackup)]
[switch]$SeatBackup,
[ValidateSet('FTPS', 'HTTP', 'SCP', 'HTTPS', 'FTP')]
$LocationType = "FTP",
$Location,
$LocationUser,
[VMware.VimAutomation.Cis.Core.Types.V1.Secret]$LocationPassword,
[VMware.VimAutomation.Cis.Core.Types.V1.Secret]$BackupPassword,
$Comment = "Backup job",
[switch]$ShowProgress
)
Begin {
if (!($global:DefaultCisServers)){
[System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null
$Connection = Connect-CisServer $global:DefaultVIServer
} else {
$Connection = $global:DefaultCisServers
}
if ($FullBackup) {$parts = @("common","seat")}
if ($SeatBackup) {$parts = @("seat")}
}
Process{
$BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job
$CreateSpec = $BackupAPI.Help.create.piece.CreateExample()
$CreateSpec.parts = $parts
$CreateSpec.backup_password = $BackupPassword
$CreateSpec.location_type = $LocationType
$CreateSpec.location = $Location
$CreateSpec.location_user = $LocationUser
$CreateSpec.location_password = $LocationPassword
$CreateSpec.comment = $Comment
try {
$BackupJob = $BackupAPI.create($CreateSpec)
}
catch {
Write-Error $Error[0].exception.Message
}
If ($ShowProgress){
do {
$BackupAPI.get("$($BackupJob.ID)") | select id, progress, state
$progress = ($BackupAPI.get("$($BackupJob.ID)").progress)
Write-Progress -Activity "Backing up VCSA" -Status $BackupAPI.get("$($BackupJob.ID)").state -PercentComplete ($BackupAPI.get("$($BackupJob.ID)").progress) -CurrentOperation "$progress% Complete"
start-sleep -seconds 5
} until ($BackupAPI.get("$($BackupJob.ID)").progress -eq 100 -or $BackupAPI.get("$($BackupJob.ID)").state -ne "INPROGRESS")
$BackupAPI.get("$($BackupJob.ID)") | select id, progress, state
}
Else {
$BackupJob | select id, progress, state
}
}
End {}
}
Function Get-VCSABackupJobs {
<#
.NOTES
===========================================================================
Created by: Brian Graf
Date: October 30, 2016
Organization: VMware
Blog: www.vtagion.com
Twitter: @vBrianGraf
===========================================================================
.SYNOPSIS
Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed (vSphere 6.5 and higher)
.DESCRIPTION
Get-VCSABackupJobs returns a list of all backup jobs VCSA has ever performed
.EXAMPLE
PS C:\> Get-VCSABackupJobs
.NOTES
The values returned are read as follows:
YYYYMMDD-hhmmss-vcsabuildnumber
You can pipe the results of this function into the Get-VCSABackupStatus function
Get-VCSABackupJobs | select -First 1 | Get-VCSABackupStatus <- Most recent backup
#>
param (
[switch]$ShowNewest
)
Begin {
if (!($global:DefaultCisServers)){
[System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null
$Connection = Connect-CisServer $global:DefaultVIServer
} else {
$Connection = $global:DefaultCisServers
}
}
Process{
$BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job
try {
if ($ShowNewest) {
$results = $BackupAPI.list()
$results[0]
} else {
$BackupAPI.list()
}
}
catch {
Write-Error $Error[0].exception.Message
}
}
End {}
}
Function Get-VCSABackupStatus {
<#
.NOTES
===========================================================================
Created by: Brian Graf
Date: October 30, 2016
Organization: VMware
Blog: www.vtagion.com
Twitter: @vBrianGraf
===========================================================================
.SYNOPSIS
Returns the ID, Progress, and State of a VCSA backup (vSphere 6.5 and higher)
.DESCRIPTION
Returns the ID, Progress, and State of a VCSA backup
.EXAMPLE
PS C:\> $backups = Get-VCSABackupJobs
$backups[0] | Get-VCSABackupStatus
.NOTES
The BackupID can be piped in from the Get-VCSABackupJobs function and can return multiple job statuses
#>
Param (
[parameter(ValueFromPipeline=$True)]
[string[]]$BackupID
)
Begin {
if (!($global:DefaultCisServers)){
[System.Windows.Forms.MessageBox]::Show("It appears you have not created a connection to the CisServer. You will now be prompted to enter your vCenter credentials to continue" , "Connect to CisServer") | out-null
$Connection = Connect-CisServer $global:DefaultVIServer
} else {
$Connection = $global:DefaultCisServers
}
$BackupAPI = Get-CisService com.vmware.appliance.recovery.backup.job
}
Process{
foreach ($id in $BackupID) {
$BackupAPI.get("$id") | select id, progress, state
}
}
End {}
}

View File

@@ -0,0 +1,216 @@
function Recommend-Sizing {
<#
.NOTES
===========================================================================
Created by: Markus Kraus
Twitter: @VMarkus_K
Private Blog: mycloudrevolution.com
===========================================================================
Changelog:
2016.11 ver 1.0 Base Release
2016.11 ver 1.1 Optional Stats Collection.
===========================================================================
External Code Sources:
http://www.lucd.info/2011/04/22/get-the-maximum-iops/
https://communities.vmware.com/thread/485386
===========================================================================
Tested Against Environment:
vSphere Version: 5.5 U2
PowerCLI Version: PowerCLI 6.3 R1, PowerCLI 6.5 R1
PowerShell Version: 4.0, 5.0
OS Version: Windows 8.1, Server 2012 R2
===========================================================================
Keywords vSphere, ESXi, VM, Storage, Sizing
===========================================================================
.DESCRIPTION
This Function collects Basic vSphere Informations for a Hardware Sizing Recomamndation. Focus is in Compute Ressources.
.Example
Recommend-Sizing -ClusterNames Cluster01, Cluster02 -Stats -StatsRange 60 -Verbose
.Example
Recommend-Sizing -ClusterNames Cluster01, Cluster02
.Example
Recommend-Sizing -ClusterNames Cluster01
.PARAMETER ClusterNames
List of your vSphere Cluser Names to process.
.PARAMETER Stats
Enables Stats Collection.
Warning: At the moment this is only tested and supported with vSphere 5.5!
.PARAMETER StatsRange
Time Range in Minutes for the Stats Collection.
Default is 24h.
#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=$False, Position=0)]
[Array] $ClusterNames,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=2)]
[switch] $Stats,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=2)]
[int] $StatsRange = 1440
)
Begin {
if ($Stats) {
Write-Warning "Stats Collection enabled.`nAt the moment this is only tested and supported with vSphere 5.5"
[int]$TimeRange = "-" + $StatsRange
}
$Validate = $True
#region: Check Clusters
Write-Verbose "$(Get-Date -Format G) Starting Cluster Validation..."
foreach ($ClusterName in $ClusterNames) {
$TestCluster = Get-Cluster -Name $ClusterName -ErrorAction SilentlyContinue -Verbose:$False
if(!($TestCluster)){
Write-Warning "No Custer found wth Name $ClusterName!"
$Validate = $False
}
elseif ($TestCluster.count -gt 1) {
Write-Warning "Multiple Custers found wth Name $ClusterName!`nUse a List of explicit Cluster Names: Recommend-Sizing -ClusterNames Cluster01, Cluster02 "
$Validate = $False
}
}
Write-Verbose "$(Get-Date -Format G) Cluster Validation completed"
#endregion
}
Process {
$MyView = @()
if ($Validate -eq $True) {
foreach ($ClusterName in $ClusterNames) {
#region: Get Cluster Objects
Write-Verbose "$(Get-Date -Format G) Collect $ClusterName Cluster Objects..."
$Cluster = Get-Cluster -Name $ClusterName -Verbose:$False
$ClusterVMs = $Cluster | Get-VM -Verbose:$False
$ClusterVMsPoweredOn = $ClusterVMs | where {$_.PowerState -eq "PoweredOn"}
$ClusterDatastores = $Cluster | Get-Datastore -Verbose:$False
$ClusterHosts = $Cluster | Get-VMHost -Verbose:$False
$HostsAverageMemoryUsageGB = [math]::round( ($ClusterHosts | Measure-Object -Average -Property MemoryUsageGB).Average,1 )
$HostsAverageMemoryUsage = $([math]::round( (($ClusterHosts | Measure-Object -Average -Property MemoryUsageGB).Average / ($ClusterHosts | Measure-Object -Average -Property MemoryTotalGB).Average) * 100,1 ))
$HostsAverageCpuUsageMhz = [math]::round( ($ClusterHosts | Measure-Object -Average -Property CpuUsageMhz).Average,1 )
$HostsAverageCpuUsage = $([math]::round( (($ClusterHosts | Measure-Object -Average -Property CpuUsageMhz).Average / ($ClusterHosts | Measure-Object -Average -Property CpuTotalMhz).Average) * 100,1 ))
Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Cluster Objects completed"
#endregion
#region: CPU Calculation
Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) CPU Details..."
$VMvCPUs = ($ClusterVMs | Measure-Object -Sum -Property NumCpu).sum
$LogicalThreads = $Cluster.ExtensionData.Summary.NumCpuThreads
$CpuCores = $Cluster.ExtensionData.Summary.NumCpuCores
$vCPUpCPUratio = [math]::round( $VMvCPUs / $LogicalThreads,1 )
Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) CPU Details completed."
#endregion
#region: Memory Calculation
Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Memory Details..."
$AllocatedVMMemoryGB = [math]::round( ($ClusterVMs | Measure-Object -Sum -Property MemoryGB).sum )
$PhysicalMemory = [math]::round( $Cluster.ExtensionData.Summary.TotalMemory / 1073741824,1 )
$MemoryUsage = [math]::round( ($AllocatedVMMemoryGB / $PhysicalMemory) * 100 ,1 )
Write-Verbose "$(Get-Date -Format G) Collect $($Cluster.name) Memory Details completed"
#endregion
if ($Stats) {
#region: Creating Disk Metrics
Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics..."
$DiskMetrics = "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average"
$start = (Get-Date).AddMinutes($TimeRange)
$DiskStats = Get-Stat -Stat $DiskMetrics -Entity $ClusterVMsPoweredOn -Start $start -Verbose:$False
Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) IOPS Metrics completed"
#endregion
#region: Creating IOPS Reports
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report..."
$reportDiskPerf = @()
$reportDiskPerf = $DiskStats | Group-Object -Property {$_.Entity.Name},Instance | %{
New-Object PSObject -Property @{
IOPSMax = ($_.Group | `
Group-Object -Property Timestamp | `
%{$_.Group[0].Value + $_.Group[1].Value} | `
Measure-Object -Maximum).Maximum
}
}
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) IOPS Report completed"
#endregion
}
else {
Write-Verbose "$(Get-Date -Format G) Stats Cellocetion skipped..."
}
#region: Create VM Disk Space Report
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Disk Space Report..."
$reportDiskSpace = @()
foreach ($ClusterVM in $ClusterVMs){
$VMDKs = $ClusterVM | get-HardDisk -Verbose:$False
foreach ($VMDK in $VMDKs) {
if ($VMDK -ne $null){
[int]$CapacityGB = $VMDK.CapacityKB/1024/1024
$Report = [PSCustomObject] @{
CapacityGB = $CapacityGB
}
$reportDiskSpace += $Report
}
}
}
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Disk Space Report completed"
#endregion
#region: Create Datastore Space Report
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) Datastore Space Report..."
$DatastoreReport = @($ClusterDatastores | Select-Object @{N="CapacityGB";E={[math]::Round($_.CapacityGB,2)}}, @{N="FreeSpaceGB";E={[math]::Round($_.FreeSpaceGB,2)}}, @{N="UsedSpaceGB";E={[math]::Round($_.CapacityGB - $_.FreeSpaceGB,2)}})
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) Datastore Space Report completed"
#endregion
#region: Create Global Report
Write-Verbose "$(Get-Date -Format G) Process Global Report..."
$SizingReport = [PSCustomObject] @{
Cluster = $Cluster.name
HAEnabled = $Cluster.HAEnabled
DrsEnabled = $Cluster.DrsEnabled
Hosts = $Cluster.ExtensionData.Summary.NumHosts
HostsAverageMemoryUsageGB = $HostsAverageMemoryUsageGB
HostsAverageMemoryUsage = "$HostsAverageMemoryUsage %"
HostsAverageCpuUsageMhz = $HostsAverageCpuUsageMhz
HostsAverageCpuUsage = "$HostsAverageCpuUsage %"
PhysicalCPUCores = $CpuCores
LogicalCPUThreads = $LogicalThreads
VMs = $ClusterVMs.count
ActiveVMs = $ClusterVMsPoweredOn.count
VMvCPUs = $VMvCPUs
vCPUpCPUratio = "$vCPUpCPUratio : 1"
PhysicalMemoryGB = $PhysicalMemory
AllocatedVMMemoryGB = $AllocatedVMMemoryGB
ClusterMemoryUsage = "$MemoryUsage %"
SumVMDiskSpaceGB = [math]::round( ($reportDiskSpace | Measure-Object -Sum -Property CapacityGB).sum, 1 )
SumDatastoreSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property CapacityGB).sum, 1 )
SumDatastoreUsedSpaceGB = [math]::round( ($DatastoreReport | Measure-Object -Sum -Property UsedSpaceGB).sum, 1 )
SumMaxVMIOPS = [math]::round( ($reportDiskPerf | Measure-Object -Sum -Property IOPSMax).sum, 1 )
AverageMaxVMIOPs = [math]::round( ($reportDiskPerf | Measure-Object -Average -Property IOPSMax).Average,1 )
}
$MyView += $SizingReport
Write-Verbose "$(Get-Date -Format G) Process Global Report completed"
#endregion
}
}
Else {
Write-Error "Validation Failed! Processing Skipped"
}
}
End {
$MyView
}
}

View File

@@ -7,58 +7,90 @@
Twitter: @vBrianGraf
VMware Blog: blogs.vmware.com/powercli
Personal Blog: www.vtagion.com
Modified on: 10/11/2016
Modified by: Erwan Quélin
Twitter: @erwanquelin
Github: https://github.com/equelin
===========================================================================
.DESCRIPTION
This function will allow users to view the VMCP settings for their clusters
This function will allow users to view the VMCP settings for their clusters
.Example
# This will show you the VMCP settings of your cluster
.PARAMETER Cluster
Cluster Name or Object
.PARAMETER Server
vCenter server object
.EXAMPLE
Get-VMCPSettings
This will show you the VMCP settings for all the clusters
.EXAMPLE
Get-VMCPSettings -cluster LAB-CL
.Example
# This will show you the VMCP settings of your cluster
Get-VMCPSettings -cluster (Get-Cluster Lab-CL)
This will show you the VMCP settings of your cluster
.EXAMPLE
Get-VMCPSettings -cluster (Get-Cluster Lab-CL)
This will show you the VMCP settings of your cluster
.EXAMPLE
Get-Cluster | Get-VMCPSettings
This will show you the VMCP settings for all the clusters
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='What is the Cluster Name?')]
$cluster
)
Begin {
# Determine input and convert to ClusterImpl object
Switch ($cluster.GetType().Name)
{
"string" {$CL = Get-Cluster $cluster}
"ClusterImpl" {$CL = $cluster}
[CmdletBinding()]
param
(
[Parameter(Mandatory=$False,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='What is the Cluster Name?')]
$cluster = (Get-Cluster -Server $Server),
[Parameter(Mandatory=$False)]
[VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers
)
Process {
Foreach ($Clus in $Cluster) {
Write-Verbose "Processing Cluster $($Clus.Name)"
# Determine input and convert to ClusterImpl object
Switch ($Clus.GetType().Name)
{
"string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue}
"ClusterImpl" {$CL = $Clus}
}
If ($CL) {
# Work with the Cluster View
$ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server
# Create Hashtable with desired properties to return
$properties = [ordered]@{
'Cluster' = $ClusterMod.Name;
'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting;
'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD;
'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts;
'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec;
'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared;
'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL
}
# Create PSObject with the Hashtable
$object = New-Object -TypeName PSObject -Prop $properties
# Show object
$object
}
}
}
Process {
# Work with the Cluster View
$ClusterMod = Get-View -Id "ClusterComputeResource-$($cl.ExtensionData.MoRef.Value)"
# Create Hashtable with desired properties to return
$properties = [ordered]@{
'Cluster' = $ClusterMod.Name;
'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting;
'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD;
'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts;
'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec;
'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared;
'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL
}
# Create PSObject with the Hashtable
$object = New-Object -TypeName PSObject -Prop $properties
# Show object
return $object
}
End {}
}
}
function Set-VMCPSettings {
@@ -70,151 +102,221 @@ function Set-VMCPSettings {
Twitter: @vBrianGraf
VMware Blog: blogs.vmware.com/powercli
Personal Blog: www.vtagion.com
Modified on: 10/11/2016
Modified by: Erwan Quélin
Twitter: @erwanquelin
Github: https://github.com/equelin
===========================================================================
.DESCRIPTION
This function will allow users to enable/disable VMCP and also allow
This function will allow users to enable/disable VMCP and also allow
them to configure the additional VMCP settings
For each parameter, users should use the 'Tab' button to auto-fill the
possible values.
.Example
# This will enable VMCP and configure the Settings
.PARAMETER Cluster
Cluster Name or Object
.PARAMETER enableVMCP
Enable or disable VMCP
.PARAMETER VmStorageProtectionForPDL
VM Storage Protection for PDL settings. Might be:
- disabled
- warning
- restartAggressive
.PARAMETER VmStorageProtectionForAPD
VM Storage Protection for APD settings. Might be:
- disabled
- restartConservative
- restartAggressive
- warning
.PARAMETER VmTerminateDelayForAPDSec
VM Terminate Delay for APD (seconds).
.PARAMETER VmReactionOnAPDCleared
VM reaction on APD Cleared. Might be:
- reset
- none
.PARAMETER Server
vCenter server object
.EXAMPLE
Set-VMCPSettings -cluster LAB-CL -enableVMCP:$True -VmStorageProtectionForPDL `
restartAggressive -VmStorageProtectionForAPD restartAggressive `
-VmTerminateDelayForAPDSec 2000 -VmReactionOnAPDCleared reset
.Example
# This will disable VMCP and configure the Settings
This will enable VMCP and configure the Settings on cluster LAB-CL
.EXAMPLE
Set-VMCPSettings -cluster LAB-CL -enableVMCP:$False -VmStorageProtectionForPDL `
disabled -VmStorageProtectionForAPD disabled `
-VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none
This will disable VMCP and configure the Settings on cluster LAB-CL
.EXAMPLE
Set-VMCPSettings -enableVMCP:$False -VmStorageProtectionForPDL `
disabled -VmStorageProtectionForAPD disabled `
-VmTerminateDelayForAPDSec 600 -VmReactionOnAPDCleared none
This will disable VMCP and configure the Settings on all clusters available
#>
[CmdletBinding()]
param
(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='What is the Cluster Name?')]
$cluster,
[Parameter(Mandatory=$True,
ValueFromPipeline=$False,
HelpMessage='True=Enabled False=Disabled')]
[switch]$enableVMCP,
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="High")]
param
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True,
HelpMessage='What is the Cluster Name?')]
$cluster,
[Parameter(Mandatory=$False,
ValueFromPipeline=$False,
HelpMessage='$True=Enabled $False=Disabled')]
[bool]$enableVMCP,
[Parameter(Mandatory=$True,
ValueFromPipeline=$False,
HelpMessage='Actions that can be taken in response to a PDL event')]
[ValidateSet("disabled","warning","restartAggressive")]
[string]$VmStorageProtectionForPDL,
[Parameter(Mandatory=$True,
ValueFromPipeline=$False,
HelpMessage='Options available for an APD response')]
[ValidateSet("disabled","restartConservative","restartAggressive","warning")]
[string]$VmStorageProtectionForAPD,
[Parameter(Mandatory=$True,
ValueFromPipeline=$False,
HelpMessage='Value in seconds')]
[Int]$VmTerminateDelayForAPDSec,
[Parameter(Mandatory=$True,
ValueFromPipeline=$False,
HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')]
[ValidateSet("reset","none")]
[string]$VmReactionOnAPDCleared
[Parameter(Mandatory=$False,
ValueFromPipeline=$False,
HelpMessage='Actions that can be taken in response to a PDL event')]
[ValidateSet("disabled","warning","restartAggressive")]
[string]$VmStorageProtectionForPDL,
[Parameter(Mandatory=$False,
ValueFromPipeline=$False,
HelpMessage='Options available for an APD response')]
[ValidateSet("disabled","restartConservative","restartAggressive","warning")]
[string]$VmStorageProtectionForAPD,
[Parameter(Mandatory=$False,
ValueFromPipeline=$False,
HelpMessage='Value in seconds')]
[Int]$VmTerminateDelayForAPDSec,
[Parameter(Mandatory=$False,
ValueFromPipeline=$False,
HelpMessage='This setting will instruct vSphere HA to take a certain action if an APD event is cleared')]
[ValidateSet("reset","none")]
[string]$VmReactionOnAPDCleared,
[Parameter(Mandatory=$False)]
[VMware.VimAutomation.Types.VIServer[]]$Server = $global:DefaultVIServers
)
)
Begin{
Process {
# Determine input and convert to ClusterImpl object
Switch ($cluster.GetType().Name)
{
"string" {$CL = Get-Cluster $cluster}
"ClusterImpl" {$CL = $cluster}
}
}
Process{
# Create the object we will configure
$settings = New-Object VMware.Vim.ClusterConfigSpecEx
$settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
# Based on $enableVMCP switch
if ($enableVMCP -eq $false) {
$settings.dasConfig.vmComponentProtecting = "disabled"
}
elseif ($enableVMCP -eq $true) {
$settings.dasConfig.vmComponentProtecting = "enabled"
}
Foreach ($Clus in $Cluster) {
#Create the VMCP object to work with
$settings.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings
#Storage Protection For PDL
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = "$VmStorageProtectionForPDL"
#Storage Protection for APD
switch ($VmStorageProtectionForAPD) {
"disabled" {
# If Disabled, there is no need to set the Timeout Value
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false
}
"restartConservative" {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec
}
"restartAggressive" {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec
}
"warning" {
# If Warning, there is no need to set the Timeout Value
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false
}
Write-Verbose "Processing Cluster $Clus"
# Determine input and convert to ClusterImpl object
Switch ($Clus.GetType().Name)
{
"string" {$CL = Get-Cluster $Clus -Server $Server -ErrorAction SilentlyContinue}
"ClusterImpl" {$CL = $Clus}
default {Throw 'Please provide a cluster name or object'}
}
# Reaction On APD Cleared
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared"
# Execute API Call
$modify = $true
$ClusterMod = Get-View -Id "ClusterComputeResource-$($cl.ExtensionData.MoRef.Value)"
$ClusterMod.ReconfigureComputeResource_Task($settings, $modify) | out-null
If ($CL) {
# Get the actual configuration of the Cluster
$ActualSettings = Get-VMCPSettings -Cluster $CL -Server $Server
}
End{
# Update variable data after API call
$ClusterMod.updateViewData()
# Show actual settings in the verbose mode
Write-Verbose "[$($CL.Name)] Actual VMCP settings "
Write-Verbose $ActualSettings
# Create Hashtable with desired properties to return
$properties = [ordered]@{
'Cluster' = $ClusterMod.Name;
'VMCP Status' = $clustermod.Configuration.DasConfig.VmComponentProtecting;
'Protection For APD' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForAPD;
'APD Timeout Enabled' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.EnableAPDTimeoutForHosts;
'APD Timeout (Seconds)' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmTerminateDelayForAPDSec;
'Reaction on APD Cleared' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmReactionOnAPDCleared;
'Protection For PDL' = $clustermod.Configuration.DasConfig.DefaultVmSettings.VmComponentProtectionSettings.VmStorageProtectionForPDL
# Create the object we will configure
$settings = New-Object VMware.Vim.ClusterConfigSpecEx
$settings.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
# Based on $enableVMCP switch
if ($enableVMCP -eq $false) {
$settings.dasConfig.vmComponentProtecting = "disabled"
}
elseif ($enableVMCP -eq $true) {
$settings.dasConfig.vmComponentProtecting = "enabled"
}
#Create the VMCP object to work with
$settings.dasConfig.defaultVmSettings = New-Object VMware.Vim.ClusterDasVmSettings
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings = New-Object VMware.Vim.ClusterVmComponentProtectionSettings
#Storage Protection For PDL
If ($PSBoundParameters.ContainsKey('VmStorageProtectionForPDL')) {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $VmStorageProtectionForPDL
} else {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForPDL = $ActualSettings.'Protection For PDL'
}
#Storage Protection for APD
If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $VmStorageProtectionForAPD
} else {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD'
}
#Storage Protection for APD
If ($PSBoundParameters.ContainsKey('VmStorageProtectionForAPD')) {
switch ($VmStorageProtectionForAPD) {
"disabled" {
# If Disabled, there is no need to set enable Timeout Value
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'disabled'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false
}
"restartConservative" {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartConservative'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true
}
"restartAggressive" {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'restartAggressive'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $true
}
"warning" {
# If Warning, there is no need to enable the Timeout Value
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = 'warning'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $false
}
}
} else {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmStorageProtectionForAPD = $ActualSettings.'Protection For APD'
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.enableAPDTimeoutForHosts = $ActualSettings.'APD Timeout Enabled'
}
#APD Timeout Enabled
If ($PSBoundParameters.ContainsKey('VmTerminateDelayForAPDSec')) {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $VmTerminateDelayForAPDSec
} else {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmTerminateDelayForAPDSec = $ActualSettings.'APD Timeout (Seconds)'
}
# Reaction On APD Cleared
If ($PSBoundParameters.ContainsKey('VmReactionOnAPDCleared')) {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = "$VmReactionOnAPDCleared"
} else {
$settings.dasConfig.defaultVmSettings.vmComponentProtectionSettings.vmReactionOnAPDCleared = $ActualSettings.'Reaction on APD Cleared'
}
# Execute API Call
If ($pscmdlet.ShouldProcess($CL.Name,"Modify VMCP configuration")) {
$modify = $true
$ClusterMod = Get-View -Id "ClusterComputeResource-$($CL.ExtensionData.MoRef.Value)" -Server $Server
$Task = $ClusterMod.ReconfigureComputeResource_Task($settings, $modify)
}
# Wait for the reconfiguration task to finish to show the result
If ($Task) {
$TaskID = "Task-" + $($Task.Value)
Get-Task -Id $TaskID -Server $Server | Wait-Task | Out-Null
Get-VMCPSettings -Cluster $CL -Server $Server
}
}
}
}
# Create PSObject with the Hashtable
$object = New-Object -TypeName PSObject -Prop $properties
# Show object
return $object
}
}

View File

@@ -0,0 +1,6 @@
[InternetShortcut]
URL=https://github.com/lucdekens/LogInsight/blob/v1.0/LICENSE.txt
IDList=
HotKey=0
IconFile=C:\Users\ldekens\AppData\Local\Mozilla\Firefox\Profiles\2ahnnh1i.default\shortcutCache\ec4nFcIEAQBPFmSiPtTJ2w==.ico
IconIndex=0

View File

@@ -0,0 +1,18 @@
@{
ModuleToProcess = 'VMFSIncrease.psm1'
ModuleVersion = '1.0.0.0'
GUID = '9f167385-c5c6-4a65-ac14-949c67519001'
Author = 'Luc Dekens '
CompanyName = 'Community'
Copyright = '(c) 2016. All rights reserved.'
Description = 'Expand and Extend VMFS DatastoresModule description'
PowerShellVersion = '3.0'
FunctionsToExport = 'Get-VmfsDatastoreInfo','Get-VmfsDatastoreIncrease','New-VmfsDatastoreIncrease'
PrivateData = @{
PSData = @{
Tags = @('VMFS','Expand','Extend','vSphere')
LicenseUri = 'https://www.tldrlegal.com/l/mit'
ProjectUri = 'https://github.com/lucdekens/VMFSIncrease'
}
}
}

View File

@@ -0,0 +1,247 @@
function Get-VmfsDatastoreInfo
{
[CmdletBinding(SupportsShouldProcess = $True)]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)]
[PSObject]$Datastore
)
Process
{
if ($Datastore -is [String])
{
$Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue
}
if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore])
{
Write-Error 'Invalid value for Datastore.'
return
}
if ($Datastore.Type -ne 'VMFS')
{
Write-Error "$($Datastore.Name) is not a VMFS datastore"
return
}
# Get the Datastore System Manager from an ESXi that has the Datastore
$esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key)
$hsSys = Get-View -Id $esx.ConfigManager.StorageSystem
foreach ($extent in $Datastore.ExtensionData.Info.Vmfs.Extent)
{
$lun = $esx.Config.StorageDevice.ScsiLun | where{ $_.CanonicalName -eq $extent.DiskName }
$hdPartInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName)
$hdPartInfo[0].Layout.Partition | %{
New-Object PSObject -Property ([ordered]@{
Datastore = $Datastore.Name
CanonicalName = $lun.CanonicalName
Model = "$($lun.Vendor.TrimEnd(' ')).$($lun.Model.TrimEnd(' ')).$($lun.Revision.TrimEnd(' '))"
DiskSizeGB = $hdPartInfo[0].Layout.Total.BlockSize * $hdPartInfo[0].Layout.Total.Block / 1GB
DiskBlocks = $hdPartInfo[0].Layout.Total.Block
DiskBlockMB = $hdPartInfo[0].Layout.Total.BlockSize/1MB
PartitionFormat = $hdPartInfo[0].Spec.PartitionFormat
Partition = if ($_.Partition -eq '') { '<free>' }else{ $_.Partition }
Used = $extent.Partition -eq $_.Partition
Type = $_.Type
PartitionSizeGB = [math]::Round(($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize / 1GB, 1)
PartitionBlocks = $_.End.Block - $_.Start.Block + 1
PartitionBlockMB = $_.Start.BlockSize/1MB
Start = $_.Start.Block
End = $_.End.Block
})
}
}
}
}
function Get-VmfsDatastoreIncrease
{
[CmdletBinding(SupportsShouldProcess = $True)]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)]
[PSObject]$Datastore
)
Process
{
if ($Datastore -is [String])
{
$Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue
}
if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore])
{
Write-Error 'Invalid value for Datastore.'
return
}
if ($Datastore.Type -ne 'VMFS')
{
Write-Error "$($Datastore.Name) is not a VMFS datastore"
return
}
# Get the Datastore System Manager from an ESXi that has the Datastore
$esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key)
$hsSys = Get-View -Id $esx.ConfigManager.StorageSystem
$hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem
$extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName
$hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef)
foreach ($disk in $hScsiDisk)
{
$partInfo = $hsSys.RetrieveDiskPartitionInfo($disk.DeviceName)
$partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
if ($extents -contains $disk.CanonicalName)
{
$incType = 'Expand'
$vmfsExpOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef)
$PartMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
}
else
{
$incType = 'Extend'
$vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $disk.DevicePath, $null)
$partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
}
New-Object PSObject -Property ([ordered]@{
Datastore = $Datastore.Name
CanonicalName = $disk.CanonicalName
Model = "$($disk.Vendor.TrimEnd(' ')).$($disk.Model.TrimEnd(' ')).$($disk.Revision.TrimEnd(' '))"
DiskSizeGB = $partInfo[0].Layout.Total.BlockSize * $hdPartInfo[0].Layout.Total.Block / 1GB
DiskBlocks = $partInfo[0].Layout.Total.Block
DiskBlockMB = $partInfo[0].Layout.Total.BlockSize/1MB
AvailableGB = [math]::Round($partMax - $partUsed, 2)
Type = $incType
})
}
}
}
function New-VmfsDatastoreIncrease
{
[CmdletBinding(SupportsShouldProcess = $True)]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $True)]
[PSObject]$Datastore,
[int]$IncreaseSizeGB,
[Parameter(Position = 1)]
[string]$CanonicalName,
[Parameter(Mandatory = $true, ParameterSetName = 'Expand')]
[switch]$Expand,
[Parameter(Mandatory = $true, ParameterSetName = 'ExTend')]
[switch]$Extend
)
Process
{
if ($Datastore -is [String])
{
$Datastore = Get-Datastore -Name $Datastore -ErrorAction SilentlyContinue
}
if ($Datastore -isnot [VMware.VimAutomation.ViCore.Types.V1.DatastoreManagement.Datastore])
{
Write-Error 'Invalid value for Datastore.'
return
}
if ($Datastore.Type -ne 'VMFS')
{
Write-Error "$($Datastore.Name) is not a VMFS datastore"
return
}
# Get the Datastore System Manager from an ESXi that has the Datastore
$esx = Get-View -Id ($Datastore.ExtensionData.Host | Get-Random | Select -ExpandProperty Key)
$hsSys = Get-View -Id $esx.ConfigManager.StorageSystem
$hdSys = Get-View -Id $esx.ConfigManager.DatastoreSystem
$extents = $Datastore.ExtensionData.Info.Vmfs.Extent | Select -ExpandProperty DiskName
$hScsiDisk = $hdSys.QueryAvailableDisksForVmfs($Datastore.ExtensionData.MoRef)
# Expand or Extend
switch ($PSCmdlet.ParameterSetName)
{
'Expand' {
$expOpt = $hdSys.QueryVmfsDatastoreExpandOptions($Datastore.ExtensionData.MoRef)
if ($CanonicalName)
{
$dsOpt = $expOpt | where{ $_.Spec.Extent.DiskName -eq $CanonicalName }
}
else
{
$dsOpt = $expOpt | Sort-Object -Property { $_.Spec.Extent.Diskname } | select -first 1
}
if ($IncreaseSizeGB -ne 0)
{
$lun = $hScsiDisk | where{ $_.CanonicalName -eq $dsOpt.Spec.Extent.DiskName }
$partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName)
$partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
$partUsed = ($partInfo[0].Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
if (($partMax - $partUsed) -ge $IncreaseSizeGB)
{
$spec = $dsOpt.Spec
$spec.Partition.Partition[0].EndSector -= ([math]::Floor(($partMax - $partUsed - $IncreaseSizeGB) * 1GB/512))
}
else
{
Write-Error "Requested expand size $($IncreaseSizeGB)GB not available on $($lun.CanonicalName)"
return
}
}
else
{
$spec = $dsOpt.Spec
}
$hdSys.ExpandVmfsDatastore($Datastore.ExtensionData.MoRef, $spec)
}
'Extend' {
if ($CanonicalName)
{
$lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName -and $_.CanonicalName -eq $CanonicalName }
}
else
{
$lun = $hScsiDisk | where{ $extents -notcontains $_.CanonicalName } | Sort-Object -Property CanonicalName | select -First 1
}
if (!$lun)
{
Write-Error "No valid LUN provided or found for extent"
return
}
$vmfsExtOpt = $hdSys.QueryVmfsDatastoreExtendOptions($Datastore.ExtensionData.MoRef, $lun.DevicePath, $null)
if ($IncreaseSizeGB -ne 0)
{
$partInfo = $hsSys.RetrieveDiskPartitionInfo($lun.DeviceName)
$partMax = ($vmfsExpOpt[0].Info.Layout.Partition | where{ $_.Type -eq 'VMFS' } | %{ ($_.End.Block - $_.Start.Block + 1) * $_.Start.BlockSize } |
Measure-Object -Sum | select -ExpandProperty Sum)/1GB
if ($partMax -ge $IncreaseSizeGB)
{
$spec = $vmfsExtOpt[0].Spec
$spec.Partition.Partition[0].EndSector = $spec.Partition.Partition[0].StartSector + [math]::Floor($IncreaseSizeGB * 1GB / 512)
}
else
{
Write-Error "No valid LUN for extent with $($IncreaseSizeGB)GB space found"
return
}
}
else
{
$spec = $vmfsExtOpt.Spec
}
$hdSys.ExtendVmfsDatastore($Datastore.ExtensionData.MoRef, $spec)
}
}
}
}
Export-ModuleMember -Function Get-VmfsDatastoreInfo,Get-VmfsDatastoreIncrease,New-VmfsDatastoreIncrease

View File

@@ -0,0 +1,473 @@
<?xml version="1.0" encoding="utf-8" ?>
<helpItems xmlns="http://msh" schema="maml">
<!--Edited with: SAPIEN PowerShell HelpWriter 2015 v1.0.16-->
<!--Generated by: SAPIEN PowerShell HelpWriter 2015 v1.0.16-->
<!--
Module: VMFSIncrease
Version: 1.0.0.0
-->
<!--All Commands-->
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
<!--Command-->
<command:details>
<command:name>Get-VmfsDatastoreInfo</command:name>
<maml:description>
<maml:para>Provides partition information for all the extents in the datastore.</maml:para>
</maml:description>
<maml:copyright>
<maml:para/>
</maml:copyright>
<command:verb>Get</command:verb>
<command:noun>VmfsDatastoreInfo</command:noun>
<dev:version/>
</command:details>
<maml:description>
<maml:para>The function will display partition information for all the extents used by the datastore.</maml:para>
</maml:description>
<command:syntax>
<!--Parameter Sets-->
<command:syntaxItem>
<maml:name>Get-VmfsDatastoreInfo</maml:name>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
</command:syntax>
<command:parameters>
<!--All Parameters-->
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:type>
<maml:name>PSObject</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:parameters>
<command:inputTypes>
<!--Inputs-->
<command:inputType>
<dev:type>
<maml:name>System.Management.Automation.PSObject
</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:inputType>
</command:inputTypes>
<command:returnValues>
<!--Outputs-->
<command:returnValue>
<dev:type>
<maml:name>System.Object</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:returnValue>
</command:returnValues>
<command:examples>
<!--Examples-->
<command:example>
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>Get-VmfsDatastoreInfo -Datastore MyDS</dev:code>
<dev:remarks>
<maml:para>Will return partition information for the Datastore named MyDS</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 2 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>Get-Datastore -Name My* | Get-VmfsDatastoreInfo</dev:code>
<dev:remarks>
<maml:para>This example will return partition information for all the Datastore objects that are returned by the Get-Datastore PowerCLI cmdlet</maml:para>
</dev:remarks>
</command:example>
</command:examples>
</command:command>
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
<!--Command-->
<command:details>
<command:name>Get-VmfsDatastoreIncrease</command:name>
<maml:description>
<maml:para>Displays the increase options for a datastore</maml:para>
</maml:description>
<maml:copyright>
<maml:para/>
</maml:copyright>
<command:verb>Get</command:verb>
<command:noun>VmfsDatastoreIncrease</command:noun>
<dev:version/>
</command:details>
<maml:description>
<maml:para>The function will provide all the Expand and Extend options for a specific datastore</maml:para>
</maml:description>
<command:syntax>
<!--Parameter Sets-->
<command:syntaxItem>
<maml:name>Get-VmfsDatastoreIncrease</maml:name>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
</command:syntax>
<command:parameters>
<!--All Parameters-->
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:type>
<maml:name>PSObject</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:parameters>
<command:inputTypes>
<!--Inputs-->
<command:inputType>
<dev:type>
<maml:name>System.Management.Automation.PSObject
</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:inputType>
</command:inputTypes>
<command:returnValues>
<!--Outputs-->
<command:returnValue>
<dev:type>
<maml:name>System.Object</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:returnValue>
</command:returnValues>
<command:examples>
<!--Examples-->
<command:example>
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>Get-VmfsDatastoreIncrease -Datastore MyDS</dev:code>
<dev:remarks>
<maml:para>The exmaple will list all Expand and Extend options available for the Datastore, named MyDS</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 2 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>Get-Datastore -Name MyDS* | Get-VmfsDatastoreIncrease</dev:code>
<dev:remarks>
<maml:para>The Expand and Extend options for all Datastore retruned by the PowerCLI Get-Datastore will be returned.</maml:para>
</dev:remarks>
</command:example>
</command:examples>
</command:command>
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
<!--Command-->
<command:details>
<command:name>New-VmfsDatastoreIncrease</command:name>
<maml:description>
<maml:para>Increase the capacity of a Datastore</maml:para>
</maml:description>
<maml:copyright>
<maml:para/>
</maml:copyright>
<command:verb>New</command:verb>
<command:noun>VmfsDatastoreIncrease</command:noun>
<dev:version/>
</command:details>
<maml:description>
<maml:para>The capacity of the Datastore in increased through an Expand or an Extend.
To allow successful completion there shall be free capacity on one of the Extents, or there shall be free LUNs available.
With the Expand or Extend switches the caller selects which type of capacity increase is used.</maml:para>
</maml:description>
<command:syntax>
<!--Parameter Sets-->
<command:syntaxItem>
<maml:name>New-VmfsDatastoreIncrease</maml:name>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="1" aliases="">
<maml:name>CanonicalName</maml:name>
<maml:description>
<maml:para>The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion.
If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">String</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>IncreaseSizeGB</maml:name>
<maml:description>
<maml:para>The amount of GB by which to increase the size of the Datastore.
If this parameter is not used, all of the available Expand or Extend diskspace will be used.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">Int32</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>Expand</maml:name>
<maml:description>
<maml:para>A switch to indicate if the Datastore shall be Expanded</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>New-VmfsDatastoreIncrease</maml:name>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="1" aliases="">
<maml:name>CanonicalName</maml:name>
<maml:description>
<maml:para>The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion.
If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">String</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>IncreaseSizeGB</maml:name>
<maml:description>
<maml:para>The amount of GB by which to increase the size of the Datastore.
If this parameter is not used, all of the available Expand or Extend diskspace will be used.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">Int32</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>Extend</maml:name>
<maml:description>
<maml:para>A switch to indicate if the Datastore shall be Extended</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
</command:syntax>
<command:parameters>
<!--All Parameters-->
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="True (ByValue)" position="0" aliases="">
<maml:name>Datastore</maml:name>
<maml:description>
<maml:para>The name of the Datastore or a PowerCLI Datastore object</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">PSObject</command:parameterValue>
<dev:type>
<maml:name>PSObject</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>IncreaseSizeGB</maml:name>
<maml:description>
<maml:para>The amount of GB by which to increase the size of the Datastore.
If this parameter is not used, all of the available Expand or Extend diskspace will be used.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">Int32</command:parameterValue>
<dev:type>
<maml:name>Int32</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="false" globbing="false" pipelineInput="false" position="1" aliases="">
<maml:name>CanonicalName</maml:name>
<maml:description>
<maml:para>The Canonical name of the LUN on which to create a new Extent, or the name of the LUN on which to apply the Expansion.
If this parameter is not provided, the function will sort the available LUN alphanumerically on the Canonical names and slect the first one.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">String</command:parameterValue>
<dev:type>
<maml:name>String</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>Expand</maml:name>
<maml:description>
<maml:para>A switch to indicate if the Datastore shall be Expanded</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">SwitchParameter</command:parameterValue>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
<command:parameter required="true" variableLength="false" globbing="false" pipelineInput="false" position="named" aliases="">
<maml:name>Extend</maml:name>
<maml:description>
<maml:para>A switch to indicate if the Datastore shall be Extended</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">SwitchParameter</command:parameterValue>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri/>
</dev:type>
<dev:defaultValue>
</dev:defaultValue>
</command:parameter>
</command:parameters>
<command:inputTypes>
<!--Inputs-->
<command:inputType>
<dev:type>
<maml:name>System.Management.Automation.PSObject
</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:inputType>
</command:inputTypes>
<command:returnValues>
<!--Outputs-->
<command:returnValue>
<dev:type>
<maml:name>System.Object</maml:name>
<maml:uri/>
</dev:type>
<maml:description>
<maml:para/>
</maml:description>
</command:returnValue>
</command:returnValues>
<command:examples>
<!--Examples-->
<command:example>
<maml:title>-------------------------- EXAMPLE 1 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>New-VmfsDatastoreIncrease -Datastore MyDS -Expand</dev:code>
<dev:remarks>
<maml:para>The capacity of the Datastore, named MyDS, will be Expanded with all available free space on the first extent of the Datastore.</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 2 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>New-VmfsDatastoreIncrease -Name MyDS -Expand -IncreaseSizeGB 25</dev:code>
<dev:remarks>
<maml:para>The capacity of the Datastore, named MyDS, will be Expanded with 25GB on the first extent of the Datastore.
Provided if course, this amount of free space is available.</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 3 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>New-VmfsDatastoreIncrease -Datastore &apos;TestDS&apos; -Expand -IncreaseSizeGB 15 -CanonicalName &apos;naa.600507680180732f1800000000000011&apos;</dev:code>
<dev:remarks>
<maml:para>The capacity of the Datastore MyDS will be increased with 15GB on the extent with the Canonicalname naa.600507680180732f1800000000000011</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 4 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>New-VmfsDatastoreIncrease -Datastore MyDS -Expand -CanonicalName &apos;naa.600507680180732f1800000000000012&apos;</dev:code>
<dev:remarks>
<maml:para>The capacity of the Datastore MyDS will be increased with all available free space on the extent with the Canonicalname naa.600507680180732f1800000000000012</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 5 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>New-VmfsDatastoreIncrease -Datastore MyDS -Extend</dev:code>
<dev:remarks>
<maml:para>A new Extent will be added to Datastore MyDS.
All available free space of the LUN will be allocated.
The available LUNs are ordered alphanumerically by their Canonicalname, and the first LUN is used.</maml:para>
</dev:remarks>
</command:example>
<command:example>
<maml:title>-------------------------- EXAMPLE 6 --------------------------</maml:title>
<maml:introduction>
<maml:para>PS C:\&gt;</maml:para>
</maml:introduction>
<dev:code>Get-Datastore -Name MyDS | New-VmfsDatastoreIncrease -Extend -IncreaseSizeGB 50</dev:code>
<dev:remarks>
<maml:para>The capacity of the Datastore returned by the PowerCLI Get-Datastore cmdlet will be increased by 50GB.
This is done by adding a new Extent to the Datastore.
The available LUNs are ordered alphanumerically by their Canonicalname, and the first LUN is used.</maml:para>
</dev:remarks>
</command:example>
</command:examples>
</command:command>
<!--Generated by: SAPIEN PowerShell HelpWriter 2015 v1.0.16-->
</helpItems>

View File

@@ -0,0 +1,13 @@
TOPIC
VMFSIncrease
SYNOPSIS
The VMFSIncrease module offers the same functionality that is available
through the Increase button in the vSphere Web Client.
DESCRIPTION
The VMFSIncrease offers functionality that allows to Expand or Extend
VMFS Datastores. The module uses the vSphere API to implement this functionality.
SEE ALSO
http://www.lucd.info/2016/07/29/vmfs-datastores-expand-and-extend

View File

@@ -0,0 +1,49 @@
<#
.MYNGC_REPORT
KEY\(VM\)
.LABEL
VM Snapshot Report
.DESCRIPTION
PowerActions Report Script that reports on VMs with snapshots along with their description, date of the snapshot, age in days of the snapshot, size of the snapshot in GB,
the VM's provisioned vs. used space in GB, if the snapshot is the current one being used, its parent snapshot (if there is one), and the Power state of the VM itself. VM
object is key (as it's the first managed object in the output), enabling you the ability to right-click an entry in the report to edit the target VM. Version 1.0, written
by Aaron Smith (@awsmith99), published 08/10/2016.
#>
param
(
[Parameter(Mandatory=$true)]
[VMware.VimAutomation.ViCore.Types.V1.Inventory.Cluster]
$vParam
);
[Array] $vmList = @( Get-VM -Location $vParam | Sort Name );
foreach ( $vmItem in $vmList )
{
[Array] $vmSnapshotList = @( Get-Snapshot -VM $vmItem );
foreach ( $snapshotItem in $vmSnapshotList )
{
$vmProvisionedSpaceGB = [Math]::Round( $vmItem.ProvisionedSpaceGB, 2 );
$vmUsedSpaceGB = [Math]::Round( $vmItem.UsedSpaceGB, 2 );
$snapshotSizeGB = [Math]::Round( $snapshotItem.SizeGB, 2 );
$snapshotAgeDays = ((Get-Date) - $snapshotItem.Created).Days;
$output = New-Object -TypeName PSObject;
$output | Add-Member -MemberType NoteProperty -Name "VM" -Value $vmItem;
$output | Add-Member -MemberType NoteProperty -Name "Name" -Value $snapshotItem.Name;
$output | Add-Member -MemberType NoteProperty -Name "Description" -Value $snapshotItem.Description;
$output | Add-Member -MemberType NoteProperty -Name "Created" -Value $snapshotItem.Created;
$output | Add-Member -MemberType NoteProperty -Name "AgeDays" -Value $snapshotAgeDays;
$output | Add-Member -MemberType NoteProperty -Name "ParentSnapshot" -Value $snapshotItem.ParentSnapshot.Name;
$output | Add-Member -MemberType NoteProperty -Name "IsCurrentSnapshot" -Value $snapshotItem.IsCurrent;
$output | Add-Member -MemberType NoteProperty -Name "SnapshotSizeGB" -Value $snapshotSizeGB;
$output | Add-Member -MemberType NoteProperty -Name "ProvisionedSpaceGB" -Value $vmProvisionedSpaceGB;
$output | Add-Member -MemberType NoteProperty -Name "UsedSpaceGB" -Value $vmUsedSpaceGB;
$output | Add-Member -MemberType NoteProperty -Name "PowerState" -Value $snapshotItem.PowerState;
$output;
}
}

View File

@@ -189,4 +189,4 @@ Members:
* Rynardt Spies (Community Member)
## Approval of Additions
Items added to the repository, including items from the Board members, require 2 votes from the board members before being added to the repository. The approving members will have ideally downloaded and tested the item. When two “Approved for Merge” comments are added from board members, the pull can then be committed to the repository.
Items added to the repository, including items from the Board members, require a review and approval from at least one board member before being added to the repository. The approving member/s will have verified for a lack of malicious code. Once an “Approved for Merge” comment has been added from a board member, the pull can then be committed to the repository.

70
Scripts/AutomaticVMFSUnmap.ps1 Executable file
View File

@@ -0,0 +1,70 @@
<#
.SYNOPSIS Retrieve the current VMFS Unmap priority for VMFS 6 datastore
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.NOTES Reference: http://www.virtuallyghetto.com/2016/10/configure-new-automatic-space-reclamation-vmfs-unmap-using-vsphere-6-5-apis.html
.PARAMETER Datastore
VMFS 6 Datastore to enable or disable VMFS Unamp
.EXAMPLE
Get-Datastore "mini-local-datastore-hdd" | Get-VMFSUnmap
#>
Function Get-VMFSUnmap {
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl]$Datastore
)
$datastoreInfo = $Datastore.ExtensionData.Info
if($datastoreInfo -is [VMware.Vim.VmfsDatastoreInfo] -and $datastoreInfo.Vmfs.MajorVersion -eq 6) {
$datastoreInfo.Vmfs | select Name, UnmapPriority, UnmapGranularity
} else {
Write-Host "Not a VMFS Datastore and/or VMFS version is not 6.0"
}
}
<#
.SYNOPSIS Configure the VMFS Unmap priority for VMFS 6 datastore
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.NOTES Reference: http://www.virtuallyghetto.com/2016/10/configure-new-automatic-space-reclamation-vmfs-unmap-using-vsphere-6-5-apis.html
.PARAMETER Datastore
VMFS 6 Datastore to enable or disable VMFS Unamp
.EXAMPLE
Get-Datastore "mini-local-datastore-hdd" | Set-VMFSUnmap -Enabled $true
.EXAMPLE
Get-Datastore "mini-local-datastore-hdd" | Set-VMFSUnmap -Enabled $false
#>
Function Set-VMFSUnmap {
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.DatastoreImpl]$Datastore,
[String]$Enabled
)
$vmhostView = ($Datastore | Get-VMHost).ExtensionData
$storageSystem = Get-View $vmhostView.ConfigManager.StorageSystem
if($Enabled -eq $true) {
$enableUNMAP = "low"
$reconfigMessage = "Enabling Automatic VMFS Unmap for $Datastore"
} else {
$enableUNMAP = "none"
$reconfigMessage = "Disabling Automatic VMFS Unmap for $Datastore"
}
$uuid = $datastore.ExtensionData.Info.Vmfs.Uuid
Write-Host "$reconfigMessage ..."
$storageSystem.UpdateVmfsUnmapPriority($uuid,$enableUNMAP)
}

30
Scripts/ESXInstallDate.ps1 Executable file
View File

@@ -0,0 +1,30 @@
<#
.SYNOPSIS Retrieve the installation date of an ESXi host
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.NOTES Reference: http://www.virtuallyghetto.com/2016/10/super-easy-way-of-getting-esxi-installation-date-in-vsphere-6-5.html
.PARAMETER Vmhost
ESXi host to query installation date
.EXAMPLE
Get-Vmhost "mini" | Get-ESXInstallDate
#>
Function Get-ESXInstallDate {
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Vmhost
)
if($Vmhost.Version -eq "6.5.0") {
$imageManager = Get-View ($Vmhost.ExtensionData.ConfigManager.ImageConfigManager)
$installDate = $imageManager.installDate()
Write-Host "$Vmhost was installed on $installDate"
} else {
Write-Host "ESXi must be running 6.5"
}
}

41
Scripts/ESXInstalledVIBs.ps1 Executable file
View File

@@ -0,0 +1,41 @@
<#
.SYNOPSIS Retrieve the installation date of an ESXi host
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.PARAMETER Vmhost
ESXi host to query installed ESXi VIBs
.EXAMPLE
Get-ESXInstalledVibs -Vmhost (Get-Vmhost "mini")
.EXAMPLE
Get-ESXInstalledVibs -Vmhost (Get-Vmhost "mini") -vibname vsan
#>
Function Get-ESXInstalledVibs {
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Vmhost,
[Parameter(
Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[String]$vibname=""
)
$imageManager = Get-View ($Vmhost.ExtensionData.ConfigManager.ImageConfigManager)
$vibs = $imageManager.fetchSoftwarePackages()
foreach ($vib in $vibs) {
if($vibname -ne "") {
if($vib.name -eq $vibname) {
return $vib | select Name, Version, Vendor, CreationDate, Summary
}
} else {
$vib | select Name, Version, Vendor, CreationDate, Summary
}
}
}

View File

@@ -0,0 +1,49 @@
Function Get-HVDesktop {
<#
.SYNOPSIS
This cmdlet retrieves the virtual desktops on a horizon view Server.
.DESCRIPTION
This cmdlet retrieves the virtual desktops on a horizon view Server.
.NOTES
Author: Alan Renouf, @alanrenouf,virtu-al.net
.PARAMETER State
Hash table containing states to filter on
.EXAMPLE
List All Desktops
Get-HVDesktop
.EXAMPLE
List All Problem Desktops
Get-HVDesktop -state @('PROVISIONING_ERROR',
'ERROR',
'AGENT_UNREACHABLE',
'AGENT_ERR_STARTUP_IN_PROGRESS',
'AGENT_ERR_DISABLED',
'AGENT_ERR_INVALID_IP',
'AGENT_ERR_NEED_REBOOT',
'AGENT_ERR_PROTOCOL_FAILURE',
'AGENT_ERR_DOMAIN_FAILURE',
'AGENT_CONFIG_ERROR',
'UNKNOWN')
#>
Param (
$State
)
$ViewAPI = $global:DefaultHVServers[0].ExtensionData
$query_service = New-Object "Vmware.Hv.QueryServiceService"
$query = New-Object "Vmware.Hv.QueryDefinition"
$query.queryEntityType = 'MachineSummaryView'
if ($State) {
[VMware.Hv.QueryFilter []] $filters = @()
foreach ($filterstate in $State) {
$filters += new-object VMware.Hv.QueryFilterEquals -property @{'memberName' = 'base.basicState'; 'value' = $filterstate}
}
$orFilter = new-object VMware.Hv.QueryFilterOr -property @{'filters' = $filters}
$query.Filter = $orFilter
}
$Desktops = $query_service.QueryService_Query($ViewAPI,$query)
$Desktops.Results.Base
}

65
Scripts/SecureBoot.ps1 Executable file
View File

@@ -0,0 +1,65 @@
Function Get-SecureBoot {
<#
.SYNOPSIS Query Seure Boot setting for a VM in vSphere 6.5
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.PARAMETER Vm
VM to query Secure Boot setting
.EXAMPLE
Get-VM -Name Windows10 | Get-SecureBoot
#>
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Vm
)
$secureBootSetting = if ($vm.ExtensionData.Config.BootOptions.EfiSecureBootEnabled) { "enabled" } else { "disabled" }
Write-Host "Secure Boot is" $secureBootSetting
}
Function Set-SecureBoot {
<#
.SYNOPSIS Enable/Disable Seure Boot setting for a VM in vSphere 6.5
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.PARAMETER Vm
VM to enable/disable Secure Boot
.EXAMPLE
Get-VM -Name Windows10 | Set-SecureBoot -Enabled
.EXAMPLE
Get-VM -Name Windows10 | Set-SecureBoot -Disabled
#>
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Vm,
[Switch]$Enabled,
[Switch]$Disabled
)
if($Enabled) {
$secureBootSetting = $true
$reconfigMessage = "Enabling Secure Boot for $Vm"
}
if($Disabled) {
$secureBootSetting = $false
$reconfigMessage = "Disabling Secure Boot for $Vm"
}
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$bootOptions = New-Object VMware.Vim.VirtualMachineBootOptions
$bootOptions.EfiSecureBootEnabled = $secureBootSetting
$spec.BootOptions = $bootOptions
Write-Host "`n$reconfigMessage ..."
$task = $vm.ExtensionData.ReconfigVM_Task($spec)
$task1 = Get-Task -Id ("Task-$($task.value)")
$task1 | Wait-Task | Out-Null
}

View File

@@ -0,0 +1,228 @@
function Get-PowerCLIInitialization {
<#
.SYNOPSIS
Gathers information on PowerShell resources which refer to the old PowerCLI Initialization Script
.DESCRIPTION
Will provide an inventory of scripts, modules, etc refering to the old vSphere PowerCLI directory
.NOTES
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
.PARAMETER Path
Directory path to be searched
.EXAMPLE
Get-PowerCLIInitialization -Path C:\Temp\Scripts
Gathers information from the 'C:\Temp\Scripts\' directory
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
[string]$Path
)
Process {
#Validate whether a path was passed as a parameter or not
if (!$Path) {$FullName = (Get-Location).ProviderPath}
else {
#Validate whether the path passed as a parameter was a literal path or not, then establish the FullName of the desired path
if ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -is [System.IO.DirectoryInfo]) {$FullName = (Get-Item -Path $Path).FullName}
elseif ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -isnot [System.IO.DirectoryInfo]) {$FullName = (Get-Item -LiteralPath $Path).FullName}
else {
$currdir = (Get-Location).ProviderPath
Write-Warning "No valid path found at - $currdir\$Path"
}
}
if ($FullName) {
#Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1"
$scripts = Get-ChildItem -Path $FullName -Recurse -Filter *.ps1 -File -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-String -Pattern "\\VMware\\Infrastructure\\vSphere PowerCLI\\Scripts\\Initialize-PowerCLIEnvironment.ps1"
#Create a report of neccessary output based on the scripts gathered above
$scriptreport = @()
foreach ($script in $scripts) {
$singleitem = New-Object System.Object
$singleitem | Add-Member -Type NoteProperty -Name Filename -Value $script.Filename
$singleitem | Add-Member -Type NoteProperty -Name LineNumber -Value $script.LineNumber
$singleitem | Add-Member -Type NoteProperty -Name Path -Value $script.Path.TrimEnd($script.Filename)
$singleitem | Add-Member -Type NoteProperty -Name FullPath -Value $script.Path
$scriptreport += $singleitem
}
return $scriptreport
}
} # End of process
} # End of function
function Get-PowerCLISnapinUse {
<#
.SYNOPSIS
Gathers information on PowerShell resources which refer to the old PowerCLI Snapins
.DESCRIPTION
Will provide an inventory of scripts, modules, etc refering to the old PowerCLI Snapins
.NOTES
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
.PARAMETER Path
Directory path to be searched
.EXAMPLE
Get-PowerCLISnapinUse -Path C:\Temp\Scripts
Gathers information from the 'C:\Temp\Scripts\' directory
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
[string]$Path
)
Process {
#Validate whether a path was passed as a parameter or not
if (!$Path) {$FullName = (Get-Location).ProviderPath}
else {
#Validate whether the path passed as a parameter was a literal path or not, then establish the FullName of the desired path
if ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -is [System.IO.DirectoryInfo]) {$FullName = (Get-Item -Path $Path).FullName}
elseif ((Test-Path -Path $Path -ErrorAction SilentlyContinue) -eq $true -and $Path -isnot [System.IO.DirectoryInfo]) {$FullName = (Get-Item -LiteralPath $Path).FullName}
else {
$currdir = (Get-Location).ProviderPath
Write-Warning "No valid path found at - $currdir\$Path"
}
}
if ($FullName) {
#Gather scripts using ps1 extension and have a string matching "add-pssnapin" and "VMware." on the same line
$scripts = Get-ChildItem -Path $FullName -Recurse -Filter *.ps1 -File -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Select-String -Pattern "add-pssnapin" | Where-Object {$_ | Select-String -Pattern "VMware."}
#Create a report of neccessary output based on the scripts gathered above
$scriptreport = @()
foreach ($script in $scripts) {
$singleitem = New-Object System.Object
$singleitem | Add-Member -Type NoteProperty -Name Filename -Value $script.Filename
$singleitem | Add-Member -Type NoteProperty -Name LineNumber -Value $script.LineNumber
$singleitem | Add-Member -Type NoteProperty -Name Path -Value $script.Path.TrimEnd($script.Filename)
$singleitem | Add-Member -Type NoteProperty -Name FullPath -Value $script.Path
$scriptreport += $singleitem
}
return $scriptreport
}
} # End of process
} # End of function
function Update-PowerCLIInitialization {
<#
.SYNOPSIS
Updates the information in PowerShell resources which refer to the old PowerCLI Initialization Script
.DESCRIPTION
Will update scripts, modules, etc refering to the old vSphere PowerCLI directory
.NOTES
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
.PARAMETER Path
Directory path to be searched
.EXAMPLE
Update-PowerCLIInitialization -Path C:\Temp\Scripts
Gathers information from the 'C:\Temp\Scripts\' directory
#>
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
[string]$Path
)
Process {
#Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1"
$scripts = Get-PowerCLIInitialization -Path $Path
#Check to see if any scripts are found
if (!$scripts) {Write-Warning "No PowerShell resources found requiring update within $Path"}
else {
foreach ($script in $scripts) {
#Finds and updates the string to the new location of the Initialize-PowerCLIEnvironment.ps1 script
(Get-Content $script.FullPath).Replace("\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1","\VMware\Infrastructure\PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1") | Set-Content $script.FullPath
}
}
} # End of process
} # End of function
function Update-PowerCLISnapinUse {
<#
.SYNOPSIS
Updates the information in PowerShell resources which refer to the old PowerCLI Initialization Script
.DESCRIPTION
Will update scripts, modules, etc refering to the old vSphere PowerCLI directory
.NOTES
Author: Kyle Ruddy, @kmruddy, thatcouldbeaproblem.com
.PARAMETER Path
Directory path to be searched
.EXAMPLE
Update-PowerCLISnapinUse -Path C:\Temp\Scripts
Gathers information from the 'C:\Temp\Scripts\' directory
#>
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory=$false,Position=0,ValueFromPipelineByPropertyName=$true)]
[string]$Path
)
Process {
#Gather scripts using ps1 extension and have a string matching "\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1"
$scripts = Get-PowerCLISnapinUse -Path $Path | select -Unique FullPath
#Check to see if any scripts are found
if (!$scripts) {Write-Warning "No PowerShell resources found requiring update within $Path"}
else {
foreach ($script in $scripts) {
#Finds and updates the string to import the PowerCLI modules
$scriptcontent = (Get-Content $script.FullPath)
$newoutput = @()
[int]$counter = 0
foreach ($line in $scriptcontent) {
#Checks to see if the line includes adding in the VMware PSSnapins and, if so, comments it out
#On first discovery, adds the invokation of get-module for the PowerCLI modules
if ($line -like "Add-PSSnapin*VMware*" -and $counter -eq 0) {
$newoutput += "Get-Module -ListAvailable VMware* | Import-Module"
$newoutput += $line.Insert(0,'#')
$counter = 1
}
elseif ($line -like "Add-PSSnapin*VMware*" -and $counter -eq 1) {
$newoutput += $line.Insert(0,'#')
}
else {$newoutput += $line}
}
#Updates the script
Set-Content -Value $newoutput -Path $script.FullPath
}
}
} # End of process
} # End of function

29
Scripts/vSphereLogins.ps1 Executable file
View File

@@ -0,0 +1,29 @@
Function Get-vSphereLogins {
<#
.SYNOPSIS Retrieve information for all currently logged in vSphere Sessions (excluding current session)
.NOTES Author: William Lam
.NOTES Site: www.virtuallyghetto.com
.REFERENCE Blog: http://www.virtuallyghetto.com/2016/11/an-update-on-how-to-retrieve-useful-information-from-a-vsphere-login.html
.EXAMPLE
Get-vSphereLogins
#>
if($DefaultVIServers -eq $null) {
Write-Host "Error: Please connect to your vSphere environment"
exit
}
# Using the first connection
$VCConnection = $DefaultVIServers[0]
$sessionManager = Get-View ($VCConnection.ExtensionData.Content.SessionManager)
# Store current session key
$currentSessionKey = $sessionManager.CurrentSession.Key
foreach ($session in $sessionManager.SessionList) {
# Ignore vpxd-extension logins as well as the current session
if($session.UserName -notmatch "vpxd-extension" -and $session.key -ne $currentSessionKey) {
$session | Select Username, IpAddress, UserAgent, @{"Name"="APICount";Expression={$Session.CallCount}}, LoginTime
}
}
}