Enable interop with Azure Stack Hub (#219)

# Description
Summary of changes:
- Improvements around `-ManagementAddressOnly` to ensure only single
result per node is returned, with priority for FQDN
- Eliminated the following functions.
    - `Get-SdnGatewayConfigurationState`
    - `Get-SdnLoadBalancerMuxConfigurationState`
    - `Get-SdnNetworkControllerConfigurationState`
    - `Get-SdnServerConfigurationState`
- Added a new centralized `Get-SdnConfigState` with the appropriate
role(s).
- Added support for a `Common` role that can be used for data collection
and tracing.
- Added additional parameters to multiple functions to allow overriding
of default values
- Added support for module to be called from non-default powershell
directory
- Updated to use `$ENV` variables rather than hardcoded file paths for
system paths
- Improvements to `Install-SdnDiagnostics` to ensure module is always
installed in `.\SdnDiagnostics\{version}` format to ensure consistency
with PSGet

# Change type
- [x] Bug fix (non-breaking change)
- [ ] Code style update (formatting, local variables)
- [x] New Feature (non-breaking change that adds new functionality
without impacting existing)
- [x] Breaking change (fix or feature that may cause functionality
impact)
- [ ] Other

# Checklist:
- [x] My code follows the style and contribution guidelines of this
project.
- [ ] I have tested and validated my code changes.
This commit is contained in:
Adam Rudell 2024-01-03 05:24:45 -06:00 коммит произвёл GitHub
Родитель e6c098e038
Коммит 5712fe9fb6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
46 изменённых файлов: 311 добавлений и 205 удалений

Просмотреть файл

@ -47,11 +47,11 @@ foreach ($folder in $folders) {
}
}
Copy-Item -Path "$PSScriptRoot\..\src\SdnDiagnostics.*" -Destination "$outDir\SdnDiagnostics\" -Force
Copy-Item -Path "$PSScriptRoot\..\src\SdnDiagnostics.*" -Destination "$outDir\SdnDiagnostics\" -Force
# copy the root files under src that are prefixed with SdnDiagnostics
Copy-Item -Path "$PSScriptRoot\..\src\*" -Include "SdnDiagnostics.*" -Destination "$outDir\SdnDiagnostics\" -Force
# setting the version of the module manifest
$modManifest = Get-ChildItem "$outDir\SdnDiagnostics" -Filter "*.psd1"
$modManifest = Get-Item "$outDir\SdnDiagnostics\SdnDiagnostics.psd1" -ErrorAction Stop
if (($null -ne (Get-Item -Path "$($modManifest.DirectoryName)\$($modManifest.BaseName).psm1" -ErrorAction SilentlyContinue))) {
try {
$manifest = Test-ModuleManifest -Path $modManifest.FullName

Просмотреть файл

@ -59,10 +59,7 @@ $scriptBlocks = @{
}
$fabricNodeParamCommands = (
'Invoke-Command',
'Invoke-SdnCommand',
'New-PSSession',
'Enter-PSSession',
'Start-SdnDataCollection',
'Start-SdnNetshTrace',
'Stop-SdnNetshTrace'

Просмотреть файл

@ -59,11 +59,11 @@
'Get-SdnAuditLog',
'Get-SdnApiEndpoint'
'Get-SdnCertificate',
'Get-SdnConfigState',
'Get-SdnDiagnosticLogFile',
'Get-SdnEventLog',
'Get-SdnFabricInfrastructureResult',
'Get-SdnGateway',
'Get-SdnGatewayConfigurationState',
'Get-SdnInfrastructureInfo',
'Get-SdnModuleConfiguration',
'Get-SdnMuxCertificate',
@ -80,8 +80,6 @@
'Get-SdnNetworkInterfaceOutboundPublicIPAddress',
'Get-SdnNetworkController',
'Get-SdnNetworkControllerClusterInfo',
'Get-SdnNetworkControllerConfigurationState',
'Get-SdnNetworkControllerClusterInfo',
'Get-SdnNetworkControllerNode',
'Get-SdnNetworkControllerNodeCertificate'
'Get-SdnNetworkControllerRestCertificate',
@ -97,7 +95,6 @@
'Get-SdnResource',
'Get-SdnServer',
'Get-SdnServerCertificate',
'Get-SdnServerConfigurationState',
'Get-SdnServiceFabricApplicationHealth',
'Get-SdnServiceFabricClusterConfig',
'Get-SdnServiceFabricClusterHealth',
@ -106,7 +103,6 @@
'Get-SdnServiceFabricPartition',
'Get-SdnServiceFabricReplica',
'Get-SdnServiceFabricService',
'Get-SdnSlbMuxConfigurationState',
'Get-SdnSlbStateInformation',
'Get-SdnVipConfig',
'Get-SdnVfpVmSwitchPort',

Просмотреть файл

@ -2,9 +2,70 @@
# Licensed under the MIT License.
Import-Module $PSScriptRoot\SdnDiagnostics.Helper.psm1
New-Variable -Name 'SdnDiagnostics' -Scope 'Global' -Force -Value @{
Cache = @{}
EnvironmentInfo = @{
RestApiVersion = 'V1'
}
Config = @{
# when creating remote sessions, the module will be imported automatically
ImportModuleOnRemoteSession = $false
# determines from a global perspective if we should be disabling automatic seeding of module to remote nodes
DisableModuleSeeding = $false
# by default will just leverage the name of the module, however if using custom path not under default module directory
# can update this to be the full path name to module, which will be used on PSRemoteSessions
ModuleName = 'SdnDiagnostics'
# defines if this module is running on Windows Server, Azure Stack HCI or Azure Stack Hub
# supported values are 'WindowsServer', 'AzureStackHCI', 'AzureStackHub'
Mode = "WindowsServer"
}
}
# in some instances where powershell has been left open for a long time, we can leave behind sessions that are no longer valid
# so we will want to clean up any SDN related sessions on module import
Remove-PSRemotingSession
function Get-SdnConfigState {
<#
.SYNOPSIS
Gets the configuration state of the computer.
.PARAMETER Role
The SDN role of the computer.
.PARAMETER OutputDirectory
The directory to output the configuration state to.
.EXAMPLE
PS> Get-SdnConfigState -Role Server -OutputDirectory C:\Temp
#>
[cmdletbinding()]
param(
[parameter(Mandatory = $true)]
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $true)]
[System.IO.FileInfo]$OutputDirectory
)
switch ($Role) {
'Common' {
Get-CommonConfigState -OutputDirectory $OutputDirectory
}
'Gateway' {
Get-GatewayConfigState -OutputDirectory $OutputDirectory
}
'NetworkController' {
Get-NetworkControllerConfigState -OutputDirectory $OutputDirectory
}
'Server' {
Get-ServerConfigState -OutputDirectory $OutputDirectory
}
'LoadBalancerMux' {
Get-SlbMuxConfigState -OutputDirectory $OutputDirectory
}
}
}

Просмотреть файл

@ -4,4 +4,11 @@
@{
DefaultLogDirectory = "C:\Windows\Tracing\SDNDiagnostics\Logs"
LogFileTypes = @("*.log", "*.etl", "*.cab")
Properties = @{
EventLogProviders = @(
"Application"
"System"
)
EtwTraceProviders = @{}
}
}

Просмотреть файл

@ -1,9 +0,0 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
enum SdnRoles {
Gateway
NetworkController
Server
LoadBalancerMux
}

Просмотреть файл

@ -1,13 +1,10 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Using module .\SdnDiag.Common.Helper.psm1
Import-Module $PSScriptRoot\SdnDiag.Common.Helper.psm1
Import-Module $PSScriptRoot\..\SdnDiag.Utilities\SdnDiag.Utilities.psm1
# create local variable to store configuration data
$configurationData = Import-PowerShellDataFile -Path "$PSScriptRoot\SdnDiag.Common.Config.psd1"
New-Variable -Name 'SdnDiagnostics_Common' -Scope 'Script' -Force -Value @{
Cache = @{}
Config = $configurationData

Просмотреть файл

@ -1,4 +1,4 @@
function Get-GeneralConfigurationState {
function Get-CommonConfigState {
<#
.SYNOPSIS
Retrieves a common set of configuration details that is collected on any role, regardless of the role.
@ -15,7 +15,7 @@ function Get-GeneralConfigurationState {
$ErrorActionPreference = 'SilentlyContinue'
try {
[System.IO.FileInfo]$OutputDirectory = Join-Path -Path $OutputDirectory.FullName -ChildPath "General"
[System.IO.FileInfo]$OutputDirectory = Join-Path -Path $OutputDirectory.FullName -ChildPath "Common"
"Collect general configuration state details" | Trace-Output
if (-NOT (Initialize-DataCollection -FilePath $OutputDirectory.FullName -MinimumMB 100)) {
@ -24,24 +24,28 @@ function Get-GeneralConfigurationState {
}
# Gather general configuration details from all nodes
"Gathering network and system properties" | Trace-Output -Level:Verbose
Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess, @{n="ProcessName";e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName}} `
| Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetTCPConnection' -FileType csv
"Gathering system details" | Trace-Output -Level:Verbose
Get-Service | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-Service' -FileType txt -Format List
Get-Process | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-Process' -FileType txt -Format List
Get-Volume | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-Volume' -FileType txt -Format Table
Get-ComputerInfo | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-ComputerInfo' -FileType txt
# gather network related configuration details
"Gathering network details" | Trace-Output -Level:Verbose
Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess, @{n="ProcessName";e={(Get-Process -Id $_.OwningProcess -ErrorAction $ErrorActionPreference).ProcessName}} `
| Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetTCPConnection' -FileType csv
Get-NetIPInterface | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetIPInterface' -FileType txt -Format Table
Get-NetNeighbor -IncludeAllCompartments | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetNeighbor' -FileType txt -Format Table
Get-NetConnectionProfile | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetConnectionProfile' -FileType txt -Format Table
Get-NetRoute -AddressFamily IPv4 -IncludeAllCompartments | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetRoute' -FileType txt -Format Table
ipconfig /allcompartments /all | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'ipconfig_allcompartments' -FileType txt
"Gathering network adapter properties" | Trace-Output -Level:Verbose
Get-NetAdapter | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetAdapter' -FileType txt -Format Table
Get-NetAdapterSriov | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetAdapterSriov' -FileType txt -Format Table
Get-NetAdapterSriovVf | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetAdapterSriovVf' -FileType txt -Format Table
Get-NetAdapterRsc | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetAdapterRsc' -FileType txt -Format Table
Get-NetAdapterHardwareInfo | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-NetAdapterHardwareInfo' -FileType txt -Format Table
netsh winhttp show proxy | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'netsh_winhttp_show_proxy' -FileType txt
$outputDir = New-Item -Path (Join-Path -Path $OutputDirectory.FullName -ChildPath 'NetAdapter') -ItemType Directory -Force
foreach($adapter in Get-NetAdapter){
@ -54,12 +58,14 @@ function Get-GeneralConfigurationState {
}
# Gather DNS client settings
"Gathering DNS client properties" | Trace-Output -Level:Verbose
$outputDir = New-Item -Path (Join-Path -Path $OutputDirectory.FullName -ChildPath 'DnsClient') -ItemType Directory -Force
$dnsCommands = Get-Command -Verb Get -Module DnsClient
foreach($cmd in $dnsCommands.Name){
Invoke-Expression -Command $cmd -ErrorAction SilentlyContinue | Export-ObjectToFile -FilePath $outputDir.FullName -Name $cmd.ToString() -FileType txt -Format List
}
Get-DnsClient | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClient' -FileType txt -Format List
Get-DnsClientCache | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientCache' -FileType txt -Format List
Get-DnsClientDohServerAddress | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientDohServerAddress' -FileType txt -Format List
Get-DnsClientGlobalSetting | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientGlobalSetting' -FileType txt -Format List
Get-DnsClientNrptGlobal | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientNrptGlobal' -FileType txt -Format List
Get-DnsClientNrptPolicy | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientNrptPolicy' -FileType txt -Format List
Get-DnsClientNrptRule | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientNrptRule' -FileType txt -Format List
Get-DnsClientServerAddress | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-DnsClientServerAddress' -FileType txt -Format List
# gather the certificates configured on the system
$certificatePaths = @('Cert:\LocalMachine\My','Cert:\LocalMachine\Root')
@ -67,7 +73,6 @@ function Get-GeneralConfigurationState {
$fileName = $path.Replace(':','').Replace('\','_')
Get-SdnCertificate -Path $path | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name "Get-SdnCertificate_$($fileName)" -FileType csv
}
}
catch {
"{0}`n{1}" -f $_.Exception, $_.ScriptStackTrace | Trace-Output -Level:Error

Просмотреть файл

@ -48,7 +48,7 @@ function Get-SdnRole {
}
}
# if we made it to here, we were unable to locate the appropriate role the computername is associated with
"Unable to determine SDN role for {0}" -f $ComputerName | Trace-Output -Level:Warning
return $null
# if we made it to here, we were unable to locate any specific SdnRole such as LoadBalancerMux, Gateway, etc.
# so instead we will return Common as the role
return ([string]"Common")
}

Просмотреть файл

@ -11,7 +11,8 @@ function Get-TraceProviders {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[SdnRoles]$Role,
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $false)]
[ValidateSet("Default", "Optional", "All")]
@ -24,7 +25,11 @@ function Get-TraceProviders {
$traceProvidersArray = @()
try {
$config = Get-SdnModuleConfiguration -Role $Role.ToString()
$config = Get-SdnModuleConfiguration -Role $Role
if ($null -eq $config.properties.EtwTraceProviders) {
return $null
}
foreach ($key in $config.properties.EtwTraceProviders.Keys) {
$traceProvider = $config.properties.EtwTraceProviders[$key]
switch ($Providers) {

Просмотреть файл

@ -10,6 +10,8 @@ function Enable-SdnVipTrace {
Specifies a user account that has permission to perform this action. The default is the current user.
.PARAMETER NcRestCredential
Specifies a user account that has permission to access the northbound NC API interface. The default is the current user.
.PARAMETER OutputDirectory
Optional. Specifies a specific path and folder in which to save the files.
.PARAMETER MaxTraceSize
Optional. Specifies the maximum size in MB for saved trace files. If unspecified, the default is 1536.
#>
@ -28,6 +30,9 @@ function Enable-SdnVipTrace {
})]
[Uri]$NcUri,
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[System.String]$OutputDirectory = "$(Get-WorkingDirectory)\NetworkTraces",
[Parameter(Mandatory = $false, ParameterSetName = 'Default')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
@ -131,13 +136,13 @@ function Enable-SdnVipTrace {
# ensure that we have SdnDiagnostics installed to the nodes that we need to enable tracing for
Install-SdnDiagnostics -ComputerName $networkTraceNodes -Credential $Credential
"Network traces will be enabled on`r`n`t - LoadBalancerMux: {0}`r`n`t - Server: {1}`r`n" `
"Network traces will be enabled on:`r`n`t - LoadBalancerMux: {0}`r`n`t - Server: {1}`r`n" `
-f ($loadBalancerMuxes -join ', '), ($Script:SdnDiagnostics_Common.Cache['TraceMapping'].Keys -join ', ') | Trace-Output
# enable tracing on the infastructure
$traceInfo = @()
$traceInfo += Start-SdnNetshTrace -ComputerName $loadBalancerMuxes -Role 'LoadBalancerMux' -Credential $Credential -MaxTraceSize $MaxTraceSize
$traceInfo += Start-SdnNetshTrace -ComputerName $Script:SdnDiagnostics_Common.Cache['TraceMapping'].Keys -Role 'Server' -Credential $Credential -MaxTraceSize $MaxTraceSize
$traceInfo += Start-SdnNetshTrace -ComputerName $loadBalancerMuxes -Role 'LoadBalancerMux' -Credential $Credential -OutputDirectory $OutputDirectory -MaxTraceSize $MaxTraceSize
$traceInfo += Start-SdnNetshTrace -ComputerName $Script:SdnDiagnostics_Common.Cache['TraceMapping'].Keys -Role 'Server' -Credential $Credential -OutputDirectory $OutputDirectory -MaxTraceSize $MaxTraceSize
"Tracing has been enabled on the SDN infrastructure nodes {0}" -f ($traceInfo.PSComputerName -join ', ') | Trace-Output
# at this point, tracing should be enabled on the sdn fabric and we can wait for user input to disable

Просмотреть файл

@ -19,7 +19,8 @@ function Get-SdnEventLog {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[SdnRoles]$Role,
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $true)]
[System.IO.FileInfo]$OutputDirectory,
@ -35,20 +36,20 @@ function Get-SdnEventLog {
$toDateUTC = $ToDate.ToUniversalTime()
try {
$roleConfig = Get-SdnModuleConfiguration -Role $Role.ToString()
$roleConfig = Get-SdnModuleConfiguration -Role $Role
$eventLogs = [System.Collections.ArrayList]::new()
[System.IO.FileInfo]$OutputDirectory = Join-Path -Path $OutputDirectory.FullName -ChildPath "EventLogs"
"Collect event logs between {0} and {1} UTC" -f $fromDateUTC, $toDateUTC | Trace-Output
if (-NOT (Initialize-DataCollection -Role $Role.ToString() -FilePath $OutputDirectory.FullName -MinimumGB 1)) {
if (-NOT (Initialize-DataCollection -Role $Role -FilePath $OutputDirectory.FullName -MinimumGB 1)) {
"Unable to initialize environment for data collection" | Trace-Output -Level:Exception
return
}
$eventLogProviders = $roleConfig.Properties.EventLogProviders
if ($null -ieq $eventLogs) {
"No event log providers found for {0}" -f $Role.ToString() | Trace-Output -Level:Warning
"No event log providers found for {0}" -f $Role | Trace-Output -Level:Warning
return
}

Просмотреть файл

@ -45,7 +45,7 @@ function Invoke-SdnGetNetView {
)
try {
Copy-Item -Path "$PSScriptRoot\..\..\..\externalPackages\Get-NetView" -Destination "C:\Program Files\WindowsPowerShell\Modules\" -Force -Recurse
Copy-Item -Path "$PSScriptRoot\..\..\..\externalPackages\Get-NetView" -Destination "$($env:ProgramFiles)\WindowsPowerShell\Modules" -Force -Recurse
Import-Module -Name 'Get-NetView' -Force
"Using Get-NetView version {0}" -f (Get-Module -Name 'Get-NetView' -ErrorAction SilentlyContinue).Version.ToString() | Trace-Output -Level:Verbose

Просмотреть файл

@ -56,7 +56,8 @@ function Start-SdnDataCollection {
[Uri]$NcUri,
[Parameter(Mandatory = $true, ParameterSetName = 'Role')]
[SdnRoles[]]$Role,
[ValidateSet('Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String[]]$Role,
[Parameter(Mandatory = $true, ParameterSetName = 'Computer')]
[System.String[]]$ComputerName,
@ -121,6 +122,11 @@ function Start-SdnDataCollection {
Get-SdnDiagnosticLogFile -LogDir $arg0 -OutputDirectory $arg1 -FromDate $arg2 -ToDate $arg3 -ConvertETW $arg4 -CleanUpFiles $arg5
}
$collectConfigStateSB = {
param([Parameter(Position = 0)][String]$Role, [Parameter(Position = 1)][String]$OutputDirectory)
Get-SdnConfigState -Role $Role -OutputDirectory $OutputDirectory
}
try {
if (-NOT ($PSBoundParameters.ContainsKey('NetworkController'))) {
$config = Get-SdnModuleConfiguration -Role 'NetworkController'
@ -214,7 +220,7 @@ function Start-SdnDataCollection {
Get-SdnNetworkControllerClusterInfo -NetworkController $NetworkController -OutputDirectory $OutputDirectory.FullName -Credential $Credential
$debugInfraHealthResults = Get-SdnFabricInfrastructureResult
if ($debugInfraHealthResults) {
$debugInfraHealthResults.Values | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-SdnFabricInfrastructureResult_Summary' -FileType 'txt' -Format 'table'
$debugInfraHealthResults | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-SdnFabricInfrastructureResult_Summary' -FileType 'txt' -Format 'table'
$debugInfraHealthResults | Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-SdnFabricInfrastructureResult' -FileType json -Depth 5
}
@ -239,27 +245,12 @@ function Start-SdnDataCollection {
$filteredDataCollectionNodes += $dataNodes
"Collect configuration state details for {0} nodes: {1}" -f $group.Name, ($dataNodes -join ', ') | Trace-Output
Invoke-PSRemoteCommand -ComputerName $dataNodes -Credential $Credential -ScriptBlock $collectConfigStateSB `
-ArgumentList @($group.Name, $tempDirectory.FullName) -AsJob -PassThru -Activity "Collect $($group.Name) Configuration State"
# collect any adhoc data based on the role
switch ($group.Name) {
'Gateway' {
Invoke-PSRemoteCommand -ComputerName $dataNodes -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$OutputDirectory)
Get-SdnGatewayConfigurationState -OutputDirectory $OutputDirectory
} -ArgumentList $tempDirectory.FullName -AsJob -PassThru -Activity 'Collect Gateway Configuration'
}
'NetworkController' {
Invoke-PSRemoteCommand -ComputerName $dataNodes -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$OutputDirectory)
Get-SdnNetworkControllerConfigurationState -OutputDirectory $OutputDirectory
} -ArgumentList $tempDirectory.FullName -AsJob -PassThru -Activity 'Collect Network Controller Configuration'
}
'Server' {
Invoke-PSRemoteCommand -ComputerName $dataNodes -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$OutputDirectory)
Get-SdnServerConfigurationState -OutputDirectory $OutputDirectory
} -ArgumentList $tempDirectory.FullName -AsJob -PassThru -Activity 'Collect Server Configuration'
Get-SdnProviderAddress -ComputerName $dataNodes -Credential $Credential `
| Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-SdnProviderAddress' -FileType csv
@ -269,13 +260,6 @@ function Start-SdnDataCollection {
Get-SdnVMNetworkAdapter -ComputerName $dataNodes -Credential $Credential -AsJob -PassThru -Timeout 900 `
| Export-ObjectToFile -FilePath $OutputDirectory.FullName -Name 'Get-SdnVMNetworkAdapter' -FileType csv
}
'LoadBalancerMux' {
Invoke-PSRemoteCommand -ComputerName $dataNodes -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$OutputDirectory)
Get-SdnSlbMuxConfigurationState -OutputDirectory $OutputDirectory
} -ArgumentList $tempDirectory.FullName -AsJob -PassThru -Activity 'Collect SLB Configuration State'
}
}
# check to see if any network traces were captured on the data nodes previously

Просмотреть файл

@ -11,7 +11,8 @@ function Start-SdnEtwTraceCapture {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[SdnRoles]$Role,
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $false)]
[System.String]$OutputDirectory = (Get-WorkingDirectory),
@ -25,11 +26,11 @@ function Start-SdnEtwTraceCapture {
$maxTraceSize = 1024
try {
$traceProvidersArray = Get-TraceProviders -Role $Role.ToString() -Providers $Providers
$traceProvidersArray = Get-TraceProviders -Role $Role -Providers $Providers
# we want to calculate the max size on number of factors to ensure sufficient disk space is available
$diskSpaceRequired = $maxTraceSize*($traceProvidersArray.Count)*1.5
if (-NOT (Initialize-DataCollection -Role $Role.ToString() -FilePath $OutputDirectory -MinimumMB $diskSpaceRequired)) {
if (-NOT (Initialize-DataCollection -Role $Role -FilePath $OutputDirectory -MinimumMB $diskSpaceRequired)) {
"Unable to initialize environment for data collection" | Trace-Output -Level:Exception
return
}

Просмотреть файл

@ -31,7 +31,8 @@ function Start-SdnNetshTrace {
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Local')]
[Parameter(Mandatory = $true, ParameterSetName = 'Remote')]
[SdnRoles]$Role,
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $false, ParameterSetName = 'Local')]
[Parameter(Mandatory = $false, ParameterSetName = 'Remote')]
@ -86,7 +87,7 @@ function Start-SdnNetshTrace {
$scriptBlock = {
param(
[Parameter(Position = 0)][SdnRoles]$Role,
[Parameter(Position = 0)][String]$Role,
[Parameter(Position = 1)][String]$OutputDirectory,
[Parameter(Position = 2)][int]$MaxTraceSize,
[Parameter(Position = 3)][String]$Capture,
@ -96,17 +97,17 @@ function Start-SdnNetshTrace {
[Parameter(Position = 7)][String]$Providers
)
Start-SdnNetshTrace -Role $Role.ToString() -OutputDirectory $OutputDirectory `
Start-SdnNetshTrace -Role $Role -OutputDirectory $OutputDirectory `
-MaxTraceSize $MaxTraceSize -Capture $Capture -Overwrite $Overwrite -Report $Report -Correlation $Correlation -Providers $Providers
}
try {
if ($PSCmdlet.ParameterSetName -eq 'Remote') {
Invoke-PSRemoteCommand -ComputerName $ComputerName -Credential $Credential -ScriptBlock $scriptBlock `
-ArgumentList @($Role.ToString(), $params.OutputDirectory, $params.MaxTraceSize, $params.Capture, $params.Overwrite, $params.Report, $params.Correlation, $Providers)
-ArgumentList @($Role, $params.OutputDirectory, $params.MaxTraceSize, $params.Capture, $params.Overwrite, $params.Report, $params.Correlation, $Providers)
}
else {
$traceProviderString = Get-TraceProviders -Role $Role.ToString() -Providers $Providers -AsString
$traceProviderString = Get-TraceProviders -Role $Role -Providers $Providers -AsString
if ($traceProviderString) {
$params.Add('TraceProviderString', $traceProviderString)
"Trace providers configured: {0}" -f $traceProviderString | Trace-Output -Level:Verbose
@ -119,7 +120,7 @@ function Start-SdnNetshTrace {
}
}
if (-NOT ( Initialize-DataCollection -Role $Role.ToString() -FilePath $OutputDirectory -MinimumMB ($MaxTraceSize*1.5) )) {
if (-NOT ( Initialize-DataCollection -Role $Role -FilePath $OutputDirectory -MinimumMB ($MaxTraceSize*1.5) )) {
"Unable to initialize environment for data collection" | Trace-Output -Level:Exception
return
}

Просмотреть файл

@ -11,7 +11,8 @@ function Stop-SdnEtwTraceCapture {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[SdnRoles]$Role,
[ValidateSet('Common', 'Gateway', 'NetworkController', 'Server', 'LoadBalancerMux')]
[String]$Role,
[Parameter(Mandatory = $false)]
[ValidateSet("Default", "Optional", "All")]

Просмотреть файл

@ -12,11 +12,9 @@
RasGatewayTraces = "C:\Windows\Tracing"
}
EventLogProviders = @(
"Application"
"Microsoft-Windows-RasAgileVpn*"
"Microsoft-Windows-RemoteAccess*"
"Microsoft-Windows-VPN*"
"System"
)
RegKeyPaths = @(
"HKLM:\Software\Microsoft\NetworkController"

Просмотреть файл

@ -1,11 +1,11 @@
function Get-SdnGatewayConfigurationState {
function Get-GatewayConfigState {
<#
.SYNOPSIS
Outputs a set of configuration state files for the gateway role.
.PARAMETER OutputDirectory
Specifies a specific path and folder in which to save the files.
.EXAMPLE
PS> Get-SdnGatewayConfigurationState -OutputDirectory "C:\Temp\CSS_SDN"
PS> Get-GatewayConfigState -OutputDirectory "C:\Temp\CSS_SDN"
#>
[CmdletBinding()]
@ -31,7 +31,7 @@ function Get-SdnGatewayConfigurationState {
}
Export-RegistryKeyConfigDetails -Path $config.properties.regKeyPaths -OutputDirectory $regDir.FullName
Get-GeneralConfigurationState -OutputDirectory $OutputDirectory.FullName
Get-CommonConfigState -OutputDirectory $OutputDirectory.FullName
# dump out the role configuration state properties
"Getting RRAS VPN configuration details" | Trace-Output -Level:Verbose

Просмотреть файл

@ -1,7 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Using module .\..\SdnDiag.Common\SdnDiag.Common.Helper.psm1
Using module .\SdnDiag.Health.Helper.psm1
Import-Module $PSScriptRoot\SdnDiag.Health.Helper.psm1

Просмотреть файл

@ -52,7 +52,7 @@ function Test-ScheduledTaskEnabled {
foreach ($result in $scheduledTaskReady) {
switch ($result.State) {
'Logging Disabled' {
"SDN Diagnostics Task is not available on {0} because logging is disabled." -f $result.PSComputerName | Trace-Output -Level:Warning
"SDN Diagnostics Task is not available on {0} because logging is disabled." -f $result.PSComputerName | Trace-Output -Level:Verbose
}
'Not Found' {
"Unable to locate SDN Diagnostics Task on {0}." -f $result.PSComputerName | Trace-Output -Level:Exception

Просмотреть файл

@ -27,7 +27,7 @@ function Get-SdnFabricInfrastructureResult {
if ($PSBoundParameters.ContainsKey('Role')) {
if ($cacheResults) {
$cacheResults = $cacheResults | Where-Object {$_.Role -eq $Role.ToString()}
$cacheResults = $cacheResults | Where-Object {$_.Role -eq $Role}
}
}

Просмотреть файл

@ -10,7 +10,6 @@
Properties = @{
CommonPaths = @{}
EventLogProviders = @(
"Application"
"Microsoft-Windows-SlbMux*"
)
RegKeyPaths = @(

Просмотреть файл

@ -1,6 +1,6 @@
function Get-MuxDriverControl {
if (-NOT (Get-Module -Name 'Microsoft.Cloudnet.Slb.Mux.MuxDriverControl')) {
Import-Module 'C:\windows\System32\Microsoft.Cloudnet.Slb.Mux.MuxDriverControl.dll' -Force
Import-Module "$env:SystemRoot\System32\Microsoft.Cloudnet.Slb.Mux.MuxDriverControl.dll" -Force
}
return ([Microsoft.Cloudnet.Slb.Mux.Driver.SlbDriverControl]::new())

Просмотреть файл

@ -1,11 +1,11 @@
function Get-SdnSlbMuxConfigurationState {
function Get-SlbMuxConfigState {
<#
.SYNOPSIS
Outputs a set of configuration state files for the load balancer role.
.PARAMETER OutputDirectory
Specifies a specific path and folder in which to save the files.
.EXAMPLE
PS> Get-SdnSlbMuxConfigurationState -OutputDirectory "C:\Temp\CSS_SDN"
PS> Get-SlbMuxConfigState -OutputDirectory "C:\Temp\CSS_SDN"
#>
[CmdletBinding()]
@ -31,7 +31,7 @@ function Get-SdnSlbMuxConfigurationState {
}
Export-RegistryKeyConfigDetails -Path $config.properties.regKeyPaths -OutputDirectory $regDir.FullName
Get-GeneralConfigurationState -OutputDirectory $OutputDirectory.FullName
Get-CommonConfigState -OutputDirectory $OutputDirectory.FullName
# output slb configuration and states
"Getting MUX Driver Control configuration settings" | Trace-Output -Level:Verbose

Просмотреть файл

@ -208,10 +208,8 @@
serviceFabricLogDirectory = "C:\ProgramData\Microsoft\Service Fabric\log\Traces"
}
EventLogProviders = @(
"Application"
"Microsoft-Windows-NetworkController*"
"Microsoft-ServiceFabric*"
"System"
)
NetControllerStatePath = "C:\Windows\Tracing\SDNDiagnostics\NetworkControllerState"
RegKeyPaths = @(

Просмотреть файл

@ -37,12 +37,12 @@ function Copy-ServiceFabricManifestFromNetworkController {
New-Item -Path $ManifestFolder -ItemType Directory -Force | Out-Null
New-Item -Path $ManifestFolderNew -ItemType Directory -Force | Out-Null
$fabricFolder = "c:\programdata\Microsoft\Service Fabric\$($NcNodeList[0].NodeName)\Fabric"
$fabricFolder = "$env:ProgramData\Microsoft\Service Fabric\$($NcNodeList[0].NodeName)\Fabric"
Copy-FileFromRemoteComputer -Path "$fabricFolder\ClusterManifest.current.xml" -ComputerName $($NcNodeList[0].IpAddressOrFQDN) -Destination $ManifestFolder -Credential $Credential
Copy-FileFromRemoteComputer -Path "$fabricFolder\Fabric.Data\InfrastructureManifest.xml" -ComputerName $($NcNodeList[0].IpAddressOrFQDN) -Destination $ManifestFolder -Credential $Credential
$NcNodeList | ForEach-Object {
$fabricFolder = "c:\programdata\Microsoft\Service Fabric\$($_.NodeName)\Fabric"
$fabricFolder = "$env:ProgramData\Microsoft\Service Fabric\$($_.NodeName)\Fabric"
$version = Invoke-PSRemoteCommand -ComputerName $_.IpAddressOrFQDN -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)

Просмотреть файл

@ -39,7 +39,7 @@ function Copy-ServiceFabricManifestToNetworkController {
$NcNodeList | ForEach-Object {
$fabricFolder = "c:\programdata\Microsoft\Service Fabric\$($_.NodeName)\Fabric"
$fabricFolder = "$env:ProgramData\Microsoft\Service Fabric\$($_.NodeName)\Fabric"
$version = Invoke-PSRemoteCommand -ComputerName $_.IpAddressOrFQDN -Credential $Credential -ScriptBlock {
param([Parameter(Position = 0)][String]$param1)

Просмотреть файл

@ -0,0 +1,27 @@
function Get-ManagementAddress {
param (
$ManagementAddress
)
$uniqueFQDN = @()
$uniqueIPAddress = @()
foreach ($ma in $ManagementAddress) {
$isIpAddress = ($ma -as [IPAddress]) -as [Bool]
if ($isIpAddress) {
$uniqueIPAddress += $ma
}
else {
$uniqueFQDN += $ma.ToLower()
}
}
# if we have a mix of FQDN and IPAddress, defer to FQDN
# use Sort-Object -Unique to remove duplicates from the list (case insensitive)
if ($uniqueFQDN) {
return ($uniqueFQDN | Sort-Object -Unique)
}
else {
return ($uniqueIPAddress | Sort-Object -Unique)
}
}

Просмотреть файл

@ -1,11 +1,11 @@
function Get-SdnNetworkControllerConfigurationState {
function Get-NetworkControllerConfigState {
<#
.SYNOPSIS
Outputs a set of configuration state files for the network controller role.
.PARAMETER OutputDirectory
Specifies a specific path and folder in which to save the files.
.EXAMPLE
PS> Get-SdnNetworkControllerConfigurationState -OutputDirectory "C:\Temp\CSS_SDN"
PS> Get-NetworkControllerConfigState -OutputDirectory "C:\Temp\CSS_SDN"
#>
[CmdletBinding()]
@ -32,10 +32,10 @@ function Get-SdnNetworkControllerConfigurationState {
}
Export-RegistryKeyConfigDetails -Path $config.properties.regKeyPaths -OutputDirectory $regDir.FullName
Get-GeneralConfigurationState -OutputDirectory $OutputDirectory.FullName
Get-CommonConfigState -OutputDirectory $OutputDirectory.FullName
# enumerate dll binary version for NC application
$ncAppDirectories = Get-ChildItem -Path "C:\Windows\NetworkController" -Directory
$ncAppDirectories = Get-ChildItem -Path "$env:SystemRoot\NetworkController" -Directory
foreach($directory in $ncAppDirectories){
[System.String]$fileName = "FileInfo_{0}" -f $directory.BaseName
Get-Item -Path "$($directory.FullName)\*" -Include *.dll,*.exe | Export-ObjectToFile -FilePath $ncAppDir.FullName -Name $fileName -FileType txt -Format List

Просмотреть файл

@ -36,15 +36,8 @@ function Get-SdnVirtualServer {
}
if ($ManagementAddressOnly) {
$managementAddress = @()
foreach ($address in $result.properties.connections.managementAddresses) {
$managementAddress += $address
}
# there might be multiple connection endpoints to each node so we will want to only return the unique results
# this does not handle if some duplicate connections are listed as IPAddress with another record saved as NetBIOS or FQDN
# further processing may be required by the calling function to handle that
return ($managementAddress | Sort-Object -Unique)
$connections = (Get-ManagementAddress -ManagementAddress $result.properties.connections.managementAddresses)
return $connections
}
else {
return $result

Просмотреть файл

@ -80,15 +80,15 @@ function Get-SdnGateway {
}
if($ManagementAddressOnly){
$managementAddress = @()
$connections = @()
foreach ($resource in $result) {
$virtualServerMgmtAddress = Get-SdnVirtualServer -NcUri $NcUri.AbsoluteUri -ResourceRef $resource.properties.virtualserver.ResourceRef -ManagementAddressOnly -Credential $Credential
$managementAddress += $virtualServerMgmtAddress
$connections += $virtualServerMgmtAddress
}
return ($managementAddress | Sort-Object -Unique)
return $connections
}
else{
else {
return $result
}
}

Просмотреть файл

@ -80,15 +80,15 @@ function Get-SdnLoadBalancerMux {
}
if($ManagementAddressOnly){
$managementAddress = @()
$connections = @()
foreach ($resource in $result) {
$virtualServerMgmtAddress = Get-SdnVirtualServer -NcUri $NcUri.AbsoluteUri -ResourceRef $resource.properties.virtualserver.ResourceRef -ManagementAddressOnly -Credential $Credential
$managementAddress += $virtualServerMgmtAddress
$connections += $virtualServerMgmtAddress
}
return ($managementAddress | Sort-Object -Unique)
return $connections
}
else{
else {
return $result
}
}

Просмотреть файл

@ -80,17 +80,10 @@ function Get-SdnServer {
}
if($ManagementAddressOnly){
$managementAddress = @()
foreach ($address in $result.properties.connections.managementAddresses) {
$managementAddress += $address
}
# there might be multiple connection endpoints to each node so we will want to only return the unique results
# this does not handle if some duplicate connections are listed as IPAddress with another record saved as NetBIOS or FQDN
# further processing may be required by the calling function to handle that
return ($managementAddress | Sort-Object -Unique)
$connections = (Get-ManagementAddress -ManagementAddress $result.properties.connections.managementAddresses)
return $connections
}
else{
else {
return $result
}
}

Просмотреть файл

@ -44,7 +44,7 @@ function Get-SdnServiceFabricClusterManifest {
# we want to loop through if multiple NetworkController objects were passed into the cmdlet
foreach ($obj in $NetworkController) {
$clusterManifestScript = {
$clusterManifestFile = Get-ChildItem -Path "C:\ProgramData\Microsoft\Service Fabric" -Recurse -Depth 2 -Filter "ClusterManifest.current.xml" -ErrorAction SilentlyContinue
$clusterManifestFile = Get-ChildItem -Path "$env:ProgramData\Microsoft\Service Fabric" -Recurse -Depth 2 -Filter "ClusterManifest.current.xml" -ErrorAction SilentlyContinue
if ($clusterManifestFile) {
$clusterManifest = Get-Content -Path $clusterManifestFile.FullName -ErrorAction SilentlyContinue
return $clusterManifest

Просмотреть файл

@ -29,6 +29,7 @@ function Invoke-SdnResourceDump {
)
try {
"Generating resource dump for Network Controller NB API endpoints" | Trace-Output
[System.IO.FileInfo]$outputDir = Join-Path -Path $OutputDirectory.FullName -ChildPath 'SdnApiResources'
if (!(Test-Path -Path $outputDir.FullName -PathType Container)) {
$null = New-Item -Path $outputDir.FullName -ItemType Directory -Force

Просмотреть файл

@ -13,9 +13,7 @@
Properties = @{
CommonPaths = @{}
EventLogProviders = @(
"Application"
"Microsoft-Windows-Hyper-V*"
"System"
)
RegKeyPaths = @(
"HKLM:\Software\Microsoft\NetworkController"

Просмотреть файл

@ -1,11 +1,11 @@
function Get-SdnServerConfigurationState {
function Get-ServerConfigState {
<#
.SYNOPSIS
Outputs a set of configuration state files for the server role.
.PARAMETER OutputDirectory
Specifies a specific path and folder in which to save the files.
.EXAMPLE
PS> Get-SdnServerConfigurationState -OutputDirectory "C:\Temp\CSS_SDN"
PS> Get-ServerConfigState -OutputDirectory "C:\Temp\CSS_SDN"
#>
[CmdletBinding()]
@ -31,7 +31,7 @@ function Get-SdnServerConfigurationState {
}
Export-RegistryKeyConfigDetails -Path $config.properties.regKeyPaths -OutputDirectory $regDir.FullName
Get-GeneralConfigurationState -OutputDirectory $OutputDirectory.FullName
Get-CommonConfigState -OutputDirectory $OutputDirectory.FullName
# Gather VFP port configuration details
"Gathering VFP port details" | Trace-Output -Level:Verbose

Просмотреть файл

@ -6,5 +6,6 @@
"C:\Windows\Tracing\SdnDiag"
"C:\Windows\Tracing\SdnDiag\*"
)
DefaultModuleDirectory = "C:\Program Files\WindowsPowerShell\Modules\SdnDiagnostics"
WorkingDirectory = "C:\Windows\Tracing\SdnDiag"
}

Просмотреть файл

@ -13,8 +13,8 @@ enum TraceLevel {
enum SdnModules {
Common
Gateway
LoadBalancerMux
NetworkController
Server
LoadBalancerMux
Utilities
}

Просмотреть файл

@ -1,7 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Using module .\..\SdnDiag.Common\SdnDiag.Common.Helper.psm1
Using module .\SdnDiag.Utilities.Helper.psm1
# create local variable to store configuration data

Просмотреть файл

@ -4,6 +4,9 @@ function Invoke-PSRemoteCommand {
[Parameter(Mandatory = $true)]
[System.String[]]$ComputerName,
[Parameter(Mandatory = $false)]
[bool]$ImportModuleOnRemoteSession,
[Parameter(Mandatory = $true)]
[ScriptBlock]$ScriptBlock,
@ -32,7 +35,16 @@ function Invoke-PSRemoteCommand {
ScriptBlock = $ScriptBlock
}
$session = New-PSRemotingSession -ComputerName $ComputerName -Credential $Credential
$psSessionParams = @{
ComputerName = $ComputerName
Credential = $Credential
}
if ($PSBoundParameters.ContainsKey('ImportModuleOnRemoteSession')) {
$psSessionParams.Add('ImportModuleOnRemoteSession', $ImportModuleOnRemoteSession)
}
$session = New-PSRemotingSession @psSessionParams
if ($session) {
$params.Add('Session', $session)
"ComputerName: {0}, ScriptBlock: {1}" -f ($session.ComputerName -join ', '), $ScriptBlock.ToString() | Trace-Output -Level:Verbose

Просмотреть файл

@ -9,10 +9,27 @@ function New-PSRemotingSession {
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false)]
[bool]$ImportModuleOnRemoteSession = $Global:SdnDiagnostics.Config.ImportModuleOnRemoteSession,
[Parameter(Mandatory = $false)]
[System.String]$ModuleName = $Global:SdnDiagnostics.Config.ModuleName,
[Parameter(Mandatory = $false)]
[Switch]$Force
)
$importRemoteModule = {
param([string]$arg0, $arg1)
try {
Import-Module $arg0 -ErrorAction Stop
$Global:SdnDiagnostics.Config = $arg1
}
catch {
throw $_
}
}
$remoteSessions = [System.Collections.ArrayList]::new()
# return a list of current sessions on the computer
@ -45,7 +62,7 @@ function New-PSRemotingSession {
try {
if($Credential -ne [System.Management.Automation.PSCredential]::Empty){
"PSRemotingSession use provided credential {0}" -f $Credential.UserName | Trace-Output -Level:Verbose
$session = New-PSSession -Name "SdnDiag-$(Get-Random)" -ComputerName $obj -Credential $Credential -SessionOption (New-PSSessionOption -Culture en-US -UICulture en-US) -ErrorAction Stop
$session = New-PSSession -Name "SdnDiag-$(Get-Random)" -ComputerName $obj -Credential $Credential -SessionOption (New-PSSessionOption -Culture en-US -UICulture en-US -IdleTimeout 86400000) -ErrorAction Stop
}
else {
# if we need to create a new remote session, need to check to ensure that if using an IP Address that credentials are specified
@ -64,13 +81,17 @@ function New-PSRemotingSession {
}
"PSRemotingSession use default credential" | Trace-Output -Level:Verbose
$session = New-PSSession -Name "SdnDiag-$(Get-Random)" -ComputerName $obj -SessionOption (New-PSSessionOption -Culture en-US -UICulture en-US) -ErrorAction Stop
$session = New-PSSession -Name "SdnDiag-$(Get-Random)" -ComputerName $obj -SessionOption (New-PSSessionOption -Culture 'en-US' -UICulture 'en-US' -IdleTimeout 86400000) -ErrorAction Stop
if ($ImportModuleOnRemoteSession) {
Invoke-Command -Session $session -ScriptBlock $importRemoteModule -ArgumentList @($ModuleName, $Global:SdnDiagnostics.Config) -ErrorAction Stop
}
}
"Created powershell session {0} to {1}" -f $session.Name, $obj | Trace-Output -Level:Verbose
}
catch {
"Unable to create powershell session to {0}`n`t{1}" -f $obj, $_.Exception | Trace-Output -Level:Warning
"Unable to create powershell session to {0}`n`t{1}" -f $obj, $_.Exception.Message | Trace-Output -Level:Warning
continue
}
}

Просмотреть файл

@ -8,37 +8,54 @@ function Remove-PSRemotingSession {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Parameter(Mandatory = $false)]
[System.String[]]$ComputerName
)
try {
[int]$timeOut = 120
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew()
$sessions = Get-PSSession -Name "SdnDiag-*" | Where-Object {$_.ComputerName -iin $ComputerName}
while($sessions){
if($stopWatch.Elapsed.TotalSeconds -gt $timeOut){
if ($PSBoundParameters.ContainsKey('ComputerName')) {
$sessions = Get-PSSession -Name "SdnDiag-*" | Where-Object { $_.ComputerName -iin $ComputerName }
}
else {
$sessions = Get-PSSession -Name "SdnDiag-*"
}
while ($sessions) {
if ($stopWatch.Elapsed.TotalSeconds -gt $timeOut) {
throw New-Object System.TimeoutException("Unable to drain PSSessions")
}
foreach($session in $sessions){
if($session.Availability -ieq 'Busy'){
foreach ($session in $sessions) {
if ($session.Availability -ieq 'Busy') {
"{0} is currently {1}. Waiting for PSSession.. {2} seconds" -f $session.Name, $session.Availability, $stopWatch.Elapsed.TotalSeconds | Trace-Output
Start-Sleep -Seconds 5
continue
}
else {
"Removing PSSession {0}" -f $session.Name | Trace-Output -Level:Verbose
$session | Remove-PSSession -ErrorAction Continue
"Removing PSSession {0} for {1}" -f $session.Name, $session.ComputerName | Trace-Output -Level:Verbose
try {
$session | Remove-PSSession -ErrorAction Stop
}
catch {
"Unable to remove PSSession {0} for {1}. Error: {2}" -f $session.Name, $session.ComputerName, $_.Exception.Message | Trace-Output -Level:Warning
continue
}
}
}
$sessions = Get-PSSession -Name "SdnDiag-*" | Where-Object {$_.ComputerName -iin $ComputerName}
if ($PSBoundParameters.ContainsKey('ComputerName')) {
$sessions = Get-PSSession -Name "SdnDiag-*" | Where-Object { $_.ComputerName -iin $ComputerName }
}
else {
$sessions = Get-PSSession -Name "SdnDiag-*"
}
}
$stopWatch.Stop()
"Successfully drained PSSessions for {0}" -f ($ComputerName -join ', ') | Trace-Output
}
catch {
$stopWatch.Stop()

Просмотреть файл

@ -7,6 +7,10 @@ function Install-SdnDiagnostics {
.PARAMETER Credential
Specifies a user account that has permission to perform this action. The default is the current user.
Type a user name, such as User01 or Domain01\User01, or enter a PSCredential object generated by the Get-Credential cmdlet. If you type a user name, you're prompted to enter the password.
.PARAMETER Path
Specifies the path to the module where it should be installed. If not specified, the default path will be used.
.PARAMETER Force
Forces a cleanup and re-install of the module on the remote computer.
#>
[CmdletBinding()]
@ -19,38 +23,45 @@ function Install-SdnDiagnostics {
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false)]
[System.String]$Path = $Script:SdnDiagnostics_Utilities.Config.DefaultModuleDirectory,
[Parameter(Mandatory = $false)]
[switch]$Force
)
try {
[System.IO.FileInfo]$moduleRootDir = "C:\Program Files\WindowsPowerShell\Modules"
$filteredComputerName = [System.Collections.ArrayList]::new()
$installNodes = [System.Collections.ArrayList]::new()
# if we have configured automatic seeding of module to remote nodes, we will want to skip this operation
if ($Global:SdnDiagnostics.Config.DisableModuleSeeding) {
return
}
$moduleName = $Global:SdnDiagnostics.Config.ModuleName
$filteredComputerName = [System.Collections.ArrayList]::new()
$installNodes = [System.Collections.ArrayList]::new()
try {
# if we have multiple modules installed on the current workstation,
# abort the operation because side by side modules can cause some interop issues to the remote nodes
$localModule = Get-Module -Name 'SdnDiagnostics'
if ($localModule.Count -gt 1) {
throw New-Object System.ArgumentOutOfRangeException("Detected more than one module version of SdnDiagnostics. Remove existing modules and restart your PowerShell session.")
throw "Detected more than one module version of SdnDiagnostics. Remove all versions of module from runspace and re-import the module."
}
# since we may not know where the module was imported from we cannot accurately assume the $localModule.ModuleBase is correct
# manually generate the destination path we want the module to be installed on remote nodes
if ($localModule.ModuleBase -ilike "*$($localModule.Version.ToString())") {
[System.IO.FileInfo]$destinationPathDir = "{0}\{1}\{2}" -f $moduleRootDir.FullName, 'SdnDiagnostics', $localModule.Version.ToString()
}
else {
[System.IO.FileInfo]$destinationPathDir = "{0}\{1}" -f $moduleRootDir.FullName, 'SdnDiagnostics'
}
"Current version of SdnDiagnostics is {0}" -f $localModule.Version.ToString() | Trace-Output
# typically PowerShell modules will be installed in the following directory configuration:
# $env:ProgramFiles\WindowsPowerShell\Modules\SdnDiagnostics\{version}
# $env:USERPROFILE\Documents\WindowsPowerShell\Modules\SdnDiagnostics\{version}
# so we default to Leaf of the path being SdnDiagnostics as PSGet will handle the versioning so we only ever do import in the following format:
# Import-Module SdnDiagnostics (if using default PowerShell module path)
# Import-Module C:\{path}\SdnDiagnostics (if using custom PowerShell module path)
# so we need to ensure that we are copying the module to the correct path on the remote computer
[System.String]$destinationPathDir = Join-Path $Path -ChildPath $localModule.Version.ToString()
"Verifying {0} is running SdnDiagnostics version {1}" -f $($ComputerName -join ', '), $localModule.Version.ToString() | Trace-Output -Level:Verbose
# make sure that in instances where we might be on a node within the sdn dataplane,
# that we do not remove the module locally
foreach ($computer in $ComputerName) {
if (Test-ComputerNameIsLocal -ComputerName $computer) {
"Detected that {0} is local machine. Skipping update operation for {0}." -f $computer | Trace-Output -Level:Warning
"Detected that {0} is local machine. Skipping update operation for {0}." -f $computer | Trace-Output -Level:Verbose
continue
}
@ -65,24 +76,23 @@ function Install-SdnDiagnostics {
# check to see if the current version is already present on the remote computers
# else if we -Force defined, we can just move forward
if ($Force) {
"{0} will be installed on all computers" -f $localModule.Version.ToString() | Trace-Output
$installNodes = $filteredComputerName
}
else {
"Getting current installed version of SdnDiagnostics on {0}" -f ($filteredComputerName -join ', ') | Trace-Output
$remoteModuleVersion = Invoke-PSRemoteCommand -ComputerName $filteredComputerName -Credential $Credential -ScriptBlock {
"Getting current installed version of SdnDiagnostics on {0}" -f ($filteredComputerName -join ', ') | Trace-Output -Level:Verbose
$remoteModuleVersion = Invoke-PSRemoteCommand -ComputerName $filteredComputerName -Credential $Credential -ImportModuleOnRemoteSession:$false -ScriptBlock {
param ([string]$arg0)
try {
# Get the latest version of SdnDiagnostics Module installed
$version = (Get-Module -Name SdnDiagnostics -ListAvailable -ErrorAction SilentlyContinue | Sort-Object Version -Descending)[0].Version.ToString()
$version = (Get-Module -Name $arg0 -ListAvailable -ErrorAction SilentlyContinue | Sort-Object Version -Descending)[0].Version.ToString()
}
catch {
# in some instances, the module will not be available and as such we want to skip the noise and return
# a string back to the remote call command which we can do proper comparison against
$version = '0.0.0.0'
}
return $version
}
} -ArgumentList @($moduleName)
# enumerate the versions returned for each computer and compare with current module version to determine if we should perform an update
foreach ($computer in ($remoteModuleVersion.PSComputerName | Sort-Object -Unique)) {
@ -104,34 +114,22 @@ function Install-SdnDiagnostics {
}
if ($updateRequired) {
"{0} will be updated to {1}" -f $computer, $localModule.Version.ToString() | Trace-Output
[void]$installNodes.Add($computer)
}
}
}
if (-NOT $installNodes) {
"All computers are up to date with version {0}. No update required" -f $localModule.Version.ToString() | Trace-Output
return
if ($installNodes) {
"SdnDiagnostics {0} will be installed to {1}" -f $localModule.Version.ToString(), ($filteredComputerName -join ', ') | Trace-Output
Copy-FileToRemoteComputer -Path $localModule.ModuleBase -ComputerName $installNodes -Destination $destinationPathDir -Credential $Credential -Recurse -Force
# ensure that we destroy the current pssessions for the computer to prevent any caching issues
# we will want to remove any existing PSSessions for the remote computers
Remove-PSRemotingSession -ComputerName $installNodes
}
# clean up the module directory on remote computers
"Cleaning up SdnDiagnostics in remote Windows PowerShell Module directory" | Trace-Output
Invoke-PSRemoteCommand -ComputerName $installNodes -Credential $Credential -ScriptBlock {
$modulePath = 'C:\Program Files\WindowsPowerShell\Modules\SdnDiagnostics'
if (Test-Path -Path $modulePath -PathType Container) {
Remove-Item -Path $modulePath -Recurse -Force
}
else {
"No update is required" | Trace-Output -Level:Verbose
}
# copy the module base directory to the remote computers
# currently hardcoded to machine's module path. Use the discussion at https://github.com/microsoft/SdnDiagnostics/discussions/68 to get requirements and improvement
Copy-FileToRemoteComputer -Path $localModule.ModuleBase -ComputerName $installNodes -Destination $destinationPathDir.FullName -Credential $Credential -Recurse -Force
# ensure that we destroy the current pssessions for the computer to prevent any caching issues
# we want to target all the original computers, as may be possible that we running on a node within the sdn fabric
# and have existing PSSession to itself from previous execution run
Remove-PSRemotingSession -ComputerName $ComputerName
}
catch {
"{0}`n{1}" -f $_.Exception, $_.ScriptStackTrace | Trace-Output -Level:Error

Просмотреть файл

@ -1,4 +1,4 @@
Describe 'NetworkController test' {
Describe 'NetworkController test' {
BeforeAll {
Mock -ModuleName SdnDiagnostics Get-SdnResource {
return $Global:PesterOfflineTests.SdnApiResources[$ResourceType.ToString()]
@ -13,6 +13,6 @@ Describe 'NetworkController test' {
It "Get-SdnServer should return Server resource" {
$servers = Get-SdnServer "https://sdnexpnc"
$servers.Count | Should -BeGreaterThan 0
$servers[0].resourceRef | Should -Not -BeNullOrEmpty
$servers[0].resourceRef | Should -Not -BeNullOrEmpty
}
}
}