stichl.at tech at work

17Jan/144

DFS quota Management the easy way

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
Filed under: Windows Leave comment
Comments (4) Trackbacks (0)
  1. Hello this script not working, error in line 1 char 18, symbol (&).

  2. Sorry to post to an old thread but thought I would share my solution that is very similar to yours just using powershell. Run on every non-master server to sync quotas.

    $erroractionpreference = “SilentlyContinue”
    $qm = new-object -com fsrm.fsrmquotamanager

    $s = New-pssession -computername Server1
    invoke-command -session $s -scriptblock {$remQM = new-object -comobject FSRM.FSRMQuotaManager}
    $quotas = invoke-command -session $s -scriptblock {$remqm.enumquotas(“e:\dfs\…”)}
    $quotas += invoke-command -session $s -scriptblock {$remqm.enumquotas(“f:\dfs\…”)}

    foreach ($quota in $quotas){
    $quotapath = $quota.path -replace(“server1″,”server2”)
    $DFS = $qm.getquota($quotapath)

    if($?){
    if($dfs.quotalimit -ne $Quota.quotalimit){
    $dfs.quotalimit = $Quota.Quotalimit
    $dfs.commit()
    } # If Quota’s not the same
    } # If last command successful
    ELSE { write-host -foregroundcolor RED “FAILED – ” $quotapath}
    }
    remove-pssession -computername Server1

    • I just quickly looked over your script now… My article is about old-style NTFS quotas. I think your powershell approach is modifying FSRM quotas. Thats a different thing…


Leave a comment

No trackbacks yet.