30 July 2014

XtremIO PowerShell Module Updated -- Now with New-XIO* Functions!

XtremIO + PowerShell!Since releasing the XtremIO PowerShell module that had "Get" capabilities (about which you can read in our previous XtremIO + PowerShell post, if you missed it), we've been working to improve the module!  Some such improvements:
  • added functions to cover New-XIO* activities, for things like volumes and initiator groups (yes, with -WhatIf)
  • added credential storing, so that you need not specify credentials for every call
  • expanded Get-XIOItemInfo to support more object types (as the API has expanded), like volume folders, initiator group folders, target groups, and bricks
  • updated numeric properties on return objects to actually be numeric (were returned as strings, previously)
  • added function to open the Java GUI (most of the time, "yuck", but, sometimes useful)
  • changed the module name to XtremIO.Utils, as it now does more than reporting information
In the works:  making module available via PsGet, so that it is that much easier to get.  I shall update this post once this is done.

* Update 28 Oct 2014:
Made the time to make this module available via the extra-cool PsGet.  In order to install the XtremIO.Utils module via PsGet's Install-Module:
PS vN:\> Install-Module -Verbose -Module XtremIO.Utils

That's it -- no muss, no fuss!  And, have a look at the PsGet page to see the easy, one-line install of the PsGet module itself if you do not already use it.
End of update - 28 Oct 2014

Now, how about some examples?  Sure!

Create an encrypted, stored credential, that the functions in this module will use by default (so you need not specify credentials for every command):
PS vN:\> New-XIOStoredCred
Windows PowerShell credential request.
Enter credentials to use for XtremIO access
User: mattXio
Password for user mattXio: *********************

VERBOSE: Credentials encrypted (via Windows Data Protection API) and saved to:
'C:\Users\Matt\AppData\Local\Temp\xioCred_by_Matt_on_VM-MattDesktop-002.enc.xml'

Create a new volume:
PS vN:\> New-XIOVolume -ComputerName myxms0.dom.com -Name testvol3 -SizeGB 5120 -ParentFolder "/testVols"

Name        NaaName   VolSizeTB   IOPS
----        -------   ---------   ----
testvol3              5.00        0

Note: there is no NaaName value at this piont, as the NaaName property does not get populated in the volume object until the volume has been mapped to an initiator group for the first time

Create a new initiator group:
PS vN:\> New-XIOInitiatorGroup -ComputerName myxms0.dom.com -Name testIG0 -ParentFolder "/testIGs" -InitiatorList @{"myserver-hba2" = "10:00:00:00:00:00:00:F4"; "myserver-hba3" = "10:00:00:00:00:00:00:F5"}

Name     Index   NumInitiator   NumVol   IOPS
----     -----   ------------   ------   ----
testIG0  21      2              0        0

Create a new initiator group for each host in a cluster:
PS vN:\> ## general params to use for each New-XIOInitiatorGroup call
PS vN:\> $hshGeneralParamsForNewXioIG = @{
    Computer = "myxms0.dom.com"
    TrustAllCert = $true
    Port = 443
    WhatIf = $true
} ## end hashtable

PS vN:\> ## get the HBA WWNs for the VMHosts in the given cluster, and for each VMHost, create a new XtremIO initiator group with initiators for each HBA
PS vN:\> Get-Cluster -Name myCluster0 -PipelineVariable cluThisOne | Get-VMHostHBAWWN | Group-Object -Property @{e={$_.VMHostName.Split(".")[0]}} | Foreach-Object{
    $strVMHostShortname = $_.Name
    ## make a hashtable of key/value pairs that are initiator-name => HBA WWN; initiator names will be like "myhost0-hba2"
    $_.Group | Foreach-Object -begin {$hshInitList = @{}} {$hshInitList["${strVMHostShortname}-$($_.DeviceName.Replace("vmhba","hba"))"] = $_.HBAPortWWN}
    ## make a hashtable of parameters specific to this new initiator group to make
    $hshParamForNewXioIG = @{
        Name = $strVMHostShortname
        InitiatorList = $hshInitList
        ParentFolder = "/$($cluThisOne.Name)"
    } ## end hashtable
    ## create the new initiator group via the given params
    New-XIOInitiatorGroup @hshGeneralParamsForNewXioIG @hshParamForNewXioIG
} ## end foreach-object

Name      Index   NumInitiator   NumVol   IOPS
----      -----   ------------   ------   ----
myhost0   21      2              0        0
myhost1   22      2              0        0
...

This creates an initiator group for each VMHost in the given cluster, each group with an initiator for each of the VMHost's HBAs.  Utilizes the vNugglets function Get-VMHostHBAWWN that we posted in Get VMHost FC HBA WWN Info Most Quickly.  These initiator groups are created in the existing initiator-group folder that is defined for this cluster (of the same name as the cluster).

Open the management console (Java GUI):
PS vN:\> Open-XIOMgmtConsole myxms0.dom.com


Credentials discussion:
Stored credentials are encrypted using the Windows Data Protection API, via a derivative of HalR9000's Export-PSCredential.  If the encrypted credential file is found at runtime of any of the module's functions that require credentials, the credentials will be imported from said file transparently.

Decryption of the encrypted credentials can only be performed by the user account that performed the encryption, and on the same computer on which the encryption was performed.  This module stores the credential file in the ${env:temp} directory by default, and this location is configurable as desired.

If no credentials are specified to the functions of this module, the given function will look for the credential file in the configured location.  If none exists, the functions behave as before:  they will prompt for credentials as necessary.  And, you can get the stored credential with Get-XIOStoredCred, and remove it from disk, if you would like, with Remove-XIOStoredCred.

To use the module, just:  (also, updated above:  install this module via PsGet. See update at top of post)
  1. download from latest and greatest! https://github.com/mtboren/XtremIO.Utils/releases/download/Latest/XtremIO.Utils.zip
  2. unzip somewhere you like (like, say, in Join-Path ${env:\userprofile} "Documents\WindowsPowerShell\Modules")
  3. you should now have a folder named <pathToModules>\XtremIO.Utils, in which the PowerShell files reside (see note in previous XtremIO + PowerShell post about using Unblock-File, since this module is not yet Authenticode signed)
  4. Import-Module <pathToModules>\XtremIO.Utils

Other upcoming changes:
  • add the other New-XIO* functions for things like folders, single initiators, lun-maps, more
  • expand Get-XIOItemInfo to support even more object types (as the API continues to expand), like volume snapshots, events, dataprotection-groups
  • actually get the project on GitHub
Enjoy, and let us know what features would be best to add the soonest!

* Update 06 Aug 2014:  included the MIT License file in the .zip file.

17 July 2014

Get VMHost FC HBA WWN Info Most Quickly with PowerCLI

VMHba WWN Info
People know about getting VMHost HBA info via PowerCLI -- there are plenty of posts about doing so, generally via Get-VMHostHba.  Since that works great, there is barely a reason to write something else to do the same thing, save one reason that is near and dear to our vNugglets hearts:  speed.  We made this a couple of years ago, have tweaked it a few times, and now it seems like time to post it (like, maybe it will be helpful in an upcoming post, or something?  So exciting).

This function uses everybody's favorite PowerCLI cmdlet Get-View.  The speed reward:  well worth it.  For example:
Technique
Time, 28 hosts
Time, 270 hosts
Get-VMHostHba
61.9s
720s
Get-VMHostHBAWWN
1.32s
14.1s
improvement:
46x
51x

More than 45 times faster?  I'm in.  Now for the function, complete with examples in comment-based help:  (double-click anywhere in the code to Select All)
function Get-VMHostHBAWWN {
<#    .Description
    Get the Port- and Node WWN(s) for HBA(s) in host(s). Feb 2012, vNugglets
    .Example
    Get-VMHostHBAWWN -VMHost myhost0.dom.com
    VMHostName       DeviceName  HBAPortWWN               HBANodeWWN               HBAStatus
    ----------       ----------  ----------               ----------               ---------
    myhost0.dom.com  vmhba1      10:00:00:00:00:00:00:ca  20:00:00:00:00:00:00:ca  online
    myhost0.dom.com  vmhba2      10:00:00:00:00:00:00:83  20:00:00:00:00:00:00:83  online
    Get the HBA WWNs for hosts whose name match the pattern myhost0.dom.com
    .Example
    Get-VMHostHBAWWN -VMHost ^my.+
    VMHostName       DeviceName  HBAPortWWN               HBANodeWWN               HBAStatus
    ----------       ----------  ----------               ----------               ---------
    myhost0.dom.com  vmhba1      10:00:00:00:00:00:00:ca  20:00:00:00:00:00:00:ca  online
    myhost0.dom.com  vmhba2      10:00:00:00:00:00:00:83  20:00:00:00:00:00:00:83  online
    mytest1.dom.com  vmhba1      10:00:00:00:00:00:00:da  20:00:00:00:00:00:00:da  online
    mytest0.dom.com  vmhba2      10:00:00:00:00:00:00:93  20:00:00:00:00:00:00:93  online
    Get the HBA WWNs for hosts whose name match the pattern ^my.+
    .Example
    Get-Cluster mycluster | Get-VMHostHBAWWN
    ...
    Get the HBA WWNs for hosts in the cluster "mycluster"
    .Outputs
    PSCustomObject
#>
[CmdletBinding()]param(
    ## Name pattern of the host for which to get HBA info (accepts regex patterns)
    [parameter(Mandatory=$true,ParameterSetName="SearchByHostName")][string]$VMHostName_str,
    ## Name pattern of the cluster for whose hosts to get HBA info (accepts regex patterns)
    [parameter(Mandatory=$true,ParameterSetName="SearchByCluster",ValueFromPipelineByPropertyName)][Alias("Name")][string]$ClusterName_str
) ## end param
Begin {
    ## helper function for formatting WWN as hex string with colon-separators
    function _Format-AsHexWWNString {
        param([parameter(Mandatory=$true)][long]$WWN_long)
        (("{0:x}" -f $WWN_long) -split "(\w{2})" | ?{$_ -ne ""}) -join ":"
    } ## end function
}

Process {
    ## params for the Get-View expression for getting the View objects
    $hshGetViewParams = @{
        ViewType = "HostSystem"
        Property = "Name", "Config.StorageDevice.HostBusAdapter"
    } ## end hashtable
    Switch ($PSCmdlet.ParameterSetName) {
        ## if host name pattern was provided, filter on it in the Get-View expression
        "SearchByHostName" {$hshGetViewParams["Filter"] = @{"Name" = $VMHostName_str}; break;} ## end case
        ## if cluster name pattern was provided, set it as the search root for the Get-View expression
        "SearchByCluster" {$hshGetViewParams["SearchRoot"] = (Get-Cluster $ClusterName_str).Id; break;}
    } ## end switch

    Get-View @hshGetViewParams | Foreach-Object {
        $viewHost = $_
        $viewHost.Config.StorageDevice.HostBusAdapter | Where-Object {$_ -is [VMware.Vim.HostFibreChannelHba]} | Foreach-Object {
            New-Object -TypeName PSObject -Property ([ordered]@{
                VMHostName = $viewHost.Name
                DeviceName = $_.Device
                HBAPortWWN = _Format-AsHexWWNString -WWN $_.PortWorldWideName
                HBANodeWWN = _Format-AsHexWWNString -WWN $_.NodeWorldWideName
                HBAStatus = $_.Status
            }) ## end new-object
        } ## end foreach-object
    } ## end foreach-object
} ## end process
} ## end function

Not terribly fancy, but something to get it done more quickly (FaF, in fact).  And, handy for other things down the road.  Like, oh, using the WWN info when creating some initiator groups on your XtremIO array?  What a good idea.

Oh, and if you have not yet seen/used parameter splatting, this provides a decent example of that, too -- the hashtable of parameters used on line 54.  Enjoy!