SpectrumControlBase-Client.Sample.ps1

##############################################################################
# #
# Licensed Materials - Property of IBM #
# #
# IBM Storage Automation Plugin for PowerShell #
# #
# (C) COPYRIGHT International Business Machines Corp. 2013, 2022 #
# All Rights Reserved #
# #
# US Government Users Restricted Rights: Use, duplication or #
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. #
# #
##############################################################################
<#
This sample script demostrates how to integrate the SpectrumControlBase-Client module in your automation solution to provision volumes for Microsft/HyperV hosts. And the following cmdlets are used in this sample script:
 
* New-SCBConnection
* Get-SCBService
* Get-SCBHostVolMapping
* Get-SCBVolume
* New-SCBVolume
* Resize-SCBVolume
* Remove-SCBVolume
 
For other cmdlets which are not covered in this sample, please refer to corresponding Help Text or Examples for more information.
#>

function Task([object] $information){
    Write-Host $information -ForegroundColor Green
}

function Info([Object] $info){
    Write-Host $info -ForegroundColor Yellow
}

function ASSERT_NOTNULL([Object] $obj){
    if($obj -eq $null){
        throw "NULL for the object($obj)"         
    }else{
        Write-Verbose "ASSERT: Object is not null"
    }
}

#Retrieve the FC WWPN or iSCSI initiator ports from Windows host server; Wrapper of Get-InitiatorPort and Get-WmiObject.
#Alternatively, you can just issue the Get-SCBHost to retrived the initiators information.
function Get-HostInitiator{
    param(
        [Alias("ComputerName")]
        [String] $HostName,        
        [PSCredential] $Credential,
        [ValidateSet("FibreChannel","iSCSI","SAS")]    
        [String] $ConnectionType
    )
    $CmdletName="Get-HostInitiator"
    Write-Verbose ("$CmdletName.ENTER: HostName=$HostName, ConnectionType=$ConnectionType")
    $pcname=""
    if([String]::IsNullOrEmpty($HostName)){
        $pcname="localhost"
    }else{
        $pcname=$HostName
    }    
    try{
        $cmd=Get-Command -Name Get-InitiatorPort
        Write-Verbose("$CmdletName`: Get-InitiatorPort")
        if([String]::IsNullOrEmpty($ConnectionType)){
            return Get-InitiatorPort -CimSession $pcname|%{if($_.ConnectionType -eq "Fibre Channel"){$_.PortAddress.ToUpper()}else{$_.NodeAddress}}
        }else{
            return Get-InitiatorPort -ConnectionType $ConnectionType -CimSession $pcname|%{if($_.ConnectionType -eq "Fibre Channel"){$_.PortAddress.ToUpper()}else{$_.NodeAddress}}
        }
        Write-Verbose("$CmdletName.EXIT")
    }
    catch{
        Write-Verbose "$CmdletName`: Exception found with information $($_.Exception.Message)"
        Write-Verbose "$CmdletName`: Fail to find the Cmdlet Get-InitiatorPort. Please ensure Storage Cmdlets are installed. Also, please ensure Windows PowerShell Remoting is enabled"
        Write-Verbose "$CmdletName`: Try getting the initiator ports via WS-Management."
        try{
            if($credential -ne $null){
                $hbas = Get-WmiObject -Namespace root/Microsoft/Windows/Storage -Class MSFT_InitiatorPort -ComputerName $pcname -Credential $credential
            }else{
                $hbas = Get-WmiObject -Namespace root/Microsoft/Windows/Storage -Class MSFT_InitiatorPort -ComputerName $pcname
            }
            Write-Verbose("$CmdletName.EXIT")        
            if($hbas -ne $null){
                if([String]::IsNullOrEmpty($ConnectionType)){
                    return $hbas | %{if($_.ConnectionType -eq 1){$_.PortAddress.ToUpper()}else{$_.NodeAddress}}
                }else{
                    $conType="Other|FibreChannel|iSCSI|SAS".Split("|").IndexOf($ConnectionType)
                    return ($hbas|?{$_.ConnectionType -eq $conType})%{if($_.ConnectionType -eq 1){$_.PortAddress.ToUpper()}else{$_.NodeAddress}}
                }
            }else{
                return $null
            }
        }catch{
            throw $_.Exception
        }
    }
}

Task "[1] Import the PowerShell Client Module for IBM SpectrumControlBase"
Info "You can get the module from PowerShell Gallery."
Info "To get the module from PowerShell Gallery, you can just issue ""Find-Module -Name SpectrumControlBase-Client|Install-Module -Force"";"
Info "For this sample script, the module is just saved to local folder and is imported directly using Import-Module cmdlet."
Import-Module R:\SpectrumControlBase-Client\SpectrumControlBase-Client.psd1
$module=Get-Module -Name SpectrumControlBase-Client 
if($module.Name -eq "SpectrumControlBase-Client"){
    Info "The Module SpectrumControlBase-Client has been imported."
    Info "Detailed information about SpectrumControlBase-Client module:"
    $module|Format-List
}

Info "PREPARATION 1: Define storage pools for allocations, and ensure that all the required hosts are connected to the storage system."
$computerName="win2012r2x215"        # The Windows Host server with iSCSI(or FC) enabled.

$domainAdmin="Domain01\User01"        # Specifies a user account that has permission to perform this action on the windows host $computerName.
$domainPassword="Passw0rd"

Info "PREPARATION 2: On the SCB server, Add a PowerShell interface and create the following PowerShell interface user"
$scbLocation="https://10.0.1.15:8440"    # The Uri of the SCB server, in the format of https:\\IP:Port
$scbUsername="powershell"                    # Credential for the PowerShell interface user.
$scbPassword="passw0rd"

Info "PREPARATION 3: On the SCB server, add a new storage space, add storage services, and attach services to the PowerShell interface created in PREPARATION 2."
$spaceName="DemoSpace"                        # Space name.
$serviceName="CompressionService"            # Service name. For this sample, this service can be used to create Compression volumes.

$LunPrefix="SCBDemoVol"    # The Prefix for the created volumes

Task "[2] Connect to the SCB Server and Create Volumes via SCB Service"
##Note: New-SCBConnection supports creating the connection using PowerShell Credential object, and you can also pass a PScredential object here
## Or use the user name/password explicitly: New-SCBConnection -ConnectionUri $scbLocation -UserName $scbUsername -Password $scbPassword
$ssPsw=ConvertTo-SecureString -AsPlainText -Force $scbPassword; 
$cred=New-Object pscredential $scbUsername,$ssPsw; 
$sc=New-SCBConnection -ConnectionUri $scbLocation -Credential $cred
Info "Successfully Connect to the SCB server($scbLocation)!"
$sc|Format-Table -AutoSize

if([String]::IsNullOrEmpty($sc.Token)){
    Throw "Fail to build the connection to the SCB server."
    return $False
}

Task "[2.1] Get the service instance via service name"
$service=Get-SCBService -SCBConnection $sc -ServiceName $serviceName
ASSERT_NOTNULL $service
Info "Service with name $serviceName found:"
$service|Format-Table name,id,total_capacity,space_name -AutoSize

Task "[2.2] Get the host initiators from Windows host"
$ssDomainPsw=ConvertTo-SecureString -AsPlainText -Force $domainPassword
$credential=New-Object PSCredential $domainAdmin,$ssDomainPsw
$iSCSIPort=(Get-HostInitiator -HostName $computerName -Credential $credential -ConnectionType iSCSI)

Task "[2.3] Add a volume via SCB service, and register it to specified iSCSI initiator"
$volName= $LunPrefix + [System.DateTime]::Now.ToString("yyMMddHHmmss")
$vol=New-SCBVolume -SCBConnection $sc -Name $volName -Size 40  -SizeUnit GiB -ServiceID $service.ID -Initiators $iSCSIPort
if($vol -eq $null){
    Info "Fail to create new volume"
    return $False
}

Info "The following volume is created:"
$vol|Format-Table name,id,array_name,pool_name,service_name,ratio -AutoSize
$mapping=Get-SCBHostVolMapping -SCBConnection $sc -VolumeID $vol.id 
Info "And its mapping information is listed below:"
$mapping|Format-Table -AutoSize

Task "[3] Mount the volume on Windows host"
Update-HostStorageCache -CimSession $computerName
$disk=Get-Disk -CimSession $computerName -UniqueId $vol.id
ASSERT_NOTNULL $disk
Info "Disk found on Windows host $computerName with following information:"
$disk|Format-Table Number,ProvisioningType,OperationalStatus,AllocatedSize,UniqueId,PartitionStyle,IsOffline,IsReadOnly,PSComputerName -AutoSize
Task "[3.1] Bring the Disk Online if the disk is Offline"
if($disk.OperationalStatus -eq "Offline"){
    Info "The disk is offline by default and will bring the disk Online"
    Set-Disk -CimSession $computerName -UniqueId $disk.UniqueId -IsOffline $False
    $disk=Get-Disk -CimSession $computerName -UniqueId $disk.UniqueId    
    if($disk.OperationalStatus -eq "Online"){
        Info "Succeed to bring the disk Online"
        $disk|Format-Table Number,ProvisioningType,OperationalStatus,AllocatedSize,UniqueId,PartitionStyle,IsOffline,IsReadOnly,PSComputerName -AutoSize
    }else{
        Info "Fail to bring the disk online"
        return $false
    }
}

Task "[3.2] Initialize the disk"
if($disk.PartitionStyle -eq "RAW"){
    Info "The partition style of the disk is detected to be RAW, and will initialize this disk to MBR partition style"
    Initialize-Disk -CimSession $computerName -UniqueId $disk.UniqueId -PartitionStyle MBR -Confirm:$False
    $disk=Get-Disk -CimSession $computerName -UniqueId $disk.UniqueId    
    if($disk.PartitionStyle -ne "RAW"){
        Info "Succeed to initialize the disk to $($disk.PartitionStyle)"
        $disk|Format-Table Number,ProvisioningType,OperationalStatus,AllocatedSize,UniqueId,PartitionStyle,IsOffline,IsReadOnly,PSComputerName -AutoSize
    }
}else{
    Info "Ignored for the partition style of the disk is detected to be $($disk.PartitionStyle)"
}

Task "[3.3] Format the Disk and Mount with a DriveLetter"
$partition=New-Partition -DiskNumber $disk.Number -AssignDriveLetter -UseMaximumSize -CimSession $computerName
$partition|Format-Table PartitionNumber,Offset,Size,IsActive,DriveLetter,PSComputerName -AutoSize
Format-Volume -DriveLetter $partition.DriveLetter -FileSystem NTFS -NewFileSystemLabel "Compressed" -Force -Confirm:$False -CimSession $computerName
Get-Volume -DriveLetter $partition.DriveLetter -CimSession $computerName|Format-Table DriveLetter,DriveType,FileSystem,HealthStatus,Size,SizeRemaining,FileSystemLabel,PSComputerName -AutoSize


Task "[4] Resize the volume"
Info "Before Resizing the Volume via SCB Service"
$vol|Format-Table name,id,array_name,pool_name,logical_capacity,ratio -AutoSize

Task "[4.1] Resize the volume to 80GiB"
$ret=Resize-SCBVolume -SCBConnection $sc -VolumeID $vol.id -NewSize 80 -SizeUnit GiB
if($ret){
    Info "Succeed to resize the disk, and the information of the volume is listed below:"
    $vol=Get-SCBVolume -SCBConnection $sc -VolumeID $vol.id
    $vol|Format-Table name,id,array_name,pool_name,logical_capacity,ratio -AutoSize
}

Info "[4.2] Update the Volume on Windows Host"
Update-Disk -CimSession $computerName -UniqueId $disk.UniqueId
$disk=Get-Disk -CimSession $computerName -UniqueId $disk.UniqueId    
Info "Disk information after updating"
$disk|Format-Table Number,ProvisioningType,OperationalStatus,AllocatedSize,UniqueId,PartitionStyle,IsOffline,IsReadOnly,PSComputerName -AutoSize

Task "[5] Remove the volume $($vol.name)"
Pause
$ret=Remove-SCBVolume -SCBConnection $sc -ID $vol.id -Force
if($ret){
    info "Succeed to remove the volume $($vol.name)!"
}else{
    info "Fail to remove the volume $($vol.name)!"
}

# SIG # Begin signature block
# MIINMwYJKoZIhvcNAQcCoIINJDCCDSACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUXUmqsdx07tjWCX9kbQiSFTYc
# LuigggpoMIIFBzCCA++gAwIBAgIQO50nymBTQHmVgRJdr11LljANBgkqhkiG9w0B
# AQsFADB/MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRp
# b24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxMDAuBgNVBAMTJ1N5
# bWFudGVjIENsYXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQTAeFw0xNzExMTAw
# MDAwMDBaFw0yMDEyMDkyMzU5NTlaMIGgMQswCQYDVQQGEwJDTjEQMA4GA1UECAwH
# QmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEvMC0GA1UECgwmSUJNIChDaGluYSkg
# SW52ZXN0bWVudCBDb21wYW55IExpbWl0ZWQxCzAJBgNVBAsMAklUMS8wLQYDVQQD
# DCZJQk0gKENoaW5hKSBJbnZlc3RtZW50IENvbXBhbnkgTGltaXRlZDCCASAwDQYJ
# KoZIhvcNAQEBBQADggENADCCAQgCggEBAPLD5ch7kY3fK7NRk6kPkWafTZzGveXm
# ZCIqDJs4Et5wt5IhZzWIeMsZ3bu+M++lhEJieQCMnPATx/UVlaKxZNHS2Lhp2AlO
# nTiNCoPsmpPMeX93dwgvNPut0Hnd+jQdAmi2SCECboAmC6nOdC6oDrvqUkZ6Dk7Y
# n8g+R3GMenDc8ytkEO/Ou8+ySznHD/4JCfHyP0AuaBdejJ7fXcoXG5Z7wptKp5e4
# 0+cmbU0I6bUf8vgC5GD7xtwauN/aA3CqIuOX1u/gk0b5vR51YKYkF6HKJyrn2JlG
# 5z17FRMLVGAKYXWpaTD6Ib0GnsbLsTed80VYqxpAkpZ3g2ut+/Tz9AMCAQOjggFd
# MIIBWTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDArBgNVHR8EJDAiMCCgHqAc
# hhpodHRwOi8vc3Yuc3ltY2IuY29tL3N2LmNybDBhBgNVHSAEWjBYMFYGBmeBDAEE
# ATBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEF
# BQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTATBgNVHSUEDDAKBggrBgEF
# BQcDAzBXBggrBgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zdi5zeW1j
# ZC5jb20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdi5zeW1jYi5jb20vc3YuY3J0MB8G
# A1UdIwQYMBaAFJY7U/B5M5evfYPvLivMyreGHnJmMB0GA1UdDgQWBBSCjmKRqxXa
# sDjI6emU05joKoNBczANBgkqhkiG9w0BAQsFAAOCAQEAUV14IxCZrkkGCKFpn048
# G7O8OYESMkJPzBUt35Rn2eXtZI0HUgDEZ4iKi8xCrZ6ssz+eATSm4m22Fc+0wRVf
# o1Uq4VfGyFPkXLAPhvQUFEsevFK9ps9buaWGTwSixRjpPOwfymcEz/6p7MIiXteL
# mIlfPDY4+ie3IWCo2PFEvrVzJObcuuEjEylraxkcVvQte7f4i3QHGQvkLhWA0OGY
# WT5YDJD6s229ujueHBkvvDGmWP7dmFWe2j2jpgJKOxZFPQ/+YyrAlRohzDAcYgGj
# 6jxuXLUoFgKiRyJ+PDmAYI695AE6QWJBC4EwmTNZNFNnu5JbFCzipRQSD122QsLh
# wzCCBVkwggRBoAMCAQICED141/l2SWCyYX308B7KhiowDQYJKoZIhvcNAQELBQAw
# gcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UE
# CxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDIwMDYgVmVy
# aVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8
# VmVyaVNpZ24gQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1
# dGhvcml0eSAtIEc1MB4XDTEzMTIxMDAwMDAwMFoXDTIzMTIwOTIzNTk1OVowfzEL
# MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
# VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydTeW1hbnRlYyBD
# bGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQCXgx4AFq8ssdIIxNdok1FgHnH24ke021hNI2JqtL9aG1H3
# ow0Yd2i72DarLyFQ2p7z518nTgvCl8gJcJOp2lwNTqQNkaC07BTOkXJULs6j20Tp
# Uhs/QTzKSuSqwOg5q1PMIdDMz3+b5sLMWGqCFe49Ns8cxZcHJI7xe74xLT1u3LWZ
# Qp9LYZVfHHDuF33bi+VhiXjHaBuvEXgamK7EVUdT2bMy1qEORkDFl5KK0VOnmVuF
# NVfT6pNiYSAKxzB3JBFNYoO2untogjHuZcrf+dWNsjXcjCtvanJcYISc8gyUXsBW
# UgBIzNP4pX3eL9cT5DiohNVGuBOGwhud6lo43ZvbAgMBAAGjggGDMIIBfzAvBggr
# BgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wEgYD
# VR0TAQH/BAgwBgEB/wIBADBsBgNVHSAEZTBjMGEGC2CGSAGG+EUBBxcDMFIwJgYI
# KwYBBQUHAgEWGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vY3BzMCgGCCsGAQUFBwIC
# MBwaGmh0dHA6Ly93d3cuc3ltYXV0aC5jb20vcnBhMDAGA1UdHwQpMCcwJaAjoCGG
# H2h0dHA6Ly9zMS5zeW1jYi5jb20vcGNhMy1nNS5jcmwwHQYDVR0lBBYwFAYIKwYB
# BQUHAwIGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIBBjApBgNVHREEIjAgpB4wHDEa
# MBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01NjcwHQYDVR0OBBYEFJY7U/B5M5evfYPv
# LivMyreGHnJmMB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
# SIb3DQEBCwUAA4IBAQAThRoeaak396C9pK9+HWFT/p2MXgymdR54FyPd/ewaA1U5
# +3GVx2Vap44w0kRaYdtwb9ohBcIuc7pJ8dGT/l3JzV4D4ImeP3Qe1/c4i6nWz7s1
# LzNYqJJW0chNO4LmeYQW/CiwsUfzHaI+7ofZpn+kVqU/rYQuKd58vKiqoz0EAeq6
# k6IOUCIpF0yH5DoRX9akJYmbBWsvtMkBTCd7C6wZBSKgYBU/2sn7TUyP+3Jnd/0n
# lMe6NQ6ISf6N/SivShK9DbOXBd5EDBX6NisD3MFQAfGhEV0U5eK9J0tUviuEXg+m
# w3QFCu+Xw4kisR93873NQ9TxTKk/tYuEr2Ty0BQhMYICNTCCAjECAQEwgZMwfzEL
# MAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYD
# VQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydTeW1hbnRlYyBD
# bGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcgQ0ECEDudJ8pgU0B5lYESXa9dS5Yw
# CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN
# AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
# IwYJKoZIhvcNAQkEMRYEFNdExzb5ijud5UZhpDVJbCr8zPeHMA0GCSqGSIb3DQEB
# AQUABIIBADWOmNhSY/jvV5xAa1AwZHP6ru6RFZdeqW/T/Iz69Hn30OMC9xO78rno
# B0cqSrxpDhxctD3KcGPHUclFiShZB+6kbC1SXXWi4i7AaBw1r9D65IUYl7s6NDeW
# GrxiwBu0JPzH/FhPrY+OlrrvIzFptPeCXleV64Ik8zlF2RMT0UOujiXA9boj0neo
# 9pRoExtYKCW5ZKcIpE7K5fxtoPXH8LFQ4czwv1RQZyLRaiDbxlTm0G62+Y/sZSZo
# p50nZn+AMFzFsL6K0BsuL/tTBHzKddxtHvQ5oG5U6wkGN/EHXprlyf1zXGXi7iMp
# Zaqa1iNrx4X95Zy2xNuaQnBQS+Wk2as=
# SIG # End signature block