Using DPM to backup a MOSS farm with SQL fixed port

Last week, a colleague of mine, called in for an issue with DPM. He was in charge of protecting a MOSS farm with DPM, as he did several times, but in this occasion content databases weren’t backed up without any explicit error.

Since this post is going to be long I anticipate the conclusions. The issue was related to MOSS being configured to use a SQL named instance with a fixed port, the issue is actually related to the fixed port, but if you have both (named instance and fixed port) you won’t get any error and this makes things confusing. So if you’re forced to use a SQL Server fixed port and you cannot use SQL endpoint mapper on port 1434, thus you hard coded the port in your MOSS configuration, and you want to use DPM to backup a MOSS farm, you should use a SQL alias to map the SQL server/instance to server/instance,port and you must use SQL server\instance (without specifying any port) in your MOSS configuration.

If you’re interested in how I get to this conclusion you can read the rest of this post.  :-)

I started from the basics, I asked for MOSS configuration via stsadm and then checked the WssCmdletsWrapperCurr log file. DPM uses a WSS wrapper to query the MOSS farm for configuration parameters and this log traces the results of this queries.

But first of all I wanted to turn on all the debug tracing for DPM. The latter task is partially documented in Diagnostic Process for Request Tracking and Error Tracing where they lack to indicate the various debugging levels, since this is standard ETL tracing it turned out the common constants can be used:


I turned on everything (0xFF) and started digging inside this issue.

The ouput from stsadm -o enumcontentdbs -url was like this:

   1: <Databases Count="1">
   2:   <ContentDatabase Server="MYSQLDB\MOSS,2319" Name="COntentDB_WA_Portal_1" />
   3: </Databases>

So I have just one content DB on SQL Server MYSQLDB instance MOSS listening on port 2319.

Then I digged inside WssCmdletsWrapperCurr and here I found that DPM was marking the content db as not to be backed up (BackupRequired=False):

WSSCmdlets.cs(292)            ==>IsDatabaseToBeBackedUp
WSSCmdlets.cs(257)            ==>GetConfigurationDatabaseName
WSSCmdlets.cs(1104)            Sql Instance Name = MYSQLDB\MOSS
WSSCmdlets.cs(257)            <--GetConfigurationDatabaseName
WSSCmdlets.cs(1104)            Sql Instance Name = MYSQLDB\MOSS,2319
WSSCmdlets.cs(1104)            Sql Instance Name = MYSQLDB\MOSS,2319
WSSCmdlets.cs(1104)            Sql Instance Name = MYSQLDB\MOSS,2319
WSSCmdlets.cs(1104)            Sql Instance Name = MYSQLDB\MOSS,2319
WSSCmdlets.cs(332)            BackupRequired for Component MYSQLDB\MOSS\ContentDB_WA_Portal_1 = False
WSSCmdlets.cs(292)            <--IsDatabaseToBeBackedUp

So DPM seemed to correctly enumerate the MOSS content DB, but somehow marked it as not to be backed up. Now it was time to understand when DPM considers a content db to be backed up. I didn’t find any documentation on the topic, but the log was clear enough and told me this is managed code (.cs), so I have good chances to get to the source code using Reflector without any need of a lengthy debugging session. Thanks (and thanks again) to the great Reflector I get to the source code of the wsswrapper (wsscmdlets.dll).

   1: public void IsDatabaseToBeBackedUp(string instanceName, string databaseName, out bool backupRequired)
   2: {
   3:     IDisposable disposable = Tracer._TraceFunction("WSSCmdlets.cs", 0x124, "IsDatabaseToBeBackedUp");
   4:     try
   5:     {
   6:         backupRequired = false;
   7:         if (!backupRequired)
   8:         {
   9:             string str = string.Empty;
  10:             string str2 = string.Empty;
  11:             this.GetConfigurationDatabaseName(out str, out str2);
  12:             if (string.Equals(instanceName, str, StringComparison.InvariantCultureIgnoreCase) && string.Equals(databaseName, str2, StringComparison.InvariantCultureIgnoreCase))
  13:             {
  14:                 Tracer._TraceMessage(0x10, "WSSCmdlets.cs", 0x138, @"Found Config Database {0}\{1}", new object[] { instanceName, databaseName });
  15:                 backupRequired = true;
  16:             }
  17:         }
  18:         if (!backupRequired)
  19:         {
  20:             SPWebService spWebService = SPWebService.get_AdministrationService();
  21:             backupRequired = this.IsContentDatabase(spWebService, instanceName, databaseName);
  22:         }
  23:         if (!backupRequired)
  24:         {
  25:             SPWebService service2 = SPWebService.get_ContentService();
  26:             backupRequired = this.IsContentDatabase(service2, instanceName, databaseName);
  27:         }
  28:         Tracer._TraceMessage(0x10, "WSSCmdlets.cs", 0x14c, @"BackupRequired for Component {0}\{1} = {2}", new object[] { instanceName, databaseName, (bool) backupRequired });
  29:     }
  30:     catch (Exception exception)
  31:     {
  32:         Tracer._TraceMessage(2, "WSSCmdlets.cs", 0x151, @"Caught Exception while checking if the database [{0}\{1}] requires Backup.", new object[] { instanceName, databaseName });
  33:         LogExceptionDetails(exception);
  34:         throw;
  35:     }
  36:     finally
  37:     {
  38:         if (disposable != null)
  39:         {
  40:             disposable.Dispose();
  41:         }
  42:     }
  43: }

And here we go, on line 11 we can find the call to GetConfigurationDatabaseName and this call returns the SQL instance name in str and the content database name in str2. OK but this is not a config db, so we must concentrate on line 21 (and 26). IsContentDatabase takes instanceName and databaseName as input  parameters, from the tracing file (line WssCmdLets.cs (332))we can assume instanceName=MYSQLDB\MOSS and databaseName=ContentDB_WA_Portal_1. Ok let’s move on, but now the log is clearer in one case we have MYSQLDB\MOSS,2319 and in the other MYSQLDB\MOSS.

Digging further this is the snippet for IsContentDatabase

   1: private bool IsContentDatabase(SPWebService spWebService, string instanceName, string databaseName)
   2: {
   3:     foreach (SPWebApplication application in spWebService.get_WebApplications())
   4:     {
   5:         foreach (SPContentDatabase database in application.get_ContentDatabases())
   6:         {
   7:             string formattedSqlInstanceName = GetFormattedSqlInstanceName(database.get_Server());
   8:             string a = database.get_Name();
   9:             if (string.Equals(formattedSqlInstanceName, instanceName, StringComparison.InvariantCultureIgnoreCase) && string.Equals(a, databaseName, StringComparison.InvariantCultureIgnoreCase))
  10:             {
  11:                 Tracer._TraceMessage(0x10, "WSSCmdlets.cs", 0x4d0, @"Found Content Database {0}\{1}", new object[] { instanceName, databaseName });
  12:                 return true;
  13:             }
  14:         }
  15:     }
  16:     return false;
  17: }

Here we can read we’re using the MOSS WebService, so we must expect the same output we got from stsadm (and indeed we do). On line 9 we find the culprit of our issue it is comparing MYSQLDB\MOSS,2319 with MYSQLDB\MOSS and they will never match, hence for DPM this is not a content db and doesn’t need to be backed up. This is an evident bug in the DPM wss wrapper that can be circumvented with the workaround proposed at the beginning of this post.

Hope this would spare time to anyone’s going to face the same situation.

– Daniele

This posting is provided "AS IS" with no warranties, and confers no rights.

Technorati Tags: ,,
  1. #1 by RogerM on March 6, 2009 - 8:14 am

    We are not using DPM but that was still a very interesting read. Great work!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: