Archive for the ‘Uncategorized’ Category

Dell XPS 12 – The Windows 8 Flagship?

Regular readers of my blog (all two of you) may recall the “series” I started this fall on Windows 8 launch devices (concerning the HP Envy X2 and the Samsung SmartPC Pro 700t). These devices both had strengths, but failed in other ways that made them difficult or impossible to support in an enterprise environment. This month, I got my hands on a device that breaks though that barrier and satisfies in a big way. The new Dell XPS 12 finally arrived on our campus about two weeks ago. We immediately were taken with its light weight (3 lbs.), sleek styling, and novel materials (full carbon fiber base, carbon fiber and aluminum lid, and that unique flip-over touch screen). The 8-second boot time is another impressive feature. A longer battery life would have been appreciated, but I can live with it. Other helpful enhancements would be the inclusion of an active stylus. I also would appreciate slightly more resistance in the keyboard.

Others have weighed in on the appearance, performance, and usability of this fancy Ultrabook, though, so I will forgo further commentary on those aspects of the XPS 12. What most concerned us was the ability to support OS redeployment, BitLocker encryption, and hardware servicing on our Campus.

We unboxed and re-deployed the computer with Windows 8 Enterprise within one day. There were a few deployment hiccoughs, but in general re-deployment was what we have come to expect from Dell. All required drivers for the XPS 12 were made available in a single downloadable CAB file. We extracted this CAB to our MDT/LiteTouch Deployment Share, rebuilt our boot media, and initiated a LiteTouch deployment. There was a brief problem getting LiteTouch to start… we needed to disable the “Safe Boot” option in EFI/BIOS, and we needed to set the EFI boot mode to “Legacy” to allow our boot media to operate. Once those changes were made, the XPS 12 booted to our USB WinPE media without complaint. Upon completion of deployment, all devices in the device manager reported as functioning. There were no “poorly-behaved” drivers that required un-scripted installation. We did find that the track-pad was behaving strangely. Investigation revealed that the PnP process had grabbed a Windows 7 track-pad driver from our deployment share. We corrected this manually, then separated our Windows 8 drivers from our Windows 7 drivers in the Deployment Workbench… this should prevent the problem from recurring in future deployments.

BitLocker was easy to implement. The TPM chip readily was recognized by the OS, and TPM-with-PIN encryption was accomplished in minutes. I spent half a day trying to encrypt an older Dell Latitude E6500 a few months back. This was a breeze by comparison.

On the servicing front, we have good news. Dell now is allowing on-site servicing for all XPS models, with full reimbursement for parts and labor for qualified technicians. Physical serviceability is a big concern for newer Ultrabooks. A troubling trend in tablet and notebook design is the use of solder on drive mounts and glue to hold batteries in place (the latest “Retina” MacBooks and the MS Surface tablets suffer from these problems). Fortunately, it appears that all major components of the XPS 12 can be removed and replaced without the need to re-solder or remove glue. The most frequently swapped components such as the battery, mSATA drive, and memory chips look pretty easy to access. The keyboard is a bit of a pain to get to, but at least it can be serviced.

If only more Windows 8 launch products had been this good… I hope we see more products of this quality coming from Dell (and other vendors) in the near future.

VMware View – Implementing Idle User Auto-Logout

We are going live with out first public VMware View terminals this week (Wyse P25 “zero-clients”… nice units).  I had what I expected would be a easy list of “little jobs” to be completed before going live. Famous last words…

One item on the list was implementing an “idle user logout” process.  This process would detect when a View session had gone idle, and would disconnect the session automatically (preferably after prompting the user).  This disconnected session then would be logged out by View Manager after a fixed amount of time.

This proved rather more difficult than I had predicted.  I tried several solutions before arriving at one that worked.  Among the failed solutions:

  • Using Group Policy to configure Remote Desktop Session Manager idle session limits.  The View configuration documents imply that this should work, but it does not.  I expect that the policies would be effective if you were connecting to your View desktops using RDP, but PCoIP sessions just will not disconnect automatically (at least, they would not for me).
  • Using the Windows Task Scheduler to configure a disconnect script that will trigger on idle.  This did not work for two reasons.  First, the Task Scheduler only evaluates for idle conditions every 15 minutes.  Second, for the Task Scheduler, “idle” means not only that the user is not directing mouse and keyboard to the computer, but that the CPU also is not doing anything.  As a result, we could not get consistent auto-logout times.

The solution that we settled on involved the use of a custom screensaver developed by the “Grim Admin”.  ”ScreenSaver Operations”:

http://www.grimadmin.com/staticpages/index.php/ss-operations

This is a great little utility that accomplishes what the “WinExit” screensaver used to for Win XP.  (WinExit cannot easily be used on Win7, and is a bit hostile to 64-bit Windows).  Screensaver Operations has a well-written README describing the use of registry entries to control the screensaver globally (i.e. for all users on the computer).  I set these registry operations as Group Policy Preferences, and we are in business.

Two slight complications… since the screensaver is 32-bit, you need to use the “sysnative” filesystem redirector if your want the screensaver to trigger 64-bit executables.  In our case, I wanted the screensaver to launch “tsdiscon.exe” (to disconnect the View session), so I had to use the path:
%windir%\sysnative\tsdiscon.exe
Additionally, you will need to specify the full path to the screensaver in the Group Policy dialogs (i.e. %SystemRoot%\SysWOW64\Screensaver Operations.scr).  If you fail to do so, the screensaver will appear to be configured in the Control Panel, and you will be able to preview it by clicking the “preview” button, but the screensaver WILL NEVER START.

Ashamedly I will admit that this little challenge too much longer to accomplish than it should have.  No wonder lab managers burn out so easily.

Evaluating Windows 8 Tablets – Samsung ATIV SmartPC Pro (700T)

The journey continues…

The boss approved purchase of a Samsung ATIV SmartPC Pro (the “700T” model).  I wassoooexcited… this was the tablet PC I had been waiting for.  Thin, light, and fully convertible from Ultrabook to slate.  Stylus included, 1080 high-definition display, full Intel i5 processor.  So much to love…

First impressions were really positive.  The build quality seemed really high… solid magnesium case, good keyboard response, fast boot, very responsive Wacom digitizer stylus.  As a tablet, this thing is awesome. And while it is expensize compared to an iPad, it is very cheap compared to the Tablet PCs of yesteryear.

However, I quickly ran into trouble.  When typing with the SmartPC on my lap, the keyboard would frequently disconnect from the display.  It would not fall off, but the tablet component would lose electrical connection to the keyboard, causing typing input to stop.  Sometimes this would happen as often as five times in a single line of text.  Awful!

There were other problems as well.  Like the HP Envy X2, the screen does not tilt back far enough to allow comfortable use of the keyboard on a countertop.  The 1080p display, which is very crisp and bright, is inconvenient to use for remote desktop connections to Server 2008 R2 and earlier hosts (the fonts do not scale for remote desktop sessions, leading to comically tiny print size and rediculiously small buttons and window controls).  The system did not include a TPM chip (that is only available on the models that ship with Win8 Pro… something that was not clear when ordering the device).  And finally, Samsung does not bundle drivers for the SmartPC in any way that is convenient for business deployment.  Re-imaging the systems would be a pain.

It also is worth noting that Microsoft decided that in-place upgrades of retail versions of Win 8 to volume license editions woudl not be supported.  If you want simply to install Win 8 Enterprise over the factory-shipped consumer edition of Win8, you are out of luck.  I also experienced this problem with the HP Envy X2.  For corporate users, volume license installs are strictly a nuke-and-repave operation.  Booooooo!  This is not Samsung’s fault, but the lack of support for business deployment (i.e. driver bundles or driver repository building tools) is a killer for the SmartPC in the enterprise.

I really wanted to love this device, but I really just have to return it.  Consumers seeking a top-performance tablet may love it, but it does not work for this sysadmin.  I am hoping that the Lenovo ThinkPad Helix will work out better.

Evaluating Windows 8 Tablets in the Enterprise – HP Envy X2

In desperation over our inability to tell University employees what they should be looking for in a Windows 8 tablet, I asked the boss if we could get our hands on one of the new Intel “Atom” processor-based Windows 8 tablets (these are the “Clover Trail” Atom processors, designed to compete with ARM-based devices).  I had been wanting to eval a Samsung ATIV Smart PC 500T, but these have been hard to get locally.  Instead, I bought a hot-off-the-shelf HP Envy X2.  This device boasts a well-engineered all-metal shell, full size keyboard dock with full-sized HDMI and SD card readers, and an extra battery in the dock for a claimed 15-hour run life.  It also claims to support an optional digitizer stylus.

I only have just started putting the machine though its paces.  My first impression is that it performs surprisingly well as a standard notebook, but that there will be significant challenges in supporting these types of devices at the same level as our existing business-model Dell systems.  I am not going to bother “reviewing” this tablet… others in the trade can handle that.  Rather, this blog post is going to address the challenges of supporting a consumer tablet in a business environment.

  • Processor:  The new “Clover Trail” Atom processors are 32-bit only.  Surprise!  I though the industry was leaving 32-bt behind, but it appears to be alive and well.  We had made the initial decision to support only 64-bit Windows 8, and have developed only 64-bit baseline images.  I see that this choice will need to be reconsidered.
  • EFI/UEFI:  These new systems boot using EFI, with emulated BIOS, with the “SafeBoot” option enabled.  Out of the box, you cannot boot to USB because the SafeBoot prohibits this.  You need to load your OS to change EFI options.  EFI is not identical between systems, so navigating the process of booting to deployment/maintenance media will be a tough challenge for technicians to work through.  I actually was completely unable to boot the Envy X2 to an USB flash drive, running either WinPE (MDT boot media) or the FreeDOS-based(?) CloneZilla  live CD.  Bummer.
  • Drivers:  Most new tablets are aimed at the consumer market.  As a result, the vendors make little effort to package drivers in a way that is convenient for local IT staff to integrate into on-premise Windows deployment tools.  The Envy X2 is no exception.  A small handful of one-off driver installers are available, including a big bundle of Intel Chipset drivers.  The chipset drivers were critical in getting a freshly installed Windows 8 Enterprise OS working with the hardware.
  • Windows Editions:  This tablet shipped with “Windows 8″.  Not “Home”, not “Professional”, not “Ultimate”.  I tried performing an in-place SKU upgrade to Windows 8 Enterprise, but setup.exe said that this was not supported, so I needed to do a full OS install.  This process worked, but it was seriously aggravating to have to boot to the OEM OS, start the Enterprise OS install, re-install all of the required drivers, then clean up the original OS install.  Our users will not want to have to deal with this, and it will make our IT support staff very tired.
  • Hardware:  No Ethernet.  Unfortunately, our MDT/LTI deployment tools are designed to run over Ethernet, not Wi-Fi.  The LTI scripts actually will terminate if a Wi-Fi connection is detected.  Of course, application-only LTI task sequences really should run just fine over wireless, but the scripts still will not run over wireless.  We either will have to comment out the Wi-Fi checks, or require that the person launching LTI have a USB Ethernet dongle handy.

So… a lot of challenges.  More details as time permits.

Oh, one small “review style” note.  I decided to evaluate this tablet because HP claims that it supports an optional stylus.  However, the stylus for this device is not actually available for sale at this time.  Further, the device does not use the common Wacom or N-Trig digitizers, so buying a spare “Bamboo” stylus will not help you here.  HP has chosen to use the new “Atmel” integrated touch/pen sensors, and as such an Atmel-compatible stylus is required.  I cannot find these on the market anywhere.  As a result I cannot make any recommendation for or against the purchase of this device for Tablet PC enthusiasts.  I don’t even know if the stylus will be available for sale before the return period for this device expires.

UPDATE:

I returned this tablet.  Why?  It was not the screen resolution, which I though would be a problem but was not.  There were three primary reasons:

  1. It was not possible to determine the quality of the digitizer within the return period of the tablet.  I was unwilling to accept the risk of having a low-quality stylus for note taking.
  2. Keyboard dock quality was low.  The keyboard itself was reasonably good, but the trackpad was very annoying.  The texture was awful, and it was overly sensitive to the slightest palm brushes.  Given the small size of the keyboard deck, it was impossible to avoid brushing the trackpad, too.  Also, the screen did not tip back far enough for comfort when used on a countertop or other waist-height surface.
  3. Business deployment essentially was unsupportable.  HP support could not assist me with initialization of the TPM chip for BitLocker.  It appeared that a TPM was present, but there was no option in BIOS to reset the TPM, and the OS could not get ownership of the chip.  Also, the total lack of driver bundles would make deployment using MDT very difficult.
  4. The graphics card could not drive my external display at native resolution.  It maxed out at 1080p.

I did quite like this tablet, though.  Consumers seeking an additional computer for the road may really enjoy using it.  For fussy power users like me, it was close butnot quite there.

Windows 8 Hardware – Waiting for Godot?

I have been running Windows 8 CP on my primary workstation for about two weeks now.  The experience is surprisingly good, although I am sure that work-a-day users of Windows are going to freak out at the site of the Metro, especially when accessed from the traditional Windows keyboard and mouse.  To that end, I though it might be useful to get my hands on some touch-enabled hardware.

This has tuned out to be less than feasible.  According to the Windows 8 build blog, Win8-certified touch devices will have to be capable of handling five-point touch input:
http://blogs.msdn.com/b/b8/archive/2012/03/28/touch-hardware-and-windows-8.aspx

This is an interesting point of data, because Windows 7 “touch ready” devices only needed to support two-point multi-touch.  Thus, the almost then entire mini-ecosystem of touch devices that were built for Windows 7 will never get a Win8 certification.  Those touch monitors from Dell and HP?  Nope.  All-in-one touchscreen PCs from a multitude of manufacturers?  Nope. 

It looks as though the Win8 touch interface has been designed with the capacitive multi-touch displays that are commonplace on tablets and smartphones in mind.  But even a number of current Tablet PC and Windows Slates with capacitive multi-touch will be out in the cold, as a lot of them only support four-point multi-touch.  As for multi-touch monitors, the only that I can find that support 5+ points of touch are the 3M displayes referenced in theWin8 Build blog (see above).  Since these displays retail for over $1000, I think most people would be better off buying a tablet like the ASUS EP121, ASUS B121, or the Samsung Slate 7.

I suppose you might be able to get some mileage out of multi-touch track pads.  Most newer laptops have pads that support multi-touch, but my venerable Dell E6500 does not.  To that end, I am going to try out a Logitech TouchPad Wireless to see if having a gesture-supporting track pad buys me anything in Win8-ville.  I’ll post back with results.

In any event, it seems that those wanting to see what the Windows 8 touch experience will really be like are going to have to wait on some hardware that does not yet exist.  Touch screen ultrabooks?  Hopefully this will be more fruitful than Waiting for Godot.

SharePoint 2010 – External Trust Configuration

Today I am attempting to get SharePoint 2010 to work with accounts stored in an Active Directory forest that is external to the SharePoint server.  This would be our “guest forest”.  Lots of tips are available in the net:

It is worth noting that the need to provide a username and password for search domain outside of the SharePoint web server’s domain is based on the type of trust that is present between the SharePoint server domain and the searched domain.  If the searched domain trusts the SharePoint domain (and selective authentication is not being enforced), no account credentials needs to be provided.

I used ”forest:guest.uvm.edu” as the external forest to search.  Now the people picker returns results from the external forest.  Good!  Unfortunately, when you go to apply permissions to the external user in a SharePoint site, I get a “No exact match was found. Click the item(s) that did not resolve for more options” error.  What gives?

The following thread seems to touch on this issue, but the resolution is a bit vague:
http://social.msdn.microsoft.com/Forums/en/sharepoint2010general/thread/edfc0ade-e994-44a3-a2e8-335abd9694ff

However, the “Full Metal Architect” page (first link in the bulleted list above) does suggest that using a “forest” search could return more limited search results, because it only queries the global catalog for user properties.  Just for grins, I converted the search scope to “domain:guest.uvm.edu”, did another IIS reset, and now I can add users.  Strange.

Ultimately, to ensure that both local domain and guest domain accounts could be searched and added using the people picker, I had to run the following commands:

stsadm -o setproperty -url [sharepointUrl] -pn peoplepicker-searchadforests -pv "domain:campus.ad.uvm.edu;domain:guest.uvm.edu"

-and-

stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:campus.ad.uvm.edu;domain:guest.uvm.edu"

(note the abasence of the “-url” parameter in the second command)

I expect one of these commands really was not necessary, but now that things are working the way I want them to, I am going to leave well enough alone.

 

Windows file server aliases, NetBIOS over TCP, and Incomplete Documentation

It was inevitable… some people have started to notice that their bloody Multi-Function Devices (the overpriced beasts formerly known as “printer/scanner/copiers”) no longer can scan to our file server.  Why?  Because we got all smarty pants and tried to disabled “NetBT” (NetBIOS over TCP) for access to our new file server.  We figured “Hey, CIFS over TCP has been available since, what, 1999?  We won’t have any problems with back level clients!”.  Rubes.  Turns out a lot of MFDs still require NetBT.  Rather than be a pain, I have decided to enable NetBT on the new server.  After all, it is mainly the laggards that suffer the consequences of back-level clients (and besides, if I don’t do this I will either have to go update their firmware myself, or locate some mythological pile of gold to pay for new MFDs).

The tricky bit for us was that our clients are using a name other than the server’s primary name to access the server.  Modern clients don’t care.  SMB2-capable systems only require that the server name being used has a valid matching DNS entry, and if you want Kerberos to work, you need to add a matching Service Principal Name (SPN).  We tested that our a long time back, and had no SMB2 client issues at go live.  SMB1 is a bit more fussy… you need to tell the server not to get bent out of shape when the requested server name is not the primary server name by adding the “DisableStrictNameChecking” DWORD in the HLKM\System\CurrentControlSet\Services\LanManServer\Parameters registry key.  We picked up on that one on migration night.

But now, after activating NetBIOS over TCP, client systems still are giving us grief.  Upon connection, we can see the NetBIOS Session Service reporting “Called Name Not Present” in a wire trace.  What gives?  DNS, SPN, and WINS entries are not enough for good-old LanMan?  Sounds like the server needs some additional convincing.

It turns out the key is in “optional names”.  When I added a Reg_multi_sz entry named “OptionalNames” to the HLKM\System\CurrentControlSet\Services\LanManServer\Parameters registry key, populated it with the alias name of our file server, activated NetBIOS over TCP, then rebooted, I found that the server started granting connection requests on TCP Port 139 (the legacy NetBT CIFS port).  Horray!  As an added bonus, our windows server is now registering both its primary name and its supported alias in WINS and DNS… no need for static entries.  Now to see if the MFDs are satisfied…

It really is a pity that there is no one article on this subject in TechNet.  It appears that the folks at Microsoft have little belief that anyone would be so asinine as to want to have a file server with an alias, and support for CIFS over NetBT, and support for CIFS over TCP, and support for modern SMB2 clients.  I’ll bet a consultants would say “Gee, I have never seen this before”.  We get that a lot.

Articles that helped during this troubleshooting process:

The Cake is a lie (and so is abecmd.exe)

In addition to playing Portal 2 (good work, Valve guys!), I have been doing that some of thing called “work”. Today I decided to get back to the question of whether it is possible to enable and disable the Windows file server feature known as “Access Based Enumeration” (or “ABE”) from the command line.

Documentation suggests “yes”, that this is possible, using a tool known as “abecmd.exe”. Unfortunately, I can find no evidence that such a tool exists on Server 2008 R2. Curious… under Server 2003 R2 you needed to use the command line to enable ABE. Now under 2008 R2, you cannot (easily) use anything other than the GUI. Also interestingly, the only GUI that supports enabling ABE is the “Share and Storage Management” MMC that is included with “Server Manager” (the old “Shared Folders” MMC does not have this feature, and neither does the “Sharing” tab in Windows Explorer). It gets even better… if you create a share from the command line using “net share”, ABE is not enabled on the share. WTF? I thought Microsoft was supposed to be reducing the number of features that require the GUI, not ramping them up.

Of course, the ABE flag can be set using the NetShareSetInfo function of the netapi32.dll. However, using these older dlls in PowerShell is a touch more complicated than I care to deal with on a daliy basis. Have gander at this code:
http://poshcode.org/1635
Yuck! (No insult to the code intended… I just mean that I should not have to deal with this to perform basic share admin tasks!)

Fortunately, Bill Steward over at Windows IP Pro has taken mercy on us:
http://www.windowsitpro.com/article/scripting/managing-abe-from-the-command-line
Here he provides a small executable called “ShareABE.exe”, with source code, that will show and set ABE status on a server share.

Thanks, Bill!

I sure hope that Window Server “8″ includes a new .NET assembly for file and print server management. These old APIs are a real pain in the keister.

Migrating from NetApp to Windows File Servers with PowerShell – part 4

In our final entry in the Windows File Server management with PowerShell series, we have a quick look at managing shares using powershell.

The one feature of the NetApp that I will miss most was the automatic home share. Similar to Samba, you can tell the filer a set of directories under which user home directories are located. The filer will create these shares on-demand for a connecting user. Even under Server 2008 R2, Windows has no such capability. So what is the solution? Well, we have to create a share for every user. Augh! Fortunaltely, a beefy box can handle all these shares fairly gracefully, and with PowerShell, creating the shares is fast.

Some logic we added to this script includes probing for existing shares using “net share” before we attempt to create the share. If output of “net share” shows that the physical directory path is not correct, we delete the existing share and re-create it. If the share exists, and has the correct path, we don’t touch it. If the share does not exist, we create it.

I learned a fair bit about invoking external commands with PowerShell while writing this script. To summarize, PowerShell is not much like cmd.exe. When invoking a command with multiple parameters, you very often need to separate the parameters into array components, otherwise PowerShell does not know where to delimit the parameters. For example, let’s say we want to run the command:

net share jsmith=h:\homes1\j\jsmith /GRANT:DOMAIN\jsmith,FULL

The username and path are to be populated using variables in the script, so we try:

& net share ($uname)=($path) /GRANT:DOMAIN\($uname),FULL

Looks good, right? Unfortunately, not. The PS invocation command (“&”) parses the command parameters incorrectly, and thus passes a bunch of trash to the “net.exe” external command, and thus puts nasty red errors all over your console.

What we need to do is put the command parameters into an array, and feed that to the PS invocation command:

[string] $cmd = 'net.exe'
[string[]] $params = 'share', ($uname + '=' + $path),`
     ('/GRANT:DOMAIN\' + $uname + ',FULL')
& $cmd $params

Or perhaps more readably:

[string] $cmd = 'net.exe'
[array] $params = @()
[string] $params += 'share'
[string] $params += $uname + '=' + $path
[string] $params += '/GRANT:DOMAIN\' + $uname + ',FULL'
& $cmd $params

I do something similar below, showing once again that there is more than one way to code a cat (and that some cats are better looking than others):

# Shares all directories at the third directory level of the 
#	volumes specified in $homeVols.
# Assumes that all subdirectories will have a name matching an 
#	existing CAMPUS user ID.

Set-PSDebug -Strict

[string[]] $homeVols = @()
$homeVols = "h:\","i:\","j:\","k:\","l:\","m:\","n:\"

foreach ($vol in $homeVols) {
    $subDirs1 = gci $vol | ? {$_.Attributes.tostring() -match "Directory"}
    foreach ($dir1 in $subDirs1) {
        $subDirs2 = gci $dir1.FullName | ? {$_.Attributes.tostring() `
			-match "Directory"}
        foreach ($dir2 in $subDirs2) {
            $uhomes = gci $dir2.FullName | ? {$_.Attributes.tostring() `
				-match "Directory"}
            if ($uhomes.count -ge 1) { foreach ($uhome in $uhomes) {
				[bool]$doShare = $false
                [string] $cmd = "net.exe"
                [string] $arg1 = "share"
				[string] $arg2 = ($uhome.name)
				[string] $out = & net $arg1, $arg2 2>&1
				[string] $homePath = $vol + $dir1.name + "\" + $dir2.name + "\" `
					+ $uhome.name				
				[string] $homePathRX = $vol + "\" + $dir1.name + "\\" `
					+ $dir2.name + "\\" + $uhome.name
				if ($out -match "does not exist") {
					write-output "Share does not exist for $homePath"
					[bool] $doShare = $true
				} elseif ($out -notmatch $homePathRX) {
					write-output "Share not defined correctly for path $homePath"
					[bool] $doShare = $true
					#Delete existing share
					[string] $arg3 = "/DELETE"
					[string] $out = & net $arg1, $arg2, $arg3 2>&1
				}
				
				if ($doShare) {
	                [string] $arg2 = ($uhome.name + "=" + $homePath)
	                [string] $arg3 = "/Grant:CAMPUS\" + $uhome.name + ",FULL"
	                #write-host "about to share: " $uhome.name
	                # The next line will call the "net" command to share the 
					#	current home directory.
	                # If no mapping can be made between the directory name and 
					#	an AD user, "No Mapping" will be in the error output.
					
	                [string] $out = & net $arg1, $arg2, $arg3 2>&1   
	                if ($out -match "No Mapping") {
						Write-Output `
							"User was not defined for share on path $homePath"
	                   $uhome.name | out-file -FilePath h:\noMapUsers.txt -append 
	                } else {
						Write-Output "Successfully shared $homePath"
					}
				}
            }} #End if ($uhomes.count -ge 1)
        } #End $dir2 in $subDirs2
    } #End $dir1 in $subDirs1
} #End $vol in $homeVols

Migrating from NetApp to Windows File Servers with PowerShell – part 3

In our old NetApp environment we utilized quotas extensively. We want to map our NetApp quotas to Windows File System Resource Manager quotas in a failrly seamless fashion. Fortunately, with PowerShell, this is almost easy. Microsoft gives us the FSRM.FsrmQuotaManager and FSRM.FsrmQuotaTemplateManager “COM” object classes, documented here:
http://msdn.microsoft.com/en-us/library/bb613257(VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb613280(v=VS.85).aspx
PowerShell works with these with ease.

I got a jump start on these scripts from my brethren on the Internet. Perhaps the most helpful post was Ben Lye’s entry on “Simple-talk”:
http://www.simple-talk.com/sysadmin/exchange/implementing-windows-server-2008-file-system-quotas/

First task… create FSRM quota templates that are similar to our NetApp qtree quotas. We don’t need to use “templates”, but it makes management a bit easier, so we will:

#Creates simple hard-limit directory quotas of the GB values specified in $tholds.

Set-PSDebug -Strict
$qtm = New-Object -com Fsrm.FsrmQuotaTemplateManager

[int[]] $tholds = 25,50,100,150,200,300,400,600,800,1200

foreach ($thold in $tholds) {
	$templ = $qtm.CreateTemplate()
	[string] $tName = [string]$($thold) + " Gb Shared Directory"
	$templ.Name = $tName
	[long] $tLimit = $thold * 1073741824
	$templ.QuotaLimit = $tLimit
	$templ.Commit()
	Clear-Variable templ
	Remove-Variable templ
}

Now we want to map our NetApp quotas to the new FSRM quotas. Challenges here are:

  1. extracting structured data from the NetApp “quotas” file.
  2. mapping NetApp quotas to the nearest-larger FSRM quota template.

The first challenge is handled using the .NET RegEx and String classes. It was a hack job, but it worked.

The second challege was handled using the powershell “switch” command. The one roadblock I ran into here was caused by a failure to cast a variable as the appropriate data type. For those who did not already know, you never, uh, I mean always should cast your valiables. Why? Look at the switch in the code below… what do you think happens when you compare the un-cast pipeline variable ($_) to “100″? Did you answer “geez dude, I don’t know, that’s a gibberish.”? Join the club. Did you answer “PowerShell does a string comparison, dude! $outQuota was an array of strings! What the heck were you thinking? Do you want 1000 to be considered a larger value than 25?”? If so, then you are correct. If you want to do mathematical comparison, you must cast your valiables an numbers. And by the way, do not cast large numbers as “[int]“. Why? Because [int] will not exceed 32-bits in length. Use [long] or [double] instead.

# Applies quota templates to s:\shared subdirectories, mapped from input file
# specified in $inQuota (the NetApp quotas file)
# NetApp quota limits are matched to the closest larger Windows quota template.

Set-PSDebug -Strict

#parse NetApp quota file:
$inQuota = Get-Content '\\files\etc$\quotas'
$outQuota = @()
#following loop strips all but the shared directory name and hard limit from input:
foreach ($line in $inQuota) {
	$arrLine = @()
	if ($line -match "/vol/vol2/") {
	[string] $ind0 = [regex]::split($line," tree ") | Select-Object -Index 0 |`
		% {$_.trim()} | % {$_.replace("/vol/vol2/", "")} | % {$_.replace('"', '')} 
	[string] $ind1 = [regex]::split($line," tree ") | Select-Object -Index 1 |`
		% {$_.split("G")} | select-object -index 0 | % {$_.trim()}
	$outQuota += ,@($ind0,$ind1)
	}
}
Remove-Variable inQuota

#instantiate quota manager:
$qm = New-Object -com Fsrm.FsrmQuotaManager

foreach ($quota in $outQuota) {
	#determine Windows Quota Template that is closest to NetApp quota:
	[long] $qVal = $quota[1]
	switch ($qVal) {
		{$_ -le 1200} {[string]$qtl = "1200"}
		{$_ -le 800} {[string]$qtl = "800"}
		{$_ -le 600} {[string]$qtl = "600"}
		{$_ -le 400} {[string]$qtl = "400"}
		{$_ -le 300} {[string]$qtl = "300"}
		{$_ -le 200} {[string]$qtl = "200"}
		{$_ -le 150} {[string]$qtl = "150"}
		{$_ -le 100} {[string]$qtl = "100"}
		{$_ -le 50} {[string]$qtl = "50"}
		{$_ -le 25} {[string]$qtl = "auto"}
	}
	# values 25 or smaller use an autoapply template, so skip these...
	if ($qtl -notmatch "auto") { 
		# create a quota object by retrieving an existing auto-apply quota, then update:
		[string] $deptDir = 's:\shared\' + $quota[0]
		$qObj = $qm.GetQuota($deptDir)
		[string] $templ = $qtl + " Gb Shared Directory"
		$qObj.ApplyTemplate($templ)
		$qObj.Commit()
		Clear-Variable qObj
		Remove-Variable qObj
	}
}

Now moving on to user home directory quotas… we used “AutoApplyTemplates” for this situation. AutoApply templates force afixed quota onto all new subdirectories of a parent. In this way, we avoid having to set a template manually for every new user home directory. Our file server contains six volumes (h:-m:), each containing a “homes1″ subdirectory, each of which in turn contins subdirectories 0-9, a-z. Individual home directories are nested within these. We needed to apply AutoApplyTemplates to these 0-9,a-z directories. Easy…

# Applies an Auto-Apply quota to all directories at the second directory level 
# of the volumes specified in $homeVols.

Set-PSDebug -Strict

[string[]] $homeVols = @()
$homeVols = "h:\","i:\","j:\","k:\","l:\","m:\"

$qm = New-Object -com Fsrm.FsrmQuotaManager

foreach ($vol in $homeVols) {
    $subDirs1 = gci $vol | ? {$_.Attributes.tostring() -match "Directory"}
    foreach ($dir1 in $subDirs1) {
        [array] $subDirs2 = gci $dir1.FullName | ? {$_.Attributes.tostring() -match "Directory"}
        if ($subDirs2.count -ge 1) { foreach ($dir2 in $subDirs2) {
            [string] $uPath = ($vol + $dir1.name + '\' + $dir2.name)
			[string] $template = "10 Gb Home Directory"
            $quota = $qm.CreateAutoApplyQuota($template,$uPath)
            $quota.Commit()
            clear-variable quota
            remove-variable quota
        }} #End if ($subDirs2.count -ge 1)
    } #End $dir1 in $subDirs1
} #End $vol in $homeVols

On the NetApp, we had a single volume that hosted users with a larger home directory quota. Under Windows, we can simply set a different directory quota for these individuals which overrides the AutoApplyTemplate. I have done this for the existing 25Gb quota users already, using PowerShell:

# Applies a new quota to the third-level directory of the volumes specified in $homeVols, 
#  under the path $homeVol:\homes2\[a-z]\[samAccountName]

Set-PSDebug -Strict

[string[]] $homeVols = @()
$homeVols = "n:\","m:\"

$qm = New-Object -com Fsrm.FsrmQuotaManager
$qtm = New-Object -com Fsrm.FsrmQuotaTemplateManager

foreach ($vol in $homeVols) {
    [string] $dir1 = $vol + "homes1"
    $subDirs2 = gci $dir1 | ? {$_.Attributes.tostring() -match "Directory"}
    foreach ($dir2 in $subDirs2) {
        [array] $uhomes = gci $dir2.FullName | ? {$_.Attributes.tostring() -match "Directory"}
        if ($uhomes.count -ge 1) { foreach ($uhome in $uhomes) {
            [string] $uHomePath = ($dir1 + '\' + $dir2.name + '\' + $uhome.name)
            $quota = $qm.GetQuota($uHomePath)
            $quota.ApplyTemplate("25 Gb Home Directory")
            $quota.Commit()
            clear-variable quota
            remove-variable quota
        }} #End if ($uhomes.count -ge 1)
    } #End $dir2 in $subDirs2

} #End $vol in $homeVols

And that is all I have for quotas for now. We will need to enhance our templates with threshold alerts and notifications in the future. This could prove interesting as the IFsrmObject.IFsrmQuotaBase class looks a bit challenging to deal with:
http://msdn.microsoft.com/en-us/library/bb613248(v=VS.85).aspx