-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAdjust-DFSReplicationStagingQuotav3.ps1
227 lines (153 loc) · 8.71 KB
/
Adjust-DFSReplicationStagingQuotav3.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
<#
Script created by Micha Vermeer for Damen Shipyards
This script will calculate the recommended StagingPathQuotaInMB for each DFS-R in $DomainName.
See also: https://msdn.microsoft.com/en-us/library/cc754229(v=ws.11).aspx#bkmk_optimize
TODO:
- Check if the DFS-R is read-only, if so then StagingPathQuotaInMB should be only equal to the 16 largest files instead of 32.
- Convert script to use jobs instead of just processing everything serially
- Run only the jobs on the remote servers so we can run them quicker then all on the 1 or 2 servers in the DC.
#>
# Function to make it easy to write to a log file
Function Write-Log {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]
$Message,
[Parameter(Mandatory=$False)]
[ValidateSet("INFO","WARN","ERROR","FATAL","DEBUG")]
[String]
$Level,
[Parameter(Mandatory=$False)]
[string]
$logfile = "$env:HOMEDRIVE$env:HOMEPATH\DFSLogfileV2 $(get-date -Format 'yyyy-MM-dd').log"
)
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
If(!$Level) {
$Level = "INFO"
}
$Line = "$Stamp $Level $Message"
If($logfile) {
Add-Content $logfile -Value $Line -Encoding UTF8 -PassThru
}
Else {
Write-Output $Line
}
}
Write-Log -Message "Running..."
# Clean variables
$DfsrMembers = ""
$DfsRepfolders = ""
$DCRepPartnerQuotas = ""
$DCRepPartnerQuota = ""
$SiteRepPartnerQuotas = ""
$SiteRepPartnerQuota = ""
$CompleteJobs = ""
# Initiallize the array that will contain the data to write to the CSV file, and setting other variables
$DFSArray = @()
$DomainName = "schelde.com"
$increment = 4096 # The minimum amount (in MB) that a staging quota should be regardless of size of files
# Get all the servers
$DfsrMembers = Get-DfsrMember -DomainName $DomainName #-GroupName "sites.damen.local\appdata\damen" # To get the servers of the replication group
$DfsRepfolders = $DfsrMembers | Get-DfsReplicatedFolder -DomainName $DomainName
$AllDfsServers = ($DfsrMembers).ComputerName | select -Unique # Each server in all replication groups
foreach ($SiteDfsServer in $AllDfsServers)
{
if ($SiteDfsServer -notmatch "FIS001") # Skip any servers in the DC
{
$SiteDfsFolders = $DfsrMembers | ?{$_.ComputerName -match $SiteDfsServer} | Get-DfsReplicatedFolder -DomainName $DomainName
foreach ($SiteDfsFolder in $SiteDfsFolders)
{
Write-Log -Message "------------------------------------------------"
Write-Log -Message "Processing: $($SiteDfsFolder.DfsnPath)"
# This DFS Replication folder has more then 1 replication partner (Server)
# Making sure we don't start more then running 20 jobs on a particular server, because of the session limit of 25
$SiteDfsServerJobsRunning = Get-Job | ?{$_.State -eq "Running" -and $_.Location -eq $SiteDfsServer}
While ($SiteDfsServerJobsRunning.Count -eq 20) # Going to throttle the amount of running jobs on the site server
{
Start-Sleep 15
$SiteDfsServerJobsRunning = Get-Job | ?{$_.State -eq "Running" -and $_.Location -eq $SiteDfsServer}
}
Invoke-Command -ComputerName $SiteDfsServer -ArgumentList $SiteDfsFolder -AsJob -JobName "$($SiteDfsFolder.DfsnPath)" `
{ param($SiteDfsFolder)
(Get-ChildItem $SiteDfsFolder.DfsnPath -Recurse -ErrorAction SilentlyContinue | `
Sort-Object Length -Descending | `
Select-Object -First 32 | `
Measure-Object -Property Length -Sum).Sum /1mb
}
$SiteDfsServerJobsRunning = Get-Job | ?{$_.State -eq "Running" -and $_.Location -eq $SiteDfsServer}
$SiteDfsServerJobsAll = Get-Job | ?{$_.Location -eq $SiteDfsServer}
Write-Log -Message "We have $($SiteDfsServerJobsRunning.Count) running job(s) on $SiteDfsServer."
Write-Log -Message "We have added $($SiteDfsServerJobsAll.Count) total job(s) on $SiteDfsServer."
}
}
else # Server is a FIS001 aka a DC server
{
# Run the jobs if there is no site server.
}
}
Write-Log -Message "Started all the jobs, now we need to wait untill they have all finished"
$RunningJobs = Get-Job | ?{$_.State -eq "Running"}
While ($RunningJobs.Count -ne 0)
{
Write-Log -Message "We have uncompleted jobs, and we are waiting for these:"
Get-Job | ?{$_.State -eq "Running"} | Format-Table -AutoSize | Out-File -append "$env:HOMEDRIVE$env:HOMEPATH\DFSLogfileV2 $(get-date -Format 'yyyy-MM-dd').log" -Encoding utf8
Start-Sleep 15
$RunningJobs = Get-Job | ?{$_.State -eq "Running"}
}
Write-Log -Message "All jobs are Finished"
foreach ($CompleteJob in $CompleteJobs)
{
$JobData = Receive-Job $CompleteJob -Keep
# Round to whole MB
$Dfs32LargestFilesRounded = [math]::Round($JobData+1,0,1)
if($Dfs32LargestFilesRounded -gt 4096) # This part checks the total size of $Dfs32LargestFilesRounded and puts at least 4096 MB
# or any increment of 4096 MB above that as integer into DfsMinimumStagingQuota. So 4097 MB will be rounded to 8192 MB.
# So 4097 MB will be rounded to 8192 MB.
{
Write-Log "Value is greater then 4096, namely $Dfs32LargestFilesRounded" -Level DEBUG
$DfsMinimumStagingQuota = [Math]::Ceiling($Dfs32LargestFilesRounded / $Increment) * $Increment;
}
else # The 32 files make up less then 4096 MB
{
Write-Log "Value is lower then 4096, namely $Dfs32LargestFilesRounded" -Level DEBUG
$DfsMinimumStagingQuota = $Increment # Which is 4096
}
Write-Log "Stagingfolder $($CompleteJob.Name) properties:" -Level DEBUG
Write-Log "Actual size of the 32 largest files is $($Dfs32LargestFilesRounded) MB" -Level DEBUG
$DCRepPartnerQuotas = $DfsRepFolders | Get-DfsrMembership -DomainName $DomainName | ?{$_.foldername -eq "$($dfsrepFolders.foldername)" -and "$($_.computername)" -match "FIS001"}
$SiteRepPartnerQuotas = $DfsRepFolders | Get-DfsrMembership -DomainName $DomainName | ?{$_.foldername -eq "$($dfsrepFolders.foldername)" -and "$($_.computername)" -notmatch "FIS001"}
foreach ($DCRepPartnerQuota in $DCRepPartnerQuotas)
{
Write-Log "The current DFS Staging Quota on server $($DCRepPartnerQuota.ComputerName) is set at $($DCRepPartnerQuota.StagingPathQuotaInMB) MB" -Level DEBUG
}
foreach ($SiteRepPartnerQuota in $SiteRepPartnerQuotas)
{
Write-Log "The current DFS Staging Quota on server $($SiteRepPartnerQuota.ComputerName) is set at $($SiteRepPartnerQuota.StagingPathQuotaInMB) MB" -Level DEBUG
}
Write-Log "The minimum size of the quota should be $($DfsMinimumStagingQuota) MB" -Level DEBUG
# Creating a new entry in the array that we use to create the CSV at the end of the run.
Write-Log -Message "Done calculating, adding to Array"
$DFSArray += @{ `
'Group Name'=$DfsRepFolders.GroupName; `
'DFS Path'=$DfsRepFolders.DfsnPath; `
'Current Staging Path Quota (MB)'=$DCRepPartnerQuota.StagingPathQuotaInMB; `
'Actual Size (MB)'= $Dfs32LargestFilesRounded; `
'New Quota Size (MB)'=$DfsMinimumStagingQuota
}
# Here is the real work being done, adjusting the actual StagingPathQuotaInMB to the value we calculated it should be. Remove -WhatIf at the end to make it actually do things
$DfsRepFolders | Get-DfsrMembership -DomainName $DomainName | ?{$_.foldername -eq "$($dfsrepFolders.foldername)"} | Set-DfsrMembership -StagingPathQuotaInMB $DfsMinimumStagingQuota -force -WhatIf
}
# Exporting the data we collected to CSV. You'll find the CSV in your homefolder ex.: D:\users\amver04\
Write-Log -Message "Finished, writing out the CSV file..."
$DFSArray | foreach {New-Object psobject -Property $_} | Export-Csv -NoTypeInformation "$env:HOMEDRIVE$env:HOMEPATH\DFSArray $(get-date -Format 'yyyy-MM-dd hhmm').csv"
# Removing the succesfull jobs from the system
$CompleteJobs | Remove-Job
# Writing out the jobs with errors
$JobErrors = Get-Job | ?{$_.State -ne "completed"}
foreach ($JobError in $JobErrors)
{
Write-Log -Message "For Server $($JobError.Location) there are the following error messages:"
Write-Log -Message "$($JobError.ChildJobs.Error)"
}
Write-Log -Message "Done"