Update Site Quota for existing sites- Tips & Tricks

on Wednesday, April 28, 2010

There is a little known discrepancy in the SharePoint 2007 Site Quota Templates; they are not easily updated. You see Site Quotas are based upon a template model that is disconnected in nature. That means that all new sites that have the template applied will get the updated version but any existing sites for which it was previously applied retain the previous values.

Unfortunately when you make changes to the template in Central Administration and then check the site quota of an existing site it does appear that the changes have taken effect. This is because the page is simply pulling the settings from the new Quota Template instead of pulling the settings applied at the site level. If you use StsAdm.exe to enumerate through the sites you will see that the site quota retains the previous values. I'll demonstrate.

Lets edit an existing Quota Template for Personal Sites. You navigate to Central Administration and click on Quota Templates. You can see that the existing values are set to allow a maximum storage limit of 100 MB.

quota1

Now change the Storage Limit Maximum to 200 MB as below.

quota2

If we navigate to Site Quotas and Locks and choose the MySites web application we can see that our changes have taken effect. Or so it would appear.

quota3

However, if we use Stsadm.exe and Enumerate through the sites in the web application though we can see that our initial value of 100 MB still applies.

enumSites

This is because the Quota Template is just that, a template, it only applies to new sites that are assigned the quota from that point forward. It does not propagate its changes. Actually there really is no way to propagate these changes and of course we can't have that, so I wrote a little extension to Stsadm.exe to make that possible.

Rather than bore you with the specifics of how I did this I'll refer you to the blog that I used for references on extending Stsadm.exe. John Holiday has a great article here. And of course there is the trusty SDK with which I could not live without.

Below is a screen shot of the help for the Update Quota command that I wrote for Stsadm.exe.

updateQuotaHelp

As you can see it takes 2 parameters, one for the URL and another for the Quota Template Name. The command would be stsadm -o updatequota -url "http://my.demo.com" -quotaname "Personal Site".

After running the command we can go back and use stsadm to enumerate through the sites and see that our changes have taken effect.

quotasUpdated

Most everything in MOSS 2007 is extensible in one way or another and Stsadm is no exceptions. Actually extending stsadm is quite simple. In this blog entry I am going to walk through creating a custom extension for stsadm that I use in a real life scenario. This extension is called Quota Updater and you can read a little history about how this came about in my post here.

The first thing we do is create a new VS project and add a new class called quotaupdater.cs and implement the ISPStsadmCommand interface. Now we have to implement the Run and GetHelpMessage methods. These look like this:

public int Run(string command, StringDictionary keyValues, out string output)
{
//logic here
}
public string GetHelpMessage(string command)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("-url <url>\t\tthe url of the site to process");
            sb.AppendLine("\t-quotaname <quotaname>\tthe template to process");
            return sb.ToString();
        }

The second thing we have to do is create an XML file that describes our commands and add it to the 12/config directory. This looks as follows:

<?xml version="1.0" encoding="utf-8" ?>
<commands>
    <command name="updatequotas"

          class="STSAdmExtensions.QuotaUpdater, STSAdmExtensions, 
      Version=1.0.0.0, Culture=neutral, PublicKeyToken=86a65a77eee85b51">
  </command>
</commands>

In the above XML file the command name is whatever you would like your user to type to activate the custom command with stsadm. This does not necessarily have to be the same as your method or class. It can literally be whatever you would like. The class section is the typical stuff you can get by using Refactor on your assembly.

Now for the meat of the application. Basically what I wanted to do was get a reference to a site collection and a quota template and force updates to the template down to the sites on which it is applied. The Run method is as follows:

public int Run(string command, StringDictionary keyValues, out string output)
{
    StringBuilder sb = new StringBuilder();
    string url = keyValues["url"], quotaName = keyValues["quotaname"];
    //if no URL specified then return 0 and message
    if (url == null || url.Length == 0)
    {
        output = "No url specified";
        return 0;
    }
    //if no Quota Template name supplied then return 0 and message
    if (quotaName == null || quotaName.Length == 0)
    {
        output = "No Quota Template specified";
        return 0;
    }
    try
    {
        SPSite site = new SPSite(url);
        SPWebApplication webApp = site.WebApplication;
        SPSiteCollection col = webApp.Sites;

        SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
        SPGlobalConfig globalConfig = globalAdmin.Config;
        SPQuotaTemplate quota = globalConfig.QuotaTemplates[quotaName];

        UpdateQouta(col, quota);
        output = message;
        
        //clean up resources
        site.Close();
        site.Dispose();
        return 1;
    }
    catch (Exception ex)
    {
        output = ex.Message;
        return 0;
    }
}


And the UpdateQuota method is shown below.

/// <summary>
/// Updates all site quotas in a site collection with updated quota template values
/// </summary>
/// <param name="sites"></param>
/// <param name="quotaTemplate"></param>

public void UpdateQouta(SPSiteCollection sites, SPQuotaTemplate quotaTemplate)
{
    int iCount = 0;
    StringBuilder sb = new StringBuilder();

    foreach (SPSite site in sites)
    {
        //verify quota on the site against the quota template to prevent overwrite
        if (site.Quota.QuotaID == quotaTemplate.QuotaID)
        {
            iCount++;
            site.Quota.InvitedUserMaximumLevel = quotaTemplate.InvitedUserMaximumLevel;
            site.Quota.StorageMaximumLevel = quotaTemplate.StorageMaximumLevel;
            site.Quota.StorageWarningLevel = quotaTemplate.StorageWarningLevel;
        }
    }
    if (iCount == 0)
    { 
message = "No sites were updated. Make sure you specified the correct " +_ "Quota Template Name.";
} else { sb.AppendLine(iCount + " Sites Updated"); sb.AppendLine("The Command Completed Successfully"); message = sb.ToString(); } }

Now all you have to do is deploy the assembly to the GAC and copy your XML file to the 12/config directory and you are set to go.

1 comments:

RenewSSLs said...

Thanks for sharing the information. That’s a awesome article you posted. I found the post very useful as well as interesting. I will come back to read some more.