Working with NetApp using PowerShell

NetApp, among many things, manufactures Storage Area Networks or SAN. A SAN is a critical piece of any large enterprise, particularly when you are working with clusters. SAN's provide (among many things) the ability to share disks between servers. With Server 2008 and Hyper-V, a 16 Node cluster is absolutely a possibility. In the world of Netapp, you have an aggregate, which consists of volumes, and volumes consist of LUN's.  LUNS are the things that show up as disk in Disk Management when you connect to Netapp.

There is a new project up on CodePlex called PowerShell OnTap which is a set of PowerShell scripts that can be used to manage a NetApp storage device. Once you dot source the two scripts, you will have access to a bunch of functions that have a noun of NA. There is even a function called get-nahelp which walks you through some basic commands to get you up and running.

Once you create your NetApp Server Object, you can run the Get-NaSystemAPIs command to see all stuff you can party with.

Here, I filtered it down to just the commands I can do with LUN's

153 >  Get-NaSystemAPIs -server  $server | ?{$_.Name -like "lun*"} | select Name


154 >


All kinds of goodness !!


Here are a few more functions I came up


function Get-NtapVolume
    param ( [string]$filer, 
    $server = New-NaServer -server $filer -credentials $credential
    $request = New-NaRequest -name "volume-list-info"
    $result = Get-NaResult -server   $server -request  $request
    $sizeUsed = @{Name="SizeUsed";Expression =  {[int64]($_."size-used"/1GB)}}
    $sizeAvailable = @{Name="SizeAvailable"; Expression = {[int64]($_."size-available"/1GB)}}
    $percentageUsed = @{Name = "PercentageUsed";Expression = {[int64]$_."percentage-used"}}
    $volumes = $result.volumes."volume-info" | select name,$sizeUsed,$sizeAvailable,$percentageUsed
    return $volumes


function Get-NtapLun {
    param ( [string]$filer, [System.Management.Automation.PSCredential]$credential) 
    $server = New-NaServer -server $filer -credentials $credential
    $request = New-NaRequest -name "lun-list-info"
    $result = Get-NaResult -server   $server -request  $request
    $size = @{Name="Size";Expression =  {[int64]($_."size"/1GB)}}
    $luns = $result.luns."lun-info" | select path,$size,online,mapped
    return $luns

function New-NtapLun {
    param (    [string]$filer, 
            $server = New-NaServer -server $filer -credentials $credential
            $request = New-NaRequest -name "lun-create-by-size"
            $request.Parameters += New-NaRequestParameter -name "path" -value $fullPath
            $request.Parameters += New-NaRequestParameter -name "size" -value $size
            $result = Get-NaResult -server   $server -request  $request
            $returnObject = "" | select Name,Size
            $returnObject.Name = $path
            $returnObject.Size = $result."actual-size"
            return $returnObject


V2 Script Cmdlets

One feature of PowerShell V2 that is being touted by many developers and hard core scripters is Script Cmdlets. This is essentially the ability to build full blown cmdlets natively in PowerShell. You will no longer have to venture into the world of C# or VB .NET to build a  real Cmdlet. I've been working on a Cmdlet in C# over the last week or so and up until then I don't think I was able to fully appreciate the power that is coming with Script Cmdlets. Now that I have seen what you can do in C# and really how ridiculously easy it is to do, I can't wait to start developing Cmdlets in PowerShell.

One of the most frustrating problems in Version 1 was having to deal with parameters. Specifically, figuring out how to get input from the pipeline if its available, and from specifying the parameter name directly. Script Cmdlets solve this problem beautifully!

When developing a cmdlet in C#, you use something called attributes that get tacked on to the parameter that is being declared. Just as an example, lets say we were writing a cmdlet to create a new Hyper-V Virtual Machine. When you create a new VM, you want to be able to specify the number of CPU's.

You can do this with the following code:

            Position = 2,
            Mandatory = false,
            ValueFromPipeline = true,
            ValueFromPipelineByPropertyName = true,
            HelpMessage = "Please enter the number of Processors to add to the VM (1-4)"
        [ValidateRange(1, 4)] //can only have up to 4 processors
        public int NumberOfCpus { get; set; }

In this code, there is a bunch of things going on, but they are fairly self-explanatory if you dig in to them. First of all, the actual parameter is just an integer named NumberOfCpus that is being declared at the very bottom. All the attributes are declared above the object that they are tied to.

In this case I have added the Parameter attribute with a few options. The first is that this is this parameter is the second parameter if no name is specified. The second is saying that this parameter is not required, by declaring "Mandatory" to be false.

The next two options are the ones that solve the pipeline problem. I can't tell you how great this will be in V2. Just by declaring these options, you can grab objects from the pipeline and inject them into the argument of your parameter.

There is a reason there are two options here. The first one is used for basic pipeline input. Take, for example, get-content servers.txt | new-vm. If there was a parameter called Name that accepted values from the pipeline, that would work.

The ValueFromPipelineByPropertyName is a little more tricky. This is the reason this command works

get-process notepad | get-childitem



This is because get-process notepad produces a "Process Object" which has a property called path. When that object gets sent to get-childitem, get-childitem has a parameter called path and PowerShell links the two up and moves on.

The last couple options are pretty self explanatory, but worth mentioning. You get interactive help for free, just by declaring the HelpMessage string, and you can do all kinds of validations on the input. Here I have specified a range of valid numbers for the Number of CPU's, so someone doesn't try to create a VM with 197 processors.

It is truly amazing how much plumbing that the PowerShell engine does that we can use for free. Its gonna be awesome. Oh yeah, and then distributing and sharing these things within the community is going to be orders of magnitude easier with the advent of modules.

Windows 7 Available at PDC

The Professional Developer's Conference, or PDC, will be taking place in LA from Oct 27th to the 30th. According to this post, Attendees will be able to receive pre-beta copies of Windows 7.

Getting Admin’s to adopt PowerShell

The RTM of PowerShell was released over 2 years ago. But still there are multiple occasions in which I find myself trying to convince someone that they should really start looking into using this incredible new tool but they end up fighting me pretty hard. There have been a couple consistent themes that I have detected in these conversations that I think are very valid points.

First, I would like to point out that my role at work is a System Engineer. I am not the Operations guy down in the trenches with Ninjas on fire chasing me everywhere I go. My role on the Infrastructure team is to figure out how to incorporate new technology into our existing infrastructure without breaking stuff. I also help troubleshoot issues that get escalated to our team. So suffice to say, I am not an Admin. But, here is some feedback I have gotten from our Ops team members.

The first is that Admins are never going to use something unless they need to. Necessity is the mother of invention, or innovation for that matter. Why would anyone switch from something that works to something that may work but they don't know how to  use yet? I think the PowerShell team is working very hard to address this very issue, although I think sometimes we miss it in the background when we are introducing people to PowerShell. One of the beauties of PowerShell is that it is a solid consistent language that can be used across multiple technologies. Regardless of whether you are administering an Exchange server or Virtual Machine manager, you are going to likely be doing a "get-doohickey | set-Doohickey." Also there is tremendous power in the consistency of naming parameters and arguments. All Cmdlets are verb-noun -parameter argument.

I think what the Admin is thinking is that PowerShell is just one more thing to learn. We are having a hard time telling them that the investment they make in learning PowerShell to manage Exchange will also help them with VMM, desktop management, AD,Group Policy, and Terminal Services, just to name a few.

The second issue is really a two-edged a sword. There is an awesome community supporting PowerShell and a ton of great content on the web that has been worked on over the years and is really quite mature. The problem here is that newcomers to PowerShell start seeing some of this stuff and get completely overwhelmed right away. If a complete beginner asks "How can I filter the services to see just the ones that are stopped?" and they find something like "gsv | ? {$_.status -eq "Stopped"}" they will completely freak out. On the other hand, they may use it but not understand what is going on and just save it as another tool in their tool bag, without understanding that they can filter just as easily on processes or on Virtual Machines.


There is one thing that I believe has not been sold quite as much as necessary is Tab-Completion. Take the example below copied from a blog entry from the MS Exchange Team

This is the Exchange Management Shell (EMS) command Tom would enter to generate the cert request to be provided to the 3rd party CA in order to generate the actual certificate:

New-Exchangecertificate -domainname,, contoso.local,, server01.contoso.local, server01 -Friendlyname contosoinc -generaterequest:$true -keysize 1024 -path c:\certrequest.req -privatekeyexportable:$true –subjectname "c=US o=contoso inc,"

We have found that the '–subjectname' option is the most confusing. The help contents in EMS are vague as well. The best description is found in the TLS whitepaper mentioned at the beginning of this post so we're not going to reproduce it here.


As an admin I would look at this and say something like, "Crap, who created this huge long command line entry. Editing this is going to suck." What people don't get is that they have Tab Completion available, not just for the Cmdlets but for parameters as well. This just doesn't get conveyed when we are posting examples. Now if you throw in PowerTab or Intellisense from PowerShell Plus, its just gravy.

And so, I would like to pose the question to you, how do you as an engineer or an admin get your teammates to start using PowerShell. What walls have you come up against and what can we as a community to do to help break down these walls.

One thing I have been doing lately is using PowerShell in the build guides and Ops guide that I write, to at least get people started with using it. What else can we do?