Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 1 addition & 19 deletions .github/Dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,4 @@ updates:
commit-message:
prefix: "ci"
include: "scope"
open-pull-requests-limit: 5

# Monitor PowerShell modules (via manifest)
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"
- "powershell"
commit-message:
prefix: "deps"
include: "scope"
open-pull-requests-limit: 5
ignore:
# PScribo updates should be reviewed manually
- dependency-name: "PScribo"
update-types: ["version-update:semver-major"]
open-pull-requests-limit: 5
2 changes: 1 addition & 1 deletion .github/workflows/PSScriptAnalyzer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
name: Run PSScriptAnalyzer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: lint
uses: alagoutte/github-action-psscriptanalyzer@master
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
publish-to-gallery:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Set PSRepository to Trusted for PowerShell Gallery
shell: pwsh
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
name: PSScriptAnalyzer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Run PSScriptAnalyzer
uses: microsoft/psscriptanalyzer-action@v1.1
Expand All @@ -44,6 +44,6 @@ jobs:

# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump Diagrammer.Core module requirement to v0.2.36
- Bump module version to v0.6.12
- Update github actions to use latest version

### Fixed

- Fix snapshot reserve space health check to use correct calculation method
- Enhance Get-AbrOntapNodesSP function with detailed service-processor information
- Fix model property assignment in Get-AbrOntapStorageAggrDiagram function
- Fix Volume SnapShot Configuration section showing healthcheck for non violated item
- Fix CodeQL analysis issues 27

### Removed

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ The ONTAP Storage As Built Report supports the following ONTAP versions;

This report is compatible with the following PowerShell versions;

| PowerShell 5.1 | PowerShell 7 |
| :----------------: | :----------------: |
| :white_check_mark: | :white_check_mark: |
| PowerShell 5.1 | PowerShell 7 |
| :------------: | :----------------: |
| :x: | :white_check_mark: |

## :wrench: System Requirements

Expand All @@ -74,7 +74,7 @@ These modules may also be manually installed.

### PowerShell

Open a PowerShell terminal window and install each of the required modules as follows;
Open a PowerShell 7 terminal window and install each of the required modules as follows;

```powershell
Install-Module -Name AsBuiltReport.NetApp.ONTAP
Expand Down
41 changes: 22 additions & 19 deletions Src/Private/Get-AbrOntapCluster.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,28 @@ function Get-AbrOntapCluster {
try {
$ClusterInfo = Get-NcCluster -Controller $Array
if ($ClusterInfo) {
$ClusterDiag = Get-NcDiagnosisStatus -Controller $Array
$ClusterVersion = Get-NcSystemVersion -Controller $Array
$ArrayAggr = Get-NcAggr -Controller $Array
$ArrayVolumes = Get-NcVol -Controller $Array
$ClusterSummary = [PSCustomObject] @{
'Cluster Name' = $ClusterInfo.ClusterName
'Cluster UUID' = $ClusterInfo.ClusterUuid
'Cluster Serial' = $ClusterInfo.ClusterSerialNumber
'Cluster Controller' = $ClusterInfo.NcController
'Cluster Contact' = $ClusterInfo.ClusterContact
'Cluster Location' = $ClusterInfo.ClusterLocation
'Ontap Version' = $ClusterVersion.value
'Number of Aggregates' = $ArrayAggr.count
'Number of Volumes' = $ArrayVolumes.count
'Overall System Health' = ${ClusterDiag}?.Status?.ToUpper()
$OutObj = @()
try {
$inObj = [ordered] @{
'Cluster Name' = $ClusterInfo.ClusterName
'Cluster UUID' = $ClusterInfo.ClusterUuid
'Cluster Serial' = $ClusterInfo.ClusterSerialNumber
'Cluster Controller' = $ClusterInfo.NcController
'Cluster Contact' = $ClusterInfo.ClusterContact ?? '--'
'Cluster Location' = $ClusterInfo.ClusterLocation ?? '--'
'Ontap Version' = (Get-NcSystemVersion -Controller $Array).value ?? 'Unknown'
'Number of Aggregates' = (Get-NcAggr -Controller $Array).count ?? 'Unknown'
'Number of Volumes' = (Get-NcVol -Controller $Array).count ?? 'Unknown'
'Overall System Health' = (Get-NcDiagnosisStatus -Controller $Array).Status?.ToUpper() ?? 'Unknown'
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}

if ($Healthcheck.Cluster.Summary) {
$ClusterSummary | Where-Object { $_.'Overall System Health' -like 'OK' } | Set-Style -Style OK -Property 'Overall System Health'
$ClusterSummary | Where-Object { $_.'Overall System Health' -notlike 'OK' } | Set-Style -Style Critical -Property 'Overall System Health'
$OutObj | Where-Object { $_.'Overall System Health' -like 'OK' } | Set-Style -Style OK -Property 'Overall System Health'
$OutObj | Where-Object { $_.'Overall System Health' -notlike 'OK' } | Set-Style -Style Critical -Property 'Overall System Health'
}

$TableParams = @{
Expand All @@ -55,8 +58,8 @@ function Get-AbrOntapCluster {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$ClusterSummary | Table @TableParams
if ($Healthcheck.Cluster.Summary -and ($ClusterSummary | Where-Object { $_.'Overall System Health' -notlike 'OK' })) {
$OutObj | Table @TableParams
if ($Healthcheck.Cluster.Summary -and ($OutObj | Where-Object { $_.'Overall System Health' -notlike 'OK' })) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
Expand Down
22 changes: 12 additions & 10 deletions Src/Private/Get-AbrOntapClusterHA.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,27 @@ function Get-AbrOntapClusterHA {
try {
$NodeSum = Get-NcNode -Controller $Array | Where-Object { $null -ne $_.NodeModel }
if ($NodeSum) {
$NodeSummary = foreach ($Nodes in $NodeSum) {
$OutObj = @()
foreach ($Nodes in $NodeSum) {
try {
$ClusterHa = Get-NcClusterHa -Node $Nodes.Node -Controller $Array
[PSCustomObject] @{
$inObj = [ordered] @{
'Name' = $Nodes.Node
'Partner' = $ClusterHa.Partner ?? '--'
'TakeOver Possible' = $ClusterHa.TakeoverPossible
'TakeOver State' = $ClusterHa.TakeoverState ?? '--'
'HA Mode' = $ClusterHa.CurrentMode
'HA State' = $ClusterHa.State
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Cluster.HA) {
$NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' } | Set-Style -Style Warning -Property 'TakeOver State'
$NodeSummary | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' } | Set-Style -Style Warning -Property 'HA State'
$NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' } | Set-Style -Style Warning -Property 'TakeOver Possible'
$OutObj | Where-Object { $_.'TakeOver State' -like 'in_takeover' } | Set-Style -Style Warning -Property 'TakeOver State'
$OutObj | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' } | Set-Style -Style Warning -Property 'HA State'
$OutObj | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' } | Set-Style -Style Warning -Property 'TakeOver Possible'
}

$TableParams = @{
Expand All @@ -55,25 +57,25 @@ function Get-AbrOntapClusterHA {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$NodeSummary | Table @TableParams
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' }))) {
$OutObj | Table @TableParams
if ($Healthcheck.Cluster.HA -and (($OutObj | Where-Object { $_.'TakeOver State' -like 'in_takeover' } ) -or ($OutObj | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) -or ($OutObj | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' }))) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
if ($NodeSummary | Where-Object { $_.'TakeOver State' -like 'in_takeover' }) {
if ($OutObj | Where-Object { $_.'TakeOver State' -like 'in_takeover' }) {
Paragraph {
Text 'Best Practice:' -Bold
Text 'One or more nodes are currently in takeover state. It is recommended to investigate the cause of the takeover and ensure that the affected node is restored to normal operation as soon as possible.'
}
BlankLine
}
if ($NodeSummary | Where-Object { $_.'TakeOver Possible' -eq 'No' }) {
if ($OutObj | Where-Object { $_.'TakeOver Possible' -eq 'No' }) {
Paragraph {
Text 'Best Practice:' -Bold
Text 'One or more nodes have takeover capability disabled. It is recommended to enable storage failover capability to ensure high availability in case of node failures.'
}
BlankLine
}
if ($NodeSummary | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) {
if ($OutObj | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) {
Paragraph {
Text 'Best Practice:' -Bold
Text 'One or more nodes are operating in HA mode and are not connected. It is recommended to verify the HA configuration and connectivity to ensure high availability is properly set up.'
Expand Down
15 changes: 8 additions & 7 deletions Src/Private/Get-AbrOntapClusterLicense.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ function Get-AbrOntapClusterLicense {
$License = Get-NcLicense -Owner $Node -Controller $Array
if ($License) {
Section -Style Heading3 "$Node License Usage" {
$LicenseSummary = foreach ($Licenses in $License) {
$EntitlementRisk = try { Get-NcLicenseEntitlementRisk -Package $Licenses.Package -Controller $Array -ErrorAction SilentlyContinue } catch { Write-PScriboMessage -IsWarning $_.Exception.Message }
[PSCustomObject] @{
$OutObj = @()
foreach ($Licenses in $License) {
$inObj = [ordered] @{
'License' = $TextInfo.ToTitleCase($Licenses.Package)
'Type' = $TextInfo.ToTitleCase($Licenses.Type)
'Description' = $Licenses.Description
'Risk' = (Get-NcLicenseEntitlementRisk -Package $Licenses.Package -Controller $Array).Risk ?? '--'
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
if ($Healthcheck.License.RiskSummary) {
$LicenseSummary | Where-Object { $_.'Risk' -like 'medium' -or $_.'Risk' -like 'unknown' -or $_.'Risk' -like 'unlicensed' } | Set-Style -Style Warning -Property 'Risk'
$LicenseSummary | Where-Object { $_.'Risk' -like 'High' } | Set-Style -Style Critical -Property 'Risk'
$OutObj | Where-Object { $_.'Risk' -like 'medium' -or $_.'Risk' -like 'unknown' -or $_.'Risk' -like 'unlicensed' } | Set-Style -Style Warning -Property 'Risk'
$OutObj | Where-Object { $_.'Risk' -like 'High' } | Set-Style -Style Critical -Property 'Risk'
}
$TableParams = @{
Name = "License Usage - $($Node)"
Expand All @@ -51,8 +52,8 @@ function Get-AbrOntapClusterLicense {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$LicenseSummary | Table @TableParams
if ($Healthcheck.License.RiskSummary -and ($LicenseSummary | Where-Object { $_.'Risk' -like 'medium' -or $_.'Risk' -like 'unknown' -or $_.'Risk' -like 'unlicensed' }) -or ($LicenseSummary | Where-Object { $_.'Risk' -like 'High' })) {
$OutObj | Table @TableParams
if ($Healthcheck.License.RiskSummary -and ($OutObj | Where-Object { $_.'Risk' -like 'medium' -or $_.'Risk' -like 'unknown' -or $_.'Risk' -like 'unlicensed' }) -or ($OutObj | Where-Object { $_.'Risk' -like 'High' })) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
Expand Down
8 changes: 5 additions & 3 deletions Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ function Get-AbrOntapClusterLicenseUsage {
try {
$LicenseFeature = Get-NcFeatureStatus -Controller $Array
if ($LicenseFeature) {
$LicenseFeature = foreach ($NodeLFs in $LicenseFeature) {
[PSCustomObject] @{
$OutObj = @()
foreach ($NodeLFs in $LicenseFeature) {
$inObj = [ordered] @{
'Name' = $NodeLFs.FeatureName
'Status' = $NodeLFs.Status
'Notes' = $NodeLFs.Notes
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
$TableParams = @{
Name = "License Feature - $($ClusterInfo.ClusterName)"
Expand All @@ -41,7 +43,7 @@ function Get-AbrOntapClusterLicenseUsage {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$LicenseFeature | Table @TableParams
$OutObj | Table @TableParams
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
Expand Down
8 changes: 5 additions & 3 deletions Src/Private/Get-AbrOntapDiskAssign.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ function Get-AbrOntapDiskAssign {
try {
$NodeDiskCount = Get-NcDisk -Controller $Array | ForEach-Object { $_.DiskOwnershipInfo.HomeNodeName } | Group-Object
if ($NodeDiskCount) {
$DiskSummary = foreach ($Disks in $NodeDiskCount) {
[PSCustomObject] @{
$OutObj = @()
foreach ($Disks in $NodeDiskCount) {
$inObj = [ordered] @{
'Node' = $Disks.Name
'Disk Count' = $Disks | Select-Object -ExpandProperty Count
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
$TableParams = @{
Name = "Assigned Disk - $($ClusterInfo.ClusterName)"
Expand All @@ -40,7 +42,7 @@ function Get-AbrOntapDiskAssign {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$DiskSummary | Table @TableParams
$OutObj | Table @TableParams
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
Expand Down
12 changes: 7 additions & 5 deletions Src/Private/Get-AbrOntapDiskBroken.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ function Get-AbrOntapDiskBroken {
try {
$NodeDiskBroken = Get-NcDisk -Controller $Array | Where-Object { $_.DiskRaidInfo.ContainerType -eq 'broken' }
if ($NodeDiskBroken) {
$DiskFailed = foreach ($DiskBroken in $NodeDiskBroken) {
[PSCustomObject] @{
$OutObj = @()
foreach ($DiskBroken in $NodeDiskBroken) {
$inObj = [ordered] @{
'Disk Name' = $DiskBroken.Name
'Shelf' = $DiskBroken.Shelf
'Bay' = $DiskBroken.Bay
'Pool' = $DiskBroken.Pool
'Disk Paths' = $DiskBroken.DiskPaths
}
$OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
if ($Healthcheck.Storage.DiskStatus) {
$DiskFailed | Set-Style -Style Critical -Property 'Disk Name', 'Shelf', 'Bay', 'Pool', 'Disk Paths'
$OutObj | Set-Style -Style Critical -Property 'Disk Name', 'Shelf', 'Bay', 'Pool', 'Disk Paths'
}
$TableParams = @{
Name = "Failed Disk - $($ClusterInfo.ClusterName)"
Expand All @@ -46,8 +48,8 @@ function Get-AbrOntapDiskBroken {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$DiskFailed | Table @TableParams
if ($Healthcheck.Storage.DiskStatus -and ($DiskFailed)) {
$OutObj | Table @TableParams
if ($Healthcheck.Storage.DiskStatus -and ($OutObj)) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
Expand Down
Loading