ES1_WorkerRolesUtils.psm1
<# .NOTES =========================================================================== Copyright � 2018 Dell Inc. or its subsidiaries. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 =========================================================================== THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE AND INFORMATION REMAINS WITH THE USER. .DESCRIPTION Functions for inspecting or getting "Worker" machine related stuff #> #requires -Version 4 $global:RoleDisplayNames = @{} # # Hard coded worker role display names in case not on machine with modules to get strings from... # The key is the taskTypeID $displayNames = @{ -1846448278 = "File Delete - Historical"; -1788567307 = "File Archive - Historical"; -1275657296 = "File Index in Place - Historical"; -623249162 = "File Shortcut - Historical"; -1373822617 = "File Removal"; 45 = "SharePoint Restore"; 44 = "File Restore"; 1818414846 = "File Restore - Historical"; 42 = "Restore Shortcuts - Microsoft Exchange Public Folders"; 40 = "Delete - Microsoft Exchange Public Folders"; 38 = "Shortcut - Microsoft Exchange Public Folders"; 36 = "Archive - Microsoft Exchange Public Folders"; 34 = "Delete - User Initiated Delete"; 32 = "Restore Shortcuts - Historical & User Directed Archive"; 31 = "Query Discovery Manager"; 28 = "Find - Microsoft Office Outlook .PST"; 26 = "Delete - User Directed Archive"; 24 = "Shortcut - User Directed Archive"; 22 = "Archive - User Directed Archive"; 21 = "Delete"; 19 = "Migrate - Microsoft Office Outlook .PST"; 18 = "Update Shortcuts - Historical & User Directed Archive"; 17 = "Export"; 16 = "Journal"; 15 = "Archive - Personal Mail Files"; 1888230777 = "File Shortcut Restore - Historical"; 8 = "Query"; 6 = "Export Discovery Manager"; 5 = "Delete - Historical"; 4 = "Shortcut - Historical"; 3 = "Archive - Historical"} # used for dynamic rebuild of table above. These strings from rooted from ExJDFEnums.Translate() $NoKnownConfigurators = @{ 45 = "SharePoint Restore"; 44 = "File Restore"; 31 = "Query Discovery Manager"; 21 = "Delete"; 17 = "Export"; 8 = "Query"; 6 = "Export Discovery Manager"; } function Set-WorkerRoleDisplayNames { <# .SYNOPSIS Loads a global hash map with the tasktypeid and UI displayable worker role name associated with it. A static copy of the map is used if this is not run on a machine with the S1 console installed. This function is used internally by other functions/commands and is generally not executed from the command line. .DESCRIPTION Loads a global hash map with the tasktypeid and UI displayable worker role name associated with it. A static copy of the map is used if this is not run on a machine with the S1 console installed. This function is used internally by other functions/commands and is generally not executed from the command line. .PARAMETER outfile Option parameter to specify an output file that will capture the hash map of task type ID and the display name that was discovered. .EXAMPLE Set-WorkerRoleDisplayNames .EXAMPLE Set-WorkerRoleDisplayNames -debug .EXAMPLE Set-WorkerRoleDisplayNames -out file.csv #> [CmdletBinding()] param ( [Parameter(Mandatory=$false)] [Alias('out')] [string]$outfile = "" ) begin { $MyDebug = $false # Do both these checks to take advantage of internal parsing of syntaxes like -Debug:$false if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("Debug") -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent) { $DebugPreference = "Continue" Write-Debug "Debug Output activated" # for convenience $MyDebug = $true } try { [bool] $loaded = Add-ES1Types #-ErrorAction SilentlyContinue if (-not $loaded ) { Write-Error 'Error loading SourceOne Objects and Types' break } } catch { Write-Error $_ break } } process { if ($MyDebug) { Write-Debug "Emptying RoleDisplayNames map ..." $global:RoleDisplayNames.Clear() } # # Some logic lifted from GetServerAssignments in "ExServerConfigCtrl.cs" # $jdfapiMgr = new-object -comobject ExJDFAPI.CoExJDFAPIMgr.1 $TaskTypeFilter = $jdfapiMgr.CreateNewObject([EMC.Interop.ExJDFAPI.exJDFObjectType]::exJDFObjectType_TaskTypeFilter) $tasktypes = $jdfapiMgr.GetTaskTypes($TaskTypeFilter) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($TaskTypeFilter) > $null # gets the Mail systems supported... :-) #$generalSettings=$jdfapiMgr.GetSystemGeneralSettings() #$generalSettings # $tasktypes | ft -AutoSize | Out-String -Width 100000 > foo $installPath = Get-ES1InstallDir # # These modules will only be on machine with the worker services installed. # $pathroot = $installPath +'Console\bin\' $ExUIDLL = $pathroot + "ExUIUtils.dll" if (Test-Path -path $pathroot) { # We load this because the "Files" components have a dependency on it and the creation # of their configruation object will fail if this isn't already loaded $ExUI = [reflection.assembly]::LoadFrom($ExUIDLL) # # if on a machine with Console, load all the strings from the installed task types.. # foreach ($tasktype in $TaskTypes) { if ((($taskType.state -band [int][EMC.Interop.ExBase.exPluginState]::exPluginState_Active) -and ` #Only Active types ( ( $taskType.state -band [int][EMC.Interop.ExBase.exPluginState]::exPluginState_NotAdminDisplayable) -eq $false)) -or ` # hide internal types ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_Query -eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_RestoreJBC -eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_DeleteFromArchiveJBC -eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_DCQuery -eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_Restoration -eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_FileRestoreJBC-eq $taskType.id ) -or ` ( [int][EMC.Interop.ExBase.exCoreTaskTypes]::exCoreTaskTypes_SharePointRestoreJBC -eq $taskType.id ) ) { if ($tasktype.configuratorModuleWin32.Length -gt 0) { #Write-Host $tasktype.id $tasktype.name $tasktype.objectID $tasktype.configuratorModuleWin32 $tasktype.configuratorObjectIDWin32 $path = $pathroot + $tasktype.configuratorModuleWin32 try { $Name = "" $Description = "" #assembly name comes from the taskType object returned by GetTask $assemblyUI = [reflection.assembly]::LoadFrom($path) Write-Debug "$($tasktype.name), cfg Module: $($tasktype.configuratorModuleWin32) cfg ObjectID: $($tasktype.configuratorObjectIDWin32)" $UIMgr = $assemblyUI.CreateInstance($tasktype.configuratorObjectIDWin32) $UIMgr.GetTypeDisplayName($tasktype.id,[ref]$Name,[ref]$Description) } catch { Write-Warning "Failed to load configurator and create object $($tasktype.id) $($tasktype.name)" Write-Error $_ } if ($Name.Length -eq 0) { Write-Host "No display name for: $($tasktype.id) $($tasktype.name) " $global:RoleDisplayNames.Add($tasktype.id,$tasktype.name) } else { #Write-Host "Got display name for: $($tasktype.id) $($tasktype.name) Display Name: $($Name) " # Write-Host "Got display name for: $($tasktype.id), Display Name: $($Name) " $global:RoleDisplayNames.Add($tasktype.id,$Name) } # Think I need to free the object but cant find the right way. #[System.Runtime.Interopservices.Marshal]::Release($UIMgr) > $null } else { # no configurator so see if there is a known string to use... if ($NoKnownConfigurators.ContainsKey($tasktype.id)) { $NameStr = $NoKnownConfigurators.Get_Item($tasktype.id) $global:RoleDisplayNames.Add($tasktype.id,$NameStr) Write-Debug "Known string for: $($tasktype.id) $($NameStr)" } else { Write-Debug "No configurator: $($tasktype.id) $($tasktype.name), using type name " $global:RoleDisplayNames.Add($tasktype.id,$tasktype.name) } } } } #end foreach # preserve the display names to CSV # the CSV can be messaged and used to update the static table... if ($outfile.Length -gt 0) { $global:RoleDisplayNames.GetEnumerator() | select Name, Value | Export-Csv -notype -path $outfile } } else { # Console\bin dir doesn't exist... $global:RoleDisplayNames = $displayNames } } end {} } function Get-ES1EnabledWorkerRoles { <# .SYNOPSIS Given a list of taskcfg objects (IExWorkerTaskConfig) obtained from a worker (IExWorker) object, return a list of the active types/roles and their UI displayable names .DESCRIPTION Given a list of taskcfg objects (IExWorkerTaskConfig) obtained from a worker (IExWorker) object, return a list of the active types/roles and their UI displayable names .EXAMPLE The following snippet displays the active role types and display names string on each worker $jdfapiMgr=new-object -comobject ExJDFAPI.CoExJDFAPIMgr.1 $Workers=@($jdfapiMgr.GetWorkers()) foreach ($worker in $Workers) { $allcfgs = @($worker.taskCfgs) $Activecfgs = @(Get-ES1EnabledWorkerRoles $allcfgs) $Activecfgs } #> [CmdletBinding()] param ([Parameter(Mandatory=$true)] [Alias('cfgs')] $list = @()) # # logic lifted from GetServerAssignments in "ExServerConfigCtrl.cs" # $retList = @() Write-Verbose "SeverRoles for display: $($global:RoleDisplayNames.Count)" foreach ($cfg in $list) { if ($cfg.state -eq [int][EMC.Interop.ExJDFAPI.exJDFWorkerTaskCfgState]::exJDFWorkerTaskCfgState_Enabled) { # $global:RoleDisplayNames contains only UI displayable taskids, if its not there is doesn't get # returned if ($global:RoleDisplayNames.ContainsKey($cfg.taskTypeId)) { $cfg.taskTypeName=$global:RoleDisplayNames.Get_Item($cfg.taskTypeId) $retList += $cfg } } } $retList } function Get-ES1WorkerInfo { <# .SYNOPSIS Gets and array of SourceOne worker objects and their roles. .DESCRIPTION Gets and array of SourceOne worker objects and their roles. .EXAMPLE #> [CmdletBinding()] param () BEGIN{ try { [bool] $loaded = Add-ES1Types #-ErrorAction SilentlyContinue if (-not $loaded ) { Write-Error 'Error loading SourceOne Objects and Types' break } # Load up the display names.... if ($global:RoleDisplayNames.Count -le 0) { Set-WorkerRoleDisplayNames } } catch { Write-Error $_ break } } PROCESS{ $retList = @() Write-Verbose "SeverRoles for display: $($global:RoleDisplayNames.Count)" $Workers = @() $jdfapiMgr = new-object -comobject ExJDFAPI.CoExJDFAPIMgr.1 $workergroups = @($jdfapiMgr.GetWorkerGroups()) $Workers = @($jdfapiMgr.GetWorkers()) # Add some new columns $Workers | Add-Member NoteProperty -Name "WorkerGroup" -Value "" $Workers | Add-Member NoteProperty -Name "EnabledRoles" -Value "" # Add the Worker Group if there is one... foreach ($worker in $Workers) { if ($workergroups.Length -gt 0) { foreach ($group in $workergroups) { if ($group.id -eq $worker.workerGroupID) { $worker.WorkerGroup = $group.name break; } } } $cfgs = @() $tasks = @() $cfgs = @($worker.taskCfgs) $allCfgs = @($worker.taskCfgs) $cfgs = @(Get-ES1EnabledWorkerRoles $cfgs) $cfgIndex = 0 $cfgs = @(Get-ES1EnabledWorkerRoles $cfgs) $cfgIndex = 0 $roles = $cfgs | Select tasktypename #$roles | foreach { $_.taskTypeName = $_.taskTypeName -join ', ' } $worker.EnabledRoles = $roles $worker | foreach {$_.EnabledRoles = $_.EnabledRoles.taskTypeName -join ', '} } [System.Runtime.Interopservices.Marshal]::ReleaseComObject($jdfapiMgr) > $null # return only relavent stuff and pretty some numeric enums # TODO - maybe I shouldnt be changing the enums here ?? $Workers | Select Name, WorkerGroup, startTime, lastActive,jobQuota, jobPollTime, @{name="State"; Expression = { ([EMC.Interop.ExJDFAPI.exJDFWorkerState]$_.state).ToString().Substring(17) }}, @{name = "Action"; Expression = { ([EMC.Interop.ExJDFAPI.exJDFWorkerAction]$_.action).ToString().Substring(18) }}, EnabledRoles } END{} } function Show-ES1WorkerRoles { <# .SYNOPSIS Display information about each worker server and it's enabled roles .DESCRIPTION Display information about each worker server and it's enabled roles .EXAMPLE Show-ES1WorkerRoles ****** Worker : S1MASTER7-J1.QAGSXPDC.COM ****** Group State Action StartTime LastActive JobQuota JobPollTime DaysAvailable ----- ----- ------ --------- ---------- -------- ----------- ------------- Working None 7/17/2014 7:27:06 PM 11/11/2015 9:57:56 PM 0 10 -1 Enabled Roles JobLimit ------------- -------- Archive - Historical 4 Archive - Personal Mail Files 2 Delete 4 Delete - Historical 4 Delete - Microsoft Exchange Public Folders 4 Delete - User Directed Archive 4 Delete - User Initiated Delete 4 .EXAMPLE Show-ES1WorkerRoles > WorkerRoles.txt Captures the worker role information to a text file named WorkerRoles.txt #> [CmdletBinding()] param () begin { try { [bool] $loaded = Add-ES1Types #-ErrorAction SilentlyContinue if (-not $loaded ) { Write-Error 'Error loading SourceOne Objects and Types' break } # Load up the display names.... if ($global:RoleDisplayNames.Count -le 0) { Set-WorkerRoleDisplayNames } } catch { Write-Error $_ break } } process{ $Workers = @() $jdfapiMgr = new-object -comobject ExJDFAPI.CoExJDFAPIMgr.1 $workergroups = @($jdfapiMgr.GetWorkerGroups()) $Workers = @($jdfapiMgr.GetWorkers()) # Add some new columns $Workers | Add-Member NoteProperty -Name "WorkerGroup" -Value "" $Rolefmt = @{ Expression = { $_.taskTypeName }; label = "Enabled Roles" }, @{ Expression = { $_.quota }; label = "JobLimit" } #@{ Expression = { $_.name }; label = "Worker" }, $Workerfmt = @{ Expression = { $_.WorkerGroup }; label = "Group"}, @{ Expression = { ([EMC.Interop.ExJDFAPI.exJDFWorkerState]$_.state).ToString().Substring(17) }; label = "State"; width=12 }, @{ Expression = { ([EMC.Interop.ExJDFAPI.exJDFWorkerAction]$_.action).ToString().Substring(18) }; label = "Action" }, @{ Expression = { $_.startTime }; label = "StartTime" }, @{ Expression = { $_.lastActive }; label = "LastActive" }, @{ Expression = { $_.jobQuota }; label = "JobQuota" }, @{ Expression = { $_.jobPollTime }; label = "JobPollTime" }, @{ Expression = { $_.daysAvailable }; label = "DaysAvailable" } # Add the Worker Group if there is one... foreach ($worker in $Workers) { if ($workergroups.Length -gt 0) { foreach ($group in $workergroups) { if ($group.id -eq $worker.workerGroupID) { $worker.WorkerGroup = $group.name break; } } } # Display the Worker information Write-Output "****** Worker : $($worker.name) ******" $worker | ft -AutoSize $Workerfmt | Out-String -Width 1000 $cfgs = @() $tasks = @() $cfgs = @($worker.taskCfgs) $allCfgs = @($worker.taskCfgs) $cfgs = @(Get-ES1EnabledWorkerRoles $cfgs) $cfgIndex = 0 # # Adjust the joblimit/quota to display like the GUI does. # some logic lifter from "PopulateGrid" in ExWorkerTaskCfgPage.cs foreach ($cfg in $cfgs) { # First thing to do is determine whether this is a job-level task (JBC). If # it's not, we'll use it to get to associated jobs that are... $childFilter = $jdfapiMgr.CreateNewObject([EMC.Interop.ExJDFAPI.exJDFObjectType]::exJDFObjectType_TaskTypeFilter) $childFilter.parentTaskTypeID = $cfg.id $childTaskTypes = @($jdfapiMgr.GetTaskTypes($childFilter)) [System.Runtime.Interopservices.Marshal]::ReleaseComObject($childFilter) > $null $useThis = $cfg # Use the first child type if we got one... if ($childTaskTypes.Length -gt 0) { $useThis = $childTaskTypes[0] } # Look for the current type in the workers full collection foreach ($parent in $allCfgs) { # # Note, there is some hairy logic in Populate grid, but I think this # gets the job done... # if ($parent.taskTypeID -eq $useThis.id) { $cfgs[$cfgIndex].quota = $parent.quota Write-Debug "Config ID $($cfg.id) Quota: $($cfg.quota) New: $($parent.quota)" } } $cfgIndex++ } # And display the Roles.... $cfgs | sort taskTypeName | ft -AutoSize $Rolefmt } [System.Runtime.Interopservices.Marshal]::ReleaseComObject($jdfapiMgr) > $null } end {} } <# .SYNOPSIS Get-ES1WorkerNameFromID .DESCRIPTION Given a workerID display the name of the worker server Used by S1Jobs etc when retrieving Job information .PARAMETER sID Provide the workerid .EXAMPLE Get-ES1WorkerNameFromID 2 Worker01 #> function Get-ES1WorkerNameFromID { param ($wId) Get-ES1Workers | out-null foreach ($w in $Script:s1Workers) { if ($w.workerid -eq $wID) { $name = $w.servername.Split(".")[0] } } $name } # Exported, "global" module scope. Once set we wont get it again unless forced $s1Workers = @() <# .SYNOPSIS Get-ES1Workers .DESCRIPTION Retrieve the names of all SourceOne workers from SQL .OUTPUTS Sets Session array $s1Workers .EXAMPLE Get-ES1Workers Master.domain.com Worker.domain.com #> function Get-ES1Workers { [CmdletBinding()] param() Get-ES1ActivityDB| out-null # # Define SQL Query # $sqlQuery = @' SELECT DISTINCT NetworkName AS servername, workerid FROM MachineInfo mi (NOLOCK) JOIN Workers w (NOLOCK) ON w.MachineID = mi.MachineID WHERE w.State <> 32767 '@ # $s1actSErver $S1Actdb are exported from another module and set by the Get-ES1ActivityObj call above $dtResults = Invoke-ES1SQLQuery $s1actSErver $S1Actdb $sqlQuery $Script:s1Workers = $dtResults $dtResults } New-Alias Get-S1WorkerNameFromID Get-ES1WorkerNameFromID New-Alias Get-S1Workers Get-ES1Workers Export-ModuleMember -Variable s1Workers Export-ModuleMember -Function * -Alias * |