I had a question for a customer recently which needed some investigation, as the seemingly “easy steps” to export and import DFSN configurations didn’t do what either of us expected.
KB969382 lists the actions to take in the event of your DFS Namespace going west. Option 2 was the one we were looking at as we wanted to create regular DFS-N backups to be used in any DFS-N related emergency.
It seemed simple enough, run this command to backup your configuration:
dfsutil root export \domain.nameDFSN DFSN-root.txt
And when disaster strikes, just run this command to put it all back again:
dfsutil root import set DFSN-Root.txt \domain.nameDFSN
However, no matter what the DFS-N emergency we created in the lab, the import would always fail citing “element not found”.
The problem was that we were breaking the DFS-N root (on purpose), but the export/import scenario requires you to have a working DFS-N root. And to get that, you’d need good system-state backups of both a DC and a DFS Namespace server. Which isn’t going to provide for a fast, efficient restore scenario in a large organisation.
So I started experimenting, and it seems that the objects in AD are easily copied and imported again using ldifde – there is no attachment to the object GUIDs (like there is say in a failover cluster). And once all the objects are back in AD, all the links and targets start working again as expected.
The same applies to the share and DFSN root information in the registry – a simple ‘reg save’ followed by a ‘reg restore’ will get that information back with the registry ACLs in tact.
So, I wrote 2 scripts (each fires of a second script to run directly on the DFS Namespace servers):
- The scheduled backup script deployed as a scheduled task to a central management server
- A restore script to be used in the case of any DFS-N emergency
Now, while the restore could be more targeted to allow you to chose the scenario to recover from (e.g. restore ONLY the objects in AD or DFS-N registry information on just 1 DFS-N server, or only one DFS-N root), I’ll leave it to you good reader to add that intelligence. This restore script restore the entire DFS-N configuration for all roots and to all DFS-N servers.
This will backup and restore both Windows 2000/2003 roots and Windows Server 2008 roots. It uses psexec from Sysinternals, available here. The reason it does this is to use reg save/reg restore, which capture ACLs on the registry keys and restores exactly the configuration which was backed up, rather than merging the configuration. While my testing shows that these reg keys do not have explicit permissions defined, you’re better safe than sorry.
Make sure and change any instances of “dc=domain,DC=name” and “\domain.name” to the domain name in your environment.
rem Setup input file
if not exist .backupfiles mkdir .backup-files
if exist servers.txt del servers.txt
for /F "tokens=1,2 delims=; " %%i IN (root-servers.txt) DO echo %%j>> serversRAW.txt
for /F %%i IN (servers.txt) DO (
ldifde -f .backup-filesdfs-export.ldf -v -d "CN=Dfs-Configuration,CN=System,DC=domain,dc=name" -l objectClass,remoteServerName,pKTGuid,pKT,msDFS-SchemaMajorVersion,msDFS-SchemaMinorVersion,msDFS-GenerationGUIDv2,msDFS-NamespaceIdentityGUIDv2,msDFS-LastModifiedv2,msDFS-Propertiesv2,msDFS-TargetListv2,msDFS-Ttlv2,msDFS-LinkPathv2,msDFS-LinkSecurityDescriptorv2,msDFS-Ttlv2,msDFS-Commentv2,msDFS-ShortNameLinkPathv2,msDFS-LinkIdentityGUIDv2 > .backup-filesldf-export.log
reg save HKLMSoftwareMicrosoftWindowsDFSRoots C:TEMP%COMPUTERNAME%-dfsroots.hiv /y
The main backup job copies NSserverBackup.bat to each Namespace server and runs it from there.
rem Check input files
if not exist allRoots.txt goto :EOF
dsquery * "CN=DFS-Configuration,CN=System,DC=DC=domain,dc=name" -filter "(|(objectClass=fTDfs)(objectClass=msDFS-NamespaceAnchor))" | dsrm -q -subtree -noprompt
ldifde -I -f .backup-filesdfs-export.ldf -k -v > .backup-filesdfs-import.log
reg restore HKLMSoftwareMicrosoftDFSRoots C:temp%COMPUTERNAME%-dfsroots.hiv
The main backup job copies NSserverRestore.bat to each Namespace server and runs it from there.