Adding scripts
This commit is contained in:
1 parent
e78eed48b6
commit
fc7cfeb008
10 files changed
+2321
No files matched your search
@@ -0,0 +1,226 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$dvSwitch = "",
|
||||||
|
[string]$CSVFile = "",
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.0.0"
|
||||||
|
$fileDate = "2026-01-28"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "dvSwitch Port Group Creation Script" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Create dvSwitch Port Groups en masse."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " CreatedvSwitchPortGroups.ps1 (-vcenter [vcenter host name]) (-dvSwitch ""[dvswitch]"") (-CSVFile ""[csvfile]"")"
|
||||||
|
Write-Host " (-savecred) (-help)`n" -foregroundcolor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -dvSwitch " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the distributed virtual switch in vCenter."
|
||||||
|
Write-Host -NoNewLine " -CSVfile " -foregroundcolor Green
|
||||||
|
Write-Host "- The path to the CSV file. See note below for format."
|
||||||
|
Write-Host -NoNewLine " -savecred " -foregroundcolor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -foregroundcolor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If any of the information is not provided, you will be prompted. If a credential has been previously stored, it will"
|
||||||
|
Write-Host "be used again unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "The CSV file must follow the format listed below. The only field required is PortGroup. Fields can be in any order."
|
||||||
|
Write-Host " PortGroup, VLAN, PortBinding, NumPorts, ActiveUplink, DisabledUplink, StandbyUplink, Notes"
|
||||||
|
Write-Host "Where:"
|
||||||
|
Write-Host " Portgroup " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - The name of the port group."
|
||||||
|
Write-Host " VLAN " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] The VLAN tag for the port group."
|
||||||
|
Write-Host " PortBinding " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] The type of port binding for the port group. This can be either Static or Dynamic."
|
||||||
|
Write-Host " Defaults to Static if not specified."
|
||||||
|
Write-Host " NumPorts " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] The number of ports for the port group. This is ignored for a dynamic port group."
|
||||||
|
Write-Host " Defaults to 254 if not specified."
|
||||||
|
Write-Host " ActiveUplink " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] A comma delimited list of switch uplinks to be set as active for the port group."
|
||||||
|
Write-Host " StandbyUplink " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] A comma delimited list of switch uplinks to be set as standby for the port group."
|
||||||
|
Write-Host " UnusedUplink " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] A comma delimited list of switch uplinks to be set as unused for the port group."
|
||||||
|
Write-Host " Notes " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - [Optional] Notes to add to the port group."
|
||||||
|
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kistools-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction Stop
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($dvSwitch -ne "") {
|
||||||
|
get-VDswitch $dvSwitch -ErrorAction Stop
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: dvSwitch ""$dvSwitch"" is not found." -ForegroundColor Red
|
||||||
|
$dvSwitch = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dvSwitch -eq "") {
|
||||||
|
$dvSwitchlist = Get-VDSwitch | Sort-Object
|
||||||
|
While (($dvSwitch -eq "") -or (-not $dvSwitch)) {
|
||||||
|
Write-Host "`ndvSwitch Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $dvSwitchlist.length; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($DVSwitchlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$dvSwitchNum = [int](Read-Host "`nSelect dvSwitch Number") - 1
|
||||||
|
$dvSwitch = $dvSwitchlist[$dvSwitchNum]
|
||||||
|
}
|
||||||
|
$mySwitch = get-VDSwitch $dvSwitch
|
||||||
|
} else {
|
||||||
|
$mySwitch = get-VDSwitch $dvSwitch
|
||||||
|
}
|
||||||
|
|
||||||
|
$csvdata = Import-CSV $csvfile
|
||||||
|
|
||||||
|
Write-Host "Processing Port Group List"
|
||||||
|
|
||||||
|
for ($x = 0; $x -lt $csvdata.length; $x++) {
|
||||||
|
$pgname = $csvdata[$x].PortGroup
|
||||||
|
if ($pgname -eq "") { continue }
|
||||||
|
if (-not ($pgvlan = $csvdata[$x].VLAN)) {
|
||||||
|
$pgvlan = 0
|
||||||
|
}
|
||||||
|
if (-not ($pgbinding = $csvdata[$x].PortBinding)) {
|
||||||
|
$pgbinding = "Static"
|
||||||
|
}
|
||||||
|
if (-not ($pgports = $csvdata[$x].NumPorts)) {
|
||||||
|
$pgports = 254
|
||||||
|
}
|
||||||
|
if ($pgactive -and (($pgactive = ($csvdata[$x].ActiveUplink).split(",")).count -eq 0)) {
|
||||||
|
$pgactive = @()
|
||||||
|
}
|
||||||
|
if ($pgstandby -and (($pgstandby = ($csvdata[$x].StandbyUplink).split(",")).count -eq 0)) {
|
||||||
|
$pgstandby = @()
|
||||||
|
}
|
||||||
|
if ($pgunused -and (($pgunused = ($csvdata[$x].UnusedUplink).split(",")).count -eq 0)) {
|
||||||
|
$pgunused = @()
|
||||||
|
}
|
||||||
|
Write-Host "$pgname... " -NoNewLine
|
||||||
|
if ($temp = Get-VdPortGroup $pgname -erroraction silentlycontinue) {
|
||||||
|
Write-Host " Already Exists - Skipping" -ForegroundColor Yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$newpg = New-VdPortGroup -name "$pgname" -vlanid $pgvlan -PortBinding $pgbinding -VdSwitch "$dvSwitch" -erroraction stop
|
||||||
|
Write-Host "Created Successfully" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host " ERROR - Unable to Create Port Group $pgname on dvSwitch $dvSwitch." -ForegroundColor Red
|
||||||
|
Write-Host "$($_.Exception.Message)" -ForegroundColor Gray
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$myuplinks = @()
|
||||||
|
foreach($uplink in $pgactive) {
|
||||||
|
if ($uplink -eq "") { continue }
|
||||||
|
if (($mySwitch.ExtensionData.Config.UplinkPortPolicy.UplinkPortName | Where-Object {$_ -eq $uplink}).Count -eq 0) {
|
||||||
|
Write-Host "Warning: Uplink ""$uplink"" for Active is not found on switch $dvSwitch" -ForegroundColor Yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$myuplinks += $uplink
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($myuplinks.Count -gt 0) {
|
||||||
|
Write-Host " Assigning active uplink ports... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$temp = $newpg | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -ActiveUplinkPort $myuplinks -ErrorAction Stop
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR assigning uplinks to $pgname" -ForegroundColor Red
|
||||||
|
Write-Host "$($_.Exception.Message)" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$myuplinks = @()
|
||||||
|
foreach($uplink in $pgstandby) {
|
||||||
|
if ($uplink -eq "") { continue }
|
||||||
|
if (($mySwitch.ExtensionData.Config.UplinkPortPolicy.UplinkPortName | Where-Object {$_ -eq $uplink}).Count -eq 0) {
|
||||||
|
Write-Host "Warning: Uplink ""$uplink"" for STANDBY is not found on switch $dvSwitch" -ForegroundColor Yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$myuplinks += $uplink
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($myuplinks.Count -gt 0) {
|
||||||
|
Write-Host " Assigning standby uplink ports... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$temp = $newpg | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -StandbyUplinkPort $myuplinks -ErrorAction Stop
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR assigning standby uplinks to $pgname" -ForegroundColor Red
|
||||||
|
Write-Host "$($_.Exception.Message)" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$myuplinks = @()
|
||||||
|
foreach($uplink in $pgunused) {
|
||||||
|
if ($uplink -eq "") { continue }
|
||||||
|
if (($mySwitch.ExtensionData.Config.UplinkPortPolicy.UplinkPortName | Where-Object {$_ -eq $uplink}).Count -eq 0) {
|
||||||
|
Write-Host "Warning: Uplink ""$uplink"" for UNUSED is not found on switch $dvSwitch" -ForegroundColor Yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$myuplinks += $uplink
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($myuplinks.Count -gt 0) {
|
||||||
|
Write-Host " Assigning unused uplink ports... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$temp = $newpg | Get-VDUplinkTeamingPolicy | Set-VDUplinkTeamingPolicy -UnusedUplinkPort $myuplinks -ErrorAction Stop
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR assigning unused uplinks to $pgname" -ForegroundColor Red
|
||||||
|
Write-Host "$($_.Exception.Message)" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
Function Get-DrsGroup {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Retrieves DRS groups from a cluster.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Retrieves DRS groups from a cluster.
|
||||||
|
|
||||||
|
.PARAMETER Cluster
|
||||||
|
Specify the cluster for which you want to retrieve the DRS groups
|
||||||
|
|
||||||
|
.PARAMETER Name
|
||||||
|
Specify the name of the DRS group you want to retrieve.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-DrsGroup -Cluster $Cluster -Name "VMs DRS Group"
|
||||||
|
Retrieves the DRS group "Vms DRS Group" from cluster $Cluster.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-Cluster | Get-DrsGroup
|
||||||
|
Retrieves all the DRS groups for all clusters.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
ClusterImpl
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
ClusterVmGroup
|
||||||
|
ClusterHostGroup
|
||||||
|
|
||||||
|
.COMPONENT
|
||||||
|
VMware vSphere PowerCLI
|
||||||
|
#>
|
||||||
|
|
||||||
|
param([parameter(Mandatory=$true, ValueFromPipeline=$true)]$Cluster,
|
||||||
|
[string] $Name="*")
|
||||||
|
|
||||||
|
process {
|
||||||
|
$Cluster = Get-Cluster -Name $Cluster
|
||||||
|
if($Cluster) {
|
||||||
|
$Cluster.ExtensionData.ConfigurationEx.Group | `
|
||||||
|
Where-Object {$_.Name -like $Name}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Add-VMToDrsGroup {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Adds a virtual machine to a cluster VM DRS group.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Adds a virtual machine to a cluster VM DRS group.
|
||||||
|
|
||||||
|
.PARAMETER Cluster
|
||||||
|
Specify the cluster for which you want to retrieve the DRS groups
|
||||||
|
|
||||||
|
.PARAMETER DrsGroup
|
||||||
|
Specify the DRS group you want to retrieve.
|
||||||
|
|
||||||
|
.PARAMETER VM
|
||||||
|
Specify the virtual machine you want to add to the DRS Group.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Add-VMToDrsGroup -Cluster $Cluster -DrsGroup "VM DRS Group" -VM $VM
|
||||||
|
Adds virtual machine $VM to the DRS group "VM DRS Group" of cluster $Cluster.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
Get-Cluster MyCluster | Get-VM "A*" | Add-VMToDrsGroup -Cluster MyCluster -DrsGroup $DrsGroup
|
||||||
|
Adds all virtual machines with a name starting with "A" in cluster MyCluster to the DRS group $DrsGroup of cluster MyCluster.
|
||||||
|
|
||||||
|
.INPUTS
|
||||||
|
VirtualMachineImpl
|
||||||
|
|
||||||
|
.OUTPUTS
|
||||||
|
Task
|
||||||
|
|
||||||
|
.COMPONENT
|
||||||
|
VMware vSphere PowerCLI
|
||||||
|
#>
|
||||||
|
|
||||||
|
param([parameter(Mandatory=$true)] $Cluster,
|
||||||
|
[parameter(Mandatory=$true)] $DrsGroup,
|
||||||
|
[parameter(Mandatory=$true, ValueFromPipeline=$true)] $VM)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
$Cluster = Get-Cluster -Name $Cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
if ($Cluster) {
|
||||||
|
if ($DrsGroup.GetType().Name -eq "string") {
|
||||||
|
$DrsGroupName = $DrsGroup
|
||||||
|
$DrsGroup = Get-DrsGroup -Cluster $Cluster -Name $DrsGroup
|
||||||
|
}
|
||||||
|
if (-not $DrsGroup) {
|
||||||
|
Write-Error "The DrsGroup $DrsGroupName was not found on cluster $($Cluster.name)."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($DrsGroup.GetType().Name -ne "ClusterVmGroup") {
|
||||||
|
Write-Error "The DrsGroup $DrsGroupName on cluster $($Cluster.Name) doesn't have the required type ClusterVmGroup."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$VM = $Cluster | Get-VM -Name $VM
|
||||||
|
If ($VM) {
|
||||||
|
$spec = New-Object VMware.Vim.ClusterConfigSpecEx
|
||||||
|
$spec.groupSpec = New-Object VMware.Vim.ClusterGroupSpec[] (1)
|
||||||
|
$spec.groupSpec[0] = New-Object VMware.Vim.ClusterGroupSpec
|
||||||
|
$spec.groupSpec[0].operation = "edit"
|
||||||
|
$spec.groupSpec[0].info = $DrsGroup
|
||||||
|
$spec.groupSpec[0].info.vm += $VM.ExtensionData.MoRef
|
||||||
|
|
||||||
|
$Cluster.ExtensionData.ReconfigureComputeResource_Task($spec, $true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,675 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$Cluster = "",
|
||||||
|
[string]$dvSwitch = "",
|
||||||
|
[string]$Datastore = "",
|
||||||
|
[string]$SourceVMName = "",
|
||||||
|
[string]$Folder = "",
|
||||||
|
[string]$CSVFile = "",
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
Import-Module .\DRSGroupFunctions.ps1
|
||||||
|
|
||||||
|
function GetFolderFromPath($folder) {
|
||||||
|
$parts = $folder.Split("\")
|
||||||
|
if ($parts.length -eq 0) { return $folder }
|
||||||
|
for ($x = 0; $x -lt $parts.length; ++$x) {
|
||||||
|
$thispart = $parts[$x]
|
||||||
|
if ($x -gt 0) {
|
||||||
|
$thisfolder = Get-Folder $parts[$x] | Where-Object {$_.Parent.Id -eq $parent.Id}
|
||||||
|
} else {
|
||||||
|
$thisfolder = Get-Folder $parts[$x] | Where-Object {$_.Parent.Name -eq "vm"}
|
||||||
|
}
|
||||||
|
$parent = $thisfolder
|
||||||
|
}
|
||||||
|
return $thisfolder
|
||||||
|
}
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.2.0"
|
||||||
|
$fileDate = "2026-06-03"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "vSphere Testing VM Deployment Script" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Deploy testing VMs for a set of port groups."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " DeployTestingVMs.ps1 (-vcenter [vCenter]) (-Cluster ""[Cluster]"") (-dvSwitch ""[dvswitch]"")" -ForegroundColor green
|
||||||
|
Write-Host " (-SourceVMName ""[SourceVMName]"") (-CSVFile ""[csvfile]"")" -ForegroundColor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -ForegroundColor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -Cluster " -ForegroundColor Green
|
||||||
|
Write-Host "- The name of the Cluster in vCenter."
|
||||||
|
Write-Host -NoNewLine " -dvSwitch " -ForegroundColor Green
|
||||||
|
Write-Host "- The name of the distributed virtual switch in vCenter."
|
||||||
|
Write-Host -NoNewLine " -SourceVMName " -ForegroundColor Green
|
||||||
|
Write-Host "- The name of the distributed virtual switch in vCenter."
|
||||||
|
Write-Host -NoNewLine " -CSVfile " -ForegroundColor Green
|
||||||
|
Write-Host "- The path to the CSV file. See note below for format."
|
||||||
|
Write-Host -NoNewLine " -savecred " -ForegroundColor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -ForegroundColor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If any of the information is not provided, you will be prompted. If a credential has been previously stored, it will"
|
||||||
|
Write-Host "be used again unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "The CSV file must follow the format listed below. The only field required is PortGroup. Fields can be in any order."
|
||||||
|
Write-Host " VLAN, Description, IPAddress, Netmask, Gateway, Site"
|
||||||
|
Write-Host "Where:"
|
||||||
|
Write-Host " VLAN " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - The VLAN tag for the port group."
|
||||||
|
Write-Host " Description " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - The Description for the port group."
|
||||||
|
Write-Host " IPAddress " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - IP address for the VM."
|
||||||
|
Write-Host " Netmask " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - Netmask for the network."
|
||||||
|
Write-Host " Gateway " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - Default gateway for the network."
|
||||||
|
Write-Host " Site " -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - The site prefix to be used for DRS group configuration."
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "The port group name will be assumed to be in the following format: ""[Description] - VLAN[VLAN]"""
|
||||||
|
Write-Host "If the VLAN tag is 12 and the description is ""Big Servers"", the port group name will be ""Big Servers - VLAN12"""
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "The DRS group name will be assumed to be in the following format: ""[Site] Only VMs"""
|
||||||
|
Write-Host "If the Site is Primary, the DRS group name will be ""Primary Only VMs"""
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Additionally, the new VM names will be in the format ""KISStress - VLAN[VLAN]"""
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$data = import-csv $CSVFile
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: Input file is not in a valid format." -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!($data | Where-Object {$_.PSObject.Properties.Name -contains "VLAN"}) -or (!($data | Where-Object {$_.PSObject.Properties.Name -contains "Description"}))) {
|
||||||
|
Write-Host "ERROR: Input file is not in a valid format." -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$setip = $false
|
||||||
|
|
||||||
|
if ($data | Where-Object {$_.PSObject.Properties.Name -contains "IPAddress"}) {
|
||||||
|
if ($data | Where-Object {$_.PSObject.Properties.Name -contains "Netmask"}) {
|
||||||
|
if ($data | Where-Object {$_.PSObject.Properties.Name -contains "Gateway"}) {
|
||||||
|
$setip = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kistools-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter... "
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction Stop
|
||||||
|
Write-Host "Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Cluster -eq "") {
|
||||||
|
$Clusterlist = Get-Cluster | Sort-Object
|
||||||
|
$startpos = 0
|
||||||
|
$step = 10
|
||||||
|
While (($Cluster -eq "") -or (-not $Cluster)) {
|
||||||
|
$endpos = $startpos + 10;
|
||||||
|
if ($endpos -gt $Clusterlist.length) { $endpos = $Clusterlist.length }
|
||||||
|
$page = $startpos / $step + 1
|
||||||
|
$maxpage = [math]::Ceiling($Clusterlist.length / $step)
|
||||||
|
Write-Host "`nCluster Selection (Page $page of $maxpage):`n"
|
||||||
|
if ($startpos -gt 0) {
|
||||||
|
Write-Host " 0" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "<< Previous Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
for ($x = $startpos; $x -lt $endpos; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1-$startpos)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($Clusterlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
if ($endpos -lt $Clusterlist.length) {
|
||||||
|
Write-Host " $($step+1)" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host ">> Next Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
$Clusternum = Read-Host "`nSelect Cluster Number"
|
||||||
|
$Clusternum = [int]$Clusternum - 1
|
||||||
|
if ($Clusternum -eq -1) {
|
||||||
|
$startpos -= $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Clusternum -eq $step) {
|
||||||
|
$startpos += $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$Cluster = $Clusterlist[$Clusternum + $startpos].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Validating cluster ""$Cluster""... " -NoNewLine
|
||||||
|
$mycluster = get-cluster $Cluster
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Unable to locate cluster ""$Cluster"" in $vCenter" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dvSwitch -eq "") {
|
||||||
|
$myhost = $mycluster | Get-VMHost | Select-Object -First 1
|
||||||
|
$SwitchList = Get-VdSwitch -VMHost $myhost
|
||||||
|
$startpos = 0
|
||||||
|
$step = 10
|
||||||
|
While (($dvSwitch -eq "") -or (-not $dvSwitch)) {
|
||||||
|
$endpos = $startpos + 10;
|
||||||
|
if ($endpos -gt $SwitchList.length) { $endpos = $SwitchList.length }
|
||||||
|
$page = $startpos / $step + 1
|
||||||
|
$maxpage = [math]::Ceiling($SwitchList.length / $step)
|
||||||
|
Write-Host "`ndvSwitch Selection (Page $page of $maxpage):`n"
|
||||||
|
if ($startpos -gt 0) {
|
||||||
|
Write-Host " 0" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "<< Previous Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
for ($x = $startpos; $x -lt $endpos; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1-$startpos)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($SwitchList[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
if ($endpos -lt $SwitchList.length) {
|
||||||
|
Write-Host " $($step+1)" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host ">> Next Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
$dvSwitchnum = Read-Host "`nSelect dvSwitch Number"
|
||||||
|
$dvSwitchnum = [int]$dvSwitchnum - 1
|
||||||
|
if ($dvSwitchnum -eq -1) {
|
||||||
|
$startpos -= $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($dvSwitchnum -eq $step) {
|
||||||
|
$startpos += $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$dvSwitch = $SwitchList[$dvSwitchnum + $startpos].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Validating dvSwitch ""$dvSwitch""... " -NoNewLine
|
||||||
|
$mydvSwitch = Get-VdSwitch $dvSwitch
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Unable to locate dvSwitch $dvSwitch in $vCenter" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SourceVMName -eq "") {
|
||||||
|
$VMList = $mycluster | Get-VM
|
||||||
|
$startpos = 0
|
||||||
|
$step = 10
|
||||||
|
While (($SourceVMName -eq "") -or (-not $SourceVMName)) {
|
||||||
|
$endpos = $startpos + 10;
|
||||||
|
if ($endpos -gt $VMList.length) { $endpos = $VMList.length }
|
||||||
|
$page = $startpos / $step + 1
|
||||||
|
$maxpage = [math]::Ceiling($VMList.length / $step)
|
||||||
|
Write-Host "`nSource VM Selection (Page $page of $maxpage):`n"
|
||||||
|
if ($startpos -gt 0) {
|
||||||
|
Write-Host " 0" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "<< Previous Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
for ($x = $startpos; $x -lt $endpos; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1-$startpos)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($VMlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
if ($endpos -lt $VMList.length) {
|
||||||
|
Write-Host " $($step+1)" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host ">> Next Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
$VMnum = Read-Host "`nSelect VM Number"
|
||||||
|
$VMnum = [int]$VMnum - 1
|
||||||
|
if ($VMnum -eq -1) {
|
||||||
|
$startpos -= $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($VMnum -eq $step) {
|
||||||
|
$startpos += $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$SourceVMName = $VMlist[$VMnum + $startpos].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Locating source VM ""$SourceVMName""... " -NoNewLine
|
||||||
|
if ($abyss = Get-VM $SourceVMName -ErrorAction Stop) {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Aborted" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Error locating VM $SourceVMName in $vCenter" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Datastore -eq "") {
|
||||||
|
$DSList = $mycluster | Get-Datastore | Where-Object {$_.ExtensionData.Host.Count -gt 1}
|
||||||
|
$startpos = 0
|
||||||
|
$step = 10
|
||||||
|
While (($Datastore -eq "") -or (-not $Datastore)) {
|
||||||
|
$endpos = $startpos + 10;
|
||||||
|
if ($endpos -gt $DSList.length) { $endpos = $DSList.length }
|
||||||
|
$page = $startpos / $step + 1
|
||||||
|
$maxpage = [math]::Ceiling($DSList.length / $step)
|
||||||
|
Write-Host "`nDatastore Selection (Page $page of $maxpage):`n"
|
||||||
|
if ($startpos -gt 0) {
|
||||||
|
Write-Host " 0" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "<< Previous Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
for ($x = $startpos; $x -lt $endpos; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1-$startpos)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($DSlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
if ($endpos -lt $DSList.length) {
|
||||||
|
Write-Host " $($step+1)" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host ">> Next Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
$dvSwitchnum = Read-Host "`nSelect Datastore Number"
|
||||||
|
$dvSwitchnum = [int]$dvSwitchnum - 1
|
||||||
|
if ($dvSwitchnum -eq -1) {
|
||||||
|
$startpos -= $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($dvSwitchnum -eq $step) {
|
||||||
|
$startpos += $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$Datastore = $DSlist[$dvSwitchnum + $startpos].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Locating Datastore ""$Datastore""... " -NoNewLine
|
||||||
|
$mydatastore = Get-Datastore $Datastore -ErrorAction Stop
|
||||||
|
if ($mydatastore) {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Unable to locate datastore $Datastore in $Cluster" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Error locating Datastore $Datastore in $vCenter" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Folder -eq "") {
|
||||||
|
Write-Host "Inventorying VM Folder Structure..." -NoNewLine
|
||||||
|
$FolderList = Get-Folder | Where-Object {$_.Parent.Name -eq "vm"} | Sort-Object -Property @{Expression={$_.Name}; Descending=$false}
|
||||||
|
$FolderList += Get-Folder | Where-Object {($_.Parent.Name -ne "vm") -and ($_.Type -eq "VM") -and $($_.Name -ne "vm")} | Sort-Object -Property @{Expression={$_.Parent.Name}; Descending=$false},@{Expression={$_.Name}; Descending=$false}
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
for($x = 0; $x -lt $FolderList.length; ++$x) {
|
||||||
|
$thisfolder = $FolderList[$x]
|
||||||
|
$path = ""
|
||||||
|
if ($thisfolder.Parent.Name -ne "vm") {
|
||||||
|
$searchcount = 0
|
||||||
|
While ($searchcount -lt 10) {
|
||||||
|
$nextfolder = $thisfolder.Parent
|
||||||
|
$path = "$($nextfolder.Name)\$($path)"
|
||||||
|
if ($nextfolder.Parent.Name -ne "vm") {
|
||||||
|
$thisfolder = $nextfolder
|
||||||
|
++$searchcount
|
||||||
|
} else {
|
||||||
|
$searchcount = 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($path -ne "") {
|
||||||
|
$path = "$($path)$($Folderlist[$x].Name)"
|
||||||
|
} else {
|
||||||
|
$path = $Folderlist[$x].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
$FolderList[$x] | Add-Member -NotePropertyName "FullPath" -NotePropertyValue $path
|
||||||
|
}
|
||||||
|
$startpos = 0
|
||||||
|
$step = 10
|
||||||
|
|
||||||
|
While (-not $myfolder) {
|
||||||
|
$endpos = $startpos + 10;
|
||||||
|
if ($endpos -gt $FolderList.length) { $endpos = $FolderList.length }
|
||||||
|
$page = $startpos / $step + 1
|
||||||
|
$maxpage = [math]::Ceiling($FolderList.length / $step)
|
||||||
|
Write-Host "`nFolder Selection (Page $page of $maxpage):`n"
|
||||||
|
if ($startpos -gt 0) {
|
||||||
|
Write-Host " 0" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "<< Previous Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
for ($x = $startpos; $x -lt $endpos; $x++) {
|
||||||
|
$path = $Folderlist[$x].FullPath
|
||||||
|
Write-Host "$(([string]($x+1-$startpos)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$path" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
if ($endpos -lt $FolderList.length) {
|
||||||
|
Write-Host " $($step+1)" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host ">> Next Page" -ForegroundColor White
|
||||||
|
}
|
||||||
|
$Foldernum = Read-Host "`nSelect Folder Number"
|
||||||
|
$Foldernum = [int]$Foldernum - 1
|
||||||
|
if ($Foldernum -eq -1) {
|
||||||
|
$startpos -= $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Foldernum -eq $step) {
|
||||||
|
$startpos += $step
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$Folder = $FolderList[$Foldernum].FullPath
|
||||||
|
$myfolder = $FolderList[$Foldernum].Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Locating Folder ""$Folder""... " -NoNewLine
|
||||||
|
$myfolder = GetFolderFromPath($Folder)
|
||||||
|
if ($myfolder) {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Error locating Folder $Folder in $vCenter" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
## Validate that the proper DRS groups exist for each site in the format "[site] Only VMs"
|
||||||
|
Write-Host "Verifying that the necessary DRS groups exist..."
|
||||||
|
$sites = $data.Site | Select-Object -Unique -CaseInsensitive
|
||||||
|
|
||||||
|
$siteerror = $false
|
||||||
|
foreach ($site in $sites) {
|
||||||
|
$sitegroup = "$site Only VMs"
|
||||||
|
Write-Host " - $sitegroup... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$drsg = Get-DrsGroup -Cluster $Cluster -Name $sitegroup
|
||||||
|
if ($drsg) {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
$siteerror = $true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host "ERROR: Unable to locate DRS group $sitegroup." -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
||||||
|
Write-Host ""
|
||||||
|
$siteerror = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($siteerror) {
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
## Validate that the necessary network port groups exist in the format "[Description] - VLAN[VLAN]"
|
||||||
|
Write-Host "Verifying that the necessary port groups exist..."
|
||||||
|
$pgerror = $false
|
||||||
|
foreach ($row in $data) {
|
||||||
|
$vlan = [int]$row.VLAN
|
||||||
|
$description = $row.Description
|
||||||
|
$myportgroupname = "$description - VLAN$vlan"
|
||||||
|
Write-Host " - $myportgroupname... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$pg = Get-VDPortGroup -Name $myportgroupname
|
||||||
|
if ($pg) {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
$pgerror = $true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
$pgerror = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pgerror) {
|
||||||
|
Write-Host "Operation Terminated" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
foreach($row in $data) {
|
||||||
|
try {
|
||||||
|
$abyss = [int]$row.VLAN
|
||||||
|
} catch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$vlan = [int]$row.VLAN
|
||||||
|
$description = $row.Description
|
||||||
|
|
||||||
|
$myportgroupname = "$description - VLAN$vlan"
|
||||||
|
$myvmname = "KISStress - VLAN$vlan"
|
||||||
|
|
||||||
|
Write-Host
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Get-VM $myvmname -ErrorAction Silent) {
|
||||||
|
Write-Host "WARNING: VM ""$myvmname"" already exists. Skipping." -ForegroundColor Yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: Unable to determine if ""$myvmname"" exists. Skipping." -ForegroundColor Red
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$myportgroup = Get-VdPortGroup -Name $myportgroupname -VDSwitch $dvswitch
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: Could not locate port group ""$myportgroupname"""
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Cloning ""$SourceVMName"" to VM ""$myvmname""... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$task = New-VM -Name $myvmname -VM $SourceVMName -ResourcePool $mycluster -Datastore $Datastore -Location $myfolder -DiskStorageFormat Thin -ErrorAction Silent -RunAsync
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$created = $false
|
||||||
|
while (($task = Get-Task -iD $task.Id).State -eq "Running") {
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
Write-Host "." -NoNewLine
|
||||||
|
}
|
||||||
|
switch(($task = Get-Task -iD $task.Id).State) {
|
||||||
|
"Success" {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
"Error" {
|
||||||
|
if ($task.ExtensionData.Info.Cancelled) {
|
||||||
|
Write-Host "Failure - Task Cancelled" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure - Unknown Error" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$nic = Get-VM $myvmname | Get-NetworkAdapter
|
||||||
|
try {
|
||||||
|
Write-Host "Changing NIC on VM ""$myvmname"" to port group ""$myportgroupname""... " -NoNewLine
|
||||||
|
$task = $nic | Set-NetworkAdapter -Portgroup $myportgroup -Confirm:$false -ErrorAction Stop -RunAsync
|
||||||
|
while (($task = Get-Task -iD $task.Id).State -eq "Running") {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
Write-Host "." -NoNewLine
|
||||||
|
}
|
||||||
|
switch(($task = Get-Task -iD $task.Id).State) {
|
||||||
|
"Success" {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
"Error" {
|
||||||
|
if ($task.ExtensionData.Info.Cancelled) {
|
||||||
|
Write-Host "Failure - Task Cancelled" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure - Unknown Error" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($row.Site) {
|
||||||
|
Write-Host "Adding VM ""$myvmname"" to DRS Group ""$($row.Site) Only VMs"" in cluster $Cluster... " -NoNewLine
|
||||||
|
try {
|
||||||
|
$task = Add-VMToDrsGroup -Cluster $Cluster -DrsGroup "$($row.Site) Only VMs" -VM $myvmname
|
||||||
|
$task | Add-Member -NotePropertyName "Id" -NotePropertyValue "Task-$($task.Value)"
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "ERROR: Error adding VM ""$myvmname"" to DRS Group ""$($row.Site) Only VMs""" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
while (($task = Get-Task -iD $task.Id).State -eq "Running") {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
Write-Host "." -NoNewLine
|
||||||
|
}
|
||||||
|
switch(($task = Get-Task -iD $task.Id).State) {
|
||||||
|
"Success" {
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
"Error" {
|
||||||
|
if ($task.ExtensionData.Info.Cancelled) {
|
||||||
|
Write-Host "Failure - Task Cancelled" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
} else {
|
||||||
|
Write-Host "Failure - Unknown Error" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host "Powering on VM ""$myvmname""... " -NoNewLine
|
||||||
|
$task = Start-VM $myvmname -ErrorAction Stop -RunAsync
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
$booted = $false
|
||||||
|
while (!$booted) {
|
||||||
|
if ((Get-VM $myvmname).ExtensionData.Guest.ToolsStatus -eq "toolsOk") {
|
||||||
|
$booted = $true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
Start-Sleep 5
|
||||||
|
Write-Host "." -NoNewLine
|
||||||
|
}
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Update Network Information If Provided
|
||||||
|
if ($setip) {
|
||||||
|
$ipaddress = $row.IPAddress
|
||||||
|
$netmask = $row.netmask
|
||||||
|
$gateway = $row.Gateway
|
||||||
|
|
||||||
|
if (!$ipaddress -or !$netmask -or !$gateway) { continue }
|
||||||
|
Write-Host "Updating network configuration for vm ""$myvmname""... " -NoNewLine
|
||||||
|
|
||||||
|
$ifcfg = "sudo echo 'STARTMODE=auto' > /etc/sysconfig/network/ifcfg-eth0
|
||||||
|
sudo echo 'BOOTPROTO=static' >> /etc/sysconfig/network/ifcfg-eth0
|
||||||
|
sudo echo 'IPADDR=$ipaddress' >> /etc/sysconfig/network/ifcfg-eth0
|
||||||
|
sudo echo 'NETMASK=$netmask' >> /etc/sysconfig/network/ifcfg-eth0
|
||||||
|
sudo echo 'default $gateway - -' > /etc/sysconfig/network/routes
|
||||||
|
sudo /etc/init.d/network restart
|
||||||
|
"
|
||||||
|
$UserName = "stress"
|
||||||
|
$Password = ConvertTo-SecureString -String "stress" -AsPlainText -Force
|
||||||
|
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $Password
|
||||||
|
try {
|
||||||
|
$abyss = Invoke-VMScript $myvmname -ScriptText $ifcfg -GuestCredential $Credential -ScriptType Bash
|
||||||
|
Write-Host "Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Message: $($_.Exception.Message)" -ForegroundColor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.1.0"
|
||||||
|
$fileDate = "2025-04-02"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "vSphere TPM Key Inventory" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Collect TPM encryption keys for all ESXi hosts."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " GetKeys.ps1 (-vcenter [vcenter host name]) (-savecred) (-help)"
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -savecred " -foregroundcolor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -foregroundcolor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If no any of the information is not provided, you will be prompted. If a credential has been previously stored, it will be used again unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-Module -ListAvailable -Name VMware.PowerCLI*)) {
|
||||||
|
Write-Host "ERROR: VMware PowerCLI is not installed!" -foregroundcolor yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$hideresult = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($savecred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vcenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kis-getkeys-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kis-getkeys-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kis-getkeys-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vcenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = (Get-Date).ToString("yyyyMMdd_hhmm")
|
||||||
|
$exportfile = "TPMKeys-$vCenter-$now.csv"
|
||||||
|
|
||||||
|
$VMHosts = Get-VMHost | Sort-Object
|
||||||
|
$VMHostKeys = @()
|
||||||
|
foreach ($VMHost in $VMHosts) {
|
||||||
|
$esxcli = Get-EsxCli -VMHost $VMHost -V2
|
||||||
|
try {
|
||||||
|
$encryption = $esxcli.system.settings.encryption.get.Invoke()
|
||||||
|
if ($encryption.Mode -eq "TPM")
|
||||||
|
{
|
||||||
|
$key = $esxcli.system.settings.encryption.recovery.list.Invoke()
|
||||||
|
$hostKey = [pscustomobject]@{
|
||||||
|
Host = $VMHost.Name
|
||||||
|
EncryptionMode = $encryption.Mode
|
||||||
|
RequireExecutablesOnlyFromInstalledVIBs = $encryption.RequireExecutablesOnlyFromInstalledVIBs
|
||||||
|
RequireSecureBoot = $encryption.RequireSecureBoot
|
||||||
|
RecoveryID = $key.RecoveryID
|
||||||
|
RecoveryKey = $key.Key
|
||||||
|
}
|
||||||
|
$VMHostKeys += $hostKey
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$hostKey = [pscustomobject]@{
|
||||||
|
Host = $VMHost.Name
|
||||||
|
EncryptionMode = $encryption.Mode
|
||||||
|
RequireExecutablesOnlyFromInstalledVIBs = $encryption.RequireExecutablesOnlyFromInstalledVIBs
|
||||||
|
RequireSecureBoot = $encryption.RequireSecureBoot
|
||||||
|
RecoveryID = $null
|
||||||
|
RecoveryKey = $null
|
||||||
|
}
|
||||||
|
$VMHostKeys += $hostKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$VMHost.Name + $_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Host "Exporting TPM keys for all hosts in $vcenter`n to $exportfile..." -NoNewLine
|
||||||
|
try {
|
||||||
|
$VMHostKeys | Export-Csv $exportfile
|
||||||
|
Write-Host " Complete" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failed" -ForegroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Attempting to reset all TPM Encryption Recovery Key Backup Alarms..."
|
||||||
|
# Locate TPM Encrytpion Recovery Key Backup Alarm ID
|
||||||
|
$alarm = Get-AlarmDefinition "TPM Encryption Recovery Key Backup Alarm"
|
||||||
|
$alarmID = $alarm.Id -split '-', 2 | select-object -last 1
|
||||||
|
$alarmMgr = Get-View AlarmManager
|
||||||
|
|
||||||
|
foreach ($VMHost in $VMHosts) {
|
||||||
|
try {
|
||||||
|
$decalarm = $VMHost.ExtensionData.TriggeredAlarmState | where-object {$_.Alarm.Value -eq $alarmID} | Select-Object -first 1
|
||||||
|
if ([string]::IsNullorEmpty($decalarm)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Host "Error retrieving alarms for host $VMHost"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Clearing all yellow alarms from ESXi hosts..."
|
||||||
|
try {
|
||||||
|
$filter = New-Object VMware.Vim.AlarmFilterSpec
|
||||||
|
$filter.Status += [VMware.Vim.ManagedEntityStatus]::yellow
|
||||||
|
$filter.TypeEntity = [VMware.Vim.AlarmFilterSpecAlarmTypeByEntity]::entityTypeHost
|
||||||
|
$filter.TypeTrigger = [vmware.vim.AlarmFilterSpecAlarmTypeByTrigger]::triggerTypeAll
|
||||||
|
$alarmMgr.ClearTriggeredAlarms($filter)
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failed" -ForegroundColor Red
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
param (
|
||||||
|
[string]$vcenter = "",
|
||||||
|
[switch]$allvms = $false,
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.0.0"
|
||||||
|
$fileDate = "2024-12-11"
|
||||||
|
$savecred = $false
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "vCenter Snapshot Report" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host "Command Syntax:" -ForegroundColor Green
|
||||||
|
Write-Host 'GetSnaps.ps1 -vcenter="VCURI" [-help] [-savecred]' -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Command line options:" -ForegroundColor Green
|
||||||
|
Write-Host "---------------------" -ForegroundColor Green
|
||||||
|
Write-Host "-vcenter - Specify the FQDN for the vCenter server" -ForegroundColor Green
|
||||||
|
Write-Host "-allvms - Get snapshots for all VMs. Omitting this option will only check powered on VMs." -ForegroundColor Green
|
||||||
|
Write-Host "-savecred - Save Credentials. If credentials were previously saved and this option is not selected," -ForegroundColor Green
|
||||||
|
Write-Host " they will be used." -ForegroundColor Green
|
||||||
|
Write-Host "-help - Show this help information." -ForegroundColor Green
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vcenter -eq "") {
|
||||||
|
$vcenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Test-Path -Path "$env:USERPROFILE\GetSnaps-${vcenter}.cred" -PathType Leaf) {
|
||||||
|
Write-Host "Using stored credentials for $vcenter."
|
||||||
|
$cred = Import-CliXML -path "$env:USERPROFILE\GetSnaps-${vcenter}.cred"
|
||||||
|
} else {
|
||||||
|
$cred = Get-Credential -Message "Enter credentials for vCenter $vcenter"
|
||||||
|
}
|
||||||
|
$vcenterConnection = connect-viserver $vcenter -credential $cred -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: Invalid credentials or incorrect vCenter FQDN"
|
||||||
|
Write-Host $_
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if ($savecred) {
|
||||||
|
Write-Host "Storing credentials for $vcenter."
|
||||||
|
$cred | Export-CliXML -Path "$env:USERPROFILE\GetSnaps-${vcenter}.cred"
|
||||||
|
}
|
||||||
|
|
||||||
|
$DesktopPath = [Environment]::GetFolderPath("Desktop")
|
||||||
|
$now = (Get-Date).ToString("yyyyMMdd_hhmm")
|
||||||
|
$outputFileName = "$DesktopPath\VMSnapshotList-$now.html"
|
||||||
|
|
||||||
|
# Get all VMs
|
||||||
|
if ($allvms) {
|
||||||
|
$VMs = Get-VM
|
||||||
|
} else {
|
||||||
|
$VMs = Get-VM | Where {$_.PowerState -eq "PoweredOn"}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create empty array to hold snapshot information
|
||||||
|
$SnapshotInfo = @()
|
||||||
|
|
||||||
|
# Loop through each VM and get snapshot information
|
||||||
|
foreach ($VM in $VMs) {
|
||||||
|
$Snapshots = Get-Snapshot -VM $VM
|
||||||
|
|
||||||
|
# Loop through each snapshot and add information to array
|
||||||
|
foreach ($Snapshot in $Snapshots) {
|
||||||
|
$SnapshotInfo += [PSCustomObject]@{
|
||||||
|
VMName = $VM.Name
|
||||||
|
SnapshotName = [System.Uri]::UnescapeDataString($Snapshot.Name)
|
||||||
|
Created = $Snapshot.Created
|
||||||
|
Description = $Snapshot.Description
|
||||||
|
SizeGB = [math]::Round(($Snapshot.SizeGB),2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create HTML output
|
||||||
|
$HTML = @"
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Snapshots Report</title>
|
||||||
|
<style>
|
||||||
|
body {background-color: #D3D3D3;}
|
||||||
|
table {border: 3px solid black; border-collapse: collapse; font-size: 14px; font-family: Arial, sans-serif; background-color: #3B3B3B; color: white; max-width: 800px;}
|
||||||
|
th, td {border: 2px solid black; padding: 10px; text-align: left; width: auto;}
|
||||||
|
th {background-color: #2F4F4F; font-weight: bold;}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
"@
|
||||||
|
$HTML += $SnapshotInfo | ConvertTo-Html -Fragment -Property VMName, SnapshotName, Created, Description, SizeGB
|
||||||
|
$HTML += @"
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"@
|
||||||
|
|
||||||
|
# Output HTML to file
|
||||||
|
$HTML | Out-File -FilePath $outputFileName
|
||||||
|
|
||||||
|
# Output confirmation message
|
||||||
|
Write-Host "Generating Snapshots Report"
|
||||||
|
Write-Host "Your snapshots report has been saved to: $outputFileName"
|
||||||
|
|
||||||
|
# Disconnect from vCenter Server
|
||||||
|
Disconnect-VIServer -Confirm:$false
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
param (
|
||||||
|
[string]$vcenter = "",
|
||||||
|
# [switch]$allvms,
|
||||||
|
[switch]$savecred,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.2.0"
|
||||||
|
$fileDate = "2024-12-13"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "vSphere VM Network Assignment Export" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host "Command Syntax:" -ForegroundColor Green
|
||||||
|
Write-Host 'GetVMNetworks.ps1 -vcenter="VCURI" [-help] [-savecred]' -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Command line options:" -ForegroundColor Green
|
||||||
|
Write-Host "---------------------" -ForegroundColor Green
|
||||||
|
Write-Host "-vcenter - Specify the URI for the vCenter server" -ForegroundColor Green
|
||||||
|
Write-Host "-savecred - Save Credentials. If credentials were previously saved and this option is not selected," -ForegroundColor Green
|
||||||
|
Write-Host " they will be used." -ForegroundColor Green
|
||||||
|
Write-Host "-help - Show this help information." -ForegroundColor Green
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($vcenter -eq "") {
|
||||||
|
$vcenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Test-Path -Path "$env:USERPROFILE\GetVMNetworks-$vcenter.cred" -PathType Leaf) {
|
||||||
|
Write-Host "Using stored credentials for $vcenter."
|
||||||
|
$cred = Import-CliXML -path "$env:USERPROFILE\GetVMNetworks-$vcenter.cred"
|
||||||
|
} else {
|
||||||
|
$cred = Get-Credential -Message "Enter credentials for vCenter $vcenter"
|
||||||
|
}
|
||||||
|
$vcenterConnection = connect-viserver $vcenter -credential $cred -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR: Invalid credentials or incorrect vCenter FQDN"
|
||||||
|
Write-Host $_
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
if ($savecred) {
|
||||||
|
Write-Host "Storing credentials for $vcenter."
|
||||||
|
$cred | Export-CliXML -Path "$env:USERPROFILE\GetVMNetworks-$vcenter.cred"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Output filename
|
||||||
|
$DesktopPath = [Environment]::GetFolderPath("Desktop")
|
||||||
|
$now = (Get-Date).ToString("yyyyMMdd_hhmm")
|
||||||
|
$csvFileName = "$DesktopPath\VMNetworkList-$now.csv"
|
||||||
|
|
||||||
|
# Find the maximum number of adapters in a VM to create the CSV header properly
|
||||||
|
$allvms = get-vm
|
||||||
|
$maxnics = 0
|
||||||
|
foreach ($vm in $allvms) {
|
||||||
|
$adaptercount = ($vm | get-networkadapter | measure).Count
|
||||||
|
if ($adaptercount -gt $maxnics) {
|
||||||
|
$maxnics = $adaptercount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write the CSV header
|
||||||
|
$header = """Cluster"",""VM Name"""
|
||||||
|
for ($x = 1; $x -le $maxnics; ++$x) {
|
||||||
|
#write-host -NoNewLine ",Network Adapter $x"
|
||||||
|
$header = "$header,""Network Adapter $x"""
|
||||||
|
}
|
||||||
|
# write-host
|
||||||
|
$header | Out-File -FilePath $csvFileName -Encoding UTF8
|
||||||
|
|
||||||
|
# Get list of clusters
|
||||||
|
$clusters = get-cluster
|
||||||
|
|
||||||
|
# Iterate through cluster list
|
||||||
|
foreach ($cluster in $clusters) {
|
||||||
|
# Get list of VMs in the cluster
|
||||||
|
$vms = $cluster | get-vm | sort-object -Property Name
|
||||||
|
$clusterName = $cluster.Name
|
||||||
|
# Iterate through the VM list
|
||||||
|
foreach($vm in $vms) {
|
||||||
|
$vmName = $vm.Name
|
||||||
|
$entry = """$cluster"",""$vmName"""
|
||||||
|
# Get all network adapters for the VM
|
||||||
|
$netAdapters = $vm | get-networkadapter
|
||||||
|
# Iterate through adapter list
|
||||||
|
foreach ($adapter in $netAdapters) {
|
||||||
|
# Append port group name for each adapter
|
||||||
|
$adapterName = $adapter.Name
|
||||||
|
$adapterPG = $adapter.NetworkName
|
||||||
|
$entry = "$entry,""$adapterPG"""
|
||||||
|
}
|
||||||
|
# Write host entry
|
||||||
|
#write-Host $entry
|
||||||
|
$entry | Out-File -FilePath $csvFileName -Append -Encoding UTF8
|
||||||
|
}
|
||||||
|
Write-Host "`nData for cluster $clusterName has been saved to the file $csvFileName."
|
||||||
|
}
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$cluster = "",
|
||||||
|
[string]$filename = "vmexport.xlsx",
|
||||||
|
[string]$Customer = "",
|
||||||
|
[switch]$Help = $false,
|
||||||
|
[switch]$SaveCred = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.0.0"
|
||||||
|
$fileDate = "2026-05-21"
|
||||||
|
$scriptName = Split-Path -Path $PSCommandPath -Leaf
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "Collect VM Information for Upgrades" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
function CheckModuleInstalled($moduleName, $command) {
|
||||||
|
Write-Host "Checking that package $moduleName is installed..." -NoNewLine
|
||||||
|
if (-not(get-command $command -erroraction silentlycontinue)) {
|
||||||
|
Write-Host " Missing" -ForegroundColor Red
|
||||||
|
if (-not (Get-Module -ListAvailable -Name $moduleName)) {
|
||||||
|
$response = ""
|
||||||
|
while (($response -ne "yes") -and ($response -ne "no")) {
|
||||||
|
$response = (Read-Host "ImportExcel module not instaled. Install now? (yes/no)").ToLower()
|
||||||
|
}
|
||||||
|
if ($response -eq "no") {
|
||||||
|
Write-Host "Operation Cancelled." -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
Write-Host "Installing PowerShell module $moduleName..." -NoNewLine
|
||||||
|
Install-Module -Name $moduleName -Scope CurrentUser -Force
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
Write-Host "Loading PowerShell module $moduleName..." -NoNewLine
|
||||||
|
Import-Module $moduleName
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host " Found" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for ImportExcel and install if missing
|
||||||
|
CheckModuleInstalled -moduleName "VCF.PowerCLI" -command "connect-viserver"
|
||||||
|
CheckModuleInstalled -moduleName "ImportExcel" -command "import-excel"
|
||||||
|
|
||||||
|
$moduleName = "ImportExcel"
|
||||||
|
Import-Module ImportExcel
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Generate a spreadsheet for VM Upgrades."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " $scriptName (-vcenter [vcenter host name]) (-cluster ""[cluster]"") (-filename ""[filename]"") (-customer ""[customer]""" -foregroundcolor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -cluster " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the cluster as shown in vCenter."
|
||||||
|
Write-Host -NoNewLine " -customer " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the customer to display on the sheet title."
|
||||||
|
Write-Host -NoNewLine " -filename " -foregroundcolor Green
|
||||||
|
Write-Host "- The CSV filename to save the result."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If any of the information is not provided, you will be prompted. If a credential has been previously stored, it will"
|
||||||
|
Write-Host "be used again unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If a filename is not specified, the file vmexport.csv will be created in the current directory."
|
||||||
|
Write-Host
|
||||||
|
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||||
|
|
||||||
|
$quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kistools-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $filename -PathType Leaf) {
|
||||||
|
Write-Host "File $filename already exists." -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cluster -eq "") {
|
||||||
|
$Clusterlist = Get-Cluster | Sort-Object
|
||||||
|
While (($cluster -eq "") -or (-not $cluster)) {
|
||||||
|
Write-Host "`nCluster Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $Clusterlist.length; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($Clusterlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$Clusternum = Read-Host "`nSelect Cluster Number"
|
||||||
|
if ($Clusternum -as [int]) {
|
||||||
|
$Clusternum = [int]$Clusternum - 1
|
||||||
|
$cluster = $Clusterlist[$Clusternum]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
} else {
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
# Collect base VMware Tools and Hardware version from first Host
|
||||||
|
$myhost = $mycluster | get-vmhost | select-object -first 1
|
||||||
|
$esxcli = Get-EsxCLI -VMHost $myhost -V2
|
||||||
|
$latestHW = ($myhost | Get-View).Capability.MaxSupportedVmVersion
|
||||||
|
$latestVMT = ($esxcli.software.vib.list.invoke() | Where-Object {$_.ID -match "VMware_locker_tools"}).Version
|
||||||
|
|
||||||
|
$latestHW
|
||||||
|
$latestVMT
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
Write-Host "Gathering information about VMs in cluster $cluster..." -NoNewLine
|
||||||
|
$vmlist = $mycluster | get-vm
|
||||||
|
$vmcount = $vmlist.length
|
||||||
|
|
||||||
|
$vmresponse = @()
|
||||||
|
|
||||||
|
for ($x = 0; $x -lt $vmlist.length; $x++) {
|
||||||
|
$percent = [Math]::Round(($x / $vmlist.length) * 100,0)
|
||||||
|
Write-Progress -ID 1 -Activity "Collecting VM Information" -Status "Processing VM $($x+1) of $($vmlist.length)" -PercentComplete $percent
|
||||||
|
$thisvm = $vmlist[$x];
|
||||||
|
$thisvmguest = $thisvm | get-vmguest
|
||||||
|
$vmname = $thisvm.Name;
|
||||||
|
$vmhardwareversion = $thisvmguest.ExtensionData.HwVersion
|
||||||
|
$vmtoolsstatus = $thisvmguest.ExtensionData.ToolsRunningStatus
|
||||||
|
$vmtoolsversionstatus = $thisvmguest.ExtensionData.ToolsVersionStatus
|
||||||
|
$vmosname = $thisvmguest.OSFullName
|
||||||
|
$vmtoolsversion = $thisvmguest.ToolsVersion
|
||||||
|
|
||||||
|
$badvmnics = ($thisvm | get-NetworkAdapter | Where-Object {$_.Type -ne "Vmxnet3"}).length -gt 0
|
||||||
|
|
||||||
|
$thisvmobj = [PSCustomObject]@{
|
||||||
|
"Name" = $vmname
|
||||||
|
"VM Hardware Version" = $vmhardwareversion
|
||||||
|
"VMTools Status" = $vmtoolsstatus
|
||||||
|
"VMTools Version" = $vmtoolsversion
|
||||||
|
"VMTools Version Status" = $vmtoolsversionstatus
|
||||||
|
"Has Non vmxnet3 NICs" = $badvmnics
|
||||||
|
"VMHW Updated" = $null
|
||||||
|
"VMTools Updated" = $null
|
||||||
|
"In Prog" = ""
|
||||||
|
"Migrating" = ""
|
||||||
|
"Complete" = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmresponse += $thisvmobj
|
||||||
|
}
|
||||||
|
Write-Host "Disconnecting from vCenter $vcenter..." -NoNewLine
|
||||||
|
try {
|
||||||
|
$quiet = Disconnect-VIServer $vcenter -Confirm:$false
|
||||||
|
} catch {
|
||||||
|
Write-Host " FAILURE" -ForegroundColor Yellow - BackgroundColor Red
|
||||||
|
}
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
Write-Progress -ID 1 -Completed
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
Write-Host "Writing information about $($vmresponse.length) VMs to file $filename..." -NoNewLine
|
||||||
|
try {
|
||||||
|
$sheetTitle = "VM Export for Cluster $cluster - $timestamp"
|
||||||
|
if ($customer -ne "") {
|
||||||
|
$sheetTitle = "$customer - $sheetTitle"
|
||||||
|
}
|
||||||
|
$exceltable = $vmresponse | Export-Excel -path $filename -WorksheetName "vCenter VM Data" -PassThru -Autosize -FreezeTopRow `
|
||||||
|
-TableName "VMData" -TableStyle Medium15 -Title $sheetTitle -TitleBold -TitleSize 22 `
|
||||||
|
-TableTotalSettings @{ CPU = "Sum"; RAM = "Sum"; "Provisioned Storage" = "Sum"; "Used Space Original" = "Sum" }
|
||||||
|
} catch {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "ERROR! Unable to create file $filename" -ForegroundColor Yellow
|
||||||
|
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red -BackgroundColor Yellow
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$sheet = $exceltable.Workbook.Worksheets["vCenter VM Data"]
|
||||||
|
$sheet.Column(3) | Set-ExcelRange -NFormat '#,##0 " GB"'
|
||||||
|
$sheet.Column(4) | Set-ExcelRange -NFormat '#,##0.00 " GB"'
|
||||||
|
$sheet.Column(5) | Set-ExcelRange -NFormat '#,##0.00 " GB"'
|
||||||
|
$sheet.Column(6) | Set-ExcelRange -NFormat '#,##0.00 " GB"'
|
||||||
|
Set-Format -Address $sheet.Cells["2:2"] -WrapText
|
||||||
|
$sheet.InsertColumn(1,1)
|
||||||
|
$sheet.Column(1).Width = 2
|
||||||
|
$sheet.Cells["I:R"].Style.HorizontalAlignment = "Center"
|
||||||
|
$sheet.Cells["C2:G2"].Style.HorizontalAlignment = "Center"
|
||||||
|
$sheet.Column(5).Width = 13
|
||||||
|
$sheet.Column(6).Width = 13
|
||||||
|
$sheet.Column(7).Width = 13
|
||||||
|
$sheet.Column(13).Width = 12
|
||||||
|
$sheet.Column(14).Width = 12
|
||||||
|
$sheet.Column(15).Width = 12
|
||||||
|
$sheet.Column(16).Width = 12
|
||||||
|
$sheet.Column(17).Width = 12
|
||||||
|
$sheet.Column(18).Width = 12
|
||||||
|
For ($counter = 3; $counter -lt 3 + $vmcount; ++$counter) {
|
||||||
|
$PFormula = '=IF(AND(COUNTIF(M' + $counter + ':O' + $counter + ',"X")<3,COUNTIF(M' + $counter + ':O' + $counter + ',"")<3),"X","")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["P" + $counter] -Formula $PFormula
|
||||||
|
$QFormula = '=IF(OR(M' + $counter + '="O",N' + $counter + '="O",O' + $counter + '="O"),"X","")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["Q" + $counter] -Formula $QFormula
|
||||||
|
$RFormula = '=IF(AND(M' + $counter + '="X",N' + $counter + '="X",O' + $counter + '="X"),"X","")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["R" + $counter] -Formula $RFormula
|
||||||
|
$HFormula = '=if(AND($G' + $counter + '>0,$G' + $counter + '<>""), $F' + $counter + ',"")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["H" + $counter] -Formula $HFormula
|
||||||
|
}
|
||||||
|
$datarange = "B3:R" + (2+$vmcount)
|
||||||
|
Add-ConditionalFormatting -Worksheet $sheet -Address $datarange -RuleType Expression -ConditionValue '=INDIRECT("VMData[@Disk Format]")="Thick"' -BackgroundColor Red -ForegroundColor White
|
||||||
|
Add-ConditionalFormatting -Worksheet $sheet -Address $datarange -RuleType Expression -ConditionValue '=INDIRECT("VMData[@Disk Format]")="O"' -BackgroundColor Orange
|
||||||
|
Add-ConditionalFormatting -Worksheet $sheet -Address $datarange -RuleType Expression -ConditionValue '=INDIRECT("VMData[@In Prog]")="X"' -BackgroundColor Yellow
|
||||||
|
Add-ConditionalFormatting -Worksheet $sheet -Address $datarange -RuleType Expression -ConditionValue '=INDIRECT("VMData[@Complete]")="X"' -BackgroundColor Green
|
||||||
|
$sheet.Cells["S4"].Value = "Total VMs:"
|
||||||
|
$sheet.Cells["S5"].Value = "Thick Provisioned:"
|
||||||
|
$sheet.Cells["S6"].Value = "Converting to Thin:"
|
||||||
|
$sheet.Cells["S7"].Value = "Partially Migrated:"
|
||||||
|
$sheet.Cells["S8"].Value = "In Progress:"
|
||||||
|
$sheet.Cells["S9"].Value = "Completed:"
|
||||||
|
$sheet.Cells["S10"].Value = "Remaining:"
|
||||||
|
$sheet.Cells["S12"].Value = "Original Space Usage:"
|
||||||
|
$sheet.Cells["S13"].Value = "New Space Usage:"
|
||||||
|
$sheet.Cells["S14"].Value = "Space Saved:"
|
||||||
|
$sheet.Cells["S15"].Value = "Savings:"
|
||||||
|
$sheet.Cells["S4:S15"].Style.HorizontalAlignment = "Right"
|
||||||
|
$sheet.Column(19).Width = 22
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T4"] -Formula '=COUNTA(VMData[Name])'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T5"] -Formula '=COUNTIF(VMData[Disk Format], "<>Thin")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T6"] -Formula '=COUNTIF(VMData[Disk Format], "O")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T7"] -Formula '=COUNTIF(VMData[Migrating],"X")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T8"] -Formula '=COUNTIF(VMData[In Prog], "X")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T9"] -Formula '=COUNTIF(VMData[Complete], "X")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T10"] -Formula '=T4-T9'
|
||||||
|
$formula = '=SUM(H3:H' + (2+$vmcount) +')'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T12"] -Formula $formula
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T12"] -NFormat '#,##0.00 " GB"'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T13"] -Formula '=SUM(VMData[Used Space Now])'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T13"] -NFormat '#,##0.00 " GB"'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T14"] -Formula '=T12-T13'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T14"] -NFormat '#,##0.00 " GB"'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T15"] -Formula '=IF(T12>0,T14/T12,"")'
|
||||||
|
Set-ExcelRange -Address $sheet.Cells["T15"] -NFormat '#.00%'
|
||||||
|
$sheet.Column(8).Hidden = $true
|
||||||
|
$sheet.Column(20).Width = 14
|
||||||
|
} catch {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "ERROR! Unable to create file $filename" -ForegroundColor Yellow
|
||||||
|
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red -BackgroundColor Yellow
|
||||||
|
try {
|
||||||
|
Close-ExcelPackage $exceltable
|
||||||
|
Remove-Item $filename
|
||||||
|
Remove-Item $filename
|
||||||
|
} catch {
|
||||||
|
Remove-Item $filename
|
||||||
|
Remove-Item $filename
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$exceltable.Workbook.WorkSheets[1].Tables["VMData"].ShowFilter = $false
|
||||||
|
Close-ExcelPackage $exceltable
|
||||||
|
Disconnect-V
|
||||||
|
Write-Host " Success" -ForegroundColor Green
|
||||||
|
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$VMHost = "",
|
||||||
|
[string]$Test1Vmk = "",
|
||||||
|
[string]$Test1Host = "",
|
||||||
|
[int]$Test1Frame = 0,
|
||||||
|
[string]$Test2Vmk = "",
|
||||||
|
[string]$Test2Host = "",
|
||||||
|
[int]$Test2Frame = 0,
|
||||||
|
[int]$Count = 0,
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
<# Write-Host "vCenter - $vCenter"
|
||||||
|
Write-Host "VMHost - $VMHost"
|
||||||
|
Write-Host "Test1VMK - $Test1Vmk"
|
||||||
|
Write-Host "Test1Host - $Test1Host"
|
||||||
|
Write-Host "Test1Frame - $Test1Frame"
|
||||||
|
Write-Host "Test2VMK - $Test2Vmk"
|
||||||
|
Write-Host "Test2Host - $Test2Host"
|
||||||
|
Write-Host "Test2Frame - $Test2Frame"
|
||||||
|
Write-Host "Count - $Count"
|
||||||
|
Write-Host "SaveCred - $SaveCred"#>
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.3.2"
|
||||||
|
$fileDate = "2023-04-16"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "Host Mulitple Concurrent VMK Ping Script" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Perform multiple ping tests simultaneously from an ESXi host."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " HostMultiPingTest.ps1 (-vcenter [vcenter host name]) (-VMHost ""[host]"") (-Test1Host ""[ipaddress]"")" -foregroundcolor green
|
||||||
|
Write-Host " (-Test1VMK ""[vmkPort]"") (-Test1Frame [framesize]) (-Test2Host ""[ipaddress]"") (-Test2VMK ""[vmkPort]"")" -foregroundcolor green
|
||||||
|
Write-Host " (-Test2Frame [framesize]) (-count [count]) (-savecred) (-help)`n" -foregroundcolor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -VMHost " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the host as shown in vCenter."
|
||||||
|
Write-Host -NoNewLine " -Test1Host " -foregroundcolor Green
|
||||||
|
Write-Host "- The IP address of the system to ping for test 1."
|
||||||
|
Write-Host -NoNewLine " -Test1Vmk " -foregroundcolor Green
|
||||||
|
Write-Host "- The VMkernel port on the host to ping for test 1."
|
||||||
|
Write-Host -NoNewLine " -Test1Frame " -foregroundcolor Green
|
||||||
|
Write-Host "- The TCP frame size to use for test 1. Default: 1500."
|
||||||
|
Write-Host -NoNewLine " -Test2Host " -foregroundcolor Green
|
||||||
|
Write-Host "- The IP address of the system to ping for test 2."
|
||||||
|
Write-Host -NoNewLine " -Test2Vmk " -foregroundcolor Green
|
||||||
|
Write-Host "- The VMkernel port on the host to ping for test 2."
|
||||||
|
Write-Host -NoNewLine " -Test2Frame " -foregroundcolor Green
|
||||||
|
Write-Host "- The TCP frame size to use for test 2. Default: 1500."
|
||||||
|
Write-Host -NoNewLine " -count " -foregroundcolor Green
|
||||||
|
Write-Host "- The number of ping tests to run. Default: unlimited."
|
||||||
|
Write-Host -NoNewLine " -savecred " -foregroundcolor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -foregroundcolor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If no any of the information is not provided, you will be prompted. If a credential has been previously stored, it will be used again"
|
||||||
|
Write-Host "unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
exit
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter x"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kispingtest-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kispingtest-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kispingtest-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($VMHost -eq "") {
|
||||||
|
$VMHostlist = Get-VMHost | Sort-Object
|
||||||
|
While (($VMHost -eq "") -or (-not $VMHost)) {
|
||||||
|
Write-Host "`nHost Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $VMHostlist.length; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($VMHostlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$VMHostnum = Read-Host "`nSelect Host Number"
|
||||||
|
$VMHostnum = [int]$VMHostnum - 1
|
||||||
|
$VMHost = $VMHostlist[$VMHostnum]
|
||||||
|
}
|
||||||
|
$myhost = get-vmhost $VMHost
|
||||||
|
} else {
|
||||||
|
$myhost = get-vmhost $VMHost
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmks = $myhost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "vmk*"} | Sort-Object Name
|
||||||
|
While (($Test1Vmk -eq "") -or (-not $Test1Vmk)) {
|
||||||
|
Write-Host "`nVMKernel Port 1 Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $vmks.length; $x++) {
|
||||||
|
$myvmk1 = $vmks[$x];
|
||||||
|
$mask = [ipaddress]$myvmk1.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($myvmk1.Name) ($($myvmk1.IP)/$($mask_length))" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$vmknum = Read-Host "`nSelect VMKernel Port Number for Test 1"
|
||||||
|
$Test1Vmk = $vmks[$vmknum - 1].Name
|
||||||
|
$myvmk1 = $vmks[$vmknum - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((-not(Test-Path variable:myvmk1) -or ($myvmk1 -ne $null))) {
|
||||||
|
$myvmk1 = $myhost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "$Test1Vmk"}
|
||||||
|
$mask = [ipaddress]$myvmk1.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "Using $($myvmk1.Name) - $($myvmk.PortGroupName) ($($myvmk1.IP)/$($mask_length)) for Test 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmk1testvalid = $false
|
||||||
|
while (-not $vmk1testvalid) {
|
||||||
|
if ($Test1Host -ne "") {
|
||||||
|
$thisip = [ipaddress]$Test1Host
|
||||||
|
$subnet = [ipaddress]$myvmk1.IP
|
||||||
|
$netmask = [ipaddress]$myvmk1.SubnetMask
|
||||||
|
$ipbits = [int[]]$($myvmk1.IP).split('.')
|
||||||
|
$maskbits = [int[]]$($myvmk1.SubnetMask).split('.')
|
||||||
|
$networkidbits = 0..3 | ForEach-Object { $ipbits[$_] -band $maskbits[$_] }
|
||||||
|
$networkid = [ipaddress]($networkidbits -join '.')
|
||||||
|
If ($networkid.Address -eq ($thisip.Address -band $netmask.Address)) {
|
||||||
|
$vmk1testvalid = $true
|
||||||
|
} else {
|
||||||
|
Write-Host "Error: IP Address is outside the allowed subnet." -ForegroundColor Red
|
||||||
|
$Test1Host = Read-Host "Enter IP Address to ping for Test 1"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$Test1Host = Read-Host "Enter IP Address to ping for Test 1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
While ( (-not ($Test1Frame -is [int]) -or ($Test1Frame -lt 1500) ) ) {
|
||||||
|
if ($Test1Frame -eq 0) {
|
||||||
|
$Test1Frame = Read-Host "`nFrame size for Test 1 (1500)"
|
||||||
|
if (!($Test1Frame -is [int]) -or ($Test1Frame -lt 1500)) { $Test1Frame = 1500 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
While (($Test2Vmk -eq "") -or (-not $Test2Vmk)) {
|
||||||
|
Write-Host "`nVMKernel Port 2 Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $vmks.length; $x++) {
|
||||||
|
$myvmk2 = $vmks[$x]
|
||||||
|
if ($myvmk2.Name.substring(0,3) -ne "vmk") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$mask = [ipaddress]$myvmk2.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($myvmk2.Name) - $($myvmk.PortGroupName) ($($myvmk2.IP)/$($mask_length))" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$vmknum = Read-Host "`nSelect VMKernel Port Number for Test 2"
|
||||||
|
$Test2Vmk = $vmks[$vmknum - 1].Name
|
||||||
|
$myvmk2 = $vmks[$vmknum - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((-not(Test-Path variable:myvmk2) -or ($myvmk2 -ne $null))) {
|
||||||
|
$myvmk2 = $myhost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "$Test2Vmk"}
|
||||||
|
$mask = [ipaddress]$myvmk2.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "Using $($myvmk2.Name) ($($myvmk2.IP)/$($mask_length)) for Test 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmk2testvalid = $false
|
||||||
|
while (-not $vmk2testvalid) {
|
||||||
|
if (($Test2Host -ne "") -and $Test2Host) {
|
||||||
|
$thisip = [ipaddress]$Test2Host
|
||||||
|
$subnet = [ipaddress]$myvmk2.IP
|
||||||
|
$netmask = [ipaddress]$myvmk2.SubnetMask
|
||||||
|
$ipbits = [int[]]$($myvmk2.IP).split('.')
|
||||||
|
$maskbits = [int[]]$($myvmk2.SubnetMask).split('.')
|
||||||
|
$networkidbits = 0..3 | ForEach-Object { $ipbits[$_] -band $maskbits[$_] }
|
||||||
|
$networkid = [ipaddress]($networkidbits -join '.')
|
||||||
|
If ($networkid.Address -eq ($thisip.Address -band $netmask.Address)) {
|
||||||
|
$vmk2testvalid = $true
|
||||||
|
} else {
|
||||||
|
Write-Host "Error: IP Address is outside the allowed subnet." -ForegroundColor Red
|
||||||
|
$Test2Host = Read-Host "Enter IP Address to ping for Test 2"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$Test2Host = Read-Host "Enter IP Address to ping for Test 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
While ( (-not ($Test2Frame -is [int]) -or ($Test2Frame -lt 1500) ) ) {
|
||||||
|
if ($Test2Frame -eq 0) {
|
||||||
|
$Test2Frame = Read-Host "`nFrame size for Test 2 (1500)"
|
||||||
|
if (!($Test2Frame -is [int]) -or ($Test2Frame -lt 1500)) { $Test2Frame = 1500 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-host "`nBegin Testing:"
|
||||||
|
|
||||||
|
$esxcli = get-esxcli -vmhost (get-vmhost $myhost) -v2
|
||||||
|
$params1 = (get-esxcli -v2 -vmhost (get-vmhost $myhost)).network.diag.ping.CreateArgs()
|
||||||
|
$params2 = (get-esxcli -v2 -vmhost (get-vmhost $myhost)).network.diag.ping.CreateArgs()
|
||||||
|
$params1.host = $Test1Host
|
||||||
|
$params1.interface = $Test1Vmk
|
||||||
|
$params1.size = $Test1Frame
|
||||||
|
$params1.count = 1
|
||||||
|
$params2.host = $Test2Host
|
||||||
|
$params2.interface = $Test2Vmk
|
||||||
|
$params2.size = $Test2Frame
|
||||||
|
$params2.count = 1
|
||||||
|
$counter = 0
|
||||||
|
$test1passcount = 0
|
||||||
|
$test2passcount = 0
|
||||||
|
try {
|
||||||
|
while (($counter -lt $Count) -or ($Count -eq 0)) {
|
||||||
|
$counter += 1
|
||||||
|
$result1 = ($esxcli.network.diag.ping.Invoke($params1)).summary
|
||||||
|
$result2 = ($esxcli.network.diag.ping.Invoke($params2)).summary
|
||||||
|
$part1 = $Test1Vmk + "->" + $result1.HostAddr + "(" + $Test1Frame + ") "
|
||||||
|
if ($result1.Received -eq 1) {
|
||||||
|
$test1 = "Good"
|
||||||
|
++$test1passcount
|
||||||
|
} else {
|
||||||
|
$test1 = "Bad"
|
||||||
|
}
|
||||||
|
$part2 = $Test2Vmk + "->" + $result2.HostAddr + "(" + $Test2Frame + ") "
|
||||||
|
if ($result2.Received -eq 1) {
|
||||||
|
$test2 = "Good"
|
||||||
|
++$test2passcount
|
||||||
|
} else {
|
||||||
|
$test2 = "Bad"
|
||||||
|
}
|
||||||
|
Write-Host "$(([string]$counter).PadLeft(4,' ')): $($VMHost): $part1" -NoNewLine
|
||||||
|
If ($test1 -eq "Good") {
|
||||||
|
Write-Host "$test1" -NoNewLine -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "$test1" -NoNewLine -ForegroundColor Red
|
||||||
|
}
|
||||||
|
Write-Host " $part2" -NoNewLine
|
||||||
|
If ($test2 -eq "Good") {
|
||||||
|
Write-Host "$test2" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "$test2" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
Start-Sleep -seconds 1
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if ($counter -ne $Count) {
|
||||||
|
Write-Host "`n--- Script processing cancelled." -ForegroundColor Red
|
||||||
|
}
|
||||||
|
Write-Host "`n------------------------------------------------"
|
||||||
|
Write-Host "Results:"
|
||||||
|
Write-Host "From: " -NoNewLine
|
||||||
|
Write-Host $VMHost -ForegroundColor Yellow
|
||||||
|
Write-Host "Count: " -NoNewLine
|
||||||
|
Write-Host $counter -ForegroundColor Yellow
|
||||||
|
Write-Host "`nTest 1:"
|
||||||
|
Write-Host "VMKernel port: " -NoNewLine
|
||||||
|
Write-Host $Test1Vmk -ForegroundColor Yellow
|
||||||
|
Write-Host "Destination: " -NoNewLine
|
||||||
|
Write-Host $Test1Host -ForegroundColor Yellow
|
||||||
|
Write-Host "Frame Size: " -NoNewLine
|
||||||
|
Write-Host $Test1Frame -ForegroundColor Yellow
|
||||||
|
Write-Host "Success: " -NoNewLine
|
||||||
|
Write-Host $test1passcount -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - Failure: " -NoNewLine
|
||||||
|
Write-Host ($counter - $test1passcount) -ForegroundColor Red
|
||||||
|
Write-Host "`nTest 2:"
|
||||||
|
Write-Host "VMKernel port: " -NoNewLine
|
||||||
|
Write-Host $Test2Vmk -ForegroundColor Yellow
|
||||||
|
Write-Host "Destination: " -NoNewLine
|
||||||
|
Write-Host $Test2Host -ForegroundColor Yellow
|
||||||
|
Write-Host "Frame Size: " -NoNewLine
|
||||||
|
Write-Host $Test2Frame -ForegroundColor Yellow
|
||||||
|
Write-Host "Success: " -NoNewLine
|
||||||
|
Write-Host $test2passcount -ForegroundColor Green -NoNewLine
|
||||||
|
Write-Host " - Failure: " -NoNewLine
|
||||||
|
Write-Host ($counter - $test2passcount) -ForegroundColor Red
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$cluster = "",
|
||||||
|
[string]$VmHost = "",
|
||||||
|
[string]$vmkPort = "",
|
||||||
|
[int]$testFrame = 1472,
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$fileVersion = "1.2.6"
|
||||||
|
$fileDate = "2025-09-15"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "Host Network Testing Script" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Perform multiple ping tests simultaneously from an ESXi host."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " NetworkTester.ps1 (-vcenter [vcenter host name]) (-cluster ""[cluster]"") (-VmHost ""[host]"") (-vmkPort ""[vmkPort]"")" -foregroundcolor green
|
||||||
|
Write-Host " (-testFrame [framesize]) (-savecred) (-help)`n" -foregroundcolor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -cluster " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the cluster as shown in vCenter."
|
||||||
|
Write-Host -NoNewLine " -VmHost " -foregroundcolor Green
|
||||||
|
Write-Host "- [Optional] The name of a host to test. If not specified, all hosts in the cluster will be tested."
|
||||||
|
Write-Host -NoNewLine " -vmkPort " -foregroundcolor Green
|
||||||
|
Write-Host "- The VMkernel port on the host to test."
|
||||||
|
Write-Host -NoNewLine " -testFrame " -foregroundcolor Green
|
||||||
|
Write-Host "- The TCP frame size to use for the test. Default: 1500."
|
||||||
|
Write-Host -NoNewLine " -savecred " -foregroundcolor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -foregroundcolor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If any of the information is not provided, you will be prompted. If a credential has been previously stored, it will"
|
||||||
|
Write-Host "be used again unless the -savecred option is specified."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Each host in the selected cluster will perform ping tests to all IP addresses assigned to the selected vmKernel port"
|
||||||
|
Write-Host "on all hosts in the cluster."
|
||||||
|
Write-Host
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kispingtest-$vcenter.cred
|
||||||
|
Write-Host "Saving credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kispingtest-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kispingtest-$vcenter.cred
|
||||||
|
Write-Host "Using stored credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cluster -eq "") {
|
||||||
|
$Clusterlist = Get-Cluster | Sort-Object
|
||||||
|
While (($cluster -eq "") -or (-not $cluster)) {
|
||||||
|
Write-Host "`nCluster Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $Clusterlist.length; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($Clusterlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$Clusternum = Read-Host "`nSelect Cluster Number"
|
||||||
|
$Clusternum = [int]$Clusternum - 1
|
||||||
|
$cluster = $Clusterlist[$Clusternum]
|
||||||
|
}
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
} else {
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
$firsthost = $mycluster | Get-VMHost | Select-Object -first 1
|
||||||
|
|
||||||
|
$vmks = $firsthost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "vmk*"} | Sort-Object Name
|
||||||
|
While (($vmkPort -eq "") -or (-not $vmkPort)) {
|
||||||
|
Write-Host "`nVMKernel Port Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $vmks.length; $x++) {
|
||||||
|
$myvmk = $vmks[$x];
|
||||||
|
$mask = [ipaddress]$myvmk.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($myvmk.Name) - $($myvmk.PortGroupName) ($($myvmk.IP)/$($mask_length))" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$vmknum = Read-Host "`nSelect VMKernel Port Number for Testing"
|
||||||
|
$vmkPort = $vmks[$vmknum - 1].Name
|
||||||
|
$myvmk = $vmks[$vmknum - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((-not(Test-Path variable:myvmk) -or ($myvmk -ne $null))) {
|
||||||
|
$myvmk = $firsthost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "$vmkPort"}
|
||||||
|
$mask = [ipaddress]$myvmk.SubnetMask
|
||||||
|
$binary = [convert]::ToString($mask.Address, 2)
|
||||||
|
$mask_length = ($binary -replace 0,$null).Length
|
||||||
|
Write-Host "Using $($myvmk.Name) ($($myvmk.PortGroupName)) for Testing"
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetlist = get-cluster $mycluster | get-vmhost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "$myvmk"} | Select-Object -Property IP | Sort-Object IP
|
||||||
|
|
||||||
|
if ($VmHost -ne "") {
|
||||||
|
try {
|
||||||
|
$hostlist = Get-VMhost $VmHost -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Write-Host "ERROR - Host $VmHost not found." -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit*
|
||||||
|
}
|
||||||
|
if ($hostlist[0].parent.name -ne $cluster) {
|
||||||
|
Write-Host "ERROR - Host $VmHost not part of cluster $cluster" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$hostlist = $mycluster | Get-VMHost | Sort-Object Name
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($x = 0; $x -lt $hostlist.length; $x++) {
|
||||||
|
$myhost = $hostlist[$x]
|
||||||
|
$myip = $myhost | Get-VMHostNetworkAdapter | Where-Object {$_.Name -like "$myvmk"} | Select-Object -Property IP
|
||||||
|
$hostname = $myhost.name
|
||||||
|
$tcpstack = $myvmk.ExtensionData.Spec.NetStackInstanceKey
|
||||||
|
Write-Host "Testing Host $hostname on $($myvmk.PortGroupName) with a frame size of $testFrame ($myip)"
|
||||||
|
$esxcli = get-esxcli -vmhost (get-vmhost $myhost) -v2
|
||||||
|
for ($y = 0; $y -lt $targetlist.length; $y++) {
|
||||||
|
$params = (get-esxcli -v2 -vmhost (get-vmhost $myhost)).network.diag.ping.CreateArgs()
|
||||||
|
$params.host = $targetlist[$y].IP
|
||||||
|
$params.interface = $vmkPort
|
||||||
|
$params.size = $testFrame
|
||||||
|
$params.df = $true
|
||||||
|
$params.count = 1
|
||||||
|
if ($tcpstack -ne "defaultTcpipStack") {
|
||||||
|
$params.netstack = $tcpstack
|
||||||
|
}
|
||||||
|
$result = ($esxcli.network.diag.ping.Invoke($params)).summary
|
||||||
|
$response = $vmkPort + "->" + $result.HostAddr + "(" + $testFrame + ") "
|
||||||
|
if ($result.Received -gt 0) {
|
||||||
|
$test = "Good"
|
||||||
|
} else {
|
||||||
|
$test = "Bad"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host " - $($hostname): $response" -NoNewLine
|
||||||
|
If ($test -eq "Good") {
|
||||||
|
Write-Host "$test" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "$test" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Disconnect-VIServer $vCenter -confirm:$false
|
||||||
|
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
#requires -Modules posh-ssh
|
||||||
|
|
||||||
|
param (
|
||||||
|
[string]$vCenter = "",
|
||||||
|
[string]$Cluster = "",
|
||||||
|
[string]$Command = "",
|
||||||
|
[switch]$SaveCred = $false,
|
||||||
|
[switch]$Help = $false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
$FileVersion = "1.0.1"
|
||||||
|
$FileDate = "2026-04-18"
|
||||||
|
|
||||||
|
# Display Script Banner
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
Write-Host "Run ESXi CLI Command" -ForegroundColor Green
|
||||||
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
||||||
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
||||||
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host "Purpose: Run a CLI command on all hosts in a cluster."
|
||||||
|
Write-Host "Command Syntax:"
|
||||||
|
Write-Host " RunESXiCommand.ps1 (-vCenter [vcenter host name]) (-Cluster ""[cluster]"") (-Command ""[command]"") (-savecred)" -foregroundcolor green
|
||||||
|
Write-Host " (-NovCenter) (-savecred) (-help)`n" -foregroundcolor green
|
||||||
|
Write-Host "Command Line Options:"
|
||||||
|
Write-Host
|
||||||
|
Write-Host -NoNewLine " -vCenter " -foregroundcolor Green
|
||||||
|
Write-Host "- The FQDN or IP address of a vCenter server."
|
||||||
|
Write-Host -NoNewLine " -Cluster " -foregroundcolor Green
|
||||||
|
Write-Host "- The name of the cluster as shown in vCenter."
|
||||||
|
Write-Host -NoNewLine " -Command " -foregroundcolor Green
|
||||||
|
Write-Host "- The full CLI command to run on each host."
|
||||||
|
Write-Host -NoNewLine " -Savecred " -foregroundcolor Green
|
||||||
|
Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under"
|
||||||
|
Write-Host " the current logged in user."
|
||||||
|
Write-Host -NoNewLine " -help " -foregroundcolor Green
|
||||||
|
Write-Host "- Display command help."
|
||||||
|
Write-Host
|
||||||
|
Write-Host "If any of the information is not provided, you will be prompted. If a credential has been previously stored, it will"
|
||||||
|
Write-Host "be used again unless the -savecred option is specified."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$quiet = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
|
||||||
|
|
||||||
|
if ($vCenter -eq "") {
|
||||||
|
$vCenter = Read-Host "Enter name of vCenter Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SaveCred) {
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Saving vCenter credentials."
|
||||||
|
$credential = Get-Credential -Message "Enter credentials for ESXi hosts in $vCenter"
|
||||||
|
$credential | Export-Clixml -path $env:USERPROFILE\kistools-$vcenter-esxi.cred
|
||||||
|
Write-Host "Saving ESXi credentials."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kistools-$vcenter.cred -PathType Leaf) {
|
||||||
|
$credentials = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter.cred
|
||||||
|
Write-Host "Using stored vCenter credentials"
|
||||||
|
} else {
|
||||||
|
$credentials = Get-Credential -Message "Enter credentials for vCenter server $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -path $env:USERPROFILE\kistools-$vcenter-esxi.cred -PathType Leaf) {
|
||||||
|
$credentials_ssh = Import-Clixml -path $env:USERPROFILE\kistools-$vcenter-esxi.cred
|
||||||
|
Write-Host "Using stored ESXi credentials"
|
||||||
|
} else {
|
||||||
|
$credentials_ssh = Get-Credential -Message "Enter credentials for ESXi hosts in $vCenter"
|
||||||
|
if (!$credentials) {
|
||||||
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Write-Host -NoNewLine "Connecting to vCenter $vcenter..."
|
||||||
|
$vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue
|
||||||
|
$test = get-cluster
|
||||||
|
Write-Host " Success" -ForegroundColor green
|
||||||
|
} catch {
|
||||||
|
Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red
|
||||||
|
Write-Host "Error: $($_.Exception.Message)"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($cluster -eq "") {
|
||||||
|
$Clusterlist = Get-Cluster | Sort-Object
|
||||||
|
While (($cluster -eq "") -or (-not $cluster)) {
|
||||||
|
Write-Host "`nCluster Selection:`n"
|
||||||
|
for ($x = 0; $x -lt $Clusterlist.length; $x++) {
|
||||||
|
Write-Host "$(([string]($x+1)).PadLeft(3,' '))" -NoNewLine -ForegroundColor Green
|
||||||
|
Write-Host ": " -NoNewLine -ForegroundColor Gray
|
||||||
|
Write-Host "$($Clusterlist[$x].name)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
$Clusternum = Read-Host "`nSelect Cluster Number"
|
||||||
|
$Clusternum = [int]$Clusternum - 1
|
||||||
|
$cluster = $Clusterlist[$Clusternum]
|
||||||
|
}
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
} else {
|
||||||
|
$mycluster = get-cluster $cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Command -eq "") {
|
||||||
|
$Command = Read-Host "Enter CLI Command to run on each host"
|
||||||
|
}
|
||||||
|
|
||||||
|
$myhosts = $mycluster | Get-VMHost | Sort-Object -Property Name
|
||||||
|
|
||||||
|
foreach($myhost in $myhosts) {
|
||||||
|
$myssh = $myhost | Get-VMHostService | Where-Object {$_.Key -eq "TSM-SSH"}
|
||||||
|
if (!$myssh.Running) {
|
||||||
|
Write-Host "-- Starting SSH Service on Host $($myhost.Name)"
|
||||||
|
$quiet = $myssh | Start-VMHostService -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
$sshsession = New-SSHSession -ComputerName $myhost.Name -Credential $credentials_ssh -AcceptKey -KeepAliveInterval 5
|
||||||
|
Write-Host "-- Running command " -NoNewLine
|
||||||
|
Write-Host "$Command" -NoNewLine -ForegroundColor yellow
|
||||||
|
Write-Host " on host " -NoNewLine
|
||||||
|
Write-Host "$myhost" -ForegroundColor yellow
|
||||||
|
$result = Invoke-SSHCommand -SessionID $sshsession.SessionId -Command $Command -Timeout 30
|
||||||
|
Write-Host "Command Output:"
|
||||||
|
$result.Output
|
||||||
|
Write-Host "Exit Status: $($result.ExitStatus)"
|
||||||
|
$quiet = Remove-SSHSession -SessionID $sshsession.SessionId
|
||||||
|
|
||||||
|
if (!$myssh.Running) {
|
||||||
|
Write-Host "-- Stoppnig SSH Service on Host $($myhost.Name)"
|
||||||
|
$quiet = $myssh | Stop-VMHostService -Confirm:$false
|
||||||
|
}
|
||||||
|
Write-Host "----------------------------"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user