Posted On August 21, 2019

PowerShell: Microsoft Failover Cluster Discovery Version 0.10

kimconnect 0 comments
blog.KimConnect.com >> Codes >> PowerShell: Microsoft Failover Cluster Discovery Version 0.10
<#  .Sypnosis: Microsoft_Clusters_Discovery_v.0.10.ps1
What it does:
- Installs Microsoft Failover Cluster PowerShell module on the local machine (Jump Box).
This can work behind a proxy if those variables are specified.
Be advised that RSAT-Clustering-PowerShell currently has known conflicts with VMWare.PowerCLI.
Thus, this must be ran on machines that does not already have VMWare.PowerCLI installed.
- Collects all FailOver Clusters in the current domain
- Lists all nodes of a selected cluster
- Checks whether Remote PowerShell is enabled on a selected node
- Connects to a user-selected node via WinRM and queries for clustering information: resource names and current owners

Requirements:
- Script must be ran using a Domain Admin account
- It can only query remote machines with WinRM being enabled
- Requires a manual trigger of PowerShell Execution Policy: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Confirm:$false -Force

Future development:
- Runs as a Domain Admin
- Uses PSExec to enable WinRM on remote machines prior to executing Remote Powershell invoke-command
- Describes the clustering types and trigger selected functions to match the type of resource (SQL, Hyper-V, FileServer, etc.)
#>

$proxy="http://proxy:8080"
$exclusionList="localhost;*.sdcs.local"

<# Future development: Domain Admin credential prompts
# Credential for PS-Remoting
$usernameInput=Read-Host -Prompt "Input the username";
$username="$($env:USERDNSDOMAIN)\$usernameInput";
$password = Read-Host -Prompt "Input the password for account $username" -AsSecureString
#$password=convertto-securestring "PASSWORD" -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$password
#>

################################## Excuting Program as an Administrator ####################################
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)

# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator

# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "Black"
clear-host
}
else
{
# We are not running "as Administrator" - so relaunch as administrator

# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";

# Specify the current script path and name as a parameter
$newProcess.Arguments = $myInvocation.MyCommand.Definition;

# Indicate that the process should be elevated
$newProcess.Verb = "runas";

# Start the new process
[System.Diagnostics.Process]::Start($newProcess);

# Exit from the current, unelevated, process
exit
}

Write-Host -NoNewLine "Running as Administrator..."
################################## Excuting Program as an Administrator ####################################

function checkProxy{
try{
$connectionTest=iwr download.microsoft.com -UseBasicParsing
#$connectionSucceeds=Test-NetConnection -Computername download.microsoft.com -Port 443 -InformationLevel Quiet
if ($connectionTest){
return $True;
}
}
catch{
return $False
}
}

function fixProxy{
# Check if proxy is enabled on the system and fix it
$proxyKey=(Get-ItemProperty -Path "Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings")
if ($proxyKey.ProxyEnable){
# Set http proxy for browsers
Set-Itemproperty -path "Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name 'ProxyServer' -value $proxy

# Set winhttp proxy for PowerShell
netsh winhttp set proxy $proxy $exclusionList

[system.net.webrequest]::defaultwebproxy = New-Object system.net.webproxy($proxy)
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}

if (checkProxy){
"Proxy is now good to go..."
}
else{
"Proxy problems..."
break;
}
}

# Set PowerShell Gallery as Trusted to bypass prompts
Function setPSGalleryTrust{
$trustPSGallery=(Get-psrepository -Name 'PSGallery').InstallationPolicy
If($trustPSGallery -ne 'Trusted'){
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
}
}

# Adding Prerequisite Active Directory Module
Function installADModule{
if (!(get-module -name "ActiveDirectory") ){
Add-WindowsFeature RSAT-AD-PowerShell | out-null;
import-module -name "ActiveDirectory" -DisableNameChecking | out-null;
}
$domain=get-addomain
}

# Adding Prerequisite Microsoft Cluster
Function installFailoverClustersModule{
if (!(get-module -Name "FailoverClusters") ){
#Install-WindowsFeature Failover-Clustering | out-null;
Install-WindowsFeature RSAT-Clustering-MGMT | out-null;
Install-WindowsFeature RSAT-Clustering-PowerShell | out-null;
Import-Module FailoverClusters | out-null;
}
}

Function installPrerequisites{
setPSGalleryTrust;
#installADModule;
installFailoverClustersModule;
}

function listClusters{
"`n`nListing all Clusters in $($env:USERDNSDOMAIN)...`n"
$GLOBAL:clusters=get-cluster -domain $env:USERDNSDOMAIN
}

function listNodes{
"`n`nAttempting to collect a list of all Nodes in this Cluster...`n"
try{
$global:nodes=(Get-ClusterNode -Cluster "$pickedItem.$env:USERDNSDOMAIN").Name
$global:pickedCluster=$pickedItem
}
catch{
$_.Exception.Message;
}
#$global:headLine="Available nodes in $pickedItem`:"
}

function showMenu{
Param($callFunction)
invoke-command (Get-Item "function:$callFunction").ScriptBlock

switch($callFunction){
"listClusters"{$count=$clusters.count; $global:list=$clusters;}
"listNodes" {$count=$nodes.count; $global:list=$nodes;}
}

$show="`n--------------------------------------------------------`nThere are $count items on this list:`n--------------------------------------------------------`n"
for ($row=0;$row -le $count-1;$row++){
$server=$list[$row]
$show += "$row" + ": " + "$server" + "`n"
}
return $show
}

function pickItem{
do {
try {
$flag = $true
[int]$pick=Read-Host -Prompt "`n---------------------------------------`nPlease pick an item from the above list`n---------------------------------------"
} # end try
catch {$flag = $false}
} # end do
until ($pick -lt $list.count -and $flag)

$global:pickIndex=$pick
$global:pickedItem=$list[$pick]
$clusters=""
$nodes=""
"$pick`: $pickedItem is picked"
}

# return true or false as determinant on whether program proceeds
function checkNodesForWinRM{
$nodes | foreach {
$winRM=Test-NetConnection -ComputerName "$_`.$($env:USERDNSDOMAIN)" -CommonTCPPort WINRM -InformationLevel Quiet
if ($winRM){"$_ is reachable via WinRM.";}
}
}

function queryFailoverClusters{

# Pick Cluster
do {
try{
$flag1=$true
showMenu -callFunction listClusters
pickItem
}
catch{$flag1=$false}
} until ($flag1)

# Pick Node
do {
try{
$flag2=$true
showMenu -callFunction listNodes
if (!($nodes)){queryFailoverClusters;}
checkNodesForWinRM;
pickItem
}
catch{$flag2=$false}
} until($flag2)
}

$failoverClusterModuleAvailable=get-cluster
if (!($failoverClusterModuleAvailable)){
if(!(checkProxy)){"Internet issues detected. Attempting a fix now..."; fixProxy;}
installPrerequisites;
}

function failoverClusterDiscovery{
queryFailoverClusters;

$pickedItemWinRM=Test-NetConnection -ComputerName "$pickedItem`.$($env:USERDNSDOMAIN)" -CommonTCPPort WINRM -InformationLevel Quiet
if($pickedItemWinRM){
"Obtaining Cluster Resource from node $pickedItem..."

# Triggering invoke-command as multi-threaded jobs so that the program will wait until these jobs are done before moving to the Pause command
$jobs = Invoke-Command -ComputerName $pickedItem -ScriptBlock {Get-ClusterResource | format-list Name,OwnerNode;} -AsJob
While ($Jobs.State -Contains "Running"){
$Jobs | Wait-Job -Any;
if ($jobs.State -contains "Completed") {
Receive-Job -Job $jobs;
Remove-Job -Job $jobs;
}
}

#Invoke-Command -ComputerName $pickedItem -ScriptBlock{Get-ClusterResource;}
}else{
"$pickedItem is not reachable via Remote PowerShell to query Cluster Resources.";
pause;
}
}

do {
failoverClusterDiscovery;
[string]$response=Read-Host -Prompt "`nPress any key to repeat process. Type 'exit' or use Ctrl+C to terminate program"
} until ($response -like "exit")

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Post

HAProxy Example for SSH & OpenVNP forwarding

# Source: https://limbenjamin.com/articles/running-https-ssh-vpn-on-port-443.html   global tune.ssl.default-dh-param 2048   defaults timeout connect 5000 timeout client 50000 timeout…

PowerShell: Windows Automated Disk Cleanup

##################################################################################     <#      This script is created to automate the cleanup activity. Doing so will benefit to reduce the size of disk.     This script will perform the following   1. Clear windows temp and user temp folder   2. Empty recycle bin   3. Disk Cleanup   4. Clear CBS cabinet log files   5. Clear downloaded patches   6. Clear downloaded driver   7. Clean download folder      Note:  …

PowerShell: Outdated Method of Sending Emails

# Credentials section $emailFrom = "[email protected]" $password = "eatYourSalad!" | ConvertTo-SecureString -AsPlainText -Force # plaintext…
Other project: DragonCoin.com