diff --git a/.github/Dependabot.yml b/.github/Dependabot.yml
index 244a5f8..ad1a88d 100644
--- a/.github/Dependabot.yml
+++ b/.github/Dependabot.yml
@@ -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"]
\ No newline at end of file
+ open-pull-requests-limit: 5
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 59ad50b..80659e4 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -10,8 +10,7 @@ body:
Thanks for taking the time to fill out this bug report :)
- Kindly **DO NOT** ask for instructions.
- Use [Discussions](https://github.com/orgs/AsBuiltReport/discussions) section if you have a query or doubts or any other relevant question.
- - You may join [Slack community](https://the-code-community.slack.com#asbuiltreport) to interact with fellow contributors and users
- - Read project's [Web Site](https://www.asbuiltreport.com/user-guide/installation/) for detailed documentation.
+ - Read project's [Web Site](https://www.asbuiltreport.com/user-guide/quickstart/) for detailed documentation.
- Read project's [FAQs](https://www.asbuiltreport.com/support/faq/) section for Frequently asked questions.
- Search for previous [Issues](https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/issues)/[Pull Requests](https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/pulls) if this issue is already reported or fix has been created.
- type: textarea
@@ -99,3 +98,10 @@ body:
- label: >-
I have read and followed the [bug reporting guidelines](https://www.asbuiltreport.com/about/contributing/#reporting-issues-and-bugs).
required: true
+ - label: >-
+ I have read [the documentation](https://www.asbuiltreport.com/user-guide/new-asbuiltreport),
+ and referred to the [known issues](https://www.asbuiltreport.com/support/known-issues/) before submitting this bug report.
+ required: true
+ - label: >-
+ I have checked for previously opened & closed [issues](https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/issues) before submitting this bug report.
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/change_request.yml b/.github/ISSUE_TEMPLATE/change_request.yml
index 4f6c670..b6b14bc 100644
--- a/.github/ISSUE_TEMPLATE/change_request.yml
+++ b/.github/ISSUE_TEMPLATE/change_request.yml
@@ -26,9 +26,9 @@ body:
If you are unsure of what a specific requirement means, please follow the links to learn about it and understand why it is necessary before submitting.
options:
- label: >-
- I have read [the documentation](https://www.asbuiltreport.com/user-guide/new-asbuiltconfig),
- and referred to the [known issues](https://www.asbuiltreport.com/user-guide/known-issues/) before submitting this change request.
+ I have read [the documentation](https://www.asbuiltreport.com/user-guide/quickstart/),
+ and referred to the [known issues](https://www.asbuiltreport.com/support/known-issues/) before submitting this change request.
required: true
- label: >-
I have checked for previously opened & closed [issues](https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/issues) before submitting this change request.
- required: true
+ required: true
\ No newline at end of file
diff --git a/.github/workflows/PSScriptAnalyzer.yml b/.github/workflows/PSScriptAnalyzer.yml
index a73694f..700425b 100755
--- a/.github/workflows/PSScriptAnalyzer.yml
+++ b/.github/workflows/PSScriptAnalyzer.yml
@@ -1,17 +1,17 @@
name: PSScriptAnalyzer
on: [push, pull_request]
jobs:
- lint:
- name: Run PSScriptAnalyzer
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v5
- - name: lint
- uses: devblackops/github-action-psscriptanalyzer@master
- with:
- sendComment: true
- failOnErrors: true
- failOnWarnings: false
- failOnInfos: false
- repoToken: ${{ secrets.GITHUB_TOKEN }}
- settingsPath: .github/workflows/PSScriptAnalyzerSettings.psd1
\ No newline at end of file
+ lint:
+ name: Run PSScriptAnalyzer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+ - name: lint
+ uses: alagoutte/github-action-psscriptanalyzer@master
+ with:
+ sendComment: true
+ failOnErrors: true
+ failOnWarnings: false
+ failOnInfos: false
+ repoToken: ${{ secrets.GITHUB_TOKEN }}
+ settingsPath: .github/workflows/PSScriptAnalyzerSettings.psd1
diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml
index 67069b2..4ff1129 100644
--- a/.github/workflows/Release.yml
+++ b/.github/workflows/Release.yml
@@ -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: |
@@ -21,18 +21,18 @@ jobs:
shell: pwsh
run: |
Install-Module -Name NetApp.ONTAP -Repository PSGallery -Force
- - name: Install Diagrammer.Core module
+ - name: Install AsBuiltReport.Diagram module
shell: pwsh
run: |
- Install-Module -Name Diagrammer.Core -Repository PSGallery -Force
+ Install-Module -Name AsBuiltReport.Diagram -Repository PSGallery -Force
- name: Test Module Manifest
shell: pwsh
run: |
- Test-ModuleManifest .\AsBuiltReport.NetApp.ONTAP.psd1
+ Test-ModuleManifest .\AsBuiltReport.NetApp.ONTAP\AsBuiltReport.NetApp.ONTAP.psd1
- name: Publish module to PowerShell Gallery
shell: pwsh
run: |
- Publish-Module -Path ./ -NuGetApiKey ${{ secrets.PSGALLERY_API_KEY }} -Verbose
+ Publish-Module -Path ./AsBuiltReport.NetApp.ONTAP -NuGetApiKey ${{ secrets.PSGALLERY_API_KEY }} -Verbose
tweet:
needs: publish-to-gallery
runs-on: ubuntu-latest
@@ -58,4 +58,4 @@ jobs:
post: "[New Release] ${{ github.event.repository.name }} ${{ github.event.release.tag_name }}! Check out what's new! ${{ github.event.release.html_url }} #Netapp #AsBuiltReport #PowerShell #Ontap #NetAppATeam"
env:
BSKY_IDENTIFIER: ${{ secrets.BSKY_IDENTIFIER }}
- BSKY_PASSWORD: ${{ secrets.BSKY_PASSWORD }}
\ No newline at end of file
+ BSKY_PASSWORD: ${{ secrets.BSKY_PASSWORD }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index a2aeb0f..c944b8c 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -10,40 +10,40 @@
name: CodeQL
on:
- push:
- branches: [ "dev" ]
- pull_request:
- branches: [ "dev" ]
- schedule:
- - cron: '20 14 * * 1'
+ push:
+ branches: ["dev"]
+ pull_request:
+ branches: ["dev"]
+ schedule:
+ - cron: "20 14 * * 1"
permissions:
- contents: read
+ contents: read
jobs:
- build:
- permissions:
- contents: read # for actions/checkout to fetch code
- security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
- actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
- name: PSScriptAnalyzer
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v5
+ build:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: PSScriptAnalyzer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
- - name: Run PSScriptAnalyzer
- uses: microsoft/psscriptanalyzer-action@v1.1
- with:
- # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options.
- # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules.
- path: .\
- recurse: true
- # Include your own basic security rules. Removing this option will run all the rules
- excludeRule: '"PSAvoidUsingPlainTextForPassword", "PSAvoidUsingUsernameAndPasswordParams", "PSAvoidUsingConvertToSecureStringWithPlainText"'
- output: results.sarif
+ - name: Run PSScriptAnalyzer
+ uses: microsoft/psscriptanalyzer-action@v1.1
+ with:
+ # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options.
+ # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules.
+ path: .\
+ recurse: true
+ # Include your own basic security rules. Removing this option will run all the rules
+ excludeRule: '"PSAvoidUsingPlainTextForPassword", "PSAvoidUsingUsernameAndPasswordParams", "PSAvoidUsingConvertToSecureStringWithPlainText"'
+ output: results.sarif
- # Upload the SARIF file generated in the previous step
- - name: Upload SARIF results file
- uses: github/codeql-action/upload-sarif@v3
- with:
- sarif_file: results.sarif
+ # Upload the SARIF file generated in the previous step
+ - name: Upload SARIF results file
+ uses: github/codeql-action/upload-sarif@v4
+ with:
+ sarif_file: results.sarif
diff --git a/AsBuiltReport.NetApp.ONTAP.Style.ps1 b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.Style.ps1
similarity index 99%
rename from AsBuiltReport.NetApp.ONTAP.Style.ps1
rename to AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.Style.ps1
index 91ce353..888d644 100755
--- a/AsBuiltReport.NetApp.ONTAP.Style.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.Style.ps1
@@ -74,10 +74,10 @@ if ($Orientation -eq 'Portrait') {
# Cover Page Image
if ($ReportConfig.Report.ShowCoverPageImage) {
- Try {
- Image -Text 'AsBuiltReport Logo' -Align 'Center' -Percent 45 -Base64 "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"
+ try {
+ Image -Text 'AsBuiltReport Logo' -Align 'Center' -Percent 45 -Base64 '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'
BlankLine -Count 1
- } Catch {
+ } catch {
Write-PScriboMessage -IsWarning "Unable to display cover page image. Please set 'ShowCoverPageImage' to 'false' in the report JSON configuration file to avoid this error."
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/AsBuiltReport.NetApp.ONTAP.json b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.json
similarity index 95%
rename from AsBuiltReport.NetApp.ONTAP.json
rename to AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.json
index 73f269f..962878e 100755
--- a/AsBuiltReport.NetApp.ONTAP.json
+++ b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.json
@@ -18,14 +18,15 @@
"DisableDiagramMainLogo": false,
"DiagramTheme": "White",
"DiagramWaterMark": "",
- "ExportDiagrams": false,
+ "ExportDiagrams": true,
"ExportDiagramsFormat": [
- "png"
+ "pdf"
],
"EnableDiagramSignature": false,
"DiagramColumnSize": 4,
"SignatureAuthorName": "",
- "SignatureCompanyName": ""
+ "SignatureCompanyName": "",
+ "UpdateCheck": true
},
"InfoLevel": {
"_comment_": "0 = Disabled, 1 = Enabled, 2 = Adv Summary",
diff --git a/AsBuiltReport.NetApp.ONTAP.psd1 b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.psd1
similarity index 91%
rename from AsBuiltReport.NetApp.ONTAP.psd1
rename to AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.psd1
index 55a542e..aeca4d0 100755
--- a/AsBuiltReport.NetApp.ONTAP.psd1
+++ b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.psd1
@@ -12,7 +12,7 @@
RootModule = 'AsBuiltReport.NetApp.ONTAP.psm1'
# Version number of this module.
- ModuleVersion = '0.6.11'
+ ModuleVersion = '0.6.12'
# Supported PSEditions
# CompatiblePSEditions = @()
@@ -27,7 +27,7 @@
#CompanyName = 'Unknown'
# Copyright statement for this module
- Copyright = '(c) 2025 Jonathan Colon Feliciano. All rights reserved.'
+ Copyright = '(c) 2026 Jonathan Colon Feliciano. All rights reserved.'
# Description of the functionality provided by this module
Description = 'A PowerShell module to generate an as built report on the configuration of NetApp ONTAP.'
@@ -54,15 +54,19 @@
RequiredModules = @(
@{
ModuleName = 'AsBuiltReport.Core';
- ModuleVersion = '1.5.0'
+ ModuleVersion = '1.6.2'
+ },
+ @{
+ ModuleName = 'AsBuiltReport.Chart';
+ ModuleVersion = '0.3.0'
},
@{
ModuleName = 'NetApp.ONTAP';
- ModuleVersion = '9.17.1.2509'
+ ModuleVersion = '9.18.1.2601'
},
@{
- ModuleName = 'Diagrammer.Core';
- ModuleVersion = '0.2.33'
+ ModuleName = 'AsBuiltReport.Diagram';
+ ModuleVersion = '1.0.3'
}
)
@@ -129,7 +133,7 @@
# HelpInfo URI of this module
# HelpInfoURI = ''
- # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+ # Default prefix for commands exported from this module. Override the default prefix using Import-Mod-Prefix.
# DefaultCommandPrefix = ''
}
diff --git a/AsBuiltReport.NetApp.ONTAP.psm1 b/AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.psm1
similarity index 100%
rename from AsBuiltReport.NetApp.ONTAP.psm1
rename to AsBuiltReport.NetApp.ONTAP/AsBuiltReport.NetApp.ONTAP.psm1
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-HashToYN.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-HashToYN.ps1
new file mode 100644
index 0000000..02be54f
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-HashToYN.ps1
@@ -0,0 +1,35 @@
+function ConvertTo-HashToYN {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to convert array content true or false automatically to Yes or No.
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.2.0
+ Author: Jonathan Colon
+
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
+ param (
+ [Parameter (Position = 0, Mandatory)]
+ [AllowEmptyString()]
+ [System.Collections.Specialized.OrderedDictionary] $TEXT
+ )
+
+ $result = [ordered] @{}
+ foreach ($i in $TEXT.GetEnumerator()) {
+ try {
+ $result.add($i.Key, (ConvertTo-TextYN $i.Value))
+ } catch {
+ $result.add($i.Key, ($i.Value))
+ }
+ }
+ if ($result) {
+ return $result
+ } else { return $TEXT }
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-TextYN.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-TextYN.ps1
new file mode 100644
index 0000000..07cd0bf
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/ConvertTo-TextYN.ps1
@@ -0,0 +1,39 @@
+function ConvertTo-TextYN {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to convert true or false automatically to Yes or No.
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.2.0
+ Author: LEE DAILEY
+
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ [OutputType([String])]
+ param
+ (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [AllowEmptyString()]
+ [string]
+ $TEXT
+ )
+
+ switch ([string]::IsNullOrEmpty($TEXT)) {
+ $true { '--' }
+ $false {
+ switch ($TEXT) {
+ 'True' { 'Yes'; break }
+ 'False' { 'No'; break }
+ default { $TEXT }
+ }
+ }
+ default { '--' }
+ }
+} # end
\ No newline at end of file
diff --git a/Src/Private/Export-AbrOntapDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Export-AbrOntapDiagram.ps1
similarity index 82%
rename from Src/Private/Export-AbrOntapDiagram.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Export-AbrOntapDiagram.ps1
index 0bfa14e..a6508ea 100644
--- a/Src/Private/Export-AbrOntapDiagram.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Export-AbrOntapDiagram.ps1
@@ -5,7 +5,7 @@ function Export-AbrOntapDiagram {
.DESCRIPTION
Documents the configuration of NetApp Ontap in Word/HTML/Text formats using PScribo.
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -15,7 +15,7 @@ function Export-AbrOntapDiagram {
https://github.com/AsBuiltReport/AsBuiltReport.NetApp.Ontap
#>
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingCmdletAliases", "", Scope = "Function")]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '', Scope = 'Function')]
[CmdletBinding()]
param (
@@ -31,7 +31,7 @@ function Export-AbrOntapDiagram {
process {
if ($Options.EnableDiagrams) {
- Write-PScriboMessage -Message "Collecting NetApp Ontap Infrastructure diagram"
+ Write-PScriboMessage -Message 'Collecting NetApp Ontap Infrastructure diagram'
$RootPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
[System.IO.FileInfo]$IconPath = Join-Path $RootPath 'icons'
@@ -83,7 +83,7 @@ function Export-AbrOntapDiagram {
}
$DiagramParams.Add('Format', $DiagramFormat)
} else {
- $DiagramParams.Add('Format', "base64")
+ $DiagramParams.Add('Format', 'base64')
}
if ($Options.EnableDiagramDebug) {
@@ -100,11 +100,11 @@ function Export-AbrOntapDiagram {
if ($Options.ExportDiagrams) {
try {
- Write-PScriboMessage -Message "Generating NetApp Ontap diagram"
+ Write-PScriboMessage -Message 'Generating NetApp Ontap diagram'
$Graph = $DiagramObject
if ($Graph) {
- Write-PScriboMessage -Message "Saving NetApp Ontap diagram"
- $Diagram = New-Diagrammer @DiagramParams -InputObject $Graph
+ Write-PScriboMessage -Message 'Saving NetApp Ontap diagram'
+ $Diagram = New-AbrDiagram @DiagramParams -InputObject $Graph
if ($Diagram) {
foreach ($OutputFormat in $DiagramFormat) {
Write-Information -MessageData "Saved '$($FileName).$($OutputFormat)' diagram to '$($OutputFolderPath)'." -InformationAction Continue
@@ -117,15 +117,14 @@ function Export-AbrOntapDiagram {
}
try {
$DiagramParams.Remove('Format')
- $DiagramParams.Add('Format', "base64")
+ $DiagramParams.Add('Format', 'base64')
$Graph = $DiagramObject
- $Diagram = New-Diagrammer @DiagramParams -InputObject $Graph
+ $Diagram = New-AbrDiagram @DiagramParams -InputObject $Graph
if ($Diagram) {
- if ((Get-DiaImagePercent -GraphObj $Diagram).Width -gt 600) { $ImagePrty = 40 } else { $ImagePrty = 30 }
+ $BestAspectRatio = Get-BestImageAspectRatio -GraphObj $Diagram -MaxWidth 600
Section -Style Heading2 $MainDiagramLabel {
- Image -Base64 $Diagram -Text "NetApp Ontap Diagram" -Percent $ImagePrty -Align Center
- Paragraph "Image preview: Opens the image in a new tab to view it at full resolution." -Tabs 2
+ Image -Base64 $Diagram -Text 'NetApp Ontap Diagram' -Width $BestAspectRatio.Width -Height $BestAspectRatio.Height -Align Center
}
}
} catch {
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapCluster.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapCluster.ps1
new file mode 100755
index 0000000..20d00bc
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapCluster.ps1
@@ -0,0 +1,79 @@
+function Get-AbrOntapCluster {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP cluster information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP cluster information.'
+ }
+
+ process {
+ try {
+ $ClusterInfo = Get-NcCluster -Controller $Array
+ if ($ClusterInfo) {
+ $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) {
+ $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 = @{
+ Name = "Cluster Information - $($ClusterInfo.ClusterName)"
+ List = $true
+ ColumnWidths = 25, 75
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Cluster.Summary -and ($OutObj | Where-Object { $_.'Overall System Health' -notlike 'OK' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'The overall system health is not OK. It is recommended to investigate the issue further to ensure the cluster is functioning properly.'
+ }
+ BlankLine
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterASUP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterASUP.ps1
new file mode 100755
index 0000000..91d79cd
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterASUP.ps1
@@ -0,0 +1,106 @@
+function Get-AbrOntapClusterASUP {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP cluster autoSupport status from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP AutoSupport information.'
+ }
+
+ process {
+ try {
+ $AutoSupport = Get-NcAutoSupportConfig -Controller $Array -ErrorAction Continue
+ if ($AutoSupport) {
+ $Outobj = @()
+ foreach ($NodesAUTO in $AutoSupport) {
+ try {
+ $Inobj = [ordered] @{
+ 'Node Name' = $NodesAUTO.NodeName
+ 'Protocol' = $NodesAUTO.Transport
+ 'Enabled' = $NodesAUTO.IsEnabled
+ 'Last Time Stamp' = $NodesAUTO.LastTimestampDT
+ 'Last Subject' = $NodesAUTO.LastSubject
+ 'Ondemand Server URL' = $NodesAUTO.OndemandServerUrl
+ 'Validate Digital Certificate' = $NodesAUTO.ValidateDigitalCertificate
+ 'Ondemand Remote Diagnostic Enabled' = $NodesAUTO.IsOndemandRemoteDiagEnabled
+ 'Performance Data Enabled' = $NodesAUTO.IsPerfDataEnabled
+ 'Private Data Removed' = $NodesAUTO.IsPrivateDataRemoved
+ 'Support Enabled' = $NodesAUTO.IsSupportEnabled
+ }
+ $Outobj += [pscustomobject](ConvertTo-HashToYN $inObj)
+
+ if ($Healthcheck.Cluster.AutoSupport) {
+ $Outobj | Where-Object { $_.'Enabled' -like 'No' } | Set-Style -Style Warning -Property 'Enabled'
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($InfoLevel.Storage -ge 2) {
+ foreach ($NodesAUTO in $Outobj) {
+ Section -Style NOTOCHeading4 -ExcludeFromTOC "$($NodesAUTO.'Node Name')" {
+ $TableParams = @{
+ Name = "Cluster AutoSupport Status - $($NodesAUTO.'Node Name')"
+ List = $true
+ ColumnWidths = 40, 60
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $NodesAUTO | Table @TableParams
+ if ($Healthcheck.Cluster.AutoSupport -and ($NodesAUTO | Where-Object { $_.'Enabled' -like 'No' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'AutoSupport is disabled on one or more nodes. It is recommended to enable AutoSupport to ensure proactive monitoring and issue resolution.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } else {
+ $TableParams = @{
+ Name = "Cluster AutoSupport Status - $($ClusterInfo.ClusterName)"
+ List = $false
+ Columns = 'Node Name', 'Protocol', 'Enabled'
+ ColumnWidths = 40, 30, 30
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $Outobj | Table @TableParams
+ if ($Healthcheck.Cluster.AutoSupport -and ($Outobj | Where-Object { $_.'Enabled' -like 'No' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'AutoSupport is disabled on one or more nodes. It is recommended to enable AutoSupport to ensure proactive monitoring and issue resolution.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterDiagram.ps1
new file mode 100644
index 0000000..ed5ca52
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterDiagram.ps1
@@ -0,0 +1,218 @@
+function Get-AbrOntapClusterDiagram {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to built NetApp ONTAP cluster diagram
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Generating Cluster Diagram for NetApp ONTAP.'
+ # Used for DiagramDebug
+ if ($Options.EnableDiagramDebug) {
+ $EdgeDebug = @{style = 'filled'; color = 'red' }
+ $SubGraphDebug = @{style = 'dashed'; color = 'red' }
+ $NodeDebug = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $NodeDebugEdge = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $IconDebug = $true
+ } else {
+ $EdgeDebug = @{style = 'invis'; color = 'red' }
+ $SubGraphDebug = @{style = 'invis'; color = 'gray' }
+ $NodeDebug = @{color = 'transparent'; style = 'transparent'; shape = 'point' }
+ $NodeDebugEdge = @{color = 'transparent'; style = 'transparent'; shape = 'none' }
+ $IconDebug = $false
+ }
+
+ if ($Options.DiagramTheme -eq 'Black') {
+ $Edgecolor = 'White'
+ $Fontcolor = 'White'
+ } elseif ($Options.DiagramTheme -eq 'Neon') {
+ $Edgecolor = 'gold2'
+ $Fontcolor = 'gold2'
+ } else {
+ $Edgecolor = '#71797E'
+ $Fontcolor = '#565656'
+ }
+ }
+
+ process {
+ try {
+ $ClusterInfo = Get-NcCluster -Controller $Array
+ $NodeSum = Get-NcNode -Controller $Array
+
+ SubGraph Cluster -Attributes @{Label = $ClusterInfo.ClusterName; fontsize = 22; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } {
+ SubGraph ClusterInfo -Attributes @{Label = "Management: $($ClusterInfo.NcController)"; fontsize = 16; penwidth = 1.5; labelloc = 'b'; labeljust = 'r'; style = 'dashed,rounded'; color = 'transparent' } {
+ try {
+
+ if ($NodeSum.Count -eq 1) {
+ $NodeSumColumnSize = 1
+ } elseif ($ColumnSize) {
+ $NodeSumColumnSize = $ColumnSize
+ } else {
+ $NodeSumColumnSize = $NodeSum.Count
+ }
+
+ $HAObject = @()
+
+ $NodeAdditionalInfo = @()
+
+ foreach ($Node in $NodeSum) {
+ $ClusterHa = try { Get-NcClusterHa -Node $Node.Node -Controller $Array } catch { Write-PScriboMessage -IsWarning $_.Exception.Message }
+
+ $NodeMgmtAddress = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'node_mgmt' -and $_.HomeNode -eq $Node.Node } | Select-Object -ExpandProperty Address
+ $NodeInterClusterAddress = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'intercluster' -and $_.HomeNode -eq $Node.Node } | Select-Object -ExpandProperty Address
+
+ if ($ClusterHa.Name -notin $HAObject.Partner) {
+ $HAObject += [PSCustomObject][ordered]@{
+ 'Name' = $ClusterHa.Name
+ 'Partner' = $ClusterHa.Partner
+ 'HAState' = $ClusterHa.State
+ }
+ }
+
+ $NodeAdditionalInfo += [PSCustomObject][ordered]@{
+ 'NodeName' = $Node.Node
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'System Id' = $Node.NodeSystemId
+ 'Serial' = $Node.NodeSerialNumber
+ 'Model' = $Node.NodeModel
+ 'Mgmt' = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
+ $true { 'Unknown' }
+ $false { @($NodeMgmtAddress) -join ', ' }
+ default { 'Unknown' }
+ }
+ 'Intercluster' = switch ([string]::IsNullOrEmpty($NodeInterClusterAddress)) {
+ $true { 'Unknown' }
+ $false { $NodeInterClusterAddress }
+ default { 'Unknown' }
+ }
+ }
+ }
+ }
+
+ # Build a flat list of all graphviz node names for edge creation
+ $AllNodeNames = @()
+ foreach ($HA in $HAObject) {
+ $AllNodeNames += Remove-SpecialCharacter -String $HA.Name -SpecialChars '\-_'
+ if ($HA.Partner) {
+ $AllNodeNames += Remove-SpecialCharacter -String $HA.Partner -SpecialChars '\-_'
+ }
+ }
+
+ # Cluster Network switch
+ $ClusterNetworkImage = Add-NodeImage -Name 'ClusterSwitch1' -ImagesObj $Images -IconType 'Ontap_Cluster_Network' -IconDebug $IconDebug -TableBackgroundColor '#a1e3fd'
+ Add-HtmlSubGraph -Name 'ClusterNetwork' -TableArray $ClusterNetworkImage -Label 'Cluster Network' -LabelPos top -ImagesObj $Images -IconDebug $IconDebug -NodeObject -TableBorder 1 -FontSize 16 -TableBorderColor '#71797E' -TableStyle 'rounded,dashed' -FontColor 'darkblue' -FontBold -FontName 'Segoe Ui Bold' -TableBackgroundColor '#a1e3fd'
+
+ if ($HAObject.Name -and $HAObject.Partner) {
+ foreach ($HA in $HAObject) {
+ $HAClusterName = Remove-SpecialCharacter -String "HA$($HA.Name)$($HA.Partner)" -SpecialChars '\-_'
+ SubGraph $HAClusterName -Attributes @{Label = 'HA Pair'; fontsize = 16; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray'; labeljust = 'c' } {
+
+ $HAName = Remove-SpecialCharacter -String $HA.Name -SpecialChars '\-_'
+ $HAPartner = Remove-SpecialCharacter -String $HA.Partner -SpecialChars '\-_'
+
+ Node $HAName @{Label = Add-NodeIcon -Name $HA.Name -AditionalInfo ($NodeAdditionalInfo | Where-Object { $_.NodeName -eq $HA.Name }).AdditionalInfo -ImagesObj $Images -IconType 'Ontap_Node' -Align 'Center' -IconDebug $IconDebug -FontSize 18; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+
+ Node $HAPartner @{Label = Add-NodeIcon -Name $HA.Partner -AditionalInfo ($NodeAdditionalInfo | Where-Object { $_.NodeName -eq $HA.Partner }).AdditionalInfo -ImagesObj $Images -IconType 'Ontap_Node' -Align 'Center' -IconDebug $IconDebug -FontSize 18; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+
+ Rank $HAName, $HAPartner
+
+ Add-NodeEdge -From $HAName -To $HAPartner -EdgeColor $Edgecolor -EdgeStyle 'solid' -EdgeThickness 2 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabel "HA: $($HA.HAState)" -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 16 -EdgeLength 2
+ }
+ }
+ } else {
+ foreach ($HA in $HAObject) {
+ $HAClusterName = Remove-SpecialCharacter -String "HA$($HA.Name)" -SpecialChars '\-_'
+ SubGraph $HAClusterName -Attributes @{Label = 'Single Node Cluster'; fontsize = 16; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray'; labeljust = 'c' } {
+ $HAName = Remove-SpecialCharacter -String $HA.Name -SpecialChars '\-_'
+ Node $HAName @{Label = Add-NodeIcon -Name $HA.Name -AditionalInfo ($NodeAdditionalInfo | Where-Object { $_.NodeName -eq $HA.Name }).AdditionalInfo -ImagesObj $Images -IconType 'Ontap_Node' -Align 'Center' -IconDebug $IconDebug -FontSize 18; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+ }
+ }
+ }
+
+ # Management Network switch
+ $MgmtNetworkImage = Add-NodeImage -Name 'MgmtSwitch1' -ImagesObj $Images -IconType 'Ontap_Cluster_Network' -IconDebug $IconDebug -TableBackgroundColor '#d5e8d4'
+ Add-HtmlSubGraph -Name 'ManagementNetwork' -TableArray $MgmtNetworkImage -Label 'Management Network' -LabelPos top -ImagesObj $Images -IconDebug $IconDebug -NodeObject -TableBorder 1 -FontSize 16 -TableBorderColor '#71797E' -TableStyle 'rounded,dashed' -FontColor 'darkgreen' -FontBold -FontName 'Segoe Ui Bold' -TableBackgroundColor '#d5e8d4'
+
+ # Data Network switch
+ $DataNetworkImage = Add-NodeImage -Name 'DataSwitch1' -ImagesObj $Images -IconType 'Ontap_Cluster_Network' -IconDebug $IconDebug -TableBackgroundColor '#dae8fc'
+ Add-HtmlSubGraph -Name 'DataNetwork' -TableArray $DataNetworkImage -Label 'Data Network' -LabelPos top -ImagesObj $Images -IconDebug $IconDebug -NodeObject -TableBorder 1 -FontSize 16 -TableBorderColor '#71797E' -TableStyle 'rounded,dashed' -FontColor 'darkblue' -FontBold -FontName 'Segoe Ui Bold' -TableBackgroundColor '#dae8fc'
+
+ # Connect all nodes to the network infrastructure elements
+ foreach ($NodeName in $AllNodeNames) {
+ Add-NodeEdge -From 'ClusterNetwork' -To $NodeName -EdgeColor '#5B9BD5' -EdgeStyle 'dashed' -Arrowhead 'none' -Arrowtail 'none' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 10 -EdgeLength 2 -EdgeThickness 3
+ Add-NodeEdge -From 'ManagementNetwork' -To $NodeName -EdgeColor $Edgecolor -EdgeStyle 'dashed' -Arrowhead 'none' -Arrowtail 'none' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 10 -EdgeLength 2 -EdgeThickness 3
+ Add-NodeEdge -From $NodeName -To 'DataNetwork' -EdgeColor '#70AD47' -EdgeStyle 'dashed' -Arrowhead 'none' -Arrowtail 'none' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 10 -EdgeLength 2 -EdgeThickness 3
+ }
+
+ # Data Network - Per Broadcast Domain Information
+ try {
+ $DataBroadcastDomains = Get-NcNetPortBroadcastDomain -Controller $Array | Where-Object { $_.BroadcastDomain -ne 'Cluster' }
+
+ if ($DataBroadcastDomains) {
+ foreach ($BDomain in $DataBroadcastDomains) {
+ $BDomainSafeName = Remove-SpecialCharacter -String $BDomain.BroadcastDomain -SpecialChars '\-_:'
+
+ $PortTextItems = @()
+ if ($BDomain.Ports) {
+ foreach ($PortMember in $BDomain.Ports) {
+ $PortSafeName = Remove-SpecialCharacter -String $PortMember -SpecialChars '\-_:'
+
+ $PortTextItems += Add-NodeText -Name "BD${BDomainSafeName}${PortSafeName}" -Text $PortMember -IconDebug $IconDebug -FontSize 12
+ }
+ } else {
+ $PortTextItems += Add-NodeText -Name "BD${BDomainSafeName}NoPorts" -Text 'No Ports Assigned' -IconDebug $IconDebug -FontSize 12
+ }
+
+ Add-HtmlSubGraph -Name "${BDomainSafeName}BroadcastDomain" `
+ -TableArray $PortTextItems `
+ -ImagesObj $Images `
+ -IconDebug $IconDebug `
+ -TableBorder 1 `
+ -Label "$($BDomain.BroadcastDomain) | MTU: $($BDomain.Mtu)" `
+ -LabelPos 'top' `
+ -TableStyle 'rounded,dashed' `
+ -TableBorderColor '#70AD47' `
+ -FontName 'Segoe Ui Bold' `
+ -NodeObject `
+ -ColumnSize 3 `
+ -FontSize 14
+
+ Add-NodeEdge -From 'DataNetwork' -To "${BDomainSafeName}BroadcastDomain" `
+ -EdgeColor '#70AD47' `
+ -EdgeStyle 'dashed' `
+ -Arrowhead 'none' `
+ -Arrowtail 'none' `
+ -EdgeLength 2 `
+ -EdgeThickness 3
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ }
+
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterHA.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterHA.ps1
new file mode 100755
index 0000000..212d6f6
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterHA.ps1
@@ -0,0 +1,163 @@
+function Get-AbrOntapClusterHA {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP cluster HA information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP cluster high availability information.'
+ }
+
+ process {
+ try {
+ $NodeSum = Get-NcNode -Controller $Array | Where-Object { $null -ne $_.NodeModel }
+ if ($NodeSum) {
+ $OutObj = @()
+ foreach ($Nodes in $NodeSum) {
+ try {
+ $ClusterHa = Get-NcClusterHa -Node $Nodes.Node -Controller $Array
+ $inObj = [ordered] @{
+ 'Name' = $Nodes.Node
+ 'NVRAM ID' = $Nodes.NodeNvramId
+ 'Local Mailbox Disks' = ($ClusterHa.LocalMailboxDisks | ForEach-Object { $_.Name }) -join ', '
+ 'Partner' = $ClusterHa.Partner ?? '--'
+ 'Partner NVRAM ID' = $ClusterHa.PartnerNvramId
+ 'Partner Mailbox Disks' = ($ClusterHa.PartnerMailboxDisks | ForEach-Object { $_.Name }) -join ', '
+ 'TakeOver Possible' = $ClusterHa.TakeoverPossible
+ 'TakeOver By Partner Possible' = $ClusterHa.TakeoverByPartnerPossible
+ 'TakeOver State' = $ClusterHa.TakeoverState ?? '--'
+ 'HA Mode' = $ClusterHa.CurrentMode
+ 'HA Type' = $ClusterHa.HaType
+ 'HA State' = $ClusterHa.State
+ 'Interconnect Type' = $ClusterHa.InterconnectType
+ 'Interconnect Links' = $ClusterHa.InterconnectLinks
+ 'Is Enabled' = $ClusterHa.IsEnabled
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ if ($Healthcheck.Cluster.HA) {
+ $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'
+ $OutObj | Where-Object { $_.'TakeOver By Partner Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' } | Set-Style -Style Warning -Property 'TakeOver By Partner Possible'
+ $OutObj | Where-Object { $_.'Is Enabled' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' } | Set-Style -Style Warning -Property 'Is Enabled'
+
+ }
+
+ if ($InfoLevel.Cluster -ge 2) {
+ foreach ($NodeHa in $OutObj) {
+ Section -Style NOTOCHeading4 -ExcludeFromTOC "$($NodeHa.Name)" {
+ $TableParams = @{
+ Name = "Cluster HA Status - $($NodeHa.Name)"
+ List = $true
+ ColumnWidths = 40, 60
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $NodeHa | Table @TableParams
+ if ($Healthcheck.Cluster.HA -and (($NodeHa | Where-Object { $_.'TakeOver State' -like 'in_takeover' } ) -or ($NodeHa | Where-Object { $_.'HA Mode' -ne 'non_ha' -and $_.'HA State' -notlike 'connected' }) -or ($NodeHa | Where-Object { $_.'TakeOver Possible' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' }))) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ if ($NodeHa | 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 ($NodeHa | 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 ($NodeHa | 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.'
+ }
+ BlankLine
+ }
+ if ($NodeHa | Where-Object { $_.'Is Enabled' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'One or more nodes have HA disabled while operating in HA mode. It is recommended to enable HA to ensure redundancy and high availability.'
+ }
+ BlankLine
+ }
+ }
+ }
+ }
+ } else {
+ $TableParams = @{
+ Name = "Cluster AutoSupport Status - $($ClusterInfo.ClusterName)"
+ List = $false
+ Columns = 'Name', 'Partner', 'TakeOver Possible', 'TakeOver State', 'HA Mode', 'HA State'
+ ColumnWidths = 20, 20, 11, 19, 10, 20
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $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 ($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 ($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 ($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.'
+ }
+ BlankLine
+ }
+ if ($Outobj | Where-Object { $_.'Is Enabled' -eq 'No' -and $_.'HA Mode' -ne 'non_ha' }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'One or more nodes have HA disabled while operating in HA mode. It is recommended to enable HA to ensure redundancy and high availability.'
+ }
+ BlankLine
+ }
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapClusterLicense.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicense.ps1
similarity index 56%
rename from Src/Private/Get-AbrOntapClusterLicense.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicense.ps1
index ef3abf6..b899ed7 100755
--- a/Src/Private/Get-AbrOntapClusterLicense.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicense.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapClusterLicense {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapClusterLicense {
)
begin {
- Write-PScriboMessage "Collecting ONTAP cluster license information."
+ Write-PScriboMessage 'Collecting ONTAP cluster license information.'
}
process {
@@ -27,21 +27,22 @@ function Get-AbrOntapClusterLicense {
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
try {
- Section -Style Heading3 "$Node License Usage" {
- $License = Get-NcLicense -Owner $Node -Controller $Array
- if ($License) {
- $LicenseSummary = foreach ($Licenses in $License) {
- $EntitlementRisk = try { Get-NcLicenseEntitlementRisk -Package $Licenses.Package -Controller $Array -ErrorAction SilentlyContinue } catch { Write-PScriboMessage -IsWarning $_.Exception.Message }
- [PSCustomObject] @{
+ $License = Get-NcLicense -Owner $Node -Controller $Array
+ if ($License) {
+ Section -Style Heading3 "$Node License Usage" {
+ $OutObj = @()
+ foreach ($Licenses in $License) {
+ $inObj = [ordered] @{
'License' = $TextInfo.ToTitleCase($Licenses.Package)
'Type' = $TextInfo.ToTitleCase($Licenses.Type)
'Description' = $Licenses.Description
- 'Risk' = ConvertTo-EmptyToFiller $EntitlementRisk.Risk
+ '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)"
@@ -51,13 +52,13 @@ 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' })) {
- Paragraph "Health Check:" -Bold -Underline
+ $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 {
- Text "Best Practice:" -Bold
- Text "Review the license risk summary above. It is recommended to address any licenses with medium, high, unknown, or unlicensed risk to ensure compliance and avoid potential disruptions."
+ Text 'Best Practice:' -Bold
+ Text 'Review the license risk summary above. It is recommended to address any licenses with medium, high, unknown, or unlicensed risk to ensure compliance and avoid potential disruptions.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapClusterLicenseUsage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
similarity index 71%
rename from Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
index 4c14837..99f213d 100755
--- a/Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterLicenseUsage.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapClusterLicenseUsage {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,22 +19,21 @@ function Get-AbrOntapClusterLicenseUsage {
)
begin {
- Write-PScriboMessage "Collecting ONTAP cluster license usage information."
+ Write-PScriboMessage 'Collecting ONTAP cluster license usage information.'
}
process {
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' = Switch ($NodeLFs.Notes) {
- "-" { 'None' }
- default { $NodeLFs.Notes }
- }
+ 'Notes' = $NodeLFs.Notes
}
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
$TableParams = @{
Name = "License Feature - $($ClusterInfo.ClusterName)"
@@ -44,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
diff --git a/Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1
similarity index 57%
rename from Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1
index af2d044..4b10045 100644
--- a/Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapClusterReplicationDiagram.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapClusterReplicationDiagram {
.DESCRIPTION
.NOTES
- Version: 0.6.9
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapClusterReplicationDiagram {
)
begin {
- Write-PScriboMessage "Generating Cluster Replication Diagram for NetApp ONTAP."
+ Write-PScriboMessage 'Generating Cluster Replication Diagram for NetApp ONTAP.'
# Used for DiagramDebug
if ($Options.EnableDiagramDebug) {
$EdgeDebug = @{style = 'filled'; color = 'red' }
@@ -72,35 +72,41 @@ function Get-AbrOntapClusterReplicationDiagram {
if ($ClusterHa.Name -notin $HAObject.Partner) {
$HAObject += [PSCustomObject][ordered]@{
- "HAState" = $ClusterHa.State
+ 'HAState' = $ClusterHa.State
}
}
$NodeAdditionalInfo += [PSCustomObject][ordered]@{
- "Management" = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
- $true { "Unknown" }
- $false { $NodeMgmtAddress }
- Default { "Unknown" }
+ 'Management' = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
+ $true { 'Unknown' }
+ $false {
+ if ($NodeMgmtAddress -is [System.Array]) {
+ $NodeMgmtAddress -join ', '
+ } else {
+ $NodeMgmtAddress
+ }
+ }
+ default { 'Unknown' }
}
- "Intercluster" = switch ([string]::IsNullOrEmpty($NodeInterClusterAddress)) {
- $true { "Unknown" }
+ 'Intercluster' = switch ([string]::IsNullOrEmpty($NodeInterClusterAddress)) {
+ $true { 'Unknown' }
$false { $NodeInterClusterAddress }
- Default { "Unknown" }
+ default { 'Unknown' }
}
}
}
if ($ClusterInfo) {
- $ClusterNodeObj = Add-DiaHTMLNodeTable -ImagesObj $Images -inputObject $NodeSum.Node -Align "Center" -iconType "Ontap_Node" -columnSize $NodeSumColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $NodeAdditionalInfo -Subgraph -SubgraphIconType "Ontap_Node_Icon" -SubgraphLabel $ClusterInfo.ClusterName -SubgraphLabelPos "top" -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder "0" -SubgraphLabelFontsize 22 -fontSize 18
+ $ClusterNodeObj = Add-HtmlNodeTable -Name 'ClusterNodeObj' -ImagesObj $Images -inputObject $NodeSum.Node -Align 'Center' -iconType 'Ontap_Node' -ColumnSize $NodeSumColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $NodeAdditionalInfo -Subgraph -SubgraphIconType 'Ontap_Node_Icon' -SubgraphLabel $ClusterInfo.ClusterName -SubgraphLabelPos 'top' -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder '0' -SubgraphLabelFontSize 22 -FontSize 18
}
if ($ClusterNodeObj) {
- $ClusterMgmtObj = Add-DiaHTMLSubGraph -ImagesObj $Images -TableArray $ClusterNodeObj -Align 'Right' -IconDebug $IconDebug -Label "Management: $($ClusterInfo.NcController)" -LabelPos 'down' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder "1" -columnSize 1 -fontSize 12
+ $ClusterMgmtObj = Add-HtmlSubGraph -Name 'ClusterMgmtObj' -ImagesObj $Images -TableArray $ClusterNodeObj -Align 'Right' -IconDebug $IconDebug -Label "Management: $($ClusterInfo.NcController)" -LabelPos 'down' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize 1 -FontSize 12
if ($ClusterMgmtObj) {
Node SourceCluster @{Label = $ClusterMgmtObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
} else {
- Write-PScriboMessage -IsWarning "Unable to create Cluster Node. No Cluster Management Object found."
+ Write-PScriboMessage -IsWarning 'Unable to create Cluster Node. No Cluster Management Object found.'
}
}
} catch {
@@ -114,20 +120,20 @@ function Get-AbrOntapClusterReplicationDiagram {
$Index = $VserverPeersColors.Count - 1
foreach ($VserverPeer in $VserverPeers) {
$VserversPeerInfo += [PSCustomObject][ordered]@{
- "SourceCluster" = $ClusterInfo.ClusterName
- "SourceVserver" = $VserverPeer.Vserver
- "RemoteCluster" = $VserverPeer.PeerCluster
- "RemoteVserver" = $VserverPeer.PeerVserver
- "Color" = Get-RandomPastelColorHex
- "SourceAdditionalInfo" = [PSCustomObject][ordered]@{
- "Peer Vserver" = $VserverPeer.PeerVserver
- "Peer Cluster" = $VserverPeer.PeerCluster
- "Applications" = $VserverPeer.Applications -join ", "
+ 'SourceCluster' = $ClusterInfo.ClusterName
+ 'SourceVserver' = $VserverPeer.Vserver
+ 'RemoteCluster' = $VserverPeer.PeerCluster
+ 'RemoteVserver' = $VserverPeer.PeerVserver
+ 'Color' = Get-RandomPastelColorHex
+ 'SourceAdditionalInfo' = [PSCustomObject][ordered]@{
+ 'Peer Vserver' = $VserverPeer.PeerVserver
+ 'Peer Cluster' = $VserverPeer.PeerCluster
+ 'Applications' = $VserverPeer.Applications -join ', '
}
- "DestinationAdditionalInfo" = [PSCustomObject][ordered]@{
- "Peer Vserver" = $VserverPeer.Vserver
- "Peer Cluster" = $ClusterInfo.ClusterName
- "Applications" = $VserverPeer.Applications -join ", "
+ 'DestinationAdditionalInfo' = [PSCustomObject][ordered]@{
+ 'Peer Vserver' = $VserverPeer.Vserver
+ 'Peer Cluster' = $ClusterInfo.ClusterName
+ 'Applications' = $VserverPeer.Applications -join ', '
}
}
}
@@ -136,7 +142,7 @@ function Get-AbrOntapClusterReplicationDiagram {
$VserverPeerObj = @()
$VserverPeerObj = foreach ($VserverPeer in $VserversPeerInfo) {
- Add-DiaHTMLNodeTable -ImagesObj $Images -inputObject $VserverPeer.SourceVserver -Align "Center" -iconType "Ontap_SVM" -columnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $VserverPeer.SourceAdditionalInfo -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder 1 -fontSize 18 -CellBackgroundColor $VserverPeer.Color
+ Add-HtmlNodeTable -Name 'VserverPeerObj' -ImagesObj $Images -inputObject $VserverPeer.SourceVserver -Align 'Center' -iconType 'Ontap_SVM' -ColumnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $VserverPeer.SourceAdditionalInfo -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder 1 -FontSize 18 -CellBackgroundColor $VserverPeer.Color
}
if ($VserverPeerObj.Count -eq 1) {
@@ -147,11 +153,11 @@ function Get-AbrOntapClusterReplicationDiagram {
$VserverPeerObjColumnSize = $VserverPeerObj.Count
}
- $VserverPeerSubGraphObj = Add-DiaHTMLSubGraph -ImagesObj $Images -TableArray $VserverPeerObj -Align 'Center' -IconDebug $IconDebug -Label "Source Storage VMs" -LabelPos 'top' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder "1" -columnSize $VserverPeerObjColumnSize -fontSize 18 -IconType "Ontap_SVM_Icon"
+ $VserverPeerSubGraphObj = Add-HtmlSubGraph -Name 'VserverPeerSubGraphObj' -ImagesObj $Images -TableArray $VserverPeerObj -Align 'Center' -IconDebug $IconDebug -Label 'Source Storage VMs' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize $VserverPeerObjColumnSize -FontSize 18 -IconType 'Ontap_SVM_Icon'
if ($VserverPeerSubGraphObj) {
Node SourceVservers @{Label = $VserverPeerSubGraphObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
- Edge -From SourceVservers -To SourceCluster @{minlen = 2; color = '#71797E'; style = 'filled'; arrowhead = 'box'; arrowtail = 'box' }
+ Add-NodeEdge -From 'SourceVservers' -To 'SourceCluster' -EdgeColor '#71797E' -Arrowhead 'box' -Arrowtail 'box' -EdgeLength 2 -GraphvizAttributes @{style = 'filled' }
Rank SourceVservers, SourceCluster
}
} catch {
@@ -182,8 +188,8 @@ function Get-AbrOntapClusterReplicationDiagram {
$NodeMgmtAddress = $ClusterReplicaInfo.NcController
$NodeAdditionalInfo += [PSCustomObject][ordered]@{
- "Intercluster" = switch ([string]::IsNullOrEmpty($ClusterReplicaInfo.ActiveAddresses)) {
- $true { "Unknown" }
+ 'Intercluster' = switch ([string]::IsNullOrEmpty($ClusterReplicaInfo.ActiveAddresses)) {
+ $true { 'Unknown' }
$false {
& {
if ($ClusterReplicaInfo.ActiveAddresses.Count -gt 1) {
@@ -193,7 +199,7 @@ function Get-AbrOntapClusterReplicationDiagram {
}
}
}
- Default { "Unknown" }
+ default { 'Unknown' }
}
}
$Num++
@@ -201,33 +207,33 @@ function Get-AbrOntapClusterReplicationDiagram {
if ($ClusterReplicaInfo -and $NodeReplicaSum) {
try {
- $ClusterReplicaNodeObj = Add-DiaHTMLNodeTable -ImagesObj $Images -inputObject $NodeReplicaSum -Align "Center" -iconType "Ontap_Node" -columnSize $NodeSumColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $NodeAdditionalInfo -Subgraph -SubgraphIconType "Ontap_Node_Icon" -SubgraphLabel $ClusterReplicaInfo.ClusterName -SubgraphLabelPos "top" -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder "1" -SubgraphLabelFontsize 22 -fontSize 18
+ $ClusterReplicaNodeObj = Add-HtmlNodeTable -Name 'ClusterReplicaNodeObj' -ImagesObj $Images -inputObject $NodeReplicaSum -Align 'Center' -iconType 'Ontap_Node' -ColumnSize $NodeSumColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $NodeAdditionalInfo -Subgraph -SubgraphIconType 'Ontap_Node_Icon' -SubgraphLabel $ClusterReplicaInfo.ClusterName -SubgraphLabelPos 'top' -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder '1' -SubgraphLabelFontSize 22 -FontSize 18
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
} else {
- Write-PScriboMessage -IsWarning "Unable to create Cluster Replication Node. No Cluster Management Object found."
+ Write-PScriboMessage -IsWarning 'Unable to create Cluster Replication Node. No Cluster Management Object found.'
}
if ($ClusterReplicaNodeObj) {
if ($ClusterReplicaNodeObj) {
- $RemoteClusterName = Remove-SpecialChar -String $ClusterReplicaInfo.ClusterName -SpecialChars '\-_'
+ $RemoteClusterName = Remove-SpecialCharacter -String $ClusterReplicaInfo.ClusterName -SpecialChars '\-_'
Node $RemoteClusterName @{Label = $ClusterReplicaNodeObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
$Ranks += $RemoteClusterName
} else {
- Write-PScriboMessage -IsWarning "Unable to create Cluster Replication Node. No Cluster Management Object found."
+ Write-PScriboMessage -IsWarning 'Unable to create Cluster Replication Node. No Cluster Management Object found.'
}
}
if ($ClusterReplicaNodeObj) {
- Edge -From SourceCluster:e -To $RemoteClusterName @{minlen = 3; color = '#71797E'; style = 'filled'; arrowhead = 'box'; arrowtail = 'box' }
+ Add-NodeEdge -From 'SourceCluster:e' -To $RemoteClusterName -EdgeColor '#71797E' -Arrowhead 'box' -Arrowtail 'box' -EdgeLength 3 -GraphvizAttributes @{style = 'filled' }
}
try {
$PeerVserverPeerObj = @()
$PeerVserverPeerObj = foreach ($VserversPeer in ($VserversPeerInfo | Where-Object { $_.RemoteCluster -eq $ClusterReplicaInfo.ClusterName })) {
- Add-DiaHTMLNodeTable -ImagesObj $Images -inputObject $VserversPeer.RemoteVserver -Align "Center" -iconType "Ontap_SVM" -columnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $VserversPeer.DestinationAdditionalInfo -SubgraphTableStyle "dashed,rounded" -TableBorderColor "#71797E" -TableBorder "1" -SubgraphLabelFontsize 22 -fontSize 18 -CellBackgroundColor $VserversPeer.Color
+ Add-HtmlNodeTable -Name 'PeerVserverPeerObj' -ImagesObj $Images -inputObject $VserversPeer.RemoteVserver -Align 'Center' -iconType 'Ontap_SVM' -ColumnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $VserversPeer.DestinationAdditionalInfo -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder '1' -SubgraphLabelFontSize 22 -FontSize 18 -CellBackgroundColor $VserversPeer.Color
}
if ($PeerVserverPeerObj.Count -eq 1) {
@@ -238,13 +244,13 @@ function Get-AbrOntapClusterReplicationDiagram {
$PeerVserverPeerObjColumnSize = $PeerVserverPeerObj.Count
}
- $PeerVserverPeerSubGraphObj = Add-DiaHTMLSubGraph -ImagesObj $Images -TableArray $PeerVserverPeerObj -Align 'Center' -IconDebug $IconDebug -Label "Peer Storage VMs" -LabelPos 'top' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder "1" -columnSize $PeerVserverPeerObjColumnSize -fontSize 18 -IconType "Ontap_SVM_Icon"
+ $PeerVserverPeerSubGraphObj = Add-HtmlSubGraph -Name 'PeerVserverPeerSubGraphObj' -ImagesObj $Images -TableArray $PeerVserverPeerObj -Align 'Center' -IconDebug $IconDebug -Label 'Peer Storage VMs' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize $PeerVserverPeerObjColumnSize -FontSize 18 -IconType 'Ontap_SVM_Icon'
if ($PeerVserverPeerSubGraphObj -and $RemoteClusterName) {
Node "$($RemoteClusterName)PeerVservers" @{Label = $PeerVserverPeerSubGraphObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
- Edge -From $RemoteClusterName -To "$($RemoteClusterName)PeerVservers" @{minlen = 2; color = '#71797E'; style = 'filled'; arrowhead = 'box'; arrowtail = 'box' }
+ Add-NodeEdge -From $RemoteClusterName -To "$($RemoteClusterName)PeerVservers" -EdgeColor '#71797E' -Arrowhead 'box' -Arrowtail 'box' -EdgeLength 2 -GraphvizAttributes @{style = 'filled' }
} else {
- Write-PScriboMessage -IsWarning "Unable to create Peer Vserver Node. No Peer Vserver Object found."
+ Write-PScriboMessage -IsWarning 'Unable to create Peer Vserver Node. No Peer Vserver Object found.'
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskAssign.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskAssign.ps1
new file mode 100755
index 0000000..a4654a2
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskAssign.ps1
@@ -0,0 +1,68 @@
+function Get-AbrOntapDiskAssign {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP disk assign summary information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP disk assignment per node information.'
+ }
+
+ process {
+ try {
+ $NodeDiskCount = Get-NcDisk -Controller $Array | ForEach-Object { $_.DiskOwnershipInfo.HomeNodeName } | Group-Object
+ if ($NodeDiskCount) {
+ $ChartData = @()
+ $OwnerName = @()
+ $OutObj = @()
+ foreach ($Disks in $NodeDiskCount) {
+ $OwnerName += $Disks.Name
+ $ChartData += $Disks.Count
+ $inObj = [ordered] @{
+ 'Node' = $Disks.Name
+ 'Disk Count' = $Disks | Select-Object -ExpandProperty Count
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+ $TableParams = @{
+ Name = "Assigned Disk - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ try {
+ $Chart = New-BarChart -Values $ChartData -Labels $OwnerName -Title 'Disk Assignment' -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 600 -Format base64 -LabelYAxis 'Disk Count' -LabelXAxis 'Nodes' -TitleFontSize 20 -TitleFontBold -AreaOrientation Vertical -EnableCustomColorPalette -CustomColorPalette @('#395879', '#59779a', '#7b98bc', '#9dbae0', '#c0ddff') -AxesMarginsTop 0.5
+ if ($Chart) {
+ Section -Style NOTOCHeading5 -ExcludeFromTOC 'Per Node Disk Assignment - Chart' {
+ Image -Text 'Per Node Disk Assignment - Chart' -Align 'Center' -Percent 100 -Base64 $Chart
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapDiskBroken.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskBroken.ps1
similarity index 65%
rename from Src/Private/Get-AbrOntapDiskBroken.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskBroken.ps1
index 9639afb..05c2135 100755
--- a/Src/Private/Get-AbrOntapDiskBroken.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskBroken.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapDiskBroken {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,24 +19,26 @@ function Get-AbrOntapDiskBroken {
)
begin {
- Write-PScriboMessage "Collecting ONTAP failed disk per node information."
+ Write-PScriboMessage 'Collecting ONTAP failed disk per node information.'
}
process {
try {
- $NodeDiskBroken = Get-NcDisk -Controller $Array | Where-Object { $_.DiskRaidInfo.ContainerType -eq "broken" }
+ $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)"
@@ -46,13 +48,13 @@ function Get-AbrOntapDiskBroken {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
- $DiskFailed | Table @TableParams
- if ($Healthcheck.Storage.DiskStatus -and ($DiskFailed)) {
- Paragraph "Health Check:" -Bold -Underline
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Storage.DiskStatus -and ($OutObj)) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Review the failed disk information above. It is recommended to replace any broken disks promptly to maintain data integrity and system performance."
+ Text 'Best Practice:' -Bold
+ Text 'Review the failed disk information above. It is recommended to replace any broken disks promptly to maintain data integrity and system performance.'
}
BlankLine
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskInv.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskInv.ps1
new file mode 100755
index 0000000..d7a2955
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskInv.ps1
@@ -0,0 +1,98 @@
+function Get-AbrOntapDiskInv {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP disk inventort information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP disk inventory per node.'
+ }
+
+ process {
+ try {
+ $DiskInv = Get-NcDisk -Controller $Array
+ $NodeDiskBroken = Get-NcDisk -Controller $Array | Where-Object { $_.DiskRaidInfo.ContainerType -eq 'broken' }
+ if ($DiskInv) {
+ $OutObj = @()
+ foreach ($Disks in $DiskInv) {
+ try {
+ $DiskType = Get-NcDisk -Controller $Array -Name $Disks.Name | ForEach-Object { $_.DiskInventoryInfo }
+ $inObj = [ordered] @{
+ 'Disk Name' = $Disks.Name
+ 'Shelf' = $Disks.Shelf
+ 'Bay' = $Disks.Bay
+ 'Capacity' = ($Disks.Capacity | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Disksize) ?? '--'
+ 'Model' = $Disks.Model
+ 'Serial Number' = $DiskType.SerialNumber
+ 'Firmware' = $Disks.FW
+ 'Type' = $DiskType.DiskType
+ 'Aggregate' = $Disks.Aggregate
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ if ($Healthcheck.Storage.DiskStatus) {
+ $OutObj | Where-Object { $_.'Disk Name' -like '*(*)' } | Set-Style -Style Critical -Property 'Disk Name'
+ }
+
+ if ($InfoLevel.Storage -ge 2) {
+ foreach ($Disks in $Outobj) {
+ Section -Style NOTOCHeading4 -ExcludeFromTOC "$($Disks.'Disk Name')" {
+ $TableParams = @{
+ Name = "Disk Inventory - $($Disks.'Disk Name')"
+ List = $true
+ ColumnWidths = 40, 60
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $Disks | Select-Object -ExcludeProperty 'Disk Name' | Table @TableParams
+ if ($Healthcheck.Cluster.AutoSupport -and ($Disks | Where-Object { $_.'Enabled' -like 'No' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'AutoSupport is disabled on one or more nodes. It is recommended to enable AutoSupport to ensure proactive monitoring and issue resolution.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } else {
+ $TableParams = @{
+ Name = "Disk Inventory - $($ClusterInfo.ClusterName)"
+ List = $false
+ Columns = 'Disk Name', 'Shelf', 'Bay', 'Capacity', 'Model', 'Type', 'Firmware'
+ ColumnWidths = 18, 13, 10, 10, 25, 12, 12
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapDiskOwner.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskOwner.ps1
similarity index 76%
rename from Src/Private/Get-AbrOntapDiskOwner.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskOwner.ps1
index 2ca44a3..4067f35 100755
--- a/Src/Private/Get-AbrOntapDiskOwner.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskOwner.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapDiskOwner {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -24,23 +24,24 @@ function Get-AbrOntapDiskOwner {
)
begin {
- Write-PScriboMessage "Collecting ONTAP disk owned per node information."
+ Write-PScriboMessage 'Collecting ONTAP disk owned per node information.'
}
process {
try {
if ($Node) {
- $DiskSummary = foreach ($Owner in $Node) {
+ $OutObj = @()
+ foreach ($Owner in $Node) {
try {
- $DiskOwner = Get-NcDiskOwner -Node $Owner -Controller $Array
- foreach ($Disk in $DiskOwner) {
- [PSCustomObject] @{
+ foreach ($Disk in (Get-NcDiskOwner -Node $Owner -Controller $Array)) {
+ $inObj = [ordered] @{
'Disk' = $Disk.Name
'Owner Id' = $Disk.OwnerId
'Home' = $Disk.Home
'Home Id' = $Disk.HomeId
'Type' = $Disk.Type
}
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
@@ -54,7 +55,7 @@ function Get-AbrOntapDiskOwner {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
- $DiskSummary | Table @TableParams
+ $OutObj | Table @TableParams
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelf.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelf.ps1
new file mode 100755
index 0000000..96c4c69
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelf.ps1
@@ -0,0 +1,84 @@
+function Get-AbrOntapDiskShelf {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP disk shelf information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP disk shelf information.'
+ }
+
+ process {
+ try {
+ $NodeSum = Get-NcNode -Controller $Array
+ if ($NodeSum) {
+ foreach ($Nodes in $NodeSum) {
+ try {
+ $Nodeshelf = Get-NcShelf -NodeName $Nodes.Node -Controller $Array -ErrorAction SilentlyContinue
+ if ($Nodeshelf) {
+ Section -ExcludeFromTOC -Style NOTOCHeading4 $($Nodes.Node) {
+ $OutObj = @()
+ foreach ($Shelf in $Nodeshelf) {
+ $inObj = [ordered] @{
+ 'Channel' = $Shelf.ChannelName
+ 'Shelf Name' = $Shelf.ShelfName
+ 'Shelf ID' = $Shelf.ShelfId
+ 'Module' = $Shelf.Module
+ 'Module State' = $Shelf.ModuleState
+ 'State' = $Shelf.ShelfState
+ 'Type' = $Shelf.ShelfType
+ 'Firmware' = ($Shelf.FirmwareRevA + $Shelf.FirmwareRevB) ?? '--'
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+ if ($Healthcheck.Storage.ShelfStatus) {
+ $OutObj | Where-Object { $_.'State' -like 'offline' -or $_.'State' -like 'missing' } | Set-Style -Style Critical -Property 'State'
+ $OutObj | Where-Object { $_.'State' -like 'unknown' -or $_.'State' -like 'no-status' } | Set-Style -Style Warning -Property 'State'
+ }
+ $TableParams = @{
+ Name = "Storage Shelf - $($Nodes.Node)"
+ List = $false
+ ColumnWidths = 13, 13, 13, 13, 12, 12, 12, 12
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Storage.ShelfStatus -and ($OutObj | Where-Object { $_.'State' -like 'offline' -or $_.'State' -like 'missing' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure all disk shelves are online and operational. Investigate any shelves marked as offline or missing.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelfStorage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelfStorage.ps1
new file mode 100755
index 0000000..8111bbd
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskShelfStorage.ps1
@@ -0,0 +1,71 @@
+function Get-AbrOntapDiskShelfStorage {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP disk shelf storage information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP disk shelf storage information.'
+ }
+
+ process {
+ try {
+ $NodeshelfObj = Get-NcStorageShelf -Controller $Array -ErrorAction SilentlyContinue
+ if ($NodeshelfObj) {
+ $OutObj = @()
+ foreach ($Shelf in $NodeshelfObj) {
+ $inObj = [ordered] @{
+ 'Model' = $Shelf.ShelfModel
+ 'Connection Type' = $Shelf.ConnectionType
+ 'Module Type' = $Shelf.ModuleType
+ 'Disk Count' = $Shelf.DiskCount
+ 'Serial Number' = $Shelf.SerialNumber
+ 'Operational Status' = $Shelf.OpStatus
+ 'Shelf Id' = $Shelf.Shelf
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+ if ($Healthcheck.Storage.ShelfStatus) {
+ $OutObj | Where-Object { $_.'Operational Status' -ne 'normal' } | Set-Style -Style Warning -Property 'Operational Status'
+ }
+ $TableParams = @{
+ Name = "Disk Shelf - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 18, 13, 12, 11, 22, 14, 10
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Storage.ShelfStatus -and ($OutObj | Where-Object { $_.'Operational Status' -ne 'normal' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text ' All disk shelves should have an working operational status.'
+ }
+ BlankLine
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskType.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskType.ps1
new file mode 100755
index 0000000..7431870
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapDiskType.ps1
@@ -0,0 +1,96 @@
+function Get-AbrOntapDiskType {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP disk type information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP disk type per node information.'
+ }
+
+ process {
+ try {
+ $OutObj = @()
+ foreach ($DiskContainers in (Get-NcDisk -Controller $Array | ForEach-Object { $_.DiskRaidInfo.ContainerType } | Group-Object)) {
+ try {
+ $inObj = [ordered] @{
+ 'Container' = $DiskContainers.Name
+ 'Disk Count' = $DiskContainers | Select-Object -ExpandProperty Count
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Storage.DiskStatus) {
+ $OutObj | Where-Object { $_.'Container' -like 'broken' } | Set-Style -Style Critical -Property 'Disk Count'
+ }
+ $TableParams = @{
+ Name = "Disk Container Type - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ $Node = Get-NcNode | Where-Object { $_.IsNodeHealthy -eq 'True' }
+ if ($Node -and (Confirm-NcAggrSpareLow | Where-Object { $_.Value -eq 'True' })) {
+ Section -ExcludeFromTOC -Style NOTOCHeading5 'Aggregate Spare Low Warning Per Node' {
+ $OutObj = @()
+ foreach ($Item in $Node) {
+ try {
+ $inObj = [ordered] @{
+ 'Node' = $Item.Node
+ 'Aggregate Spare Low' = (Confirm-NcAggrSpareLow -Node $Item.Node).Value.ToString().Replace('True', 'Yes').Replace('False', 'No')
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Storage.DiskStatus) {
+ $OutObj | Where-Object { $_.'Aggregate Spare Low' -like 'Yes' } | Set-Style -Style Critical -Property 'Node', 'Aggregate Spare Low'
+ }
+ $TableParams = @{
+ Name = "Aggregate Disk Spare Low - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Storage.DiskStatus -and ($OutObj | Where-Object { $_.'Aggregate Spare Low' -like 'Yes' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that aggregate spare capacity is above the recommended threshold to maintain optimal performance and reliability.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapEfficiencyAggr.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyAggr.ps1
similarity index 77%
rename from Src/Private/Get-AbrOntapEfficiencyAggr.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyAggr.ps1
index 5898951..a1d7a0e 100755
--- a/Src/Private/Get-AbrOntapEfficiencyAggr.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyAggr.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyAggr {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapEfficiencyAggr {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Aggregate Efficiency Savings information."
+ Write-PScriboMessage 'Collecting ONTAP Aggregate Efficiency Savings information.'
}
process {
@@ -32,13 +32,13 @@ function Get-AbrOntapEfficiencyAggr {
$Saving = Get-NcAggrEfficiency -Aggregate $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrEfficiencyAggrInfo
$inObj = [ordered] @{
'Aggregate' = $Item.Name
- 'Logical Used' = $Saving.AggrLogicalUsed | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Physical Used' = $Saving.AggrPhysicalUsed | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Compaction Saved' = $Saving.AggrCompactionSaved | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Data Reduction' = $Saving.AggrDataReductionStorageEfficiencyRatio
+ 'Logical Used' = ($Saving.AggrLogicalUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Physical Used' = ($Saving.AggrPhysicalUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Compaction Saved' = ($Saving.AggrCompactionSaved | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Data Reduction' = ${Saving}?.AggrDataReductionStorageEfficiencyRatio
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -55,21 +55,21 @@ function Get-AbrOntapEfficiencyAggr {
$OutObj | Table @TableParams
}
try {
+ $OutObj = @()
$Data = Get-NcAggr -Controller $Array | Where-Object { $_.AggrRaidAttributes.HasLocalRoot -ne 'True' }
$Savingfilter = (Get-NcAggrEfficiency -Controller $Array | Select-Object -ExpandProperty AggrEfficiencyAdditionalDetailsInfo).NumberOfSisDisabledVolumes | Measure-Object -Sum
if ($Data -and $Savingfilter.Sum -gt 0 -and $Healthcheck.Storage.Efficiency) {
- $OutObj = @()
foreach ($Item in $Data) {
try {
$Saving = (Get-NcAggrEfficiency -Aggregate $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrEfficiencyAdditionalDetailsInfo).NumberOfSisDisabledVolumes
$VolInAggr = Get-NcVol -Aggregate $Item.Name -Controller $Array | Where-Object { $_.VolumeStateAttributes.IsVserverRoot -ne 'True' }
- $VolFilter = $VolInAggr | Where-Object { $_.VolumeSisAttributes.IsSisStateEnabled -ne "True" }
+ $VolFilter = $VolInAggr | Where-Object { $_.VolumeSisAttributes.IsSisStateEnabled -ne 'True' }
if ($Saving -ne 0 -and $VolFilter) {
$inObj = [ordered] @{
'Aggregate' = $Item.Name
- 'Volumes without Deduplication' = $VolFilter.Name -join ", "
+ 'Volumes without Deduplication' = $VolFilter.Name -join ', '
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
@@ -95,11 +95,11 @@ function Get-AbrOntapEfficiencyAggr {
BlankLine
$OutObj | Table @TableParams
if ($Healthcheck.Storage.Efficiency) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that deduplication is enabled on all volumes to maximize storage efficiency."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that deduplication is enabled on all volumes to maximize storage efficiency.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapEfficiencyConfig.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyConfig.ps1
similarity index 59%
rename from Src/Private/Get-AbrOntapEfficiencyConfig.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyConfig.ps1
index f20c2c5..5d5a625 100755
--- a/Src/Private/Get-AbrOntapEfficiencyConfig.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyConfig.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyConfig {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapEfficiencyConfig {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Storage Efficiency Savings information."
+ Write-PScriboMessage 'Collecting ONTAP Storage Efficiency Savings information.'
}
process {
@@ -30,17 +30,16 @@ function Get-AbrOntapEfficiencyConfig {
foreach ($Item in $Data) {
try {
$Saving = Get-NcAggr -Aggregate $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrSpaceAttributes
- $TotalStorageEfficiencyRatio = Get-NcAggrEfficiency -Aggregate $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrEfficiencyCumulativeInfo
$inObj = [ordered] @{
'Aggregate' = $Item.Name
- 'Used %' = $Saving.PercentUsedCapacity | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
- 'Capacity Tier Used' = $Saving.CapacityTierUsed | ConvertTo-FormattedNumber -Type Datasize -NumberFormatString "0.0" -ErrorAction SilentlyContinue
- 'Compaction Saved %' = $Saving.DataCompactionSpaceSavedPercent | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
- 'Deduplication Saved %' = $Saving.SisSpaceSavedPercent | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
- 'Total Data Reduction' = $TotalStorageEfficiencyRatio.TotalStorageEfficiencyRatio
+ 'Used %' = ($Saving.PercentUsedCapacity | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Capacity Tier Used' = ($Saving.CapacityTierUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Compaction Saved %' = ($Saving.DataCompactionSpaceSavedPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Deduplication Saved %' = ($Saving.SisSpaceSavedPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Total Data Reduction' = (Get-NcAggrEfficiency -Aggregate $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrEfficiencyCumulativeInfo).TotalStorageEfficiencyRatio ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapEfficiencyVol.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVol.ps1
similarity index 57%
rename from Src/Private/Get-AbrOntapEfficiencyVol.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVol.ps1
index f2e2e1f..e38c518 100755
--- a/Src/Private/Get-AbrOntapEfficiencyVol.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVol.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyVol {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapEfficiencyVol {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Volume Efficiency Savings information."
+ Write-PScriboMessage 'Collecting ONTAP Volume Efficiency Savings information.'
}
process {
try {
- $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.State -eq "online" }
+ $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.State -eq 'online' }
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -36,14 +36,14 @@ function Get-AbrOntapEfficiencyVol {
$Saving = Get-NcEfficiency -Volume $Item.Name -Vserver $Vserver -Controller $Array
$inObj = [ordered] @{
'Volume' = $Item.Name
- 'Capacity' = $Saving.Capacity | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $Saving.Used | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Snapshot Used' = $Saving.SnapshotUsed | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Total Savings' = $Saving.Returns.Total | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Effective Used' = $Saving.EffectiveUsed | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Efficiency Percent' = $Saving.EfficiencyPercent | ConvertTo-FormattedNumber -Type Percent -NumberFormatString "0.0" -ErrorAction SilentlyContinue
+ 'Capacity' = ($Saving.Capacity | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Saving.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Snapshot Used' = ($Saving.SnapshotUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Total Savings' = ($Saving.Returns.Total | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Effective Used' = ($Saving.EffectiveUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Efficiency Percent' = ($Saving.EfficiencyPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent -NumberFormatString 0.0) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1
similarity index 51%
rename from Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1
index c745d29..207dc92 100755
--- a/Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolDetailed.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyVolDetailed {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapEfficiencyVolDetailed {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Volume Efficiency Savings information."
+ Write-PScriboMessage 'Collecting ONTAP Volume Efficiency Savings information.'
}
process {
try {
- $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.State -eq "online" }
+ $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.State -eq 'online' }
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -36,15 +36,15 @@ function Get-AbrOntapEfficiencyVolDetailed {
$Saving = Get-NcEfficiency -Volume $Item.Name -Vserver $Vserver -Controller $Array
$inObj = [ordered] @{
'Volume' = $Item.Name
- 'Capacity' = $Saving.Capacity | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Dedupe Savings' = $Saving.Returns.Dedupe | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Compression Savings' = $Saving.Returns.Compression | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Snapshot Savings' = $Saving.Returns.Snapshot | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Cloning Savings' = $Saving.Returns.Cloning | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Efficiency %' = $Saving.EfficiencyPercent | ConvertTo-FormattedNumber -Type Percent -NumberFormatString "0.0" -ErrorAction SilentlyContinue
- 'Efficiency % w/o Snapshots' = [Math]::Round((($Saving.Returns.Dedupe + $Saving.Returns.Compression) / ($Saving.Used + $Saving.Returns.Dedupe + $Saving.Returns.Compression)) * 100) | ConvertTo-FormattedNumber -Type Percent -NumberFormatString "0.0" -ErrorAction SilentlyContinue
+ 'Capacity' = ($Saving.Capacity | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Dedupe Savings' = ($Saving.Returns.Dedupe | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Compression Savings' = ($Saving.Returns.Compression | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Snapshot Savings' = ($Saving.Returns.Snapshot | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Cloning Savings' = ($Saving.Returns.Cloning | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Efficiency %' = ($Saving.EfficiencyPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Percent ) ?? '--'
+ 'Efficiency % w/o Snapshots' = ([Math]::Round((($Saving.Returns.Dedupe + $Saving.Returns.Compression) / ($Saving.Used + $Saving.Returns.Dedupe + $Saving.Returns.Compression)) * 100) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Percent) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1
similarity index 69%
rename from Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1
index fb8ae4d..919e961 100755
--- a/Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapEfficiencyVolSisStatus.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyVolSisStatus {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapEfficiencyVolSisStatus {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Volume Deduplication information."
+ Write-PScriboMessage 'Collecting ONTAP Volume Deduplication information.'
}
process {
@@ -33,19 +33,14 @@ function Get-AbrOntapEfficiencyVolSisStatus {
if ($Data) {
foreach ($Item in $Data) {
try {
- $Volume = $Item.Path.split('/')
$inObj = [ordered] @{
- 'Volume' = $Volume[2]
- 'State' = switch ($Item.State) {
- 'enabled' { 'Enabled' }
- 'disabled' { 'Disabled' }
- default { $Item.State }
- }
+ 'Volume' = ($Item.Path.split('/'))[2] ?? '--'
+ 'State' = ($Item.State -eq 'enabled') ? 'Enabled': 'Disabled'
'Status' = $Item.Status
- 'Schedule Or Policy' = ConvertTo-EmptyToFiller $Item.ScheduleOrPolicy
- 'Progress' = ConvertTo-EmptyToFiller $Item.Progress
+ 'Schedule Or Policy' = $Item.ScheduleOrPolicy
+ 'Progress' = $Item.Progress
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -64,11 +59,11 @@ function Get-AbrOntapEfficiencyVolSisStatus {
}
$OutObj | Table @TableParams
if ($Healthcheck.Storage.Efficiency -and ($OutObj | Where-Object { $_.'State' -like 'Disabled' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that volume deduplication is enabled on volumes where data reduction is beneficial to optimize storage efficiency."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that volume deduplication is enabled on volumes where data reduction is beneficial to optimize storage efficiency.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapNetworkBdomain.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkBroadCastDomain.ps1
similarity index 58%
rename from Src/Private/Get-AbrOntapNetworkBdomain.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkBroadCastDomain.ps1
index 26a6201..97ee163 100755
--- a/Src/Private/Get-AbrOntapNetworkBdomain.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkBroadCastDomain.ps1
@@ -1,11 +1,11 @@
-function Get-AbrOntapNetworkBdomain {
+function Get-AbrOntapNetworkBroadCastDomain {
<#
.SYNOPSIS
Used by As Built Report to retrieve NetApp ONTAP Network Broadcast Domain information from the Cluster Management Network
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapNetworkBdomain {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Broadcast information."
+ Write-PScriboMessage 'Collecting ONTAP Broadcast information.'
}
process {
@@ -35,7 +35,11 @@ function Get-AbrOntapNetworkBdomain {
'MTU' = $Item.Mtu
'Ports' = $Item.Ports
}
- $BDomainObj += [pscustomobject]$inobj
+ $BDomainObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+
+ if ($Healthcheck.Network.Port) {
+ $BDomainObj | Where-Object { $null -eq $_.'Failover Groups' -and $null -eq $_.'Ports' } | Set-Style -Style Warning
}
$TableParams = @{
@@ -47,6 +51,15 @@ function Get-AbrOntapNetworkBdomain {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$BDomainObj | Table @TableParams
+ if ($Healthcheck.Network.Port -and ($BDomainObj | Where-Object { $null -eq $_.'Failover Groups' -and $null -eq $_.'Ports' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ 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.'
+ }
+ BlankLine
+ }
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
diff --git a/Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1
index d855ead..831570f 100755
--- a/Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkFailoverGroup.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkFailoverGroup {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapNetworkFailoverGroup {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Failover Group information."
+ Write-PScriboMessage 'Collecting ONTAP Failover Group information.'
}
process {
@@ -34,7 +34,7 @@ function Get-AbrOntapNetworkFailoverGroup {
'Vserver' = $Item.Vserver
'Target' = $Item.Target
}
- $FGObj += [pscustomobject]$inobj
+ $FGObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapNetworkIfgrp.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIfgrp.ps1
similarity index 73%
rename from Src/Private/Get-AbrOntapNetworkIfgrp.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIfgrp.ps1
index a02298b..50e79bb 100755
--- a/Src/Private/Get-AbrOntapNetworkIfgrp.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIfgrp.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkIfgrp {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapNetworkIfgrp {
)
begin {
- Write-PScriboMessage "Collecting ONTAP physical aggregata interface information."
+ Write-PScriboMessage 'Collecting ONTAP physical aggregata interface information.'
}
process {
@@ -33,25 +33,22 @@ function Get-AbrOntapNetworkIfgrp {
if ($IFGRPPorts) {
foreach ($Nics in $IFGRPPorts) {
try {
- if ($Nics.DownPorts) {
- $UPPort = "$($Nics.UpPorts) $($Nics.DownPorts)(Down)"
- } else { $UPPort = [String]$Nics.UpPorts }
$inObj = [ordered] @{
'Port Name' = $Nics.IfgrpName
'Distribution Function' = $Nics.DistributionFunction
'Mode' = $Nics.Mode
- 'Port' = $UPPort
+ 'Port' = ($Null -eq $Nics.DownPorts) ? [String]$Nics.UpPorts: "$($Nics.UpPorts) - {$($Nics.DownPorts)}(Down)"
'Mac Address' = $Nics.MacAddress
'Port Participation' = $Nics.PortParticipation
}
- $AggregatePorts += [pscustomobject]$inobj
+ $AggregatePorts += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Network.Port) {
- $AggregatePorts | Where-Object { $_.'Port' -match "Down" } | Set-Style -Style Warning -Property 'Port'
- $AggregatePorts | Where-Object { $_.'Port Participation' -ne "full" } | Set-Style -Style Warning -Property 'Port Participation'
+ $AggregatePorts | Where-Object { $_.'Port' -match 'Down' } | Set-Style -Style Warning -Property 'Port'
+ $AggregatePorts | Where-Object { $_.'Port Participation' -ne 'full' } | Set-Style -Style Warning -Property 'Port Participation'
}
@@ -64,12 +61,12 @@ function Get-AbrOntapNetworkIfgrp {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$AggregatePorts | Table @TableParams
- if ($Healthcheck.Network.Port -and ($AggregatePorts | Where-Object { $_.'Port Participation' -ne "full" })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Network.Port -and ($AggregatePorts | Where-Object { $_.'Port Participation' -ne 'full' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all ports in the interface group are active and participating fully to maintain optimal network performance and redundancy."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all ports in the interface group are active and participating fully to maintain optimal network performance and redundancy.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapNetworkIpSpace.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIpSpace.ps1
similarity index 90%
rename from Src/Private/Get-AbrOntapNetworkIpSpace.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIpSpace.ps1
index 34eb286..8c0ff0a 100755
--- a/Src/Private/Get-AbrOntapNetworkIpSpace.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkIpSpace.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkIpSpace {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapNetworkIpSpace {
)
begin {
- Write-PScriboMessage "Collecting ONTAP IPSpace information."
+ Write-PScriboMessage 'Collecting ONTAP IPSpace information.'
}
process {
@@ -35,7 +35,7 @@ function Get-AbrOntapNetworkIpSpace {
'Ports' = $Item.Ports -join '; '
'Broadcast Domains' = $Item.BroadcastDomains -join '; '
}
- $IPSpaceObj = [pscustomobject]$inobj
+ $IPSpaceObj = [pscustomobject](ConvertTo-HashToYN $inObj)
$TableParams = @{
Name = "Network IPSpace - $($Item.Ipspace)"
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkMGMT.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkMGMT.ps1
new file mode 100755
index 0000000..946ea39
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkMGMT.ps1
@@ -0,0 +1,276 @@
+function Get-AbrOntapNetworkMgmt {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP network management interfaces information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP network management interface information.'
+ }
+
+ process {
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'cluster' }
+ if ($ClusterData) {
+ try {
+ Section -ExcludeFromTOC -Style Heading6 'Cluster Network Interfaces' {
+ $ClusterObj = @()
+ foreach ($Item in $ClusterData) {
+ try {
+ $inObj = [ordered] @{
+ 'Cluster Interface' = $Item.InterfaceName
+ 'Status' = ${Item}?.OpStatus?.ToString()?.ToUpper()
+ 'Data Protocols' = $Item.DataProtocols
+ 'Address' = $Item.Address
+ 'Home Node' = $Item.HomeNode
+ 'Vserver' = $Item.Vserver
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'Status' -notlike 'UP' } | Set-Style -Style Warning -Property 'Status'
+ }
+
+ $TableParams = @{
+ Name = "Cluster Network - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 27, 8, 12, 18, 17, 18
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and ($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all cluster network interfaces are operational (UP) to maintain cluster connectivity and performance.'
+ }
+ BlankLine
+ }
+ }
+
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'cluster_mgmt' -or $_.Role -eq 'node_mgmt' }
+ if ($ClusterData) {
+ Section -ExcludeFromTOC -Style Heading6 'Management Network Interfaces' {
+ $ClusterObj = @()
+ foreach ($Item in $ClusterData) {
+ try {
+ $inObj = [ordered] @{
+ 'MGMT Interface' = $Item.InterfaceName
+ 'Status' = ${Item}?.OpStatus?.ToString()?.ToUpper()
+ 'Data Protocols' = $Item.DataProtocols
+ 'Address' = $Item.Address
+ 'Home Node' = $Item.HomeNode
+ 'Vserver' = $Item.Vserver
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'Status' -notlike 'UP' } | Set-Style -Style Warning -Property 'Status'
+ }
+
+ $TableParams = @{
+ Name = "Management Network - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 27, 8, 17, 15, 15, 18
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and ($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all management network interfaces are operational (UP) to maintain proper management access to the cluster.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'intercluster' }
+ if ($ClusterData) {
+ Section -ExcludeFromTOC -Style Heading6 'Intercluster Network Interfaces' {
+ $ClusterObj = @()
+ foreach ($Item in $ClusterData) {
+ try {
+ $inObj = [ordered] @{
+ 'Intercluster Interface' = $Item.InterfaceName
+ 'Status' = ${Item}?.OpStatus?.ToString()?.ToUpper()
+ 'Data Protocols' = $Item.DataProtocols
+ 'Address' = $Item.Address
+ 'Home Node' = $Item.HomeNode
+ 'Vserver' = $Item.Vserver
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'Status' -notlike 'UP' } | Set-Style -Style Warning -Property 'Status'
+ }
+
+ $TableParams = @{
+ Name = "Intercluster Network - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 27, 8, 17, 15, 15, 18
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and ($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all intercluster network interfaces are operational (UP) to maintain cluster-to-cluster communication.'
+ }
+ BlankLine
+ }
+
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'data' -and $_.Vserver -notin $options.Exclude.Vserver }
+ if ($ClusterData) {
+ Section -ExcludeFromTOC -Style Heading6 'Data Network Interfaces' {
+ $ClusterObj = @()
+ foreach ($Item in $ClusterData) {
+ try {
+ if ($Item.Wwpn) {
+ $AddressData = $Item.Wwpn
+ } else { $AddressData = $Item.Address }
+ $inObj = [ordered] @{
+ 'Data Interface' = $Item.InterfaceName
+ 'Status' = ${Item}?.OpStatus?.ToString()?.ToUpper()
+ 'Data Protocols' = [string]$Item.DataProtocols
+ 'Address' = $AddressData
+ 'Home Node' = $Item.HomeNode
+ 'Vserver' = $Item.Vserver
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'Status' -notlike 'UP' } | Set-Style -Style Warning -Property 'Status'
+ }
+
+ $TableParams = @{
+ Name = "Data Network - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 25, 10, 17, 15, 15, 18
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and ($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all data network interfaces are operational (UP) to maintain optimal data access and performance.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.DataProtocols -ne 'fcp' -and $_.IsHome -like 'False' }
+ if ($ClusterData) {
+ Section -ExcludeFromTOC -Style Heading6 'Network Interfaces Home Status' {
+ Paragraph "The following table provides the LIF Home Status Information from $($ClusterInfo.ClusterName)."
+ BlankLine
+ $ClusterObj = @()
+ foreach ($Item in $ClusterData) {
+ try {
+ $inObj = [ordered] @{
+ 'Network Interface' = $Item.InterfaceName
+ 'Home Port' = $Item.HomeNode + ':' + $Item.HomePort
+ 'Current Port' = $Item.CurrentNode + ':' + $Item.CurrentPort
+ 'IsHome' = ($Item.IsHome -eq $True) ? 'Yes': 'No'
+ 'Vserver' = $Item.Vserver
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'IsHome' -ne 'Yes' } | Set-Style -Style Warning -Property 'Network Interface', 'IsHome', 'Home Port', 'Current Port', 'Vserver'
+ }
+
+ $TableParams = @{
+ Name = "Network Interfaces Home Status - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 20, 25, 25, 10, 20
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and ($ClusterObj | Where-Object { $_.'IsHome' -ne 'Yes' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all network interfaces are on their designated home ports to maintain optimal network performance and reliability.'
+ }
+ BlankLine
+ }
+
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapNetworkPorts.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkPorts.ps1
similarity index 67%
rename from Src/Private/Get-AbrOntapNetworkPorts.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkPorts.ps1
index 9deb02d..7078a76 100755
--- a/Src/Private/Get-AbrOntapNetworkPorts.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkPorts.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkPort {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,33 +23,31 @@ function Get-AbrOntapNetworkPort {
)
begin {
- Write-PScriboMessage "Collecting ONTAP physical interface information."
+ Write-PScriboMessage 'Collecting ONTAP physical interface information.'
}
process {
try {
$PhysicalPorts = Get-NcNetPort -Node $Node -Controller $Array | Where-Object { $_.PortType -like 'physical' }
if ($PhysicalPorts) {
- $PhysicalNic = foreach ($Nics in $PhysicalPorts) {
+ $OutObj = @()
+ foreach ($Nics in $PhysicalPorts) {
try {
- [PSCustomObject] @{
+ $inObj = [ordered] @{
'Port Name' = $Nics.Port
'Role' = $TextInfo.ToTitleCase($Nics.Role)
'Mac Address' = $Nics.MacAddress
'MTU' = $Nics.MTU
'Link Status' = $TextInfo.ToTitleCase($Nics.LinkStatus)
- 'Admin Status' = switch ($Nics.IsAdministrativeUp) {
- "True" { 'Up' }
- "False" { 'Down' }
- default { $Nics.IsAdministrativeUp }
- }
+ 'Admin Status' = $Nics.IsAdministrativeUp -eq $True ? 'Up': 'Down'
}
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Network.Port) {
- $PhysicalNic | Where-Object { $_.'Link Status' -like 'down' -and $_.'Admin Status' -like 'Up' } | Set-Style -Style Warning -Property 'Link Status'
+ $OutObj | Where-Object { $_.'Link Status' -like 'down' -and $_.'Admin Status' -like 'Up' } | Set-Style -Style Warning -Property 'Link Status'
}
$TableParams = @{
@@ -60,12 +58,12 @@ function Get-AbrOntapNetworkPort {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
- $PhysicalNic | Table @TableParams
- if ($Healthcheck.Network.Port -and ($PhysicalNic | Where-Object { $_.'Link Status' -like 'down' -and $_.'Admin Status' -like 'Up' })) {
- Paragraph "Health Check:" -Bold -Underline
+ $OutObj | Table @TableParams
+ if ($Healthcheck.Network.Port -and ($OutObj | Where-Object { $_.'Link Status' -like 'down' -and $_.'Admin Status' -like 'Up' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure that all physical network ports with an administrative status of 'Up' also have a link status of 'Up' to maintain optimal network connectivity."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapNetworkRoute.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRoute.ps1
similarity index 85%
rename from Src/Private/Get-AbrOntapNetworkRoute.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRoute.ps1
index e682990..316d6fc 100755
--- a/Src/Private/Get-AbrOntapNetworkRoute.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRoute.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkRoute {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapNetworkRoute {
)
begin {
- Write-PScriboMessage "Collecting ONTAP network route information."
+ Write-PScriboMessage 'Collecting ONTAP network route information.'
}
process {
@@ -37,9 +37,9 @@ function Get-AbrOntapNetworkRoute {
'Destination' = $Item.Destination
'Gateway' = $Item.Gateway
'Metric' = $Item.Metric
- 'Address Family' = $Item.AddressFamily.ToString()
+ 'Address Family' = ${Item}?.AddressFamily?.ToString()
}
- $RoutesObj += [pscustomobject]$inobj
+ $RoutesObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapNetworkRouteLifs.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRouteLifs.ps1
similarity index 85%
rename from Src/Private/Get-AbrOntapNetworkRouteLifs.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRouteLifs.ps1
index cfdf15f..42399f7 100755
--- a/Src/Private/Get-AbrOntapNetworkRouteLifs.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkRouteLifs.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkRouteLif {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapNetworkRouteLif {
)
begin {
- Write-PScriboMessage "Collecting ONTAP network route per lif information."
+ Write-PScriboMessage 'Collecting ONTAP network route per lif information.'
}
process {
@@ -37,9 +37,9 @@ function Get-AbrOntapNetworkRouteLif {
'Destination' = $Item.Destination
'Gateway' = $Item.Gateway
'Lif Names' = $Item.LifNames
- 'Address Family' = $Item.AddressFamily.ToString()
+ 'Address Family' = ${Item}?.AddressFamily?.ToString()
}
- $RoutesObj += [pscustomobject]$inobj
+ $RoutesObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapNetworkSubnet.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkSubnet.ps1
similarity index 90%
rename from Src/Private/Get-AbrOntapNetworkSubnet.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkSubnet.ps1
index b046cd1..cee259c 100755
--- a/Src/Private/Get-AbrOntapNetworkSubnet.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkSubnet.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkSubnet {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapNetworkSubnet {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Subnets information."
+ Write-PScriboMessage 'Collecting ONTAP Subnets information.'
}
process {
@@ -37,7 +37,7 @@ function Get-AbrOntapNetworkSubnet {
'Used IP' = $Item.Used
'Ip Ranges' = $Item.IpRanges
}
- $SubnetObj += [pscustomobject]$inobj
+ $SubnetObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapNetworkVlans.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkVlans.ps1
similarity index 90%
rename from Src/Private/Get-AbrOntapNetworkVlans.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkVlans.ps1
index dba8b79..cb19877 100755
--- a/Src/Private/Get-AbrOntapNetworkVlans.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNetworkVlans.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNetworkVlan {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapNetworkVlan {
)
begin {
- Write-PScriboMessage "Collecting ONTAP VLAN information."
+ Write-PScriboMessage 'Collecting ONTAP VLAN information.'
}
process {
@@ -38,7 +38,7 @@ function Get-AbrOntapNetworkVlan {
'Parent Interface' = $Item.ParentInterface
'Vlan ID' = $Item.VlanID
}
- $VlanObj += [pscustomobject]$inobj
+ $VlanObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapNodeAggrDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeAggrDiagram.ps1
similarity index 59%
rename from Src/Private/Get-AbrOntapNodeAggrDiagram.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeAggrDiagram.ps1
index 10f40eb..a9273c6 100644
--- a/Src/Private/Get-AbrOntapNodeAggrDiagram.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeAggrDiagram.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapStorageAggrDiagram {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapStorageAggrDiagram {
)
begin {
- Write-PScriboMessage "Generating Storage Aggregates Diagram for NetApp ONTAP."
+ Write-PScriboMessage 'Generating Storage Aggregates Diagram for NetApp ONTAP.'
# Used for DiagramDebug
if ($Options.EnableDiagramDebug) {
$EdgeDebug = @{style = 'filled'; color = 'red' }
@@ -52,7 +52,7 @@ function Get-AbrOntapStorageAggrDiagram {
$ClusterInfo = Get-NcCluster -Controller $Array
$NodeSum = Get-NcNode -Controller $Array
- SubGraph Cluster -Attributes @{Label = $ClusterInfo.ClusterName; fontsize = 22; penwidth = 1.5; labelloc = 't'; style = "dashed,rounded"; color = "gray" } {
+ SubGraph Cluster -Attributes @{Label = $ClusterInfo.ClusterName; fontsize = 22; penwidth = 1.5; labelloc = 't'; style = 'dashed,rounded'; color = 'gray' } {
try {
if ($NodeSum.Count -eq 1) {
@@ -76,22 +76,22 @@ function Get-AbrOntapStorageAggrDiagram {
if ($ClusterHa.Name -notin $HAObject.Partner) {
$HAObject += [PSCustomObject][ordered]@{
- "Name" = $ClusterHa.Name
- "Partner" = $ClusterHa.Partner
- "HAState" = $ClusterHa.State
+ 'Name' = $ClusterHa.Name
+ 'Partner' = $ClusterHa.Partner
+ 'HAState' = $ClusterHa.State
}
}
$NodeAdditionalInfo += [PSCustomObject][ordered]@{
'NodeName' = $Node.Node
'AdditionalInfo' = [PSCustomObject][ordered]@{
- "System Id" = $Node.NodeSystemId
- "Serial" = $Node.NodeSerialNumber
- "Model" = $Node.NodeSerialNumber
- "Mgmt" = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
- $true { "Unknown" }
- $false { $NodeMgmtAddress }
- default { "Unknown" }
+ 'System Id' = $Node.NodeSystemId
+ 'Serial' = $Node.NodeSerialNumber
+ 'Model' = $Node.NodeModel
+ 'Mgmt' = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
+ $true { 'Unknown' }
+ $false { $NodeMgmtAddress -join ', ' }
+ default { 'Unknown' }
}
}
}
@@ -99,33 +99,33 @@ function Get-AbrOntapStorageAggrDiagram {
$NodeAggr = Get-NcAggr | Where-Object { $_.Nodes -eq $Node.Node }
foreach ($Aggr in $NodeAggr) {
$AggrInfo += [PSCustomObject][ordered]@{
- "NodeName" = $Node.Node
- "AggregateName" = $Aggr.Name
- "AdditionalInfo" = [PSCustomObject][ordered]@{
- "Total Size" = $Aggr.TotalSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- "Used Space" = ($Aggr.TotalSize - $Aggr.Available) | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- "Assigned Disk" = $Aggr.Disks
- "Raid Type" = switch ([string]::IsNullOrEmpty($Aggr.RaidType)) {
- $true { "Unknown" }
+ 'NodeName' = $Node.Node
+ 'AggregateName' = $Aggr.Name
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'Total Size' = $Aggr.TotalSize | ConvertTo-FormattedNumber -NumberFormatString 0.0 -Type Datasize -ErrorAction SilentlyContinue
+ 'Used Space' = ($Aggr.TotalSize - $Aggr.Available) | ConvertTo-FormattedNumber -NumberFormatString 0.0 -Type Datasize -ErrorAction SilentlyContinue
+ 'Assigned Disk' = $Aggr.Disks
+ 'Raid Type' = switch ([string]::IsNullOrEmpty($Aggr.RaidType)) {
+ $true { 'Unknown' }
$false {
& {
- switch ($Aggr.RaidType.Split(", ")[0]) {
- "raid4" { "RAID 4" }
- "raid_dp" { "RAID DP" }
- "raid0" { "RAID 0" }
- "raid1" { "RAID 1" }
- "raid10" { "RAID 10" }
- default { "Unknown" }
+ switch ($Aggr.RaidType.Split(', ')[0]) {
+ 'raid4' { 'RAID 4' }
+ 'raid_dp' { 'RAID DP' }
+ 'raid0' { 'RAID 0' }
+ 'raid1' { 'RAID 1' }
+ 'raid10' { 'RAID 10' }
+ default { 'Unknown' }
}
}
}
- default { "Unknown" }
+ default { 'Unknown' }
}
- "Raid Size" = $Aggr.RaidSize
- "State" = switch ([string]::IsNullOrEmpty($Aggr.State)) {
- $true { "Unknown" }
+ 'Raid Size' = $Aggr.RaidSize
+ 'State' = switch ([string]::IsNullOrEmpty($Aggr.State)) {
+ $true { 'Unknown' }
$false { $Aggr.State.ToUpper() }
- default { "Unknown" }
+ default { 'Unknown' }
}
}
}
@@ -136,7 +136,7 @@ function Get-AbrOntapStorageAggrDiagram {
foreach ($Node in $NodeAdditionalInfo) {
$ClusterNodeObj = @()
- $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
+ $ClusterNodeObj += Add-HtmlNodeTable -Name 'ClusterNodeObj' -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
if ($ClusterNodeObj) {
if ($AggrInfo.Count -eq 1) {
@@ -146,11 +146,11 @@ function Get-AbrOntapStorageAggrDiagram {
} else {
$AggrInfoColumnSize = $AggrInfo.Count
}
- $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
+ $ClusterNodeObj += Add-HtmlNodeTable -Name 'ClusterNodeObj' -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
}
if ($ClusterNodeObj) {
- $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
+ $ClusterNodeSubgraphObj = Add-HtmlSubGraph -Name 'ClusterNodeSubgraphObj' -ImagesObj $Images -TableArray $ClusterNodeObj -Align 'Center' -IconDebug $IconDebug -Label ' ' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder 1 -ColumnSize 1 -FontSize 12
}
$ClusterNodesObj += $ClusterNodeSubgraphObj
@@ -164,13 +164,13 @@ function Get-AbrOntapStorageAggrDiagram {
} else {
$ClusterNodesObjColumnSize = $ClusterNodesObj.Count
}
- $ClusterMgmtObj = Add-DiaHtmlSubGraph -ImagesObj $Images -TableArray $ClusterNodesObj -Align 'Right' -IconDebug $IconDebug -Label "Management: $($ClusterInfo.NcController.Name)" -LabelPos 'down' -TableStyle "dashed,rounded" -TableBorderColor $Edgecolor -TableBorder 0 -ColumnSize $ClusterNodesObjColumnSize -FontSize 18
+ $ClusterMgmtObj = Add-HtmlSubGraph -Name 'ClusterMgmtObj' -ImagesObj $Images -TableArray $ClusterNodesObj -Align 'Right' -IconDebug $IconDebug -Label "Management: $($ClusterInfo.NcController.Name)" -LabelPos 'down' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder 0 -ColumnSize $ClusterNodesObjColumnSize -FontSize 18
if ($ClusterMgmtObj) {
Node ClusterAggrs @{Label = $ClusterMgmtObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
} else {
- Write-PScriboMessage -IsWarning "Unable to create ClusterNodesObj. No Cluster Management Object found."
+ Write-PScriboMessage -IsWarning 'Unable to create ClusterNodesObj. No Cluster Management Object found.'
}
}
} catch {
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeNetworkDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeNetworkDiagram.ps1
new file mode 100644
index 0000000..718c1f0
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeNetworkDiagram.ps1
@@ -0,0 +1,343 @@
+function Get-AbrOntapNodeNetworkDiagram {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to built NetApp ONTAP node network diagram
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Generating Node Network Diagram for NetApp ONTAP.'
+ # Set the root path for icons
+ $RootPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
+ [System.IO.FileInfo]$IconPath = Join-Path $RootPath 'icons'
+
+ # Used for DiagramDebug
+ if ($Options.EnableDiagramDebug) {
+ $EdgeDebug = @{style = 'filled'; color = 'red' }
+ $SubGraphDebug = @{style = 'dashed'; color = 'red' }
+ $NodeDebug = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $NodeDebugEdge = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $IconDebug = $true
+ } else {
+ $EdgeDebug = @{style = 'invis'; color = 'red' }
+ $SubGraphDebug = @{style = 'invis'; color = 'gray' }
+ $NodeDebug = @{color = 'transparent'; style = 'transparent'; shape = 'point' }
+ $NodeDebugEdge = @{color = 'transparent'; style = 'transparent'; shape = 'none' }
+ $IconDebug = $false
+ }
+
+ if ($Options.DiagramTheme -eq 'Black') {
+ $Edgecolor = 'White'
+ $Fontcolor = 'White'
+ } elseif ($Options.DiagramTheme -eq 'Neon') {
+ $Edgecolor = 'gold2'
+ $Fontcolor = 'gold2'
+ } else {
+ $Edgecolor = '#71797E'
+ $Fontcolor = '#565656'
+ }
+ }
+
+ process {
+ try {
+ $ClusterInfo = Get-NcCluster -Controller $Array
+ $NodeSum = Get-NcNode -Controller $Array
+
+ try {
+
+ $HAObject = @()
+
+ $NodeAdditionalInfo = @()
+ $NetPortInfo = @()
+ $NetLifsInfo = @()
+ $NetVlanInfo = @()
+
+ foreach ($Node in $NodeSum) {
+ $ClusterHa = Get-NcClusterHa -Node $Node.Node -Controller $Array
+
+ $NodeMgmtAddress = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'node_mgmt' -and $_.HomeNode -eq $Node.Node } | Select-Object -ExpandProperty Address
+
+ if ($ClusterHa.Name -notin $HAObject.Partner) {
+ $HAObject += [PSCustomObject][ordered]@{
+ 'Name' = $ClusterHa.Name
+ 'Partner' = $ClusterHa.Partner
+ 'HAState' = $ClusterHa.State
+ }
+ }
+
+ $NodeAdditionalInfo += [PSCustomObject][ordered]@{
+ 'NodeName' = $Node.Node
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'System Id' = $Node.NodeSystemId
+ 'Serial' = $Node.NodeSerialNumber
+ 'Model' = $Node.NodeModel
+ 'Mgmt' = switch ([string]::IsNullOrEmpty($NodeMgmtAddress)) {
+ $true { 'Unknown' }
+ $false { $NodeMgmtAddress -join ', ' }
+ default { 'Unknown' }
+ }
+ }
+ }
+
+ $NodePorts = Get-NcNetPort -Controller $Array | Where-Object { $_.Node -eq $Node.Node }
+ foreach ($NodePort in $NodePorts) {
+ $NetPortInfo += [PSCustomObject][ordered]@{
+ 'NodeName' = $NodePort.Node
+ 'PortName' = $NodePort.Name
+ 'PortType' = $NodePort.PortType
+ 'IsParentVlan' = & { if (Get-NcNetPortVlan -Controller $Array -ParentInterface $NodePort.Name -Node $Node.Node) { $true } else { $false } }
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'Health' = $NodePort.HealthStatus
+ 'Broadcast Domain' = switch ([string]::IsNullOrEmpty($NodePort.BroadcastDomain)) {
+ $true { 'Unknown' }
+ $false { $NodePort.BroadcastDomain }
+ default { 'Unknown' }
+ }
+ 'Ifgrp Port' = switch ([string]::IsNullOrEmpty($NodePort.IfgrpPort)) {
+ $true { 'None' }
+ $false { $NodePort.IfgrpPort }
+ default { 'Unknown' }
+ }
+ 'Ipspace' = $NodePort.IpSpace
+ 'Link Status' = switch ($NodePort.LinkStatus) {
+ 'up' { 'Up' }
+ 'down' { 'Down' }
+ default { 'Unknown' }
+ }
+ 'Mac' = $NodePort.MacAddress
+ 'Mtu' = $NodePort.Mtu
+ }
+ }
+ }
+
+ $NodeLifs = Get-NcNetInterface -Controller $Array | Where-Object { $_.HomeNode -eq $Node.Node -and $_.DataProtocols -ne 'fcp' }
+ foreach ($NodeLif in $NodeLifs) {
+ $NetLifsInfo += [PSCustomObject][ordered]@{
+ 'NodeName' = $NodeLif.HomeNode
+ 'InterfaceName' = $NodeLif.InterfaceName
+ 'HomeNode' = $NodeLif.HomeNode
+ 'HomePort' = $NodeLif.HomePort
+ 'CurrentNode' = $NodeLif.CurrentNode
+ 'CurrentPort' = $NodeLif.CurrentPort
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'IP' = $NodeLif.Address
+ 'Netmask' = $NodeLif.Netmask
+ 'Is Home?' = switch ($NodeLif.IsHome) {
+ $true { 'Yes' }
+ $false { 'No' }
+ default { 'Unknown' }
+ }
+ 'Status' = switch ($NodeLif.AdministrativeStatus) {
+ 'up' { 'Up' }
+ 'down' { 'Down' }
+ default { 'Unknown' }
+ }
+ 'Role' = switch ([string]::IsNullOrEmpty($NodeLif.Role)) {
+ $true { 'Unknown' }
+ $false { $TextInfo.ToTitleCase($NodeLif.Role) }
+ default { 'Unknown' }
+ }
+ }
+ }
+ }
+
+ $NodeVlans = Get-NcNetPortVlan -Node $Node.Node -Controller $Array
+ foreach ($NodeVlan in $NodeVlans) {
+ $NetVlanInfo += [PSCustomObject][ordered]@{
+ 'NodeName' = $NodeVlan.Node
+ 'InterfaceName' = $NodeVlan.InterfaceName
+ 'ParentInterface' = $NodeVlan.ParentInterface
+ 'VlanID' = $NodeVlan.VlanID
+ }
+ }
+ }
+
+ # Cluster Network Diagram
+ $ClusterNetwork = Add-NodeImage -Name 'ClusterSwitch1' -ImagesObj $Images -IconType 'Ontap_Cluster_Network' -IconDebug $IconDebug -TableBackgroundColor '#a1e3fd'
+
+ Add-HtmlSubGraph -Name 'ClusterNetwork' -TableArray $ClusterNetwork -Label 'Cluster Network' -LabelPos top -ImagesObj $Images -IconDebug $IconDebug -NodeObject -TableBorder 1 -FontSize 20 -TableBorderColor '#71797E' -TableStyle 'rounded,dashed' -FontColor 'darkblue' -FontBold -FontName 'Segoe Ui Bold' -TableBackgroundColor '#a1e3fd'
+
+ foreach ($Node in $NodeAdditionalInfo) {
+
+ # Ontap System Node
+ Add-NodeIcon -Name $Node.NodeName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Node' -IconDebug $IconDebug -AditionalInfo $Node.AdditionalInfo -TableBorder 1 -FontSize 18 -NodeObject -TableBorderColor '#71797E' -TableStyle 'rounded,dashed'
+
+
+ if ($NetPortInfo) {
+ # Cluster Network Ports
+ $ClusterPortObj = @()
+ foreach ($Port in ($NetPortInfo | Where-Object { $_.Nodename -eq $Node.Nodename -and $_.AdditionalInfo.'Broadcast Domain' -eq 'Cluster' })) {
+
+ $PerPortLifs = @()
+ foreach ($Lif in ($NetLifsInfo | Where-Object { $_.NodeName -eq $Node.Nodename -and $_.CurrentPort -eq $Port.PortName })) {
+ $PerPortLifs += if ($Lif.AdditionalInfo.'Is Home?' -eq 'Yes') {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12
+ } else {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12 -TableBackgroundColor '#ffcccc' -CellBackgroundColor '#ffcccc'
+ }
+ }
+
+ if (-not $PerPortLifs) {
+ $PerPortLifs = Add-NodeIcon -Name "$($Port.NodeName)_$($Port.PortName)_NoLifs" -LabelName 'No LIFs Assigned' -ImagesObj $Images -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -FontSize 12 -ImageSizePercent 50 -AditionalInfo @() -IconPath $IconPath
+ }
+
+ if ($PerPortLifs.Count -eq 1) { $PerPortLifsColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $PerPortLifsColumnSize = $Options.DiagramColumnSize } else { $PerPortLifsColumnSize = $PerPortLifs.Count }
+
+ $ClusterPortObj += Add-HtmlSubGraph -Name "$($Port.NodeName)$($Port.PortName)_Lifs" -TableArray $PerPortLifs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -Label $Port.PortName -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $PerPortLifsColumnSize
+ }
+
+ if ($ClusterPortObj.Count -eq 1) { $ClusterPortObjColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $ClusterPortObjColumnSize = $Options.DiagramColumnSize } else { $ClusterPortObjColumnSize = $ClusterPortObj.Count }
+
+ Add-HtmlSubGraph -Name "$($Port.NodeName)ClusterPorts" -TableArray $ClusterPortObj -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -IconType 'Ontap_Network_Port' -Label 'Cluster Network Ports' -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $ClusterPortObjColumnSize -NodeObject
+
+ Add-NodeEdge -From 'ClusterNetwork' -To "$($Port.NodeName)ClusterPorts" -EdgeColor $Edgecolor -EdgeStyle 'dashed' -EdgeThickness 1 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 12
+
+ Add-NodeEdge -From "$($Port.NodeName)ClusterPorts" -To $Node.NodeName -EdgeColor $Edgecolor -EdgeStyle 'dashed' -EdgeThickness 1 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 12 -EdgeLength 1
+
+ # Non-IFGRP Ports without Vlan Interfces
+ foreach ($Port in ($NetPortInfo | Where-Object { $_.Nodename -eq $Node.Nodename -and $_.AdditionalInfo.'Broadcast Domain' -ne 'Cluster' -and $_.AdditionalInfo.'Ifgrp Port' -in @('None', 'Unknown') -and $_.PortName -notmatch 'a0' -and $_.PortType -ne 'vlan' -and $_.IsParentVlan -eq $false })) {
+ $PerPortLifs = @()
+ foreach ($Lif in ($NetLifsInfo | Where-Object { $_.CurrentNode -eq $Node.Nodename -and $_.CurrentPort -eq $Port.PortName })) {
+ $PerPortLifs += if ($Lif.AdditionalInfo.'Is Home?' -eq 'Yes') {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12
+ } else {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12 -TableBackgroundColor '#ffcccc' -CellBackgroundColor '#ffcccc'
+ }
+ }
+
+ if (-not $PerPortLifs) {
+ $PerPortLifs = Add-NodeIcon -Name "$($Port.NodeName)_$($Port.PortName)_NoLifs" -LabelName 'No LIFs Assigned' -ImagesObj $Images -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -FontSize 12 -ImageSizePercent 50 -AditionalInfo @() -IconPath $IconPath
+ }
+
+ if ($PerPortLifs.Count -eq 1) { $PerPortLifsColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $PerPortLifsColumnSize = $Options.DiagramColumnSize } else { $PerPortLifsColumnSize = $PerPortLifs.Count }
+
+ Add-HtmlSubGraph -Name "$($Port.NodeName)$($Port.PortName)_Lifs" -TableArray $PerPortLifs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -IconType 'Ontap_Network_Port' -Label $Port.PortName -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -NodeObject -ColumnSize $PerPortLifsColumnSize
+
+ Add-NodeEdge -From $Node.NodeName -To "$($Port.NodeName)$($Port.PortName)_Lifs" -EdgeColor $Edgecolor -EdgeStyle 'dashed' -EdgeThickness 1 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 12 -EdgeLength 1
+ }
+
+ # IFGRP Ports (Link Aggregation Groups) with member ports and LIFs
+ foreach ($IfgrpPort in ($NetPortInfo | Where-Object { $_.Nodename -eq $Node.Nodename -and $_.PortType -eq 'ifgrp' })) {
+ $IfgrpPortLifs = @()
+ foreach ($Lif in ($NetLifsInfo | Where-Object { $_.CurrentNode -eq $Node.Nodename -and $_.CurrentPort -eq $IfgrpPort.PortName })) {
+ $IfgrpPortLifs += if ($Lif.AdditionalInfo.'Is Home?' -eq 'Yes') {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12
+ } else {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12 -TableBackgroundColor '#ffcccc' -CellBackgroundColor '#ffcccc'
+ }
+ }
+
+ if (-not $IfgrpPortLifs) {
+ $IfgrpPortLifs = Add-NodeIcon -Name "$($IfgrpPort.NodeName)_$($IfgrpPort.PortName)_NoLifs" -LabelName 'No LIFs Assigned' -ImagesObj $Images -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -FontSize 12 -ImageSizePercent 50 -AditionalInfo @() -IconPath $IconPath
+ }
+
+ if ($IfgrpPortLifs.Count -eq 1) { $IfgrpPortLifsColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $IfgrpPortLifsColumnSize = $Options.DiagramColumnSize } else { $IfgrpPortLifsColumnSize = $IfgrpPortLifs.Count }
+
+ # Member physical ports of this IFGRP
+ $MemberPortItems = @()
+ foreach ($MemberPort in ($NetPortInfo | Where-Object { $_.Nodename -eq $Node.Nodename -and $_.AdditionalInfo.'Ifgrp Port' -eq $IfgrpPort.PortName })) {
+ $MemberPortItems += Add-NodeText -Name "$($MemberPort.NodeName)_$($MemberPort.PortName)_MemberPort" -Text $MemberPort.PortName -IconDebug $IconDebug -FontSize 12
+ }
+
+ $IfgrpPortObj = @()
+ if ($MemberPortItems) {
+ if ($MemberPortItems.Count -eq 1) { $MemberPortColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $MemberPortColumnSize = $Options.DiagramColumnSize } else { $MemberPortColumnSize = $MemberPortItems.Count }
+ $IfgrpPortObj += Add-HtmlSubGraph -Name "$($IfgrpPort.NodeName)$($IfgrpPort.PortName)_Members" -TableArray $MemberPortItems -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -Label 'Member Ports' -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $MemberPortColumnSize
+ }
+
+ $IfgrpPortObj += Add-HtmlSubGraph -Name "$($IfgrpPort.NodeName)$($IfgrpPort.PortName)_IfgrpLifs" -TableArray $IfgrpPortLifs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -Label $IfgrpPort.PortName -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $IfgrpPortLifsColumnSize
+
+ # Child VLAN interfaces grouped under this IFGRP port
+ if ($NetVlanInfo) {
+ foreach ($VlanPort in ($NetVlanInfo | Where-Object { $_.NodeName -eq $Node.Nodename -and $_.ParentInterface -eq $IfgrpPort.PortName })) {
+ $IfgrpVlanLifs = @()
+ foreach ($Lif in ($NetLifsInfo | Where-Object { $_.CurrentNode -eq $Node.Nodename -and $_.CurrentPort -eq $VlanPort.InterfaceName })) {
+ $IfgrpVlanLifs += if ($Lif.AdditionalInfo.'Is Home?' -eq 'Yes') {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12
+ } else {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12 -TableBackgroundColor '#ffcccc' -CellBackgroundColor '#ffcccc'
+ }
+ }
+
+ if (-not $IfgrpVlanLifs) {
+ $IfgrpVlanLifs = Add-NodeIcon -Name "$($VlanPort.NodeName)_$($VlanPort.InterfaceName)_NoLifs" -LabelName 'No LIFs Assigned' -ImagesObj $Images -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -FontSize 12 -ImageSizePercent 50 -AditionalInfo @() -IconPath $IconPath
+ }
+
+ if ($IfgrpVlanLifs.Count -eq 1) { $IfgrpVlanLifsColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $IfgrpVlanLifsColumnSize = $Options.DiagramColumnSize } else { $IfgrpVlanLifsColumnSize = $IfgrpVlanLifs.Count }
+
+ $IfgrpPortObj += Add-HtmlSubGraph -Name "$($VlanPort.NodeName)$($VlanPort.InterfaceName)_VlanLifs" -TableArray $IfgrpVlanLifs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -Label "$($VlanPort.InterfaceName) (VLAN $($VlanPort.VlanID))" -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $IfgrpVlanLifsColumnSize
+ }
+ }
+
+ if ($IfgrpPortObj.Count -eq 1) { $IfgrpPortObjColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $IfgrpPortObjColumnSize = $Options.DiagramColumnSize } else { $IfgrpPortObjColumnSize = $IfgrpPortObj.Count }
+
+ Add-HtmlSubGraph -Name "$($IfgrpPort.NodeName)$($IfgrpPort.PortName)_Ifgrp" -TableArray $IfgrpPortObj -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -IconType 'Ontap_Network_Port' -Label "$($IfgrpPort.PortName) (IFGRP)" -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -NodeObject -ColumnSize $IfgrpPortObjColumnSize
+
+ Add-NodeEdge -From $Node.NodeName -To "$($IfgrpPort.NodeName)$($IfgrpPort.PortName)_Ifgrp" -EdgeColor $Edgecolor -EdgeStyle 'dashed' -EdgeThickness 1 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 12 -EdgeLength 1
+ }
+
+ # Physical Parent Ports with grouped Child VLAN Interfaces
+ if ($NetVlanInfo) {
+ foreach ($ParentPort in ($NetPortInfo | Where-Object { $_.Nodename -eq $Node.Nodename -and $_.IsParentVlan -eq $true -and $_.PortType -ne 'ifgrp' -and $_.AdditionalInfo.'Broadcast Domain' -ne 'Cluster' -and $_.AdditionalInfo.'Ifgrp Port' -in @('None', 'Unknown') })) {
+ $ChildVlanObjs = @()
+ foreach ($VlanPort in ($NetVlanInfo | Where-Object { $_.NodeName -eq $Node.Nodename -and $_.ParentInterface -eq $ParentPort.PortName })) {
+ $VlanPortLifs = @()
+ foreach ($Lif in ($NetLifsInfo | Where-Object { $_.CurrentNode -eq $Node.Nodename -and $_.CurrentPort -eq $VlanPort.InterfaceName })) {
+ $VlanPortLifs += if ($Lif.AdditionalInfo.'Is Home?' -eq 'Yes') {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12
+ } else {
+ Add-NodeIcon -Name $Lif.InterfaceName -ImagesObj $Images -Align 'Center' -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -AditionalInfo $Lif.AdditionalInfo -ImageSizePercent 50 -IconPath $IconPath -FontSize 12 -TableBackgroundColor '#ffcccc' -CellBackgroundColor '#ffcccc'
+ }
+ }
+
+ if (-not $VlanPortLifs) {
+ $VlanPortLifs = Add-NodeIcon -Name "$($VlanPort.NodeName)_$($VlanPort.InterfaceName)_NoLifs" -LabelName 'No LIFs Assigned' -ImagesObj $Images -IconType 'Ontap_Network_Nic' -IconDebug $IconDebug -FontSize 12 -ImageSizePercent 50 -AditionalInfo @() -IconPath $IconPath
+ }
+
+ if ($VlanPortLifs.Count -eq 1) { $VlanPortLifsColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $VlanPortLifsColumnSize = $Options.DiagramColumnSize } else { $VlanPortLifsColumnSize = $VlanPortLifs.Count }
+
+ $ChildVlanObjs += Add-HtmlSubGraph -Name "$($VlanPort.NodeName)$($VlanPort.InterfaceName)_VlanLifs" -TableArray $VlanPortLifs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -Label "$($VlanPort.InterfaceName) (VLAN $($VlanPort.VlanID))" -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -ColumnSize $VlanPortLifsColumnSize
+ }
+
+ if ($ChildVlanObjs) {
+ if ($ChildVlanObjs.Count -eq 1) { $ChildVlanColumnSize = 1 } elseif ($Options.DiagramColumnSize) { $ChildVlanColumnSize = $Options.DiagramColumnSize } else { $ChildVlanColumnSize = $ChildVlanObjs.Count }
+
+ Add-HtmlSubGraph -Name "$($ParentPort.NodeName)$($ParentPort.PortName)_ParentVlanPort" -TableArray $ChildVlanObjs -ImagesObj $Images -IconDebug $IconDebug -TableBorder 1 -IconType 'Ontap_Network_Port' -Label $ParentPort.PortName -LabelPos top -TableStyle 'rounded,dashed' -TableBorderColor '#71797E' -FontName 'Segoe Ui Bold' -NodeObject -ColumnSize $ChildVlanColumnSize
+
+ Add-NodeEdge -From $Node.NodeName -To "$($ParentPort.NodeName)$($ParentPort.PortName)_ParentVlanPort" -EdgeColor $Edgecolor -EdgeStyle 'dashed' -EdgeThickness 1 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 12 -EdgeLength 1
+ }
+ }
+ }
+ }
+ }
+
+ foreach ($HA in $HAObject) {
+ if ($HA.Partner) {
+ Add-NodeEdge -From $HA.Name -To $HA.Partner -EdgeColor $Edgecolor -EdgeStyle 'solid' -EdgeThickness 2 -Arrowhead 'box' -Arrowtail 'box' -EdgeLabel "HA: $($HA.HAState)" -EdgeLabelFontColor $Fontcolor -EdgeLabelFontSize 16 -EdgeLength 3 -TailPort $HA.Name -HeadPort $HA.Partner
+ Rank $HA.Name, $HA.Partner
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapNodeStorage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeStorage.ps1
similarity index 65%
rename from Src/Private/Get-AbrOntapNodeStorage.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeStorage.ps1
index af6f9ff..3f34217 100755
--- a/Src/Private/Get-AbrOntapNodeStorage.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodeStorage.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNodeStorage {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapNodeStorage {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Node Storage information."
+ Write-PScriboMessage 'Collecting ONTAP Node Storage information.'
}
process {
@@ -32,36 +32,34 @@ function Get-AbrOntapNodeStorage {
$inObj = [ordered] @{
'Node' = $Item.Vserver
'Aggregate' = $Item.Aggregate
- 'Volume' = $Item.Name
- 'Capacity' = $Item.Totalsize | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Available' = $Item.Available | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Used' = $Item.Used | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Totalsize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Available' = ($Item.Available | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Used' = ($Item.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Node.HW) {
- $OutObj | Where-Object { $_.'Status' -like 'offline' } | Set-Style -Style Warning -Property 'Status'
$OutObj | Where-Object { $_.'Used' -ge 90 } | Set-Style -Style Critical -Property 'Used'
}
$TableParams = @{
Name = "Node Storage - $($ClusterInfo.ClusterName)"
List = $false
- ColumnWidths = 30, 30, 10, 10, 10, 10
+ ColumnWidths = 30, 30, 15, 15, 10
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$OutObj | Table @TableParams
if ($Healthcheck.Node.HW -and (($OutObj | Where-Object { $_.'Status' -like 'offline' }) -or ($OutObj | Where-Object { $_.'Used' -ge 90 }))) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all nodes are online and that storage usage is within acceptable limits."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all nodes are online and that storage usage is within acceptable limits.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapNodes.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodes.ps1
similarity index 80%
rename from Src/Private/Get-AbrOntapNodes.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodes.ps1
index a4f5eeb..22496db 100755
--- a/Src/Private/Get-AbrOntapNodes.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodes.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapNode {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,22 +19,24 @@ function Get-AbrOntapNode {
)
begin {
- Write-PScriboMessage "Collecting ONTAP node information."
+ Write-PScriboMessage 'Collecting ONTAP node information.'
}
process {
try {
$NodeSum = Get-NcNode -Controller $Array
if ($NodeSum) {
- $NodeSummary = foreach ($Nodes in $NodeSum) {
+ $OutObj = @()
+ foreach ($Nodes in $NodeSum) {
try {
- [PSCustomObject] @{
+ $inObj = [ordered] @{
'Name' = $Nodes.Node
'Model' = $Nodes.NodeModel
'Id' = $Nodes.NodeSystemId
'Serial' = $Nodes.NodeSerialNumber
'Uptime' = $Nodes.NodeUptimeTS
}
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -47,7 +49,7 @@ function Get-AbrOntapNode {
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
- $NodeSummary | Table @TableParams
+ $OutObj | Table @TableParams
}
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesHW.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesHW.ps1
new file mode 100755
index 0000000..43e20bd
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesHW.ps1
@@ -0,0 +1,83 @@
+function Get-AbrOntapNodesHW {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP system nodes hardware information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Node Hardware information.'
+ }
+
+ process {
+ try {
+ $NodeHW = Get-NcNodeInfo -Controller $Array -ErrorAction Continue
+ if ($NodeHW) {
+ $Outobj = @()
+ foreach ($NodeHWs in $NodeHW) {
+ Section -ExcludeFromTOC -Style NOTOCHeading5 $($NodeHWs.SystemName) {
+ try {
+ $NodeInfo = Get-NcNode -Node $NodeHWs.SystemName -Controller $Array
+ $Inobj = [ordered] @{
+ 'System Type' = $NodeHWs.SystemMachineType
+ 'CPU Count' = $NodeHWs.NumberOfProcessors
+ 'Total Memory' = ("$($NodeHWs.MemorySize / 1024)GB") ?? '--'
+ 'Vendor' = $NodeHWs.VendorId
+ 'AFF/FAS' = $NodeHWs.ProdType
+ 'All Flash Optimized' = $NodeInfo.IsAllFlashOptimized
+ 'Cloud Optimized' = $NodeInfo.IsCloudOptimized
+ 'Epsilon' = $NodeInfo.IsEpsilonNode
+ 'System Healthy' = ($NodeInfo.IsNodeHealthy -eq $True) ? 'Healthy': 'UnHealthy'
+ 'Failed Fan Count' = $NodeInfo.EnvFailedFanCount
+ 'Failed Fan Error' = $NodeInfo.EnvFailedFanMessage
+ 'Failed PowerSupply Count' = $NodeInfo.EnvFailedPowerSupplyCount
+ 'Failed PowerSupply Error' = $NodeInfo.EnvFailedPowerSupplyMessage
+ 'Over Temperature' = ($NodeInfo.EnvOverTemperature -eq $True) ? 'High Temperature': 'Normal Temperature'
+ 'NVRAM Battery Healthy' = $NodeInfo.NvramBatteryStatus
+ }
+ $Outobj = [pscustomobject](ConvertTo-HashToYN $inObj)
+
+ if ($Healthcheck.Node.HW) {
+ $Outobj | Where-Object { $_.'System Healthy' -like 'UnHealthy' } | Set-Style -Style Critical -Property 'System Healthy'
+ $Outobj | Where-Object { $_.'Failed Fan Count' -gt 0 } | Set-Style -Style Critical -Property 'Failed Fan Count'
+ $Outobj | Where-Object { $_.'Failed PowerSupply Count' -gt 0 } | Set-Style -Style Critical -Property 'Failed PowerSupply Count'
+ $Outobj | Where-Object { $_.'Over Temperature' -like 'High Temperature' } | Set-Style -Style Critical -Property 'Over Temperature'
+ $Outobj | Where-Object { $_.'NVRAM Battery Healthy' -notlike 'battery_ok' } | Set-Style -Style Critical -Property 'NVRAM Battery Healthy'
+ }
+
+ $TableParams = @{
+ Name = "Node Hardware - $($NodeHWs.SystemName)"
+ List = $true
+ ColumnWidths = 40, 60
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $Outobj | Table @TableParams
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesSP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesSP.ps1
new file mode 100755
index 0000000..ec2e360
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapNodesSP.ps1
@@ -0,0 +1,119 @@
+function Get-AbrOntapNodesSP {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP system nodes service-processor information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Node Service-Processor information.'
+ }
+
+ process {
+ try {
+ $ServiceProcessor = Get-NcServiceProcessor -Controller $Array
+
+ # $ServiceProcessor = @(
+ # @{
+ # 'Node' = 'cluster-01'
+ # 'Type' = 'BMC'
+ # 'IpAddress' = '192.168.0.1'
+ # 'MacAddress' = '00:02:23:24:43:AA'
+ # 'IsIpConfigured' = 'True'
+ # 'FirmwareVersion' = '8.1'
+ # 'Status' = 'Online'
+ # },
+ # @{
+ # 'Node' = 'cluster-02'
+ # 'Type' = 'BMC'
+ # 'IpAddress' = '192.168.0.2'
+ # 'MacAddress' = '00:02:23:24:43:AB'
+ # 'IsIpConfigured' = 'True'
+ # 'FirmwareVersion' = '8.1'
+ # 'Status' = 'Online'
+ # },
+ # @{
+ # 'Node' = 'cluster-03'
+ # 'Type' = 'BMC'
+ # 'IpAddress' = '192.168.0.2'
+ # 'MacAddress' = '00:02:23:24:43:AB'
+ # 'IsIpConfigured' = 'True'
+ # 'FirmwareVersion' = '8.1'
+ # 'Status' = 'Unknown'
+ # },
+ # @{
+ # 'Node' = 'cluster-04'
+ # 'Type' = 'BMC'
+ # 'IpAddress' = ''
+ # 'MacAddress' = '00:02:23:24:43:AB'
+ # 'IsIpConfigured' = 'False'
+ # 'FirmwareVersion' = '8.1'
+ # 'Status' = 'Offline'
+ # }
+ # )
+ if ($ServiceProcessor) {
+ $SPObj = @()
+ foreach ($NodeSPs in $ServiceProcessor) {
+ try {
+ $inObj = [ordered] @{
+ 'Name' = $NodeSPs.Node
+ 'Type' = $NodeSPs.Type
+ 'IP Address' = $NodeSPs.IpAddress
+ 'MAC Address' = $NodeSPs.MacAddress
+ 'Network Configured' = $NodeSPs.IsIpConfigured
+ 'Firmware' = $NodeSPs.FirmwareVersion
+ 'Status' = $NodeSPs.Status
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+
+ $SPObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+ if ($Healthcheck.Node.ServiceProcessor) {
+ $SPObj | Where-Object { $_.'Status' -like 'offline' -or $_.'Status' -like 'degraded' } | Set-Style -Style Critical -Property 'Status'
+ $SPObj | Where-Object { $_.'Status' -like 'unknown' -or $_.'Status' -like 'sp-daemon-offline' } | Set-Style -Style Warning -Property 'Status'
+ $SPObj | Where-Object { $_.'Network Configured' -eq 'No' } | Set-Style -Style Critical -Property 'Network Configured'
+ }
+
+ $TableParams = @{
+ Name = "Node Service-Processor - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 16, 11, 16, 20, 13, 12, 12
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $SPObj | Table @TableParams
+ if ($Healthcheck.Node.ServiceProcessor -and ($SPObj | Where-Object { $_.'Status' -in @('unknown', 'offline', 'degraded') -or $_.'Network Configured' -eq 'No' })) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all service-processors are online, configured and functioning properly to maintain system management capabilities.'
+ }
+ BlankLine
+ }
+ }
+
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapRepClusterPeer.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepClusterPeer.ps1
similarity index 84%
rename from Src/Private/Get-AbrOntapRepClusterPeer.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepClusterPeer.ps1
index f4989dc..0aadaf9 100755
--- a/Src/Private/Get-AbrOntapRepClusterPeer.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepClusterPeer.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepClusterPeer {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapRepClusterPeer {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Replication information."
+ Write-PScriboMessage 'Collecting ONTAP Replication information.'
}
process {
@@ -37,7 +37,7 @@ function Get-AbrOntapRepClusterPeer {
'IP Space' = $Item.IpspaceName
'Status' = ($Item.Availability)
}
- $ReplicaObj += [pscustomobject]$inobj
+ $ReplicaObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -56,11 +56,11 @@ function Get-AbrOntapRepClusterPeer {
}
$ReplicaObj | Table @TableParams
if ($Healthcheck.Replication.ClusterPeer -and ($ReplicaObj | Where-Object { $_.'Status' -notlike 'Available' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all cluster peers are available to maintain replication integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all cluster peers are available to maintain replication integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapRepDestinations.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepDestinations.ps1
similarity index 80%
rename from Src/Private/Get-AbrOntapRepDestinations.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepDestinations.ps1
index 58f942b..fc3d05c 100755
--- a/Src/Private/Get-AbrOntapRepDestinations.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepDestinations.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepDestination {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapRepDestination {
)
begin {
- Write-PScriboMessage "Collecting ONTAP SnapMirror Destination relationship information."
+ Write-PScriboMessage 'Collecting ONTAP SnapMirror Destination relationship information.'
}
process {
@@ -46,15 +46,12 @@ function Get-AbrOntapRepDestination {
default { $Item.RelationshipType }
}
'Policy Type' = $Item.PolicyType
- 'Status' = switch ($Item.RelationshipStatus) {
- $Null { 'Unknown' }
- default { $Item.RelationshipStatus }
- }
+ 'Status' = ($Null -eq $Item.RelationshipStatus) ? 'Unknown': $Item.RelationshipStatus
}
- $ReplicaObj = [pscustomobject]$inobj
+ $ReplicaObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Replication.Relationship) {
- $ReplicaObj | Where-Object { $_.'Status' -eq "Unknown" } | Set-Style -Style Warning -Property 'Status'
+ $ReplicaObj | Where-Object { $_.'Status' -eq 'Unknown' } | Set-Style -Style Warning -Property 'Status'
}
$TableParams = @{
@@ -66,12 +63,12 @@ function Get-AbrOntapRepDestination {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$ReplicaObj | Table @TableParams
- if ($Healthcheck.Replication.Relationship -and ($ReplicaObj | Where-Object { $_.'Status' -eq "Unknown" })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Replication.Relationship -and ($ReplicaObj | Where-Object { $_.'Status' -eq 'Unknown' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all SnapMirror relationships have a known status to maintain replication integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all SnapMirror relationships have a known status to maintain replication integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapRepHistory.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepHistory.ps1
similarity index 85%
rename from Src/Private/Get-AbrOntapRepHistory.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepHistory.ps1
index 980c566..d8def2d 100755
--- a/Src/Private/Get-AbrOntapRepHistory.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepHistory.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepHistory {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapRepHistory {
)
begin {
- Write-PScriboMessage "Collecting ONTAP SnapMirror replication history information."
+ Write-PScriboMessage 'Collecting ONTAP SnapMirror replication history information.'
}
process {
@@ -36,7 +36,7 @@ function Get-AbrOntapRepHistory {
'Result' = $Item.Result
'Start' = $Item.Start
}
- $ReplicaObj += [pscustomobject]$inobj
+ $ReplicaObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -55,11 +55,11 @@ function Get-AbrOntapRepHistory {
}
$ReplicaObj | Table @TableParams
if ($Healthcheck.Replication.History -and ($ReplicaObj | Where-Object { $_.'Result' -ne 'success' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all SnapMirror replication operations complete successfully to maintain data integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all SnapMirror replication operations complete successfully to maintain data integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapRepMediator.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepMediator.ps1
similarity index 68%
rename from Src/Private/Get-AbrOntapRepMediator.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepMediator.ps1
index d815a33..5a92cad 100755
--- a/Src/Private/Get-AbrOntapRepMediator.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepMediator.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepMediator {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,12 +19,12 @@ function Get-AbrOntapRepMediator {
)
begin {
- Write-PScriboMessage "Collecting ONTAP SnapMirror Mediator relationship information."
+ Write-PScriboMessage 'Collecting ONTAP SnapMirror Mediator relationship information.'
}
process {
try {
- $ReplicaData = Get-NetAppOntapAPI -uri "/api/cluster/mediators?fields=*&return_records=true&return_timeout=15"
+ $ReplicaData = Get-NetAppOntapAPI -uri '/api/cluster/mediators?fields=*&return_records=true&return_timeout=15'
$ReplicaObj = @()
if ($ReplicaData) {
foreach ($Item in $ReplicaData) {
@@ -33,19 +33,15 @@ function Get-AbrOntapRepMediator {
'Peer cluster' = $Item.peer_cluster.name
'IP Address' = $Item.ip_address
'port' = $Item.port
- 'Status' = switch ($Item.reachable) {
- 'True' { 'Reachable' }
- 'False' { 'Unreachable' }
- default { $Item.reachable }
- }
+ 'Status' = ($Item.reachable -eq $True) ? 'Reachable': 'Unreachable'
}
- $ReplicaObj += [pscustomobject]$inobj
+ $ReplicaObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Replication.Mediator) {
- $ReplicaObj | Where-Object { $_.'Status' -eq "Unreachable" } | Set-Style -Style Critical -Property 'Status'
+ $ReplicaObj | Where-Object { $_.'Status' -eq 'Unreachable' } | Set-Style -Style Critical -Property 'Status'
}
$TableParams = @{
@@ -57,12 +53,12 @@ function Get-AbrOntapRepMediator {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$ReplicaObj | Table @TableParams
- if ($Healthcheck.Replication.Mediator -and ($ReplicaObj | Where-Object { $_.'Status' -eq "Unreachable" })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Replication.Mediator -and ($ReplicaObj | Where-Object { $_.'Status' -eq 'Unreachable' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all SnapMirror Mediator relationships are reachable to facilitate proper replication management."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all SnapMirror Mediator relationships are reachable to facilitate proper replication management.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapRepRelations.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepRelations.ps1
similarity index 66%
rename from Src/Private/Get-AbrOntapRepRelations.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepRelations.ps1
index b67d4fc..f880bb3 100755
--- a/Src/Private/Get-AbrOntapRepRelations.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepRelations.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepRelationship {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapRepRelationship {
)
begin {
- Write-PScriboMessage "Collecting ONTAP SnapMirror relationship information."
+ Write-PScriboMessage 'Collecting ONTAP SnapMirror relationship information.'
}
process {
@@ -30,19 +30,15 @@ function Get-AbrOntapRepRelationship {
foreach ($Item in $ReplicaData) {
try {
$lag = [timespan]::fromseconds($Item.LagTime).tostring()
- $time = $lag.Split(".").Split(":")
- $lagtime = $time[0] + " days, " + $time[1] + " hrs, " + $time[2] + " mins, " + $time[0] + " secs"
+ $time = $lag.Split('.').Split(':')
+ $lagtime = $time[0] + ' days, ' + $time[1] + ' hrs, ' + $time[2] + ' mins, ' + $time[0] + ' secs'
$inObj = [ordered] @{
'Source Vserver' = $Item.SourceVserver
'Source Location' = $Item.SourceLocation
'Destination Vserver' = $Item.DestinationVserver
'Destination Location' = $Item.DestinationLocation
'Mirror State' = $Item.MirrorState
- 'Schedule' = switch ([string]::IsNullOrEmpty($Item.Schedule)) {
- $true { "None" }
- $false { ($Item.Schedule).toUpper() }
- default { "Unknown" }
- }
+ 'Schedule' = ${Item}?.Schedule?.toUpper()
'Relationship Type' = switch ($Item.RelationshipType) {
'extended_data_protection' { 'XDP' }
'data_protection' { 'DP' }
@@ -53,21 +49,14 @@ function Get-AbrOntapRepRelationship {
}
'Policy' = $Item.Policy
'Policy Type' = $Item.PolicyType
- 'Unhealthy Reason' = switch ($Item.UnhealthyReason) {
- $NULL { "None" }
- default { $Item.UnhealthyReason }
- }
+ 'Unhealthy Reason' = ($Null -eq $Item.UnhealthyReason) ? 'None': $Item.UnhealthyReason
'Lag Time' = $lagtime
- 'Status' = switch ([string]::IsNullOrEmpty($Item.Status)) {
- $true { '--' }
- $false { ($Item.Status).toUpper() }
- default { 'Unknown' }
- }
+ 'Status' = ${Item}?.Status?.toUpper()
}
- $ReplicaObj = [pscustomobject]$inobj
+ $ReplicaObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Replication.Relationship) {
- $ReplicaObj | Where-Object { $_.'Unhealthy Reason' -ne "None" } | Set-Style -Style Warning -Property 'Unhealthy Reason'
+ $ReplicaObj | Where-Object { $_.'Unhealthy Reason' -ne 'None' } | Set-Style -Style Warning -Property 'Unhealthy Reason'
}
$TableParams = @{
@@ -79,12 +68,12 @@ function Get-AbrOntapRepRelationship {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$ReplicaObj | Table @TableParams
- if ($Healthcheck.Replication.Relationship -and ($ReplicaObj | Where-Object { $_.'Unhealthy Reason' -ne "None" })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Replication.Relationship -and ($ReplicaObj | Where-Object { $_.'Unhealthy Reason' -ne 'None' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all SnapMirror relationships are healthy to maintain data replication integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all SnapMirror relationships are healthy to maintain data replication integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapRepVserverPeer.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepVserverPeer.ps1
similarity index 88%
rename from Src/Private/Get-AbrOntapRepVserverPeer.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepVserverPeer.ps1
index 9ee1ed9..76f7d37 100755
--- a/Src/Private/Get-AbrOntapRepVserverPeer.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapRepVserverPeer.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapRepVserverPeer {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapRepVserverPeer {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Peer information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Peer information.'
}
process {
@@ -36,7 +36,7 @@ function Get-AbrOntapRepVserverPeer {
'Applications' = $Item.Applications
'Peer State' = $Item.PeerState
}
- $ReplicaObj += [pscustomobject]$inobj
+ $ReplicaObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -55,10 +55,10 @@ function Get-AbrOntapRepVserverPeer {
}
$ReplicaObj | Table @TableParams
if ($Healthcheck.Replication.VserverPeer -and ($ReplicaObj | Where-Object { $_.'Peer State' -notlike 'peered' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure that all Vserver Peer relationships are in 'peered' state to maintain proper data replication."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapSecurityKMS.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMS.ps1
similarity index 88%
rename from Src/Private/Get-AbrOntapSecurityKMS.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMS.ps1
index 4980d0e..1453007 100755
--- a/Src/Private/Get-AbrOntapSecurityKMS.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMS.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityKMS {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecurityKMS {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Key Management Service information."
+ Write-PScriboMessage 'Collecting ONTAP Security Key Management Service information.'
}
process {
@@ -34,7 +34,7 @@ function Get-AbrOntapSecurityKMS {
'Key Store' = $TextInfo.ToTitleCase($Item.KeyStore)
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecurityKMSExt.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExt.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapSecurityKMSExt.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExt.ps1
index c772041..699473a 100755
--- a/Src/Private/Get-AbrOntapSecurityKMSExt.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExt.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityKMSExt {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecurityKMSExt {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Key Management Service External information."
+ Write-PScriboMessage 'Collecting ONTAP Security Key Management Service External information.'
}
process {
@@ -36,7 +36,7 @@ function Get-AbrOntapSecurityKMSExt {
'Timeout' = $Item.Timeout
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1
similarity index 87%
rename from Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1
index a13772e..25582c9 100755
--- a/Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityKMSExtStatus.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityKMSExtStatus {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecurityKMSExtStatus {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Key Management Service External Status information."
+ Write-PScriboMessage 'Collecting ONTAP Security Key Management Service External Status information.'
}
process {
@@ -35,7 +35,7 @@ function Get-AbrOntapSecurityKMSExtStatus {
'Key Manager Port' = $Item.KeyManagerTcpPort
'Status' = $TextInfo.ToTitleCase($Item.KeyManagerServerStatus)
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -55,10 +55,10 @@ function Get-AbrOntapSecurityKMSExtStatus {
}
$OutObj | Table @TableParams
if ($Healthcheck.Security.KMS -and ($OutObj | Where-Object { $_.'Status' -ne 'Available' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure that all External Key Management Services are in 'Available' status to maintain encryption functionality."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapSecurityMAP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAP.ps1
similarity index 63%
rename from Src/Private/Get-AbrOntapSecurityMAP.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAP.ps1
index c4fd05c..999dd86 100755
--- a/Src/Private/Get-AbrOntapSecurityMAP.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAP.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityMAP {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,30 +19,22 @@ function Get-AbrOntapSecurityMAP {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Vserver Multi-Admin Approval information."
+ Write-PScriboMessage 'Collecting ONTAP Security Vserver Multi-Admin Approval information.'
}
process {
try {
- $Data = Get-NetAppOntapAPI -uri "/api/security/multi-admin-verify/approval-groups?fields=**&return_records=true&return_timeout=15"
+ $Data = Get-NetAppOntapAPI -uri '/api/security/multi-admin-verify/approval-groups?fields=**&return_records=true&return_timeout=15'
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
try {
$inObj = [ordered] @{
'Name' = $Item.Name
- 'Approvers' = Switch ([string]::IsNullOrEmpty($Item.Approvers)) {
- $true { '-' }
- $false { $Item.Approvers -join ', ' }
- default { '-' }
- }
- 'Email' = Switch ([string]::IsNullOrEmpty($Item.Email)) {
- $true { '-' }
- $false { $Item.Email -join ', ' }
- default { '-' }
- }
+ 'Approvers' = $Item.Approvers -join ', '
+ 'Email' = $Item.Email -join ', '
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecurityMAPRule.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAPRule.ps1
similarity index 64%
rename from Src/Private/Get-AbrOntapSecurityMAPRule.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAPRule.ps1
index ce0329c..b380cc5 100755
--- a/Src/Private/Get-AbrOntapSecurityMAPRule.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityMAPRule.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityMAPRule {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,29 +19,25 @@ function Get-AbrOntapSecurityMAPRule {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Vserver Multi-Admin Approval rules information."
+ Write-PScriboMessage 'Collecting ONTAP Security Vserver Multi-Admin Approval rules information.'
}
process {
try {
- $Data = Get-NetAppOntapAPI -uri "/api/security/multi-admin-verify/rules?fields=**&return_records=true&return_timeout=15"
+ $Data = Get-NetAppOntapAPI -uri '/api/security/multi-admin-verify/rules?fields=**&return_records=true&return_timeout=15'
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
try {
$inObj = [ordered] @{
'operation' = $Item.operation
- 'query' = ConvertTo-EmptyToFiller $Item.query
- 'Approval Groups' = Switch ([string]::IsNullOrEmpty($Item.approval_groups.name)) {
- $true { '-' }
- $false { $Item.approval_groups.name }
- default { '-' }
- }
- 'Required Approvers' = ConvertTo-EmptyToFiller $Item.required_approvers
- 'System Defined' = ConvertTo-TextYN $Item.system_defined
+ 'query' = $Item.query
+ 'Approval Groups' = $Item.approval_groups.name
+ 'Required Approvers' = $Item.required_approvers
+ 'System Defined' = $Item.system_defined
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecurityNAE.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNAE.ps1
similarity index 75%
rename from Src/Private/Get-AbrOntapSecurityNAE.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNAE.ps1
index 8379cda..3fa21f8 100755
--- a/Src/Private/Get-AbrOntapSecurityNAE.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNAE.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityNAE {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecurityNAE {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Aggregate NAE information."
+ Write-PScriboMessage 'Collecting ONTAP Security Aggregate NAE information.'
}
process {
@@ -29,19 +29,14 @@ function Get-AbrOntapSecurityNAE {
if ($Data) {
foreach ($Item in $Data) {
try {
- $NAE = try { (Get-NcAggrOption -Name $Item.Name -Controller $Array | Where-Object { $_.Name -eq "encrypt_with_aggr_key" }).Value } catch { Write-PScriboMessage -IsWarning $_.Exception.Message }
+ $NAE = try { (Get-NcAggrOption -Name $Item.Name -Controller $Array | Where-Object { $_.Name -eq 'encrypt_with_aggr_key' }).Value } catch { Write-PScriboMessage -IsWarning $_.Exception.Message }
$inObj = [ordered] @{
'Aggregate' = $Item.Name
- 'Aggregate Encryption' = switch ($NAE) {
- 'true' { 'Yes' }
- 'false' { 'No' }
- $Null { 'Unknown' }
- default { $NAE }
- }
+ 'Aggregate Encryption' = $NAE
'Volume Count' = $Item.Volumes
'State' = $TextInfo.ToTitleCase($Item.State)
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -60,10 +55,10 @@ function Get-AbrOntapSecurityNAE {
}
$OutObj | Table @TableParams
if ($Healthcheck.Storage.Aggr -and ($OutObj | Where-Object { $_.'State' -ne 'Online' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure that all Aggregates are in 'Online' state to maintain optimal storage performance and client access availability."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapSecurityNVE.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNVE.ps1
similarity index 75%
rename from Src/Private/Get-AbrOntapSecurityNVE.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNVE.ps1
index 3615aec..a31c33d 100755
--- a/Src/Private/Get-AbrOntapSecurityNVE.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityNVE.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityNVE {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,12 +19,12 @@ function Get-AbrOntapSecurityNVE {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Volume NVE information."
+ Write-PScriboMessage 'Collecting ONTAP Security Volume NVE information.'
}
process {
try {
- $Data = Get-NcVol -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsConstituent -ne "True" } | Select-Object -Property vserver, name, aggregate, state, @{Label = "Node"; expression = { $_.VolumeIdAttributes.Nodes } }, encrypt, @{Label = "encryptionstate"; expression = { (Get-NcVolumeEncryptionConversion -Vserver $_.vserver -Volume $_.name -Controller $Array).status } }
+ $Data = Get-NcVol -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsConstituent -ne 'True' } | Select-Object -Property vserver, name, aggregate, state, @{Label = 'Node'; expression = { $_.VolumeIdAttributes.Nodes } }, encrypt, @{Label = 'encryptionstate'; expression = { (Get-NcVolumeEncryptionConversion -Vserver $_.vserver -Volume $_.name -Controller $Array).status } }
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -32,10 +32,10 @@ function Get-AbrOntapSecurityNVE {
$inObj = [ordered] @{
'Name' = $Item.Name
'Aggregate' = $Item.Aggregate
- 'Encrypted' = ConvertTo-TextYN $Item.Encrypt
+ 'Encrypted' = $Item.Encrypt
'State' = $TextInfo.ToTitleCase($Item.State)
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1
similarity index 75%
rename from Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1
index f34bec7..b2af76a 100755
--- a/Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLDetailed.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySSLDetailed {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,12 +19,12 @@ function Get-AbrOntapSecuritySSLDetailed {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Vserver SSL Detailed information."
+ Write-PScriboMessage 'Collecting ONTAP Security Vserver SSL Detailed information.'
}
process {
try {
- $Data = Get-NcSecurityCertificate -Controller $Array | Where-Object { $_.Type -eq "server" -and $_.Vserver -notin $Options.Exclude.Vserver }
+ $Data = Get-NcSecurityCertificate -Controller $Array | Where-Object { $_.Type -eq 'server' -and $_.Vserver -notin $Options.Exclude.Vserver }
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -34,14 +34,10 @@ function Get-AbrOntapSecuritySSLDetailed {
'Protocol' = $Item.Protocol
'Hash Function' = $Item.HashFunction
'Serial Number' = $Item.SerialNumber
- 'Expiration' = Switch ([string]::IsNullOrEmpty($Item.ExpirationDateDT)) {
- $true { '-' }
- $false { ($Item.ExpirationDateDT).ToString().Split(" ")[0] }
- default { 'Unknown' }
- }
+ 'Expiration' = ${Item}?.ExpirationDateDT?.ToString()?.Split(' ')[0]
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySSLVserver.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLVserver.ps1
similarity index 83%
rename from Src/Private/Get-AbrOntapSecuritySSLVserver.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLVserver.ps1
index 58b2a9d..e4d6c68 100755
--- a/Src/Private/Get-AbrOntapSecuritySSLVserver.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySSLVserver.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySSLVserver {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecuritySSLVserver {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Vserver SSL information."
+ Write-PScriboMessage 'Collecting ONTAP Security Vserver SSL information.'
}
process {
@@ -32,12 +32,12 @@ function Get-AbrOntapSecuritySSLVserver {
$inObj = [ordered] @{
'Common Name' = $Item.CommonName
'Certificate Authority' = $Item.CertificateAuthority
- 'Client Auth' = ConvertTo-TextYN $Item.ClientAuth
- 'Server Auth' = ConvertTo-TextYN $Item.ServerAuth
+ 'Client Auth' = $Item.ClientAuth
+ 'Server Auth' = $Item.ServerAuth
'Serial Number' = $Item.CertificateSerialNumber
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1
index 3c52902..aa1a234 100755
--- a/Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockAggr.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySnapLockAggr {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecuritySnapLockAggr {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Aggregate Snaplock Type information."
+ Write-PScriboMessage 'Collecting ONTAP Security Aggregate Snaplock Type information.'
}
process {
@@ -29,12 +29,11 @@ function Get-AbrOntapSecuritySnapLockAggr {
if ($Data) {
foreach ($Item in $Data) {
try {
- $SnapLockType = Get-NcAggr $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrSnaplockAttributes
$inObj = [ordered] @{
'Aggregate Name' = $Item.Name
- 'Snaplock Type' = $TextInfo.ToTitleCase($SnapLockType.SnaplockType)
+ 'Snaplock Type' = $TextInfo.ToTitleCase((Get-NcAggr $Item.Name -Controller $Array | Select-Object -ExpandProperty AggrSnaplockAttributes).SnaplockType)
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1
similarity index 84%
rename from Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1
index 2e5e159..847f8c5 100755
--- a/Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockClock.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySnapLockClock {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecuritySnapLockClock {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Snaplock compliance clock information."
+ Write-PScriboMessage 'Collecting ONTAP Security Snaplock compliance clock information.'
}
process {
@@ -32,12 +32,12 @@ function Get-AbrOntapSecuritySnapLockClock {
$SnapLockClock = Get-NcSnaplockComplianceClock $Item.Node -Controller $Array
$inObj = [ordered] @{
'Node Name' = $Item.Node
- 'Compliance Clock' = Switch ($SnapLockClock.FormattedSnaplockComplianceClock) {
+ 'Compliance Clock' = switch (($SnapLockClock).FormattedSnaplockComplianceClock) {
$Null { 'Uninitialized' }
default { $SnapLockClock.FormattedSnaplockComplianceClock }
}
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1
similarity index 82%
rename from Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1
index 21459b8..c34cba4 100755
--- a/Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVol.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySnapLockVol {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSecuritySnapLockVol {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Volume Snaplock Type information."
+ Write-PScriboMessage 'Collecting ONTAP Security Volume Snaplock Type information.'
}
process {
@@ -29,13 +29,12 @@ function Get-AbrOntapSecuritySnapLockVol {
if ($Data) {
foreach ($Item in $Data) {
try {
- $SnapLockType = Get-NcVol $Item.Name -Controller $Array | Select-Object -ExpandProperty VolumeSnaplockAttributes
$inObj = [ordered] @{
'Volume' = $Item.Name
'Aggregate' = $Item.Aggregate
- 'Snaplock Type' = $TextInfo.ToTitleCase($SnapLockType.SnaplockType)
+ 'Snaplock Type' = $TextInfo.ToTitleCase((Get-NcVol $Item.Name -Controller $Array | Select-Object -ExpandProperty VolumeSnaplockAttributes).SnaplockType)
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1
index dda9191..a55de44 100755
--- a/Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecuritySnapLockVollAttr.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecuritySnapLockVollAttr {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,18 +19,18 @@ function Get-AbrOntapSecuritySnapLockVollAttr {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Snaplock volume attributes information."
+ Write-PScriboMessage 'Collecting ONTAP Security Snaplock volume attributes information.'
}
process {
try {
- $Data = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq "data" }
- $VolumeFilter = Get-NcVol -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in "enterprise", "compliance" }
+ $Data = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq 'data' }
+ $VolumeFilter = Get-NcVol -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in 'enterprise', 'compliance' }
$OutObj = @()
if ($Data -and $VolumeFilter) {
foreach ($Item in $Data) {
try {
- $VolumeFilter = Get-NcVol -VserverContext $Item.Vserver -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in "enterprise", "compliance" }
+ $VolumeFilter = Get-NcVol -VserverContext $Item.Vserver -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in 'enterprise', 'compliance' }
foreach ($vol in $VolumeFilter) {
$SnapLockVolAttr = Get-NcSnaplockVolAttr -Volume $vol.Name -VserverContext $Item.VserverName -Controller $Array
$inObj = [ordered] @{
@@ -39,17 +39,14 @@ function Get-AbrOntapSecuritySnapLockVollAttr {
'Snaplock Type' = $TextInfo.ToTitleCase($SnapLockVolAttr.Type)
'Maximum Retention Period' = $SnapLockVolAttr.MaximumRetentionPeriod
'Minimum Retention Period' = $SnapLockVolAttr.MinimumRetentionPeriod
- 'Privileged Delete State' = Switch ($SnapLockVolAttr.PrivilegedDeleteState) {
- $Null { '-' }
- default { $SnapLockVolAttr.PrivilegedDeleteState }
- }
+ 'Privileged Delete State' = $SnapLockVolAttr.PrivilegedDeleteState
'Volume Expiry Time' = $SnapLockVolAttr.VolumeExpiryTime
'Volume Expiry Time Secs' = $SnapLockVolAttr.VolumeExpiryTimeSecs
'Auto Commit Period' = $SnapLockVolAttr.AutocommitPeriod
'Default Retention Period' = $SnapLockVolAttr.DefaultRetentionPeriod
'Litigation Count' = $SnapLockVolAttr.LitigationCount
}
- $OutObj = [pscustomobject]$inobj
+ $OutObj = [pscustomobject](ConvertTo-HashToYN $inObj)
$TableParams = @{
Name = "Snaplock Volume Attributes - $($vol.Name)"
diff --git a/Src/Private/Get-AbrOntapSecurityUsers.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityUsers.ps1
similarity index 77%
rename from Src/Private/Get-AbrOntapSecurityUsers.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityUsers.ps1
index 22e2309..be2a554 100755
--- a/Src/Private/Get-AbrOntapSecurityUsers.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSecurityUsers.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSecurityUser {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapSecurityUser {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Security Local Users information."
+ Write-PScriboMessage 'Collecting ONTAP Security Local Users information.'
}
process {
@@ -38,15 +38,15 @@ function Get-AbrOntapSecurityUser {
'Application' = $TextInfo.ToTitleCase($Item.Application)
'Auth Method' = $Item.AuthMethod
'Role Name' = $Item.RoleName
- 'Locked' = ConvertTo-TextYN $Item.IsLocked
+ 'Locked' = $Item.IsLocked
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Security.Users) {
- $OutObj | Where-Object { $_.'Locked' -eq 'Yes' -and $_.'User Name' -ne "vsadmin" } | Set-Style -Style Warning -Property 'Locked'
+ $OutObj | Where-Object { $_.'Locked' -eq 'Yes' -and $_.'User Name' -ne 'vsadmin' } | Set-Style -Style Warning -Property 'Locked'
}
$TableParams = @{
@@ -58,12 +58,12 @@ function Get-AbrOntapSecurityUser {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$OutObj | Table @TableParams
- if ($Healthcheck.Security.Users -and ($OutObj | Where-Object { $_.'Locked' -eq 'Yes' -and $_.'User Name' -ne "vsadmin" })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Security.Users -and ($OutObj | Where-Object { $_.'Locked' -eq 'Yes' -and $_.'User Name' -ne 'vsadmin' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that local users are not locked out to maintain proper access to the system. Review locked users and unlock them if necessary."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that local users are not locked out to maintain proper access to the system. Review locked users and unlock them if necessary.'
}
BlankLine
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageAGGR.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageAGGR.ps1
new file mode 100755
index 0000000..0da894f
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageAGGR.ps1
@@ -0,0 +1,230 @@
+function Get-AbrOntapStorageAGGR {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP storage summary information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP storage aggregate information.'
+ }
+
+ process {
+ try {
+ try {
+ $ObjectData = Get-NcAggr -Controller $Array
+ if ($ObjectData) {
+ $ChartData = @()
+ $AggrName = @()
+ $ObjectDataInfo = @()
+ foreach ($Data in $ObjectData) {
+ try {
+ if (-not (Get-NcAggr -Name $Data.Name -Controller $Array).AggrRaidAttributes.IsRootAggregate) {
+ $AggrName += $Data.Name
+ $ChartData += , @([math]::Round((($Data.Totalsize - $Data.Available) / $Data.TotalSize * 100), 0), [math]::Round(($Data.Available / $Data.TotalSize) * 100, 0))
+ }
+ $AggrOwner = (Get-NcAggr -Name $Data.Name ).AggrOwnershipAttributes
+ $inObj = [Ordered]@{
+ 'Name' = $Data.Name
+ 'Home Nodes' = ${AggrOwner}?.HomeName ?? '--'
+ 'Owner Nodes' = ${AggrOwner}?.OwnerName ?? '--'
+ 'Capacity' = ($Data.Totalsize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Available' = ($Data.Available | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = (($Data.Totalsize - $Data.Available ) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Disk Count' = $Data.Disks
+ 'Root' = ((Get-NcAggr -Name $Data.Name -Controller $Array).AggrRaidAttributes.IsRootAggregate) ? 'Yes': 'No'
+ 'Raid Type' = (($Data.RaidType.Split(',')[0]).ToUpper()) ?? '--'
+ 'Raid Size' = $Data.RaidSize
+ 'Volumes in Aggregate' = $Data.Volumes
+ 'State' = $Data.State
+ }
+ $ObjectDataInfo += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ if ($Healthcheck.Storage.Aggr) {
+ $ObjectDataInfo | Where-Object { $_.'State' -eq 'failed' } | Set-Style -Style Critical -Property 'State'
+ $ObjectDataInfo | Where-Object { $_.'State' -eq 'unknown' -or $_.'State' -eq 'offline' } | Set-Style -Style Warning -Property 'State'
+ $ObjectDataInfo | Where-Object { $_.'Used' -ge 90 } | Set-Style -Style Critical -Property 'Used'
+ }
+
+ if ($InfoLevel.Storage -ge 2) {
+ Paragraph "The following sections detail the storage aggregate configuration and health status in $($ClusterInfo.ClusterName)."
+ foreach ($Data in $ObjectDataInfo) {
+ Section -Style NOTOCHeading4 -ExcludeFromTOC "$($Data.Name)" {
+ $TableParams = @{
+ Name = "Aggregates - $($Data.Name)"
+ List = $true
+ ColumnWidths = 40, 60
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $Data | Table @TableParams
+ if ($Healthcheck.Storage.Aggr -and (($Data | Where-Object { $_.'State' -eq 'failed' } ) -or ($Data | Where-Object { $_.'State' -eq 'unknown' -or $_.'State' -eq 'offline' }) -or ($Data | Where-Object { $_.'Used' -ge 90 -and $_.'Root' -ne 'Yes' }))) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all Aggregates are in healthy state to maintain optimal storage performance and client access availability.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } else {
+ Paragraph "The following table summarises the aggregates in $($ClusterInfo.ClusterName)."
+ BlankLine
+ $TableParams = @{
+ Name = "Aggregates - $($ClusterInfo.ClusterName)"
+ List = $false
+ Columns = 'Name', 'Capacity', 'Available', 'Used', 'Disk Count', 'Root', 'Raid Type', 'State'
+ ColumnWidths = 27, 10, 10, 10, 10, 8, 15, 10
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ObjectDataInfo | Table @TableParams
+ if ($Healthcheck.Storage.Aggr -and (($ObjectDataInfo | Where-Object { $_.'State' -eq 'failed' } ) -or ($ObjectDataInfo | Where-Object { $_.'State' -eq 'unknown' -or $_.'State' -eq 'offline' }) -or ($ObjectDataInfo | Where-Object { $_.'Used' -ge 90 -and $_.'Root' -ne 'Yes' }))) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all Aggregates are in healthy state to maintain optimal storage performance and client access availability.'
+ }
+ BlankLine
+ }
+ }
+ $Chart = New-StackedBarChart -Values $ChartData -Labels $AggrName -LegendCategories @('Used', 'Free') -Title 'Aggregates Usage' -EnableLegend -LegendOrientation Horizontal -LegendAlignment UpperCenter -Width 600 -Height 600 -Format base64 -LabelYAxis '%' -LabelXAxis 'Aggregates' -TitleFontSize 20 -TitleFontBold -AreaOrientation Horizontal -EnableCustomColorPalette -CustomColorPalette @('#7b98bc', '#c0ddff')
+ if ($Chart) {
+ Section -Style NOTOCHeading4 -ExcludeFromTOC 'Aggragate Usage - Chart' {
+ Image -Text 'Aggragate Usage - Chart' -Align 'Center' -Percent 100 -Base64 $Chart
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $($_.Exception.Message)
+ }
+ try {
+ $AggrSpare = Get-NcAggrSpare -Controller $Array
+ if ($AggrSpare) {
+ Section -Style Heading4 'Disk Spares' {
+ $OutObj = @()
+ foreach ($Spare in $AggrSpare) {
+ try {
+ $inObj = [ordered] @{
+ 'Name' = $Spare.Disk
+ 'Capacity' = ($Spare.TotalSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Root Usable' = ($Spare.LocalUsableRootSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Data Usable' = ($Spare.LocalUsableDataSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Shared Disk' = $Spare.IsDiskShared
+ 'Disk Zeroed' = $Spare.IsDiskZeroed
+ 'Owner' = $Spare.OriginalOwner
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Storage.Aggr) {
+ $OutObj | Where-Object { $_.'Disk Zeroed' -eq 'No' } | Set-Style -Style Warning -Property 'Disk Zeroed'
+ }
+ $TableParams = @{
+ Name = "Disk Spares - $($ClusterInfo.ClusterName)"
+ List = $false
+ ColumnWidths = 20, 12, 12, 12, 12, 12, 20
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ try {
+ if ($InfoLevel.Storage -ge 2) {
+ Section -Style Heading4 'Per Aggregate Options' {
+ $Aggregates = Get-NcAggr -Controller $Array | Where-Object { !$_.AggrRaidAttributes.HasLocalRoot }
+ foreach ($Aggregate in $Aggregates) {
+ try {
+ Section -ExcludeFromTOC -Style NOTOCHeading5 "$($Aggregate.Name)" {
+ $OutObj = @()
+ $Options = Get-NcAggrOption -Controller $Array -Name $Aggregate.Name
+ $Option = @{}
+ $Options | ForEach-Object { $Option.add($_.Name, $_.Value) }
+ $inObj = [ordered] @{
+ 'azcs_read_optimization' = $TextInfo.ToTitleCase($Option.azcs_read_optimization)
+ 'dir_holes' = $Option.dir_holes
+ 'dlog_hole_reserve' = $TextInfo.ToTitleCase($Option.dlog_hole_reserve)
+ 'enable_cold_data_reporting' = $Option.enable_cold_data_reporting
+ 'encrypt_with_aggr_key' = $Option.encrypt_with_aggr_key
+ 'free_space_realloc' = $TextInfo.ToTitleCase($Option.free_space_realloc)
+ 'fs_size_fixed' = $TextInfo.ToTitleCase($Option.fs_size_fixed)
+ 'ha_policy' = $TextInfo.ToTitleCase($Option.ha_policy)
+ 'hybrid_enabled' = $Option.hybrid_enabled
+ 'ignore_inconsistent' = $TextInfo.ToTitleCase($Option.ignore_inconsistent)
+ 'logical_space_enforcement' = $Option.logical_space_enforcement
+ 'logical_space_reporting' = $Option.logical_space_reporting
+ 'max_write_alloc_blocks' = $TextInfo.ToTitleCase($Option.max_write_alloc_blocks)
+ 'nearly_full_threshold' = $TextInfo.ToTitleCase($Option.nearly_full_threshold)
+ 'no_delete_log' = $TextInfo.ToTitleCase($Option.no_delete_log)
+ 'no_i2p' = $TextInfo.ToTitleCase($Option.no_i2p)
+ 'nosnap' = $TextInfo.ToTitleCase($Option.nosnap)
+ 'percent_snapshot_space' = $TextInfo.ToTitleCase($Option.percent_snapshot_space)
+ 'raid_cv' = $TextInfo.ToTitleCase($Option.raid_cv)
+ 'raid_lost_write' = $TextInfo.ToTitleCase($Option.raid_lost_write)
+ 'raidsize' = $TextInfo.ToTitleCase($Option.raidsize)
+ 'raidtype' = $TextInfo.ToTitleCase($Option.raidtype)
+ 'resyncsnaptime' = $TextInfo.ToTitleCase($Option.resyncsnaptime)
+ 'single_instance_data_logging' = $TextInfo.ToTitleCase($Option.single_instance_data_logging)
+ 'snapmirrored' = $TextInfo.ToTitleCase($Option.snapmirrored)
+ 'snapshot_autodelete' = $TextInfo.ToTitleCase($Option.snapshot_autodelete)
+ 'striping' = $TextInfo.ToTitleCase($Option.striping)
+ 'thorough_scrub' = $TextInfo.ToTitleCase($Option.thorough_scrub)
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+
+ $TableParams = @{
+ Name = "Options - $($Aggregate.Name)"
+ List = $true
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapStorageFabricPool.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPool.ps1
similarity index 82%
rename from Src/Private/Get-AbrOntapStorageFabricPool.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPool.ps1
index b05d8bf..60c087d 100755
--- a/Src/Private/Get-AbrOntapStorageFabricPool.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPool.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapStorageFabricPool {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapStorageFabricPool {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Aggregate FabriPool information."
+ Write-PScriboMessage 'Collecting ONTAP Aggregate FabriPool information.'
}
process {
@@ -34,10 +34,10 @@ function Get-AbrOntapStorageFabricPool {
'Aggregate' = $Item.Aggregate
'Fabric Pool Name' = $Item.ObjectStoreName
'Type' = $Item.ProviderType
- 'Used Space' = $Item.UsedSpace | ConvertTo-FormattedNumber -Type Datasize -NumberFormatString "0.0" -ErrorAction SilentlyContinue
+ 'Used Space' = ($Item.UsedSpace | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize -NumberFormatString 0.0) ?? '--'
'Status' = $Item.ObjectStoreAvailability
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1
similarity index 79%
rename from Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1
index efcec6f..50091e9 100755
--- a/Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapStorageFabricPoolConfig.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapEfficiencyAggrConfig {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapEfficiencyAggrConfig {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Aggregate FabriPool Object Store information."
+ Write-PScriboMessage 'Collecting ONTAP Aggregate FabriPool Object Store information.'
}
process {
@@ -34,11 +34,11 @@ function Get-AbrOntapEfficiencyAggrConfig {
'S3 Name' = $Item.S3Name
'Server FQDN' = $Item.Server
'Port' = $Item.Port
- 'SSL Enabled' = ConvertTo-TextYN $Item.SslEnabled
+ 'SSL Enabled' = $Item.SslEnabled
'Provider Type' = $Item.ProviderType
- 'Used Space' = $Item.UsedSpace | ConvertTo-FormattedNumber -Type Datasize -NumberFormatString "0.0" -ErrorAction SilentlyContinue
+ 'Used Space' = ($Item.UsedSpace | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize -NumberFormatString 0.0) ?? '--'
}
- $OutObj = [pscustomobject]$inobj
+ $OutObj = [pscustomobject](ConvertTo-HashToYN $inObj)
$TableParams = @{
Name = "Aggregate FabriPool Object Store Configuration - $($Item.ObjectStoreName)"
diff --git a/Src/Private/Get-AbrOntapSysConfigBackup.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackup.ps1
similarity index 79%
rename from Src/Private/Get-AbrOntapSysConfigBackup.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackup.ps1
index e8d515a..1c4af77 100755
--- a/Src/Private/Get-AbrOntapSysConfigBackup.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackup.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigBackup {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapSysConfigBackup {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System Configuration Backups information."
+ Write-PScriboMessage 'Collecting ONTAP System Configuration Backups information.'
}
process {
@@ -36,11 +36,11 @@ function Get-AbrOntapSysConfigBackup {
$inObj = [ordered] @{
'Backup Name' = $Item.BackupName
'Created' = $Item.Created
- 'Size' = $Item.BackupSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Size' = ($Item.BackupSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
'Schedule' = $Item.Schedule
- 'Is Auto' = ConvertTo-TextYN $Item.IsAuto
+ 'Is Auto' = $Item.IsAuto
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigBackupURL.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackupURL.ps1
similarity index 72%
rename from Src/Private/Get-AbrOntapSysConfigBackupURL.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackupURL.ps1
index 3cbd415..fd004d7 100755
--- a/Src/Private/Get-AbrOntapSysConfigBackupURL.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigBackupURL.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigBackupURL {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigBackupURL {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System Configuration Backup Setting information."
+ Write-PScriboMessage 'Collecting ONTAP System Configuration Backup Setting information.'
}
process {
@@ -30,16 +30,10 @@ function Get-AbrOntapSysConfigBackupURL {
foreach ($Item in $Data) {
try {
$inObj = [ordered] @{
- 'Url' = switch ($Item.Url) {
- $Null { 'Not Configured' }
- default { $Item.Url }
- }
- 'Username' = switch ($Item.Username) {
- $Null { 'Not Configured' }
- default { $Item.Username }
- }
+ 'Url' = ($Null -eq $Item.Url) ? 'Not Configured': $Item.Url
+ 'Username' = ($Null -eq $Item.Username) ? 'Not Configured': $Item.Username
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -60,11 +54,11 @@ function Get-AbrOntapSysConfigBackupURL {
}
$OutObj | Table @TableParams
if ($Healthcheck.System.Backup -and ($OutObj | Where-Object { $_.'Url' -eq 'Not Configured' -or $_.'Username' -eq 'Not Configured' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "It is recommended to backup the system configuration to a remote location to ensure recovery in case of failures."
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to backup the system configuration to a remote location to ensure recovery in case of failures.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapSysConfigDNS.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigDNS.ps1
similarity index 83%
rename from Src/Private/Get-AbrOntapSysConfigDNS.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigDNS.ps1
index 908be39..90c718e 100755
--- a/Src/Private/Get-AbrOntapSysConfigDNS.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigDNS.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigDNS {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigDNS {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System DNS Configuration information."
+ Write-PScriboMessage 'Collecting ONTAP System DNS Configuration information.'
}
process {
@@ -36,7 +36,7 @@ function Get-AbrOntapSysConfigDNS {
'Name Servers' = $Item.NameServers
'Timeout/s' = $Item.Timeout
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -57,19 +57,19 @@ function Get-AbrOntapSysConfigDNS {
}
$OutObj | Table @TableParams
if ($Healthcheck.System.DNS -and (($OutObj | Where-Object { $_.'Dns State' -notlike 'Enabled' }) -or ($OutObj | Where-Object { $_.'Name Servers' -lt 2 }))) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
if ($OutObj | Where-Object { $_.'Dns State' -notlike 'Enabled' }) {
Paragraph {
- Text "Best Practice:" -Bold
- Text "It is recommended to enable DNS on the cluster to ensure proper name resolution for network services."
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to enable DNS on the cluster to ensure proper name resolution for network services.'
}
BlankLine
}
if ($OutObj | Where-Object { $_.'Name Servers' -lt 2 } ) {
Paragraph {
- Text "Best Practice:" -Bold
- Text "It is recommended to configure at least two DNS name servers for redundancy and reliability."
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to configure at least two DNS name servers for redundancy and reliability.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapSysConfigEMS.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMS.ps1
similarity index 82%
rename from Src/Private/Get-AbrOntapSysConfigEMS.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMS.ps1
index b1bf68e..98de35b 100755
--- a/Src/Private/Get-AbrOntapSysConfigEMS.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMS.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigEMS {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapSysConfigEMS {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System EMS Messages information."
+ Write-PScriboMessage 'Collecting ONTAP System EMS Messages information.'
}
process {
try {
- $Data = Get-NcEmsMessage -Node $Node -Severity "emergency", "alert" -Controller $Array | Select-Object -First 30
+ $Data = Get-NcEmsMessage -Node $Node -Severity 'emergency', 'alert' -Controller $Array | Select-Object -First 30
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -38,7 +38,7 @@ function Get-AbrOntapSysConfigEMS {
'Severity' = $Item.Severity
'Event' = $Item.Event
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1
similarity index 68%
rename from Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1
index 085490d..6d0ad43 100755
--- a/Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigEMSSettings.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigEMSSetting {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigEMSSetting {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System EMS Settings information."
+ Write-PScriboMessage 'Collecting ONTAP System EMS Settings information.'
}
process {
@@ -31,33 +31,22 @@ function Get-AbrOntapSysConfigEMSSetting {
try {
$inObj = [ordered] @{
'Name' = $Item.Name
- 'Email Destinations' = switch ($Item.Mail) {
- $Null { '-' }
- default { $Item.Mail }
- }
- 'Snmp Traphost' = switch ($Item.Snmp) {
- $Null { '-' }
- default { $Item.Snmp }
- }
- 'Snmp Community' = switch ($Item.SnmpCommunity) {
- $Null { '-' }
- default { $Item.SnmpCommunity }
- }
- 'Syslog' = switch ($Item.Syslog) {
- $Null { '-' }
- default { $Item.Syslog }
- }
- 'Syslog Facility' = switch ($Item.SyslogFacility) {
- $Null { '-' }
- default { $Item.SyslogFacility }
- }
+ 'Email Destinations' = $Item.Mail
+ 'Snmp Traphost' = $Item.Snmp
+ 'Snmp Community' = $Item.SnmpCommunity
+ 'Syslog' = $Item.Syslog
+ 'Syslog Facility' = $Item.SyslogFacility
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
+ if ($Healthcheck.System.EMS) {
+ $OutObj | Where-Object { $_.'Email Destinations' -eq '--' -or $_.'Snmp Traphost' -eq '--' -or $_.'Syslog' -eq '--' } | Set-Style -Style Warning
+ }
+
$TableParams = @{
Name = "EMS Configuration Setting - $($ClusterInfo.ClusterName)"
List = $false
@@ -67,12 +56,12 @@ function Get-AbrOntapSysConfigEMSSetting {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$OutObj | Table @TableParams
- if ($Healthcheck.System.EMS -and ($OutObj | Where-Object { $_.'Email Destinations' -eq '-' -and $_.'Snmp Traphost' -eq '-' -and $_.'Syslog' -eq '-' })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.System.EMS -and ($OutObj | Where-Object { $_.'Email Destinations' -eq '--' -and $_.'Snmp Traphost' -eq '--' -and $_.'Syslog' -eq '--' })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "It is recommended to configure at least one EMS destination (Email, SNMP, or Syslog) to ensure proper monitoring and alerting of system events."
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to configure at least one EMS destination (Email, SNMP, or Syslog) to ensure proper monitoring and alerting of system events.'
}
BlankLine
}
@@ -83,18 +72,18 @@ function Get-AbrOntapSysConfigEMSSetting {
try {
$Data = Get-NcAudit -Controller $Array
if ($Data) {
- Section -Style Heading4 "Audit Settings" {
+ Section -Style Heading4 'Audit Settings' {
Paragraph "The following section provides information about Audit Setting from $($ClusterInfo.ClusterName)."
BlankLine
$OutObj = @()
foreach ($Item in $Data) {
try {
$inObj = [ordered] @{
- 'Enable HTTP Get request' = ConvertTo-TextYN $Item.HttpGet
- 'Enable ONTAPI Get request' = ConvertTo-TextYN $Item.OntapiGet
- 'Enable CLI Get request' = ConvertTo-TextYN $Item.CliGet
+ 'Enable HTTP Get request' = $Item.HttpGet
+ 'Enable ONTAPI Get request' = $Item.OntapiGet
+ 'Enable CLI Get request' = $Item.CliGet
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -112,7 +101,7 @@ function Get-AbrOntapSysConfigEMSSetting {
try {
$Data = Get-NcClusterLogForward -Controller $Array
if ($Data) {
- Section -Style Heading4 "Audit Log Destinations" {
+ Section -Style Heading4 'Audit Log Destinations' {
$OutObj = @()
foreach ($Item in $Data) {
try {
@@ -121,9 +110,9 @@ function Get-AbrOntapSysConfigEMSSetting {
'Facility' = $Item.Facility
'Port' = $Item.Port
'Protocol' = $Item.Protocol
- 'Server Verification' = ConvertTo-TextYN $Item.VerifyServerSpecified
+ 'Server Verification' = $Item.VerifyServerSpecified
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigImage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigImage.ps1
similarity index 83%
rename from Src/Private/Get-AbrOntapSysConfigImage.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigImage.ps1
index 25e2347..8fd901c 100755
--- a/Src/Private/Get-AbrOntapSysConfigImage.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigImage.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigImage {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigImage {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System Image information."
+ Write-PScriboMessage 'Collecting ONTAP System Image information.'
}
process {
@@ -32,12 +32,12 @@ function Get-AbrOntapSysConfigImage {
$inObj = [ordered] @{
'Node' = $Item.Node
'Location' = $Item.Image
- 'Is Current' = ConvertTo-TextYN $Item.IsCurrent
- 'Is Default' = ConvertTo-TextYN $Item.IsDefault
+ 'Is Current' = $Item.IsCurrent
+ 'Is Default' = $Item.IsDefault
'Install Time' = $Item.InstallTimeDT
'Version' = $Item.Version
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigNTP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTP.ps1
similarity index 66%
rename from Src/Private/Get-AbrOntapSysConfigNTP.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTP.ps1
index d4a7bd4..dea13fa 100755
--- a/Src/Private/Get-AbrOntapSysConfigNTP.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTP.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigNTP {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigNTP {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System NTP information."
+ Write-PScriboMessage 'Collecting ONTAP System NTP information.'
}
process {
@@ -32,15 +32,19 @@ function Get-AbrOntapSysConfigNTP {
$inObj = [ordered] @{
'Server Name' = $Item.ServerName
'NTP Version' = $TextInfo.ToTitleCase($Item.Version)
- 'Preferred' = ConvertTo-TextYN $Item.IsPreferred
- 'Authentication Enabled' = ConvertTo-TextYN $Item.IsAuthenticationEnabled
+ 'Preferred' = $Item.IsPreferred
+ 'Authentication Enabled' = $Item.IsAuthenticationEnabled
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
+ if ($Healthcheck.System.NTP -and $OutObj.Count -eq 1) {
+ $OutObj | Set-Style -Style Warning
+ }
+
$TableParams = @{
Name = "Network Time Protocol - $($ClusterInfo.ClusterName)"
List = $false
@@ -50,6 +54,15 @@ function Get-AbrOntapSysConfigNTP {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$OutObj | Table @TableParams
+ if ($Healthcheck.System.NTP -and ($OutObj.Count -eq 1)) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to configure multiple NTP servers for redundancy and reliability.'
+ }
+ BlankLine
+ }
} else {
$inObj = [ordered] @{
'Server Name' = 'No NTP Servers Configured'
@@ -57,7 +70,7 @@ function Get-AbrOntapSysConfigNTP {
'Preferred' = 'N/A'
'Authentication Enabled' = 'N/A'
}
- $OutObj = [pscustomobject]$inObj
+ $OutObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.System.NTP) {
$OutObj | Set-Style -Style Warning
@@ -73,11 +86,11 @@ function Get-AbrOntapSysConfigNTP {
}
$OutObj | Table @TableParams
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Configure at least one NTP server to ensure accurate time synchronization across the cluster."
+ Text 'Best Practice:' -Bold
+ Text 'Configure at least one NTP server to ensure accurate time synchronization across the cluster.'
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapSysConfigNTPHost.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTPHost.ps1
similarity index 76%
rename from Src/Private/Get-AbrOntapSysConfigNTPHost.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTPHost.ps1
index 4a3b5e1..8695606 100755
--- a/Src/Private/Get-AbrOntapSysConfigNTPHost.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigNTPHost.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigNTPHost {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigNTPHost {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System NTP Host Status information."
+ Write-PScriboMessage 'Collecting ONTAP System NTP Host Status information.'
}
process {
@@ -34,13 +34,9 @@ function Get-AbrOntapSysConfigNTPHost {
'Time Offset' = $Item.Offset
'Selection State' = $Item.SelectionState
'Server' = $Item.Server
- 'Peer Status' = switch ($Item.IsPeerReachable) {
- 'True' { 'Reachable' }
- 'False' { 'Unreachable' }
- default { $Item.IsPeerReachable }
- }
+ 'Peer Status' = ($Item.IsPeerReachable -eq $True) ? 'Reachable': 'Unreachable'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -59,11 +55,11 @@ function Get-AbrOntapSysConfigNTPHost {
}
$OutObj | Table @TableParams
if ($Healthcheck.System.NTP -and ($OutObj | Where-Object { $_.'Peer Status' -notlike 'Reachable' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all configured NTP servers are reachable to maintain accurate time synchronization across the cluster."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all configured NTP servers are reachable to maintain accurate time synchronization across the cluster.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapSysConfigSNMP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigSNMP.ps1
similarity index 77%
rename from Src/Private/Get-AbrOntapSysConfigSNMP.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigSNMP.ps1
index eb7fe3f..df9ff94 100755
--- a/Src/Private/Get-AbrOntapSysConfigSNMP.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigSNMP.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigSNMP {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigSNMP {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System SNMP Configuration information."
+ Write-PScriboMessage 'Collecting ONTAP System SNMP Configuration information.'
}
process {
@@ -34,13 +34,9 @@ function Get-AbrOntapSysConfigSNMP {
'Location' = $Item.Location
'Communities' = $Item.Communities
'Traphosts' = $Item.Traphosts
- 'Status' = Switch ($Item.IsTrapEnabled) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsTrapEnabled }
- }
+ 'Status' = $Item.IsTrapEnabled -eq $True ? 'Enabled': 'Disabled'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigTZ.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigTZ.ps1
similarity index 80%
rename from Src/Private/Get-AbrOntapSysConfigTZ.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigTZ.ps1
index b58f82a..42d8759 100755
--- a/Src/Private/Get-AbrOntapSysConfigTZ.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigTZ.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigTZ {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigTZ {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System TimeZone information."
+ Write-PScriboMessage 'Collecting ONTAP System TimeZone information.'
}
process {
@@ -29,15 +29,13 @@ function Get-AbrOntapSysConfigTZ {
if ($Data) {
foreach ($Item in $Data) {
try {
- $Time = (Get-NcTime -Controller $Array).UtcTime[0]
- $CurrentTime = Get-UnixDate($Time)
$inObj = [ordered] @{
'Timezone' = $Item.Timezone
'Timezone UTC' = $Item.TimezoneUtc
'Timezone Version' = $Item.TimezoneVersion
- 'Current Time' = $CurrentTime
+ 'Current Time' = ([timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds((Get-NcTime -Controller $Array).UtcTime[0]))) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapSysConfigWebStatus.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigWebStatus.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapSysConfigWebStatus.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigWebStatus.ps1
index f6e9ee8..52f3227 100755
--- a/Src/Private/Get-AbrOntapSysConfigWebStatus.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapSysConfigWebStatus.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapSysConfigWebStatus {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapSysConfigWebStatus {
)
begin {
- Write-PScriboMessage "Collecting ONTAP System Web Service information."
+ Write-PScriboMessage 'Collecting ONTAP System Web Service information.'
}
process {
@@ -31,14 +31,14 @@ function Get-AbrOntapSysConfigWebStatus {
try {
$inObj = [ordered] @{
'Node' = $Item.Node
- 'Http Enabled' = ConvertTo-TextYN $Item.HttpEnabled
+ 'Http Enabled' = $Item.HttpEnabled
'Http Port' = $Item.HttpPort
'Https Port' = $Item.HttpsPort
- 'External' = ConvertTo-TextYN $Item.External
+ 'External' = $Item.External
'Status' = $TextInfo.ToTitleCase($Item.Status)
'Status Code' = $Item.StatusCode
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -59,11 +59,11 @@ function Get-AbrOntapSysConfigWebStatus {
}
$OutObj | Table @TableParams
if ($Healthcheck.System.Web -and (($OutObj | Where-Object { $_.'Http Enabled' -eq 'Yes' }))) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "It is recommended to enable HTTPS and disable HTTP on all nodes to ensure secure communication with the cluster management interface."
+ Text 'Best Practice:' -Bold
+ Text 'It is recommended to enable HTTPS and disable HTTP on all nodes to ensure secure communication with the cluster management interface.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverCGLun.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGLun.ps1
similarity index 65%
rename from Src/Private/Get-AbrOntapVserverCGLun.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGLun.ps1
index ca307e9..2472c35 100755
--- a/Src/Private/Get-AbrOntapVserverCGLun.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGLun.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCGLun {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -22,7 +22,7 @@ function Get-AbrOntapVserverCGLun {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Consistency Groups lun information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Consistency Groups lun information.'
}
process {
@@ -34,25 +34,17 @@ function Get-AbrOntapVserverCGLun {
try {
$inObj = [ordered] @{
'Name' = $Item.Name.Split('/')[3]
- 'Capacity' = switch ([string]::IsNullOrEmpty($Item.space.size)) {
- $true { '-' }
- $false { $Item.space.size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'Used' = switch ([string]::IsNullOrEmpty($Item.space.used)) {
- $true { '-' }
- $false { $Item.space.used | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'OS Type' = ConvertTo-EmptyToFiller $Item.os_type
+ 'Capacity' = ($Item.space.size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Item.space.used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'OS Type' = $Item.os_type
'Volume State' = $Item.status.container_state
- 'Mapped' = ConvertTo-TextYN $Item.status.mapped
- 'Read Only' = ConvertTo-TextYN $Item.status.read_only
+ 'Mapped' = $Item.status.mapped
+ 'Read Only' = $Item.status.read_only
'State' = $Item.status.state
}
- $CGLunObj += [pscustomobject]$inobj
+ $CGLunObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -75,11 +67,11 @@ function Get-AbrOntapVserverCGLun {
}
$CGLunObj | Sort-Object -Property Name | Table @TableParams
if ($Healthcheck.Vserver.CG -and ($CGLunObj | Where-Object { $_.'State' -eq 'offline' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all LUNs within the Consistency Group are online to maintain data availability and integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all LUNs within the Consistency Group are online to maintain data availability and integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverCGNamespace.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGNamespace.ps1
similarity index 66%
rename from Src/Private/Get-AbrOntapVserverCGNamespace.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGNamespace.ps1
index 1989c4b..c19e611 100755
--- a/Src/Private/Get-AbrOntapVserverCGNamespace.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGNamespace.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCGNamespace {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -22,7 +22,7 @@ function Get-AbrOntapVserverCGNamespace {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Consistency Groups namespace information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Consistency Groups namespace information.'
}
process {
@@ -34,25 +34,17 @@ function Get-AbrOntapVserverCGNamespace {
try {
$inObj = [ordered] @{
'Name' = $Item.Name.Split('/')[3]
- 'Capacity' = switch ([string]::IsNullOrEmpty($Item.space.size)) {
- $true { '-' }
- $false { $Item.space.size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'Used' = switch ([string]::IsNullOrEmpty($Item.space.used)) {
- $true { '-' }
- $false { $Item.space.used | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'OS Type' = ConvertTo-EmptyToFiller $Item.os_type
+ 'Capacity' = ($Item.space.size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Item.space.used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'OS Type' = $Item.os_type
'Volume State' = $Item.status.container_state
- 'Mapped' = ConvertTo-TextYN $Item.status.mapped
- 'Read Only' = ConvertTo-TextYN $Item.status.read_only
+ 'Mapped' = $Item.status.mapped
+ 'Read Only' = $Item.status.read_only
'State' = $Item.status.state
}
- $CGNamespaceObj += [pscustomobject]$inobj
+ $CGNamespaceObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -75,11 +67,11 @@ function Get-AbrOntapVserverCGNamespace {
}
$CGNamespaceObj | Sort-Object -Property Name | Table @TableParams
if ($Healthcheck.Vserver.CG -and ($CGNamespaceObj | Where-Object { $_.'State' -eq 'offline' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all namespaces within the Consistency Group are online to maintain data availability and integrity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all namespaces within the Consistency Group are online to maintain data availability and integrity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverCGSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGSummary.ps1
similarity index 50%
rename from Src/Private/Get-AbrOntapVserverCGSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGSummary.ps1
index 597232d..9ec9b78 100755
--- a/Src/Private/Get-AbrOntapVserverCGSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCGSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCGSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCGSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Consistency Groups information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Consistency Groups information.'
}
process {
@@ -35,29 +35,13 @@ function Get-AbrOntapVserverCGSummary {
try {
$inObj = [ordered] @{
'Name' = $Item.Name
- 'Capacity' = Switch ([string]::IsNullOrEmpty($Item.space.size)) {
- $true { '-' }
- $false { $Item.space.size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'Available' = Switch ([string]::IsNullOrEmpty($Item.space.available)) {
- $true { '-' }
- $false { $Item.space.available | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'Used' = Switch ([string]::IsNullOrEmpty($Item.space.used)) {
- $true { '-' }
- $false { $Item.space.used | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue }
- default { '-' }
- }
- 'Replicated' = ConvertTo-TextYN $Item.replicated
- 'Lun Count' = Switch ([string]::IsNullOrEmpty($Item.luns.name)) {
- $true { '-' }
- $false { ($Item.luns.name).count }
- default { '-' }
- }
+ 'Capacity' = ($Item.space.size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Available' = ($Item.space.available | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Item.space.used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Replicated' = $Item.replicated
+ 'Lun Count' = ($Item.luns.name).count
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSDC.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSDC.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapVserverCIFSDC.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSDC.ps1
index 2136918..b8166d4 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSDC.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSDC.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSDC {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSDC {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Domain Controller Properties information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Domain Controller Properties information.'
}
process {
@@ -41,7 +41,7 @@ function Get-AbrOntapVserverCIFSDC {
'Prefer Type' = $Item.PreferType
'Status' = $Item.Status
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1
index 73e02db..82c8daf 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLGMembers.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSLGMember {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSLGMember {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Local Group Members information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Local Group Members information.'
}
process {
@@ -37,7 +37,7 @@ function Get-AbrOntapVserverCIFSLGMember {
'Group Name' = $Item.GroupName
'Description' = $Item.Member
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1
index 70350fd..df6a837 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSLocalGroup.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSLocalGroup {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSLocalGroup {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Local Group information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Local Group information.'
}
process {
@@ -37,7 +37,7 @@ function Get-AbrOntapVserverCIFSLocalGroup {
'Group Name' = $Item.GroupName
'Description' = $Item.Description
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSOptions.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSOptions.ps1
similarity index 64%
rename from Src/Private/Get-AbrOntapVserverCIFSOptions.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSOptions.ps1
index 5a1d499..51517f5 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSOptions.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSOptions.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSOption {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSOption {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver CIFS Option information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver CIFS Option information.'
}
process {
@@ -33,29 +33,29 @@ function Get-AbrOntapVserverCIFSOption {
if ($VserverData) {
foreach ($SVM in $VserverData) {
try {
- $CIFSSVM = Get-NcCifsOption -VserverContext $SVM.Vserver -Controller $Array
+ $CIFSSVM = Get-NcCifsOption -VserverContext $SVM -Controller $Array
foreach ($Item in $CIFSSVM) {
try {
$inObj = [ordered] @{
'Client Session Timeout' = $Item.ClientSessionTimeout
'Default Unix User' = $Item.DefaultUnixUser
- 'Client Version Reporting Enabled' = ConvertTo-TextYN $Item.IsClientVersionReportingEnabled
- 'Copy Offload Direct Copy Enabled' = ConvertTo-TextYN $Item.IsCopyOffloadDirectCopyEnabled
- 'Copy Offload Enabled' = ConvertTo-TextYN $Item.IsCopyOffloadEnabled
- 'Dac Enabled' = ConvertTo-TextYN $Item.IsDacEnabled
- 'Export Policy Enabled' = ConvertTo-TextYN $Item.IsExportpolicyEnabled
- 'Large MTU Enabled' = ConvertTo-TextYN $Item.IsLargeMtuEnabled
- 'Local Auth Enabled' = ConvertTo-TextYN $Item.IsLocalAuthEnabled
- 'Local Users And Groups Enabled' = ConvertTo-TextYN $Item.IsLocalUsersAndGroupsEnabled
- 'Multi Channel Enabled' = ConvertTo-TextYN $Item.IsMultichannelEnabled
- 'Nbns Enabled' = ConvertTo-TextYN $Item.IsNbnsEnabled
- 'Netbios Over Tcp Enabled' = ConvertTo-TextYN $Item.IsNetbiosOverTcpEnabled
- 'Referral Enabled' = ConvertTo-TextYN $Item.IsReferralEnabled
- 'Shadow Copy Enabled' = ConvertTo-TextYN $Item.IsShadowcopyEnabled
- 'Smb1 Enabled' = ConvertTo-TextYN $Item.IsSmb1Enabled
- 'Smb2 Enabled' = ConvertTo-TextYN $Item.IsSmb2Enabled
- 'Smb31 Enabled' = ConvertTo-TextYN $Item.IsSmb31Enabled
- 'Smb3 Enabled' = ConvertTo-TextYN $Item.IsSmb3Enabled
+ 'Client Version Reporting Enabled' = $Item.IsClientVersionReportingEnabled
+ 'Copy Offload Direct Copy Enabled' = $Item.IsCopyOffloadDirectCopyEnabled
+ 'Copy Offload Enabled' = $Item.IsCopyOffloadEnabled
+ 'Dac Enabled' = $Item.IsDacEnabled
+ 'Export Policy Enabled' = $Item.IsExportpolicyEnabled
+ 'Large MTU Enabled' = $Item.IsLargeMtuEnabled
+ 'Local Auth Enabled' = $Item.IsLocalAuthEnabled
+ 'Local Users And Groups Enabled' = $Item.IsLocalUsersAndGroupsEnabled
+ 'Multi Channel Enabled' = $Item.IsMultichannelEnabled
+ 'Nbns Enabled' = $Item.IsNbnsEnabled
+ 'Netbios Over Tcp Enabled' = $Item.IsNetbiosOverTcpEnabled
+ 'Referral Enabled' = $Item.IsReferralEnabled
+ 'Shadow Copy Enabled' = $Item.IsShadowcopyEnabled
+ 'Smb1 Enabled' = $Item.IsSmb1Enabled
+ 'Smb2 Enabled' = $Item.IsSmb2Enabled
+ 'Smb31 Enabled' = $Item.IsSmb31Enabled
+ 'Smb3 Enabled' = $Item.IsSmb3Enabled
'Max Connections Per Session' = $Item.MaxConnectionsPerSession
'Max Credits' = $Item.MaxCredits
'Max File Write Zero Length' = $Item.MaxFileWriteZeroLength
@@ -66,7 +66,7 @@ function Get-AbrOntapVserverCIFSOption {
'Shadow Copy Dir Depth' = $Item.ShadowcopyDirDepth
'Smb1 Max Buffer Size' = $Item.Smb1MaxBufferSize
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1
similarity index 84%
rename from Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1
index 9220a3e..d1b47ca 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSecurity.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSSecurity {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSSecurity {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver CIFS Security information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver CIFS Security information.'
}
process {
@@ -40,12 +40,12 @@ function Get-AbrOntapVserverCIFSSecurity {
'Kerberos Clock Skew' = $SVM.KerberosClockSkew
'Kerberos Renew Age' = $SVM.KerberosRenewAge
'Kerberos Ticket Age' = $SVM.KerberosTicketAge
- 'Aes Encryption Enabled' = ConvertTo-TextYN $SVM.IsAesEncryptionEnabled
- 'Signing Required' = ConvertTo-TextYN $SVM.IsSigningRequired
- 'Smb Encryption Required' = ConvertTo-TextYN $SVM.IsSmbEncryptionRequired
+ 'Aes Encryption Enabled' = $SVM.IsAesEncryptionEnabled
+ 'Signing Required' = $SVM.IsSigningRequired
+ 'Smb Encryption Required' = $SVM.IsSmbEncryptionRequired
'Lm Compatibility Level' = $SVM.LmCompatibilityLevel
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} else { continue }
}
} catch {
diff --git a/Src/Private/Get-AbrOntapVserverCIFSSession.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSession.ps1
similarity index 90%
rename from Src/Private/Get-AbrOntapVserverCIFSSession.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSession.ps1
index 3c434d1..4b1c5b9 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSSession.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSession.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSSession {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSSession {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Session information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Session information.'
}
process {
@@ -40,7 +40,7 @@ function Get-AbrOntapVserverCIFSSession {
'Address' = $Item.Address
'User' = $Item.WindowsUser
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSShare.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShare.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapVserverCIFSShare.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShare.ps1
index e617292..51c9b29 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSShare.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShare.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSShare {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSShare {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Share information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Share information.'
}
process {
@@ -38,7 +38,7 @@ function Get-AbrOntapVserverCIFSShare {
'Volume' = $Item.Volume
'Path' = $Item.Path
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1
similarity index 85%
rename from Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1
index 85c0406..1b9c8ca 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSShareProp.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSShareProp {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSShareProp {
)
begin {
- Write-PScriboMessage "Collecting ONTAP CIFS Share Properties information."
+ Write-PScriboMessage 'Collecting ONTAP CIFS Share Properties information.'
}
process {
@@ -36,9 +36,9 @@ function Get-AbrOntapVserverCIFSShareProp {
$inObj = [ordered] @{
'Share Name' = $Item.ShareName
'Share ACL' = $Item.Acl
- 'Share Properties' = ($Item).ShareProperties -join ', '
+ 'Share Properties' = $Item.ShareProperties -join ', '
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverCIFSSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSummary.ps1
similarity index 87%
rename from Src/Private/Get-AbrOntapVserverCIFSSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSummary.ps1
index 038995e..4c33532 100755
--- a/Src/Private/Get-AbrOntapVserverCIFSSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverCIFSSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverCIFSSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverCIFSSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver CIFS information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver CIFS information.'
}
process {
@@ -43,9 +43,9 @@ function Get-AbrOntapVserverCIFSSummary {
'AD Server Site' = $SVM.CifsServerSite
'Cifs Server Status' = $SVM.CifsServerStatus
'Status Details' = $SVM.StatusDetails
- 'Status' = $SVM.Status.ToString()
+ 'Status' = ${SVM}?.Status?.ToString()
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.CIFS) {
$VserverObj | Where-Object { $_.'Cifs Server Status' -notlike 'Running' } | Set-Style -Style Warning -Property 'Cifs Server Status'
@@ -62,11 +62,11 @@ function Get-AbrOntapVserverCIFSSummary {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.CIFS -and ($VserverObj | Where-Object { $_.'Status' -like 'down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that the CIFS service is running on all nodes to maintain file sharing capabilities."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that the CIFS service is running on all nodes to maintain file sharing capabilities.'
}
BlankLine
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverDiagram.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverDiagram.ps1
new file mode 100644
index 0000000..c45d2cb
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverDiagram.ps1
@@ -0,0 +1,279 @@
+function Get-AbrOntapVserverDiagram {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to build NetApp ONTAP Vserver resources diagram
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage "Generating Vserver Diagram for $Vserver."
+ # Used for DiagramDebug
+ if ($Options.EnableDiagramDebug) {
+ $EdgeDebug = @{style = 'filled'; color = 'red' }
+ $SubGraphDebug = @{style = 'dashed'; color = 'red' }
+ $NodeDebug = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $NodeDebugEdge = @{color = 'black'; style = 'red'; shape = 'plain' }
+ $IconDebug = $true
+ } else {
+ $EdgeDebug = @{style = 'invis'; color = 'red' }
+ $SubGraphDebug = @{style = 'invis'; color = 'gray' }
+ $NodeDebug = @{color = 'transparent'; style = 'transparent'; shape = 'point' }
+ $NodeDebugEdge = @{color = 'transparent'; style = 'transparent'; shape = 'none' }
+ $IconDebug = $false
+ }
+
+ if ($Options.DiagramTheme -eq 'Black') {
+ $Edgecolor = 'White'
+ $Fontcolor = 'White'
+ } elseif ($Options.DiagramTheme -eq 'Neon') {
+ $Edgecolor = 'gold2'
+ $Fontcolor = 'gold2'
+ } else {
+ $Edgecolor = '#71797E'
+ $Fontcolor = '#565656'
+ }
+ }
+
+ process {
+ try {
+ $ClusterInfo = Get-NcCluster -Controller $Array
+ $VserverData = Get-NcVserver -VserverContext $Vserver | Where-Object { $_.VserverType -eq 'data' }
+ $VserverAggrs = (Get-NcVol -VserverContext $Vserver -Controller $Array).Aggregate | ForEach-Object { Get-NcAggr -Name $_ } | Select-Object -Unique
+ $VserverLifs = Get-NcNetInterface -Controller $Array | Where-Object { $_.Vserver -eq $Vserver -and $_.Role -eq 'data' }
+
+ $VserverNodeName = Remove-SpecialChar -String $Vserver -SpecialChars '\-_'
+
+ # SVM Additional Info
+ $SVMAdditionalInfo = [PSCustomObject][ordered]@{
+ 'State' = switch ([string]::IsNullOrEmpty($VserverData.State)) {
+ $true { 'Unknown' }
+ $false { $TextInfo.ToTitleCase($VserverData.State) }
+ default { 'Unknown' }
+ }
+ 'Protocols' = switch ([string]::IsNullOrEmpty($VserverData.AllowedProtocols)) {
+ $true { 'None' }
+ $false { ($VserverData.AllowedProtocols | Sort-Object) -join ', ' }
+ default { 'None' }
+ }
+ 'IPSpace' = switch ([string]::IsNullOrEmpty($VserverData.Ipspace)) {
+ $true { 'Unknown' }
+ $false { $VserverData.Ipspace }
+ default { 'Unknown' }
+ }
+ 'Root Vol' = switch ([string]::IsNullOrEmpty($VserverData.RootVolume)) {
+ $true { 'Unknown' }
+ $false { $VserverData.RootVolume }
+ default { 'Unknown' }
+ }
+ }
+
+ # SVM node
+ $SVMNodeObj = Add-HtmlNodeTable -Name 'SVMNodeObj' -ImagesObj $Images -inputObject $Vserver -Align 'Center' -iconType 'Ontap_SVM' -ColumnSize 1 -IconDebug $IconDebug -MultiIcon -AditionalInfo $SVMAdditionalInfo -TableBorderColor '#71797E' -TableBorder '0' -FontSize 18
+
+ if ($SVMNodeObj) {
+ $SVMMgmtObj = Add-HtmlSubGraph -Name 'SVMMgmtObj' -ImagesObj $Images -TableArray $SVMNodeObj -Align 'Right' -IconDebug $IconDebug -Label "Management: $($ClusterInfo.NcController)" -LabelPos 'down' -TableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder 1 -ColumnSize 1 -FontSize 12
+
+ if ($SVMMgmtObj) {
+ Node $VserverNodeName @{Label = $SVMMgmtObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+ } else {
+ Write-PScriboMessage -IsWarning "Unable to create SVM Node for $Vserver."
+ }
+ }
+
+ # Aggregates
+ if ($VserverAggrs) {
+ try {
+ $AggrInfo = @()
+ foreach ($Aggr in $VserverAggrs) {
+ $AggrData = Get-NcAggr -Name $Aggr.AggregateName -Controller $Array
+ $AggrInfo += [PSCustomObject][ordered]@{
+ 'Name' = $Aggr.AggregateName
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'Raid Type' = switch ([string]::IsNullOrEmpty($Aggr.RaidType)) {
+ $true { 'Unknown' }
+ $false { $Aggr.RaidType }
+ default { 'Unknown' }
+ }
+ 'Available' = switch ([string]::IsNullOrEmpty($AggrData.Available)) {
+ $true { 'Unknown' }
+ $false { ($AggrData.Available | ConvertTo-FormattedNumber -NumberFormatString 0.0 -Type Datasize -ErrorAction SilentlyContinue) }
+ default { 'Unknown' }
+ }
+ 'SnapLock' = switch ([string]::IsNullOrEmpty($Aggr.SnaplockType)) {
+ $true { 'None' }
+ $false { $Aggr.SnaplockType }
+ default { 'None' }
+ }
+ }
+ }
+ }
+
+ if ($AggrInfo.Count -eq 1) {
+ $AggrColumnSize = 1
+ } elseif ($ColumnSize) {
+ $AggrColumnSize = $ColumnSize
+ } else {
+ $AggrColumnSize = $AggrInfo.Count
+ }
+
+ $AggrNodeObj = Add-HtmlNodeTable -Name 'AggrNodeObj' -ImagesObj $Images -inputObject $AggrInfo.Name -Align 'Center' -iconType 'Ontap_Aggregate' -ColumnSize $AggrColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $AggrInfo.AdditionalInfo -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder 1 -FontSize 18
+
+ if ($AggrNodeObj) {
+ $AggrSubGraphObj = Add-HtmlSubGraph -Name 'AggrSubGraphObj' -ImagesObj $Images -TableArray $AggrNodeObj -Align 'Center' -IconDebug $IconDebug -Label 'Aggregates' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize 1 -FontSize 18
+
+ if ($AggrSubGraphObj) {
+ Node "$($VserverNodeName)Aggrs" @{Label = $AggrSubGraphObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+ Edge -To "$($VserverNodeName)Aggrs" -From $VserverNodeName @{minlen = 2; color = $Edgecolor; style = 'filled'; arrowhead = 'box'; arrowtail = 'box' }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ # Volumes
+ $VserverVolumes = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ if ($VserverVolumes) {
+ try {
+ $VolInfo = @()
+ foreach ($Vol in $VserverVolumes) {
+ $VolInfo += [PSCustomObject][ordered]@{
+ 'Name' = $Vol.Name
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'State' = switch ([string]::IsNullOrEmpty($Vol.State)) {
+ $true { 'Unknown' }
+ $false { $TextInfo.ToTitleCase($Vol.State) }
+ default { 'Unknown' }
+ }
+ 'Size' = switch ([string]::IsNullOrEmpty($Vol.Totalsize)) {
+ $true { 'Unknown' }
+ $false { ($Vol.Totalsize | ConvertTo-FormattedNumber -NumberFormatString 0.0 -Type DataSize -ErrorAction SilentlyContinue) }
+ default { 'Unknown' }
+ }
+ 'Used' = switch ([string]::IsNullOrEmpty($Vol.Used)) {
+ $true { 'Unknown' }
+ $false { ($Vol.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) }
+ default { 'Unknown' }
+ }
+ 'Aggr' = switch ([string]::IsNullOrEmpty($Vol.Aggregate)) {
+ $true { 'Unknown' }
+ $false { $Vol.Aggregate }
+ default { 'Unknown' }
+ }
+ }
+ }
+ }
+
+ if ($VolInfo.Count -eq 1) {
+ $VolColumnSize = 1
+ } elseif ($ColumnSize) {
+ $VolColumnSize = $ColumnSize
+ } else {
+ $VolColumnSize = $VolInfo.Count
+ }
+
+ $VolNodeObj = Add-HtmlNodeTable -Name 'VolNodeObj' -ImagesObj $Images -inputObject $VolInfo.Name -Align 'Center' -iconType 'Ontap_Volume' -ColumnSize $VolColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $VolInfo.AdditionalInfo -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder 1 -FontSize 18
+
+ if ($VolNodeObj) {
+ $VolSubGraphObj = Add-HtmlSubGraph -Name 'VolSubGraphObj' -ImagesObj $Images -TableArray $VolNodeObj -Align 'Center' -IconDebug $IconDebug -Label 'Volumes' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize 1 -FontSize 18
+
+ if ($VolSubGraphObj) {
+ Node "$($VserverNodeName)Vols" @{Label = $VolSubGraphObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+ Add-NodeEdge -From $VserverNodeName -To "$($VserverNodeName)Vols" -EdgeColor $Edgecolor -Arrowhead 'box' -Arrowtail 'box' -EdgeLength 2 -GraphvizAttributes @{style = 'filled'}
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ # LIFs
+ if ($VserverLifs) {
+ try {
+ $LifInfo = @()
+ foreach ($Lif in $VserverLifs) {
+ $LifInfo += [PSCustomObject][ordered]@{
+ 'Name' = $Lif.InterfaceName
+ 'AdditionalInfo' = [PSCustomObject][ordered]@{
+ 'IP' = switch ($Null -eq $Lif.Wwpn) {
+ $true {
+ switch ([string]::IsNullOrEmpty($Lif.Address)) {
+ $true { 'Unknown' }
+ $false { $Lif.Address }
+ default { 'Unknown' }
+ }
+ }
+ $false { $Lif.Wwpn }
+ }
+ 'Protocol' = switch ([string]::IsNullOrEmpty($Lif.DataProtocols)) {
+ $true { 'Unknown' }
+ $false { ($Lif.DataProtocols | Sort-Object) -join ', ' }
+ default { 'Unknown' }
+ }
+ 'Status' = switch ($Lif.AdministrativeStatus) {
+ 'up' { 'Up' }
+ 'down' { 'Down' }
+ default { 'Unknown' }
+ }
+ 'Is Home?' = switch ($Lif.IsHome) {
+ $true { 'Yes' }
+ $false { 'No' }
+ default { 'Unknown' }
+ }
+ 'Home Node' = switch ([string]::IsNullOrEmpty($Lif.HomeNode)) {
+ $true { 'Unknown' }
+ $false { $Lif.HomeNode }
+ default { 'Unknown' }
+ }
+ }
+ }
+ }
+
+ if ($LifInfo.Count -eq 1) {
+ $LifColumnSize = 1
+ } elseif ($ColumnSize) {
+ $LifColumnSize = $ColumnSize
+ } else {
+ $LifColumnSize = $LifInfo.Count
+ }
+
+ $LifNodeObj = Add-HtmlNodeTable -Name 'LifNodeObj' -ImagesObj $Images -inputObject $LifInfo.Name -Align 'Center' -iconType 'Ontap_Network_Nic' -ColumnSize $LifColumnSize -IconDebug $IconDebug -MultiIcon -AditionalInfo $LifInfo.AdditionalInfo -SubgraphTableStyle 'dashed,rounded' -TableBorderColor '#71797E' -TableBorder 1 -FontSize 18
+
+ if ($LifNodeObj) {
+ $LifSubGraphObj = Add-HtmlSubGraph -Name 'LifSubGraphObj' -ImagesObj $Images -TableArray $LifNodeObj -Align 'Center' -IconDebug $IconDebug -Label 'Network Interfaces (LIFs)' -LabelPos 'top' -TableStyle 'dashed,rounded' -TableBorderColor $Edgecolor -TableBorder '1' -ColumnSize 1 -FontSize 18
+
+ if ($LifSubGraphObj) {
+ Node "$($VserverNodeName)Lifs" @{Label = $LifSubGraphObj; shape = 'plain'; fillColor = 'transparent'; fontsize = 14 }
+ Add-NodeEdge -From $VserverNodeName -To "$($VserverNodeName)Lifs" -EdgeColor $Edgecolor -Arrowhead 'box' -Arrowtail 'box' -EdgeLength 2 -GraphvizAttributes @{style = 'filled'}
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverExportPolicy.ps1
similarity index 78%
rename from Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverExportPolicy.ps1
index d0a2554..42c905b 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverExportPolicy.ps1
@@ -1,11 +1,11 @@
-function Get-AbrOntapVserverVolumesExportPolicy {
+function Get-AbrOntapVserverExportPolicy {
<#
.SYNOPSIS
- Used by As Built Report to retrieve NetApp ONTAP vserver volumes export policy information from the Cluster Management Network
+ Used by As Built Report to retrieve NetApp ONTAP vserver export policy information from the Cluster Management Network
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumesExportPolicy {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes export policy information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver export policy information.'
}
process {
@@ -37,18 +37,18 @@ function Get-AbrOntapVserverVolumesExportPolicy {
'Policy Name' = $Item.PolicyName
'Rule Index' = $Item.RuleIndex
'Client Match' = $Item.ClientMatch
- 'Protocol' = $Item.Protocol -join ", "
+ 'Protocol' = $Item.Protocol -join ', '
'Ro Rule' = $Item.RoRule
'Rw Rule' = $Item.RwRule
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
$TableParams = @{
- Name = "Volume Export Policy - $($Vserver)"
+ Name = "Export Policies - $($Vserver)"
List = $false
ColumnWidths = 20, 15, 20, 15, 15, 15
}
diff --git a/Src/Private/Get-AbrOntapVserverFcpAdapter.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpAdapter.ps1
similarity index 76%
rename from Src/Private/Get-AbrOntapVserverFcpAdapter.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpAdapter.ps1
index 813c0e8..45ce34c 100755
--- a/Src/Private/Get-AbrOntapVserverFcpAdapter.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpAdapter.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverFcpAdapter {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapVserverFcpAdapter {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver FCP adapter information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver FCP adapter information.'
}
process {
@@ -34,13 +34,9 @@ function Get-AbrOntapVserverFcpAdapter {
'Adapter' = $Item.Adapter
'Protocol' = $Item.PhysicalProtocol
'Speed' = $Item.Speed
- 'Status' = switch ($Item.State) {
- 'online' { 'Up' }
- 'offline' { 'Down' }
- default { $Item.State }
- }
+ 'Status' = ($Item.State -eq 'online') ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -59,11 +55,11 @@ function Get-AbrOntapVserverFcpAdapter {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.FCP -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all FCP adapters are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all FCP adapters are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverFcpInterface.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpInterface.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapVserverFcpInterface.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpInterface.ps1
index e200fd3..99b789e 100755
--- a/Src/Private/Get-AbrOntapVserverFcpInterface.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpInterface.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverFcpInterface {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapVserverFcpInterface {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver FCP interface information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver FCP interface information.'
}
process {
try {
- $VserverData = Get-NcFcpInterface -VserverContext $Vserver -Controller $Array
+ $VserverData = Get-NcFcpInterface -VserverContext $Vserver -Controller $Array | Sort-Object -Property CurrentNode
$VserverObj = @()
if ($VserverData) {
foreach ($Item in $VserverData) {
@@ -36,9 +36,10 @@ function Get-AbrOntapVserverFcpInterface {
$inObj = [ordered] @{
'Interface Name' = $Item.InterfaceName
'FCP WWPN' = $Item.PortName
+ 'Node Name' = $Item.CurrentNode
'Home Port' = $Item.CurrentPort
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -47,7 +48,7 @@ function Get-AbrOntapVserverFcpInterface {
$TableParams = @{
Name = "FCP Interface - $($Vserver)"
List = $false
- ColumnWidths = 35, 35, 30
+ ColumnWidths = 30, 30, 20, 20
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
diff --git a/Src/Private/Get-AbrOntapVserverFcpSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpSummary.ps1
similarity index 74%
rename from Src/Private/Get-AbrOntapVserverFcpSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpSummary.ps1
index 9ef7a26..7c5d4c8 100755
--- a/Src/Private/Get-AbrOntapVserverFcpSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverFcpSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverFcpSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverFcpSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver FCP information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver FCP information.'
}
process {
@@ -35,13 +35,9 @@ function Get-AbrOntapVserverFcpSummary {
try {
$inObj = [ordered] @{
'FCP WWNN' = $Item.NodeName
- 'Status' = switch ($Item.IsAvailable) {
- 'True' { 'Up' }
- 'False' { 'Down' }
- default { $Item.IsAvailable }
- }
+ 'Status' = $Item.IsAvailable -eq $true ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -60,11 +56,11 @@ function Get-AbrOntapVserverFcpSummary {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.FCP -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' } )) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all FCP services are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all FCP services are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1
similarity index 88%
rename from Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1
index 793bab6..a53cd7e 100755
--- a/Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInitiator.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverIscsiInitiator {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverIscsiInitiator {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver ISCSI Client Initiators information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver ISCSI Client Initiators information.'
}
process {
@@ -37,7 +37,7 @@ function Get-AbrOntapVserverIscsiInitiator {
'Initiator Name' = $Item.InitiatorNodeName
'Target Port Group' = $Item.TpGroupName
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverIscsiInterface.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInterface.ps1
similarity index 75%
rename from Src/Private/Get-AbrOntapVserverIscsiInterface.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInterface.ps1
index 7119480..7564713 100755
--- a/Src/Private/Get-AbrOntapVserverIscsiInterface.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiInterface.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverIscsiInterface {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverIscsiInterface {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver ISCSI interface information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver ISCSI interface information.'
}
process {
@@ -37,13 +37,9 @@ function Get-AbrOntapVserverIscsiInterface {
'Interface Name' = $Item.InterfaceName
'IP Address' = $Item.IpAddress
'Port' = $Item.IpPort
- 'Status' = switch ($Item.IsInterfaceEnabled) {
- 'True' { 'Up' }
- 'False' { 'Down' }
- default { $Item.IsInterfaceEnabled }
- }
+ 'Status' = ($Item.IsInterfaceEnabled -eq $true) ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -62,11 +58,11 @@ function Get-AbrOntapVserverIscsiInterface {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Iscsi -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all ISCSI interfaces are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all ISCSI interfaces are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverIscsiSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiSummary.ps1
similarity index 77%
rename from Src/Private/Get-AbrOntapVserverIscsiSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiSummary.ps1
index 8b6d4a2..3e7007d 100755
--- a/Src/Private/Get-AbrOntapVserverIscsiSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverIscsiSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverIscsiSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverIscsiSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver ISCSI information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver ISCSI information.'
}
process {
@@ -40,13 +40,9 @@ function Get-AbrOntapVserverIscsiSummary {
'Max Cmds Per Session' = $Item.MaxCmdsPerSession
'Max Conn Per Session' = $Item.MaxConnPerSession
'Login Timeout' = $Item.LoginTimeout
- 'Status' = switch ($Item.IsAvailable) {
- 'True' { 'Up' }
- 'False' { 'Down' }
- default { $Item.IsAvailable }
- }
+ 'Status' = ($Item.IsAvailable -eq $true) ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -65,11 +61,11 @@ function Get-AbrOntapVserverIscsiSummary {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Iscsi -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all ISCSI services are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all ISCSI services are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverLunIgroup.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunIgroup.ps1
similarity index 79%
rename from Src/Private/Get-AbrOntapVserverLunIgroup.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunIgroup.ps1
index f92f660..85e00f8 100755
--- a/Src/Private/Get-AbrOntapVserverLunIgroup.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunIgroup.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverLunIgroup {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverLunIgroup {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Igroup information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Igroup information.'
}
process {
@@ -49,16 +49,10 @@ function Get-AbrOntapVserverLunIgroup {
'Type' = $Item.Type
'Protocol' = $Item.Protocol
'Initiators' = $Item.Initiators.InitiatorName
- 'Mapped Lun' = switch (($MappedLun).count) {
- 0 { "None" }
- default { $MappedLun }
- }
- 'Reporting Nodes' = switch (($reportingnodes).count) {
- 0 { "None" }
- default { $reportingnodes }
- }
+ 'Mapped Lun' = (($MappedLun).count -eq 0) ? 'None': $MappedLun
+ 'Reporting Nodes' = (($reportingnodes).count) ? 'None': $reportingnodes
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { ($_.'Reporting Nodes').count -gt 2 } | Set-Style -Style Warning -Property 'Reporting Nodes'
}
@@ -73,11 +67,11 @@ function Get-AbrOntapVserverLunIgroup {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { ($_.'Reporting Nodes').count -gt 2 })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that igroups have an optimal number of reporting nodes to maintain performance and reliability."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that igroups have an optimal number of reporting nodes to maintain performance and reliability.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverLunStorage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunStorage.ps1
similarity index 55%
rename from Src/Private/Get-AbrOntapVserverLunStorage.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunStorage.ps1
index 5762b94..16e33a1 100755
--- a/Src/Private/Get-AbrOntapVserverLunStorage.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverLunStorage.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverLunStorage {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverLunStorage {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver lun information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver lun information.'
}
process {
@@ -34,43 +34,25 @@ function Get-AbrOntapVserverLunStorage {
foreach ($Item in $VserverLun) {
try {
$lunmap = Get-NcLunMap -Path $Item.Path -Controller $Array | Select-Object -ExpandProperty InitiatorGroup
- $lunpath = $Item.Path.split('/')
- $lun = $lunpath[3]
- $available = $Item.Size - $Item.SizeUsed
- $used = ($Item.SizeUsed / $Item.Size) * 100
+ $lun = $Item.Path.split('/')[3]
$inObj = [ordered] @{
'Lun Name' = $lun
'Parent Volume' = $Item.Volume
'Path' = $Item.Path
'Serial Number' = $Item.SerialNumber
- 'Initiator Group' = switch (($lunmap).count) {
- 0 { "None" }
- default { $lunmap }
- }
+ 'Initiator Group' = ($lunmap.count -eq 0) ? 'None': $lunmap
'Home Node ' = $Item.Node
- 'Capacity' = $Item.Size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Available' = $available | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $used | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Available' = (($Item.Size - $Item.SizeUsed) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ((($Item.SizeUsed / $Item.Size) * 100) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
'OS Type' = $Item.Protocol
- 'Is Thin' = ConvertTo-TextYN $Item.Thin
- 'Space Allocation' = switch ($Item.IsSpaceAllocEnabled) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsSpaceAllocEnabled }
- }
- 'Space Reservation' = switch ($Item.IsSpaceReservationEnabled) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsSpaceReservationEnabled }
- }
- 'Is Mapped' = ConvertTo-TextYN $Item.Mapped
- 'Status' = switch ($Item.Online) {
- 'True' { 'Up' }
- 'False' { 'Down' }
- default { $Item.Online }
- }
+ 'Is Thin' = $Item.Thin
+ 'Space Allocation' = $Item.IsSpaceAllocEnabled -eq $True ? 'Enabled': 'Disabled'
+ 'Space Reservation' = $Item.IsSpaceReservationEnabled -eq $True ? 'Enabled': 'Disabled'
+ 'Is Mapped' = $Item.Mapped
+ 'Status' = $Item.Online -eq $True ? 'Up': 'Down'
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { $_.'Status' -like 'Down' } | Set-Style -Style Warning -Property 'Status'
@@ -88,11 +70,11 @@ function Get-AbrOntapVserverLunStorage {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all LUNs are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all LUNs are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSExport.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSExport.ps1
new file mode 100755
index 0000000..e1daa28
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSExport.ps1
@@ -0,0 +1,64 @@
+function Get-AbrOntapVserverNFSExport {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP Vserver NFS Export information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver NFS Export information.'
+ }
+
+ process {
+ try {
+ $VserverObj = @()
+ $NFSVserver = Get-NcNfsExport -VS $Vserver -Controller $Array
+ if ($NFSVserver ) {
+ foreach ($Item in $NFSVserver) {
+ try {
+ $inObj = [ordered] @{
+ 'Path Name' = $Item.Pathname
+ 'Export Policy' = (((Get-NcVol -VS $Vserver -Controller $Array | Where-Object { $_.JunctionPath -eq $Item.Pathname }).VolumeExportAttributes).Policy) ?? 'None'
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ }
+ }
+
+ $TableParams = @{
+ Name = "NFS Service Volume Export - $($Vserver)"
+ List = $false
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ if ($VserverObj) {
+ $VserverObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapVserverNFSOptions.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSOptions.ps1
similarity index 56%
rename from Src/Private/Get-AbrOntapVserverNFSOptions.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSOptions.ps1
index 154a408..cc1078e 100755
--- a/Src/Private/Get-AbrOntapVserverNFSOptions.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSOptions.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNFSOption {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNFSOption {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver NFS Option information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver NFS Option information.'
}
process {
@@ -34,21 +34,21 @@ function Get-AbrOntapVserverNFSOption {
foreach ($Item in $VserverData) {
try {
$inObj = [ordered] @{
- 'Allow Idle Connection' = ConvertTo-TextYN $Item.AllowIdleConnection
+ 'Allow Idle Connection' = $Item.AllowIdleConnection
'Idle Connection Timeout' = $Item.IdleConnectionTimeout
- 'Ignore NtAcl For Root' = ConvertTo-TextYN $Item.IgnoreNtAclForRoot
- 'Enable Ejukebox' = ConvertTo-TextYN $Item.EnableEjukebox
- 'Nfs Access Enabled' = ConvertTo-TextYN $Item.IsNfsAccessEnabled
- 'Nfs Rootonly Enabled' = ConvertTo-TextYN $Item.IsNfsRootonlyEnabled
- 'Nfsv2 Enabled' = ConvertTo-TextYN $Item.IsNfsv2Enabled
- 'Nfsv3 Enabled' = ConvertTo-TextYN $Item.IsNfsv3Enabled
- 'Nfsv3 64bit Identifiers Enabled' = ConvertTo-TextYN $Item.IsNfsv364bitIdentifiersEnabled
- 'Nfsv3 Connection Drop Enabled' = ConvertTo-TextYN $Item.IsNfsv3ConnectionDropEnabled
- 'Nfsv3 Fsid Change Enabled' = ConvertTo-TextYN $Item.IsNfsv3FsidChangeEnabled
- 'Nfsv40 Acl Enabled' = ConvertTo-TextYN $Item.IsNfsv40AclEnabled
- 'Nfsv40 Enabled' = ConvertTo-TextYN $Item.IsNfsv40Enabled
+ 'Ignore NtAcl For Root' = $Item.IgnoreNtAclForRoot
+ 'Enable Ejukebox' = $Item.EnableEjukebox
+ 'Nfs Access Enabled' = $Item.IsNfsAccessEnabled
+ 'Nfs Rootonly Enabled' = $Item.IsNfsRootonlyEnabled
+ 'Nfsv2 Enabled' = $Item.IsNfsv2Enabled
+ 'Nfsv3 Enabled' = $Item.IsNfsv3Enabled
+ 'Nfsv3 64bit Identifiers Enabled' = $Item.IsNfsv364bitIdentifiersEnabled
+ 'Nfsv3 Connection Drop Enabled' = $Item.IsNfsv3ConnectionDropEnabled
+ 'Nfsv3 Fsid Change Enabled' = $Item.IsNfsv3FsidChangeEnabled
+ 'Nfsv40 Acl Enabled' = $Item.IsNfsv40AclEnabled
+ 'Nfsv40 Enabled' = $Item.IsNfsv40Enabled
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverNFSSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSSummary.ps1
similarity index 61%
rename from Src/Private/Get-AbrOntapVserverNFSSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSSummary.ps1
index 030269b..cbaf343 100755
--- a/Src/Private/Get-AbrOntapVserverNFSSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNFSSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNFSSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNFSSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver NFS information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver NFS information.'
}
process {
@@ -34,25 +34,13 @@ function Get-AbrOntapVserverNFSSummary {
foreach ($Item in $VserverData) {
try {
$inObj = [ordered] @{
- 'Nfs v3' = switch ($Item.IsNfsv3) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsNfsv3 }
- }
- 'Nfs v4' = switch ($Item.IsNfsv4) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsNfsv4 }
- }
- 'Nfs v41' = switch ($Item.IsNfsv41) {
- 'True' { 'Enabled' }
- 'False' { 'Disabled' }
- default { $Item.IsNfsv41 }
- }
- 'General Access' = ConvertTo-TextYN $Item.GeneralAccess
+ 'Nfs v3' = $Item.IsNfsv3 -eq $true ? 'Enabled': 'Disabled'
+ 'Nfs v4' = $Item.IsNfsv4 -eq $true ? 'Enabled': 'Disabled'
+ 'Nfs v41' = $Item.IsNfsv41 -eq $true ? 'Enabled': 'Disabled'
+ 'General Access' = $Item.GeneralAccess
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -71,11 +59,11 @@ function Get-AbrOntapVserverNFSSummary {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.NFS -and ($VserverObj | Where-Object { $_.'Nfs v3' -like 'Disabled' -and $_.'Nfs v4' -like 'Disabled' -and $_.'Nfs v41' -like 'Disabled' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Evaluate enabling NFS services to support client connectivity and file sharing."
+ Text 'Best Practice:' -Bold
+ Text 'Evaluate enabling NFS services to support client connectivity and file sharing.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1
similarity index 69%
rename from Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1
index 57f13d1..c9435a1 100755
--- a/Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNamespaceStorage.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNamespaceStorage {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNamespaceStorage {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver namespace information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver namespace information.'
}
process {
@@ -34,37 +34,31 @@ function Get-AbrOntapVserverNamespaceStorage {
foreach ($Item in $VserverNamespace) {
try {
$namespacemap = Get-NcNvmeSubsystemMap -Vserver $Vserver -Controller $Array | Where-Object { $_.Path -eq $Item.Path }
- $namespacepath = $Item.Path.split('/')
- $namespace = $namespacepath[3]
- $available = $Item.Size - $Item.SizeUsed
- $used = ($Item.SizeUsed / $Item.Size) * 100
+ $namespace = $Item.Path.split('/')[3]
$inObj = [ordered] @{
'Namespace Name' = $namespace
'Parent Volume' = $Item.Volume
'Path' = $Item.Path
'Serial Number' = $Item.Uuid
- 'Subsystem Map' = switch (($namespacemap).count) {
- 0 { "None" }
- default { $namespacemap.Subsystem }
- }
+ 'Subsystem Map' = ($namespacemap).count -eq 0 ? 'None': $namespacemap.Subsystem
'Home Node ' = $Item.Node
- 'Capacity' = $Item.Size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Available' = $available | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $used | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Available' = (($Item.Size - $Item.SizeUsed) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ((($Item.SizeUsed / $Item.Size) * 100) | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
'OS Type' = $Item.Ostype
'Is Mapped' = switch ([string]::IsNullOrEmpty($Item.Subsystem)) {
- $true { "No" }
- $false { "Yes" }
+ $true { 'No' }
+ $false { 'Yes' }
default { $Item.Subsystem }
}
- 'ReadOnly' = ConvertTo-TextYN $Item.IsReadOnly
+ 'ReadOnly' = $Item.IsReadOnly
'Status' = switch ($Item.State) {
'online' { 'Up' }
'offline' { 'Down' }
default { $Item.Online }
}
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { $_.'Status' -like 'Down' } | Set-Style -Style Warning -Property 'Status'
@@ -82,11 +76,11 @@ function Get-AbrOntapVserverNamespaceStorage {
}
$VserverObj | Sort-Object -Property 'Namespace Name' | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure that all namespaces are operational to maintain optimal storage connectivity."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all namespaces are operational to maintain optimal storage connectivity.'
}
BlankLine
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNetworkInterface.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNetworkInterface.ps1
new file mode 100644
index 0000000..6352416
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNetworkInterface.ps1
@@ -0,0 +1,90 @@
+function Get-AbrOntapVserverNetworkInterface {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver interfaces information
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ [CmdletBinding()]
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP vserver network interface information.'
+ }
+
+ process {
+ try {
+ $ClusterData = Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'data' -and $_.Vserver -notin $options.Exclude.Vserver -and $_.Vserver -eq $Vserver }
+ $ClusterObj = @()
+ if ($ClusterData) {
+ foreach ($Item in $ClusterData) {
+ try {
+ $inObj = [ordered] @{
+ 'Data Interface' = $Item.InterfaceName
+ 'Status' = ${Item}?.OpStatus?.ToString()?.ToUpper()
+ 'Data Protocols' = [string]$Item.DataProtocols
+ 'Address' = ($Null -eq $Item.Wwpn) ? $Item.Address: $Item.Wwpn
+ 'Home Node' = $Item.HomeNode
+ 'Is Home' = $Item.IsHome
+ }
+ $ClusterObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+ if ($Healthcheck.Network.Interface) {
+ $ClusterObj | Where-Object { $_.'Status' -notlike 'UP' } | Set-Style -Style Warning -Property 'Status'
+ $ClusterObj | Where-Object { $_.'Is Home' -eq 'No' } | Set-Style -Style Warning -Property 'Is Home'
+ }
+
+ $TableParams = @{
+ Name = "Data Network - $($Vserver)"
+ List = $false
+ ColumnWidths = 25, 9, 19, 17, 15, 15
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $ClusterObj | Table @TableParams
+ if ($Healthcheck.Network.Interface -and (($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' }) -or (($ClusterObj | Where-Object { $_.'Is Home' -ne 'Yes' })))) {
+ Paragraph 'Health Check:' -Bold -Underline
+ BlankLine
+ if ($ClusterObj | Where-Object { $_.'Status' -notlike 'UP' }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all data network interfaces are operational (UP) to maintain optimal data access and performance.'
+ }
+ BlankLine
+ }
+ if ($ClusterObj | Where-Object { $_.'Is Home' -ne 'Yes' }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure that all network interfaces are on their designated home ports to maintain optimal network performance and reliability.'
+ }
+ BlankLine
+ }
+ }
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapVserverNonMappedLun.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedLun.ps1
similarity index 74%
rename from Src/Private/Get-AbrOntapVserverNonMappedLun.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedLun.ps1
index fdd9129..d6eb756 100755
--- a/Src/Private/Get-AbrOntapVserverNonMappedLun.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedLun.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNonMappedLun {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,25 +23,24 @@ function Get-AbrOntapVserverNonMappedLun {
)
begin {
- Write-PScriboMessage "Collecting ONTAP ISCSI/FCP Non Mapped Lun information."
+ Write-PScriboMessage 'Collecting ONTAP ISCSI/FCP Non Mapped Lun information.'
}
process {
try {
- $LunFilter = Get-NcLun -VserverContext $Vserver -Controller $Array | Where-Object { $_.Mapped -ne "True" }
+ $LunFilter = Get-NcLun -VserverContext $Vserver -Controller $Array | Where-Object { $_.Mapped -ne 'True' }
$OutObj = @()
if ($LunFilter) {
foreach ($Item in $LunFilter) {
try {
- $lunname = (($Item.Path).split('/'))[3]
$inObj = [ordered] @{
'Volume Name' = $Item.Volume
- 'Lun Name' = $lunname
- 'Online' = ConvertTo-TextYN $Item.Online
- 'Mapped' = ConvertTo-TextYN $Item.Mapped
+ 'Lun Name' = ($Item.Path).split('/')[3]
+ 'Online' = $Item.Online
+ 'Mapped' = $Item.Mapped
'Lun Format' = $Item.Protocol
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -60,11 +59,11 @@ function Get-AbrOntapVserverNonMappedLun {
}
$OutObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($OutObj)) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Review non-mapped LUNs to determine if they are still required or can be removed to optimize storage resources."
+ Text 'Best Practice:' -Bold
+ Text 'Review non-mapped LUNs to determine if they are still required or can be removed to optimize storage resources.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1
similarity index 79%
rename from Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1
index 8090e74..29fac33 100755
--- a/Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNonMappedNamespace.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNonMappedNamespace {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNonMappedNamespace {
)
begin {
- Write-PScriboMessage "Collecting ONTAP NVME Non Mapped Namespace information."
+ Write-PScriboMessage 'Collecting ONTAP NVME Non Mapped Namespace information.'
}
process {
@@ -33,15 +33,14 @@ function Get-AbrOntapVserverNonMappedNamespace {
if ($NamespaceFilter) {
foreach ($Item in $NamespaceFilter) {
try {
- $namespacename = (($Item.Path).split('/'))[3]
$inObj = [ordered] @{
'Volume Name' = $Item.Volume
- 'Lun Name' = $namespacename
+ 'Namespace Name' = ($Item.Path).split('/')[3]
'Type' = $Item.Ostype
- 'Mapped' = "No"
+ 'Mapped' = 'No'
'State' = $Item.State
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -60,11 +59,11 @@ function Get-AbrOntapVserverNonMappedNamespace {
}
$OutObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($OutObj)) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Review non-mapped Namespaces to determine if they are still required or can be removed to optimize storage resources."
+ Text 'Best Practice:' -Bold
+ Text 'Review non-mapped Namespaces to determine if they are still required or can be removed to optimize storage resources.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1
index cdf77e8..ecfa5d1 100755
--- a/Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeFcAdapter.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNvmeFcAdapter {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNvmeFcAdapter {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Nvme FC adapter information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Nvme FC adapter information.'
}
process {
@@ -39,13 +39,9 @@ function Get-AbrOntapVserverNvmeFcAdapter {
'Protocol' = $Item.PhysicalProtocol
'WWNN' = $Item.FcWwnn
'WWPN' = $Item.FcWwpn
- 'Status' = switch ($Item.StatusAdmin) {
- 'up' { 'Up' }
- 'down' { 'Down' }
- default { $Item.StatusAdmin }
- }
+ 'Status' = ($Item.StatusAdmin -eq 'up') ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -65,10 +61,10 @@ function Get-AbrOntapVserverNvmeFcAdapter {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.FCP -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all Nvme FC adapters are in 'Up' status to maintain optimal connectivity and performance."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapVserverNvmeInterface.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeInterface.ps1
similarity index 80%
rename from Src/Private/Get-AbrOntapVserverNvmeInterface.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeInterface.ps1
index e510d6d..5b5f4fb 100755
--- a/Src/Private/Get-AbrOntapVserverNvmeInterface.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeInterface.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNvmeInterface {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNvmeInterface {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver NVME interface information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver NVME interface information.'
}
process {
@@ -37,13 +37,9 @@ function Get-AbrOntapVserverNvmeInterface {
'Interface Name' = $Item.Lif
'Transport Address' = $Item.TransportAddress
'Transport Protocols' = $Item.TransportProtocols
- 'Status' = switch ($Item.StatusAdmin) {
- 'up' { 'Up' }
- 'down' { 'Down' }
- default { $Item.StatusAdmin }
- }
+ 'Status' = $Item.StatusAdmin -eq 'up' ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -62,10 +58,10 @@ function Get-AbrOntapVserverNvmeInterface {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Nvme -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all NVME interfaces are in 'Up' status to maintain optimal connectivity and performance."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1
similarity index 81%
rename from Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1
index ca01d90..863e86c 100755
--- a/Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverNvmeTcpAdapter.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverNvmeTcpAdapter {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverNvmeTcpAdapter {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Nvme TCP adapter information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Nvme TCP adapter information.'
}
process {
@@ -38,13 +38,9 @@ function Get-AbrOntapVserverNvmeTcpAdapter {
'Adapter' = $Item.HomePort
'Protocol' = $Item.PhysicalProtocol
'IP Address' = $Item.TransportAddress
- 'Status' = switch ($Item.StatusAdmin) {
- 'up' { 'Up' }
- 'down' { 'Down' }
- default { $Item.StatusAdmin }
- }
+ 'Status' = $Item.StatusAdmin -eq 'up' ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -64,10 +60,10 @@ function Get-AbrOntapVserverNvmeTcpAdapter {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.FCP -and ($VserverObj | Where-Object { $_.'Status' -like 'Down' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all Nvme TCP adapters are in 'Up' status to maintain optimal connectivity and performance."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapVserverS3Bucket.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Bucket.ps1
similarity index 75%
rename from Src/Private/Get-AbrOntapVserverS3Bucket.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Bucket.ps1
index 799cc1d..6353c22 100755
--- a/Src/Private/Get-AbrOntapVserverS3Bucket.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Bucket.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverS3Bucket {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverS3Bucket {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver S3 bucket information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver S3 bucket information.'
}
process {
@@ -36,10 +36,10 @@ function Get-AbrOntapVserverS3Bucket {
$inObj = [ordered] @{
'Bucket' = $Item.Name
'Volume' = $Item.volume.name
- 'Total' = $Item.size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $Item.logical_used_size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Total' = ($Item.size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Item.logical_used_size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverS3Summary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Summary.ps1
similarity index 74%
rename from Src/Private/Get-AbrOntapVserverS3Summary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Summary.ps1
index 25b1c07..69fd8d6 100755
--- a/Src/Private/Get-AbrOntapVserverS3Summary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverS3Summary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverS3Summary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverS3Summary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver S3 information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver S3 information.'
}
process {
@@ -34,17 +34,13 @@ function Get-AbrOntapVserverS3Summary {
foreach ($Item in $VserverData) {
try {
$inObj = [ordered] @{
- 'HTTP' = ConvertTo-TextYN $Item.is_http_enabled
+ 'HTTP' = $Item.is_http_enabled
'HTTP Port' = $Item.port
- 'HTTPS' = ConvertTo-TextYN $Item.is_https_enabled
+ 'HTTPS' = $Item.is_https_enabled
'HTTPS Port' = $Item.secure_port
- 'Status' = Switch ($Item.enabled) {
- 'True' { 'UP' }
- 'False' { 'Down' }
- default { $Item.enabled }
- }
+ 'Status' = $Item.enabled -eq $true ? 'Up': 'Down'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverSubsystem.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSubsystem.ps1
similarity index 83%
rename from Src/Private/Get-AbrOntapVserverSubsystem.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSubsystem.ps1
index b00710d..38ddb93 100755
--- a/Src/Private/Get-AbrOntapVserverSubsystem.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSubsystem.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverSubsystem {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverSubsystem {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver Subsystem information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver Subsystem information.'
}
process {
@@ -48,12 +48,9 @@ function Get-AbrOntapVserverSubsystem {
'Type' = $Item.Ostype
'Target NQN' = $Item.TargetNqn
'Host NQN' = $Item.Hosts.Nqn
- 'Mapped Namespace' = switch (($MappedNamespace).count) {
- 0 { "None" }
- default { $MappedNamespace }
- }
+ 'Mapped Namespace' = (($MappedNamespace).count -eq 0) ? 'None': $MappedNamespaces
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { ($_.'Mapped Namespace').count -eq 0 } | Set-Style -Style Warning -Property 'Mapped Namespace'
}
@@ -68,11 +65,11 @@ function Get-AbrOntapVserverSubsystem {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { ($_.'Mapped Namespace').count -eq 0 })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure all subsystems have mapped namespaces to guarantee proper functionality and performance."
+ Text 'Best Practice:' -Bold
+ Text 'Ensure all subsystems have mapped namespaces to guarantee proper functionality and performance.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverSummary.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSummary.ps1
similarity index 82%
rename from Src/Private/Get-AbrOntapVserverSummary.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSummary.ps1
index 7d4a542..f8e4100 100755
--- a/Src/Private/Get-AbrOntapVserverSummary.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverSummary.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverSummary {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapVserverSummary {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver information.'
}
process {
try {
- $VserverData = Get-NcVserver -VserverContext $Vserver | Where-Object { $_.VserverType -eq "data" }
+ $VserverData = Get-NcVserver -VserverContext $Vserver | Where-Object { $_.VserverType -eq 'data' }
$VserverObj = @()
if ($VserverData) {
foreach ($Item in $VserverData) {
@@ -40,7 +40,7 @@ function Get-AbrOntapVserverSummary {
'IPSpace' = $Item.Ipspace
'Status' = $Item.State
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -59,10 +59,10 @@ function Get-AbrOntapVserverSummary {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $_.'Status' -like 'stopped' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all Vservers are in 'running' status to provide uninterrupted services."
}
BlankLine
@@ -78,13 +78,13 @@ function Get-AbrOntapVserverSummary {
$inObj = [ordered] @{
'Root Volume' = $Item.Name
'Status' = $Item.State
- 'Total Size' = $Item.Totalsize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $Item.Used | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
- 'Available' = $Item.Available | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Dedup' = ConvertTo-TextYN $Item.Dedupe
+ 'Total Size' = ($Item.Totalsize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($Item.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Available' = ($Item.Available | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Dedup' = $Item.Dedupe
'Aggregate' = $Item.Aggregate
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -109,7 +109,7 @@ function Get-AbrOntapVserverSummary {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
try {
- if (Get-NcVserverAggr) {
+ if (Get-NcVserverAggr -VserverContext $Vserver) {
Section -Style Heading4 'Aggregate Resource Allocation' {
$VserverAGGR = Get-NcVserverAggr -VserverContext $Vserver -Controller $Array
$VserverObj = @()
@@ -120,9 +120,9 @@ function Get-AbrOntapVserverSummary {
'Aggregate' = $Item.AggregateName
'Type' = $Item.AggregateType
'SnapLock Type' = $Item.SnaplockType
- 'Available' = $Item.AvailableSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Available' = ($Item.AvailableSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1
similarity index 65%
rename from Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1
index 3a10b87..0f41d19 100755
--- a/Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshot.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumeSnapshot {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumeSnapshot {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes snapshot information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes snapshot information.'
}
process {
@@ -37,20 +37,20 @@ function Get-AbrOntapVserverVolumeSnapshot {
$SnapPolicy = Get-NcVol $Item.Name -VserverContext $Vserver -Controller $Array | Select-Object -ExpandProperty VolumeSnapshotAttributes
$inObj = [ordered] @{
'Volume' = $Item.Name
- 'Snapshot Enabled' = ConvertTo-TextYN $SnapPolicy.AutoSnapshotsEnabled
- 'Reserve Size' = $SnapReserve.SnapshotReserveSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Reserve Available' = $SnapReserve.SnapshotReserveAvailable | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
- 'Used' = $SnapReserve.SizeUsedBySnapshots | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Snapshot Enabled' = $SnapPolicy.AutoSnapshotsEnabled
+ 'Reserve Size' = ($SnapReserve.SnapshotReserveSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Reserve Available' = ($SnapReserve.SnapshotReserveAvailable | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($SnapReserve.SizeUsedBySnapshots | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
'Policy' = $SnapPolicy.SnapshotPolicy
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Vserver.Snapshot) {
- $VserverObj | Where-Object { $_.'Snapshot Enabled' -eq 'Yes' -and $_.'Reserve Available' -eq 0 } | Set-Style -Style Warning -Property 'Reserve Size', 'Reserve Available', 'Used'
+ $VserverObj | Where-Object { $_.'Used' -gt $_.'Reserve Size' } | Set-Style -Style Warning -Property 'Reserve Size', 'Reserve Available', 'Used'
}
$TableParams = @{
@@ -63,12 +63,12 @@ function Get-AbrOntapVserverVolumeSnapshot {
}
if ($VserverObj) {
$VserverObj | Table @TableParams
- if ($Healthcheck.Vserver.Snapshot -and ($VserverObj | Where-Object { $_.'Snapshot Enabled' -eq 'Yes' -and $_.'Reserve Available' -eq 0 })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Vserver.Snapshot -and ($VserverObj | Where-Object { $_.'Snapshot Enabled' -eq 'Yes' -and ($_.'Used'.split()[0] -gt $_.'Reserve Size'.split()[0]) })) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Snapshots are enabled on volumes but there is no available snapshot reserve space. It is recommended to increase the snapshot reserve size to avoid snapshot failures."
+ Text 'Best Practice:' -Bold
+ Text 'Snapshots are enabled on volumes but there is no available snapshot reserve space. It is recommended to increase the snapshot reserve size to avoid snapshot failures.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1
similarity index 78%
rename from Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1
index c810933..efd6fd7 100755
--- a/Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumeSnapshotHealth.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumeSnapshotHealth {
.DESCRIPTION
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,17 +23,17 @@ function Get-AbrOntapVserverVolumeSnapshotHealth {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes snapshot healthcheck information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes snapshot healthcheck information.'
}
process {
try {
- $SnapshotDays = 7
+ $SnapshotDays = 30
$Now = Get-Date
$VserverFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
- $SnapShotData = Get-NcSnapshot -Volume $VserverFilter -Vserver $Vserver -Controller $Array | Where-Object { $_.Name -notmatch "snapmirror.*" -and $_.Created -le $Now.AddDays(-$SnapshotDays) }
+ $SnapShotData = Get-NcSnapshot -Volume $VserverFilter -Vserver $Vserver -Controller $Array | Where-Object { $_.Name -notmatch 'snapmirror.*' -and $_.Created -le $Now.AddDays(-$SnapshotDays) }
if ($SnapShotData) {
- Section -Style Heading4 "HealthCheck - Volumes Snapshot" {
+ Section -Style Heading4 'HealthCheck - Volumes Snapshot' {
Paragraph "The following section provides the Vserver Volumes Snapshot HealthCheck in $($SVM)."
BlankLine
$VserverObj = @()
@@ -43,16 +43,16 @@ function Get-AbrOntapVserverVolumeSnapshotHealth {
'Volume Name' = $Item.Volume
'Snapshot Name' = $Item.Name
'Created Time' = $Item.Created
- 'Used' = $Item.Total | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Used' = ($Item.Total | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
$TableParams = @{
- Name = "HealthCheck - Volume Snapshot over 7 days - $($Vserver)"
+ Name = "HealthCheck - Volume Snapshot over $($SnapshotDays) days - $($Vserver)"
List = $false
ColumnWidths = 25, 35, 25, 15
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumes.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumes.ps1
similarity index 52%
rename from Src/Private/Get-AbrOntapVserverVolumes.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumes.ps1
index 04d2a04..98a5dc8 100755
--- a/Src/Private/Get-AbrOntapVserverVolumes.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumes.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolume {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolume {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes information.'
}
process {
@@ -36,19 +36,19 @@ function Get-AbrOntapVserverVolume {
$inObj = [ordered] @{
'Volume' = $Item.Name
'Status' = $Item.State
- 'Capacity' = $Item.Totalsize | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Available' = $Item.Available | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Used' = $Item.Used | ConvertTo-FormattedNumber -Type Percent -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Totalsize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Available' = ($Item.Available | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Used' = ($Item.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
'Aggregate' = $Item.Aggregate
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { $_.'Status' -like 'offline' } | Set-Style -Style Warning -Property 'Status'
- $VserverObj | Where-Object { $_.'Used' -ge 75 } | Set-Style -Style Warning -Property 'Used'
+ $VserverObj | Where-Object { [int]$_.'Used'.Split('%')[0] -ge 75 } | Set-Style -Style Warning -Property 'Used'
}
$TableParams = @{
@@ -60,14 +60,23 @@ function Get-AbrOntapVserverVolume {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$VserverObj | Table @TableParams
- if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $_.'Status' -like 'offline' })) {
- Paragraph "Health Check:" -Bold -Underline
+ if ($Healthcheck.Vserver.Status -and (($VserverObj | Where-Object { $_.'Status' -like 'offline' }) -or ($VserverObj | Where-Object { $_.'Used'.Split('%')[0] -ge 75 }))) {
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
- Paragraph {
- Text "Best Practice:" -Bold
- Text "Ensure all volumes are in 'online' status and monitor volume usage to prevent capacity issues."
+ if ($VserverObj | Where-Object { $_.'Status' -like 'offline' }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text "Ensure all volumes are in 'online' status and monitor volume usage to prevent capacity issues."
+ }
+ BlankLine
+ }
+ if ($VserverObj | Where-Object { [int]$_.'Used'.Split('%')[0] -ge 75 }) {
+ Paragraph {
+ Text 'Best Practice:' -Bold
+ Text 'Ensure all volumes are below 95% usage to prevent capacity issues.'
+ }
+ BlankLine
}
- BlankLine
}
}
} catch {
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesAutosize.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesAutosize.ps1
new file mode 100644
index 0000000..8258929
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesAutosize.ps1
@@ -0,0 +1,69 @@
+function Get-AbrOntapVserverVolumesAutosize {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver per volumes autosize attributes information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver per volumes autosize attributes information.'
+ }
+
+ process {
+ try {
+ $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ $OutObj = @()
+ if ($VolumeFilter) {
+ foreach ($Item in $VolumeFilter) {
+ try {
+ $AutosizeAttr = $Item.VolumeAutosizeAttributes
+ $inObj = [ordered] @{
+ 'Volume' = $Item.Name
+ 'Autosize Enabled' = $AutosizeAttr.IsEnabled
+ 'Mode' = $AutosizeAttr.Mode ?? '--'
+ 'Minimum Size' = ($AutosizeAttr.MinimumSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Maximum Size' = ($AutosizeAttr.MaximumSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Grow Threshold %' = ($AutosizeAttr.GrowThresholdPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Shrink Threshold %' = ($AutosizeAttr.ShrinkThresholdPercent | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ $TableParams = @{
+ Name = "Per Volume Autosize Attributes - $($Vserver)"
+ List = $false
+ ColumnWidths = 20, 14, 10, 14, 14, 14, 14
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1
new file mode 100755
index 0000000..604b3f3
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesExportPolicy.ps1
@@ -0,0 +1,63 @@
+function Get-AbrOntapVserverVolumesExportPolicy {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver per volumes export policy information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver per volumes export policy information.'
+ }
+
+ process {
+ try {
+ $VolumeData = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ $VolumeObj = @()
+ if ($VolumeData) {
+ foreach ($Volume in $VolumeData) {
+ try {
+ $inObj = [ordered] @{
+ 'Volume Name' = $Volume.Name
+ 'Export Policy' = (((Get-NcVol -VS $Vserver -Controller $Array | Where-Object { $_.Name -eq $Volume.Name }).VolumeExportAttributes).Policy) ?? 'None'
+ }
+ $VolumeObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ $TableParams = @{
+ Name = "Per Volume Export Policy - $($Vserver)"
+ List = $false
+ ColumnWidths = 50, 50
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $VolumeObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
\ No newline at end of file
diff --git a/Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1
similarity index 84%
rename from Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1
index 3ff0c21..c72c62c 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexcache.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesFlexcache {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumesFlexcache {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver flexcache volumes information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver flexcache volumes information.'
}
process {
@@ -41,9 +41,9 @@ function Get-AbrOntapVserverVolumesFlexcache {
'Cache Volume' = $Item.CacheVolume
'Origin Vserver' = $Item.OriginVserver
'Origin Volume' = $Item.OriginVolume
- 'Capacity' = $VolumeUsage.TotalSize | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Capacity' = ($VolumeUsage.TotalSize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -72,9 +72,9 @@ function Get-AbrOntapVserverVolumesFlexcache {
'Origin Volume' = $Item.OriginVolume
'Cache Vserver' = $Item.Vserver
'Cache Volume' = $Item.Volume
- 'Capacity' = $Item.Size | ConvertTo-FormattedNumber -Type Datasize -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1
similarity index 68%
rename from Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1
index 7315427..45e0bdc 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexclone.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesFlexclone {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumesFlexclone {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes flexclone information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes flexclone information.'
}
process {
@@ -35,16 +35,16 @@ function Get-AbrOntapVserverVolumesFlexclone {
$inObj = [ordered] @{
'Volume' = $Item.Name
'Parent Volume' = $Item.ParentVolume
- 'Volume Type' = $Item.VolumeType.ToUpper()
+ 'Volume Type' = ${Item}?.VolumeType?.ToUpper()
'Parent Snapshot' = $Item.ParentSnapshot
'Space Reserve' = $Item.SpaceReserve
- 'Space Guarantee' = ConvertTo-TextYN $Item.SpaceGuaranteeEnabled
- 'Capacity' = $Item.Size | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Available' = $Item.Size - $Item.Used | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
- 'Used' = $Item.Used | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
+ 'Space Guarantee' = $Item.SpaceGuaranteeEnabled
+ 'Capacity' = ($Item.Size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Available' = ($Item.Size - $Item.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Used' = ($Item.Used | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
'Aggregate' = $Item.Aggregate
}
- $VserverObj = [pscustomobject]$inobj
+ $VserverObj = [pscustomobject](ConvertTo-HashToYN $inObj)
if ($Healthcheck.Vserver.Status) {
$VserverObj | Where-Object { $_.'Status' -like 'offline' } | Set-Style -Style Warning -Property 'Status'
@@ -60,11 +60,11 @@ function Get-AbrOntapVserverVolumesFlexclone {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj)) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Regularly monitor flexclone volumes to manage storage utilization effectively."
+ Text 'Best Practice:' -Bold
+ Text 'Regularly monitor flexclone volumes to manage storage utilization effectively.'
}
BlankLine
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1
similarity index 80%
rename from Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1
index 2b18794..d58f158 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesFlexgroup.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesFlexgroup {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapVserverVolumesFlexgroup {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver flexgroup volumes information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver flexgroup volumes information.'
}
process {
try {
- $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsFlexgroup -eq "True" }
+ $Data = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsFlexgroup -eq 'True' }
$OutObj = @()
if ($Data) {
foreach ($Item in $Data) {
@@ -36,9 +36,9 @@ function Get-AbrOntapVserverVolumesFlexgroup {
$inObj = [ordered] @{
'Volume' = $Item.Name
'Status' = $Item.State
- 'Capacity' = $Item.Totalsize | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
+ 'Capacity' = ($Item.Totalsize | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -57,10 +57,10 @@ function Get-AbrOntapVserverVolumesFlexgroup {
}
$OutObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($OutObj | Where-Object { $_.'Status' -like 'offline' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all flexgroup volumes are in 'online' status to maintain data availability."
}
BlankLine
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesInodeAttr.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesInodeAttr.ps1
new file mode 100644
index 0000000..6edd3e9
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesInodeAttr.ps1
@@ -0,0 +1,68 @@
+function Get-AbrOntapVserverVolumesInodeAttr {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver per volumes inode attributes information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver per volumes inode attributes information.'
+ }
+
+ process {
+ try {
+ $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ $OutObj = @()
+ if ($VolumeFilter) {
+ foreach ($Item in $VolumeFilter) {
+ try {
+ $InodeAttr = $Item.VolumeInodeAttributes
+ $inObj = [ordered] @{
+ 'Volume' = $Item.Name
+ 'Files Total' = $InodeAttr.FilesTotal ?? '--'
+ 'Files Used' = $InodeAttr.FilesUsed ?? '--'
+ 'Files Private Used' = $InodeAttr.FilesPrivateUsed ?? '--'
+ 'Inode File Private Capacity' = $InodeAttr.InodefilePrivateCapacity ?? '--'
+ 'Inode File Public Capacity' = $InodeAttr.InodefilePublicCapacity ?? '--'
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ $TableParams = @{
+ Name = "Per Volume Inode Attributes - $($Vserver)"
+ List = $false
+ ColumnWidths = 22, 14, 14, 16, 17, 17
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesLanguage.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesLanguage.ps1
new file mode 100644
index 0000000..06ab363
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesLanguage.ps1
@@ -0,0 +1,67 @@
+function Get-AbrOntapVserverVolumesLanguage {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver per volumes language attributes information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver per volumes language attributes information.'
+ }
+
+ process {
+ try {
+ $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ $OutObj = @()
+ if ($VolumeFilter) {
+ foreach ($Item in $VolumeFilter) {
+ try {
+ $LangAttr = $Item.VolumeLanguageAttributes
+ $inObj = [ordered] @{
+ 'Volume' = $Item.Name
+ 'Language' = $LangAttr.Language ?? '--'
+ 'Language Code' = $LangAttr.LanguageCode ?? '--'
+ 'Convert Ucode Enabled' = $LangAttr.IsConvertUcodeEnabled
+ 'Create Ucode Enabled' = $LangAttr.IsCreateUcodeEnabled
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ $TableParams = @{
+ Name = "Per Volume Language Attributes - $($Vserver)"
+ List = $false
+ ColumnWidths = 22, 30, 20, 14, 14
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesQos.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQos.ps1
similarity index 72%
rename from Src/Private/Get-AbrOntapVserverVolumesQos.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQos.ps1
index fb4d293..c839444 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesQos.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQos.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesQosSetting {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,12 +23,12 @@ function Get-AbrOntapVserverVolumesQosSetting {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes qos information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes qos information.'
}
process {
try {
- $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsConstituent -ne "True" }
+ $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsConstituent -ne 'True' }
$OutObj = @()
if ($VolumeFilter) {
foreach ($Item in $VolumeFilter) {
@@ -36,16 +36,10 @@ function Get-AbrOntapVserverVolumesQosSetting {
$VolQoS = Get-NcVol $Item.Name -Controller $Array | Select-Object -ExpandProperty VolumeQosAttributes
$inObj = [ordered] @{
'Volume' = $Item.Name
- 'Fixed Policy Name' = Switch ($VolQoS.PolicyGroupName) {
- $Null { 'None' }
- default { $VolQoS.PolicyGroupName }
- }
- 'Adaptive Policy Name' = Switch ($VolQoS.AdaptivePolicyGroupName) {
- $Null { 'None' }
- default { $VolQoS.AdaptivePolicyGroupName }
- }
+ 'Fixed Policy Name' = ($Null -eq $VolQoS.PolicyGroupName) ? 'None': $VolQoS.PolicyGroupName
+ 'Adaptive Policy Name' = ($Null -eq $VolQoS.PolicyGroupName) ? 'None': $VolQoS.AdaptivePolicyGroupName
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1
similarity index 89%
rename from Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1
index e0143db..1f68801 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPAdaptive.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesQosGPAdaptive {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,7 +19,7 @@ function Get-AbrOntapVserverVolumesQosGPAdaptive {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes qos group adaptive information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes qos group adaptive information.'
}
process {
@@ -36,7 +36,7 @@ function Get-AbrOntapVserverVolumesQosGPAdaptive {
'Min Iops' = $Item.AbsoluteMinIops
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1
similarity index 83%
rename from Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1
index 9e631cb..f05976b 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQosGPFixed.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesQosGPFixed {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -19,12 +19,12 @@ function Get-AbrOntapVserverVolumesQosGPFixed {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes qos group fixed information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes qos group fixed information.'
}
process {
try {
- $QoSFilter = Get-NcQosPolicyGroup -Controller $Array | Where-Object { $_.PolicyGroupClass -eq "user_defined" }
+ $QoSFilter = Get-NcQosPolicyGroup -Controller $Array | Where-Object { $_.PolicyGroupClass -eq 'user_defined' }
$OutObj = @()
if ($QoSFilter) {
foreach ($Item in $QoSFilter) {
@@ -33,10 +33,10 @@ function Get-AbrOntapVserverVolumesQosGPFixed {
'Policy Name' = $Item.PolicyGroup
'Max Throughput' = $Item.MaxThroughput
'Min Throughput' = $Item.MinThroughput
- 'Is Shared' = ConvertTo-TextYN $Item.IsShared
+ 'Is Shared' = $Item.IsShared
'Vserver' = $Item.Vserver
}
- $OutObj += [pscustomobject]$inobj
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/Src/Private/Get-AbrOntapVserverVolumesQtree.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQtree.ps1
similarity index 88%
rename from Src/Private/Get-AbrOntapVserverVolumesQtree.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQtree.ps1
index 2bb0a03..093e998 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesQtree.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQtree.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesQtree {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumesQtree {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes qtree information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes qtree information.'
}
process {
@@ -40,7 +40,7 @@ function Get-AbrOntapVserverVolumesQtree {
'Security Style' = $Item.SecurityStyle
'Export Policy' = $Item.ExportPolicy
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -59,10 +59,10 @@ function Get-AbrOntapVserverVolumesQtree {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $_.'Status' -notlike 'normal' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
+ Text 'Best Practice:' -Bold
Text "Ensure all qtrees are in 'normal' status to maintain data integrity and accessibility."
}
BlankLine
diff --git a/Src/Private/Get-AbrOntapVserverVolumesQuota.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQuota.ps1
similarity index 72%
rename from Src/Private/Get-AbrOntapVserverVolumesQuota.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQuota.ps1
index 0b75970..50d1a1d 100755
--- a/Src/Private/Get-AbrOntapVserverVolumesQuota.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesQuota.ps1
@@ -5,7 +5,7 @@ function Get-AbrOntapVserverVolumesQuota {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -23,7 +23,7 @@ function Get-AbrOntapVserverVolumesQuota {
)
begin {
- Write-PScriboMessage "Collecting ONTAP Vserver volumes quota information."
+ Write-PScriboMessage 'Collecting ONTAP Vserver volumes quota information.'
}
process {
@@ -41,7 +41,7 @@ function Get-AbrOntapVserverVolumesQuota {
'Status' = $Item.Status
'Substatus' = $Item.Substatus
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
if ($null -ne $Item.QuotaErrorMsgs) {
$VserverObj.Add('Quota Error', $Item.QuotaErrorMsgs)
}
@@ -63,11 +63,11 @@ function Get-AbrOntapVserverVolumesQuota {
}
$VserverObj | Table @TableParams
if ($Healthcheck.Vserver.Status -and ($VserverObj | Where-Object { $null -ne $_.'Quota Error' })) {
- Paragraph "Health Check:" -Bold -Underline
+ Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
- Text "Best Practice:" -Bold
- Text "Review and resolve any quota errors to ensure proper quota enforcement and avoid potential data management issues."
+ Text 'Best Practice:' -Bold
+ Text 'Review and resolve any quota errors to ensure proper quota enforcement and avoid potential data management issues.'
}
BlankLine
}
@@ -91,24 +91,12 @@ function Get-AbrOntapVserverVolumesQuota {
'Volume' = $Item.Volume
'Type' = $Item.QuotaType
'Target' = $Item.QuotaTarget
- 'Disk Limit' = switch ($Item.DiskLimit) {
- "-" { $Item.DiskLimit }
- default { $Item.DiskLimit | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue }
- }
- 'File Limit' = switch ($Item.FileLimit) {
- "-" { $Item.FileLimit }
- default { $Item.FileLimit | ConvertTo-FormattedNumber -Type Count -ErrorAction SilentlyContinue }
- }
- 'Soft Disk Limit' = switch ($Item.SoftDiskLimit) {
- "-" { $Item.SoftDiskLimit }
- default { $Item.SoftDiskLimit | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue }
- }
- 'Soft File Limit' = switch ($Item.SoftFileLimit) {
- "-" { $Item.SoftFileLimit }
- default { $Item.SoftFileLimit | ConvertTo-FormattedNumber -Type Count -ErrorAction SilentlyContinue }
- }
+ 'Disk Limit' = ($Item.DiskLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'File Limit' = ($Item.FileLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Count) ?? '--'
+ 'Soft Disk Limit' = ($Item.SoftDiskLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Soft File Limit' = ($Item.SoftFileLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Count) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
if ($null -ne $Item.QuotaError) {
$VserverObj.Add('Quota Error', $Item.QuotaError)
}
@@ -148,17 +136,11 @@ function Get-AbrOntapVserverVolumesQuota {
'Volume' = $Item.Volume
'Quota Target' = $Item.QuotaTarget
'Qtree' = $Item.Qtree
- 'Disk Limit' = switch ($Item.DiskLimit) {
- "-" { $Item.DiskLimit }
- default { $Item.DiskLimit | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue }
- }
- 'Soft Disk Limit' = switch ($Item.SoftDiskLimit) {
- "-" { $Item.SoftDiskLimit }
- default { $Item.SoftDiskLimit | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue }
- }
- 'Disk Used' = $Item.DiskUsed | ConvertTo-FormattedNumber -Type DataSize -ErrorAction SilentlyContinue
+ 'Disk Limit' = ($Item.DiskLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Soft Disk Limit' = ($Item.SoftDiskLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
+ 'Disk Used' = ($Item.DiskUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type DataSize) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
@@ -197,17 +179,11 @@ function Get-AbrOntapVserverVolumesQuota {
'Volume' = $Item.Volume
'Quota Target' = $Item.QuotaTarget
'Qtree' = $Item.Qtree
- 'File Limit' = switch ($Item.FileLimit) {
- "-" { $Item.FileLimit }
- default { $Item.FileLimit | ConvertTo-FormattedNumber -Type Count -ErrorAction SilentlyContinue }
- }
- 'Soft File Limit' = switch ($Item.SoftFileLimit) {
- "-" { $Item.SoftFileLimit }
- default { $Item.SoftFileLimit | ConvertTo-FormattedNumber -Type Count -ErrorAction SilentlyContinue }
- }
- 'Files Used' = $Item.FilesUsed | ConvertTo-FormattedNumber -Type Count -ErrorAction SilentlyContinue
+ 'File Limit' = ($Item.FileLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Count) ?? '--'
+ 'Soft File Limit' = ($Item.SoftFileLimit | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Count) ?? '--'
+ 'Files Used' = ($Item.FilesUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Count) ?? '--'
}
- $VserverObj += [pscustomobject]$inobj
+ $VserverObj += [pscustomobject](ConvertTo-HashToYN $inObj)
} catch {
Write-PScriboMessage -IsWarning $_.Exception.Message
}
diff --git a/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesSpaceAttr.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesSpaceAttr.ps1
new file mode 100644
index 0000000..5cc32eb
--- /dev/null
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-AbrOntapVserverVolumesSpaceAttr.ps1
@@ -0,0 +1,69 @@
+function Get-AbrOntapVserverVolumesSpaceAttr {
+ <#
+ .SYNOPSIS
+ Used by As Built Report to retrieve NetApp ONTAP vserver per volumes space attributes information from the Cluster Management Network
+ .DESCRIPTION
+
+ .NOTES
+ Version: 0.6.12
+ Author: Jonathan Colon
+ Twitter: @jcolonfzenpr
+ Github: rebelinux
+ .EXAMPLE
+
+ .LINK
+
+ #>
+ param (
+ [Parameter (
+ Position = 0,
+ Mandatory)]
+ [string]
+ $Vserver
+ )
+
+ begin {
+ Write-PScriboMessage 'Collecting ONTAP Vserver per volumes space attributes information.'
+ }
+
+ process {
+ try {
+ $VolumeFilter = Get-NcVol -VserverContext $Vserver -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }
+ $OutObj = @()
+ if ($VolumeFilter) {
+ foreach ($Item in $VolumeFilter) {
+ try {
+ $SpaceAttr = $Item.VolumeSpaceAttributes
+ $inObj = [ordered] @{
+ 'Volume' = $Item.Name
+ 'Total Size' = ($SpaceAttr.Size | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Available' = ($SpaceAttr.SizeAvailable | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ 'Used' = ($SpaceAttr.SizeUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -NumberFormatString 0.0 -Type Datasize) ?? '--'
+ '% Used' = ($SpaceAttr.PercentageSizeUsed | ConvertTo-FormattedNumber -ErrorAction SilentlyContinue -Type Percent) ?? '--'
+ 'Space Guarantee' = $SpaceAttr.SpaceGuarantee ?? '--'
+ 'Guarantee Enabled' = $SpaceAttr.IsSpaceGuaranteeEnabled
+ }
+ $OutObj += [pscustomobject](ConvertTo-HashToYN $inObj)
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ $TableParams = @{
+ Name = "Per Volume Space Attributes - $($Vserver)"
+ List = $false
+ ColumnWidths = 20, 12, 12, 12, 10, 18, 16
+ }
+ if ($Report.ShowTableCaptions) {
+ $TableParams['Caption'] = "- $($TableParams.Name)"
+ }
+ $OutObj | Table @TableParams
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
+
+ end {}
+
+}
diff --git a/Src/Private/Get-NetAppOntapAPI.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-NetAppOntapAPI.ps1
similarity index 92%
rename from Src/Private/Get-NetAppOntapAPI.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Private/Get-NetAppOntapAPI.ps1
index efc0e2e..8d6e12c 100644
--- a/Src/Private/Get-NetAppOntapAPI.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Private/Get-NetAppOntapAPI.ps1
@@ -5,7 +5,7 @@ function Get-NetAppOntapAPI {
.DESCRIPTION
.NOTES
- Version: 0.6.7
+ Version: 0.6.12
Author: Tim Carman
Editor: Jonathan Colon
Twitter: @jcolonfzenpr
@@ -26,7 +26,7 @@ function Get-NetAppOntapAPI {
)
begin {
- $certCallback = @"
+ $certCallback = @'
using System;
using System.Net;
using System.Net.Security;
@@ -51,23 +51,23 @@ function Get-NetAppOntapAPI {
}
}
}
-"@
+'@
if ($PSVersionTable.PSEdition -ne 'Core') {
#region Workaround for SelfSigned Cert an force TLS 1.2
if (-not ([System.Management.Automation.PSTypeName]'ServerCertificateValidationCallback').Type) {
Add-Type $certCallback
}
[ServerCertificateValidationCallback]::Ignore()
- [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
+ [Net.ServicePointManager]::SecurityProtocol = 'tls12, tls11, tls'
#endregion Workaround for SelfSigned Cert an force TLS 1.2
}
$username = $Credential.UserName
$password = $Credential.GetNetworkCredential().Password
- $auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($username + ":" + $password ))
+ $auth = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($username + ':' + $password ))
$ClusterIP = $ClusterInfo.NcController.Address.IPAddressToString
#$fields = 'fields=*&return_records=true&return_timeout=15'
- $api = "https://" + $($ClusterIP)
+ $api = 'https://' + $($ClusterIP)
$headers = @{
'Accept' = 'application/json'
'Authorization' = "Basic $auth"
diff --git a/Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1 b/AsBuiltReport.NetApp.ONTAP/Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1
similarity index 51%
rename from Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1
rename to AsBuiltReport.NetApp.ONTAP/Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1
index ff05765..822c9f0 100755
--- a/Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1
+++ b/AsBuiltReport.NetApp.ONTAP/Src/Public/Invoke-AsBuiltReport.NetApp.ONTAP.ps1
@@ -5,7 +5,7 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
.DESCRIPTION
Documents the configuration of NetApp ONTAP in Word/HTML/Text formats using PScribo.
.NOTES
- Version: 0.6.8
+ Version: 0.6.12
Author: Jonathan Colon Feliciano
Twitter: @jcolonfzenpr
Github: rebelinux
@@ -15,13 +15,15 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP
#>
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Scope = "Function")]
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingUserNameAndPassWordParams", "", Scope = "Function")]
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "", Scope = "Function")]
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "", Scope = "Function")]
- [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Scope = "Function")]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope = 'Function')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', '', Scope = 'Function')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Scope = 'Function')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Scope = 'Function')]
#Requires -RunAsAdministrator
+ #Requires -Version 7.5
+ #Requires -PSEdition Core
# Do not remove or add to these parameters
param (
@@ -29,50 +31,52 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
[PSCredential] $Credential
)
- #Requires -RunAsAdministrator
-
if ($psISE) {
- Write-Error -Message "You cannot run this script inside the PowerShell ISE. Please execute it from the PowerShell Command Window."
+ Write-Error -Message 'You cannot run this script inside the PowerShell ISE. Please execute it from the PowerShell Command Window.'
break
}
- Write-Host "- Please refer to the AsBuiltReport.NetApp.ONTAP github website for more detailed information about this project."
- Write-Host "- Do not forget to update your report configuration file after each new version release."
- Write-Host "- Documentation: https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP"
- Write-Host "- Issues or bug reporting: https://github.com/AsBuiltReport/AsBuiltReport.NetApp.ONTAP/issues"
- Write-Host "- This project is community maintained and has no sponsorship from NetApp, its employees or any of its affiliates."
- Write-Host "- To sponsor this project, please visit: https://ko-fi.com/F1F8DEV80"
- Write-Host "- Getting dependency information:"
-
+ # Import Report Configuration
+ $script:Report = $ReportConfig.Report
+ $script:InfoLevel = $ReportConfig.InfoLevel
+ $script:Options = $ReportConfig.Options
# Check the version of the dependency modules
- $ModuleArray = @('AsBuiltReport.Netapp.ONTAP', 'Diagrammer.Core')
+ if ($Options.UpdateCheck) {
+ Write-ReportModuleInfo -ModuleName 'Netapp.ONTAP'
+ }
+ Write-Host ' - To sponsor this project, please visit: ' -NoNewline
+ Write-Host 'https://ko-fi.com/F1F8DEV80' -ForegroundColor Cyan
- foreach ($Module in $ModuleArray) {
- try {
- $InstalledVersion = Get-Module -ListAvailable -Name $Module -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version
+ if ($Options.UpdateCheck) {
+ Write-Host ' - Getting dependency information:'
+ # Check the version of the dependency modules
+ $ModuleArray = @('AsBuiltReport.Core', 'AsBuiltReport.Diagram', 'NetApp.ONTAP')
- if ($InstalledVersion) {
- Write-Host " - $Module module v$($InstalledVersion.ToString()) is currently installed."
- $LatestVersion = Find-Module -Name $Module -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version
- if ($InstalledVersion -lt $LatestVersion) {
- Write-Host " - $Module module v$($LatestVersion.ToString()) is available." -ForegroundColor Red
- Write-Host " - Run 'Update-Module -Name $Module -Force' to install the latest version." -ForegroundColor Red
+ foreach ($Module in $ModuleArray) {
+ try {
+ $InstalledVersion = Get-Module -ListAvailable -Name $Module -ErrorAction SilentlyContinue | Sort-Object -Property Version -Descending | Select-Object -First 1 -ExpandProperty Version
+
+ if ($InstalledVersion) {
+ Write-Host " - $Module module v$($InstalledVersion.ToString()) is currently installed."
+ $LatestVersion = Find-Module -Name $Module -Repository PSGallery -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Version
+ if ($InstalledVersion -lt $LatestVersion) {
+ Write-Host " - $Module module v$($LatestVersion.ToString()) is available." -ForegroundColor Red
+ Write-Host " - Run 'Update-Module -Name $Module -Force' to install the latest version." -ForegroundColor Red
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
- } catch {
- Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
- # Import Report Configuration
- $script:Report = $ReportConfig.Report
- $script:InfoLevel = $ReportConfig.InfoLevel
- $script:Options = $ReportConfig.Options
-
# General information
$script:TextInfo = (Get-Culture).TextInfo
+ $script:RootPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
+ $FontPath = Join-Path -Path $RootPath -ChildPath 'Tools/Fonts/ARIAL.TTF'
+
#Connect to Ontap Storage Array using supplied credentials
foreach ($OntapArray in $Target) {
try {
@@ -101,15 +105,21 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
# Variable translating Icon to Image Path ($IconPath)
$script:Images = @{
- "Ontap_LOGO" = "netapp-logo.png"
- "AsBuiltReport_LOGO" = "AsBuiltReport_Logo.png"
- "AsBuiltReport_Signature" = "AsBuiltReport_Signature.png"
- "Ontap_Node" = "ontap_node_new.png"
- "Abr_LOGO_Footer" = "AsBuiltReport.png"
- "Ontap_Node_Icon" = "netapp_node_icon.png"
- "Ontap_Aggregate" = "netapp_aggregate.png"
- "Ontap_SVM" = "ontap_svm.png"
- "Ontap_SVM_Icon" = "ontap_svm_icon.png"
+ 'Ontap_LOGO' = 'netapp-logo.png'
+ 'AsBuiltReport_LOGO' = 'AsBuiltReport_Logo.png'
+ 'AsBuiltReport_Signature' = 'AsBuiltReport_Signature.png'
+ 'Ontap_Node' = 'ontap_node_new.png'
+ 'Abr_LOGO_Footer' = 'AsBuiltReport.png'
+ 'Ontap_Node_Icon' = 'netapp_node_icon.png'
+ 'Ontap_Aggregate' = 'netapp_aggregate.png'
+ 'Ontap_SVM' = 'ontap_svm.png'
+ 'Ontap_SVM_Icon' = 'ontap_svm_icon.png'
+ 'Ontap_Network_Port' = 'network_port.png'
+ 'Ontap_Management_Network' = 'network-switch.png'
+ 'Ontap_Cluster_Network' = 'ontap_stack_switch.png'
+ 'Ontap_Single_Network' = 'ontap_single_switch.png'
+ 'Ontap_Network_Nic' = 'nic_port.png'
+ 'Ontap_Volume' = 'FlexVol.png'
}
$script:ColumnSize = $Options.DiagramColumnSize
@@ -122,9 +132,9 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
#region Cluster Section
$ClusterDiagram = Get-AbrOntapClusterDiagram
if ($ClusterDiagram) {
- Export-AbrOntapDiagram -DiagramObject $ClusterDiagram -MainDiagramLabel "$($ClusterInfo.ClusterName) Cluster Diagram" -FileName "AsBuiltReport.NetApp.Ontap.Cluster"
+ Export-AbrOntapDiagram -DiagramObject $ClusterDiagram -MainDiagramLabel "$($ClusterInfo.ClusterName) Cluster Diagram" -FileName 'AsBuiltReport.NetApp.Ontap.Cluster'
} else {
- Write-PScriboMessage -IsWarning "Unable to generate the Cluster Diagram."
+ Write-PScriboMessage -IsWarning 'Unable to generate the Cluster Diagram.'
}
Write-PScriboMessage "Cluster InfoLevel set at $($InfoLevel.Cluster)."
if ($InfoLevel.Cluster -gt 0) {
@@ -146,23 +156,21 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
Write-PScriboMessage "Node InfoLevel set at $($InfoLevel.Node)."
if ($InfoLevel.Node -gt 0) {
- Section -Style Heading2 'Node Information' {
- Paragraph "The following section provides a summary of the Node in $($ClusterInfo.ClusterName)."
+ Section -Style Heading2 'Nodes' {
+ Paragraph "The following section provides detailed information of nodes in cluster $($ClusterInfo.ClusterName)."
BlankLine
- Section -Style Heading3 'Node Inventory' {
- Paragraph "The following section provides the node inventory in $($ClusterInfo.ClusterName)."
- BlankLine
+ Section -Style Heading3 'Inventory' {
Get-AbrOntapNode
- Section -Style Heading4 'Node Vol0 Inventory' {
+ Section -Style Heading4 'Root Volume Vol0' {
Get-AbrOntapNodeStorage
}
if ($InfoLevel.Node -ge 2) {
- Section -Style Heading4 'Node Hardware Inventory' {
+ Section -Style Heading4 'Hardware Details' {
Get-AbrOntapNodesHW
}
}
- if (Get-NcServiceProcessor -Controller $Array | Where-Object { $NULL -ne $_.IpAddress -and $NULL -ne $_.MacAddress }) {
- Section -Style Heading4 'Node Service-Processor Inventory' {
+ if (Get-NcServiceProcessor -Controller $Array) {
+ Section -Style Heading4 'Service-Processor' {
Get-AbrOntapNodesSP
}
}
@@ -176,20 +184,18 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
Write-PScriboMessage "Storage InfoLevel set at $($InfoLevel.Node)."
if ($InfoLevel.Storage -gt 0) {
Section -Style Heading2 'Storage Information' {
- Paragraph "The following section provides a summary of the storage hardware in $($ClusterInfo.ClusterName)."
+ Paragraph "The following section provides detailed information about the storage configuration for cluster $($ClusterInfo.ClusterName)."
BlankLine
- Section -Style Heading3 'Aggregate Inventory' {
- Paragraph "The following section provides the Aggregates in $($ClusterInfo.ClusterName)."
- BlankLine
+ Section -Style Heading3 'Aggregates (Local Tiers)' {
if (Get-NcAggr -Controller $Array) {
+ Get-AbrOntapStorageAGGR
$StorageAggrDiagram = Get-AbrOntapStorageAggrDiagram
if ($StorageAggrDiagram) {
- Export-AbrOntapDiagram -DiagramObject $StorageAggrDiagram -MainDiagramLabel "Storage Aggregate Diagram" -FileName "AsBuiltReport.NetApp.Ontap.StorageAggr"
+ Export-AbrOntapDiagram -DiagramObject $StorageAggrDiagram -MainDiagramLabel 'Aggregate Diagram' -FileName 'AsBuiltReport.NetApp.Ontap.Aggregate'
BlankLine
} else {
- Write-PScriboMessage -IsWarning "Unable to generate the Storage Aggregate Diagram."
+ Write-PScriboMessage -IsWarning 'Unable to generate the Aggregate Diagram.'
}
- Get-AbrOntapStorageAGGR
}
if (Get-NcAggrObjectStore -Controller $Array -Aggregate (Get-NcAggr -Controller $Array).Name) {
Section -Style Heading4 'FabricPool' {
@@ -204,36 +210,45 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
}
}
}
- Section -Style Heading3 'Disk Information' {
- Paragraph "The following section provides the disk summary information in controller $($ClusterInfo.ClusterName)."
- BlankLine
- Section -Style Heading4 'Per Node Disk Assignment' {
- Paragraph "The following section provides the number of disks assigned to each controller in $($ClusterInfo.ClusterName)."
+ if ($InfoLevel.Storage -gt 0) {
+ Section -Style Heading3 'Disks' {
+ Paragraph "The following section provides a comprehensive summary of disk inventory and configuration across all controllers in the $($ClusterInfo.ClusterName) cluster."
BlankLine
- Get-AbrOntapDiskAssign
- }
- $Nodes = Get-NcNode -Controller $Array
- foreach ($Node in $Nodes) {
- Section -Style Heading4 "Disk Owned by Node $Node" {
- Get-AbrOntapDiskOwner -Node $Node
+ Section -Style Heading4 'Per Node Disk Assignment' {
+ Get-AbrOntapDiskAssign
+ $Nodes = Get-NcNode -Controller $Array
+ foreach ($Node in $Nodes) {
+ try {
+ Section -ExcludeFromTOC -Style NOTOCHeading5 $Node {
+ Get-AbrOntapDiskOwner -Node $Node
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
+ }
+ }
}
- }
- Section -Style Heading4 'Disk Container Type' {
- Get-AbrOntapDiskType
- }
- if (Get-NcDisk -Controller $Array | Where-Object { $_.DiskRaidInfo.ContainerType -eq "broken" }) {
- Section -Style Heading4 'Failed Disk' {
- Get-AbrOntapDiskBroken
+ Section -Style Heading4 'Disk Container Type' {
+ Get-AbrOntapDiskType
}
- }
- if (Get-NcNode -Controller $Array | Select-Object Node | Get-NcShelf -Controller $Array -ErrorAction SilentlyContinue) {
- Section -Style Heading3 'Shelf Inventory' {
- Get-AbrOntapDiskShelf
+ if (Get-NcDisk -Controller $Array | Where-Object { $_.DiskRaidInfo.ContainerType -eq 'broken' }) {
+ Section -Style Heading4 'Failed Disk' {
+ Get-AbrOntapDiskBroken
+ }
}
- }
- if ($InfoLevel.Storage -ge 2) {
- Section -Style Heading4 'Disk Inventory' {
- Get-AbrOntapDiskInv
+ if (Get-NcNode -Controller $Array | Select-Object Node | Get-NcShelf -Controller $Array -ErrorAction SilentlyContinue) {
+ Section -Style Heading3 'Storage Shelf' {
+ Get-AbrOntapDiskShelf
+ }
+ }
+ if (Get-NcStorageShelf -Controller $Array -ErrorAction SilentlyContinue) {
+ Section -Style Heading3 ' Disk Shelf' {
+ Get-AbrOntapDiskShelfStorage
+ }
+ }
+ if (Get-NcDisk -Controller $Array) {
+ Section -Style Heading4 'Disk Inventory' {
+ Get-AbrOntapDiskInv
+ }
}
}
}
@@ -264,6 +279,13 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
#---------------------------------------------------------------------------------------------#
Write-PScriboMessage "Network InfoLevel set at $($InfoLevel.Network)."
if ($InfoLevel.Network -gt 0) {
+ $NetworkDiagram = Get-AbrOntapNodeNetworkDiagram
+ if ($NetworkDiagram) {
+ Export-AbrOntapDiagram -DiagramObject $NetworkDiagram -MainDiagramLabel 'Networking Diagram' -FileName 'AsBuiltReport.NetApp.Ontap.Networking'
+ BlankLine
+ } else {
+ Write-PScriboMessage -IsWarning 'Unable to generate the Networking Diagram.'
+ }
Section -Style Heading2 'Network Information' {
Paragraph "The following section provides a summary of the networking features in $($ClusterInfo.ClusterName)."
BlankLine
@@ -276,8 +298,12 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
BlankLine
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
- Section -Style Heading5 "$Node Ports" {
- Get-AbrOntapNetworkPort -Node $Node
+ try {
+ Section -Style Heading5 "$Node Ports" {
+ Get-AbrOntapNetworkPort -Node $Node
+ }
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
@@ -287,10 +313,14 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
BlankLine
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
- if (Get-NcNetPortIfgrp -Node $Node -Controller $Array) {
- Section -Style Heading4 "$Node IFGRP" {
- Get-AbrOntapNetworkIfgrp -Node $Node
+ try {
+ if (Get-NcNetPortIfgrp -Node $Node -Controller $Array) {
+ Section -Style Heading4 "$Node IFGRP" {
+ Get-AbrOntapNetworkIfgrp -Node $Node
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
@@ -301,16 +331,20 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
BlankLine
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
- if (Get-NcNetPortVlan -Node $Node -Controller $Array) {
- Section -Style Heading4 "$Node Vlans" {
- Get-AbrOntapNetworkVlan -Node $Node
+ try {
+ if (Get-NcNetPortVlan -Node $Node -Controller $Array) {
+ Section -Style Heading4 "$Node Vlans" {
+ Get-AbrOntapNetworkVlan -Node $Node
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
}
- Section -Style Heading4 'Broadcast Domain' {
- Get-AbrOntapNetworkBdomain
+ Section -Style Heading4 'Broadcast Domains' {
+ Get-AbrOntapNetworkBroadcastDomain
}
Section -Style Heading4 'Failover Groups' {
Get-AbrOntapNetworkFailoverGroup
@@ -320,19 +354,23 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
Get-AbrOntapNetworkSubnet
}
}
- $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -ne "node" -and $_.VserverType -ne "system" -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
+ $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -ne 'node' -and $_.VserverType -ne 'system' -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
foreach ($SVM in $Vservers) {
- if (Get-NcNetRoute -VserverContext $SVM -Controller $Array) {
- Section -Style Heading4 "$SVM Vserver Routes" {
- Paragraph "The following section provides the Routes information in $($ClusterInfo.ClusterName)."
- BlankLine
- Get-AbrOntapNetworkRoute -Vserver $SVM
- if ($InfoLevel.Network -ge 2) {
- Section -Style Heading5 "Network Interface Routes" {
- Get-AbrOntapNetworkRouteLif -Vserver $SVM
+ try {
+ if (Get-NcNetRoute -VserverContext $SVM -Controller $Array) {
+ Section -Style Heading4 "$SVM Vserver Routes" {
+ Paragraph "The following section provides the Routes information in $($ClusterInfo.ClusterName)."
+ BlankLine
+ Get-AbrOntapNetworkRoute -Vserver $SVM
+ if ($InfoLevel.Network -ge 2) {
+ Section -Style Heading5 'Network Interface Routes' {
+ Get-AbrOntapNetworkRouteLif -Vserver $SVM
+ }
}
}
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
Section -Style Heading4 'Network Interfaces' {
@@ -349,287 +387,327 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
#---------------------------------------------------------------------------------------------#
Write-PScriboMessage "Vserver InfoLevel set at $($InfoLevel.Vserver)."
if ($InfoLevel.Vserver -gt 0) {
- if (Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq "data" }) {
+ if (Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq 'data' }) {
Section -Style Heading2 'Vserver Information' {
Paragraph "The following section provides a summary of the vserver information in $($ClusterInfo.ClusterName)."
BlankLine
- $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq "data" -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
+ $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
foreach ($SVM in $Vservers) {
- Section -Style Heading3 "$SVM Vserver Configuration" {
- Paragraph "The following section provides the configuration of the vserver $($SVM)."
- BlankLine
- Get-AbrOntapVserverSummary -Vserver $SVM
- if ($InfoLevel.Vserver -ge 2) {
- if (Get-NcVol -Controller $Array | Select-Object -ExpandProperty VolumeQosAttributes) {
- Section -Style Heading4 'Volumes QoS Policy' {
- Paragraph "The following section provides the Vserver QoS Configuration in $($ClusterInfo.ClusterName)."
- Section -Style Heading5 'Volumes Fixed QoS Policy' {
- Get-AbrOntapVserverVolumesQosGPFixed
- }
- Section -Style Heading5 'Volumes Adaptive QoS Policy' {
- Get-AbrOntapVserverVolumesQosGPAdaptive
- }
- }
+ try {
+ Section -Style Heading3 "$SVM Vserver Configuration" {
+ Paragraph "The following section provides the configuration of the vserver $($SVM)."
+ BlankLine
+ $VserverDiagram = Get-AbrOntapVserverDiagram -Vserver $SVM
+ if ($VserverDiagram) {
+ Export-AbrOntapDiagram -DiagramObject $VserverDiagram -MainDiagramLabel "$SVM Vserver Diagram" -FileName "AsBuiltReport.NetApp.Ontap.Vserver.$SVM"
+ } else {
+ Write-PScriboMessage -IsWarning "Unable to generate the $SVM Vserver Diagram."
}
- }
- if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }) {
- Section -Style Heading4 "Storage Volumes" {
- Get-AbrOntapVserverVolume -Vserver $SVM
- if ($InfoLevel.Vserver -ge 2) {
- if (Get-NcVol -VserverContext $SVM -Controller $Array | Select-Object -ExpandProperty VolumeQosAttributes) {
- Section -Style Heading5 "Per Volumes QoS Policy" {
- Get-AbrOntapVserverVolumesQosSetting -Vserver $SVM
- }
- }
- }
- if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsFlexgroup -eq "True" }) {
- Section -Style Heading4 "FlexGroup Volumes" {
- Get-AbrOntapVserverVolumesFlexgroup -Vserver $SVM
- }
- }
- if (Get-NcVolClone -VserverContext $SVM -Controller $Array) {
- Section -Style Heading4 "Flexclone Volumes" {
- Get-AbrOntapVserverVolumesFlexclone -Vserver $SVM
- }
- }
- if ((Get-NcFlexcacheConnectedCache -VserverContext $SVM -Controller $Array) -or ((Get-NcFlexcache -Controller $Array).CacheVolume).count -gt 0) {
- Section -Style Heading4 "Flexcache Volumes" {
- Get-AbrOntapVserverVolumesFlexcache -Vserver $SVM
- }
+ Get-AbrOntapVserverSummary -Vserver $SVM
+
+ if (Get-NcNetInterface -Controller $Array | Where-Object { $_.Role -eq 'data' -and $_.Vserver -notin $options.Exclude.Vserver -and $_.Vserver -eq $SVM }) {
+ Section -Style Heading4 'Interfaces (Lifs)' {
+ Get-AbrOntapVserverNetworkInterface -Vserver $SVM
}
}
- if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' } | Get-NcSnapshot -Controller $Array) {
- Section -Style Heading4 "Volumes Snapshot Configuration" {
- Get-AbrOntapVserverVolumeSnapshot -Vserver $SVM
- if ($HealthCheck.Vserver.Snapshot) {
- Get-AbrOntapVserverVolumeSnapshotHealth -Vserver $SVM
+
+ if ($InfoLevel.Vserver -ge 2) {
+ if (Get-NcVol -Controller $Array | Select-Object -ExpandProperty VolumeQosAttributes) {
+ Section -Style Heading4 'Volumes QoS Policy' {
+ Paragraph "The following section provides the Vserver QoS Configuration in $($ClusterInfo.ClusterName)."
+ Section -Style Heading5 'Volumes Fixed QoS Policy' {
+ Get-AbrOntapVserverVolumesQosGPFixed
+ }
+ Section -Style Heading5 'Volumes Adaptive QoS Policy' {
+ Get-AbrOntapVserverVolumesQosGPAdaptive
+ }
}
}
}
if (Get-NcExportRule -VserverContext $SVM -Controller $Array) {
- Section -Style Heading4 "Export Policy" {
- Get-AbrOntapVserverVolumesExportPolicy -Vserver $SVM
- }
- }
- if (Get-NcQtree -VserverContext $SVM -Controller $Array | Where-Object { $NULL -ne $_.Qtree }) {
- Section -Style Heading4 "Qtrees" {
- Get-AbrOntapVserverVolumesQtree -Vserver $SVM
+ Section -Style Heading4 'Export Policies' {
+ Get-AbrOntapVserverExportPolicy -Vserver $SVM
}
}
- if (Get-NcQuota -VserverContext $SVM -Controller $Array) {
- Section -Style Heading4 "Volume Quota" {
- Get-AbrOntapVserverVolumesQuota -Vserver $SVM
- }
- }
- }
- Section -Style Heading4 "Protocol Information" {
- Paragraph "The following section provides a summary of the Vserver protocol information in $($SVM)."
- BlankLine
- #---------------------------------------------------------------------------------------------#
- # NFS Section #
- #---------------------------------------------------------------------------------------------#
- if (Get-NcNfsService -VserverContext $SVM -Controller $Array) {
- Section -Style Heading5 "NFS Services" {
- Paragraph "The following section provides the NFS Service Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverNFSSummary -Vserver $SVM
- if ($InfoLevel.Vserver -ge 2) {
- Section -ExcludeFromTOC -Style Heading6 "NFS Options" {
- Get-AbrOntapVserverNFSOption -Vserver $SVM
- }
- }
- if (Get-NcVserver -VserverContext $SVM -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.AllowedProtocols -eq 'nfs' -and $_.State -eq 'running' } | Get-NcNfsExport) {
- Section -ExcludeFromTOC -Style Heading6 "NFS Volume Export" {
- Get-AbrOntapVserverNFSExport -Vserver $SVM
+ if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' }) {
+ Section -Style Heading4 'Storage Volumes' {
+ Get-AbrOntapVserverVolume -Vserver $SVM
+ if ((Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' } | Select-Object -ExpandProperty VolumeExportAttributes) ) {
+ Section -Style Heading5 'Per Volumes Export Policies' {
+ Get-AbrOntapVserverVolumesExportPolicy -Vserver $SVM
}
}
- }
- }
- #---------------------------------------------------------------------------------------------#
- # CIFS Section #
- #---------------------------------------------------------------------------------------------#
- if (Get-NcVserver -VserverContext $SVM -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.AllowedProtocols -eq 'cifs' -and $_.State -eq 'running' } | Get-NcCifsServerStatus -Controller $Array -ErrorAction SilentlyContinue) {
- Section -Style Heading5 "CIFS Services Information" {
- Paragraph "The following section provides the CIFS Service Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverCIFSSummary -Vserver $SVM
if ($InfoLevel.Vserver -ge 2) {
- Section -ExcludeFromTOC -Style Heading6 'CIFS Service Configuration' {
- Get-AbrOntapVserverCIFSSecurity -Vserver $SVM
+ if (Get-NcVol -VserverContext $SVM -Controller $Array | Select-Object -ExpandProperty VolumeQosAttributes) {
+ Section -Style Heading5 'Per Volumes QoS Policies' {
+ Get-AbrOntapVserverVolumesQosSetting -Vserver $SVM
+ }
+ }
+ Section -Style Heading5 'Per Volumes Space Attributes' {
+ Get-AbrOntapVserverVolumesSpaceAttr -Vserver $SVM
+ }
+ Section -Style Heading5 'Per Volumes Autosize Attributes' {
+ Get-AbrOntapVserverVolumesAutosize -Vserver $SVM
+ }
+ Section -Style Heading5 'Per Volumes Inode Attributes' {
+ Get-AbrOntapVserverVolumesInodeAttr -Vserver $SVM
}
- Section -ExcludeFromTOC -Style Heading6 'CIFS Domain Controller' {
- Get-AbrOntapVserverCIFSDC -Vserver $SVM
+ Section -Style Heading5 'Per Volumes Language Attributes' {
+ Get-AbrOntapVserverVolumesLanguage -Vserver $SVM
}
}
- Section -ExcludeFromTOC -Style Heading6 'CIFS Local Group' {
- Get-AbrOntapVserverCIFSLocalGroup -Vserver $SVM
+ if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' -and $_.VolumeStateAttributes.IsFlexgroup -eq 'True' }) {
+ Section -Style Heading4 'FlexGroup Volumes' {
+ Get-AbrOntapVserverVolumesFlexgroup -Vserver $SVM
+ }
}
- Section -ExcludeFromTOC -Style Heading6 'CIFS Local Group Members' {
- Get-AbrOntapVserverCIFSLGMember -Vserver $SVM
+ if (Get-NcVolClone -VserverContext $SVM -Controller $Array) {
+ Section -Style Heading4 'Flexclone Volumes' {
+ Get-AbrOntapVserverVolumesFlexclone -Vserver $SVM
+ }
}
- if ($InfoLevel.Vserver -ge 2) {
- Section -ExcludeFromTOC -Style Heading6 'CIFS Options' {
- Get-AbrOntapVserverCIFSOption -Vserver $SVM
+ if ((Get-NcFlexcacheConnectedCache -VserverContext $SVM -Controller $Array) -or ((Get-NcFlexcache -Controller $Array).CacheVolume).count -gt 0) {
+ Section -Style Heading4 'Flexcache Volumes' {
+ Get-AbrOntapVserverVolumesFlexcache -Vserver $SVM
}
}
- Section -ExcludeFromTOC -Style Heading6 'CIFS Share' {
- Get-AbrOntapVserverCIFSShare -Vserver $SVM
+ }
+ if (Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { $_.JunctionPath -ne '/' -and $_.Name -ne 'vol0' } | Get-NcSnapshot -Controller $Array) {
+ Section -Style Heading4 'Volumes Snapshot Configuration' {
+ Get-AbrOntapVserverVolumeSnapshot -Vserver $SVM
+ if ($HealthCheck.Vserver.Snapshot) {
+ Get-AbrOntapVserverVolumeSnapshotHealth -Vserver $SVM
+ }
}
- Section -ExcludeFromTOC -Style Heading6 'CIFS Share Configuration' {
- Get-AbrOntapVserverCIFSShareProp -Vserver $SVM
+ }
+ if (Get-NcQtree -VserverContext $SVM -Controller $Array | Where-Object { $NULL -ne $_.Qtree }) {
+ Section -Style Heading4 'Qtrees' {
+ Get-AbrOntapVserverVolumesQtree -Vserver $SVM
}
- if ($InfoLevel.Vserver -ge 2) {
- if (Get-NcCifsSession -VserverContext $SVM -Controller $Array) {
- Section -ExcludeFromTOC -Style Heading6 'CIFS Sessions' {
- Get-AbrOntapVserverCIFSSession -Vserver $SVM
- }
- }
+ }
+ if (Get-NcQuota -VserverContext $SVM -Controller $Array) {
+ Section -Style Heading4 'Volume Quota' {
+ Get-AbrOntapVserverVolumesQuota -Vserver $SVM
}
}
}
- #---------------------------------------------------------------------------------------------#
- # NVME Section #
- #---------------------------------------------------------------------------------------------#
- if ( Get-NcNvme -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
- Section -Style Heading5 'Nvme Services Information' {
- Paragraph "The following section provides the Nvme Service Information in $($SVM)."
- BlankLine
- # Get-AbrOntapVserverNvmeSummary -Vserver $SVM
- if (Get-NcNvmeInterface -VserverContext $Vserver -Controller $Array | Where-Object { $_.PhysicalProtocol -eq 'fibre_channel' }) {
- Section -ExcludeFromTOC -Style Heading6 'Nvme FC Physical Adapter' {
- Get-AbrOntapVserverNvmeFcAdapter -Vserver $SVM
+ Section -Style Heading4 'Protocol Information' {
+ Paragraph "The following section provides a summary of the Vserver protocol information in $($SVM)."
+ BlankLine
+ #---------------------------------------------------------------------------------------------#
+ # NFS Section #
+ #---------------------------------------------------------------------------------------------#
+ if (Get-NcNfsService -VserverContext $SVM -Controller $Array) {
+ Section -Style Heading5 'NFS Services' {
+ Paragraph "The following section provides the NFS Service Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverNFSSummary -Vserver $SVM
+ if ($InfoLevel.Vserver -ge 2) {
+ Section -ExcludeFromTOC -Style Heading6 'NFS Options' {
+ Get-AbrOntapVserverNFSOption -Vserver $SVM
+ }
}
- }
- if (Get-NcNvmeInterface -VserverContext $Vserver -Controller $Array | Where-Object { $_.PhysicalProtocol -eq 'ethernet' }) {
- Section -ExcludeFromTOC -Style Heading6 'Nvme TCP Physical Adapter' {
- Get-AbrOntapVserverNvmeTcpAdapter -Vserver $SVM
+ if (Get-NcVserver -VserverContext $SVM -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.AllowedProtocols -eq 'nfs' -and $_.State -eq 'running' } | Get-NcNfsExport) {
+ Section -ExcludeFromTOC -Style Heading6 'NFS Volume Export' {
+ Get-AbrOntapVserverNFSExport -Vserver $SVM
+ }
}
}
- Section -ExcludeFromTOC -Style Heading6 'NVME Interfaces' {
- Get-AbrOntapVserverNvmeInterface -Vserver $SVM
+ }
+ #---------------------------------------------------------------------------------------------#
+ # CIFS Section #
+ #---------------------------------------------------------------------------------------------#
+ if (Get-NcVserver -VserverContext $SVM -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.AllowedProtocols -eq 'cifs' -and $_.State -eq 'running' } | Get-NcCifsServerStatus -Controller $Array -ErrorAction SilentlyContinue) {
+ Section -Style Heading5 'CIFS Services Information' {
+ Paragraph "The following section provides the CIFS Service Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverCIFSSummary -Vserver $SVM
+ if ($InfoLevel.Vserver -ge 2) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Service Configuration' {
+ Get-AbrOntapVserverCIFSSecurity -Vserver $SVM
+ }
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Domain Controller' {
+ Get-AbrOntapVserverCIFSDC -Vserver $SVM
+ }
+ }
+ if (Get-NcCifsLocalGroup -VserverContext $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Local Group' {
+ Get-AbrOntapVserverCIFSLocalGroup -Vserver $SVM
+ }
+ }
+ if (Get-NcCifsLocalGroupMember -VserverContext $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Local Group Members' {
+ Get-AbrOntapVserverCIFSLGMember -Vserver $SVM
+ }
+ }
+ if ($InfoLevel.Vserver -ge 2) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Options' {
+ Get-AbrOntapVserverCIFSOption -Vserver $SVM
+ }
+ }
+ if (Get-NcCifsShare -VserverContext $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Share' {
+ Get-AbrOntapVserverCIFSShare -Vserver $SVM
+ }
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Share Configuration' {
+ Get-AbrOntapVserverCIFSShareProp -Vserver $SVM
+ }
+ }
+ if ($InfoLevel.Vserver -ge 2) {
+ if (Get-NcCifsSession -VserverContext $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'CIFS Sessions' {
+ Get-AbrOntapVserverCIFSSession -Vserver $SVM
+ }
+ }
+ }
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # ISCSI Section #
- #---------------------------------------------------------------------------------------------#
- if ( Get-NcIscsiService -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
- Section -Style Heading5 "ISCSI Services" {
- Paragraph "The following section provides the ISCSI Service Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverIscsiSummary -Vserver $SVM
- Section -ExcludeFromTOC -Style Heading6 "ISCSI Interfaces" {
- Get-AbrOntapVserverIscsiInterface -Vserver $SVM
+ #---------------------------------------------------------------------------------------------#
+ # NVME Section #
+ #---------------------------------------------------------------------------------------------#
+ if ( Get-NcNvme -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
+ Section -Style Heading5 'Nvme Services Information' {
+ Paragraph "The following section provides the Nvme Service Information in $($SVM)."
+ BlankLine
+ # Get-AbrOntapVserverNvmeSummary -Vserver $SVM
+ if (Get-NcNvmeInterface -VserverContext $Vserver -Controller $Array | Where-Object { $_.PhysicalProtocol -eq 'fibre_channel' }) {
+ Section -ExcludeFromTOC -Style Heading6 'Nvme FC Physical Adapter' {
+ Get-AbrOntapVserverNvmeFcAdapter -Vserver $SVM
+ }
+ }
+ if (Get-NcNvmeInterface -VserverContext $Vserver -Controller $Array | Where-Object { $_.PhysicalProtocol -eq 'ethernet' }) {
+ Section -ExcludeFromTOC -Style Heading6 'Nvme TCP Physical Adapter' {
+ Get-AbrOntapVserverNvmeTcpAdapter -Vserver $SVM
+ }
+ }
+ Section -ExcludeFromTOC -Style Heading6 'NVME Interfaces' {
+ Get-AbrOntapVserverNvmeInterface -Vserver $SVM
+ }
}
+ }
+ #---------------------------------------------------------------------------------------------#
+ # ISCSI Section #
+ #---------------------------------------------------------------------------------------------#
+ if ( Get-NcIscsiService -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
+ Section -Style Heading5 'ISCSI Services' {
+ Paragraph "The following section provides the ISCSI Service Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverIscsiSummary -Vserver $SVM
+ Section -ExcludeFromTOC -Style Heading6 'ISCSI Interfaces' {
+ Get-AbrOntapVserverIscsiInterface -Vserver $SVM
+ }
- $ISCSIClientInitiators = Get-AbrOntapVserverIscsiInitiator -Vserver $SVM
- if ($ISCSIClientInitiators) {
- Section -ExcludeFromTOC -Style Heading6 "ISCSI Client Initiators" {
- $ISCSIClientInitiators
+ $ISCSIClientInitiators = Get-AbrOntapVserverIscsiInitiator -Vserver $SVM
+ if ($ISCSIClientInitiators) {
+ Section -ExcludeFromTOC -Style Heading6 'ISCSI Client Initiators' {
+ $ISCSIClientInitiators
+ }
}
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # FCP Section #
- #---------------------------------------------------------------------------------------------#
- if ( Get-NcFcpService -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
- Section -Style Heading5 'FCP Services Information' {
- Paragraph "The following section provides the FCP Service Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverFcpSummary -Vserver $SVM
- Section -ExcludeFromTOC -Style Heading6 'FCP Physical Adapter' {
- Get-AbrOntapVserverFcpAdapter
- }
- Section -ExcludeFromTOC -Style Heading6 'FCP Interfaces' {
- Get-AbrOntapVserverFcpInterface -Vserver $SVM
+ #---------------------------------------------------------------------------------------------#
+ # FCP Section #
+ #---------------------------------------------------------------------------------------------#
+ if ( Get-NcFcpService -Controller $Array | Where-Object { $_.Vserver -eq $SVM } ) {
+ Section -Style Heading5 'FCP Services Information' {
+ Paragraph "The following section provides the FCP Service Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverFcpSummary -Vserver $SVM
+ Section -ExcludeFromTOC -Style Heading6 'FCP Physical Adapter' {
+ Get-AbrOntapVserverFcpAdapter
+ }
+ Section -ExcludeFromTOC -Style Heading6 'FCP Interfaces' {
+ Get-AbrOntapVserverFcpInterface -Vserver $SVM
+ }
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # Lun Storage Section #
- #---------------------------------------------------------------------------------------------#
- if (Get-NcLun -Controller $Array | Where-Object { $_.Vserver -eq $SVM }) {
- Section -Style Heading5 'Lun Storage' {
- Paragraph "The following section provides the Lun Storage Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverLunStorage -Vserver $SVM
- if (Get-NcIgroup -Vserver $SVM -Controller $Array) {
- Section -ExcludeFromTOC -Style Heading6 'Igroup Mapping' {
- Get-AbrOntapVserverLunIgroup -Vserver $SVM
+ #---------------------------------------------------------------------------------------------#
+ # Lun Storage Section #
+ #---------------------------------------------------------------------------------------------#
+ if (Get-NcLun -Controller $Array | Where-Object { $_.Vserver -eq $SVM }) {
+ Section -Style Heading5 'Lun Storage' {
+ Paragraph "The following section provides the Lun Storage Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverLunStorage -Vserver $SVM
+ if (Get-NcIgroup -Vserver $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'Igroup Mapping' {
+ Get-AbrOntapVserverLunIgroup -Vserver $SVM
+ }
}
- }
- $NonMappedLun = Get-AbrOntapVserverNonMappedLun -Vserver $SVM
- if ($Healthcheck.Vserver.Status -and $NonMappedLun) {
- Section -ExcludeFromTOC -Style Heading6 'HealthCheck - Non-Mapped Lun Information' {
- Paragraph "The following section provides information of Non Mapped Lun in $($SVM)."
- BlankLine
- $NonMappedLun
+ $NonMappedLun = Get-AbrOntapVserverNonMappedLun -Vserver $SVM
+ if ($Healthcheck.Vserver.Status -and $NonMappedLun) {
+ Section -ExcludeFromTOC -Style Heading6 'HealthCheck - Non-Mapped Lun Information' {
+ Paragraph "The following section provides information of Non Mapped Lun in $($SVM)."
+ BlankLine
+ $NonMappedLun
+ }
}
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # NameSpace & Subsystem Storage Section #
- #---------------------------------------------------------------------------------------------#
- if (Get-NcNvmeNamespace -Controller $Array | Where-Object { $_.Vserver -eq $SVM }) {
- Section -Style Heading5 'Namespace Storage' {
- Paragraph "The following section provides the Namespace Storage Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverNamespaceStorage -Vserver $SVM
- if (Get-NcNvmeSubsystem -Vserver $SVM -Controller $Array) {
- Section -ExcludeFromTOC -Style Heading6 'Subsystem Mapping' {
- Get-AbrOntapVserverSubsystem -Vserver $SVM
+ #---------------------------------------------------------------------------------------------#
+ # NameSpace & Subsystem Storage Section #
+ #---------------------------------------------------------------------------------------------#
+ if (Get-NcNvmeNamespace -Controller $Array | Where-Object { $_.Vserver -eq $SVM }) {
+ Section -Style Heading5 'Namespace Storage' {
+ Paragraph "The following section provides the Namespace Storage Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverNamespaceStorage -Vserver $SVM
+ if (Get-NcNvmeSubsystem -Vserver $SVM -Controller $Array) {
+ Section -ExcludeFromTOC -Style Heading6 'Subsystem Mapping' {
+ Get-AbrOntapVserverSubsystem -Vserver $SVM
+ }
}
- }
- $NonMappedNamespace = Get-AbrOntapVserverNonMappedNamespace -Vserver $SVM
- if ($Healthcheck.Vserver.Status -and $NonMappedNamespace) {
- Section -ExcludeFromTOC -Style Heading6 'HealthCheck - Non-Mapped Namespace Information' {
- Paragraph "The following table provides information about Non Mapped Namespace in $($SVM)."
- BlankLine
- $NonMappedNamespace
+ $NonMappedNamespace = Get-AbrOntapVserverNonMappedNamespace -Vserver $SVM
+ if ($Healthcheck.Vserver.Status -and $NonMappedNamespace) {
+ Section -ExcludeFromTOC -Style Heading6 'HealthCheck - Non-Mapped Namespace Information' {
+ Paragraph "The following table provides information about Non Mapped Namespace in $($SVM)."
+ BlankLine
+ $NonMappedNamespace
+ }
}
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # Consistency Groups Section #
- #---------------------------------------------------------------------------------------------#
- $CGs = Get-NetAppOntapAPI -uri "/api/application/consistency-groups?svm=$SVM&fields=**&return_records=true&return_timeout=15"
- if ($CGs) {
- Section -Style Heading5 'Consistency Groups' {
- Paragraph "The following section provides Consistency Group Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverCGSummary -Vserver $SVM
- foreach ($CG in $CGs) {
- if ($CG.luns) {
- Section -ExcludeFromTOC -Style Heading6 "$($CG.name) Luns" {
- Get-AbrOntapVserverCGLun -CGObj $CG
+ #---------------------------------------------------------------------------------------------#
+ # Consistency Groups Section #
+ #---------------------------------------------------------------------------------------------#
+ $CGs = Get-NetAppOntapAPI -uri "/api/application/consistency-groups?svm=$SVM&fields=**&return_records=true&return_timeout=15"
+ if ($CGs) {
+ Section -Style Heading5 'Consistency Groups' {
+ Paragraph "The following section provides Consistency Group Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverCGSummary -Vserver $SVM
+ foreach ($CG in $CGs) {
+ if ($CG.luns) {
+ Section -ExcludeFromTOC -Style Heading6 "$($CG.name) Luns" {
+ Get-AbrOntapVserverCGLun -CGObj $CG
+ }
}
- }
- if ($CG.namespaces) {
- Section -ExcludeFromTOC -Style Heading6 "$($CG.name) Namespaces" {
- Get-AbrOntapVserverCGNamespace -CGObj $CG
+ if ($CG.namespaces) {
+ Section -ExcludeFromTOC -Style Heading6 "$($CG.name) Namespaces" {
+ Get-AbrOntapVserverCGNamespace -CGObj $CG
+ }
}
}
}
}
- }
- #---------------------------------------------------------------------------------------------#
- # S3 Section #
- #---------------------------------------------------------------------------------------------#
- $S3Data = Get-NetAppOntapAPI -uri "/api/protocols/s3/services?svm=$SVM&fields=*&return_records=true&return_timeout=15"
- if ($S3Data) {
- Section -Style Heading5 'S3 Services Configuration Information' {
- Paragraph "The following section provides the S3 Service Information in $($SVM)."
- BlankLine
- Get-AbrOntapVserverS3Summary -Vserver $SVM
- Section -ExcludeFromTOC -Style Heading6 'S3 Buckets' {
- Get-AbrOntapVserverS3Bucket -Vserver $SVM
+ #---------------------------------------------------------------------------------------------#
+ # S3 Section #
+ #---------------------------------------------------------------------------------------------#
+ $S3Data = Get-NetAppOntapAPI -uri "/api/protocols/s3/services?svm=$SVM&fields=*&return_records=true&return_timeout=15"
+ if ($S3Data) {
+ Section -Style Heading5 'S3 Services Configuration Information' {
+ Paragraph "The following section provides the S3 Service Information in $($SVM)."
+ BlankLine
+ Get-AbrOntapVserverS3Summary -Vserver $SVM
+ Section -ExcludeFromTOC -Style Heading6 'S3 Buckets' {
+ Get-AbrOntapVserverS3Bucket -Vserver $SVM
+ }
}
}
}
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
@@ -647,9 +725,9 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
BlankLine
$ClusterReplicationDiagram = Get-AbrOntapClusterReplicationDiagram
if ($ClusterReplicationDiagram) {
- Export-AbrOntapDiagram -DiagramObject $ClusterReplicationDiagram -MainDiagramLabel "Cluster Replication Diagram" -FileName "AsBuiltReport.NetApp.Ontap.Replication"
+ Export-AbrOntapDiagram -DiagramObject $ClusterReplicationDiagram -MainDiagramLabel 'Cluster Replication Diagram' -FileName 'AsBuiltReport.NetApp.Ontap.Replication'
} else {
- Write-PScriboMessage -IsWarning "Unable to generate the Cluster Replication Diagram."
+ Write-PScriboMessage -IsWarning 'Unable to generate the Cluster Replication Diagram.'
}
Section -Style Heading3 'Cluster Peer' {
Paragraph "The following section provides the Cluster Peer information in $($ClusterInfo.ClusterName)."
@@ -674,7 +752,7 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
Get-AbrOntapRepDestination
}
}
- if (Get-NetAppOntapAPI -uri "/api/cluster/mediators?") {
+ if (Get-NetAppOntapAPI -uri '/api/cluster/mediators?') {
Section -Style Heading5 'Ontap Mediator' {
Get-AbrOntapRepMediator
}
@@ -688,7 +766,7 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
#---------------------------------------------------------------------------------------------y
Write-PScriboMessage "Efficiency InfoLevel set at $($InfoLevel.Efficiency)."
if ($InfoLevel.Efficiency -gt 0) {
- $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq "data" -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
+ $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq 'data' -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
if (Get-NcAggrEfficiency -Controller $Array) {
Section -Style Heading2 'Efficiency Information' {
Paragraph "The following section provides the Storage Efficiency Saving information in $($ClusterInfo.ClusterName)."
@@ -699,19 +777,23 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
BlankLine
Get-AbrOntapEfficiencyAggr
foreach ($SVM in $Vservers) {
- $VolFilter = Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { ($_.State -eq "online") -and ($_.Name -ne "vol0") }
- if (Get-NcEfficiency -Volume $VolFilter.Name[0] -Vserver $SVM -Controller $Array) {
- Section -Style Heading4 "$SVM Vserver Volume Deduplication" {
- Get-AbrOntapEfficiencyVolSisStatus -Vserver $SVM
- Section -Style Heading5 "Volume Efficiency" {
- Get-AbrOntapEfficiencyVol -Vserver $SVM
- }
- if ($InfoLevel.Efficiency -ge 2) {
- Section -Style Heading5 "Detailed Volume Efficiency" {
- Get-AbrOntapEfficiencyVolDetailed -Vserver $SVM
+ try {
+ $VolFilter = Get-NcVol -VserverContext $SVM -Controller $Array | Where-Object { ($_.State -eq 'online') -and ($_.Name -ne 'vol0') }
+ if ($VolFilter -and (Get-NcEfficiency -Volume $VolFilter.Name[0] -Vserver $SVM -Controller $Array)) {
+ Section -Style Heading4 "$SVM Vserver Volume Deduplication" {
+ Get-AbrOntapEfficiencyVolSisStatus -Vserver $SVM
+ Section -Style Heading5 'Volume Efficiency' {
+ Get-AbrOntapEfficiencyVol -Vserver $SVM
+ }
+ if ($InfoLevel.Efficiency -ge 2) {
+ Section -Style Heading5 'Detailed Volume Efficiency' {
+ Get-AbrOntapEfficiencyVolDetailed -Vserver $SVM
+ }
}
}
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
@@ -724,20 +806,24 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
#---------------------------------------------------------------------------------------------#
Write-PScriboMessage "Security InfoLevel set at $($InfoLevel.Security)."
if ($InfoLevel.Security -gt 0) {
- $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq "data" -or $_.VserverType -eq "admin" -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
+ $Vservers = Get-NcVserver -Controller $Array | Where-Object { $_.VserverType -eq 'data' -or $_.VserverType -eq 'admin' -and $_.Vserver -notin $Options.Exclude.Vserver } | Select-Object -ExpandProperty Vserver
Section -Style Heading2 'Security Information' {
Paragraph "The following section provides the Security related information in $($ClusterInfo.ClusterName)."
BlankLine
foreach ($SVM in $Vservers) {
- if (Get-NcUser -Vserver $SVM -Controller $Array) {
- Section -Style Heading3 "$SVM Vserver Local User" {
- Paragraph "The following section provides the Local User information in $($SVM)."
- BlankLine
- Get-AbrOntapSecurityUser -Vserver $SVM
+ try {
+ if (Get-NcUser -Vserver $SVM -Controller $Array) {
+ Section -Style Heading3 "$SVM Vserver Local User" {
+ Paragraph "The following section provides the Local User information in $($SVM)."
+ BlankLine
+ Get-AbrOntapSecurityUser -Vserver $SVM
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
- $MAPData = Get-NetAppOntapAPI -uri "/api/security/multi-admin-verify/approval-groups?fields=**&return_records=true&return_timeout=15"
+ $MAPData = Get-NetAppOntapAPI -uri '/api/security/multi-admin-verify/approval-groups?fields=**&return_records=true&return_timeout=15'
if ($MAPData) {
Section -Style Heading3 'Multi-Admin Approval Configuration' {
Paragraph "The following section provides information about Multi-Admin Approval from $($ClusterInfo.ClusterName)."
@@ -794,7 +880,7 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
Section -Style Heading5 'Volume Snaplock Type' {
Get-AbrOntapSecuritySnapLockVol
if ($InfoLevel.Security -ge 2) {
- if (Get-NcVol -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in "enterprise", "compliance" }) {
+ if (Get-NcVol -Controller $Array | Where-Object { $_.VolumeSnaplockAttributes.SnaplockType -in 'enterprise', 'compliance' }) {
Section -ExcludeFromTOC -Style Heading6 'Snaplock Volume Attributes' {
Get-AbrOntapSecuritySnapLockVollAttr
}
@@ -841,10 +927,14 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
if ($InfoLevel.System -ge 2) {
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
- if (Get-NcConfigBackup -Node $Node -Controller $Array) {
- Section -Style Heading4 "$Node Configuration" {
- Get-AbrOntapSysConfigBackup -Node $Node
+ try {
+ if (Get-NcConfigBackup -Node $Node -Controller $Array) {
+ Section -Style Heading4 "$Node Configuration" {
+ Get-AbrOntapSysConfigBackup -Node $Node
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
@@ -858,10 +948,14 @@ function Invoke-AsBuiltReport.NetApp.ONTAP {
if ($InfoLevel.System -ge 2) {
$Nodes = Get-NcNode -Controller $Array
foreach ($Node in $Nodes) {
- if ($HealthCheck.System.EMS -and (Get-NcEmsMessage -Node $Node -Severity "emergency", "alert" -Controller $Array | Select-Object -First 30)) {
- Section -Style Heading4 "$Node Emergency and Alert Messages" {
- Get-AbrOntapSysConfigEMS -Node $Node
+ try {
+ if ($HealthCheck.System.EMS -and (Get-NcEmsMessage -Node $Node -Severity 'emergency', 'alert' -Controller $Array | Select-Object -First 30)) {
+ Section -Style Heading4 "$Node Emergency and Alert Messages" {
+ Get-AbrOntapSysConfigEMS -Node $Node
+ }
}
+ } catch {
+ Write-PScriboMessage -IsWarning $_.Exception.Message
}
}
}
diff --git a/icons/AsBuiltReport_Logo.png b/AsBuiltReport.NetApp.ONTAP/icons/AsBuiltReport_Logo.png
similarity index 100%
rename from icons/AsBuiltReport_Logo.png
rename to AsBuiltReport.NetApp.ONTAP/icons/AsBuiltReport_Logo.png
diff --git a/icons/AsBuiltReport_Signature.png b/AsBuiltReport.NetApp.ONTAP/icons/AsBuiltReport_Signature.png
similarity index 100%
rename from icons/AsBuiltReport_Signature.png
rename to AsBuiltReport.NetApp.ONTAP/icons/AsBuiltReport_Signature.png
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/Disk.png b/AsBuiltReport.NetApp.ONTAP/icons/Disk.png
new file mode 100644
index 0000000..4cb66ea
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/Disk.png differ
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/FlexVol.png b/AsBuiltReport.NetApp.ONTAP/icons/FlexVol.png
new file mode 100644
index 0000000..3fd51a5
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/FlexVol.png differ
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/RaidGroup.png b/AsBuiltReport.NetApp.ONTAP/icons/RaidGroup.png
new file mode 100644
index 0000000..027a3b1
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/RaidGroup.png differ
diff --git a/icons/netapp-logo.png b/AsBuiltReport.NetApp.ONTAP/icons/netapp-logo.png
similarity index 100%
rename from icons/netapp-logo.png
rename to AsBuiltReport.NetApp.ONTAP/icons/netapp-logo.png
diff --git a/icons/netapp_aggregate.png b/AsBuiltReport.NetApp.ONTAP/icons/netapp_aggregate.png
similarity index 100%
rename from icons/netapp_aggregate.png
rename to AsBuiltReport.NetApp.ONTAP/icons/netapp_aggregate.png
diff --git a/icons/netapp_node.png b/AsBuiltReport.NetApp.ONTAP/icons/netapp_node.png
similarity index 100%
rename from icons/netapp_node.png
rename to AsBuiltReport.NetApp.ONTAP/icons/netapp_node.png
diff --git a/icons/netapp_node_icon.png b/AsBuiltReport.NetApp.ONTAP/icons/netapp_node_icon.png
similarity index 100%
rename from icons/netapp_node_icon.png
rename to AsBuiltReport.NetApp.ONTAP/icons/netapp_node_icon.png
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/network-switch.png b/AsBuiltReport.NetApp.ONTAP/icons/network-switch.png
new file mode 100644
index 0000000..a51e7e1
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/network-switch.png differ
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/network_port.png b/AsBuiltReport.NetApp.ONTAP/icons/network_port.png
new file mode 100644
index 0000000..fa6b0d6
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/network_port.png differ
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/nic_port.png b/AsBuiltReport.NetApp.ONTAP/icons/nic_port.png
new file mode 100644
index 0000000..dd984ba
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/nic_port.png differ
diff --git a/icons/no_icon.png b/AsBuiltReport.NetApp.ONTAP/icons/no_icon.png
similarity index 100%
rename from icons/no_icon.png
rename to AsBuiltReport.NetApp.ONTAP/icons/no_icon.png
diff --git a/icons/ontap_node_new.png b/AsBuiltReport.NetApp.ONTAP/icons/ontap_node_new.png
similarity index 100%
rename from icons/ontap_node_new.png
rename to AsBuiltReport.NetApp.ONTAP/icons/ontap_node_new.png
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/ontap_single_switch.png b/AsBuiltReport.NetApp.ONTAP/icons/ontap_single_switch.png
new file mode 100644
index 0000000..f6f8add
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/ontap_single_switch.png differ
diff --git a/AsBuiltReport.NetApp.ONTAP/icons/ontap_stack_switch.png b/AsBuiltReport.NetApp.ONTAP/icons/ontap_stack_switch.png
new file mode 100644
index 0000000..ace130f
Binary files /dev/null and b/AsBuiltReport.NetApp.ONTAP/icons/ontap_stack_switch.png differ
diff --git a/icons/ontap_svm.png b/AsBuiltReport.NetApp.ONTAP/icons/ontap_svm.png
similarity index 100%
rename from icons/ontap_svm.png
rename to AsBuiltReport.NetApp.ONTAP/icons/ontap_svm.png
diff --git a/icons/ontap_svm_icon.png b/AsBuiltReport.NetApp.ONTAP/icons/ontap_svm_icon.png
similarity index 100%
rename from icons/ontap_svm_icon.png
rename to AsBuiltReport.NetApp.ONTAP/icons/ontap_svm_icon.png
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f3bde6..cd1d749 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.6.12] - 2026-03-16
+
+### Added
+
+- Add Vserver resources diagram showing SVM information, allocated aggregates, and network interfaces (LIFs)
+- Add Network ports diagram showing all network ports and their associated LIFs
+- Add Volume resources usage to the vserver diagram
+- Add node owner (Home Node) to network interface tables (Vserver, Cluster, Management, Intercluster, and Data network interfaces)
+- Add Health Check best practices for Network Broadcast Domains
+- Add Health Check best practices for NTP configuration
+ - Recommend multiple NTP servers for redundancy
+- Add Per Volume export policy information
+- Add `Node Name` to FCP Interfaces section in FCP Vserver configuration
+- Apply powershell best practices
+- Add ConvertTo-HashToYN function
+- Add EMS configuration setting health check
+- Add support for charts
+ - Aggregate Usage
+ - Per Node Disk Assignment
+
+### Changed
+
+- Migrate from Diagrammer.Core to AsBuiltReport.Diagram for diagram generation
+- Bump AsBuiltReport.Chart module requirement to v0.3.0
+- Bump AsBuiltReport.Core module requirement to v1.6.2
+- Bump NetApp.ONTAP module requirement to v9.18.1.2601
+- Bump module version to v0.6.12
+- Update github actions to use latest version
+- Export diagrams by default
+- Improved Cluster diagram to show Broadcast Domains and network ports per node
+- Reorganize module structure - moved module files to AsBuiltReport.System.Resources/ subdirectory
+
+### 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
+- Fix diagram size not respecting document border size
+- Fix HealthCheck - Volume without deduplication section displaying incorrect values
+- Fix type conversion for volume usage percentage checks in Get-AbrOntapVserverVolume function
+- Fix: Join management addresses into a comma-separated string in cluster and node diagrams
+
+### Removed
+
+- Removed Pwsh v5.1 support
+
## [0.6.11] - 2025-11-07
### Added
diff --git a/README.md b/README.md
index 27f4df1..a256f21 100755
--- a/README.md
+++ b/README.md
@@ -48,15 +48,15 @@ Below are the instructions on how to install, configure and generate a NetApp ON
The ONTAP Storage As Built Report supports the following ONTAP versions;
- ONTAP 9.x
- - Tested on v9.5, 9.7, 9.8, 9.9.1, 9.10.1, 9.11.1, 9.12.1, 9.13.1, 9.14.1, 9.15.1, 9.16.1, 9.17.1
+ - Tested on v9.5, 9.7, 9.8, 9.9.1, 9.10.1, 9.11.1, 9.12.1, 9.13.1, 9.14.1, 9.15.1, 9.16.1, 9.17.1, 9.18.1
### **PowerShell**
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
@@ -64,17 +64,19 @@ Each of the following modules will be automatically installed by following the [
These modules may also be manually installed.
-| Module Name | Minimum Required Version | PS Gallery | GitHub |
-| ------------------ | :----------------------: | :-------------------------------------------------------------------: | :-------------------------------------------------------------------------: |
-| PScribo | 0.10.0 | [Link](https://www.powershellgallery.com/packages/PScribo) | [Link](https://github.com/iainbrighton/PScribo/tree/master) |
-| AsBuiltReport.Core | 1.5.0 | [Link](https://www.powershellgallery.com/packages/AsBuiltReport.Core) | [Link](https://github.com/AsBuiltReport/AsBuiltReport.Core/releases/latest) |
-| Netapp.ONTAP | 9.17.1.2509 | [Link](https://www.powershellgallery.com/packages/NetApp.ONTAP) | |
+| Module Name | Minimum Required Version | PS Gallery | GitHub |
+| --------------------- | :----------------------: | :----------------------------------------------------------------------: | :-------------------------------------------------------------------------: |
+| PScribo | 0.11.1 | [Link](https://www.powershellgallery.com/packages/PScribo) | [Link](https://github.com/iainbrighton/PScribo/tree/master) |
+| AsBuiltReport.Core | 1.6.2 | [Link](https://www.powershellgallery.com/packages/AsBuiltReport.Core) | [Link](https://github.com/AsBuiltReport/AsBuiltReport.Core/releases/latest) |
+| Netapp.ONTAP | 9.18.1.2601 | [Link](https://www.powershellgallery.com/packages/NetApp.ONTAP) | [Link](https://github.com/NetApp/ontap-powershell-modules) |
+| AsBuiltReport.Chart | 0.3.0 | [Link](https://www.powershellgallery.com/packages/AsBuiltReport.Chart) | [Link](https://github.com/AsBuiltReport/AsBuiltReport.Chart) |
+| AsBuiltReport.Diagram | 1.0.3 | [Link](https://www.powershellgallery.com/packages/AsBuiltReport.Diagram) | [Link](https://github.com/AsBuiltReport/AsBuiltReport.Diagram) |
## :package: Module Installation
### 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
diff --git a/Samples/Sample NetApp As-Built Report.html b/Samples/Sample NetApp As-Built Report.html
index ddd6bfd..0921517 100755
--- a/Samples/Sample NetApp As-Built Report.html
+++ b/Samples/Sample NetApp As-Built Report.html
@@ -8,31 +8,31 @@
hr { margin-top: 1.0rem; }
.portrait { background: white; width: 210mm; display: block; margin-top: 1rem; margin-left: auto; margin-right: auto; margin-bottom: 1rem; position: relative; border-style: solid; border-width: 1px; border-color: #c6c6c6; }
.landscape { background: white; width: 297mm; display: block; margin-top: 1rem; margin-left: auto; margin-right: auto; margin-bottom: 1rem; position: relative; border-style: solid; border-width: 1px; border-color: #c6c6c6; }
- .NOTOCHeading7 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; font-style: italic; color: #00ebcd; }
- .NOTOCHeading5 { font-family: 'Segoe Ui'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #009684; }
- .Caption { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; font-style: italic; color: #072e58; }
- .TOC { font-family: 'Segoe Ui'; font-size: 1.33rem; text-align: left; font-weight: normal; color: #072e58; }
+ .NOTOCHeading6 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #009683; }
+ .Footer { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: center; font-weight: normal; color: #565656; }
.Heading4 { font-family: 'Segoe Ui'; font-size: 1.00rem; text-align: left; font-weight: normal; color: #958026; }
+ .Warning { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #fff4c7; }
+ .Heading5 { font-family: 'Segoe Ui'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #009684; }
+ .Heading3 { font-family: 'Segoe Ui'; font-size: 1.08rem; text-align: left; font-weight: normal; color: #395879; }
+ .Heading1 { font-family: 'Segoe Ui'; font-size: 1.33rem; text-align: left; font-weight: normal; color: #072e58; }
+ .Title { font-family: 'Segoe Ui'; font-size: 2.00rem; text-align: center; font-weight: normal; color: #072e58; }
.Header { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: center; font-weight: normal; color: #565656; }
+ .TableDefaultHeading { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #fafafa; background-color: #072e58; }
+ .OK { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #dff0d0; }
+ .Caption { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; font-style: italic; color: #072e58; }
+ .Title2 { font-family: 'Segoe Ui'; font-size: 1.50rem; text-align: center; font-weight: normal; color: #204369; }
+ .TableDefaultAltRow { font-family: 'Calibri','Candara','Segoe','Segoe UI','Optima','Arial','Sans-Serif'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #000000; background-color: #d0ddee; }
+ .Heading6 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #009683; }
+ .Normal { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; }
+ .TableDefaultRow { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; }
.Heading2 { font-family: 'Segoe Ui'; font-size: 1.17rem; text-align: left; font-weight: normal; color: #204369; }
+ .TOC { font-family: 'Segoe Ui'; font-size: 1.33rem; text-align: left; font-weight: normal; color: #072e58; }
.NOTOCHeading4 { font-family: 'Segoe Ui'; font-size: 1.00rem; text-align: left; font-weight: normal; color: #958026; }
- .Normal { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; }
- .Title3 { font-family: 'Segoe Ui'; font-size: 1.00rem; text-align: left; font-weight: normal; color: #395879; }
.Info { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #e3f5fc; }
- .TableDefaultHeading { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #fafafa; background-color: #072e58; }
- .Heading1 { font-family: 'Segoe Ui'; font-size: 1.33rem; text-align: left; font-weight: normal; color: #072e58; }
- .Title { font-family: 'Segoe Ui'; font-size: 2.00rem; text-align: center; font-weight: normal; color: #072e58; }
- .TableDefaultRow { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; }
- .Title2 { font-family: 'Segoe Ui'; font-size: 1.50rem; text-align: center; font-weight: normal; color: #204369; }
- .Footer { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: center; font-weight: normal; color: #565656; }
- .Warning { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #fff4c7; }
+ .NOTOCHeading5 { font-family: 'Segoe Ui'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #009684; }
+ .Title3 { font-family: 'Segoe Ui'; font-size: 1.00rem; text-align: left; font-weight: normal; color: #395879; }
+ .NOTOCHeading7 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; font-style: italic; color: #00ebcd; }
.Critical { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #feddd7; }
- .Heading6 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #009683; }
- .TableDefaultAltRow { font-family: 'Calibri','Candara','Segoe','Segoe UI','Optima','Arial','Sans-Serif'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #000000; background-color: #d0ddee; }
- .NOTOCHeading6 { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #009683; }
- .OK { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #565656; background-color: #dff0d0; }
- .Heading5 { font-family: 'Segoe Ui'; font-size: 0.92rem; text-align: left; font-weight: normal; color: #009684; }
- .Heading3 { font-family: 'Segoe Ui'; font-size: 1.08rem; text-align: left; font-weight: normal; color: #395879; }
table.tabledefault { padding: 0.08rem 0.17rem 0.13rem 0.17rem; border-style: solid; border-width: 0.02rem; border-color: #072e58; border-collapse: collapse; }
table.tabledefault th { font-family: 'Segoe Ui'; font-size: 0.83rem; text-align: left; font-weight: normal; color: #fafafa; background-color: #072e58; padding: 0.08rem 0.17rem 0.13rem 0.17rem; border-style: solid; border-width: 0.02rem; border-color: #072e58; border-collapse: collapse; }
table.tabledefault td { padding: 0.08rem 0.17rem 0.13rem 0.17rem; border-style: solid; border-width: 0.02rem; border-color: #072e58; border-collapse: collapse; }
@@ -49,401 +49,847 @@
-
NetApp ONTAP As Built Report
Acme Inc.
-| Author: | Jonathan Colon |
-| Date: | Friday, August 22, 2025 |
+
NetApp ONTAP As Built Report
As Built Report
+| Author: | As Built Report |
+| Date: | Tuesday, February 3, 2026 |
| Version: | 1.0 |
-
1 PHARMAX-HQ Cluster Report
The following section provides a summary of the array configuration for PHARMAX-HQ.
1.1 PHARMAX-HQ Cluster Diagram
-

+
1 PHARMAX-HQ Cluster Report
The following section provides a summary of the array configuration for PHARMAX-HQ.
1.1 PHARMAX-HQ Cluster Diagram
+
-
Image preview: Opens the image in a new tab to view it at full resolution.
1.2 Cluster Information
+1.2 Cluster Information
| Cluster Name | PHARMAX-HQ |
-| Cluster UUID | 6a7cdc49-6fbd-11f0-9ce1-005056b06182 |
+| Cluster UUID | 8db621bf-d2cf-11f0-9194-005056b09767 |
| Cluster Serial | 1-80-000011 |
| Cluster Controller | 192.168.7.60 |
-| Cluster Contact | - |
-| Cluster Location | - |
-| Ontap Version | NetApp Release 9.16.1P4: Tue May 27 23:22:56 UTC 2025 |
-| Number of Aggregates | 4 |
-| Number of Volumes | 6 |
+| Cluster Contact | -- |
+| Cluster Location | -- |
+| Ontap Version | NetApp Release 9.18.1RC1: Sat Nov 08 06:50:56 UTC 2025 |
+| Number of Aggregates | 8 |
+| Number of Volumes | 17 |
| Overall System Health | OK |
Table 1 - Cluster Information - PHARMAX-HQ
-1.2.1 Cluster HA Status
+1.2.1 Cluster HA Status
| Name | Partner | TakeOver Possible | TakeOver State | HA Mode | HA State |
-| PHARMAX-HQ-01 | PHARMAX-HQ-02 | Yes | not_in_takeover | ha | connected |
-| PHARMAX-HQ-02 | PHARMAX-HQ-01 | Yes | not_in_takeover | ha | connected |
-
-
Table 2 - Cluster HA Status - PHARMAX-HQ
-1.3 Node Information
The following section provides a summary of the Node on PHARMAX-HQ.
1.3.1 Node Inventory
The following section provides the node inventory on PHARMAX-HQ.
+| cluster-01 | cluster-02 | Yes | not_in_takeover | ha | connected |
+| cluster-02 | cluster-01 | Yes | not_in_takeover | ha | connected |
+| cluster-03 | cluster-04 | No | not_in_takeover | ha | connected |
+| cluster-04 | cluster-03 | No | not_in_takeover | ha | connected |
+
+
Table 2 - Cluster AutoSupport Status - PHARMAX-HQ
+Health Check:
Best Practice: 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.
Best Practice: One or more nodes have HA disabled while operating in HA mode. It is recommended to enable HA to ensure redundancy and high availability.
1.2.2 Cluster AutoSupport Status
+| Node Name | Protocol | Enabled |
+| cluster-01 | https | Yes |
+| cluster-02 | https | Yes |
+| cluster-03 | https | Yes |
+| cluster-04 | https | Yes |
+
+
Table 3 - Cluster AutoSupport Status - PHARMAX-HQ
+1.3 Nodes
The following section provides detailed information of nodes in cluster PHARMAX-HQ.
1.3.1 Inventory
| Name | Model | Id | Serial | Uptime |
-| PHARMAX-HQ-01 | SIMBOX | 4082577507 | 4082368511 | 00:42:12 |
-| PHARMAX-HQ-02 | SIMBOX | 4082577508 | 4034389062 | 00:42:12 |
-
-
Table 3 - Nodes - PHARMAX-HQ
-1.3.1.1 Node Vol0 Inventory
-| Node | Aggregate | Volume | Capacity | Available | Used |
-| PHARMAX-HQ-01 | aggr0_PHARMAX_HQ_01 | vol0 | 9 GB | 3 GB | 65% |
-| PHARMAX-HQ-02 | aggr0_PHARMAX_HQ_02 | vol0 | 9 GB | 3 GB | 64% |
-
-
Table 4 - Node Storage - PHARMAX-HQ
-1.4 Storage Information
The following section provides a summary of the storage hardware on PHARMAX-HQ.
1.4.1 Aggregate Inventory
The following section provides the Aggregates on PHARMAX-HQ.
1.4.1.1 Storage Aggregate Diagram
-

-
-Image preview: Opens the image in a new tab to view it at full resolution.
+| cluster-01 | SIMBOX | 4082116507 | 621803000017 | 00:26:30 |
+| cluster-02 | SIMBOX | 4082116508 | 621803000018 | 00:26:31 |
+| cluster-03 | SIMBOX | 4082717607 | 721803000013 | 00:26:30 |
+| cluster-04 | SIMBOX | 4082717608 | 721803000014 | 00:26:30 |
+
+
Table 4 - Nodes - PHARMAX-HQ
+1.3.1.1 Root Volume Vol0
+| Node | Aggregate | Capacity | Available | Used |
+| cluster-01 | aggr0_cluster_01 | 5.8 GB | 1.3 GB | 76% |
+| cluster-02 | aggr0_cluster_02 | 5.3 GB | 928.2 MB | 81% |
+| cluster-03 | aggr0_cluster_03 | 5.8 GB | 1.3 GB | 75% |
+| cluster-04 | aggr0_cluster_04 | 5.3 GB | 1.2 GB | 76% |
+
+
Table 5 - Node Storage - PHARMAX-HQ
+1.3.1.2 Service-Processor
+| Name | Type | IP Address | MAC Address | Network Configured | Firmware | Status |
+| cluster-01 | -- | -- | -- | -- | -- | unknown |
+| cluster-02 | -- | -- | -- | -- | -- | unknown |
+| cluster-03 | -- | -- | -- | -- | -- | unknown |
+| cluster-04 | -- | -- | -- | -- | -- | unknown |
+
+
Table 6 - Node Service-Processor - PHARMAX-HQ
+Health Check:
Best Practice: Ensure that all service-processors are online, configured and functioning properly to maintain system management capabilities.
1.4 Storage Information
The following section provides detailed information about the storage configuration for cluster PHARMAX-HQ.
1.4.1 Aggregates (Local Tiers)
The following table summarises the aggregates in PHARMAX-HQ.
| Name | Capacity | Available | Used | Disk Count | Root | Raid Type | State |
-| aggr0_PHARMAX_HQ_01 | 9 GB | 454 MB | 95% | 10 | Yes | RAID_DP | online |
-| aggr0_PHARMAX_HQ_02 | 9 GB | 454 MB | 95% | 10 | Yes | RAID_DP | online |
-| PHARMAX_HQ_01_SSD_1 | 87 GB | 54 GB | 38% | 23 | No | RAID_DP | online |
-| PHARMAX_HQ_02_SSD_1 | 87 GB | 87 GB | 0% | 23 | No | RAID_DP | online |
-
-
Table 5 - Aggregates - PHARMAX-HQ
-1.4.1.2 Aggregate Spares
+| aggr0_cluster_01 | 6.1 GB | 303.4 MB | 5.8 GB | 14 | Yes | RAID_DP | online |
+| aggr0_cluster_02 | 5.6 GB | 278.3 MB | 5.3 GB | 13 | Yes | RAID_DP | online |
+| aggr0_cluster_03 | 6.1 GB | 303.4 MB | 5.8 GB | 14 | Yes | RAID_DP | online |
+| aggr0_cluster_04 | 5.6 GB | 278.3 MB | 5.3 GB | 13 | Yes | RAID_DP | online |
+| cluster_01_SSD_1 | 90.6 GB | 80.5 GB | 10.1 GB | 35 | No | RAID_DP | online |
+| cluster_02_SSD_1 | 75.0 GB | 43.2 GB | 31.8 GB | 30 | No | RAID_DP | online |
+| cluster_03_SSD_1 | 90.6 GB | 60.4 GB | 30.2 GB | 35 | No | RAID_DP | online |
+| cluster_04_SSD_1 | 75.0 GB | 42.9 GB | 32.1 GB | 30 | No | RAID_DP | online |
+
+
Table 7 - Aggregates - PHARMAX-HQ
+Aggragate Usage - Chart
+

+
+1.4.1.1 Disk Spares
| Name | Capacity | Root Usable | Data Usable | Shared Disk | Disk Zeroed | Owner |
-| VMw-1.11 | 11 GB | 1 GB | - | Yes | Yes | PHARMAX-HQ-01 |
-| VMw-1.12 | 11 GB | 1 GB | - | Yes | Yes | PHARMAX-HQ-01 |
-| VMw-1.22 | 11 GB | - | 5 GB | Yes | Yes | PHARMAX-HQ-01 |
-| VMw-1.21 | 11 GB | 1 GB | - | Yes | Yes | PHARMAX-HQ-02 |
-| VMw-1.22 | 11 GB | 1 GB | 5 GB | Yes | Yes | PHARMAX-HQ-02 |
-
-
Table 6 - Aggregates Spares - PHARMAX-HQ
-1.4.2 Disk Information
The following section provides the disk summary information on controller PHARMAX-HQ.
1.4.2.1 Per Node Disk Assignment
The following section provides the number of disks assigned to each controller on PHARMAX-HQ.
+| VMw-1.19 | 7.1 GB | 627.5 MB | -- | Yes | Yes | cluster-01 |
+| VMw-1.7 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-01 |
+| VMw-1.12 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-02 |
+| VMw-1.19 | 7.1 GB | -- | 3.2 GB | Yes | Yes | cluster-02 |
+| VMw-1.24 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-02 |
+| VMw-1.43 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-03 |
+| VMw-1.55 | 7.1 GB | -- | -- | No | No | cluster-03 |
+| VMw-1.66 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-03 |
+| VMw-1.47 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-04 |
+| VMw-1.67 | 7.1 GB | 627.3 MB | -- | Yes | Yes | cluster-04 |
+| VMw-1.70 | 7.1 GB | -- | 3.2 GB | Yes | Yes | cluster-04 |
+
+
Table 8 - Disk Spares - PHARMAX-HQ
+1.4.1.2 Aggregate Diagram
+

+
+
1.4.2 Disks
The following section provides a comprehensive summary of disk inventory and configuration across all controllers in the PHARMAX-HQ cluster.
1.4.2.1 Per Node Disk Assignment
| Node | Disk Count |
-| PHARMAX-HQ-01 | 12 |
-| PHARMAX-HQ-02 | 12 |
-
-
Table 7 - Assigned Disk - PHARMAX-HQ
-1.4.2.2 Disk Owned by Node PHARMAX-HQ-01
+| cluster-01 | 21 |
+| cluster-02 | 15 |
+| cluster-03 | 21 |
+| cluster-04 | 15 |
+
+
Table 9 - Assigned Disk - PHARMAX-HQ
+Per Node Disk Assignment - Chart
+

+
+cluster-01
+| Disk | Owner Id | Home | Home Id | Type |
+| VMw-1.1 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.13 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.14 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.15 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.16 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.17 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.18 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.19 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.2 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.25 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.26 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.27 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.28 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.29 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.3 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.30 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.31 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.4 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.5 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.6 | 4082116507 | cluster-01 | 4082116507 | SSD |
+| VMw-1.7 | 4082116507 | cluster-01 | 4082116507 | SSD |
+
+
Table 10 - Node Disk Owner - cluster-01
+cluster-02
+| Disk | Owner Id | Home | Home Id | Type |
+| VMw-1.10 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.11 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.12 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.20 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.21 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.22 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.23 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.24 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.32 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.33 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.34 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.35 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.36 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.8 | 4082116508 | cluster-02 | 4082116508 | SSD |
+| VMw-1.9 | 4082116508 | cluster-02 | 4082116508 | SSD |
+
+
Table 11 - Node Disk Owner - cluster-02
+cluster-03
| Disk | Owner Id | Home | Home Id | Type |
-| VMw-1.1 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.10 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.11 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.12 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.2 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.3 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.4 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.5 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.6 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.7 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.8 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-| VMw-1.9 | 4082577507 | PHARMAX-HQ-01 | 4082577507 | SSD |
-
-
Table 8 - Node Disk Owner - PHARMAX-HQ-01
-1.4.2.3 Disk Owned by Node PHARMAX-HQ-02
+| VMw-1.37 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.38 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.39 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.40 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.41 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.42 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.43 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.49 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.50 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.51 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.52 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.53 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.54 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.55 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.60 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.61 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.62 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.63 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.64 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.65 | 4082717607 | cluster-03 | 4082717607 | SSD |
+| VMw-1.66 | 4082717607 | cluster-03 | 4082717607 | SSD |
+
+
Table 12 - Node Disk Owner - cluster-03
+cluster-04
| Disk | Owner Id | Home | Home Id | Type |
-| VMw-1.13 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.14 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.15 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.16 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.17 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.18 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.19 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.20 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.21 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.22 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.23 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-| VMw-1.24 | 4082577508 | PHARMAX-HQ-02 | 4082577508 | SSD |
-
-
Table 9 - Node Disk Owner - PHARMAX-HQ-02
-1.4.2.4 Disk Container Type
+| VMw-1.44 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.45 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.46 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.47 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.48 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.56 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.57 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.58 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.59 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.67 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.68 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.69 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.70 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.71 | 4082717608 | cluster-04 | 4082717608 | SSD |
+| VMw-1.72 | 4082717608 | cluster-04 | 4082717608 | SSD |
+
+
Table 13 - Node Disk Owner - cluster-04
+1.4.2.2 Disk Container Type
| Container | Disk Count |
-| shared | 24 |
+| aggregate | 8 |
+| broken | 1 |
+| shared | 62 |
+| spare | 1 |
+
+
Table 14 - Disk Container Type - PHARMAX-HQ
+Aggregate Spare Low Warning Per Node
+| Node | Aggregate Spare Low |
+| cluster-01 | Yes |
+| cluster-02 | No |
+| cluster-03 | No |
+| cluster-04 | No |
+
+
Table 15 - Aggregate Disk Spare Low - PHARMAX-HQ
+Health Check:
Best Practice: Ensure that aggregate spare capacity is above the recommended threshold to maintain optimal performance and reliability.
1.4.2.3 Failed Disk
+| Disk Name | Shelf | Bay | Pool | Disk Paths |
+| VMw-1.1 | -- | 0 | 0 | cluster-01:0b.0 cluster-02:0c.0 |
+
+
Table 16 - Failed Disk - PHARMAX-HQ
+Health Check:
Best Practice: Review the failed disk information above. It is recommended to replace any broken disks promptly to maintain data integrity and system performance.
1.4.2.4 Disk Inventory
+| Disk Name | Shelf | Bay | Capacity | Model | Type | Firmware |
+| VMw-1.1 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.10 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.11 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.12 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.13 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.14 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.15 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.16 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.17 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.18 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.19 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.2 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.20 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.21 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.22 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.23 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.24 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.25 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.26 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.27 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.28 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.29 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.3 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.30 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.31 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.32 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.33 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.34 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.35 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.36 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.37 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.38 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.39 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.4 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.40 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.41 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.42 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.43 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.44 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.45 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.46 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.47 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.48 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.49 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.5 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.50 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.51 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.52 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.53 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.54 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.55 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.56 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.57 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.58 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.59 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.6 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.60 | -- | 0 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.61 | -- | 1 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.62 | -- | 2 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.63 | -- | 3 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.64 | -- | 4 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.65 | -- | 5 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.66 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.67 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.68 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.69 | -- | 10 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.7 | -- | 6 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.70 | -- | 11 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.71 | -- | 12 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.72 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.8 | -- | 8 | 8.6G | Virtualdisk | SSD | 2.0 |
+| VMw-1.9 | -- | 9 | 8.6G | Virtualdisk | SSD | 2.0 |
+
+
Table 17 - Disk Inventory - PHARMAX-HQ
+1.5 Licenses Information
The following section provides a summary of the license usage in PHARMAX-HQ.
1.5.1 cluster-01 License Usage
+| License | Type | Description | Risk |
+| Cifs | License | CIFS License | low |
+| Fcp | License | FCP License | low |
+| Flexclone | License | FlexClone License | low |
+| Iscsi | License | iSCSI License | low |
+| Nfs | License | NFS License | low |
+| Snaplock | License | SnapLock License | low |
+| Snapmanagersuite | License | SnapCenter License | low |
+| Snapmirror | License | SnapMirror License | low |
+| Snaprestore | License | SnapRestore License | low |
+| Snapvault | License | SnapVault License | low |
+| Tpm | License | Trusted Platform Module License | -- |
+| Ve | License | Volume Encryption License | -- |
-
Table 10 - Disk Container Type - PHARMAX-HQ
-1.5 Licenses Information
The following section provides a summary of the license usage on PHARMAX-HQ.
1.5.1 PHARMAX-HQ-01 License Usage
+Table 18 - License Usage - cluster-01
+1.5.2 cluster-02 License Usage
| License | Type | Description | Risk |
| Cifs | License | CIFS License | low |
| Fcp | License | FCP License | low |
| Flexclone | License | FlexClone License | low |
-| Insight_Balance | License | OnCommand Balance | low |
| Iscsi | License | iSCSI License | low |
| Nfs | License | NFS License | low |
| Snaplock | License | SnapLock License | low |
| Snapmanagersuite | License | SnapCenter License | low |
| Snapmirror | License | SnapMirror License | low |
-| Snapprotectapps | License | SnapProtectApp License | low |
| Snaprestore | License | SnapRestore License | low |
| Snapvault | License | SnapVault License | low |
+| Tpm | License | Trusted Platform Module License | -- |
+| Ve | License | Volume Encryption License | -- |
-
Table 11 - License Usage - PHARMAX-HQ-01
-1.5.2 PHARMAX-HQ-02 License Usage
+Table 19 - License Usage - cluster-02
+1.5.3 cluster-03 License Usage
| License | Type | Description | Risk |
| Cifs | License | CIFS License | low |
| Fcp | License | FCP License | low |
| Flexclone | License | FlexClone License | low |
-| Insight_Balance | License | OnCommand Balance | low |
| Iscsi | License | iSCSI License | low |
| Nfs | License | NFS License | low |
| Snaplock | License | SnapLock License | low |
| Snapmanagersuite | License | SnapCenter License | low |
| Snapmirror | License | SnapMirror License | low |
-| Snapprotectapps | License | SnapProtectApp License | low |
| Snaprestore | License | SnapRestore License | low |
| Snapvault | License | SnapVault License | low |
+| Tpm | License | Trusted Platform Module License | -- |
+| Ve | License | Volume Encryption License | -- |
-
Table 12 - License Usage - PHARMAX-HQ-02
-1.6 Network Information
The following section provides a summary of the networking features on PHARMAX-HQ.
1.6.1 IPSpace
The following section provides the IPSpace information on PHARMAX-HQ.
+Table 20 - License Usage - cluster-03
+1.5.4 cluster-04 License Usage
+| License | Type | Description | Risk |
+| Cifs | License | CIFS License | low |
+| Fcp | License | FCP License | low |
+| Flexclone | License | FlexClone License | low |
+| Iscsi | License | iSCSI License | low |
+| Nfs | License | NFS License | low |
+| Snaplock | License | SnapLock License | low |
+| Snapmanagersuite | License | SnapCenter License | low |
+| Snapmirror | License | SnapMirror License | low |
+| Snaprestore | License | SnapRestore License | low |
+| Snapvault | License | SnapVault License | low |
+| Tpm | License | Trusted Platform Module License | -- |
+| Ve | License | Volume Encryption License | -- |
+
+
Table 21 - License Usage - cluster-04
+1.6 Networking Diagram
+

+
+
1.7 Network Information
The following section provides a summary of the networking features in PHARMAX-HQ.
1.7.1 IPSpace
The following section provides the IPSpace information in PHARMAX-HQ.
| Name | Cluster |
| SVM | Cluster |
-| Ports | PHARMAX-HQ-02:e0a; PHARMAX-HQ-02:e0b; PHARMAX-HQ-01:e0a; PHARMAX-HQ-01:e0b |
+| Ports | cluster-04:e0a; cluster-04:e0b; cluster-03:e0a; cluster-03:e0b; cluster-02:e0a; cluster-02:e0b; cluster-01:e0a; cluster-01:e0b |
| Broadcast Domains | Cluster |
-
Table 13 - Network IPSpace - Cluster
+Table 22 - Network IPSpace - Cluster
| Name | Default |
-| SVM | SAN; NAS; PHARMAX-HQ |
-| Ports | PHARMAX-HQ-02:a0a; PHARMAX-HQ-02:a0a-11; PHARMAX-HQ-02:a0a-12; PHARMAX-HQ-02:a0a-5; PHARMAX-HQ-02:a0a-6; PHARMAX-HQ-02:a0a-7; PHARMAX-HQ-02:e0c; PHARMAX-HQ-02:e0d; PHARMAX-HQ-01:a0a; PHARMAX-HQ-01:a0a-11; PHARMAX-HQ-01:a0a-12; PHARMAX-HQ-01:a0a-5; PHARMAX-HQ-01:a0a-6; PHARMAX-HQ-01:a0a-7; PHARMAX-HQ-01:e0c; PHARMAX-HQ-01:e0d |
-| Broadcast Domains | Default; Default-1; Default-2; Default-3; Default-4; Default-5; Default-6; ISCSI-A; ISCSI-B |
+| SVM | NFS; ISCSI; CIFS; FCP; PHARMAX-HQ |
+| Ports | cluster-04:a0a; cluster-04:a0a-12; cluster-04:a0a-5; cluster-04:a0a-6; cluster-04:a0a-7; cluster-04:a0b; cluster-04:a0b-24; cluster-04:e0c; cluster-04:e0d; cluster-04:e0f; cluster-04:e0g; cluster-04:e0h; cluster-03:a0a; cluster-03:a0a-12; cluster-03:a0a-5; cluster-03:a0a-6; cluster-03:a0a-7; cluster-03:a0b; cluster-03:a0b-24; cluster-03:e0c; cluster-03:e0d; cluster-03:e0f; cluster-03:e0g; cluster-03:e0h; cluster-02:a0a; cluster-02:a0a-12; cluster-02:a0a-5; cluster-02:a0a-6; cluster-02:a0a-7; cluster-02:a0b; cluster-02:a0b-24; cluster-02:e0c; cluster-02:e0d; cluster-02:e0f; cluster-02:e0g; cluster-02:e0h; cluster-01:a0a; cluster-01:a0a-12; cluster-01:a0a-5; cluster-01:a0a-6; cluster-01:a0a-7; cluster-01:a0b; cluster-01:a0b-24; cluster-01:e0c; cluster-01:e0d; cluster-01:e0f; cluster-01:e0g; cluster-01:e0h |
+| Broadcast Domains | Default; Default-1; Default-2; Default-3; Default-4; Default-5; ISCSI-A-6; ISCSI-B-12; MGMT-5; Replication-11; VM-Network-7 |
-
Table 14 - Network IPSpace - Default
-1.6.1.1 Network Ports
The following section provides the physical network ports on PHARMAX-HQ.
1.6.1.1.1 PHARMAX-HQ-01 Ports
+Table 23 - Network IPSpace - Default
+1.7.1.1 Network Ports
The following section provides the physical network ports in PHARMAX-HQ.
1.7.1.1.1 cluster-01 Ports
| Port Name | Role | Mac Address | MTU | Link Status | Admin Status |
-| e0a | Cluster | 00:50:56:b0:61:82 | 9000 | Up | Up |
-| e0b | Cluster | 00:50:56:b0:e4:9d | 9000 | Up | Up |
-| e0c | Node_Mgmt | 02:50:56:b0:61:82 | 1500 | Up | Up |
-| e0d | Data | 02:50:56:b0:61:82 | 1500 | Up | Up |
-
-
Table 15 - Physical Port - PHARMAX-HQ-01
-1.6.1.1.2 PHARMAX-HQ-02 Ports
+| e0a | Cluster | 00:50:56:b0:97:67 | 9000 | Up | Up |
+| e0b | Cluster | 00:50:56:b0:39:18 | 9000 | Up | Up |
+| e0c | Node_Mgmt | 02:50:56:b0:97:67 | 9000 | Up | Up |
+| e0d | Data | 02:50:56:b0:97:67 | 9000 | Up | Up |
+| e0f | Data | 02:50:56:b0:39:18 | 9000 | Up | Up |
+| e0g | Data | 02:50:56:b0:39:18 | 9000 | Up | Up |
+| e0h | Data | 00:50:56:b0:fe:c4 | 1500 | Up | Up |
+
+
Table 24 - Physical Port - cluster-01
+1.7.1.1.2 cluster-02 Ports
+| Port Name | Role | Mac Address | MTU | Link Status | Admin Status |
+| e0a | Cluster | 00:50:56:b0:b8:94 | 9000 | Up | Up |
+| e0b | Cluster | 00:50:56:b0:0d:c5 | 9000 | Up | Up |
+| e0c | Node_Mgmt | 02:50:56:b0:b8:94 | 9000 | Up | Up |
+| e0d | Data | 02:50:56:b0:b8:94 | 9000 | Up | Up |
+| e0f | Data | 02:50:56:b0:0d:c5 | 9000 | Up | Up |
+| e0g | Data | 02:50:56:b0:0d:c5 | 9000 | Up | Up |
+| e0h | Data | 00:50:56:b0:53:d3 | 1500 | Up | Up |
+
+
Table 25 - Physical Port - cluster-02
+1.7.1.1.3 cluster-03 Ports
| Port Name | Role | Mac Address | MTU | Link Status | Admin Status |
-| e0a | Cluster | 00:50:56:b0:ea:5c | 9000 | Up | Up |
-| e0b | Cluster | 00:50:56:b0:5b:04 | 9000 | Up | Up |
-| e0c | Node_Mgmt | 02:50:56:b0:ea:5c | 1500 | Up | Up |
-| e0d | Data | 02:50:56:b0:ea:5c | 1500 | Up | Up |
+| e0a | Cluster | 00:50:56:b0:22:fe | 9000 | Up | Up |
+| e0b | Cluster | 00:50:56:b0:50:bc | 9000 | Up | Up |
+| e0c | Node_Mgmt | 02:50:56:b0:22:fe | 9000 | Up | Up |
+| e0d | Data | 02:50:56:b0:22:fe | 9000 | Up | Up |
+| e0f | Data | 02:50:56:b0:50:bc | 9000 | Up | Up |
+| e0g | Data | 02:50:56:b0:50:bc | 9000 | Up | Up |
+| e0h | Data | 00:50:56:b0:e5:da | 1500 | Up | Up |
+
+
Table 26 - Physical Port - cluster-03
+1.7.1.1.4 cluster-04 Ports
+| Port Name | Role | Mac Address | MTU | Link Status | Admin Status |
+| e0a | Cluster | 00:50:56:b0:39:57 | 9000 | Up | Up |
+| e0b | Cluster | 00:50:56:b0:8d:c2 | 9000 | Up | Up |
+| e0c | Node_Mgmt | 02:50:56:b0:39:57 | 9000 | Up | Up |
+| e0d | Data | 02:50:56:b0:39:57 | 9000 | Up | Up |
+| e0f | Data | 02:50:56:b0:8d:c2 | 9000 | Up | Up |
+| e0g | Data | 02:50:56:b0:8d:c2 | 9000 | Up | Up |
+| e0h | Data | 00:50:56:b0:5f:4e | 1500 | Up | Up |
+
+
Table 27 - Physical Port - cluster-04
+1.7.1.2 Network Link Aggregation Group
The following section provides per Node IFGRP Aggregated Ports in PHARMAX-HQ.
1.7.1.2.1 cluster-01 IFGRP
+| Port Name | Distribution Function | Mode | Port | Mac Address | Port Participation |
+| a0a | sequential | multimode | e0c e0d | 02:50:56:b0:97:67 | full |
+| a0b | sequential | multimode | e0f e0g | 02:50:56:b0:39:18 | full |
+
+
Table 28 - Link Aggregation Group - cluster-01
+1.7.1.2.2 cluster-02 IFGRP
+| Port Name | Distribution Function | Mode | Port | Mac Address | Port Participation |
+| a0a | sequential | multimode | e0c e0d | 02:50:56:b0:b8:94 | full |
+| a0b | sequential | multimode | e0f e0g | 02:50:56:b0:0d:c5 | full |
-
Table 16 - Physical Port - PHARMAX-HQ-02
-1.6.1.2 Network Link Aggregation Group
The following section provides per Node IFGRP Aggregated Ports on PHARMAX-HQ.
1.6.1.2.1 PHARMAX-HQ-01 IFGRP
+Table 29 - Link Aggregation Group - cluster-02
+1.7.1.2.3 cluster-03 IFGRP
| Port Name | Distribution Function | Mode | Port | Mac Address | Port Participation |
-| a0a | ip | multimode | e0d | 02:50:56:b0:61:82 | full |
+| a0a | sequential | multimode | e0c e0d | 02:50:56:b0:22:fe | full |
+| a0b | sequential | multimode | e0f e0g | 02:50:56:b0:50:bc | full |
-
Table 17 - Link Aggregation Group - PHARMAX-HQ-01
-1.6.1.2.2 PHARMAX-HQ-02 IFGRP
+Table 30 - Link Aggregation Group - cluster-03
+1.7.1.2.4 cluster-04 IFGRP
| Port Name | Distribution Function | Mode | Port | Mac Address | Port Participation |
-| a0a | ip | multimode | e0d | 02:50:56:b0:ea:5c | full |
+| a0a | sequential | multimode | e0c e0d | 02:50:56:b0:39:57 | full |
+| a0b | sequential | multimode | e0f e0g | 02:50:56:b0:8d:c2 | full |
-
Table 18 - Link Aggregation Group - PHARMAX-HQ-02
-1.6.1.3 Network VLANs
The following section provides Network VLAN information on PHARMAX-HQ.
1.6.1.3.1 PHARMAX-HQ-01 Vlans
+Table 31 - Link Aggregation Group - cluster-04
+1.7.1.3 Network VLANs
The following section provides Network VLAN information in PHARMAX-HQ.
1.7.1.3.1 cluster-01 Vlans
| Interface Name | Parent Interface | Vlan ID |
-| a0a-11 | a0a | 11 |
| a0a-12 | a0a | 12 |
+| a0b-24 | a0b | 24 |
| a0a-5 | a0a | 5 |
| a0a-6 | a0a | 6 |
| a0a-7 | a0a | 7 |
-
Table 19 - Network VLAN - PHARMAX-HQ-01
-1.6.1.3.2 PHARMAX-HQ-02 Vlans
+Table 32 - Network VLAN - cluster-01
+1.7.1.3.2 cluster-02 Vlans
| Interface Name | Parent Interface | Vlan ID |
-| a0a-11 | a0a | 11 |
| a0a-12 | a0a | 12 |
+| a0b-24 | a0b | 24 |
| a0a-5 | a0a | 5 |
| a0a-6 | a0a | 6 |
| a0a-7 | a0a | 7 |
-
Table 20 - Network VLAN - PHARMAX-HQ-02
-1.6.1.4 Broadcast Domain
+Table 33 - Network VLAN - cluster-02
+1.7.1.3.3 cluster-03 Vlans
+| Interface Name | Parent Interface | Vlan ID |
+| a0a-12 | a0a | 12 |
+| a0b-24 | a0b | 24 |
+| a0a-5 | a0a | 5 |
+| a0a-6 | a0a | 6 |
+| a0a-7 | a0a | 7 |
+
+
Table 34 - Network VLAN - cluster-03
+1.7.1.3.4 cluster-04 Vlans
+| Interface Name | Parent Interface | Vlan ID |
+| a0a-12 | a0a | 12 |
+| a0b-24 | a0b | 24 |
+| a0a-5 | a0a | 5 |
+| a0a-6 | a0a | 6 |
+| a0a-7 | a0a | 7 |
+
+
Table 35 - Network VLAN - cluster-04
+1.7.1.4 Broadcast Domains
| Name | IPSpace | Failover Groups | MTU | Ports |
-| Cluster | Cluster | Cluster | 9000 | PHARMAX-HQ-02:e0a PHARMAX-HQ-02:e0b PHARMAX-HQ-01:e0a PHARMAX-HQ-01:e0b |
-| Default | Default | Default | 1500 | PHARMAX-HQ-02:a0a PHARMAX-HQ-02:e0c PHARMAX-HQ-01:a0a PHARMAX-HQ-01:e0c |
-| Default-1 | Default | Default-1 | 1500 | PHARMAX-HQ-01:a0a-5 |
-| Default-2 | Default | Default-2 | 1500 | PHARMAX-HQ-01:a0a-7 |
-| Default-3 | Default | Default-3 | 1500 | PHARMAX-HQ-01:a0a-11 |
-| Default-4 | Default | Default-4 | 1500 | PHARMAX-HQ-02:a0a-11 |
-| Default-5 | Default | Default-5 | 1500 | PHARMAX-HQ-02:a0a-5 |
-| Default-6 | Default | Default-6 | 1500 | PHARMAX-HQ-02:a0a-7 |
-| ISCSI-A | Default | ISCSI-A | 1500 | PHARMAX-HQ-02:a0a-6 PHARMAX-HQ-01:a0a-6 |
-| ISCSI-B | Default | ISCSI-B | 1500 | PHARMAX-HQ-02:a0a-12 PHARMAX-HQ-01:a0a-12 |
-
-
Table 21 - Network Broadcast Domain - PHARMAX-HQ
-1.6.1.5 Failover Groups
+| Cluster | Cluster | Cluster | 9000 | cluster-04:e0a cluster-04:e0b cluster-03:e0a cluster-03:e0b cluster-02:e0a cluster-02:e0b cluster-01:e0a cluster-01:e0b |
+| Default | Default | Default | 1500 | cluster-04:a0a cluster-03:a0a cluster-02:a0a cluster-01:a0a |
+| Default-1 | Default | Default-1 | 9000 | cluster-01:a0b |
+| Default-2 | Default | Default-2 | 9000 | cluster-02:a0b |
+| Default-3 | Default | Default-3 | 9000 | cluster-03:a0b |
+| Default-4 | Default | Default-4 | 9000 | cluster-04:a0b |
+| Default-5 | Default | Default-5 | 9000 | cluster-04:a0b-24 cluster-03:a0b-24 cluster-02:a0b-24 cluster-01:a0b-24 |
+| ISCSI-A-6 | Default | ISCSI-A-6 | 9000 | cluster-04:a0a-6 cluster-03:a0a-6 cluster-02:a0a-6 cluster-01:a0a-6 |
+| ISCSI-B-12 | Default | ISCSI-B-12 | 9000 | cluster-04:a0a-12 cluster-03:a0a-12 cluster-02:a0a-12 cluster-01:a0a-12 |
+| MGMT-5 | Default | MGMT-5 | 1500 | cluster-04:a0a-5 cluster-03:a0a-5 cluster-02:a0a-5 cluster-01:a0a-5 |
+| Replication-11 | Default | Replication-11 | 1500 | cluster-04:e0h cluster-03:e0h cluster-02:e0h cluster-01:e0h |
+| VM-Network-7 | Default | VM-Network-7 | 1500 | cluster-04:a0a-7 cluster-03:a0a-7 cluster-02:a0a-7 cluster-01:a0a-7 |
+
+
Table 36 - Network Broadcast Domain - PHARMAX-HQ
+1.7.1.5 Failover Groups
| Name | Vserver | Target |
-| Cluster | Cluster | PHARMAX-HQ-02:e0a PHARMAX-HQ-02:e0b PHARMAX-HQ-01:e0a PHARMAX-HQ-01:e0b |
-| Default | PHARMAX-HQ | PHARMAX-HQ-02:a0a PHARMAX-HQ-02:e0c PHARMAX-HQ-01:a0a PHARMAX-HQ-01:e0c |
-| Default-1 | PHARMAX-HQ | PHARMAX-HQ-01:a0a-5 |
-| Default-2 | PHARMAX-HQ | PHARMAX-HQ-01:a0a-7 |
-| Default-3 | PHARMAX-HQ | PHARMAX-HQ-01:a0a-11 |
-| Default-4 | PHARMAX-HQ | PHARMAX-HQ-02:a0a-11 |
-| Default-5 | PHARMAX-HQ | PHARMAX-HQ-02:a0a-5 |
-| Default-6 | PHARMAX-HQ | PHARMAX-HQ-02:a0a-7 |
-| ISCSI-A | PHARMAX-HQ | PHARMAX-HQ-02:a0a-6 PHARMAX-HQ-01:a0a-6 |
-| ISCSI-B | PHARMAX-HQ | PHARMAX-HQ-02:a0a-12 PHARMAX-HQ-01:a0a-12 |
-
-
Table 22 - Network Failover Group - PHARMAX-HQ
-1.6.1.6 PHARMAX-HQ Vserver Routes
The following section provides the Routes information on PHARMAX-HQ.
+| Cluster | Cluster | cluster-04:e0a cluster-04:e0b cluster-03:e0a cluster-03:e0b cluster-02:e0a cluster-02:e0b cluster-01:e0a cluster-01:e0b |
+| Default | PHARMAX-HQ | cluster-04:a0a cluster-03:a0a cluster-02:a0a cluster-01:a0a |
+| Default-1 | PHARMAX-HQ | cluster-01:a0b |
+| Default-2 | PHARMAX-HQ | cluster-02:a0b |
+| Default-3 | PHARMAX-HQ | cluster-03:a0b |
+| Default-4 | PHARMAX-HQ | cluster-04:a0b |
+| Default-5 | PHARMAX-HQ | cluster-04:a0b-24 cluster-03:a0b-24 cluster-02:a0b-24 cluster-01:a0b-24 |
+| ISCSI-A-6 | PHARMAX-HQ | cluster-04:a0a-6 cluster-03:a0a-6 cluster-02:a0a-6 cluster-01:a0a-6 |
+| ISCSI-B-12 | PHARMAX-HQ | cluster-04:a0a-12 cluster-03:a0a-12 cluster-02:a0a-12 cluster-01:a0a-12 |
+| MGMT-5 | PHARMAX-HQ | cluster-04:a0a-5 cluster-03:a0a-5 cluster-02:a0a-5 cluster-01:a0a-5 |
+| Replication-11 | PHARMAX-HQ | cluster-04:e0h cluster-03:e0h cluster-02:e0h cluster-01:e0h |
+| VM-Network-7 | PHARMAX-HQ | cluster-04:a0a-7 cluster-03:a0a-7 cluster-02:a0a-7 cluster-01:a0a-7 |
+
+
Table 37 - Network Failover Group - PHARMAX-HQ
+1.7.1.6 Network Subnets
+| Name | Subnet | Gateway | Total IP | Used IP | Ip Ranges |
+| DeptA-Client-VMnet4 | 172.23.4.0/24 | 172.23.4.254 | 51 | 7 | 172.23.4.100-172.23.4.150 |
+| ISCSI-A-6 | 192.168.6.0/24 | -- | 51 | 4 | 192.168.6.100-192.168.6.150 |
+| ISCSI-B-12 | 192.168.12.0/24 | -- | 51 | 4 | 192.168.12.100-192.168.12.150 |
+
+
Table 38 - Network Subnet - PHARMAX-HQ
+1.7.1.7 PHARMAX-HQ Vserver Routes
The following section provides the Routes information in PHARMAX-HQ.
| Destination | Gateway | Metric | Address Family |
| 0.0.0.0/0 | 192.168.7.254 | 20 | ipv4 |
+| 0.0.0.0/0 | 192.168.11.254 | 20 | ipv4 |
-
Table 23 - Network Route - PHARMAX-HQ
-1.6.1.7 NAS Vserver Routes
The following section provides the Routes information on PHARMAX-HQ.
+Table 39 - Network Route - PHARMAX-HQ
+1.7.1.8 CIFS Vserver Routes
The following section provides the Routes information in PHARMAX-HQ.
| Destination | Gateway | Metric | Address Family |
-| 0.0.0.0/0 | 192.168.7.254 | 20 | ipv4 |
+| 0.0.0.0/0 | 172.23.4.254 | 20 | ipv4 |
-
Table 24 - Network Route - NAS
-1.6.1.8 Network Interfaces
The following section provides the Network Interfaces information on PHARMAX-HQ.
Cluster Network Interfaces
-| Cluster Interface | Status | Data Protocols | Address | Vserver |
-| PHARMAX-HQ-01_clus1 | UP | none | 169.254.97.130 | Cluster |
-| PHARMAX-HQ-01_clus2 | UP | none | 169.254.228.157 | Cluster |
-| PHARMAX-HQ-02_clus1 | UP | none | 169.254.234.92 | Cluster |
-| PHARMAX-HQ-02_clus2 | UP | none | 169.254.91.4 | Cluster |
+Table 40 - Network Route - CIFS
+1.7.1.9 FCP Vserver Routes
The following section provides the Routes information in PHARMAX-HQ.
+| Destination | Gateway | Metric | Address Family |
+| 0.0.0.0/0 | 172.23.4.254 | 20 | ipv4 |
+
+
Table 41 - Network Route - FCP
+1.7.1.10 ISCSI Vserver Routes
The following section provides the Routes information in PHARMAX-HQ.
+| Destination | Gateway | Metric | Address Family |
+| 0.0.0.0/0 | 172.23.4.254 | 20 | ipv4 |
+
+
Table 42 - Network Route - ISCSI
+1.7.1.11 NFS Vserver Routes
The following section provides the Routes information in PHARMAX-HQ.
+| Destination | Gateway | Metric | Address Family |
+| 0.0.0.0/0 | 192.168.5.254 | 20 | ipv4 |
-
Table 25 - Cluster Network - PHARMAX-HQ
-Management Network Interfaces
+Table 43 - Network Route - NFS
+1.7.1.12 Network Interfaces
The following section provides the Network Interfaces information in PHARMAX-HQ.
Cluster Network Interfaces
+| Cluster Interface | Status | Data Protocols | Address | Vserver |
+| cluster-01_clus1 | UP | none | 169.254.151.103 | Cluster |
+| cluster-01_clus2 | UP | none | 169.254.57.24 | Cluster |
+| cluster-02_clus1 | UP | none | 169.254.184.148 | Cluster |
+| cluster-02_clus2 | UP | none | 169.254.13.197 | Cluster |
+| cluster-03_clus1 | UP | none | 169.254.34.254 | Cluster |
+| cluster-03_clus2 | UP | none | 169.254.80.188 | Cluster |
+| cluster-04_clus1 | UP | none | 169.254.57.87 | Cluster |
+| cluster-04_clus2 | UP | none | 169.254.141.194 | Cluster |
+
+
Table 44 - Cluster Network - PHARMAX-HQ
+Management Network Interfaces
| MGMT Interface | Status | Data Protocols | Address | Vserver |
| cluster_mgmt | UP | none | 192.168.7.60 | PHARMAX-HQ |
-| PHARMAX-HQ-01_mgmt1 | UP | none | 192.168.7.61 | PHARMAX-HQ |
-| PHARMAX-HQ-02_mgmt1 | UP | none | 192.168.7.62 | PHARMAX-HQ |
+| cluster-01_mgmt1 | UP | none | 192.168.7.61 | PHARMAX-HQ |
+| cluster-02_mgmt1 | UP | none | 192.168.7.62 | PHARMAX-HQ |
+| cluster-03_mgmt1 | UP | none | 192.168.7.63 | PHARMAX-HQ |
+| cluster-04_mgmt1 | UP | none | 192.168.7.64 | PHARMAX-HQ |
-
Table 26 - Management Network - PHARMAX-HQ
-Intercluster Network Interfaces
+Table 45 - Management Network - PHARMAX-HQ
+Intercluster Network Interfaces
| Intercluster Interface | Status | Data Protocols | Address | Vserver |
-| PHARMAX-HQ-01_replication01 | UP | none | 192.168.11.61 | PHARMAX-HQ |
-| PHARMAX-HQ-02_replication01 | UP | none | 192.168.11.62 | PHARMAX-HQ |
+| lif_Default_2276 | UP | none | 192.168.11.63 | PHARMAX-HQ |
+| lif_Default_374 | UP | none | 192.168.11.64 | PHARMAX-HQ |
+| lif_Default_7971 | UP | none | 192.168.11.61 | PHARMAX-HQ |
+| lif_Default_8739 | UP | none | 192.168.11.62 | PHARMAX-HQ |
-
Table 27 - Intercluster Network - PHARMAX-HQ
-Data Network Interfaces
+Table 46 - Intercluster Network - PHARMAX-HQ
+Data Network Interfaces
| Data Interface | Status | Data Protocols | Address | Vserver |
-| PHARMAX-HQ-01_nas01 | UP | nfs cifs fcache | 192.168.7.63 | NAS |
-| PHARMAX-HQ-02_nas01 | UP | nfs cifs fcache | 192.168.7.64 | NAS |
-| PHARMAX-HQ-01_iscsia01 | UP | iscsi | 192.168.6.61 | SAN |
-| PHARMAX-HQ-01_iscsib01 | UP | iscsi | 192.168.12.61 | SAN |
-| PHARMAX-HQ-02_iscsia01 | UP | iscsi | 192.168.6.62 | SAN |
-| PHARMAX-HQ-02_iscsib01 | UP | iscsi | 192.168.12.62 | SAN |
-
-
Table 28 - Data Network - PHARMAX-HQ
-1.7 Vserver Information
The following section provides a summary of the vserver information on PHARMAX-HQ.
1.7.1 NAS Vserver Configuration
The following section provides the configuration of the vserver NAS.
+| lif_CIFS_1728 | UP | cifs | 172.23.4.102 | CIFS |
+| lif_CIFS_2101 | UP | cifs | 172.23.4.103 | CIFS |
+| lif_CIFS_3310 | UP | cifs | 172.23.4.101 | CIFS |
+| lif_CIFS_4245 | UP | none | 172.23.4.105 | CIFS |
+| lif_CIFS_4715 | UP | cifs | 172.23.4.104 | CIFS |
+| lif_FCP_1840 | UP | fcp | 20:07:00:50:56:b0:39:57 | FCP |
+| lif_FCP_206 | UP | fcp | 20:08:00:50:56:b0:39:57 | FCP |
+| lif_FCP_2670 | UP | fcp | 20:04:00:50:56:b0:39:57 | FCP |
+| lif_FCP_2920 | UP | fcp | 20:05:00:50:56:b0:39:57 | FCP |
+| lif_FCP_7769 | UP | fcp | 20:01:00:50:56:b0:39:57 | FCP |
+| lif_FCP_7889 | UP | fcp | 20:06:00:50:56:b0:39:57 | FCP |
+| lif_FCP_8085 | UP | none | 172.23.4.106 | FCP |
+| lif_FCP_8379 | UP | fcp | 20:03:00:50:56:b0:39:57 | FCP |
+| lif_FCP_8389 | UP | fcp | 20:02:00:50:56:b0:39:57 | FCP |
+| lif_ISCSI_253 | UP | iscsi | 192.168.6.102 | ISCSI |
+| lif_ISCSI_4091 | UP | iscsi | 192.168.6.101 | ISCSI |
+| lif_ISCSI_4260 | UP | iscsi | 192.168.12.102 | ISCSI |
+| lif_ISCSI_4837 | UP | none | 172.23.4.100 | ISCSI |
+| lif_ISCSI_6264 | UP | iscsi | 192.168.12.100 | ISCSI |
+| lif_ISCSI_6900 | UP | iscsi | 192.168.6.100 | ISCSI |
+| lif_ISCSI_7101 | UP | iscsi | 192.168.12.101 | ISCSI |
+| lif_ISCSI_8687 | UP | iscsi | 192.168.6.103 | ISCSI |
+| lif_ISCSI_8946 | UP | iscsi | 192.168.12.103 | ISCSI |
+| lif_NFS_331 | UP | nfs | 192.168.5.62 | NFS |
+| lif_NFS_6545 | UP | nfs | 192.168.5.61 | NFS |
+| lif_NFS_7087 | UP | nfs | 192.168.5.64 | NFS |
+| lif_NFS_9802 | UP | nfs | 192.168.5.63 | NFS |
+
+
Table 47 - Data Network - PHARMAX-HQ
+1.8 Vserver Information
The following section provides a summary of the vserver information in PHARMAX-HQ.
1.8.1 CIFS Vserver Configuration
The following section provides the configuration of the vserver CIFS.
| Vserver Type | Allowed Protocols | Disallowed Protocols | IPSpace | Status |
| data | nfs cifs fcp iscsi ndmp s3 | nvme | Default | running |
-
Table 29 - Information - NAS
-1.7.1.1 Root Volume
+Table 48 - Information - CIFS
+1.8.1.1 Root Volume
| Root Volume | Status | Total Size | Used | Available | Dedup | Aggregate |
-| NAS_root | online | 20 MB | 6% | 18 MB | No | PHARMAX_HQ_02_SSD_1 |
-
-
Table 30 - Root Volume - NAS
-1.7.1.2 Storage Volumes
+| CIFS_root | online | 20.0 MB | 5% | 17.9 MB | No | cluster_01_SSD_1 |
+
+
Table 49 - Root Volume - CIFS
+1.8.1.2 Interfaces (Lifs)
+| Data Interface | Status | Data Protocols | Address | Is Home |
+| lif_CIFS_1728 | UP | cifs | 172.23.4.102 | Yes |
+| lif_CIFS_2101 | UP | cifs | 172.23.4.103 | Yes |
+| lif_CIFS_3310 | UP | cifs | 172.23.4.101 | Yes |
+| lif_CIFS_4245 | UP | none | 172.23.4.105 | Yes |
+| lif_CIFS_4715 | UP | cifs | 172.23.4.104 | Yes |
+
+
Table 50 - Data Network - CIFS
+1.8.1.3 Storage Volumes
| Volume | Status | Capacity | Available | Used | Aggregate |
-| DATA | online | 20 GB | 13 GB | 29% | PHARMAX_HQ_01_SSD_1 |
-
-
Table 31 - Volume - NAS
-1.7.1.3 Volumes Snapshot Configuration
+| DATA | online | 10.5 GB | 10.0 GB | 0% | cluster_02_SSD_1 |
+| DATA_dest | online | 128.0 MB | 121.3 MB | 0% | cluster_03_SSD_1 |
+| Global_Documents | online | 21.1 GB | 19.5 GB | 2% | cluster_02_SSD_1 |
+
+
Table 51 - Volume - CIFS
+1.8.1.3.1 Per Volumes Export Policies
+| Volume Name | Export Policy |
+| DATA | default |
+| DATA_dest | default |
+| Global_Documents | default |
+
+
Table 52 - Per Volume Export Policy - CIFS
+1.8.1.3.2 Flexcache Volumes
+| Cache Cluster | Cache Vserver | Cache Volume | Origin Vserver | Origin Volume | Capacity |
+| PHARMAX-DR | NAS_DR | Global_Documents | CIFS | Global_Documents | 21.1 GB |
+
+
Table 53 - Flexcache Volume Connected Cache - CIFS
+1.8.1.4 Volumes Snapshot Configuration
| Volume | Snapshot Enabled | Reserve Size | Reserve Available | Used | Policy |
-| DATA | Yes | 1 GB | 1022 MB | 2 MB | default |
-
-
Table 32 - Volume SnapShot Configuration - NAS
-1.7.1.4 Protocol Information
The following section provides a summary of the Vserver protocol information on NAS.
1.7.1.4.1 CIFS Services Information
The following section provides the CIFS Service Information on NAS.
+| DATA | Yes | 538.9 MB | 536.6 MB | 2.4 MB | default |
+| DATA_dest | No | 6.4 MB | 6.2 MB | 188.0 KB | none |
+| Global_Documents | Yes | 1.1 GB | 1.1 GB | 2.4 MB | default |
+
+
Table 54 - Volume SnapShot Configuration - CIFS
+Health Check:
Best Practice: Snapshots are enabled on volumes but there is no available snapshot reserve space. It is recommended to increase the snapshot reserve size to avoid snapshot failures.
1.8.1.5 Qtrees
+| Qtree | Volume | Status | Security Style | Export Policy |
+| IT | DATA | normal | unix | default |
+| IT | DATA_dest | readonly | unix | default |
+
+
Table 55 - Volume Qtree - CIFS
+Health Check:
Best Practice: Ensure all qtrees are in 'normal' status to maintain data integrity and accessibility.
1.8.1.6 Volume Quota
CIFS Vserver Volume Quota Status
The following section provides the CIFS Volumes Quota Status Information in PHARMAX-HQ.
+| Volume | Status | Substatus |
+| CIFS_root | off | none |
+| DATA | on | none |
+| DATA_dest | off | none |
+| Global_Documents | off | none |
+
+
Table 56 - Volume Quota Status - CIFS
+1.8.1.7 Protocol Information
The following section provides a summary of the Vserver protocol information in CIFS.
1.8.1.7.1 CIFS Services Information
The following section provides the CIFS Service Information in CIFS.
-| Node Name | PHARMAX-HQ-01 |
+| Node Name | cluster-01 |
| Cifs Domain Name | pharmax.local |
-| Cifs NetBios Name | NAS |
+| Cifs NetBios Name | CIFS |
| Cifs Domain IP | 192.168.7.1 |
-| AD Server Site | |
+| AD Server Site | -- |
| Cifs Server Status | Running |
-| Status Details | Response time (msec): 2016 |
+| Status Details | Response time (msec): 4027 |
| Status | up |
-
Table 33 - CIFS Service - PHARMAX-HQ-01
+Table 57 - CIFS Service - cluster-01
-| Node Name | PHARMAX-HQ-02 |
+| Node Name | cluster-02 |
| Cifs Domain Name | pharmax.local |
-| Cifs NetBios Name | NAS |
-| Cifs Domain IP | 192.168.7.1 |
-| AD Server Site | |
+| Cifs NetBios Name | CIFS |
+| Cifs Domain IP | 192.168.5.1 |
+| AD Server Site | -- |
| Cifs Server Status | Running |
-| Status Details | Response time (msec): 2015 |
+| Status Details | Response time (msec): 9 |
| Status | up |
-
Table 34 - CIFS Service - PHARMAX-HQ-02
-CIFS Local Group
+Table 58 - CIFS Service - cluster-02
+
+
+| Node Name | cluster-03 |
+| Cifs Domain Name | pharmax.local |
+| Cifs NetBios Name | CIFS |
+| Cifs Domain IP | 192.168.5.1 |
+| AD Server Site | -- |
+| Cifs Server Status | Running |
+| Status Details | Response time (msec): 9 |
+| Status | up |
+
+
Table 59 - CIFS Service - cluster-03
+
+
+| Node Name | cluster-04 |
+| Cifs Domain Name | pharmax.local |
+| Cifs NetBios Name | CIFS |
+| Cifs Domain IP | 192.168.5.1 |
+| AD Server Site | -- |
+| Cifs Server Status | Running |
+| Status Details | Response time (msec): 8 |
+| Status | up |
+
+
Table 60 - CIFS Service - cluster-04
+CIFS Local Group
| Group Name | Description |
| BUILTIN\Administrators | Built-in Administrators group |
| BUILTIN\Backup Operators | Backup Operators group |
@@ -451,162 +897,413 @@
| BUILTIN\Power Users | Restricted administrative privileges |
| BUILTIN\Users | All users |
-
Table 35 - CIFS Connected Local Group - NAS
-CIFS Local Group Members
+Table 61 - CIFS Connected Local Group - CIFS
+CIFS Local Group Members
| Group Name | Description |
-| BUILTIN\Administrators | NAS\Administrator |
+| BUILTIN\Administrators | CIFS\Administrator |
| BUILTIN\Administrators | PHARMAX\Domain Admins |
| BUILTIN\Guests | PHARMAX\Domain Guests |
| BUILTIN\Users | PHARMAX\Domain Users |
-
Table 36 - CIFS Connected Local Group Members - NAS
-CIFS Share
+Table 62 - CIFS Connected Local Group Members - CIFS
+CIFS Share
| Share Name | Volume | Path |
-| c$ | NAS_root | / |
+| c$ | CIFS_root | / |
| DATA | DATA | /DATA |
-| ipc$ | NAS_root | / |
+| Global_Documents | Global_Documents | /Global_Documents |
+| ipc$ | CIFS_root | / |
-
Table 37 - CIFS Share - NAS
-CIFS Share Configuration
+Table 63 - CIFS Share - CIFS
+CIFS Share Configuration
| Share Name | Share ACL | Share Properties |
| c$ | BUILTIN\Administrators / Full Control | oplocks, browsable, changenotify, show_previous_versions |
-| DATA | Everyone / Full Control | oplocks, browsable, changenotify, show_previous_versions |
-| ipc$ | | browsable |
+| DATA | Everyone / Full Control | oplocks, browsable, showsnapshot, changenotify, continuously_available, access_based_enumeration, encrypt_data, show_previous_versions |
+| Global_Documents | Everyone / Full Control | browsable, show_previous_versions, oplocks, changenotify |
+| ipc$ | -- | browsable |
-
Table 38 - The CIFS Share Properties & Acl - NAS
-1.7.2 SAN Vserver Configuration
The following section provides the configuration of the vserver SAN.
+Table 64 - The CIFS Share Properties & Acl - CIFS
+1.8.2 FCP Vserver Configuration
The following section provides the configuration of the vserver FCP.
| Vserver Type | Allowed Protocols | Disallowed Protocols | IPSpace | Status |
| data | nfs cifs fcp iscsi ndmp s3 | nvme | Default | running |
-
Table 39 - Information - SAN
-1.7.2.1 Root Volume
+Table 65 - Information - FCP
+1.8.2.1 Root Volume
| Root Volume | Status | Total Size | Used | Available | Dedup | Aggregate |
-| SAN_root | online | 20 MB | 7% | 18 MB | No | PHARMAX_HQ_02_SSD_1 |
+| FCP_root | online | 20.0 MB | 7% | 17.6 MB | No | cluster_04_SSD_1 |
+
+
Table 66 - Root Volume - FCP
+1.8.2.2 Interfaces (Lifs)
+| Data Interface | Status | Data Protocols | Address | Is Home |
+| lif_FCP_1840 | UP | fcp | 20:07:00:50:56:b0:39:57 | Yes |
+| lif_FCP_206 | UP | fcp | 20:08:00:50:56:b0:39:57 | Yes |
+| lif_FCP_2670 | UP | fcp | 20:04:00:50:56:b0:39:57 | Yes |
+| lif_FCP_2920 | UP | fcp | 20:05:00:50:56:b0:39:57 | Yes |
+| lif_FCP_7769 | UP | fcp | 20:01:00:50:56:b0:39:57 | Yes |
+| lif_FCP_7889 | UP | fcp | 20:06:00:50:56:b0:39:57 | Yes |
+| lif_FCP_8085 | UP | none | 172.23.4.106 | Yes |
+| lif_FCP_8379 | UP | fcp | 20:03:00:50:56:b0:39:57 | Yes |
+| lif_FCP_8389 | UP | fcp | 20:02:00:50:56:b0:39:57 | Yes |
+
+
Table 67 - Data Network - FCP
+1.8.2.3 Protocol Information
The following section provides a summary of the Vserver protocol information in FCP.
1.8.2.3.1 FCP Services Information
The following section provides the FCP Service Information in FCP.
+| FCP WWNN | Status |
+| 20:00:00:50:56:b0:39:57 | Up |
+
+
Table 68 - FCP Service - FCP
+FCP Physical Adapter
+| Node Name | Adapter | Protocol | Speed | Status |
+| cluster-01 | 0a | fibre_channel | auto | Up |
+| cluster-01 | 0b | fibre_channel | auto | Up |
+| cluster-01 | 0e | fibre_channel | auto | Up |
+| cluster-01 | 0f | fibre_channel | auto | Up |
+| cluster-01 | 1a | fibre_channel | auto | Up |
+| cluster-01 | 1b | fibre_channel | auto | Up |
+| cluster-02 | 0a | fibre_channel | auto | Up |
+| cluster-02 | 0b | fibre_channel | auto | Up |
+| cluster-02 | 0e | fibre_channel | auto | Up |
+| cluster-02 | 0f | fibre_channel | auto | Up |
+| cluster-02 | 1a | fibre_channel | auto | Up |
+| cluster-02 | 1b | fibre_channel | auto | Up |
+| cluster-03 | 0a | fibre_channel | auto | Up |
+| cluster-03 | 0b | fibre_channel | auto | Up |
+| cluster-03 | 0e | fibre_channel | auto | Up |
+| cluster-03 | 0f | fibre_channel | auto | Up |
+| cluster-03 | 1a | fibre_channel | auto | Up |
+| cluster-03 | 1b | fibre_channel | auto | Up |
+| cluster-04 | 0a | fibre_channel | auto | Up |
+| cluster-04 | 0b | fibre_channel | auto | Up |
+| cluster-04 | 0e | fibre_channel | auto | Up |
+| cluster-04 | 0f | fibre_channel | auto | Up |
+| cluster-04 | 1a | fibre_channel | auto | Up |
+| cluster-04 | 1b | fibre_channel | auto | Up |
+
+
Table 69 - FCP Physical Adapter - PHARMAX-HQ
+FCP Interfaces
+| Interface Name | FCP WWPN | Node Name | Home Port |
+| lif_FCP_7769 | 20:01:00:50:56:b0:39:57 | cluster-01 | 0a |
+| lif_FCP_8389 | 20:02:00:50:56:b0:39:57 | cluster-01 | 0b |
+| lif_FCP_2670 | 20:04:00:50:56:b0:39:57 | cluster-02 | 0b |
+| lif_FCP_8379 | 20:03:00:50:56:b0:39:57 | cluster-02 | 0a |
+| lif_FCP_2920 | 20:05:00:50:56:b0:39:57 | cluster-03 | 0a |
+| lif_FCP_7889 | 20:06:00:50:56:b0:39:57 | cluster-03 | 0b |
+| lif_FCP_1840 | 20:07:00:50:56:b0:39:57 | cluster-04 | 0a |
+| lif_FCP_206 | 20:08:00:50:56:b0:39:57 | cluster-04 | 0b |
+
+
Table 70 - FCP Interface - FCP
+1.8.3 ISCSI Vserver Configuration
The following section provides the configuration of the vserver ISCSI.
+| Vserver Type | Allowed Protocols | Disallowed Protocols | IPSpace | Status |
+| data | nfs cifs fcp iscsi ndmp s3 | nvme | Default | running |
-
Table 40 - Root Volume - SAN
-1.7.2.2 Storage Volumes
+Table 71 - Information - ISCSI
+1.8.3.1 Root Volume
+| Root Volume | Status | Total Size | Used | Available | Dedup | Aggregate |
+| ISCSI_root | online | 20.0 MB | 6% | 17.7 MB | No | cluster_03_SSD_1 |
+
+
Table 72 - Root Volume - ISCSI
+1.8.3.2 Aggregate Resource Allocation
+| Aggregate | Type | SnapLock Type | Available |
+| cluster_03_SSD_1 | ssd | non_snaplock | 60.4 GB |
+| cluster_04_SSD_1 | ssd | non_snaplock | 42.9 GB |
+
+
Table 73 - Aggregate Resource Allocation - ISCSI
+1.8.3.3 Interfaces (Lifs)
+| Data Interface | Status | Data Protocols | Address | Is Home |
+| lif_ISCSI_253 | UP | iscsi | 192.168.6.102 | Yes |
+| lif_ISCSI_4091 | UP | iscsi | 192.168.6.101 | Yes |
+| lif_ISCSI_4260 | UP | iscsi | 192.168.12.102 | Yes |
+| lif_ISCSI_4837 | UP | none | 172.23.4.100 | Yes |
+| lif_ISCSI_6264 | UP | iscsi | 192.168.12.100 | Yes |
+| lif_ISCSI_6900 | UP | iscsi | 192.168.6.100 | Yes |
+| lif_ISCSI_7101 | UP | iscsi | 192.168.12.101 | Yes |
+| lif_ISCSI_8687 | UP | iscsi | 192.168.6.103 | Yes |
+| lif_ISCSI_8946 | UP | iscsi | 192.168.12.103 | Yes |
+
+
Table 74 - Data Network - ISCSI
+1.8.3.4 Storage Volumes
| Volume | Status | Capacity | Available | Used | Aggregate |
-| SQL_DATA | online | 13 GB | 2 GB | 84% | PHARMAX_HQ_01_SSD_1 |
+| DB | online | 11.9 GB | 1.9 GB | 84% | cluster_04_SSD_1 |
+
+
Table 75 - Volume - ISCSI
+Health Check:
Best Practice: Ensure all volumes are below 95% usage to prevent capacity issues.
1.8.3.4.1 Per Volumes Export Policies
+| Volume Name | Export Policy |
+| DB | default |
-
Table 41 - Volume - SAN
-1.7.2.3 Volumes Snapshot Configuration
+Table 76 - Per Volume Export Policy - ISCSI
+1.8.3.5 Volumes Snapshot Configuration
| Volume | Snapshot Enabled | Reserve Size | Reserve Available | Used | Policy |
-| SQL_DATA | Yes | 643 MB | 637 MB | 6 MB | default |
+| DB | No | 0 | 0 | 196.0 KB | none |
-
Table 42 - Volume SnapShot Configuration - SAN
-1.7.2.4 Protocol Information
The following section provides a summary of the Vserver protocol information on SAN.
1.7.2.4.1 ISCSI Services
The following section provides the ISCSI Service Information on SAN.
+Table 77 - Volume SnapShot Configuration - ISCSI
+1.8.3.6 Protocol Information
The following section provides a summary of the Vserver protocol information in ISCSI.
1.8.3.6.1 ISCSI Services
The following section provides the ISCSI Service Information in ISCSI.
-| IQN Name | iqn.1992-08.com.netapp:sn.5971f5526fe011f0aa34005056b06182:vs.3 |
-| Alias Name | SAN |
+| IQN Name | iqn.1992-08.com.netapp:sn.eb7e8829d2ff11f0bea5005056b09767:vs.6 |
+| Alias Name | ISCSI |
| Tcp Window Size | 131400 |
| Max Cmds Per Session | 128 |
| Max Conn Per Session | 4 |
| Login Timeout | 15 |
| Status | Up |
-
Table 43 - ISCSI Service - SAN
-ISCSI Interfaces
+Table 78 - ISCSI Service - ISCSI
+ISCSI Interfaces
| Interface Name | IP Address | Port | Status |
-| PHARMAX-HQ-01_iscsia01 | 192.168.6.61 | 3260 | Up |
-| PHARMAX-HQ-01_iscsib01 | 192.168.12.61 | 3260 | Up |
-| PHARMAX-HQ-02_iscsia01 | 192.168.6.62 | 3260 | Up |
-| PHARMAX-HQ-02_iscsib01 | 192.168.12.62 | 3260 | Up |
-
-
Table 44 - ISCSI Interface - SAN
-1.7.2.4.2 Lun Storage
The following section provides the Lun Storage Information on SAN.
+| lif_ISCSI_253 | 192.168.6.102 | 3260 | Up |
+| lif_ISCSI_4091 | 192.168.6.101 | 3260 | Up |
+| lif_ISCSI_4260 | 192.168.12.102 | 3260 | Up |
+| lif_ISCSI_6264 | 192.168.12.100 | 3260 | Up |
+| lif_ISCSI_6900 | 192.168.6.100 | 3260 | Up |
+| lif_ISCSI_7101 | 192.168.12.101 | 3260 | Up |
+| lif_ISCSI_8687 | 192.168.6.103 | 3260 | Up |
+| lif_ISCSI_8946 | 192.168.12.103 | 3260 | Up |
+
+
Table 79 - ISCSI Interface - ISCSI
+1.8.3.6.2 Lun Storage
The following section provides the Lun Storage Information in ISCSI.
-| Lun Name | SQL_DATA |
-| Parent Volume | SQL_DATA |
-| Path | /vol/SQL_DATA/SQL_DATA |
-| Serial Number | wpRkN]Yhbtn8 |
+| Lun Name | DB |
+| Parent Volume | DB |
+| Path | /vol/DB/DB |
+| Serial Number | wp/Ie$ZKGTlF |
| Initiator Group | SQLLun |
-| Home Node | PHARMAX-HQ-01 |
-| Capacity | 10 GB |
-| Available | 10 GB |
+| Home Node | cluster-04 |
+| Capacity | 10.0 GB |
+| Available | 10.0 GB |
| Used | 0% |
| OS Type | windows_2008 |
| Is Thin | No |
| Space Allocation | Enabled |
| Space Reservation | Enabled |
| Is Mapped | Yes |
-| Status | Up |
+| Status | Down |
-
Table 45 - Lun - SQL_DATA
-Igroup Mapping
+Table 80 - Lun - DB
+Health Check:
Best Practice: Ensure that all LUNs are operational to maintain optimal storage connectivity.
Igroup Mapping
| Igroup Name | SQLLun |
| Type | windows |
| Protocol | mixed |
| Initiators | iqn.1991-05.com.microsoft:server-dc-01v.pharmax.local |
-| Mapped Lun | SQL_DATA |
-| Reporting Nodes | PHARMAX-HQ-01 PHARMAX-HQ-02 |
+| Mapped Lun | DB |
+| Reporting Nodes | None |
+
+
Table 81 - Igroup - SQLLun
+1.8.4 NFS Vserver Configuration
The following section provides the configuration of the vserver NFS.
+| Vserver Type | Allowed Protocols | Disallowed Protocols | IPSpace | Status |
+| data | nfs cifs fcp iscsi ndmp s3 | nvme | Default | running |
-
Table 46 - Igroup - SQLLun
-1.8 Replication Information
The following section provides a summary of the replication information on PHARMAX-HQ.
1.8.1 Cluster Replication Diagram
-

+
Table 82 - Information - NFS
+1.8.4.1 Root Volume
+| Root Volume | Status | Total Size | Used | Available | Dedup | Aggregate |
+| NFS_root | online | 20.0 MB | 7% | 17.6 MB | No | cluster_01_SSD_1 |
+
+
Table 83 - Root Volume - NFS
+1.8.4.2 Interfaces (Lifs)
+| Data Interface | Status | Data Protocols | Address | Is Home |
+| lif_NFS_331 | UP | nfs | 192.168.5.62 | Yes |
+| lif_NFS_6545 | UP | nfs | 192.168.5.61 | Yes |
+| lif_NFS_7087 | UP | nfs | 192.168.5.64 | Yes |
+| lif_NFS_9802 | UP | nfs | 192.168.5.63 | Yes |
+
+
Table 84 - Data Network - NFS
+1.8.4.3 Export Policies
+| Policy Name | Rule Index | Client Match | Protocol | Ro Rule | Rw Rule |
+| DAS | 1 | 0.0.0.0/0 | any | any | never |
+| VM_DataStore | 1 | 0.0.0.0/0 | any | any | any |
+| VM_DataStore | 2 | 192.168.5.253 | nfs3, nfs4, nfs | never | any |
+
+
Table 85 - Export Policies - NFS
+1.8.4.4 Storage Volumes
+| Volume | Status | Capacity | Available | Used | Aggregate |
+| DAS | online | 10.0 GB | 9.5 GB | 0% | cluster_01_SSD_1 |
+| DAS_clone_515 | online | 1.1 GB | 1023.5 MB | 0% | cluster_01_SSD_1 |
+| DATA1 | online | 20.0 GB | 19.0 GB | 0% | cluster_04_SSD_1 |
+| DBs_dest | online | 128.0 MB | 121.3 MB | 0% | cluster_01_SSD_1 |
+| VM_DataStore | online | 30.0 GB | 28.5 GB | 0% | cluster_03_SSD_1 |
+
+
Table 86 - Volume - NFS
+1.8.4.4.1 Per Volumes Export Policies
+| Volume Name | Export Policy |
+| DAS | DAS |
+| DAS_clone_515 | DAS |
+| DATA1 | default |
+| DBs_dest | default |
+| VM_DataStore | default |
+
+
Table 87 - Per Volume Export Policy - NFS
+1.8.4.4.2 Flexclone Volumes
+
+| Volume | DAS_clone_515 |
+| Parent Volume | DAS |
+| Volume Type | RW |
+| Parent Snapshot | clone_DAS_clone_515.2025-12-21_214319.0 |
+| Space Reserve | none |
+| Space Guarantee | Yes |
+| Capacity | 1.1 GB |
+| Available | 1.1 GB |
+| Used | 480.0 KB |
+| Aggregate | cluster_01_SSD_1 |
+
+
Table 88 - Cloned Volumes - DAS_clone_515
+Health Check:
Best Practice: Regularly monitor flexclone volumes to manage storage utilization effectively.
1.8.4.5 Volumes Snapshot Configuration
+| Volume | Snapshot Enabled | Reserve Size | Reserve Available | Used | Policy |
+| DAS | Yes | 512.0 MB | 510.0 MB | 2.0 MB | default |
+| DAS_clone_515 | Yes | 53.9 MB | 51.2 MB | 2.7 MB | default |
+| DATA1 | Yes | 1.0 GB | 1023.0 MB | 1.0 MB | default |
+| DBs_dest | No | 6.4 MB | 6.2 MB | 188.0 KB | none |
+| VM_DataStore | Yes | 1.5 GB | 1.5 GB | 2.4 MB | default |
+
+
Table 89 - Volume SnapShot Configuration - NFS
+Health Check:
Best Practice: Snapshots are enabled on volumes but there is no available snapshot reserve space. It is recommended to increase the snapshot reserve size to avoid snapshot failures.
1.8.4.5.1 HealthCheck - Volumes Snapshot
The following section provides the Vserver Volumes Snapshot HealthCheck in NFS.
+| Volume Name | Snapshot Name | Created Time | Used |
+| DAS | clone_DAS_clone_515.2025-12-21_214319.0 | 12/21/2025 21:43:19 | 200.0 KB |
+| DAS_clone_515 | clone_DAS_clone_515.2025-12-21_214319.0 | 12/21/2025 21:43:19 | 204.0 KB |
+
+
Table 90 - HealthCheck - Volume Snapshot over 30 days - NFS
+1.8.4.6 Protocol Information
The following section provides a summary of the Vserver protocol information in NFS.
1.8.4.6.1 NFS Services
The following section provides the NFS Service Information in NFS.
+| Nfs v3 | Nfs v4 | Nfs v41 | General Access |
+| Enabled | Enabled | Enabled | Yes |
+
+
Table 91 - NFS Service - PHARMAX-HQ
+NFS Volume Export
+| Path Name | Export Policy |
+| /DAS | DAS |
+| /vol/DAS | None |
+| /vol/DAS_clone_515 | None |
+
+
Table 92 - NFS Service Volume Export - NFS
+1.9 Replication Information
The following section provides a summary of the replication information in PHARMAX-HQ.
1.9.1 Cluster Replication Diagram
+
-Image preview: Opens the image in a new tab to view it at full resolution.
1.8.2 Cluster Peer
The following section provides the Cluster Peer information on PHARMAX-HQ.
+1.9.2 Cluster Peer
The following section provides the Cluster Peer information in PHARMAX-HQ.
| Cluster Peer | Cluster Nodes | Peer Addresses | Cluster Health | IP Space | Status |
-| PHARMAX-DR | PHARMAX-DR-01 | 10.10.36.14 | True | Default | available |
-| PHARMAX-EDGE | PHARMAX-EDGE-01 | 172.23.9.14 | True | Default | available |
+| PHARMAX-DR | cluster-dr-01 | 192.168.11.70 | Yes | Default | available |
-
Table 47 - Cluster Peer - PHARMAX-HQ
-1.8.3 Vserver Peer
+Table 93 - Cluster Peer - PHARMAX-HQ
+1.9.3 Vserver Peer
| Vserver | Peer Vserver | Peer Cluster | Applications | Peer State |
-| NAS | NAS-EDGE | PHARMAX-EDGE | snapmirror flexcache | peered |
-| SAN | SAN_DR | PHARMAX-DR | snapmirror flexcache | peered |
+| CIFS | NAS_DR | PHARMAX-DR | snapmirror flexcache | peered |
+| ISCSI | NAS_DR | PHARMAX-DR | snapmirror | peered |
+| NFS | NAS_DR | PHARMAX-DR | snapmirror flexcache | peered |
-
Table 48 - Peer - PHARMAX-HQ
-1.8.3.1 SnapMirror Destinations
+Table 94 - Peer - PHARMAX-HQ
+1.9.3.1 SnapMirror Relationship
-| Destination Vserver | NAS-EDGE |
-| Destination Location | NAS-EDGE:DATA |
-| Source Vserver | NAS |
-| Source Location | NAS:DATA |
+| Source Vserver | CIFS |
+| Source Location | CIFS:DATA |
+| Destination Vserver | CIFS |
+| Destination Location | CIFS:DATA_dest |
+| Mirror State | snapmirrored |
+| Schedule | -- |
| Relationship Type | XDP |
+| Policy | MirrorLatest |
| Policy Type | async_mirror |
-| Status | Unknown |
+| Unhealthy Reason | None |
+| Lag Time | 1 days, 21 hrs, 53 mins, 1 secs |
+| Status | IDLE |
-
Table 49 - SnapMirror Destination (List-Destinations) - NAS-EDGE:DATA
+Table 95 - SnapMirror relationship - CIFS:DATA
-| Destination Vserver | SAN_DR |
-| Destination Location | SAN_DR:SQL_DATA_dest |
-| Source Vserver | SAN |
-| Source Location | SAN:SQL_DATA |
+| Source Vserver | NAS_DR |
+| Source Location | NAS_DR:DBs |
+| Destination Vserver | NFS |
+| Destination Location | NFS:DBs_dest |
+| Mirror State | snapmirrored |
+| Schedule | -- |
+| Relationship Type | XDP |
+| Policy | MirrorLatest |
+| Policy Type | async_mirror |
+| Unhealthy Reason | None |
+| Lag Time | 1 days, 21 hrs, 50 mins, 1 secs |
+| Status | IDLE |
+
+
Table 96 - SnapMirror relationship - NAS_DR:DBs
+1.9.3.2 SnapMirror Destinations
+
+| Destination Vserver | CIFS |
+| Destination Location | CIFS:DATA_dest |
+| Source Vserver | CIFS |
+| Source Location | CIFS:DATA |
+| Relationship Type | XDP |
+| Policy Type | async_mirror |
+| Status | Unknown |
+
+
Table 97 - SnapMirror Destination (List-Destinations) - CIFS:DATA_dest
+Health Check:
Best Practice: Ensure that all SnapMirror relationships have a known status to maintain replication integrity.
+
+| Destination Vserver | NAS_DR |
+| Destination Location | NAS_DR:DB_dest2 |
+| Source Vserver | ISCSI |
+| Source Location | ISCSI:DB |
| Relationship Type | XDP |
| Policy Type | mirror_vault |
| Status | idle |
-
Table 50 - SnapMirror Destination (List-Destinations) - SAN_DR:SQL_DATA_dest
-1.9 Efficiency Information
The following section provides the Storage Efficiency Saving information on PHARMAX-HQ.
+Table 98 - SnapMirror Destination (List-Destinations) - NAS_DR:DB_dest2
+1.10 Efficiency Information
The following section provides the Storage Efficiency Saving information in PHARMAX-HQ.
| Aggregate | Used % | Capacity Tier Used | Compaction Saved % | Deduplication Saved % | Total Data Reduction |
-| PHARMAX_HQ_01_SSD_1 | 38% | 0 | 0% | 0% | 10.99:1 |
-| PHARMAX_HQ_02_SSD_1 | 0% | 0 | 0% | 0% | 1.91:1 |
+| cluster_01_SSD_1 | 11% | 0 | 0% | 0% | 1.24:1 |
+| cluster_02_SSD_1 | 42% | 0 | 0% | 0% | 4.05:1 |
+| cluster_03_SSD_1 | 33% | 0 | 0% | 0% | 2.34:1 |
+| cluster_04_SSD_1 | 43% | 0 | 0% | 0% | 2.20:1 |
-
Table 51 - Storage Efficiency Savings - PHARMAX-HQ
-1.9.1 Aggregate Total Efficiency
The following section provides the Aggregate Efficiency Saving information on PHARMAX-HQ.
+Table 99 - Storage Efficiency Savings - PHARMAX-HQ
+1.10.1 Aggregate Total Efficiency
The following section provides the Aggregate Efficiency Saving information in PHARMAX-HQ.
| Aggregate | Logical Used | Physical Used | Compaction Saved | Data Reduction |
-| PHARMAX_HQ_01_SSD_1 | 6 GB | 6 GB | | 1.00:1 |
-| PHARMAX_HQ_02_SSD_1 | 4 MB | 4 MB | | 1.00:1 |
+| cluster_01_SSD_1 | 16.6 MB | 16.6 MB | -- | 1.00:1 |
+| cluster_02_SSD_1 | 12.8 MB | 12.8 MB | -- | 1.00:1 |
+| cluster_03_SSD_1 | 5.6 MB | 5.6 MB | -- | 1.00:1 |
+| cluster_04_SSD_1 | 4.2 MB | 4.2 MB | -- | 1.00:1 |
-
Table 52 - Aggregate Efficiency Savings - PHARMAX-HQ
-1.9.1.1 HealthCheck - Volume with Disabled Deduplication
The following table provides the Volume efficiency healthcheck Information on PHARMAX-HQ.
+Table 100 - Aggregate Efficiency Savings - PHARMAX-HQ
+1.10.1.1 HealthCheck - Volume with Disabled Deduplication
The following table provides the Volume efficiency healthcheck Information in PHARMAX-HQ.
| Aggregate | Volumes without Deduplication |
-| PHARMAX_HQ_01_SSD_1 | DATA, SQL_DATA |
-
-
Table 53 - HealthCheck - Volume without deduplication - PHARMAX-HQ
-1.9.1.2 NAS Vserver Volume Deduplication
1.9.1.2.1 Volume Efficiency
+| cluster_01_SSD_1 | DAS, DAS_clone_515 |
+| cluster_03_SSD_1 | VM_DataStore |
+| cluster_04_SSD_1 | DB, DATA1 |
+
+
Table 101 - HealthCheck - Volume without deduplication - PHARMAX-HQ
+Health Check:
Best Practice: Ensure that deduplication is enabled on all volumes to maximize storage efficiency.
1.10.1.2 CIFS Vserver Volume Deduplication
+| Volume | State | Status | Schedule Or Policy | Progress |
+| DATA | Disabled | idle | auto | Idle for 726:15:54 |
+| DATA_dest | Enabled | idle | - | Idle for 45:53:27 |
+| Global_Documents | Disabled | idle | auto | Idle for 1411:48:56 |
+
+
Table 102 - Volume Deduplication - CIFS
+Health Check:
Best Practice: Ensure that volume deduplication is enabled on volumes where data reduction is beneficial to optimize storage efficiency.
1.10.1.2.1 Volume Efficiency
| Volume | Capacity | Used | Snapshot Used | Total Savings | Effective Used | Efficiency Percent |
-| DATA | 19 GB | 6 GB | 2 MB | 6 GB | 11 GB | 59.9% |
+| DATA | 10.0 GB | 7.7 MB | 2.4 MB | 7.5 MB | 15.3 MB | 0.1% |
+| DATA_dest | 121.6 MB | 356.0 KB | 188.0 KB | 168.0 KB | 524.0 KB | 0.4% |
+| Global_Documents | 20.0 GB | 513.1 MB | 2.4 MB | 512.9 MB | 1.0 GB | 5.0% |
-
Table 54 - Volume Efficiency Savings - NAS
-1.9.1.3 SAN Vserver Volume Deduplication
1.9.1.3.1 Volume Efficiency
-| Volume | Capacity | Used | Snapshot Used | Total Savings | Effective Used | Efficiency Percent |
-| SQL_DATA | 12 GB | 10 GB | 6 MB | 10 GB | 20 GB | 168.3% |
+Table 103 - Volume Efficiency Savings - CIFS
+1.10.1.3 ISCSI Vserver Volume Deduplication
+| Volume | State | Status | Schedule Or Policy | Progress |
+| DB | Disabled | idle | auto | Idle for 1413:08:28 |
-
Table 55 - Volume Efficiency Savings - SAN
-1.10 Security Information
The following section provides the Security related information on PHARMAX-HQ.
1.10.1 PHARMAX-HQ Vserver Local User
The following section provides the Local User information on PHARMAX-HQ.
+Table 104 - Volume Deduplication - ISCSI
+Health Check:
Best Practice: Ensure that volume deduplication is enabled on volumes where data reduction is beneficial to optimize storage efficiency.
1.10.1.3.1 Volume Efficiency
+| Volume | Capacity | Used | Snapshot Used | Total Savings | Effective Used | Efficiency Percent |
+| DB | 11.9 GB | 10.0 GB | 196.0 KB | 10.0 GB | 20.1 GB | 168.3% |
+
+
Table 105 - Volume Efficiency Savings - ISCSI
+1.10.1.4 NFS Vserver Volume Deduplication
+| Volume | State | Status | Schedule Or Policy | Progress |
+| DAS | Disabled | idle | auto | Idle for 1051:42:04 |
+| DAS_clone_515 | Disabled | idle | auto | Idle for 1051:42:04 |
+| DBs_dest | Enabled | idle | - | Idle for 45:49:39 |
+| VM_DataStore | Disabled | idle | auto | Idle for 1413:11:35 |
+
+
Table 106 - Volume Deduplication - NFS
+Health Check:
Best Practice: Ensure that volume deduplication is enabled on volumes where data reduction is beneficial to optimize storage efficiency.
1.10.1.4.1 Volume Efficiency
+| Volume | Capacity | Used | Snapshot Used | Total Savings | Effective Used | Efficiency Percent |
+| DAS | 9.5 GB | 940.0 KB | 2.0 MB | 750.2 KB | 1.7 MB | 0.0% |
+| DAS_clone_515 | 1.0 GB | 480.0 KB | 2.7 MB | 549.8 KB | 1.0 MB | 0.1% |
+| DATA1 | 19.0 GB | 736.0 KB | 1.0 MB | 589.1 KB | 1.3 MB | 0.0% |
+| DBs_dest | 121.6 MB | 368.0 KB | 188.0 KB | 180.0 KB | 548.0 KB | 0.4% |
+| VM_DataStore | 28.5 GB | 1.0 MB | 2.4 MB | 798.0 KB | 1.8 MB | 0.0% |
+
+
Table 107 - Volume Efficiency Savings - NFS
+1.11 Security Information
The following section provides the Security related information in PHARMAX-HQ.
1.11.1 PHARMAX-HQ Vserver Local User
The following section provides the Local User information in PHARMAX-HQ.
| User Name | Application | Auth Method | Role Name | Locked |
| admin | Amqp | password | admin | No |
| admin | Console | password | admin | No |
@@ -616,117 +1313,159 @@
| admin | Ssh | password | admin | No |
| autosupport | Console | password | autosupport | No |
-
Table 56 - Security Local Users - PHARMAX-HQ
-1.10.2 NAS Vserver Local User
The following section provides the Local User information on NAS.
+Table 108 - Security Local Users - PHARMAX-HQ
+1.11.2 CIFS Vserver Local User
The following section provides the Local User information in CIFS.
| User Name | Application | Auth Method | Role Name | Locked |
-| vsadmin | Http | password | vsadmin | Yes |
-| vsadmin | Ontapi | password | vsadmin | Yes |
-| vsadmin | Ssh | password | vsadmin | Yes |
+| vsadmin | Http | password | vsadmin | No |
+| vsadmin | Ontapi | password | vsadmin | No |
+| vsadmin | Ssh | password | vsadmin | No |
-
Table 57 - Security Local Users - NAS
-1.10.3 SAN Vserver Local User
The following section provides the Local User information on SAN.
+Table 109 - Security Local Users - CIFS
+1.11.3 FCP Vserver Local User
The following section provides the Local User information in FCP.
+| User Name | Application | Auth Method | Role Name | Locked |
+| vsadmin | Http | password | vsadmin | No |
+| vsadmin | Ontapi | password | vsadmin | No |
+| vsadmin | Ssh | password | vsadmin | No |
+
+
Table 110 - Security Local Users - FCP
+1.11.4 ISCSI Vserver Local User
The following section provides the Local User information in ISCSI.
+| User Name | Application | Auth Method | Role Name | Locked |
+| vsadmin | Http | password | vsadmin | No |
+| vsadmin | Ontapi | password | vsadmin | No |
+| vsadmin | Ssh | password | vsadmin | No |
+
+
Table 111 - Security Local Users - ISCSI
+1.11.5 NFS Vserver Local User
The following section provides the Local User information in NFS.
| User Name | Application | Auth Method | Role Name | Locked |
| vsadmin | Http | password | vsadmin | Yes |
| vsadmin | Ontapi | password | vsadmin | Yes |
| vsadmin | Ssh | password | vsadmin | Yes |
-
Table 58 - Security Local Users - SAN
-1.10.4 Vserver SSL Certificate
The following section provides the Vserver SSL Certificates information on PHARMAX-HQ.
+Table 112 - Security Local Users - NFS
+1.11.6 Vserver SSL Certificate
The following section provides the Vserver SSL Certificates information in PHARMAX-HQ.
| Common Name | Certificate Authority | Client Auth | Server Auth | Serial Number | Vserver |
-| NAS | NAS | No | Yes | 185C5D33114F6D5D | NAS |
-| PHARMAX-HQ | PHARMAX-HQ | No | Yes | 1857FFF41883F7A4 | PHARMAX-HQ |
-| SAN | SAN | No | Yes | 18580D938FAA5CCB | SAN |
-
-
Table 59 - Per Vserver SSL - PHARMAX-HQ
-1.10.4.1 Vserver SSL Certificate Details
+| CIFS | CIFS | No | Yes | 187ECA83103365B0 | CIFS |
+| FCP | FCP | No | Yes | 188366D9C772700C | FCP |
+| ISCSI | ISCSI | No | Yes | 187EC5E9C5482D4A | ISCSI |
+| CIFS | CIFS | No | Yes | 187EC4E124A07BFD | NFS |
+| PHARMAX-HQ | PHARMAX-HQ | No | Yes | 187EB31560CB29BD | PHARMAX-HQ |
+
+
Table 113 - Per Vserver SSL - PHARMAX-HQ
+1.11.6.1 Vserver SSL Certificate Details
| Common Name | Protocol | Hash Function | Serial Number | Expiration | Vserver |
-| NAS | ssl | SHA256 | 185C5D33114F6D5D | 8/16/2026 | NAS |
-| PHARMAX-HQ | ssl | SHA256 | 1857FFF41883F7A4 | 8/2/2026 | PHARMAX-HQ |
-| SAN | ssl | SHA256 | 18580D938FAA5CCB | 8/2/2026 | SAN |
-
-
Table 60 - SSL Detailed - PHARMAX-HQ
-1.10.5 Aggregate Encryption (NAE)
The following section provides the Aggregate Encryption (NAE) information on PHARMAX-HQ.
+| CIFS | ssl | SHA256 | 187ECA83103365B0 | 12/6/2026 | CIFS |
+| FCP | ssl | SHA256 | 188366D9C772700C | 12/21/2026 | FCP |
+| ISCSI | ssl | SHA256 | 187EC5E9C5482D4A | 12/6/2026 | ISCSI |
+| CIFS | ssl | SHA256 | 187EC4E124A07BFD | 12/6/2026 | NFS |
+| PHARMAX-HQ | ssl | SHA256 | 187EB31560CB29BD | 12/6/2026 | PHARMAX-HQ |
+
+
Table 114 - SSL Detailed - PHARMAX-HQ
+1.11.7 Aggregate Encryption (NAE)
The following section provides the Aggregate Encryption (NAE) information in PHARMAX-HQ.
| Aggregate | Aggregate Encryption | Volume Count | State |
-| aggr0_PHARMAX_HQ_01 | No | 1 | Online |
-| aggr0_PHARMAX_HQ_02 | No | 1 | Online |
-| PHARMAX_HQ_01_SSD_1 | No | 2 | Online |
-| PHARMAX_HQ_02_SSD_1 | No | 2 | Online |
-
-
Table 61 - Aggregate Encryption (NAE) - PHARMAX-HQ
-1.10.5.1 Volume Encryption (NVE)
+| aggr0_cluster_01 | No | 1 | Online |
+| aggr0_cluster_02 | No | 1 | Online |
+| aggr0_cluster_03 | No | 1 | Online |
+| aggr0_cluster_04 | No | 1 | Online |
+| cluster_01_SSD_1 | No | 5 | Online |
+| cluster_02_SSD_1 | No | 2 | Online |
+| cluster_03_SSD_1 | No | 3 | Online |
+| cluster_04_SSD_1 | No | 3 | Online |
+
+
Table 115 - Aggregate Encryption (NAE) - PHARMAX-HQ
+1.11.7.1 Volume Encryption (NVE)
| Name | Aggregate | Encrypted | State |
-| DATA | PHARMAX_HQ_01_SSD_1 | No | Online |
-| SQL_DATA | PHARMAX_HQ_01_SSD_1 | No | Online |
-
-
Table 62 - Volume Encryption (NVE) - PHARMAX-HQ
-1.10.6 Snaplock Compliance Clock
The following section provides the Snaplock Compliance Clock information on PHARMAX-HQ.
+| DATA | cluster_02_SSD_1 | No | Online |
+| DATA_dest | cluster_03_SSD_1 | No | Online |
+| Global_Documents | cluster_02_SSD_1 | No | Online |
+| DB | cluster_04_SSD_1 | No | Online |
+| DAS | cluster_01_SSD_1 | No | Online |
+| DAS_clone_515 | cluster_01_SSD_1 | No | Online |
+| DATA1 | cluster_04_SSD_1 | No | Online |
+| DBs_dest | cluster_01_SSD_1 | No | Online |
+| VM_DataStore | cluster_03_SSD_1 | No | Online |
+
+
Table 116 - Volume Encryption (NVE) - PHARMAX-HQ
+1.11.8 Snaplock Compliance Clock
The following section provides the Snaplock Compliance Clock information in PHARMAX-HQ.
| Node Name | Compliance Clock |
-| PHARMAX-HQ-01 | ComplianceClock is not configured. |
-| PHARMAX-HQ-02 | ComplianceClock is not configured. |
+| cluster-01 | Sun Feb 01 23:20:10 AST 2026 -04:00 |
+| cluster-02 | Sun Feb 01 23:19:25 AST 2026 -04:00 |
+| cluster-03 | Sun Feb 01 23:19:16 AST 2026 -04:00 |
+| cluster-04 | Sun Feb 01 23:20:12 AST 2026 -04:00 |
-
Table 63 - Snaplock Compliance Clock - PHARMAX-HQ
-1.10.6.1 Aggregate Snaplock Type
+Table 117 - Snaplock Compliance Clock - PHARMAX-HQ
+1.11.8.1 Aggregate Snaplock Type
| Aggregate Name | Snaplock Type |
-| PHARMAX_HQ_01_SSD_1 | Non_Snaplock |
-| PHARMAX_HQ_02_SSD_1 | Non_Snaplock |
+| cluster_01_SSD_1 | Non_Snaplock |
+| cluster_02_SSD_1 | Non_Snaplock |
+| cluster_03_SSD_1 | Non_Snaplock |
+| cluster_04_SSD_1 | Non_Snaplock |
-
Table 64 - Aggregate Snaplock Type - PHARMAX-HQ
-1.10.6.1.1 Volume Snaplock Type
+Table 118 - Aggregate Snaplock Type - PHARMAX-HQ
+1.11.8.1.1 Volume Snaplock Type
| Volume | Aggregate | Snaplock Type |
-| DATA | PHARMAX_HQ_01_SSD_1 | Non_Snaplock |
-| SQL_DATA | PHARMAX_HQ_01_SSD_1 | Non_Snaplock |
-
-
Table 65 - Volume Snaplock Type - PHARMAX-HQ
-1.11 System Configuration Information
The following section provides the Cluster System Configuration on PHARMAX-HQ.
1.11.1 System Image Configuration
+| DATA | cluster_02_SSD_1 | Non_Snaplock |
+| DATA_dest | cluster_03_SSD_1 | Non_Snaplock |
+| Global_Documents | cluster_02_SSD_1 | Non_Snaplock |
+| DB | cluster_04_SSD_1 | Non_Snaplock |
+| DAS | cluster_01_SSD_1 | Non_Snaplock |
+| DAS_clone_515 | cluster_01_SSD_1 | Non_Snaplock |
+| DATA1 | cluster_04_SSD_1 | Non_Snaplock |
+| DBs_dest | cluster_01_SSD_1 | Non_Snaplock |
+| VM_DataStore | cluster_03_SSD_1 | Non_Snaplock |
+
+
Table 119 - Volume Snaplock Type - PHARMAX-HQ
+1.12 System Configuration Information
The following section provides the Cluster System Configuration in PHARMAX-HQ.
1.12.1 System Image Configuration
| Node | Location | Is Current | Is Default | Install Time | Version |
-| PHARMAX-HQ-01 | image1 | Yes | Yes | 08/02/2025 14:35:48 | 9.16.1P4 |
-| PHARMAX-HQ-01 | image2 | No | No | 08/02/2025 13:54:16 | 9.15.1P11 |
-| PHARMAX-HQ-02 | image1 | Yes | Yes | 08/02/2025 14:37:08 | 9.16.1P4 |
-| PHARMAX-HQ-02 | image2 | No | No | 08/02/2025 13:56:06 | 9.15.1P11 |
+| cluster-01 | image1 | Yes | Yes | -- | 9.18.1RC1 |
+| cluster-02 | image1 | Yes | Yes | -- | 9.18.1RC1 |
+| cluster-03 | image1 | Yes | Yes | -- | 9.18.1RC1 |
+| cluster-04 | image1 | Yes | Yes | -- | 9.18.1RC1 |
-
Table 66 - System Image - PHARMAX-HQ
-1.11.2 System Web Service
+Table 120 - System Image - PHARMAX-HQ
+1.12.2 System Web Service
| Node | Http Enabled | Http Port | Https Port | External | Status | Status Code |
-| PHARMAX-HQ-01 | No | 80 | 443 | Yes | Online | 200 |
-| PHARMAX-HQ-02 | No | 80 | 443 | Yes | Online | 200 |
+| cluster-01 | No | 80 | 443 | Yes | Online | 200 |
+| cluster-02 | No | 80 | 443 | Yes | Online | 200 |
+| cluster-03 | No | 80 | 443 | Yes | Online | 200 |
+| cluster-04 | No | 80 | 443 | Yes | Online | 200 |
-
Table 67 - System Web Service - PHARMAX-HQ
-1.11.3 DNS Configuration
+Table 121 - Web Service - PHARMAX-HQ
+1.12.3 DNS Configuration
| Vserver | Dns State | Domains | Name Servers | Timeout/s |
-| NAS | Enabled | pharmax.local | 192.168.5.1 | 2 |
-| PHARMAX-HQ | Enabled | pharmax.local | 192.168.5.1 | 2 |
+| CIFS | Enabled | pharmax.local | 192.168.5.1 | 2 |
+| PHARMAX-HQ | Enabled | pharmax.local | 192.168.5.1 | 2 |
-
Table 68 - System DNS Configuration - PHARMAX-HQ
-1.11.4 Configuration Backup Setting
+Table 122 - DNS Configuration - PHARMAX-HQ
+Health Check:
Best Practice: It is recommended to configure at least two DNS name servers for redundancy and reliability.
1.12.4 Configuration Backup Setting
| Url | Username |
| Not Configured | Not Configured |
-
Table 69 - System Configuration Backup Setting - PHARMAX-HQ
-1.11.5 EMS Configuration
The following section provides the EMS Configuration on PHARMAX-HQ.
+Table 123 - Configuration Backup Setting - PHARMAX-HQ
+Health Check:
Best Practice: It is recommended to backup the system configuration to a remote location to ensure recovery in case of failures.
1.12.5 EMS Configuration
The following section provides the EMS Configuration in PHARMAX-HQ.
| Name | Email Destinations | Snmp Traphost | Snmp Community | Syslog | Syslog Facility |
-| allevents | - | - | - | - | - |
-| asup | - | - | - | - | - |
-| criticals | - | - | - | - | - |
-| pager | - | - | - | - | - |
-| traphost | - | - | - | - | - |
-
-
Table 70 - System EMS Configuration Setting - PHARMAX-HQ
-1.11.5.1 Audit Settings
The following section provides information about Audit Setting from PHARMAX-HQ.
+| allevents | -- | -- | -- | -- | -- |
+| asup | -- | -- | -- | -- | -- |
+| criticals | -- | -- | -- | -- | -- |
+| pager | -- | -- | -- | -- | -- |
+| traphost | -- | -- | -- | -- | -- |
+
+
Table 124 - EMS Configuration Setting - PHARMAX-HQ
+Health Check:
Best Practice: It is recommended to configure at least one EMS destination (Email, SNMP, or Syslog) to ensure proper monitoring and alerting of system events.
1.12.5.1 Audit Settings
The following section provides information about Audit Setting from PHARMAX-HQ.
| Enable HTTP Get request | No |
| Enable ONTAPI Get request | No |
| Enable CLI Get request | No |
-
Table 71 - Audit Settings - PHARMAX-HQ
-1.11.6 System Timezone Configuration
The following section provides the System Timezone Configuration on PHARMAX-HQ.
+Table 125 - Audit Settings - PHARMAX-HQ
+1.12.6 Timezone Configuration
The following section provides the Timezone Configuration in PHARMAX-HQ.
| Timezone | Timezone UTC | Timezone Version | Current Time |
-| America/Puerto_Rico | -0400 | 2024a | 08/22/2025 15:31:34 |
+| America/Puerto_Rico | -0400 | 2024a | 02/03/2026 17:17:16 |
-
Table 72 - System TimeZone - PHARMAX-HQ
-1.11.6.1 NTP Configuration
+Table 126 - TimeZone - PHARMAX-HQ
+1.12.6.1 NTP Configuration
| Server Name | NTP Version | Preferred | Authentication Enabled |
-| 192.168.5.1 | Auto | No | No |
+| 192.168.5.1 | Auto | No | No |
-
Table 73 - System Network Time Protocol - PHARMAX-HQ
-
-