Skip to content

Commit ce3e669

Browse files
committed
Bump module version to 0.6.12 and update changelog with health check best practices for NTP and network broadcast domains
1 parent d10326d commit ce3e669

8 files changed

+243
-11
lines changed

AsBuiltReport.NetApp.ONTAP.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
RootModule = 'AsBuiltReport.NetApp.ONTAP.psm1'
1313

1414
# Version number of this module.
15-
ModuleVersion = '0.6.11'
15+
ModuleVersion = '0.6.12'
1616

1717
# Supported PSEditions
1818
# CompatiblePSEditions = @()

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.6.12] - Unreleased
9+
10+
### Added
11+
12+
- Add Health Check best practices for Network Broadcast Domains
13+
- Add Health Check best practices for NTP configuration
14+
- Recommend multiple NTP servers for redundancy
15+
16+
### Fixed
17+
18+
- Fix snapshot reserve space health check to use correct calculation method
19+
820
## [0.6.11] - 2025-11-07
921

1022
### Added

Src/Private/Get-AbrOntapClusterHA.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Get-AbrOntapClusterHA {
55
.DESCRIPTION
66
77
.NOTES
8-
Version: 0.6.9
8+
Version: 0.6.12
99
Author: Jonathan Colon
1010
Twitter: @jcolonfzenpr
1111
Github: rebelinux
@@ -51,8 +51,8 @@ function Get-AbrOntapClusterHA {
5151
}
5252
if ($Healthcheck.Cluster.HA) {
5353
$NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' } | Set-Style -Style Warning -Property 'TakeOver State'
54-
$NodeSummary | Where-Object { $_.'HA Mode' -eq 'non_ha' -and $_.'HA State' -notlike 'connected' } | Set-Style -Style Warning -Property 'HA State'
55-
$NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' } | Set-Style -Style Warning -Property 'TakeOver Possible'
54+
$NodeSummary | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' } | Set-Style -Style Warning -Property 'HA State'
55+
$NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' } | Set-Style -Style Warning -Property 'TakeOver Possible'
5656
}
5757

5858
$TableParams = @{
@@ -64,7 +64,7 @@ function Get-AbrOntapClusterHA {
6464
$TableParams['Caption'] = "- $($TableParams.Name)"
6565
}
6666
$NodeSummary | Table @TableParams
67-
if ($Healthcheck.Cluster.HA -and (($NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' } ) -or ($NodeSummary | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) -or ($NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' }))) {
67+
if ($Healthcheck.Cluster.HA -and (($NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' } ) -or ($NodeSummary | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) -or ($NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' }))) {
6868
Paragraph "Health Check:" -Bold -Underline
6969
BlankLine
7070
if ($NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' }) {

Src/Private/Get-AbrOntapNetworkBdomain.ps1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkBdomain {
55
.DESCRIPTION
66
77
.NOTES
8-
Version: 0.6.7
8+
Version: 0.6.12
99
Author: Jonathan Colon
1010
Twitter: @jcolonfzenpr
1111
Github: rebelinux
@@ -38,6 +38,10 @@ function Get-AbrOntapNetworkBdomain {
3838
$BDomainObj += [pscustomobject]$inobj
3939
}
4040

41+
if ($Healthcheck.Network.Port) {
42+
$BDomainObj | Where-Object { $null -eq $_.'Failover Groups' -and $null -eq $_.'Ports' } | Set-Style -Style Warning
43+
}
44+
4145
$TableParams = @{
4246
Name = "Network Broadcast Domain - $($ClusterInfo.ClusterName)"
4347
List = $false
@@ -47,6 +51,15 @@ function Get-AbrOntapNetworkBdomain {
4751
$TableParams['Caption'] = "- $($TableParams.Name)"
4852
}
4953
$BDomainObj | Table @TableParams
54+
if ($Healthcheck.Network.Port -and ($BDomainObj | Where-Object { $null -eq $_.'Failover Groups' -and $null -eq $_.'Ports' })) {
55+
Paragraph "Health Check:" -Bold -Underline
56+
BlankLine
57+
Paragraph {
58+
Text "Best Practice:" -Bold
59+
Text " Broadcast Domains should have associated Failover Groups and Ports assigned to them, review the highlighted Broadcast Domains above and take corrective action as necessary."
60+
}
61+
BlankLine
62+
}
5063
}
5164
} catch {
5265
Write-PScriboMessage -IsWarning $_.Exception.Message
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
function Get-AbrOntapNodeNetworkDiagram {
2+
<#
3+
.SYNOPSIS
4+
Used by As Built Report to built NetApp ONTAP node network diagram
5+
.DESCRIPTION
6+
7+
.NOTES
8+
Version: 0.6.12
9+
Author: Jonathan Colon
10+
Twitter: @jcolonfzenpr
11+
Github: rebelinux
12+
.EXAMPLE
13+
14+
.LINK
15+
16+
#>
17+
[CmdletBinding()]
18+
param (
19+
)
20+
21+
begin {
22+
Write-PScriboMessage "Generating Node Network Diagram for NetApp ONTAP."
23+
# Used for DiagramDebug
24+
if ($Options.EnableDiagramDebug) {
25+
$EdgeDebug = @{style = 'filled'; color = 'red' }
26+
$SubGraphDebug = @{style = 'dashed'; color = 'red' }
27+
$NodeDebug = @{color = 'black'; style = 'red'; shape = 'plain' }
28+
$NodeDebugEdge = @{color = 'black'; style = 'red'; shape = 'plain' }
29+
$IconDebug = $true
30+
} else {
31+
$EdgeDebug = @{style = 'invis'; color = 'red' }
32+
$SubGraphDebug = @{style = 'invis'; color = 'gray' }
33+
$NodeDebug = @{color = 'transparent'; style = 'transparent'; shape = 'point' }
34+
$NodeDebugEdge = @{color = 'transparent'; style = 'transparent'; shape = 'none' }
35+
$IconDebug = $false
36+
}
37+
38+
if ($Options.DiagramTheme -eq 'Black') {
39+
$Edgecolor = 'White'
40+
$Fontcolor = 'White'
41+
} elseif ($Options.DiagramTheme -eq 'Neon') {
42+
$Edgecolor = 'gold2'
43+
$Fontcolor = 'gold2'
44+
} else {
45+
$Edgecolor = '#71797E'
46+
$Fontcolor = '#565656'
47+
}
48+
}
49+
50+
process {
51+
try {
52+
$ClusterInfo = Get-NcCluster -Controller $Array
53+
$NodeSum = Get-NcNode -Controller $Array
54+
55+
try {
56+
57+
if ($NodeSum.Count -eq 1) {
58+
$NodeSumColumnSize = 1
59+
} elseif ($ColumnSize) {
60+
$NodeSumColumnSize = $ColumnSize
61+
} else {
62+
$NodeSumColumnSize = $NodeSum.Count
63+
}
64+
65+
$HAObject = @()
66+
67+
$NodeAdditionalInfo = @()
68+
$AggrInfo = @()
69+
70+
foreach ($Node in $NodeSum) {
71+
$ClusterHa = Get-NcClusterHa -Node $Node.Node -Controller $Array
72+
73+
$NodeMgmtAddress = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'node_mgmt' -and $_.HomeNode -eq $Node.Node } | Select-Object -ExpandProperty Address
74+
$NodeInterClusterAddress = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'intercluster' -and $_.HomeNode -eq $Node.Node } | Select-Object -ExpandProperty Address
75+
76+
if ($ClusterHa.Name -notin $HAObject.Partner) {
77+
$HAObject += [PSCustomObject][ordered]@{
78+
"Name" = $ClusterHa.Name
79+
"Partner" = $ClusterHa.Partner
80+
"HAState" = $ClusterHa.State
81+
}
82+
}
83+
84+
$NodeAdditionalInfo += [PSCustomObject][ordered]@{
85+
'NodeName' = $Node.Node
86+
'AdditionalInfo' = [PSCustomObject][ordered]@{
87+
"System Id" = $Node.NodeSystemId
88+
"Serial" = $Node.NodeSerialNumber
89+
"Model" = $Node.NodeSerialNumber
90+
"Mgmt" = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
91+
$true { "Unknown" }
92+
$false { $NodeMgmtAddress }
93+
default { "Unknown" }
94+
}
95+
}
96+
}
97+
98+
$NodeAggr = Get-NcAggr | Where-Object { $_.Nodes -eq $Node.Node }
99+
foreach ($Aggr in $NodeAggr) {
100+
$AggrInfo += [PSCustomObject][ordered]@{
101+
"NodeName" = $Node.Node
102+
"AggregateName" = $Aggr.Name
103+
"AdditionalInfo" = [PSCustomObject][ordered]@{
104+
"Total Size" = $Aggr.TotalSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
105+
"Used Space" = ($Aggr.TotalSize - $Aggr.Available) | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
106+
"Assigned Disk" = $Aggr.Disks
107+
"Raid Type" = switch ([string]::IsNullOrEmpty($Aggr.RaidType)) {
108+
$true { "Unknown" }
109+
$false {
110+
& {
111+
switch ($Aggr.RaidType.Split(", ")[0]) {
112+
"raid4" { "RAID 4" }
113+
"raid_dp" { "RAID DP" }
114+
"raid0" { "RAID 0" }
115+
"raid1" { "RAID 1" }
116+
"raid10" { "RAID 10" }
117+
default { "Unknown" }
118+
}
119+
}
120+
}
121+
default { "Unknown" }
122+
}
123+
"Raid Size" = $Aggr.RaidSize
124+
"State" = switch ([string]::IsNullOrEmpty($Aggr.State)) {
125+
$true { "Unknown" }
126+
$false { $Aggr.State.ToUpper() }
127+
default { "Unknown" }
128+
}
129+
}
130+
}
131+
}
132+
}
133+
134+
$ClusterNodesObj = @()
135+
136+
foreach ($Node in $NodeAdditionalInfo) {
137+
$ClusterNodeObj = @()
138+
$ClusterNodeObj += Add-DiaHtmlNodeTable -ImagesObj $Images -inputObject $Node.NodeName -Align "Center" -iconType "Ontap_Node" -ColumnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $Node.AdditionalInfo -Subgraph -SubgraphLabel $Node.NodeName -SubgraphLabelPos "top" -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder 0 -SubgraphLabelFontSize 22 -FontSize 18
139+
140+
if ($ClusterNodeObj) {
141+
if ($AggrInfo.Count -eq 1) {
142+
$AggrInfoColumnSize = 1
143+
} elseif ($ColumnSize) {
144+
$AggrInfoColumnSize = $ColumnSize
145+
} else {
146+
$AggrInfoColumnSize = $AggrInfo.Count
147+
}
148+
$ClusterNodeObj += Add-DiaHtmlNodeTable -ImagesObj $Images -inputObject ($AggrInfo | Where-Object { $_.NodeName -eq $Node.Nodename }).AggregateName -Align "Center" -iconType "Ontap_Aggregate" -ColumnSize $AggrInfoColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo ($AggrInfo | Where-Object { $_.NodeName -eq $Node.Nodename }).AdditionalInfo -Subgraph -SubgraphLabel "Aggregates" -SubgraphLabelPos "top" -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder 1 -SubgraphLabelFontSize 22 -FontSize 18
149+
}
150+
151+
if ($ClusterNodeObj) {
152+
$ClusterNodeSubgraphObj = Add-DiaHtmlSubGraph -ImagesObj $Images -TableArray $ClusterNodeObj -Align 'Center' -IconDebug $IconDebug -Label " " -LabelPos 'top' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder 1 -ColumnSize 1 -FontSize 12
153+
}
154+
155+
$ClusterNodesObj += $ClusterNodeSubgraphObj
156+
}
157+
158+
if ($ClusterNodesObj) {
159+
$Index = 0
160+
foreach ($Node in $ClusterNodesObj) {
161+
162+
$ClusterMgmtObj = Add-DiaHtmlSubGraph -ImagesObj $Images -TableArray $Node -Align 'Right' -IconDebug $IconDebug -Label " " -LabelPos 'down' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder 0 -ColumnSize 1 -FontSize 18
163+
164+
if ($ClusterMgmtObj) {
165+
Node Node$Index @{Label = $ClusterMgmtObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
166+
$Index++
167+
} else {
168+
Write-PScriboMessage -IsWarning "Unable to create ClusterNodesObj. No Cluster Management Object found."
169+
}
170+
}
171+
foreach ($HA in $HAObject) {
172+
Edge -From Node0 -To Node1 @{tailport = $HA.Name; headport = $HA.Partner; minlen = 2; label = "HA: $($HA.HAState)"; color = $Edgecolor; fontcolor = $Fontcolor; fontsize = 16; style = 'solid'; penwidth = 2; arrowhead = 'box'; arrowtail = 'box' }
173+
Rank Node0, Node1
174+
}
175+
}
176+
} catch {
177+
Write-PScriboMessage -IsWarning $_.Exception.Message
178+
}
179+
} catch {
180+
Write-PScriboMessage -IsWarning $_.Exception.Message
181+
}
182+
}
183+
184+
end {}
185+
186+
}

Src/Private/Get-AbrOntapSysConfigNTP.ps1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigNTP {
55
.DESCRIPTION
66
77
.NOTES
8-
Version: 0.6.7
8+
Version: 0.6.12
99
Author: Jonathan Colon
1010
Twitter: @jcolonfzenpr
1111
Github: rebelinux
@@ -41,6 +41,10 @@ function Get-AbrOntapSysConfigNTP {
4141
}
4242
}
4343

44+
if ($Healthcheck.System.NTP) {
45+
$OutObj.Count -eq 1 | Set-Style -Style Warning
46+
}
47+
4448
$TableParams = @{
4549
Name = "Network Time Protocol - $($ClusterInfo.ClusterName)"
4650
List = $false
@@ -50,6 +54,15 @@ function Get-AbrOntapSysConfigNTP {
5054
$TableParams['Caption'] = "- $($TableParams.Name)"
5155
}
5256
$OutObj | Table @TableParams
57+
if ($Healthcheck.System.NTP -and ($OutObj.Count -eq 1)) {
58+
Paragraph "Health Check:" -Bold -Underline
59+
BlankLine
60+
Paragraph {
61+
Text "Best Practice:" -Bold
62+
Text "It is recommended to configure multiple NTP servers for redundancy and reliability."
63+
}
64+
BlankLine
65+
}
5366
} else {
5467
$inObj = [ordered] @{
5568
'Server Name' = 'No NTP Servers Configured'

Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumeSnapshot {
55
.DESCRIPTION
66
77
.NOTES
8-
Version: 0.6.8
8+
Version: 0.6.12
99
Author: Jonathan Colon
1010
Twitter: @jcolonfzenpr
1111
Github: rebelinux
@@ -50,7 +50,7 @@ function Get-AbrOntapVserverVolumeSnapshot {
5050
}
5151
}
5252
if ($Healthcheck.Vserver.Snapshot) {
53-
$VserverObj | Where-Object { $_.'Snapshot Enabled' -eq 'Yes' -and $_.'Reserve Available' -eq 0 } | Set-Style -Style Warning -Property 'Reserve Size', 'Reserve Available', 'Used'
53+
$VserverObj | Where-Object { $_.'Used'.split()[0] -gt $_.'Reserve Size'.split()[0] } | Set-Style -Style Warning -Property 'Reserve Size', 'Reserve Available', 'Used'
5454
}
5555

5656
$TableParams = @{

Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
55
.DESCRIPTION
66
Documents the configuration of NetApp ONTAP in Word/HTML/Text formats using PScribo.
77
.NOTES
8-
Version: 0.6.8
8+
Version: 0.6.12
99
Author: Jonathan Colon Feliciano
1010
Twitter: @jcolonfzenpr
1111
Github: rebelinux
@@ -41,7 +41,8 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
4141
Write-Host "- Documentation: https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP"
4242
Write-Host "- Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/issues"
4343
Write-Host "- This project is community maintained and has no sponsorship from NetApp, its employees or any of its affiliates."
44-
Write-Host "- To sponsor this project, please visit: https://ko-fi.com/F1F8DEV80"
44+
Write-Host "- To sponsor this project, please visit: " -NoNewline
45+
Write-Host "https://ko-fi.com/F1F8DEV80" -ForegroundColor Cyan
4546
Write-Host "- Getting dependency information:"
4647

4748

@@ -264,6 +265,13 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
264265
#---------------------------------------------------------------------------------------------#
265266
Write-PScriboMessage "Network InfoLevel set at $($InfoLevel.Network)."
266267
if ($InfoLevel.Network -gt 0) {
268+
$NetworkDiagram = Get-AbrOntapNodeNetworkDiagram
269+
if ($NetworkDiagram) {
270+
Export-AbrOntapDiagram -DiagramObject $NetworkDiagram -MainDiagramLabel "Networking Diagram" -FileName "AsBuiltReport.NetApp.Ontap.Networking"
271+
BlankLine
272+
} else {
273+
Write-PScriboMessage -IsWarning "Unable to generate the Networking Diagram."
274+
}
267275
Section -Style Heading2 'Network Information' {
268276
Paragraph "The following section provides a summary of the networking features in $($ClusterInfo.ClusterName)."
269277
BlankLine

0 commit comments

Comments
 (0)