This week I migrated some older Windows 2003 DFS servers to newer machines running Windows 2008R2. Just DO NOT ask me why I’m not using 2012 or 2012R2, thanks!
In the past we have been using the old style NTFS volume quotas to stop our users from storing every bullsh*t on the servers. They needed to request another 5GB whenever they ran out of disk space.
When one user’s quota value changed it has to be modified on each DFS server – stupid work! And if you do not keep the values in sync, DFS will have massive problems when the user runs out of disk space on just ONE of the DFS servers…
At first we tried to solve this problem with FSRM (which also offers a full-featured command line interface), but it’s not possible. FSRM can not assign individual user quotas. Thank you Microsoft!
Volume based NTFS quotas can be viewed by a command line tool, but exporting/importing or changing values (like in the GUI) is not possible via command line 🙁
This is the point where we built two different VBS-Scripts. One script is running on our master DFS server, which exports all quota settings to a CSV-File. This file is stored on the DFS volume and gets replicated to every branch DFS server. The branch DFS servers are running a script which is importing the quota settings. We are running these scripts every 10 minutes using the task scheduler.
We also placed the VBS-scripts in the same folder as the CSV file (QUOTA_FILE) so we didn’t need to copy them on each single server.
Our monitoring is checking the result code of the scheduled tasks and the age of the CSV file on the master server. If this file is older than 15 minutes, there is a problem.
As a result you just have to modify a quota on the master server and it gets updated on the branch servers automatically 🙂
UPDATE: There seems to be a problem with objFSO.OpenTextFile and DFS, as DFS-R sometimes misses the changed contents of the .csv file. Just add a line (see below) to delete the csv file before writing into it.
quota_export.vbs
Const QUOTA_FILE="D:\DFSroot\_quota\usrquota.csv";
Const QUOTA_PATH="D:\";
Set objDiskQuotas = CreateObject("Microsoft.DiskQuota.1")
Set objFSO = CreateObject("Scripting.FileSystemObject")
objDiskQuotas.Initialize QUOTA_PATH, False
objFSO.DeleteFile(QUOTA_FILE)
Set objFile = objFSO.OpenTextFile(QUOTA_FILE, 2, True)
For Each objUser in objDiskQuotas
If objUser.AccountStatus<>5 Then
strOutput = objUser.LogonName & ";" & objUser.AccountStatus & ";" & objUser.QuotaLimit & ";" & objUser.QuotaThreshold
objFile.WriteLine strOutput
End If
Next
objFile.Close
quota_import.vbs
Const QUOTA_FILE="D:\DFSroot\_quota\usrquota.csv"
Const QUOTA_PATH="D:\"
Set objDiskQuotas = CreateObject("Microsoft.DiskQuota.1")
Set objFSO = CreateObject("Scripting.FileSystemObject")
objDiskQuotas.Initialize QUOTA_PATH, True
objDiskQuotas.UserNameResolution=1
Set objFile = objFSO.OpenTextFile(QUOTA_FILE, 1)
Do While Not objFile.AtEndOfStream
quotaentries = objFile.ReadAll()
Loop
quotaentries = Split(quotaentries, vbCrLf)
For Each quotaentry in quotaentries
if quotaentry <> "" Then
entry = Split(quotaentry, ";")
sLogonName = trim(entry(0))
sQuotaLimit = int(entry(2))
sQuotaThreshold = int(entry(3))
Set objQuotaUser = objDiskQuotas.AddUser(sLogonName)
If objQuotaUser.QuotaLimit<>sQuotaLimit or objQuotaUser.QuotaThreshold <> sQuotaThreshold Then
objQuotaUser.QuotaLimit = sQuotaLimit
objQuotaUser.QuotaThreshold = sQuotaThreshold
End If
End If
Next
objFile.Close