UPM has been around for nearly 4 years now, and seems to have been well adopted, to the point where we’re starting to see some support calls along the lines of “I’ve outgrown my original user store and I need to migrate my users to a more scalable store, without losing my data.  How?”

There are some obvious solutions around using tools like robocopy and Profile Nurse (sepago.de), but they don’t fit all scenarios, as they tend to require some downtime, or high-bandwidth connections (or both).

So I’m going talk about a couple of other techniques that might help upgrade a live installation.  One of those techniques is a bit “off-the-wall”, but maybe it’ll inspire you.

Technique #1 – DFS is your friend

Suppose in the early days of my UPM deployment I had defined my profile store (i.e. Path to user store) to be \\MyCorpLonSrv01\profile$\#cn#

Imagine now that we’ve kept adding users, plus we really need to add a couple more file servers in the new Tokyo and Seattle offices, which are planned to have their own farms.  We can’t really afford any downtime, either.  And we’d rather do it without adding any new OUs for the moment.

Scaling UPM to thousands of users really needs DFS Namespaces, and it’s this that we’ll use.

Step 1 is to set up the new file servers \\MyCorpTkoSrv01 and \\MyCorpSeaSrv01 and create profile shares on each of them.

Step 2 is to create a DFS Namespace called (say) \\MyCorp\Profiles.  Beneath this namespace we can now create folders, and assign them to targets.  This is very similar to the technique described in eDocs at http://support.citrix.com/proddocs/topic/user-profile-manager-sou/upm-plan-high-availability-disaster-recovery-scenario1.html .  Typically we’ll use a department-based or a geo-based attribute from the AD user object to load balance.  The eDocs page suggests #l# (the location attribute) as a suitable example.

So at this point we have the following folders defined in a DFS namespace, pointing to the targets shown

\\MyCorp\Profiles\London   -->  \\MyCorpLonSrv01\profile$
\\MyCorp\Profiles\Tokyo    -->  \\MyCorpTkoSrv01\profile$
\\MyCorp\Profiles\Seattle  -->  \\MyCorpSeaSrv01\profile$

Step 3 is to add or fix all the AD user objects so that every user has a location attribute set to one of London, Tokyo and Seattle.  After that, you can simply change the path to user store policy to be \\MyCorp\Profiles\#l#\#cn#

Simple?

Maybe too simple…

But what if some early Tokyo users already have profiles on MyCorpLonSrv01, or if MyCorpLonSrv01 isn’t really powerful enough to handle all the users on it.  Or maybe there’s a merger/acquisition and we’re integrating hundreds of new users from the NewCorp domain?  This can be a real headache, as #cn# probably isn’t unique – consider that both MyCorp and NewCorp may have employees called “John Smith”, for example – we really need to switch the profiles to use %USERNAME%.%USERDOMAIN% rather than #cn#

We need a mechanism to migrate (some) users off MyCorpLonSrv01.  Of course, if we don’t mind a bit of downtime, it’s easy.  Use robocopy and/or Profile Nurse to migrate selected profiles to new servers, change the Path to user store and let everyone back on again.  And we’ll need quite a bit of bandwidth if we want to get all profiles copied over a long weekend, which may not work over intercontinental links.

But is there a way to do it without downtime, and without huge bandwidth?

Maybe…

Technique #2 – UPM Profiles are just like MS Roaming Profiles – Really!

(Warning – This is the off-the-wall one!)

UPM has a feature to migrate MS Roaming Profiles to UPM Profiles.  If UPM finds that a user doesn’t yet have a UPM Profile, it can be configured to migrate an existing Roaming Profile.

But what’s the difference between a UPM Profile and a Roaming Profile?  It turns out there’s very little difference at all.  This what you’d expect – if there were major differences between UPM Profiles and Roaming Profiles, then there would be application compatibility issues.

How little a difference?  On the local machine there’s a registry value in HKLM that tells UPM that the local profile for a particular user SID is actually a UPM profile.  And there are a couple of extra copies of the registry (NTUSER.DAT.START and NTUSER.DAT.NET) that UPM uses to merge registry changes – they’re temporary files that get deleted at logoff anyway.

On the profile store, there are a couple of extra files (PmCompatibility.ini and UPMSettings.ini) that record which machines have been sharing the profile, and how they’re configured.  There’s also the Pending area, which is a temporary area used for managing profile updates made by concurrent sessions.  If there are no sessions active, the Pending area will be empty.

So maybe we can convince UPM that our old UPM Profile is actually a Roaming Profile and get it to migrate it to a new UPM Profile in a new location.

Let’s see what we have to do…

First of all, we have to get rid of that registry value in HKLM.  If that’s around, UPM will find a UPM profile on the local machine but no UPM profile in the User Store.  UPM (rightly) regards this as an error condition.

To get rid of that registry value, we need to make sure UPM deletes the locally cached profile off the machine on logoff.  So we set the policy “Delete locally cached profiles on logoff”.  That gets rid of the profile and that troublesome registry value too.  It doesn’t have much effect on performance, as you should be using “Profile streaming” anyway.

Now we have to convince (=trick) UPM to treat the old UPM Profile as if it were a Roaming Profile, and migrate it.

UPM looks for Roaming Profiles by querying Group Policy and the AD User Account (the user object) in the following order:

  1. Group policy TS profile directory (if in TS session)
  2. User account TS profile directory (if in TS session)
  3. Group policy “normal” profile directory (if on Vista/7/2008)
  4. User account “normal” profile directory

So we need to set up one of these sources to point to the old user store, and all will be well.

The Group policy works by putting the path into a registry key+value, which will be either:

TS Profile:

Key HKLM:SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services
Value WFProfilePath 

(Value WFDontAppendUserNameToProfile should also be set if WFProfilePath already includes the user name, otherwise UPM tries to append Username.Userdomain or Username)

Normal Profile:

Key HKLM:SOFTWARE\Policies\Microsoft\Windows\System
Value MachineProfilePath

The equivalent attributes in the AD user account are:

TerminalServicesProfilePath

or

ProfilePath

respectively.

The two policies are machine policies, so may not be suitable in all cases.  However, it should be straightforward to script an AD update that overwrites either TerminalServicesProfilePath or ProfilePath for each user to reference the “old” UPM Profile path.  PowerShell, for example, provides Get-ADUser and Set-ADUser cmdlets that let a suitably-privileged administrator update the AD User Object.

So now we have a way to:

  1. Clear out the locally cached copy of the UPM profile
  2. Convince UPM that the old UPM profile is in fact a Roaming Profile, by setting the AD user attribute TerminalServicesProfilePath to the old UPM profile (for example, changing John Smith’s attribute to “\\MyCorpLonSrv01\profile$\John Smith”)

It just remains to point UPM at the new profile store (by changing the Path to user store policy to \\MyCorp\Profiles\#l#\%USERNAME%.%USERDOMAIN%) and UPM will migrate the old UPM profiles to the new user store, complete with name changes, and moving to new servers.

The best and the worst of this solution is that migrations happen when users log on.  If the logons are staggered, that’s great – your profiles will get migrated without straining your intercontinental link.  But if all your users log on at once – the classic “thundering herd” scenario – then this solution is no better than robocopy.

The mitigation is to move small batches of users at a time, moving them to a new farm with separate machines and the new user store, but still able to access the old user store.  Sadly this involves setting up either a new OU or at least putting WMI filtering on, to give the new farm a different Path to user store policy.

Conclusion

The moral of this tale is to get your Path to user store right in the first place.  If you don’t, it’ll be painful later.  Some specific points:

  • Don’t use #cn#.  Use %USERNAME%.%USERDOMAIN%
  • Do include a user attribute in the Path to user store that will help you load balance across file servers and across geos when your deployment grows.  Make sure your user attributes are also valid as NTFS folder names!
  • Plan from the start to use DFS Namespaces for scalable profile deployments

Hope that helps somebody…

PostScript

Some of you will be asking, has Bill actually tried any of this out?

No, but that’s not the point.

The point is to start some discussion on what issues UPM users have faced around this area, with a view of collecting some best practices and maybe setting UPM development direction.

  • Is this a realistic migration scenario?
  • How much control do UPM users typically have over their AD environment?  Can you set up an OU at the drop of a hat?  Or do you have to wait 6 weeks to get even the tiniest changes made?
  • Have you tried something like this, and did it work?
  • What other techniques have you found useful?
  • What new features or tools would be useful to you, to help in such a scenario?

Disclaimer

WARNING! Modifying the Active Directory incorrectly, either manually or by a script, can cause serious problems that may require you to restore your Active Directory. Citrix cannot guarantee that problems resulting from the incorrect modification of the Active Directory can be solved. Modifications of Active Directory, either manually or by script, are undertaken at your own risk.