Skip to content

Commit 3e26310

Browse files
Add Test-DbaInstantFileInitialization command (#10236)
1 parent 9c81f3d commit 3e26310

File tree

4 files changed

+192
-0
lines changed

4 files changed

+192
-0
lines changed

dbatools.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@
703703
'Test-DbaOptimizeForAdHoc',
704704
'Test-DbaPath',
705705
'Test-DbaPowerPlan',
706+
'Test-DbaInstantFileInitialization',
706707
'Test-DbaReplLatency',
707708
'Test-DbaSpn',
708709
'Test-DbaTempDbConfig',

dbatools.psm1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,7 @@ if ($PSVersionTable.PSVersion.Major -lt 5) {
10851085
'Get-DbaDiskSpace',
10861086
'Test-DbaDiskAllocation',
10871087
'Test-DbaPowerPlan',
1088+
'Test-DbaInstantFileInitialization',
10881089
'Set-DbaPowerPlan',
10891090
'Test-DbaDiskAlignment',
10901091
'Get-DbaStartupParameter',
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
function Test-DbaInstantFileInitialization {
2+
<#
3+
.SYNOPSIS
4+
Tests whether Instant File Initialization (IFI) is properly configured for SQL Server Engine service accounts.
5+
6+
.DESCRIPTION
7+
Audits Instant File Initialization (IFI) configuration for all SQL Server Engine services on the specified computer(s).
8+
9+
IFI allows SQL Server to skip zeroing out data file space during file creation and auto-growth operations, which can dramatically speed up database creation, restore operations, and auto-growth events. Microsoft recommends enabling IFI as a best practice for all SQL Server installations.
10+
11+
IFI is controlled by the Windows "Perform Volume Maintenance Tasks" privilege (SeManageVolumePrivilege). The recommended approach is to grant this privilege to the virtual service account "NT SERVICE\<ServiceName>" rather than to the actual service account (StartName), as this follows the principle of least privilege and is account-independent.
12+
13+
This command checks both the virtual service account (NT SERVICE\<ServiceName>) and the actual start account (StartName) to determine:
14+
- IsEnabled: IFI is enabled via either account (the service will benefit from IFI)
15+
- IsBestPractice: IFI is enabled via the virtual service account only (the recommended configuration)
16+
17+
Note: This command checks direct privilege assignments only. IFI may also be enabled indirectly via group membership (e.g., Administrators), which is not detected by this command.
18+
19+
Requires Local Admin rights on destination computer(s).
20+
21+
References:
22+
https://docs.microsoft.com/en-us/sql/relational-databases/databases/database-instant-file-initialization
23+
https://blog.ordix.de/instant-file-initialization-microsoft-sql-server-set-up-check
24+
25+
.PARAMETER ComputerName
26+
Specifies the SQL Server host computer(s) to test IFI configuration on. Accepts server names, IP addresses, or DbaInstance objects.
27+
28+
.PARAMETER Credential
29+
Specifies a PSCredential object used to authenticate to the target computer(s) when the current user account is insufficient.
30+
31+
.PARAMETER EnableException
32+
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
33+
This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
34+
Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
35+
36+
.NOTES
37+
Tags: IFI, Privilege, Security, BestPractice, OS
38+
Author: the dbatools team + Claude
39+
40+
Website: https://dbatools.io
41+
Copyright: (c) 2018 by dbatools, licensed under MIT
42+
License: MIT https://opensource.org/licenses/MIT
43+
44+
.LINK
45+
https://dbatools.io/Test-DbaInstantFileInitialization
46+
47+
.OUTPUTS
48+
PSCustomObject
49+
50+
Returns one object per SQL Server Engine service found on each computer tested.
51+
52+
Default display properties (via Select-DefaultView):
53+
- ComputerName: The target computer name
54+
- InstanceName: The SQL Server instance name
55+
- ServiceName: The Windows service name (e.g. MSSQLSERVER, MSSQL$INSTANCENAME)
56+
- StartName: The actual Windows account running the service
57+
- IsEnabled: Boolean indicating if IFI is enabled via either the virtual or start account
58+
- IsBestPractice: Boolean indicating if IFI is enabled via the virtual service account (NT SERVICE\<ServiceName>) only
59+
60+
Additional properties available:
61+
- ServiceNameIFI: Boolean indicating if the virtual service account (NT SERVICE\<ServiceName>) has IFI privilege
62+
- StartNameIFI: Boolean indicating if the actual start account (StartName) has IFI privilege
63+
64+
.EXAMPLE
65+
PS C:\> Test-DbaInstantFileInitialization -ComputerName sqlserver2019
66+
67+
Tests IFI configuration for all SQL Server Engine services on sqlserver2019.
68+
69+
.EXAMPLE
70+
PS C:\> Test-DbaInstantFileInitialization -ComputerName sql1, sql2, sql3
71+
72+
Tests IFI configuration for all SQL Server Engine services on sql1, sql2, and sql3.
73+
74+
.EXAMPLE
75+
PS C:\> 'sql1', 'sql2' | Test-DbaInstantFileInitialization
76+
77+
Tests IFI configuration for all SQL Server Engine services on sql1 and sql2.
78+
79+
.EXAMPLE
80+
PS C:\> Test-DbaInstantFileInitialization -ComputerName sqlserver2019 | Where-Object IsBestPractice -eq $false
81+
82+
Returns SQL Server services on sqlserver2019 where IFI is not configured as best practice.
83+
84+
#>
85+
[CmdletBinding()]
86+
param (
87+
[parameter(ValueFromPipeline)]
88+
[DbaInstance[]]$ComputerName = $env:COMPUTERNAME,
89+
[PSCredential]$Credential,
90+
[switch]$EnableException
91+
)
92+
93+
process {
94+
foreach ($computer in $ComputerName) {
95+
try {
96+
Write-Message -Level Verbose -Message "Getting SQL Server Engine services on $computer"
97+
$splatGetService = @{
98+
ComputerName = $computer
99+
Credential = $Credential
100+
Type = "Engine"
101+
EnableException = $EnableException
102+
}
103+
$services = Get-DbaService @splatGetService
104+
} catch {
105+
Stop-Function -Message "Failed to get SQL Server services on $computer" -ErrorRecord $_ -Target $computer -Continue
106+
}
107+
108+
if (-not $services) {
109+
Write-Message -Level Verbose -Message "No SQL Server Engine services found on $computer"
110+
continue
111+
}
112+
113+
try {
114+
Write-Message -Level Verbose -Message "Getting Windows privileges on $computer"
115+
$splatGetPrivilege = @{
116+
ComputerName = $computer
117+
Credential = $Credential
118+
EnableException = $EnableException
119+
}
120+
$privileges = Get-DbaPrivilege @splatGetPrivilege
121+
} catch {
122+
Stop-Function -Message "Failed to get privileges on $computer" -ErrorRecord $_ -Target $computer -Continue
123+
}
124+
125+
foreach ($service in $services) {
126+
Write-Message -Level Verbose -Message "Checking IFI for service $($service.ServiceName) on $computer"
127+
128+
$serviceNameIFI = ($privileges | Where-Object User -eq "NT SERVICE\$($service.ServiceName)").InstantFileInitialization -eq $true
129+
$startNameIFI = ($privileges | Where-Object User -eq $service.StartName).InstantFileInitialization -eq $true
130+
131+
$isEnabled = $serviceNameIFI -or $startNameIFI
132+
$isBestPractice = $serviceNameIFI -and -not $startNameIFI
133+
134+
[PSCustomObject]@{
135+
ComputerName = $service.ComputerName
136+
InstanceName = $service.InstanceName
137+
ServiceName = $service.ServiceName
138+
StartName = $service.StartName
139+
ServiceNameIFI = $serviceNameIFI
140+
StartNameIFI = $startNameIFI
141+
IsEnabled = $isEnabled
142+
IsBestPractice = $isBestPractice
143+
} | Select-DefaultView -Property ComputerName, InstanceName, ServiceName, StartName, IsEnabled, IsBestPractice
144+
}
145+
}
146+
}
147+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#Requires -Module @{ ModuleName="Pester"; ModuleVersion="5.0" }
2+
param(
3+
$ModuleName = "dbatools",
4+
$CommandName = "Test-DbaInstantFileInitialization",
5+
$PSDefaultParameterValues = $TestConfig.Defaults
6+
)
7+
8+
Describe $CommandName -Tag UnitTests {
9+
Context "Parameter validation" {
10+
It "Should have the expected parameters" {
11+
$hasParameters = (Get-Command $CommandName).Parameters.Values.Name | Where-Object { $PSItem -notin ("WhatIf", "Confirm") }
12+
$expectedParameters = $TestConfig.CommonParameters
13+
$expectedParameters += @(
14+
"ComputerName",
15+
"Credential",
16+
"EnableException"
17+
)
18+
Compare-Object -ReferenceObject $expectedParameters -DifferenceObject $hasParameters | Should -BeNullOrEmpty
19+
}
20+
}
21+
}
22+
23+
Describe $CommandName -Tag IntegrationTests {
24+
Context "Gets IFI status" {
25+
BeforeAll {
26+
$PSDefaultParameterValues["*-Dba*:EnableException"] = $true
27+
$computerName = Resolve-DbaComputerName -ComputerName $TestConfig.InstanceSingle -Property ComputerName
28+
$results = Test-DbaInstantFileInitialization -ComputerName $computerName
29+
$PSDefaultParameterValues.Remove("*-Dba*:EnableException")
30+
}
31+
32+
It "Gets results" {
33+
$results | Should -Not -BeNullOrEmpty
34+
}
35+
36+
It "Results have expected properties" {
37+
$results[0].ComputerName | Should -Not -BeNullOrEmpty
38+
$results[0].ServiceName | Should -Not -BeNullOrEmpty
39+
$results[0].IsEnabled | Should -BeOfType [bool]
40+
$results[0].IsBestPractice | Should -BeOfType [bool]
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)