One of the main trends that I have in my job is to automate as many of the task I perform on a daily basis as possible.
Automation does not always mean a particular task takes care of itself, sometimes its just the retrieval of the information that can then help in making a human decision.
New tasks come up all the time and searching for the information you need is always the first step. Often this means logging onto servers or remotely accessing servers through GUI tools while you search around of the information.
Once you know where the information is however you can then look at more efficient ways of retrieving it.
This script below will find the Cluster Resources Information given a File Share Name.
The main reason why I use this script is to find the File location where the share is located, which is commonly used for:
- Restoring Backups
- Changing Permissions
- Adding Directories
- Adding/Adjusting File Quotas
This is necessary since in a Windows Cluster the resources could be across a
- host of servers
- host of drives
- host of mount points
Here are a few ways to run this script
.\Get-ClusterResource.ps1 -Share Users-Home-01 -Cluster MyClusterServer
.\Get-ClusterResource.ps1 -Share Users-Home-01
.\Get-ClusterResource.ps1 Users-Home-01
Retrieving Cluster Info . . . MyClusterServerName Server Share Path
—- —— —– —-
home 1 CLUSSERVENODE-03 users-home-01 N:\Mount123\Folder\home1Path: \\CLUSSERVENODE-03\N$\Mount123\Folder\home1
The script has been created for my environment, I look up the Server name by making a call to the function Get-NodeActiveResource using the Drive Resource Name E.g. “Disk N:”. I do this because I know the Disk will always have that name and the Share Name does not always match the Resource Name used to create the Share E.g. Above the Name is “home 1”, however the Share is “users-home-01”. Secondly I know the Share will always be located on the same server as that Disk, so the look up always works.
Okay here is the script.
#Requires -Version 2.0 [CmdletBinding(DefaultParametersetName="HostList")] Param ( [Parameter(Mandatory=$false, Position=1, ParameterSetName="HostList", ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false)] [Array]$Cluster = "MyClusterServer", [Parameter(Mandatory=$true, Position=0, ParameterSetName="HostList", ValueFromPipeline=$true)] [String]$Share )#End Param Begin { Write-Host "`n Retrieving Cluster Info . . . " -nonewline }#Begin Process { switch ($PsCmdlet.ParameterSetName) { "HostFile" {$Servers = (Get-Content $HostFile)} "HostList" {$Servers = $Cluster} } $Servers | ForEach-Object { $ClusterServer = $_ $ClusterServer | Out-Host function Get-NodeActiveResource($Drive, $ComputerName) { # Find the Active Resources $PartComponent = 'MSCluster_Resource.Name="' + $Drive + '"' $Filter = "PartComponent = '$PartComponent'" $Info = get-wmiobject -Filter $Filter -namespace "root\MSCluster" ` -class "MSCluster_NodeToActiveResource" -ComputerName $ComputerName if ($Info -ne $Null) { $Info | ForEach-Object { $Server = ($_.GroupComponent).split("=")[1] $Resource = ($_.PartComponent).split("=")[1] $Hash = @{ Server=$Server.substring(1, ($Server.length-2)) Resource=$Resource.substring(1, ($Resource.length-2)) } $ResourceInfo = New-Object PSObject -Property $Hash $ResourceInfo } } }#Get-NodeActiveResource # Find the Resource Information $Filter2 = "PrivateProperties.ShareName = '$Share'" get-wmiobject -namespace "root\MSCluster" -class "MSCluster_Resource"` -ComputerName $ClusterServer -Filter $Filter2 | ForEach-Object { $Path = $_.PrivateProperties.Path $PathSplit = $Path.split(":") $Drive = "Disk " + $PathSplit[0] + ":" $Server = (Get-NodeActiveResource -Drive $Drive ` -Computername $ClusterServer).Server $Hash2 = @{ Name=$_.Name Share=$_.PrivateProperties.ShareName Path=$Path Server=$Server } $ShareInfo = New-Object PSObject -Property $Hash2 $ShareInfo | ft -autosize | Out-Host $ShareInfo }#ForEach-Object(WMI) }#ForEach-Object(Servers) }#Process End { If ($ShareInfo -ne $Null) { $Path = "\\" + $ShareInfo.Server + "\" + $PathSplit[0] ` + "$" + $PathSplit[1] if ($Path -ne $Null) {Write-Host "`n Path:" $Path} } else { Write-Host "`n No share """$Share """ on" $ClusterServer ` -BackgroundColor Red -ForegroundColor White } # Cleanup Variables, useful during testing to # make sure no false positives $Servers,$Server,$Resource,$Path,$Hash,$Hash2,$Filter = $Null $Filter2, $ResourceInfo,$ShareInfo,$PathSplit,$Info = $Null }#End
Summary Info
The inner function of this script Get-NodeActiveResource is also very useful as a standalone script for finding out which servers resources are hosted on and can be used like below:
.\Get-NodeActiveResource.ps1 "Disk N:" Retrieving Cluster Info . . . Server Resource ------ -------- CLUSSERVENODE-05 Disk N:
It is worth noting that I have used Windows Management Instrumentation (WMI) for retrieving this information. Server 2008 R2 Failover Clustering has built in cmdlets that are very useful and I will include a script for setting up the Failover Clustering on Server 2008 R2 from scratch in another post.
Leave a comment