Added folders for all .psm1 Files in /Modules
Signed-off-by: Kevin Kirkpatrick <kevin@vmotioned.com>
This commit is contained in:
202
Modules/Backup-VCSA/Backup-VCSA.psm1
Normal file
202
Modules/Backup-VCSA/Backup-VCSA.psm1
Normal 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 {}
|
||||||
|
}
|
||||||
93
Modules/Get-NICDetails/Get-NICDetails.psm1
Normal file
93
Modules/Get-NICDetails/Get-NICDetails.psm1
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
function Get-NICDetails {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2017.02 ver 1.0 Base Release
|
||||||
|
===========================================================================
|
||||||
|
External Code Sources:
|
||||||
|
-
|
||||||
|
===========================================================================
|
||||||
|
Tested Against Environment:
|
||||||
|
vSphere Version: ESXi 6.0 U2, ESXi 6.5
|
||||||
|
PowerCLI Version: PowerCLI 6.3 R1, PowerCLI 6.5 R1
|
||||||
|
PowerShell Version: 4.0, 5.0
|
||||||
|
OS Version: Windows 8.1, Server 2008 R2, Server 2012 R2
|
||||||
|
Keyword: ESXi, NIC, vmnic, Driver, Firmware
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Reports Firmware and Driver Details for your ESXi vmnics.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-NICDetails -Clustername *
|
||||||
|
|
||||||
|
.PARAMETER Clustername
|
||||||
|
Name or Wildcard of your vSphere Cluster Name to process.
|
||||||
|
|
||||||
|
|
||||||
|
#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)]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[String] $Clustername
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
$Validate = $True
|
||||||
|
|
||||||
|
if (($myCluster = Get-Cluster -Name $Clustername).count -lt 1) {
|
||||||
|
$Validate = $False
|
||||||
|
thow "No Cluster '$myCluster' found!"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
|
||||||
|
$MyView = @()
|
||||||
|
if ($Validate -eq $True) {
|
||||||
|
|
||||||
|
foreach ($myVMhost in ($myCluster | Get-VMHost)) {
|
||||||
|
|
||||||
|
$esxcli2 = Get-ESXCLI -VMHost $myVMhost -V2
|
||||||
|
$niclist = $esxcli2.network.nic.list.invoke()
|
||||||
|
|
||||||
|
$nicdetails = @()
|
||||||
|
foreach ($nic in $niclist) {
|
||||||
|
|
||||||
|
$args = $esxcli2.network.nic.get.createargs()
|
||||||
|
$args.nicname = $nic.name
|
||||||
|
$nicdetail = $esxcli2.network.nic.get.Invoke($args)
|
||||||
|
$nicdetails += $nicdetail
|
||||||
|
|
||||||
|
}
|
||||||
|
ForEach ($nicdetail in $nicdetails){
|
||||||
|
$NICReport = [PSCustomObject] @{
|
||||||
|
Host = $myVMhost.Name
|
||||||
|
vmnic = $nicdetail.Name
|
||||||
|
LinkStatus = $nicdetail.LinkStatus
|
||||||
|
BusInfo = $nicdetail.driverinfo.BusInfo
|
||||||
|
Driver = $nicdetail.driverinfo.Driver
|
||||||
|
FirmwareVersion = $nicdetail.driverinfo.FirmwareVersion
|
||||||
|
DriverVersion = $nicdetail.driverinfo.Version
|
||||||
|
}
|
||||||
|
$MyView += $NICReport
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$MyView
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
Modules/Get-NewAndRemovedVMs/Get-NewAndRemovedVMs.psm1
Normal file
131
Modules/Get-NewAndRemovedVMs/Get-NewAndRemovedVMs.psm1
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
function Get-NewAndRemovedVMs {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2016.12 ver 1.0 Base Release
|
||||||
|
===========================================================================
|
||||||
|
External Code Sources:
|
||||||
|
https://github.com/alanrenouf/vCheck-vSphere
|
||||||
|
===========================================================================
|
||||||
|
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, VM
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This Function report newly created and deleted VMs by Cluster.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-NewAndRemovedVMs -ClusterName Cluster* | ft -AutoSize
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-NewAndRemovedVMs -ClusterName Cluster01 -Days 90
|
||||||
|
|
||||||
|
.PARAMETER ClusterName
|
||||||
|
Name or Wildcard of your vSphere Cluster Name(s) to report.
|
||||||
|
|
||||||
|
.PARAMETER Day
|
||||||
|
Range in Days to report.
|
||||||
|
|
||||||
|
|
||||||
|
#Requires PS -Version 4.0
|
||||||
|
#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"}
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=0, HelpMessage = "Name or Wildcard of your vSphere Cluster Name to report")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[String]$ClusterName,
|
||||||
|
[Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1, HelpMessage = "Range in Days to report")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[String]$Days = "30"
|
||||||
|
)
|
||||||
|
Begin {
|
||||||
|
function Get-VIEventPlus {
|
||||||
|
|
||||||
|
param(
|
||||||
|
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$Entity,
|
||||||
|
[string[]]$EventType,
|
||||||
|
[DateTime]$Start,
|
||||||
|
[DateTime]$Finish = (Get-Date),
|
||||||
|
[switch]$Recurse,
|
||||||
|
[string[]]$User,
|
||||||
|
[Switch]$System,
|
||||||
|
[string]$ScheduledTask,
|
||||||
|
[switch]$FullMessage = $false,
|
||||||
|
[switch]$UseUTC = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
process {
|
||||||
|
$eventnumber = 100
|
||||||
|
$events = @()
|
||||||
|
$eventMgr = Get-View EventManager
|
||||||
|
$eventFilter = New-Object VMware.Vim.EventFilterSpec
|
||||||
|
$eventFilter.disableFullMessage = ! $FullMessage
|
||||||
|
$eventFilter.entity = New-Object VMware.Vim.EventFilterSpecByEntity
|
||||||
|
$eventFilter.entity.recursion = &{if($Recurse){"all"}else{"self"}}
|
||||||
|
$eventFilter.eventTypeId = $EventType
|
||||||
|
if($Start -or $Finish){
|
||||||
|
$eventFilter.time = New-Object VMware.Vim.EventFilterSpecByTime
|
||||||
|
if($Start){
|
||||||
|
$eventFilter.time.beginTime = $Start
|
||||||
|
}
|
||||||
|
if($Finish){
|
||||||
|
$eventFilter.time.endTime = $Finish
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($User -or $System){
|
||||||
|
$eventFilter.UserName = New-Object VMware.Vim.EventFilterSpecByUsername
|
||||||
|
if($User){
|
||||||
|
$eventFilter.UserName.userList = $User
|
||||||
|
}
|
||||||
|
if($System){
|
||||||
|
$eventFilter.UserName.systemUser = $System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($ScheduledTask){
|
||||||
|
$si = Get-View ServiceInstance
|
||||||
|
$schTskMgr = Get-View $si.Content.ScheduledTaskManager
|
||||||
|
$eventFilter.ScheduledTask = Get-View $schTskMgr.ScheduledTask |
|
||||||
|
where {$_.Info.Name -match $ScheduledTask} |
|
||||||
|
Select -First 1 |
|
||||||
|
Select -ExpandProperty MoRef
|
||||||
|
}
|
||||||
|
if(!$Entity){
|
||||||
|
$Entity = @(Get-Folder -NoRecursion)
|
||||||
|
}
|
||||||
|
$entity | %{
|
||||||
|
$eventFilter.entity.entity = $_.ExtensionData.MoRef
|
||||||
|
$eventCollector = Get-View ($eventMgr.CreateCollectorForEvents($eventFilter))
|
||||||
|
$eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)
|
||||||
|
while($eventsBuffer){
|
||||||
|
$events += $eventsBuffer
|
||||||
|
$eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)
|
||||||
|
}
|
||||||
|
$eventCollector.DestroyCollector()
|
||||||
|
}
|
||||||
|
if (-not $UseUTC)
|
||||||
|
{
|
||||||
|
$events | % { $_.createdTime = $_.createdTime.ToLocalTime() }
|
||||||
|
}
|
||||||
|
|
||||||
|
$events
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
$result = Get-VIEventPlus -Start ((get-date).adddays(-$Days)) -EventType @("VmCreatedEvent", "VmBeingClonedEvent", "VmBeingDeployedEvent","VmRemovedEvent")
|
||||||
|
$sortedResult = $result | Select CreatedTime, @{N='Cluster';E={$_.ComputeResource.Name}}, @{Name="VMName";Expression={$_.vm.name}}, UserName, @{N='Type';E={$_.GetType().Name}}, FullFormattedMessage | Sort CreatedTime
|
||||||
|
$sortedResult | where {$_.Cluster -like $ClusterName}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
Modules/Get-VMmaxIOPS/Get-VMmaxIOPS.psm1
Normal file
114
Modules/Get-VMmaxIOPS/Get-VMmaxIOPS.psm1
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
function Get-VMmaxIOPS {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2016.10 ver 1.0 Base Release
|
||||||
|
2016.11 ver 1.1 Added vSphere 6.5 Support, New Counters, More Error Handling
|
||||||
|
===========================================================================
|
||||||
|
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, 6.5
|
||||||
|
PowerCLI Version: PowerCLI 6.3 R1, 6.5 R1
|
||||||
|
PowerShell Version: 4.0, 5.0
|
||||||
|
OS Version: Windows 8.1, Windows Server 2012 R2
|
||||||
|
===========================================================================
|
||||||
|
Keywords vSphere, ESXi, VM, Storage
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.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)
|
||||||
|
|
||||||
|
#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)]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $VMs,
|
||||||
|
[Parameter(Mandatory=$false, Position=1, HelpMessage = "Specify the Minutes to report (10080 is one Week)")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[int] $Minutes = 30
|
||||||
|
)
|
||||||
|
Begin {
|
||||||
|
# none
|
||||||
|
}
|
||||||
|
Process {
|
||||||
|
if ($_.PowerState -eq "PoweredOn") {
|
||||||
|
#region: Global Definitions
|
||||||
|
[int]$TimeRange = "-" + $Minutes
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Creating VM Stats
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create VM Stats..."
|
||||||
|
$VMMetrics = "virtualdisk.numberwriteaveraged.average","virtualdisk.numberreadaveraged.average"
|
||||||
|
$Start = (Get-Date).AddMinutes($TimeRange)
|
||||||
|
$stats = Get-Stat -Realtime -Stat $VMMetrics -Entity $VMs -Start $Start -Verbose:$False
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create VM Stats completed"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Creating HD-Tab
|
||||||
|
Write-Verbose "$(Get-Date -Format G) 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('[')
|
||||||
|
}
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create HD Tab completed"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Creating Reports
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create Report..."
|
||||||
|
$reportPerf = @()
|
||||||
|
$reportPerf = $stats | Group-Object -Property {$_.Entity.Name},Instance | %{
|
||||||
|
New-Object PSObject -Property @{
|
||||||
|
VM = $_.Values[0]
|
||||||
|
Disk = $_.Values[1]
|
||||||
|
IOPSWriteAvg = [math]::round( ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "virtualdisk.numberwriteaveraged.average"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average,2)
|
||||||
|
IOPSReadAvg = [math]::round( ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "virtualdisk.numberreadaveraged.average"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average,2)
|
||||||
|
Datastore = $hdTab[$_.Values[0] + "/"+ $_.Values[1]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create Report completed"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Else {
|
||||||
|
Write-Error "VM $($_.Name) is Powered Off! Processing Skipped"
|
||||||
|
}
|
||||||
|
$reportPerf | Select-Object VM, Disk, Datastore, IOPSWriteAvg, IOPSReadAvg
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
# none
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
234
Modules/Konfig-ESXi/Konfig-ESXi.psm1
Normal file
234
Modules/Konfig-ESXi/Konfig-ESXi.psm1
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
function Konfig-ESXi {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2016.12 ver 1.0 Base Release
|
||||||
|
2016.12 ver 1.1 ESXi 6.5 Tests, Minor enhancements
|
||||||
|
===========================================================================
|
||||||
|
External Code Sources:
|
||||||
|
Function My-Logger : http://www.virtuallyghetto.com/
|
||||||
|
===========================================================================
|
||||||
|
Tested Against Environment:
|
||||||
|
vSphere Version: ESXi 5.5 U2, ESXi 6.5
|
||||||
|
PowerCLI Version: PowerCLI 6.3 R1, PowerCLI 6.5 R1
|
||||||
|
PowerShell Version: 4.0, 5.0
|
||||||
|
OS Version: Windows 8.1, Server 2012 R2
|
||||||
|
Keyword: ESXi, NTP, SSH, Syslog, SATP,
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This Function sets the Basic settings for a new ESXi.
|
||||||
|
|
||||||
|
* NTP
|
||||||
|
* SSH
|
||||||
|
* Syslog
|
||||||
|
* Power Management
|
||||||
|
* HP 3PAR SATP/PSP Rule
|
||||||
|
* ...
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Konfig-ESXi -VMHost myesxi.lan.local -NTP 192.168.2.1, 192.168.2.2 -syslog "udp://loginsight.lan.local:514"
|
||||||
|
|
||||||
|
.PARAMETER VMHost
|
||||||
|
Host to configure.
|
||||||
|
|
||||||
|
.PARAMETER NTP
|
||||||
|
NTP Server(s) to set.
|
||||||
|
|
||||||
|
.PARAMETER Syslog
|
||||||
|
Syslog Server to set, e.g. "udp://loginsight.lan.local:514"
|
||||||
|
|
||||||
|
DNS Name must be resolvable!
|
||||||
|
|
||||||
|
|
||||||
|
#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)]
|
||||||
|
[String] $VMHost,
|
||||||
|
[Parameter(Mandatory=$true, ValueFromPipeline=$False, Position=1)]
|
||||||
|
[array]$NTP,
|
||||||
|
[Parameter(Mandatory=$true, ValueFromPipeline=$False, Position=2)]
|
||||||
|
[String] $syslog
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
Begin {
|
||||||
|
Function My-Logger {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[String]$message
|
||||||
|
)
|
||||||
|
|
||||||
|
$timeStamp = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
|
||||||
|
|
||||||
|
Write-Host -NoNewline -ForegroundColor White "[$timestamp]"
|
||||||
|
Write-Host -ForegroundColor Green " $message"
|
||||||
|
}
|
||||||
|
function Set-MyESXiOption {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$True, ValueFromPipeline=$False, Position=0)]
|
||||||
|
[String] $Name,
|
||||||
|
[Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=1)]
|
||||||
|
[String] $Value
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$myESXiOption = Get-AdvancedSetting -Entity $ESXiHost -Name $Name
|
||||||
|
if ($myESXiOption.Value -ne $Value) {
|
||||||
|
My-Logger " Setting ESXi Option $Name to Value $Value"
|
||||||
|
$myESXiOption | Set-AdvancedSetting -Value $Value -Confirm:$false | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
My-Logger " ESXi Option $Name already has Value $Value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
$Validate = $True
|
||||||
|
|
||||||
|
#region: Start vCenter Connection
|
||||||
|
My-Logger "Starting to Process ESXi Server Connection to $VMHost ..."
|
||||||
|
if (($global:DefaultVIServers).count -gt 0) {
|
||||||
|
Disconnect-VIServer -Force -Confirm:$False -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
$VIConnection = Connect-VIServer -Server $VMHost
|
||||||
|
if (-not $VIConnection.IsConnected) {
|
||||||
|
Write-Error "ESXi Connection Failed."
|
||||||
|
$Validate = $False
|
||||||
|
}
|
||||||
|
elseif ($VIConnection.ProductLine -ne "EmbeddedEsx") {
|
||||||
|
Write-Error "Connencted System is not an ESXi."
|
||||||
|
$Validate = $False
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ESXiHost = Get-VMHost
|
||||||
|
My-Logger "Connected ESXi Version: $($ESXiHost.Version) $($ESXiHost.Build) "
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
if ($Validate -eq $True) {
|
||||||
|
|
||||||
|
#region: Enable SSH and disable SSH Warning
|
||||||
|
$SSHService = $ESXiHost | Get-VMHostService | where {$_.Key -eq 'TSM-SSH'}
|
||||||
|
My-Logger "Starting SSH Service..."
|
||||||
|
if($SSHService.Running -ne $True){
|
||||||
|
Start-VMHostService -HostService $SSHService -Confirm:$false | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
My-Logger " SSH Service is already running"
|
||||||
|
}
|
||||||
|
My-Logger "Setting SSH Service to Automatic Start..."
|
||||||
|
if($SSHService.Policy -ne "automatic"){
|
||||||
|
Set-VMHostService -HostService $SSHService -Policy "Automatic" | Out-Null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
My-Logger " SSH Service is already set to Automatic Start"
|
||||||
|
}
|
||||||
|
My-Logger "Disabling SSH Warning..."
|
||||||
|
Set-MyESXiOption -Name "UserVars.SuppressShellWarning" -Value "1"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Config NTP
|
||||||
|
My-Logger "Removing existing NTP Server..."
|
||||||
|
try {
|
||||||
|
$ESXiHost | Remove-VMHostNtpServer -NtpServer (Get-VMHostNtpServer) -Confirm:$false
|
||||||
|
}
|
||||||
|
catch [System.Exception] {
|
||||||
|
Write-Warning "Error during removing existing NTP Servers."
|
||||||
|
}
|
||||||
|
My-Logger "Setting new NTP Servers..."
|
||||||
|
foreach ($myNTP in $NTP) {
|
||||||
|
$ESXiHost | Add-VMHostNtpServer -ntpserver $myNTP -confirm:$False | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
My-Logger "Configure NTP Service..."
|
||||||
|
$NTPService = $ESXiHost | Get-VMHostService| Where-Object {$_.key -eq "ntpd"}
|
||||||
|
if($NTPService.Running -eq $True){
|
||||||
|
Stop-VMHostService -HostService $NTPService -Confirm:$false | Out-Null
|
||||||
|
}
|
||||||
|
if($NTPService.Policy -ne "on"){
|
||||||
|
Set-VMHostService -HostService $NTPService -Policy "on" -confirm:$False | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
My-Logger "Configure Local Time..."
|
||||||
|
$HostTimeSystem = Get-View $ESXiHost.ExtensionData.ConfigManager.DateTimeSystem
|
||||||
|
$HostTimeSystem.UpdateDateTime([DateTime]::UtcNow)
|
||||||
|
|
||||||
|
My-Logger "Start NTP Service..."
|
||||||
|
Start-VMHostService -HostService $NTPService -confirm:$False | Out-Null
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Remove default PG
|
||||||
|
My-Logger "Checking for Default Port Group ..."
|
||||||
|
if ($defaultPG = $ESXiHost | Get-VirtualSwitch -Name vSwitch0 | Get-VirtualPortGroup -Name "VM Network" -ErrorAction SilentlyContinue ){
|
||||||
|
Remove-VirtualPortGroup -VirtualPortGroup $defaultPG -confirm:$False | Out-Null
|
||||||
|
My-Logger " Default PG Removed"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
My-Logger " No Default PG found"
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Configure Static HighPower
|
||||||
|
My-Logger "Setting PowerProfile to Static HighPower..."
|
||||||
|
try {
|
||||||
|
$HostView = ($ESXiHost | Get-View)
|
||||||
|
(Get-View $HostView.ConfigManager.PowerSystem).ConfigurePowerPolicy(1)
|
||||||
|
}
|
||||||
|
catch [System.Exception] {
|
||||||
|
Write-Warning "Error during Configure Static HighPower. See latest errors..."
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Conf Syslog
|
||||||
|
My-Logger "Setting Syslog Firewall Rule ..."
|
||||||
|
$SyslogFW = ($ESXiHost | Get-VMHostFirewallException | where {$_.Name -eq 'syslog'})
|
||||||
|
if ($SyslogFW.Enabled -eq $False ){
|
||||||
|
$SyslogFW | Set-VMHostFirewallException -Enabled:$true -Confirm:$false | Out-Null
|
||||||
|
My-Logger " Syslog Firewall Rule enabled"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
My-Logger " Syslog Firewall Rule already enabled"
|
||||||
|
}
|
||||||
|
My-Logger "Setting Syslog Server..."
|
||||||
|
Set-MyESXiOption -Name "Syslog.global.logHost" -Value $syslog
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Change Disk Scheduler
|
||||||
|
My-Logger "Changing Disk Scheduler..."
|
||||||
|
Set-MyESXiOption -Name "Disk.SchedulerWithReservation" -Value "0"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Configure HP 3PAR SATP/PSP Rule
|
||||||
|
My-Logger "Configure HP 3PAR SATP/PSP Rule"
|
||||||
|
$esxcli2 = Get-ESXCLI -VMHost $ESXiHost -V2
|
||||||
|
$arguments = $esxcli2.storage.nmp.satp.rule.add.CreateArgs()
|
||||||
|
$arguments.satp = "VMW_SATP_ALUA"
|
||||||
|
$arguments.psp = "VMW_PSP_RR"
|
||||||
|
$arguments.pspoption = "iops=100"
|
||||||
|
$arguments.claimoption = "tpgs_on"
|
||||||
|
$arguments.vendor = "3PARdata"
|
||||||
|
$arguments.model = "VV"
|
||||||
|
$arguments.description = "HP 3PAR custom SATP Claimrule"
|
||||||
|
try {
|
||||||
|
$esxcli2.storage.nmp.satp.rule.add.Invoke($arguments)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Warning "Error during Configure HP 3PAR SATP/PSP Rule. See latest errors..."
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
123
Modules/PSvLIMessage/PSvLIMessage.psm1
Normal file
123
Modules/PSvLIMessage/PSvLIMessage.psm1
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
add-type @"
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
public class TrustAllCertsPolicy : ICertificatePolicy {
|
||||||
|
public bool CheckValidationResult(
|
||||||
|
ServicePoint srvPoint, X509Certificate certificate,
|
||||||
|
WebRequest request, int certificateProblem) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
||||||
|
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Organization: Private
|
||||||
|
Personal Blog: mycloudrevolution.com
|
||||||
|
Twitter: @vMarkus_K
|
||||||
|
===========================================================================
|
||||||
|
Tested Against Environment:
|
||||||
|
vRealize Log Insight 3.3.1
|
||||||
|
PowerShell Version: 4.0, 5.0
|
||||||
|
OS Version: Windows 8.1, Server 2012 R2
|
||||||
|
Keyword: vRealize, RestAPI
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
PowerCLI Version: PowerCLI 6.3 R1
|
||||||
|
|
||||||
|
.SYNOPSIS
|
||||||
|
Push Messages to VMware vRealize Log Insight.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Creates a Messages in VMware vRealize Log Insight via the Ingestion API
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Push-vLIMessage -vLIServer "loginsight.lan.local" -vLIAgentID "12862842-5A6D-679C-0E38-0E2BE888BB28" -Text "My Test"
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Push-vLIMessage -vLIServer "loginsight.lan.local" -vLIAgentID "12862842-5A6D-679C-0E38-0E2BE888BB28" -Text "My Test" -Hostname MyTEST -FieldName myTest -FieldContent myTest
|
||||||
|
|
||||||
|
.PARAMETER vLIServer
|
||||||
|
Specify the FQDN of your vRealize Log Insight Appliance
|
||||||
|
|
||||||
|
.PARAMETER vLIAgentID
|
||||||
|
Specify the vRealize Log Insight Agent ID, e.g. "12862842-5A6D-679C-0E38-0E2BE888BB28"
|
||||||
|
|
||||||
|
.PARAMETER Text
|
||||||
|
Specify the Event Text
|
||||||
|
|
||||||
|
.PARAMETER Hostname
|
||||||
|
Specify the Hostanme displayed in vRealize Log Insight
|
||||||
|
|
||||||
|
.PARAMETER FieldName
|
||||||
|
Specify the a Optional Field Name for vRealize Log Insight
|
||||||
|
|
||||||
|
.PARAMETER FieldContent
|
||||||
|
Specify the a Optional FieldContent for the Field in -FieldName for vRealize Log Insight
|
||||||
|
If FielName is missing and FieldContent is given, it will be ignored
|
||||||
|
|
||||||
|
#Requires PS -Version 3.0
|
||||||
|
|
||||||
|
#>
|
||||||
|
function Push-vLIMessage {
|
||||||
|
|
||||||
|
[cmdletbinding()]
|
||||||
|
param (
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$Text,
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$vLIServer,
|
||||||
|
[parameter(Mandatory=$true)]
|
||||||
|
[string]$vLIAgentID,
|
||||||
|
[parameter(Mandatory=$false)]
|
||||||
|
[string]$Hostname = $env:computername,
|
||||||
|
[parameter(Mandatory=$false)]
|
||||||
|
[string]$FieldName,
|
||||||
|
[parameter(Mandatory=$false)]
|
||||||
|
[string]$FieldContent = ""
|
||||||
|
)
|
||||||
|
Process {
|
||||||
|
$Field_vLI = [ordered]@{
|
||||||
|
name = "PS_vLIMessage"
|
||||||
|
content = "true"
|
||||||
|
}
|
||||||
|
$Field_HostName = [ordered]@{
|
||||||
|
name = "hostname"
|
||||||
|
content = $Hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
$Fields = @($Field_vLI, $Field_HostName)
|
||||||
|
|
||||||
|
if ($FieldName) {
|
||||||
|
$Field_Custom = [ordered]@{
|
||||||
|
name = $FieldName
|
||||||
|
content = $FieldContent
|
||||||
|
}
|
||||||
|
$Fields += @($Field_Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Restcall = @{
|
||||||
|
messages = ([Object[]]([ordered]@{
|
||||||
|
text = ($Text)
|
||||||
|
fields = ([Object[]]$Fields)
|
||||||
|
}))
|
||||||
|
} | convertto-json -Depth 4
|
||||||
|
|
||||||
|
$Resturl = ("http://" + $vLIServer + ":9000/api/v1/messages/ingest/" + $vLIAgentID)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$Response = Invoke-RestMethod $Resturl -Method Post -Body $Restcall -ContentType 'application/json' -ErrorAction stop
|
||||||
|
Write-Information "REST Call to Log Insight server successful"
|
||||||
|
Write-Verbose $Response
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Write-Error "REST Call failed to Log Insight server"
|
||||||
|
Write-Verbose $error[0]
|
||||||
|
Write-Verbose $Resturl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
468
Modules/ProactiveHA/ProactiveHA.psm1
Normal file
468
Modules/ProactiveHA/ProactiveHA.psm1
Normal file
@@ -0,0 +1,468 @@
|
|||||||
|
Function New-PHAProvider {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to register a new Proactive HA Provider with vCenter Server
|
||||||
|
.PARAMETER ProviderName
|
||||||
|
Name of ProactiveHA Provider
|
||||||
|
.PARAMETER ComponentType
|
||||||
|
Name of a supported ComponentType that ProactiveHA supports (Fan, Memory, Network, Power or Storage)
|
||||||
|
.PARAMETER ComponentDescription
|
||||||
|
Description of the health check for the given component
|
||||||
|
.PARAMETER ComponentId
|
||||||
|
Unique identifier for the given component within a ProactiveHA Provider
|
||||||
|
.EXAMPLE
|
||||||
|
New-PHAProvider -ProviderName "virtuallyGhetto" -ComponentType Power -ComponentDescription "Simulated ProactiveHA Provider" -ComponentId "Power"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ProviderName,
|
||||||
|
[Parameter(Mandatory=$true)][ValidateSet("Fan","Memory","Network","Power","Storage")][String]$ComponentType,
|
||||||
|
[Parameter(Mandatory=$true)][String]$ComponentDescription,
|
||||||
|
[Parameter(Mandatory=$true)][String]$ComponentId
|
||||||
|
)
|
||||||
|
Write-Host -ForegroundColor Red "`n******************** DISCLAIMER ********************"
|
||||||
|
Write-Host -ForegroundColor Red "**** THIS IS NOT INTENDED FOR PRODUCTION USE ****"
|
||||||
|
Write-Host -ForegroundColor Red "**** LEARNING PURPOSES ONLY ****"
|
||||||
|
Write-Host -ForegroundColor Red "******************** DISCLAIMER ********************`n"
|
||||||
|
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
$healthInfo = [VMware.Vim.HealthUpdateInfo] @{
|
||||||
|
ComponentType = $ComponentType
|
||||||
|
description = $ComponentDescription
|
||||||
|
Id = $ComponentId
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "`nRegistering new Proactive HA Provider $ProviderName ..."
|
||||||
|
$providerId = $healthManager.RegisterHealthUpdateProvider($ProviderName,$healthInfo)
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-PHAProvider {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return list of all Proactive HA Providers registered with vCenter Server
|
||||||
|
.EXAMPLE
|
||||||
|
Get-PHAProvider
|
||||||
|
#>
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
$healthProviderResults = @()
|
||||||
|
$hpIDs = $healthManager.QueryProviderList()
|
||||||
|
|
||||||
|
foreach ($hpID in $hpIDs) {
|
||||||
|
$hpName = $healthManager.QueryProviderName($hpID)
|
||||||
|
$hpConfig = $healthManager.QueryHealthUpdateInfos($hpID)
|
||||||
|
|
||||||
|
$hp = [pscustomobject] @{
|
||||||
|
ProviderName = $hpName
|
||||||
|
ProviderID = $hpID
|
||||||
|
ComponentType = $hpConfig.componentType
|
||||||
|
ComponentID = $hpConfig.id
|
||||||
|
Description = $hpConfig.description
|
||||||
|
}
|
||||||
|
$healthProviderResults+=$hp
|
||||||
|
}
|
||||||
|
$healthProviderResults
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Remove-PHAProvider {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to remove a registered Proactive HA Provider from vCenter Server
|
||||||
|
.PARAMETER ProviderId
|
||||||
|
The ProactiveHA provider ID (retrieved from Get-PHAProvider) to unregister
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-PHAProvider -ProviderID "52 85 22 c2 f2 6a e7 b9-fc ff 63 9e 10 81 00 79"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ProviderId
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host -ForegroundColor Red "`n******************** DISCLAIMER ********************"
|
||||||
|
Write-Host -ForegroundColor Red "**** THIS IS NOT INTENDED FOR PRODUCTION USE ****"
|
||||||
|
Write-Host -ForegroundColor Red "**** LEARNING PURPOSES ONLY ****"
|
||||||
|
Write-Host -ForegroundColor Red "******************** DISCLAIMER ********************`n"
|
||||||
|
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "`nUnregistering Proactive HA Provider $ProviderId ... "
|
||||||
|
$healthManager.UnregisterHealthUpdateProvider($providerId)
|
||||||
|
} catch {
|
||||||
|
if($Error[0].Exception.InnerException.MethodFault.getType().Name -eq "InvalidState") {
|
||||||
|
Write-host -ForegroundColor Red "The Proactive HA Provider is still in use, please disable it before unregistering"
|
||||||
|
} else {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Set-PHAConfig {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to enable/disable Proactive HA for vSphere Cluster
|
||||||
|
.PARAMETER Cluster
|
||||||
|
Name of the vSphere Cluster to enable Proactive HA
|
||||||
|
.PARAMETER ProviderId
|
||||||
|
Proactive HA Provider ID to enable in vSphere Cluster
|
||||||
|
.PARAMETER ClusterMode
|
||||||
|
Whether Proactive HA should be "Automated" or "Manual" for actions it will take
|
||||||
|
.PARAMETER ModerateRemediation
|
||||||
|
Type of operation (Maintenance Mode or Quaratine Mode) to perform when a Moderate issue is observed
|
||||||
|
.PARAMETER SevereRemediation
|
||||||
|
Type of operation (Maintenance Mode or Quaratine Mode) to perform when a Severe issue is observed
|
||||||
|
.EXAMPLE
|
||||||
|
Set-PHAConfig -Cluster VSAN-Cluster -Enabled -ClusterMode Automated -ModerateRemediation QuarantineMode -SevereRemediation QuarantineMode -ProviderID "52 85 22 c2 f2 6a e7 b9-fc ff 63 9e 10 81 00 79"
|
||||||
|
.EXAMPLE
|
||||||
|
Set-PHAConfig -Cluster VSAN-Cluster -Disabled -ProviderID "52 85 22 c2 f2 6a e7 b9-fc ff 63 9e 10 81 00 79"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ProviderId,
|
||||||
|
[Parameter(Mandatory=$true)][String]$Cluster,
|
||||||
|
[Parameter(Mandatory=$false)][ValidateSet("Automated","Manual")]$ClusterMode="Manual",
|
||||||
|
[Parameter(Mandatory=$false)][ValidateSet("MaintenanceMode","QuarantineMode")]$ModerateRemediation="QuarantineMode",
|
||||||
|
[Parameter(Mandatory=$false)][ValidateSet("MaintenanceMode","QuarantineMode")]$SevereRemediation="QuarantineMode",
|
||||||
|
[Switch]$Enabled,
|
||||||
|
[Switch]$Disabled
|
||||||
|
)
|
||||||
|
|
||||||
|
$ClusterView = Get-View -ViewType ClusterComputeResource -Property Name,Host,ConfigurationEx -Filter @{"Name" = $Cluster}
|
||||||
|
|
||||||
|
if($ClusterView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Unable to find vSphere Cluster $cluster ..."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmhosts = $ClusterView.host
|
||||||
|
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
if($Enabled) {
|
||||||
|
try {
|
||||||
|
$entities = @()
|
||||||
|
foreach ($vmhost in $vmhosts) {
|
||||||
|
if(-not $healthManager.HasMonitoredEntity($ProviderId,$vmhost)) {
|
||||||
|
$entities += $vmhost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Enabling Proactive HA monitoring for all ESXi hosts in cluster ..."
|
||||||
|
$healthManager.AddMonitoredEntities($ProviderId,$entities)
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$healthProviders = @()
|
||||||
|
|
||||||
|
# Make sure not to remove existing ProactiveHA providers
|
||||||
|
if($ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers -ne $null) {
|
||||||
|
$currentHPs = $ClusterView.ConfigurationEx.infraUpdateHaConfig.providers
|
||||||
|
foreach ($currentHP in $currentHPs) {
|
||||||
|
$healthProviders+=$currentHP
|
||||||
|
}
|
||||||
|
if(-not ($healthProviders -contains $ProviderID)) {
|
||||||
|
$healthProviders+=$ProviderId
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$healthProviders+=$ProviderId
|
||||||
|
}
|
||||||
|
|
||||||
|
$PHASpec = [VMware.Vim.ClusterInfraUpdateHaConfigInfo] @{
|
||||||
|
enabled = $true
|
||||||
|
behavior = $ClusterMode
|
||||||
|
moderateRemediation = $ModerateRemediation
|
||||||
|
severeRemediation = $SevereRemediation
|
||||||
|
providers = $healthProviders
|
||||||
|
}
|
||||||
|
|
||||||
|
$spec = [VMware.Vim.ClusterConfigSpecEx] @{
|
||||||
|
infraUpdateHaConfig = $PHASpec
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Enabling Proactive HA Provider $ProviderId on $Cluster ..."
|
||||||
|
$task = $ClusterView.ReconfigureComputeResource_Task($spec,$True)
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Disabled) {
|
||||||
|
foreach ($vmhost in $vmhosts) {
|
||||||
|
if($vmhost.runtime.inQuarantineMode) {
|
||||||
|
Write-Host -ForegroundColor Red $vmhost.name " is currently still in Quaratine Mode, please remediate this before disabling Proactive HA"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$healthProviders = @()
|
||||||
|
|
||||||
|
# Make sure not to remove existing ProactiveHA providers
|
||||||
|
if($ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers -ne $null) {
|
||||||
|
$currentHPs = $ClusterView.ConfigurationEx.infraUpdateHaConfig.providers
|
||||||
|
foreach ($currentHP in $currentHPs) {
|
||||||
|
if($currentHP -ne $ProviderId) {
|
||||||
|
$healthProviders+=$currentHP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$PHASpec = [VMware.Vim.ClusterInfraUpdateHaConfigInfo] @{
|
||||||
|
enabled = $true
|
||||||
|
behavior = $ClusterMode
|
||||||
|
moderateRemediation = $ModerateRemediation
|
||||||
|
severeRemediation = $SevereRemediation
|
||||||
|
providers = $healthProviders
|
||||||
|
}
|
||||||
|
|
||||||
|
$spec = [VMware.Vim.ClusterConfigSpecEx] @{
|
||||||
|
infraUpdateHaConfig = $PHASpec
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Disabling Proactive HA Provider $ProviderId on $Cluster ..."
|
||||||
|
$task = $ClusterView.ReconfigureComputeResource_Task($spec,$True)
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task | Out-Null
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
|
||||||
|
$ClusterView.UpdateViewData()
|
||||||
|
|
||||||
|
try {
|
||||||
|
$entities = @()
|
||||||
|
foreach ($vmhost in $vmhosts) {
|
||||||
|
if($healthManager.HasMonitoredEntity($ProviderId,$vmhost)) {
|
||||||
|
$entities += $vmhost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Disabling Proactive HA monitoring for all ESXi hosts in cluster ..."
|
||||||
|
$healthManager.RemoveMonitoredEntities($ProviderId,$entities)
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-PHAConfig {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to retrieve Proactive HA configuration for a vSphere Cluster
|
||||||
|
.PARAMETER Cluster
|
||||||
|
Name of the vSphere Cluster to check Proactive HA configuration
|
||||||
|
.EXAMPLE
|
||||||
|
Get-PHAConfig -Cluster VSAN-Cluster
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$Cluster
|
||||||
|
)
|
||||||
|
|
||||||
|
$ClusterView = Get-View -ViewType ClusterComputeResource -Property Name,ConfigurationEx -Filter @{"Name" = $Cluster}
|
||||||
|
|
||||||
|
if($ClusterView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Unable to find vSphere Cluster $cluster ..."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if($ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers -ne $null) {
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
$phSettings = $ClusterView.ConfigurationEx.InfraUpdateHaConfig
|
||||||
|
$providers = $ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers
|
||||||
|
$healthProviders = @()
|
||||||
|
foreach ($provider in $providers) {
|
||||||
|
$providerName = $healthManager.QueryProviderName($provider)
|
||||||
|
$healthProviders+=$providerName
|
||||||
|
}
|
||||||
|
|
||||||
|
$pHAConfig = [pscustomobject] @{
|
||||||
|
Enabled = $phSettings.Enabled
|
||||||
|
ClusterMode = $phSettings.behavior
|
||||||
|
ModerateRemediation = $phSettings.ModerateRemediation
|
||||||
|
SevereRemediation = $phSettings.SevereRemediation
|
||||||
|
HealthProviders = $healthProviders
|
||||||
|
}
|
||||||
|
$pHAConfig
|
||||||
|
} else {
|
||||||
|
Write-Host "Proactive HA has not been configured on this vSphere Cluster"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-PHAHealth {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to retrieve the Proactive HA health info for all ESXi hosts in vSphere Cluster
|
||||||
|
.PARAMETER Cluster
|
||||||
|
Name of the vSphere Cluster to check Proactive HA health information
|
||||||
|
.EXAMPLE
|
||||||
|
Get-PHAHealth -Cluster VSAN-Cluster
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$Cluster
|
||||||
|
)
|
||||||
|
|
||||||
|
$ClusterView = Get-View -ViewType ClusterComputeResource -Property Name,ConfigurationEx -Filter @{"Name" = $Cluster}
|
||||||
|
|
||||||
|
if($ClusterView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Unable to find vSphere Cluster $cluster ..."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if($ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers -ne $null) {
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
$providers = $ClusterView.ConfigurationEx.InfraUpdateHaConfig.Providers
|
||||||
|
|
||||||
|
foreach ($provider in $providers) {
|
||||||
|
$providerName = $healthManager.QueryProviderName($provider)
|
||||||
|
$healthUpdates = $healthManager.QueryHealthUpdates($provider)
|
||||||
|
|
||||||
|
$healthResults = @()
|
||||||
|
Write-Host -NoNewline -ForegroundColor Magenta "Health summary for Proactive HA Provider $providerName`:`n"
|
||||||
|
foreach ($healthUpdate in $healthUpdates) {
|
||||||
|
$vmhost = Get-View $healthUpdate.Entity
|
||||||
|
|
||||||
|
$hr = [PSCustomObject] @{
|
||||||
|
Entity = $vmhost.name
|
||||||
|
Status = $healthUpdate.status
|
||||||
|
HealthComponentId = $healthUpdate.HealthUpdateInfoId
|
||||||
|
HealthUpdateId = $healthUpdate.Id
|
||||||
|
Remediation = $healthUpdate.Remediation
|
||||||
|
}
|
||||||
|
$healthResults+=$hr
|
||||||
|
}
|
||||||
|
$healthResults
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "Proactive HA has not been configured on this vSphere Cluster"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function New-PHASimulation {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VCHA Configuration
|
||||||
|
.PARAMETER ProviderId
|
||||||
|
The Proactive HA Provider ID that you like to simulate a health update from
|
||||||
|
.PARAMETER EsxiHost
|
||||||
|
The name of ESXi host to update the health on
|
||||||
|
.PARAMETER Component
|
||||||
|
The name of the matching component ID from Proactive HA Provider to simulate a health update from
|
||||||
|
.PARAMETER HealthStatus
|
||||||
|
The health value (green, yellow or red) for the given simulated health Update
|
||||||
|
.PARAMETER Remediation
|
||||||
|
The remediation message associated with simulated health update
|
||||||
|
.EXAMPLE
|
||||||
|
New-PHASimulation -EsxiHost vesxi65-4.primp-industries.com -Component Power -HealthStatus green -Remediation "" -ProviderId "52 85 22 c2 f2 6a e7 b9-fc ff 63 9e 10 81 00 79"
|
||||||
|
.EXAMPLE
|
||||||
|
New-PHASimulation -EsxiHost vesxi65-4.primp-industries.com -Component Power -HealthStatus red -Remediation "Please replace my virtual PSU" -ProviderId "52 85 22 c2 f2 6a e7 b9-fc ff 63 9e 10 81 00 79"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ProviderId,
|
||||||
|
[Parameter(Mandatory=$true)][String]$EsxiHost,
|
||||||
|
[Parameter(Mandatory=$true)][String]$Component,
|
||||||
|
[Parameter(Mandatory=$true)][ValidateSet("green","red","yellow")][String]$HealthStatus,
|
||||||
|
[Parameter(Mandatory=$false)][String]$Remediation
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host -ForegroundColor Red "`n******************** DISCLAIMER ********************"
|
||||||
|
Write-Host -ForegroundColor Red "**** THIS IS NOT INTENDED FOR PRODUCTION USE ****"
|
||||||
|
Write-Host -ForegroundColor Red "**** LEARNING PURPOSES ONLY ****"
|
||||||
|
Write-Host -ForegroundColor Red "******************** DISCLAIMER ********************`n"
|
||||||
|
|
||||||
|
$vmhost = Get-View -ViewType HostSystem -Property Name -Filter @{"name" = $EsxiHost}
|
||||||
|
|
||||||
|
if($vmhost -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "`nUnable to find ESXi host $EsxiHost ..."
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
$healthManager = Get-View $global:DefaultVIServer.ExtensionData.Content.HealthUpdateManager
|
||||||
|
|
||||||
|
# Randomly generating an ID for Health Update
|
||||||
|
# In general, you would want to generate a specific ID
|
||||||
|
# which can be referenced between ProactiveHA Provider
|
||||||
|
# and VMware logs for troubleshooting purposes
|
||||||
|
$HealthUpdateID = "vghetto-" + (Get-Random -Minimum 1 -Maximum 100000)
|
||||||
|
|
||||||
|
# All other Health Status can have a remediation message
|
||||||
|
# but for green, it must be an empty string or API call will fail
|
||||||
|
if($HealthStatus -eq "green") {
|
||||||
|
$Remediation = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
$healthUpdate = [VMware.Vim.HealthUpdate] @{
|
||||||
|
Entity = $vmhost.moref
|
||||||
|
HealthUpdateInfoId = $Component
|
||||||
|
Id = $HealthUpdateId
|
||||||
|
Status = $HealthStatus
|
||||||
|
Remediation = $Remediation
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "`nSimulating Proactive HA Health Update to ..."
|
||||||
|
Write-Host "`tHost: $EsxiHost "
|
||||||
|
Write-Host -NoNewline "`tStatus: "
|
||||||
|
Write-Host -ForegroundColor $HealthStatus "$HealthStatus"
|
||||||
|
Write-Host "`tRemediation Messsage: $Remediation"
|
||||||
|
$healthManager.PostHealthUpdates($providerId,$healthUpdate)
|
||||||
|
} catch {
|
||||||
|
Write-host -ForegroundColor Red $Error[0].Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
227
Modules/Recommend-Sizing/Recommend-Sizing.psm1
Normal file
227
Modules/Recommend-Sizing/Recommend-Sizing.psm1
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
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
|
||||||
|
2016.11 ver 1.2 VM Stats from Realtime Data and new Counters
|
||||||
|
===========================================================================
|
||||||
|
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, 6.0
|
||||||
|
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 Recommandation. 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 fully tested with vSphere 5.5 and vSphere 6.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=1, ParameterSetName = "Stats")]
|
||||||
|
[switch] $Stats,
|
||||||
|
[Parameter(Mandatory=$False, ValueFromPipeline=$False, Position=2, ParameterSetName = "Stats")]
|
||||||
|
[int] $StatsRange = 1440
|
||||||
|
|
||||||
|
)
|
||||||
|
Begin {
|
||||||
|
if ($Stats) {
|
||||||
|
Write-Warning "Stats Collection requested.`nAt the moment this is only fully tested with vSphere 5.5 and vSphere 6.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 VM Stats
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) VM Stats..."
|
||||||
|
$VMMetrics = "disk.numberwrite.summation","disk.numberread.summation","cpu.usage.average", "mem.usage.average"
|
||||||
|
$Start = (Get-Date).AddMinutes($TimeRange)
|
||||||
|
$VMStats = Get-Stat -Realtime -Stat $VMMetrics -Entity $ClusterVMsPoweredOn -Start $Start -Verbose:$False
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Create $($Cluster.name) VM Stats completed"
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Creating VM Stats Report
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Stats Report..."
|
||||||
|
$ReportVMPerf = @()
|
||||||
|
$ReportVMPerf = $VMStats | Group-Object -Property {$_.Entity.Name},Instance | %{
|
||||||
|
New-Object PSObject -Property @{
|
||||||
|
IOPSWriteAvg = ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "disk.numberwrite.summation"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average
|
||||||
|
IOPSReadAvg = ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "disk.numberread.summation"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average
|
||||||
|
CPUUsageAvg = ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "cpu.usage.average"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average
|
||||||
|
MEMUsageAvg = ($_.Group | `
|
||||||
|
where{$_.MetricId -eq "mem.usage.average"} | `
|
||||||
|
Measure-Object -Property Value -Average).Average
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Process $($Cluster.name) VM Stats Report completed"
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Stats Collection 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 )
|
||||||
|
AverageVMIOPSWriteAvg = [math]::round( ($ReportVMPerf | Measure-Object -Average -Property IOPSWriteAvg).Average,1 )
|
||||||
|
AverageVMIOPSReadAvg = [math]::round( ($ReportVMPerf | Measure-Object -Average -Property IOPSReadAvg).Average,1 )
|
||||||
|
AverageVMCPUUsageAvg = "$([math]::round( ($ReportVMPerf | Measure-Object -Average -Property CPUUsageAvg).Average,1 )) %"
|
||||||
|
AverageVMMEMUsageAvg = "$([math]::round( ($ReportVMPerf | Measure-Object -Average -Property MEMUsageAvg).Average,1 )) %"
|
||||||
|
}
|
||||||
|
$MyView += $SizingReport
|
||||||
|
Write-Verbose "$(Get-Date -Format G) Process Global Report completed"
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Else {
|
||||||
|
Write-Error "Validation Failed! Processing Skipped"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
End {
|
||||||
|
$MyView
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
111
Modules/Set-CBT/Set-CBT.psm1
Normal file
111
Modules/Set-CBT/Set-CBT.psm1
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
function Set-CBT {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2016.11 ver 1.0 Base Release
|
||||||
|
===========================================================================
|
||||||
|
External Code Sources:
|
||||||
|
http://wahlnetwork.com/2015/12/01/change-block-tracking-cbt-powercli/
|
||||||
|
===========================================================================
|
||||||
|
Tested Against Environment:
|
||||||
|
vSphere Version: 5.5 U2
|
||||||
|
PowerCLI Version: PowerCLI 6.3 R1
|
||||||
|
PowerShell Version: 4.0
|
||||||
|
OS Version: Windows Server 2012 R2
|
||||||
|
===========================================================================
|
||||||
|
Keywords vSphere, ESXi, VM, Storage, CBT, Backup
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This Function enables or disables CBT.
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-VN TST* | Set-CBT -DisableCBT
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-VN TST* | Set-CBT -EnableCBT
|
||||||
|
|
||||||
|
.PARAMETER DisableCBT
|
||||||
|
Disables CBT for any VMs found with it enabled
|
||||||
|
|
||||||
|
.PARAMETER EnableCBT
|
||||||
|
Enables CBT for any VMs found with it disabled
|
||||||
|
|
||||||
|
#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, HelpMessage = "VMs to process")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] $myVMs,
|
||||||
|
[Parameter(Mandatory = $False,ValueFromPipeline=$False, Position = 1, HelpMessage = "Enables CBT for any VMs found with it disabled", ParameterSetName = "EnableCBT")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[Switch]$EnableCBT,
|
||||||
|
[Parameter(Mandatory = $False,ValueFromPipeline=$False, Position = 1, HelpMessage = "Disables CBT for any VMs found with it enabled", ParameterSetName = "DisableCBT")]
|
||||||
|
[ValidateNotNullorEmpty()]
|
||||||
|
[Switch]$DisableCBT
|
||||||
|
)
|
||||||
|
Process {
|
||||||
|
|
||||||
|
$vmconfigspec = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec
|
||||||
|
Write-Verbose -Message "Walking through given VMs"
|
||||||
|
foreach($myVM in $myVMs)
|
||||||
|
{
|
||||||
|
if ($DisableCBT -and $myVM.ExtensionData.Config.ChangeTrackingEnabled -eq $true -and $myVM.ExtensionData.Snapshot -eq $null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Write-Verbose -Message "Reconfiguring $($myVM.name) to disable CBT" -Verbose
|
||||||
|
$vmconfigspec.ChangeTrackingEnabled = $false
|
||||||
|
$myVM.ExtensionData.ReconfigVM($vmconfigspec)
|
||||||
|
|
||||||
|
if ($myVM.PowerState -eq "PoweredOn" ) {
|
||||||
|
Write-Verbose -Message "Creating a snapshot on $($myVM.name) to clear CBT file" -Verbose
|
||||||
|
$SnapShot = New-Snapshot -VM $myVM -Name "CBT Cleanup"
|
||||||
|
|
||||||
|
Write-Verbose -Message "Removing snapshot on $($myVM.name)" -Verbose
|
||||||
|
$SnapShot| Remove-Snapshot -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw $myVM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($EnableCBT -and $myVM.ExtensionData.Config.ChangeTrackingEnabled -eq $false -and $myVM.ExtensionData.Snapshot -eq $null)
|
||||||
|
{
|
||||||
|
Write-Verbose -Message "Reconfiguring $($myVM.name) to enable CBT" -Verbose
|
||||||
|
$vmconfigspec.ChangeTrackingEnabled = $true
|
||||||
|
$myVM.ExtensionData.ReconfigVM($vmconfigspec)
|
||||||
|
|
||||||
|
if ($myVM.PowerState -eq "PoweredOn" ) {
|
||||||
|
Write-Verbose -Message "Creating a snapshot on $($myVM.name) to Create CBT file" -Verbose
|
||||||
|
$SnapShot = New-Snapshot -VM $myVM -Name "CBT Cleanup"
|
||||||
|
|
||||||
|
Write-Verbose -Message "Removing snapshot on $($myVM.name)" -Verbose
|
||||||
|
$SnapShot | Remove-Snapshot -Confirm:$false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($myVM.ExtensionData.Snapshot -ne $null -and $EnableCBT)
|
||||||
|
{
|
||||||
|
Write-Warning -Message "Skipping $($myVM.name) - Snapshots found"
|
||||||
|
}
|
||||||
|
elseif ($myVM.ExtensionData.Snapshot -ne $null -and $DisableCBT)
|
||||||
|
{
|
||||||
|
Write-Warning -Message "Skipping $($myVM.name) - Snapshots found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
99
Modules/Start-UNMAP/Start-UNMAP.psm1
Normal file
99
Modules/Start-UNMAP/Start-UNMAP.psm1
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
716
Modules/VAMI/VAMI.psm1
Executable file
716
Modules/VAMI/VAMI.psm1
Executable file
@@ -0,0 +1,716 @@
|
|||||||
|
Function Get-VAMISummary {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves some basic information from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return basic VAMI summary info
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMISummary
|
||||||
|
#>
|
||||||
|
$systemVersionAPI = Get-CisService -Name 'com.vmware.appliance.system.version'
|
||||||
|
$results = $systemVersionAPI.get() | select product, type, version, build, install_time
|
||||||
|
|
||||||
|
$systemUptimeAPI = Get-CisService -Name 'com.vmware.appliance.system.uptime'
|
||||||
|
$ts = [timespan]::fromseconds($systemUptimeAPI.get().toString())
|
||||||
|
$uptime = $ts.ToString("hh\:mm\:ss\,fff")
|
||||||
|
|
||||||
|
$summaryResult = [pscustomobject] @{
|
||||||
|
Product = $results.product;
|
||||||
|
Type = $results.type;
|
||||||
|
Version = $results.version;
|
||||||
|
Build = $results.build;
|
||||||
|
InstallTime = $results.install_time;
|
||||||
|
Uptime = $uptime
|
||||||
|
}
|
||||||
|
$summaryResult
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIHealth {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves health information from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VAMI health
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIHealth
|
||||||
|
#>
|
||||||
|
$healthOverall = (Get-CisService -Name 'com.vmware.appliance.health.system').get()
|
||||||
|
$healthLastCheck = (Get-CisService -Name 'com.vmware.appliance.health.system').lastcheck()
|
||||||
|
$healthCPU = (Get-CisService -Name 'com.vmware.appliance.health.load').get()
|
||||||
|
$healthMem = (Get-CisService -Name 'com.vmware.appliance.health.mem').get()
|
||||||
|
$healthSwap = (Get-CisService -Name 'com.vmware.appliance.health.swap').get()
|
||||||
|
$healthStorage = (Get-CisService -Name 'com.vmware.appliance.health.storage').get()
|
||||||
|
|
||||||
|
# DB health only applicable for Embedded/External VCSA Node
|
||||||
|
$vami = (Get-CisService -Name 'com.vmware.appliance.system.version').get()
|
||||||
|
|
||||||
|
if($vami.type -eq "vCenter Server with an embedded Platform Services Controller" -or $vami.type -eq "vCenter Server with an external Platform Services Controller") {
|
||||||
|
$healthVCDB = (Get-CisService -Name 'com.vmware.appliance.health.databasestorage').get()
|
||||||
|
} else {
|
||||||
|
$healthVCDB = "N/A"
|
||||||
|
}
|
||||||
|
$healthSoftwareUpdates = (Get-CisService -Name 'com.vmware.appliance.health.softwarepackages').get()
|
||||||
|
|
||||||
|
$healthResult = [pscustomobject] @{
|
||||||
|
HealthOverall = $healthOverall;
|
||||||
|
HealthLastCheck = $healthLastCheck;
|
||||||
|
HealthCPU = $healthCPU;
|
||||||
|
HealthMem = $healthMem;
|
||||||
|
HealthSwap = $healthSwap;
|
||||||
|
HealthStorage = $healthStorage;
|
||||||
|
HealthVCDB = $healthVCDB;
|
||||||
|
HealthSoftware = $healthSoftwareUpdates
|
||||||
|
}
|
||||||
|
$healthResult
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIAccess {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves access information from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VAMI access interfaces (Console,DCUI,Bash Shell & SSH)
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIAccess
|
||||||
|
#>
|
||||||
|
$consoleAccess = (Get-CisService -Name 'com.vmware.appliance.access.consolecli').get()
|
||||||
|
$dcuiAccess = (Get-CisService -Name 'com.vmware.appliance.access.dcui').get()
|
||||||
|
$shellAccess = (Get-CisService -Name 'com.vmware.appliance.access.shell').get()
|
||||||
|
$sshAccess = (Get-CisService -Name 'com.vmware.appliance.access.ssh').get()
|
||||||
|
|
||||||
|
$accessResult = New-Object PSObject -Property @{
|
||||||
|
Console = $consoleAccess;
|
||||||
|
DCUI = $dcuiAccess;
|
||||||
|
BashShell = $shellAccess.enabled;
|
||||||
|
SSH = $sshAccess
|
||||||
|
}
|
||||||
|
$accessResult
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMITime {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves the time and NTP info from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return current Time and NTP information
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMITime
|
||||||
|
#>
|
||||||
|
$systemTimeAPI = Get-CisService -Name 'com.vmware.appliance.system.time'
|
||||||
|
$timeResults = $systemTimeAPI.get()
|
||||||
|
|
||||||
|
$timeSync = (Get-CisService -Name 'com.vmware.appliance.techpreview.timesync').get()
|
||||||
|
$timeSyncMode = $timeSync.mode
|
||||||
|
|
||||||
|
$timeResult = [pscustomobject] @{
|
||||||
|
Timezone = $timeResults.timezone;
|
||||||
|
Date = $timeResults.date;
|
||||||
|
CurrentTime = $timeResults.time;
|
||||||
|
Mode = $timeSyncMode;
|
||||||
|
NTPServers = "N/A";
|
||||||
|
NTPStatus = "N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($timeSyncMode -eq "NTP") {
|
||||||
|
$ntpServers = (Get-CisService -Name 'com.vmware.appliance.techpreview.ntp').get()
|
||||||
|
$timeResult.NTPServers = $ntpServers.servers
|
||||||
|
$timeResult.NTPStatus = $ntpServers.status
|
||||||
|
}
|
||||||
|
$timeResult
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMINetwork {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves network information from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return networking information including details for each interface
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMINetwork
|
||||||
|
#>
|
||||||
|
$netResults = @()
|
||||||
|
|
||||||
|
$Hostname = (Get-CisService -Name 'com.vmware.appliance.networking.dns.hostname').get()
|
||||||
|
$dns = (Get-CisService -Name 'com.vmware.appliance.networking.dns.servers').get()
|
||||||
|
|
||||||
|
Write-Host "Hostname: " $hostname
|
||||||
|
Write-Host "DNS Servers: " $dns.servers
|
||||||
|
|
||||||
|
$interfaces = (Get-CisService -Name 'com.vmware.appliance.networking.interfaces').list()
|
||||||
|
foreach ($interface in $interfaces) {
|
||||||
|
$ipv4API = (Get-CisService -Name 'com.vmware.appliance.techpreview.networking.ipv4')
|
||||||
|
$spec = $ipv4API.Help.get.interfaces.CreateExample()
|
||||||
|
$spec+= $interface.name
|
||||||
|
$ipv4result = $ipv4API.get($spec)
|
||||||
|
|
||||||
|
$interfaceResult = [pscustomobject] @{
|
||||||
|
Inteface = $interface.name;
|
||||||
|
MAC = $interface.mac;
|
||||||
|
Status = $interface.status;
|
||||||
|
Mode = $ipv4result.mode;
|
||||||
|
IP = $ipv4result.address;
|
||||||
|
Prefix = $ipv4result.prefix;
|
||||||
|
Gateway = $ipv4result.default_gateway;
|
||||||
|
Updateable = $ipv4result.updateable
|
||||||
|
}
|
||||||
|
$netResults += $interfaceResult
|
||||||
|
}
|
||||||
|
$netResults
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIDisks {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves VMDK disk number to partition mapping VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VMDK disk number to OS partition mapping
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIDisks
|
||||||
|
#>
|
||||||
|
$storageAPI = Get-CisService -Name 'com.vmware.appliance.system.storage'
|
||||||
|
$disks = $storageAPI.list()
|
||||||
|
|
||||||
|
foreach ($disk in $disks | sort {[int]$_.disk.toString()}) {
|
||||||
|
$disk | Select Disk, Partition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Start-VAMIDiskResize {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function triggers an OS partition resize after adding additional disk capacity
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function triggers OS partition resize operation
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Start-VAMIDiskResize
|
||||||
|
#>
|
||||||
|
$storageAPI = Get-CisService -Name 'com.vmware.appliance.system.storage'
|
||||||
|
Write-Host "Initiated OS partition resize operation ..."
|
||||||
|
$storageAPI.resize()
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIStatsList {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves list avialable monitoring metrics in VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return list of available monitoring metrics that can be queried
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIStatsList
|
||||||
|
#>
|
||||||
|
$monitoringAPI = Get-CisService -Name 'com.vmware.appliance.monitoring'
|
||||||
|
$ids = $monitoringAPI.list() | Select id | Sort-Object -Property id
|
||||||
|
|
||||||
|
foreach ($id in $ids) {
|
||||||
|
$id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIStorageUsed {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves the individaul OS partition storage utilization
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return individual OS partition storage utilization
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIStorageUsed
|
||||||
|
#>
|
||||||
|
$monitoringAPI = Get-CisService 'com.vmware.appliance.monitoring'
|
||||||
|
$querySpec = $monitoringAPI.help.query.item.CreateExample()
|
||||||
|
|
||||||
|
# List of IDs from Get-VAMIStatsList to query
|
||||||
|
$querySpec.Names = @(
|
||||||
|
"storage.used.filesystem.autodeploy",
|
||||||
|
"storage.used.filesystem.boot",
|
||||||
|
"storage.used.filesystem.coredump",
|
||||||
|
"storage.used.filesystem.imagebuilder",
|
||||||
|
"storage.used.filesystem.invsvc",
|
||||||
|
"storage.used.filesystem.log",
|
||||||
|
"storage.used.filesystem.netdump",
|
||||||
|
"storage.used.filesystem.root",
|
||||||
|
"storage.used.filesystem.updatemgr",
|
||||||
|
"storage.used.filesystem.vcdb_core_inventory",
|
||||||
|
"storage.used.filesystem.vcdb_seat",
|
||||||
|
"storage.used.filesystem.vcdb_transaction_log",
|
||||||
|
"storage.totalsize.filesystem.autodeploy",
|
||||||
|
"storage.totalsize.filesystem.boot",
|
||||||
|
"storage.totalsize.filesystem.coredump",
|
||||||
|
"storage.totalsize.filesystem.imagebuilder",
|
||||||
|
"storage.totalsize.filesystem.invsvc",
|
||||||
|
"storage.totalsize.filesystem.log",
|
||||||
|
"storage.totalsize.filesystem.netdump",
|
||||||
|
"storage.totalsize.filesystem.root",
|
||||||
|
"storage.totalsize.filesystem.updatemgr",
|
||||||
|
"storage.totalsize.filesystem.vcdb_core_inventory",
|
||||||
|
"storage.totalsize.filesystem.vcdb_seat",
|
||||||
|
"storage.totalsize.filesystem.vcdb_transaction_log"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Tuple (Filesystem Name, Used, Total) to store results
|
||||||
|
$storageStats = @{
|
||||||
|
"autodeploy"=@{"name"="/storage/autodeploy";"used"=0;"total"=0};
|
||||||
|
"boot"=@{"name"="/boot";"used"=0;"total"=0};
|
||||||
|
"coredump"=@{"name"="/storage/core";"used"=0;"total"=0};
|
||||||
|
"imagebuilder"=@{"name"="/storage/imagebuilder";"used"=0;"total"=0};
|
||||||
|
"invsvc"=@{"name"="/storage/invsvc";"used"=0;"total"=0};
|
||||||
|
"log"=@{"name"="/storage/log";"used"=0;"total"=0};
|
||||||
|
"netdump"=@{"name"="/storage/netdump";"used"=0;"total"=0};
|
||||||
|
"root"=@{"name"="/";"used"=0;"total"=0};
|
||||||
|
"updatemgr"=@{"name"="/storage/updatemgr";"used"=0;"total"=0};
|
||||||
|
"vcdb_core_inventory"=@{"name"="/storage/db";"used"=0;"total"=0};
|
||||||
|
"vcdb_seat"=@{"name"="/storage/seat";"used"=0;"total"=0};
|
||||||
|
"vcdb_transaction_log"=@{"name"="/storage/dblog";"used"=0;"total"=0}
|
||||||
|
}
|
||||||
|
|
||||||
|
$querySpec.interval = "DAY1"
|
||||||
|
$querySpec.function = "MAX"
|
||||||
|
$querySpec.start_time = ((get-date).AddDays(-1))
|
||||||
|
$querySpec.end_time = (Get-Date)
|
||||||
|
$queryResults = $monitoringAPI.query($querySpec) | Select * -ExcludeProperty Help
|
||||||
|
|
||||||
|
foreach ($queryResult in $queryResults) {
|
||||||
|
# Update hash if its used storage results
|
||||||
|
if($queryResult.name -match "used") {
|
||||||
|
$key = (($queryResult.name).toString()).split(".")[-1]
|
||||||
|
$value = [Math]::Round([int]($queryResult.data[1]).toString()/1MB,2)
|
||||||
|
$storageStats[$key]["used"] = $value
|
||||||
|
# Update hash if its total storage results
|
||||||
|
} else {
|
||||||
|
$key = (($queryResult.name).toString()).split(".")[-1]
|
||||||
|
$value = [Math]::Round([int]($queryResult.data[1]).toString()/1MB,2)
|
||||||
|
$storageStats[$key]["total"] = $value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$storageResults = @()
|
||||||
|
foreach ($key in $storageStats.keys | Sort-Object -Property name) {
|
||||||
|
$statResult = [pscustomobject] @{
|
||||||
|
Filesystem = $storageStats[$key].name;
|
||||||
|
Used = $storageStats[$key].used;
|
||||||
|
Total = $storageStats[$key].total
|
||||||
|
}
|
||||||
|
$storageResults += $statResult
|
||||||
|
}
|
||||||
|
$storageResults
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIService {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves list of services in VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return list of services and their description
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIService
|
||||||
|
.EXAMPLE
|
||||||
|
Get-VAMIService -Name rbd
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$false,
|
||||||
|
ValueFromPipeline=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true)
|
||||||
|
]
|
||||||
|
[String]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
if($Name -ne "") {
|
||||||
|
$vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service'
|
||||||
|
|
||||||
|
try {
|
||||||
|
$serviceStatus = $vMonAPI.get($name,0)
|
||||||
|
$serviceString = [pscustomobject] @{
|
||||||
|
Name = $name;
|
||||||
|
State = $serviceStatus.state;
|
||||||
|
Health = "";
|
||||||
|
Startup = $serviceStatus.startup_type
|
||||||
|
}
|
||||||
|
if($serviceStatus.health -eq $null) { $serviceString.Health = "N/A"} else { $serviceString.Health = $serviceStatus.health }
|
||||||
|
$serviceString
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service'
|
||||||
|
$services = $vMonAPI.list_details()
|
||||||
|
|
||||||
|
$serviceResult = @()
|
||||||
|
foreach ($key in $services.keys | Sort-Object -Property Value) {
|
||||||
|
$serviceString = [pscustomobject] @{
|
||||||
|
Name = $key;
|
||||||
|
State = $services[$key].state;
|
||||||
|
Health = "N/A";
|
||||||
|
Startup = $services[$key].Startup_type
|
||||||
|
}
|
||||||
|
if($services[$key].health -eq $null) { $serviceString.Health = "N/A"} else { $serviceString.Health = $services[$key].health }
|
||||||
|
|
||||||
|
$serviceResult += $serviceString
|
||||||
|
}
|
||||||
|
$serviceResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Start-VAMIService {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves list of services in VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return list of services and their description
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Start-VAMIService -Name rbd
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true,
|
||||||
|
ValueFromPipeline=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true)
|
||||||
|
]
|
||||||
|
[String]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
$vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service'
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Starting $name service ..."
|
||||||
|
$vMonAPI.start($name)
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Stop-VAMIService {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves list of services in VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return list of services and their description
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Stop-VAMIService -Name rbd
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true,
|
||||||
|
ValueFromPipeline=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true)
|
||||||
|
]
|
||||||
|
[String]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
$vMonAPI = Get-CisService 'com.vmware.appliance.vmon.service'
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Stopping $name service ..."
|
||||||
|
$vMonAPI.stop($name)
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIBackupSize {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves the backup size of the VCSA from VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return the current backup size of the VCSA (common and core data)
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIBackupSize
|
||||||
|
#>
|
||||||
|
$recoveryAPI = Get-CisService 'com.vmware.appliance.recovery.backup.parts'
|
||||||
|
$backupParts = $recoveryAPI.list() | select id
|
||||||
|
|
||||||
|
$estimateBackupSize = 0
|
||||||
|
$backupPartSizes = ""
|
||||||
|
foreach ($backupPart in $backupParts) {
|
||||||
|
$partId = $backupPart.id.value
|
||||||
|
$partSize = $recoveryAPI.get($partId)
|
||||||
|
$estimateBackupSize += $partSize
|
||||||
|
$backupPartSizes += $partId + " data is " + $partSize + " MB`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Estimated Backup Size: $estimateBackupSize MB"
|
||||||
|
Write-Host $backupPartSizes
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VAMIUser {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves VAMI local users using VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to retrieve VAMI local users
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIUser
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$false,
|
||||||
|
ValueFromPipeline=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true)
|
||||||
|
]
|
||||||
|
[String]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
$userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user'
|
||||||
|
|
||||||
|
$userResults = @()
|
||||||
|
|
||||||
|
if($Name -ne "") {
|
||||||
|
try {
|
||||||
|
$user = $userAPI.get($name)
|
||||||
|
|
||||||
|
$userString = [pscustomobject] @{
|
||||||
|
User = $user.username
|
||||||
|
Name = $user.fullname
|
||||||
|
Email = $user.email
|
||||||
|
Status = $user.status
|
||||||
|
PasswordStatus = $user.passwordstatus
|
||||||
|
Role = $user.role
|
||||||
|
}
|
||||||
|
$userResults += $userString
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$users = $userAPI.list()
|
||||||
|
|
||||||
|
foreach ($user in $users) {
|
||||||
|
$userString = [pscustomobject] @{
|
||||||
|
User = $user.username
|
||||||
|
Name = $user.fullname
|
||||||
|
Email = $user.email
|
||||||
|
Status = $user.status
|
||||||
|
PasswordStatus = $user.passwordstatus
|
||||||
|
Role = $user.role
|
||||||
|
}
|
||||||
|
$userResults += $userString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$userResults
|
||||||
|
}
|
||||||
|
|
||||||
|
Function New-VAMIUser {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function to create new VAMI local user using VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to create a new VAMI local user
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
New-VAMIUser -name lamw -fullname "William Lam" -role "operator" -email "lamw@virtuallyghetto.com" -password "VMware1!"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true)
|
||||||
|
]
|
||||||
|
[String]$name,
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true)
|
||||||
|
]
|
||||||
|
[String]$fullname,
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true)
|
||||||
|
]
|
||||||
|
[ValidateSet("admin","operator","superAdmin")][String]$role,
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$false)
|
||||||
|
]
|
||||||
|
[String]$email="",
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true)
|
||||||
|
]
|
||||||
|
[String]$password
|
||||||
|
)
|
||||||
|
|
||||||
|
$userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user'
|
||||||
|
$createSpec = $userAPI.Help.add.config.CreateExample()
|
||||||
|
|
||||||
|
$createSpec.username = $name
|
||||||
|
$createSpec.fullname = $fullname
|
||||||
|
$createSpec.role = $role
|
||||||
|
$createSpec.email = $email
|
||||||
|
$createSpec.password = [VMware.VimAutomation.Cis.Core.Types.V1.Secret]$password
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Creating new user $name ..."
|
||||||
|
$userAPI.add($createSpec)
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Remove-VAMIUser {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function to remove VAMI local user using VAMI interface (5480)
|
||||||
|
for a VCSA node which can be an Embedded VCSA, External PSC or External VCSA.
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to remove VAMI local user
|
||||||
|
.EXAMPLE
|
||||||
|
Connect-CisServer -Server 192.168.1.51 -User administrator@vsphere.local -Password VMware1!
|
||||||
|
Get-VAMIAccess
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true)
|
||||||
|
]
|
||||||
|
[String]$name,
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$false)
|
||||||
|
]
|
||||||
|
[boolean]$confirm=$false
|
||||||
|
)
|
||||||
|
|
||||||
|
if(!$confirm) {
|
||||||
|
$answer = Read-Host -Prompt "Do you want to delete user $name (Y or N)"
|
||||||
|
if($answer -eq "Y" -or $answer -eq "y") {
|
||||||
|
$userAPI = Get-CisService 'com.vmware.appliance.techpreview.localaccounts.user'
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Deleting user $name ..."
|
||||||
|
$userAPI.delete($name)
|
||||||
|
} catch {
|
||||||
|
Write-Error $Error[0].exception.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
413
Modules/VCHA/VCHA.psm1
Normal file
413
Modules/VCHA/VCHA.psm1
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
Function Get-VCHAConfig {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Date: Nov 20, 2016
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves the VCHA Configuration which provides you with
|
||||||
|
the current state, mode as well as the IP Addresses of the Active,
|
||||||
|
Passive & Witness Node. This is only available on VCSA 6.5 (vSphere 6.5 or greater)
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VCHA Configuration
|
||||||
|
.EXAMPLE
|
||||||
|
Get-VCHAConfig
|
||||||
|
#>
|
||||||
|
$vcHAClusterConfig = Get-View failoverClusterConfigurator
|
||||||
|
$vcHAConfig = $vcHAClusterConfig.getVchaConfig()
|
||||||
|
|
||||||
|
$vcHAState = $vcHAConfig.State
|
||||||
|
switch($vcHAState) {
|
||||||
|
configured {
|
||||||
|
$activeIp = $vcHAConfig.FailoverNodeInfo1.ClusterIpSettings.Ip.IpAddress
|
||||||
|
$passiveIp = $vcHAConfig.FailoverNodeInfo2.ClusterIpSettings.Ip.IpAddress
|
||||||
|
$witnessIp = $vcHAConfig.WitnessNodeInfo.IpSettings.Ip.IpAddress
|
||||||
|
|
||||||
|
$vcHAClusterManager = Get-View failoverClusterManager
|
||||||
|
$vcHAMode = $vcHAClusterManager.getClusterMode()
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "VCHA State: "
|
||||||
|
Write-Host -ForegroundColor White "$vcHAState"
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green " VCHA Mode: "
|
||||||
|
Write-Host -ForegroundColor White "$vcHAMode"
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green " ActiveIP: "
|
||||||
|
Write-Host -ForegroundColor White "$activeIp"
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green " PassiveIP: "
|
||||||
|
Write-Host -ForegroundColor White "$passiveIp"
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green " WitnessIP: "
|
||||||
|
Write-Host -ForegroundColor White "$witnessIp`n"
|
||||||
|
;break
|
||||||
|
}
|
||||||
|
invalid { Write-Host -ForegroundColor Red "VCHA State is in invalid state ...";break}
|
||||||
|
notConfigured { Write-Host "VCHA is not configured";break}
|
||||||
|
prepared { Write-Host "VCHA is being prepared, please try again in a little bit ...";break}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-VCHAClusterHealth {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Date: Nov 20, 2016
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function retrieves the VCHA Cluster Health which provides more info
|
||||||
|
on each of the individual. This is only available on VCSA 6.5 (vSphere 6.5 or greater)
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to return VCHA Cluster Health
|
||||||
|
.EXAMPLE
|
||||||
|
Get-VCHAClusterHealth
|
||||||
|
#>
|
||||||
|
$vcHAClusterConfig = Get-View failoverClusterConfigurator
|
||||||
|
$vcHAConfig = $vcHAClusterConfig.getVchaConfig()
|
||||||
|
$vcHAState = $vcHAConfig.State
|
||||||
|
|
||||||
|
switch($vcHAState) {
|
||||||
|
invalid { Write-Host -ForegroundColor Red "VCHA State is in invalid state ...";break}
|
||||||
|
notConfigured { Write-Host "VCHA is not configured";break}
|
||||||
|
prepared { Write-Host "VCHA is being prepared ...";break}
|
||||||
|
configured {
|
||||||
|
$vcHAClusterManager = Get-View failoverClusterManager
|
||||||
|
$healthInfo = $vcHAClusterManager.GetVchaClusterHealth()
|
||||||
|
|
||||||
|
$vcClusterState = $healthInfo.RuntimeInfo.ClusterState
|
||||||
|
$nodeState = $healthInfo.RuntimeInfo.NodeInfo
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "VCHA Cluster State: "
|
||||||
|
Write-Host -ForegroundColor White "$vcClusterState"
|
||||||
|
Write-Host -NoNewline -ForegroundColor Green "VCHA Node Information: "
|
||||||
|
$nodeState | Select NodeIp, NodeRole, NodeState
|
||||||
|
;break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Set-VCHAClusterMode {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Date: Nov 20, 2016
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function allows you to set the mode of the VCHA Cluster whether
|
||||||
|
that is Enabled, Disabled or in Maintenance Mode. This is only available on VCSA 6.5 (vSphere 6.5 or greater)
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to set VCHA Cluster Mode
|
||||||
|
.EXAMPLE
|
||||||
|
Set-VCHAClusterMode -Enabled $true
|
||||||
|
.EXAMPLE
|
||||||
|
Set-VCHAClusterMode -Disabled $true
|
||||||
|
.EXAMPLE
|
||||||
|
Set-VCHAClusterMode -Maintenance $true
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Switch]$Enabled,
|
||||||
|
[Switch]$Disabled,
|
||||||
|
[Switch]$Maintenance
|
||||||
|
)
|
||||||
|
|
||||||
|
$vcHAClusterManager = Get-View failoverClusterManager
|
||||||
|
|
||||||
|
if($Enabled) {
|
||||||
|
Write-Host "Setting VCHA Cluster to Enabled ..."
|
||||||
|
$task = $vcHAClusterManager.setClusterMode_Task("enabled")
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task
|
||||||
|
} elseIf($Maintenance) {
|
||||||
|
Write-Host "Setting VCHA Cluster to Maintenance ..."
|
||||||
|
$task = $vcHAClusterManager.setClusterMode_Task("maintenance")
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task
|
||||||
|
} elseIf($Disabled) {
|
||||||
|
Write-Host "`nSetting VCHA Cluster to Disabled ...`n"
|
||||||
|
$task = $vcHAClusterManager.setClusterMode_Task("disabled")
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function New-VCHABasicConfig {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Date: Nov 20, 2016
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function allows you create a new "Basic" VCHA Cluster, it does not
|
||||||
|
cover the "Advanced" use case. You will need to ensure that you have a
|
||||||
|
"Self Managed" vCenter Server before attempting this workflow.
|
||||||
|
This is only available on VCSA 6.5 (vSphere 6.5 or greater)
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to create "Basic" VCHA Cluster
|
||||||
|
.PARAMETER VCSAVM
|
||||||
|
The name of the vCenter Server Appliance (VCSA) in which you wish to enable VCHA on (must be self-managed)
|
||||||
|
.PARAMETER HANetwork
|
||||||
|
The name of the Virtual Portgroup or Distributed Portgroup used for the HA Network
|
||||||
|
.PARAMETER ActiveHAIp
|
||||||
|
The IP Address for the Active VCSA node
|
||||||
|
.PARAMETER ActiveNetmask
|
||||||
|
The Netmask for the Active VCSA node
|
||||||
|
.PARAMETER PassiveHAIp
|
||||||
|
The IP Address for the Passive VCSA node
|
||||||
|
.PARAMETER PassiveNetmask
|
||||||
|
The Netmask for the Passive VCSA node
|
||||||
|
.PARAMETER WitnessHAIp
|
||||||
|
The IP Address for the Witness VCSA node
|
||||||
|
.PARAMETER WitnessNetmask
|
||||||
|
The Netmask for the Witness VCSA node
|
||||||
|
.PARAMETER PassiveDatastore
|
||||||
|
The name of the datastore to deploy the Passive node to
|
||||||
|
.PARAMETER WitnessDatastore
|
||||||
|
The name of the datastore to deploy the Witness node to
|
||||||
|
.PARAMETER VCUsername
|
||||||
|
The VCSA username (e.g. administrator@vghetto.local)
|
||||||
|
.PARAMETER VCPassword
|
||||||
|
The VCSA password
|
||||||
|
.EXAMPLE
|
||||||
|
New-VCHABasicConfig -VCSAVM "vcenter65-1" -HANetwork "DVPG-VCHA-Network" `
|
||||||
|
-ActiveHAIp 192.168.1.70 `
|
||||||
|
-ActiveNetmask 255.255.255.0 `
|
||||||
|
-PassiveHAIp 192.168.1.71 `
|
||||||
|
-PassiveNetmask 255.255.255.0 `
|
||||||
|
-WitnessHAIp 192.168.1.72 `
|
||||||
|
-WitnessNetmask 255.255.255.0 `
|
||||||
|
-PassiveDatastore "vsanDatastore" `
|
||||||
|
-WitnessDatastore "vsanDatastore" `
|
||||||
|
-VCUsername "administrator@vghetto.local" `
|
||||||
|
-VCPassword "VMware1!"
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(
|
||||||
|
Mandatory=$true,
|
||||||
|
ValueFromPipeline=$true,
|
||||||
|
ValueFromPipelineByPropertyName=$true)
|
||||||
|
]
|
||||||
|
[String]$VCSAVM,
|
||||||
|
[String]$HANetwork,
|
||||||
|
[String]$ActiveHAIp,
|
||||||
|
[String]$ActiveNetmask,
|
||||||
|
[String]$PassiveHAIp,
|
||||||
|
[String]$PassiveNetmask,
|
||||||
|
[String]$PassiveDatastore,
|
||||||
|
[String]$WitnessHAIp,
|
||||||
|
[String]$WitnessNetmask,
|
||||||
|
[String]$WitnessDatastore,
|
||||||
|
# Crappy Implementation but need to research more into using PSH Credential
|
||||||
|
[String]$VCUsername,
|
||||||
|
[String]$VCPassword
|
||||||
|
)
|
||||||
|
|
||||||
|
$VCSAVMView = Get-View -ViewType VirtualMachine -Filter @{"name"=$VCSAVM}
|
||||||
|
if($VCSAVMView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Error: Unable to find Virtual Machine $VCSAVM"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$HANetworkView = Get-View -ViewType Network -Filter @{"name"=$HANetwork}
|
||||||
|
if($HANetworkView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Error: Unable to find Network $HANetwork"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$PassiveDatastoreView = Get-View -ViewType Datastore -Filter @{"name"=$PassiveDatastore}
|
||||||
|
if($PassiveDatastoreView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Error: Unable to find Passive Datastore $PassiveDatastore"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$WitnessDatastoreView = Get-View -ViewType Datastore -Filter @{"name"=$WitnessDatastore}
|
||||||
|
if($WitnessDatastoreView -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Error: Unable to find Witness Datastore $WitnessDatastore"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$vcIP = $VCSAVMView.Guest.IpAddress
|
||||||
|
if($vcIP -eq $null) {
|
||||||
|
Write-Host -ForegroundColor Red "Error: Unable to automatically retrieve the IP Address of $VCSAVM which is needed to use this function"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieve Source VC SSL Thumbprint
|
||||||
|
$vcurl = "https://$vcIP"
|
||||||
|
add-type @"
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
public class IDontCarePolicy : ICertificatePolicy {
|
||||||
|
public IDontCarePolicy() {}
|
||||||
|
public bool CheckValidationResult(
|
||||||
|
ServicePoint sPoint, X509Certificate cert,
|
||||||
|
WebRequest wRequest, int certProb) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
[System.Net.ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy
|
||||||
|
# Need to do simple GET connection for this method to work
|
||||||
|
Invoke-RestMethod -Uri $VCURL -Method Get | Out-Null
|
||||||
|
|
||||||
|
$endpoint_request = [System.Net.Webrequest]::Create("$vcurl")
|
||||||
|
# Get Thumbprint + add colons for a valid Thumbprint
|
||||||
|
$vcSSLThumbprint = ($endpoint_request.ServicePoint.Certificate.GetCertHashString()) -replace '(..(?!$))','$1:'
|
||||||
|
|
||||||
|
$vcHAClusterConfig = Get-View failoverClusterConfigurator
|
||||||
|
$spec = New-Object VMware.Vim.VchaClusterDeploymentSpec
|
||||||
|
|
||||||
|
$activeNetworkConfig = New-Object VMware.Vim.ClusterNetworkConfigSpec
|
||||||
|
$activeNetworkConfig.NetworkPortGroup = $HANetworkView.MoRef
|
||||||
|
$ipSettings = New-Object Vmware.Vim.CustomizationIPSettings
|
||||||
|
$ipSettings.SubnetMask = $ActiveNetmask
|
||||||
|
$activeIpSpec = New-Object VMware.Vim.CustomizationFixedIp
|
||||||
|
$activeIpSpec.IpAddress = $ActiveHAIp
|
||||||
|
$ipSettings.Ip = $activeIpSpec
|
||||||
|
$activeNetworkConfig.IpSettings = $ipSettings
|
||||||
|
$spec.ActiveVcNetworkConfig = $activeNetworkConfig
|
||||||
|
|
||||||
|
$activeVCConfig = New-Object Vmware.Vim.SourceNodeSpec
|
||||||
|
$activeVCConfig.ActiveVc = $VCSAVMView.MoRef
|
||||||
|
$serviceLocator = New-Object Vmware.Vim.ServiceLocator
|
||||||
|
$credential = New-Object VMware.Vim.ServiceLocatorNamePassword
|
||||||
|
$credential.username = $VCUsername
|
||||||
|
$credential.password = $VCPassword
|
||||||
|
$serviceLocator.Credential = $credential
|
||||||
|
$serviceLocator.InstanceUuid = $global:DefaultVIServer.InstanceUuid
|
||||||
|
$serviceLocator.Url = $vcurl
|
||||||
|
$serviceLocator.SslThumbprint = $vcSSLThumbprint
|
||||||
|
$activeVCConfig.ManagementVc = $serviceLocator
|
||||||
|
$spec.ActiveVcSpec = $activeVCConfig
|
||||||
|
|
||||||
|
$passiveSpec = New-Object VMware.Vim.PassiveNodeDeploymentSpec
|
||||||
|
$passiveSpec.Folder = (Get-View (Get-Folder vm)).MoRef
|
||||||
|
$passiveIpSettings = New-object Vmware.Vim.CustomizationIPSettings
|
||||||
|
$passiveIpSettings.SubnetMask = $passiveNetmask
|
||||||
|
$passiveIpSpec = New-Object VMware.Vim.CustomizationFixedIp
|
||||||
|
$passiveIpSpec.IpAddress = $passiveHAIp
|
||||||
|
$passiveIpSettings.Ip = $passiveIpSpec
|
||||||
|
$passiveSpec.IpSettings = $passiveIpSettings
|
||||||
|
$passiveSpec.NodeName = $VCSAVMView.Name + "-Passive"
|
||||||
|
$passiveSpec.datastore = $PassiveDatastoreView.MoRef
|
||||||
|
$spec.PassiveDeploymentSpec = $passiveSpec
|
||||||
|
|
||||||
|
$witnessSpec = New-Object VMware.Vim.NodeDeploymentSpec
|
||||||
|
$witnessSpec.Folder = (Get-View (Get-Folder vm)).MoRef
|
||||||
|
$witnessSpec.NodeName = $VCSAVMView.Name + "-Witness"
|
||||||
|
$witnessIpSettings = New-object Vmware.Vim.CustomizationIPSettings
|
||||||
|
$witnessIpSettings.SubnetMask = $witnessNetmask
|
||||||
|
$witnessIpSpec = New-Object VMware.Vim.CustomizationFixedIp
|
||||||
|
$witnessIpSpec.IpAddress = $witnessHAIp
|
||||||
|
$witnessIpSettings.Ip = $witnessIpSpec
|
||||||
|
$witnessSpec.IpSettings = $witnessIpSettings
|
||||||
|
$witnessSpec.datastore = $WitnessDatastoreView.MoRef
|
||||||
|
$spec.WitnessDeploymentSpec = $witnessSpec
|
||||||
|
|
||||||
|
Write-Host "`nDeploying VCHA Cluster ...`n"
|
||||||
|
$task = $vcHAClusterConfig.deployVcha_Task($spec)
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task -Verbose
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Remove-VCHAConfig {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: William Lam
|
||||||
|
Date: Nov 20, 2016
|
||||||
|
Organization: VMware
|
||||||
|
Blog: www.virtuallyghetto.com
|
||||||
|
Twitter: @lamw
|
||||||
|
===========================================================================
|
||||||
|
.SYNOPSIS
|
||||||
|
This function allows you destroy a VCHA Cluster. In addition, you have
|
||||||
|
the option to specify whether you would like both the Passive & Witness
|
||||||
|
Virtual Machines be deleted after the VCHA Cluster has been destroyed.
|
||||||
|
This is only available on VCSA 6.5 (vSphere 6.5 or greater)
|
||||||
|
.DESCRIPTION
|
||||||
|
Function to destroy a VCHA Cluster Mode
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-VCHAConfig
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-VCHAConfig -Confirm:$false
|
||||||
|
.EXAMPLE
|
||||||
|
Remove-VCHAConfig -DeleteVM $true -Confirm:$false
|
||||||
|
.NOTES
|
||||||
|
Before you can destroy a VCHA Cluster, you must make sure it is first
|
||||||
|
disabled. Run the Set-VCHAClusterMode -Disabled $true to do so
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Boolean]$Confirm=$true,
|
||||||
|
[Switch]$DeleteVM=$false
|
||||||
|
)
|
||||||
|
|
||||||
|
$Verified = $false
|
||||||
|
if($Confirm -eq $true) {
|
||||||
|
Write-Host -ForegroundColor Yellow "`nDo you want to destroy VCHA Cluster?"
|
||||||
|
$answer = Read-Host -Prompt "Do you accept (Y or N)"
|
||||||
|
if($answer -eq "Y" -or $answer -eq "y") {
|
||||||
|
$Verified = $true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$Verified = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Verified) {
|
||||||
|
$vcHAClusterManager = Get-View failoverClusterManager
|
||||||
|
$vcHAMode = $vcHAClusterManager.getClusterMode()
|
||||||
|
|
||||||
|
if($vcHAMode -ne "disabled") {
|
||||||
|
Write-Host -ForegroundColor Yellow "To destroy VCHA Cluster, you must first set the VCHA Cluster Mode to `"Disabled`""
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Query BIOS UUID of the Passive/Witness to be able to delete
|
||||||
|
if($DeleteVM) {
|
||||||
|
$vcHAClusterConfig = Get-View failoverClusterConfigurator
|
||||||
|
$vcHAConfig = $vcHAClusterConfig.getVchaConfig()
|
||||||
|
$passiveBiosUUID = $vcHAConfig.FailoverNodeInfo2.biosUuid
|
||||||
|
$witnessBiosUUID = $vcHAConfig.WitnessNodeInfo.biosUuid
|
||||||
|
}
|
||||||
|
|
||||||
|
$vcHAClusterConfig = Get-View failoverClusterConfigurator
|
||||||
|
|
||||||
|
Write-Host "Destroying VCHA Cluster ..."
|
||||||
|
$task = $vcHAClusterConfig.destroyVcha_Task()
|
||||||
|
$task1 = Get-Task -Id ("Task-$($task.value)")
|
||||||
|
$task1 | Wait-Task
|
||||||
|
|
||||||
|
# After VCHA Cluster has been destroyed, we can now delete the VMs we had queried earlier
|
||||||
|
if($DeleteVM) {
|
||||||
|
if($passiveBiosUUID -ne $null -and $witnessBiosUUID -ne $null) {
|
||||||
|
$searchIndex = Get-View searchIndex
|
||||||
|
|
||||||
|
$passiveVM = $searchIndex.FindByUuid($null,$passiveBiosUUID,$true,$null)
|
||||||
|
$witnessVM = $searchIndex.FindByUuid($null,$witnessBiosUUID,$true,$null)
|
||||||
|
|
||||||
|
if($passiveVM -ne $null -and $witnessVM -ne $null) {
|
||||||
|
Write-Host "Powering off & deleting Passive VM ..."
|
||||||
|
Stop-VM -VM (Get-View $passiveVM).Name -Confirm:$false | Out-Null
|
||||||
|
Remove-VM (Get-View $passiveVM).Name -DeletePermanently -Confirm:$false
|
||||||
|
Write-Host "Powering off & deleting Witness VM ..."
|
||||||
|
Stop-VM -VM (Get-View $witnessVM).Name -Confirm:$false | Out-Null
|
||||||
|
Remove-VM (Get-View $witnessVM).Name -DeletePermanently -Confirm:$false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
322
Modules/VMCPFunctions/VMCPFunctions.psm1
Normal file
322
Modules/VMCPFunctions/VMCPFunctions.psm1
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
function Get-VMCPSettings {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created on: 10/27/2015 9:25 PM
|
||||||
|
Created by: Brian Graf
|
||||||
|
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
|
||||||
|
|
||||||
|
.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
|
||||||
|
|
||||||
|
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=$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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-VMCPSettings {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created on: 10/27/2015 9:25 PM
|
||||||
|
Created by: Brian Graf
|
||||||
|
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
|
||||||
|
them to configure the additional VMCP settings
|
||||||
|
For each parameter, users should use the 'Tab' button to auto-fill the
|
||||||
|
possible values.
|
||||||
|
|
||||||
|
.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
|
||||||
|
|
||||||
|
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(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=$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
|
||||||
|
)
|
||||||
|
|
||||||
|
Process {
|
||||||
|
|
||||||
|
Foreach ($Clus in $Cluster) {
|
||||||
|
|
||||||
|
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'}
|
||||||
|
}
|
||||||
|
|
||||||
|
If ($CL) {
|
||||||
|
|
||||||
|
# Get the actual configuration of the Cluster
|
||||||
|
$ActualSettings = Get-VMCPSettings -Cluster $CL -Server $Server
|
||||||
|
|
||||||
|
# Show actual settings in the verbose mode
|
||||||
|
Write-Verbose "[$($CL.Name)] Actual VMCP settings "
|
||||||
|
Write-Verbose $ActualSettings
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
93
Modules/apply-hardening/apply-hardening.psm1
Normal file
93
Modules/apply-hardening/apply-hardening.psm1
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
function Apply-Hardening {
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
===========================================================================
|
||||||
|
Created by: Markus Kraus
|
||||||
|
Twitter: @VMarkus_K
|
||||||
|
Private Blog: mycloudrevolution.com
|
||||||
|
===========================================================================
|
||||||
|
Changelog:
|
||||||
|
2016.11 ver 2.0 Base Release
|
||||||
|
===========================================================================
|
||||||
|
External Code Sources:
|
||||||
|
|
||||||
|
===========================================================================
|
||||||
|
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
|
||||||
|
Keyword: VM, Hardening, Security
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Applys a set of Hardening options to your VMs
|
||||||
|
|
||||||
|
.Example
|
||||||
|
Get-VM TST* | Apply-Hardening
|
||||||
|
|
||||||
|
.Example
|
||||||
|
$SampleVMs = Get-VM "TST*"
|
||||||
|
Apply-Hardening -VMs $SampleVMs
|
||||||
|
|
||||||
|
.PARAMETER VMs
|
||||||
|
Specify the VMs
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
)
|
||||||
|
|
||||||
|
Process {
|
||||||
|
#region: Create Options
|
||||||
|
$ExtraOptions = @{
|
||||||
|
"isolation.tools.diskShrink.disable"="true";
|
||||||
|
"isolation.tools.diskWiper.disable"="true";
|
||||||
|
"isolation.tools.copy.disable"="true";
|
||||||
|
"isolation.tools.paste.disable"="true";
|
||||||
|
"isolation.tools.dnd.disable"="true";
|
||||||
|
"isolation.tools.setGUIOptions.enable"="false";
|
||||||
|
"log.keepOld"="10";
|
||||||
|
"log.rotateSize"="100000"
|
||||||
|
"RemoteDisplay.maxConnections"="2";
|
||||||
|
"RemoteDisplay.vnc.enabled"="false";
|
||||||
|
|
||||||
|
}
|
||||||
|
if ($DebugPreference -eq "Inquire") {
|
||||||
|
Write-Output "VM Hardening Options:"
|
||||||
|
$ExtraOptions | Format-Table -AutoSize
|
||||||
|
}
|
||||||
|
|
||||||
|
$VMConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
|
||||||
|
|
||||||
|
Foreach ($Option in $ExtraOptions.GetEnumerator()) {
|
||||||
|
$OptionValue = New-Object VMware.Vim.optionvalue
|
||||||
|
$OptionValue.Key = $Option.Key
|
||||||
|
$OptionValue.Value = $Option.Value
|
||||||
|
$VMConfigSpec.extraconfig += $OptionValue
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region: Apply Options
|
||||||
|
ForEach ($VM in $VMs){
|
||||||
|
$VMv = Get-VM $VM | Get-View
|
||||||
|
$state = $VMv.Summary.Runtime.PowerState
|
||||||
|
Write-Output "...Starting Reconfiguring VM: $VM "
|
||||||
|
$TaskConf = ($VMv).ReconfigVM_Task($VMConfigSpec)
|
||||||
|
if ($state -eq "poweredOn") {
|
||||||
|
Write-Output "...Migrating VM: $VM "
|
||||||
|
$TaskMig = $VMv.MigrateVM_Task($null, $_.Runtime.Host, 'highPriority', $null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user