scripts/Drive.ps1
# Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. # This program is free software; you can redistribute it and/or modify # it under the terms of the MIT License # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MIT License for more detail <# NOTE: iBMC Drive module Cmdlets #> function Get-iBMCDrives { <# .SYNOPSIS Query information about the drive resource collection of a server. .DESCRIPTION Query information about the drive resource collection of a server. This cmdlet works only after BIOS boot is complete when the RAID controller card supports out-of-band management or after iBMA 2.0 has been installed and started. .PARAMETER Session iBMC redfish session object which is created by Connect-iBMC cmdlet. A session object identifies an iBMC server to which this cmdlet will be executed. .PARAMETER StorageId Indicates the identifier of the storage which the drive belongs to. If StorageId is not provided, will get all drives instead. The Id properties of "Get-iBMCRAIDControllers" cmdlet's return value represents Storage ID. .OUTPUTS PSObject[][] Returns an array of PSObject indicates all drive resources if cmdlet executes successfully. In case of an error or warning, exception will be returned. .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> $Drives = Get-iBMCDrives -Session $Session PS C:\> $Drives Host : 10.1.1.2 Id : HDDPlaneDisk0 Name : Disk0 Model : MG04ACA400N Revision : FJ3J Status : @{State=Enabled; Health=OK} CapacityBytes : 3999999721472 FailurePredicted : False Protocol : SATA MediaType : HDD Manufacturer : TOSHIBA SerialNumber : 38DGK77LF77D CapableSpeedGbs : 6 NegotiatedSpeedGbs : 12 PredictedMediaLifeLeftPercent : IndicatorLED : Off HotspareType : None StatusIndicator : OK Location : {@{Info=Disk0; InfoFormat=DeviceName}} DriveID : 0 FirmwareStatus : Online HoursOfPoweredUp : 6056 PatrolState : DoneOrNotPatrolled Position : HDDPlane RebuildProgress : RebuildState : DoneOrNotRebuilt SASAddress : {500e004aaaaaaa00, 0000000000000000} SASSmartInformation : SATASmartInformation : @{AttributeRevision=; AttributeRevisionNumber=; AttributeItemList=System.Object[]} SpareforLogicalDrives : {} TemperatureCelsius : 33 Type : Disk Host : 10.1.1.2 Id : HDDPlaneDisk1 Name : Disk1 Model : MG04ACA400N Revision : FJ3J Status : @{State=Enabled; Health=OK} CapacityBytes : 3999999721472 FailurePredicted : False Protocol : SATA MediaType : HDD Manufacturer : TOSHIBA SerialNumber : 38DFK62PF77D CapableSpeedGbs : 6 NegotiatedSpeedGbs : 12 PredictedMediaLifeLeftPercent : IndicatorLED : Off HotspareType : None StatusIndicator : OK Location : {@{Info=Disk1; InfoFormat=DeviceName}} DriveID : 1 FirmwareStatus : UnconfiguredGood HoursOfPoweredUp : 6058 PatrolState : DoneOrNotPatrolled Position : HDDPlane RebuildProgress : RebuildState : DoneOrNotRebuilt SASAddress : {500e004aaaaaaa01, 0000000000000000} SASSmartInformation : SATASmartInformation : @{AttributeRevision=; AttributeRevisionNumber=; AttributeItemList=System.Object[]} SpareforLogicalDrives : {} TemperatureCelsius : 33 Type : Disk This example shows how to get all drives. .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> $Drives = Get-iBMCDrives -Session $Session -StorageId RAIDStorage0 PS C:\> $Drives Host : 10.1.1.2 Id : HDDPlaneDisk0 Name : Disk0 Model : MG04ACA400N Revision : FJ3J Status : @{State=Enabled; Health=OK} CapacityBytes : 3999999721472 FailurePredicted : False Protocol : SATA MediaType : HDD Manufacturer : TOSHIBA SerialNumber : 38DGK77LF77D CapableSpeedGbs : 6 NegotiatedSpeedGbs : 12 PredictedMediaLifeLeftPercent : IndicatorLED : Off HotspareType : None StatusIndicator : OK Location : {@{Info=Disk0; InfoFormat=DeviceName}} DriveID : 0 FirmwareStatus : Online HoursOfPoweredUp : 6056 PatrolState : DoneOrNotPatrolled Position : HDDPlane RebuildProgress : RebuildState : DoneOrNotRebuilt SASAddress : {500e004aaaaaaa00, 0000000000000000} SASSmartInformation : SATASmartInformation : @{AttributeRevision=; AttributeRevisionNumber=; AttributeItemList=System.Object[]} SpareforLogicalDrives : {} TemperatureCelsius : 33 Type : Disk This example shows how to get all drives belongs to Storage controller "RAIDStorage0". .LINK https://github.com/Huawei/Huawei-iBMC-Cmdlets Get-iBMCDrivesHealth Set-iBMCDrive Connect-iBMC Disconnect-iBMC #> [CmdletBinding()] param ( [RedfishSession[]] [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] $Session, [String[]] [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1)] $StorageId ) begin { } process { Assert-ArrayNotNull $Session 'Session' $StorageIdList = Get-OptionalMatchedSizeArray $Session $StorageId $Logger.info("Invoke Get iBMC drive resources function") $ScriptBlock = { param($RedfishSession, $StorageId) $Logger.info($(Trace-Session $RedfishSession "Invoke Get iBMC drive resources now")) $Drives = New-Object System.Collections.ArrayList if ($null -eq $StorageId) { $GetChassisPath = "/Chassis/$($RedfishSession.Id)" $Chassis = Invoke-RedfishRequest $RedfishSession $GetChassisPath | ConvertFrom-WebResponse $DriveLinkList = $Chassis.Links.Drives } else { # validate whether storage exists $GetStoragesPath = "/Systems/$($RedfishSession.Id)/Storages/$StorageId" $Response = Invoke-RedfishRequest $RedfishSession $GetStoragesPath -ContinueEvenFailed $StatusCode = $Response.StatusCode.value__ if ($StatusCode -eq 404) { $ErrorDetail = [String]::Format($(Get-i18n ERROR_STORAGE_ID_NOT_EXISTS), $StorageId) throw "[$($RedfishSession.Address)] $ErrorDetail" } $StorageController = $Response | ConvertFrom-WebResponse $DriveLinkList = $StorageController.Drives } $DriveLinkList | ForEach-Object { $OdataId = $_."@odata.id" $Drive = Invoke-RedfishRequest $RedfishSession $OdataId | ConvertFrom-WebResponse $CleanUp = $Drive | Clear-OdataProperties | Merge-OemProperties [Void] $Drives.Add($(Update-SessionAddress $RedfishSession $CleanUp)) } return ,$Drives.ToArray() } try { $tasks = New-Object System.Collections.ArrayList $pool = New-RunspacePool $Session.Count for ($idx = 0; $idx -lt $Session.Count; $idx++) { $RedfishSession = $Session[$idx] $_StorageId = $StorageIdList[$idx] $Logger.info($(Trace-Session $RedfishSession "Submit Get iBMC drive resources task")) [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock @($RedfishSession, $_StorageId))) } $Results = Get-AsyncTaskResults $tasks return ,$Results } finally { Close-Pool $pool } } end { } } function Get-iBMCDrivesHealth { <# .SYNOPSIS Query health information about the Drive resources of a server. .DESCRIPTION Query health information about the Drive resources of a server including summary health status and every Drive controller health status. .PARAMETER Session iBMC redfish session object which is created by Connect-iBMC cmdlet. A session object identifies an iBMC server to which this cmdlet will be executed. .OUTPUTS PSObject[] Returns PSObject indicates Drive health status of server if cmdlet executes successfully. In case of an error or warning, exception will be returned. .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> $health = Get-iBMCDrivesHealth -Session $session PS C:\> $health | fl Host : 10.1.1.2 Summary : @{HealthRollup=OK} ID#HDDPlaneDisk0 : @{Health=OK; State=; Name=Disk0} ID#HDDPlaneDisk1 : @{Health=OK; State=; Name=Disk1} ID#HDDPlaneDisk2 : @{Health=OK; State=; Name=Disk2} ID#HDDPlaneDisk3 : @{Health=OK; State=; Name=Disk3} ID#HDDPlaneDisk4 : @{Health=OK; State=; Name=Disk4} ID#HDDPlaneDisk5 : @{Health=OK; State=; Name=Disk5} ID#HDDPlaneDisk6 : @{Health=OK; State=; Name=Disk6} ID#HDDPlaneDisk7 : @{Health=OK; State=; Name=Disk7} ID#HDDPlaneDisk40 : @{Health=OK; State=; Name=Disk40} ID#HDDPlaneDisk41 : @{Health=OK; State=; Name=Disk41} .LINK https://github.com/Huawei/Huawei-iBMC-Cmdlets Get-iBMCDrives Set-iBMCDrive Connect-iBMC Disconnect-iBMC #> [CmdletBinding()] param ( [RedfishSession[]] [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] $Session ) begin { } process { Assert-ArrayNotNull $Session 'Session' $Logger.info("Invoke Get iBMC Drive health function") $ScriptBlock = { param($RedfishSession) $(Get-Logger).info($(Trace-Session $RedfishSession "Invoke Get iBMC Drive health now")) $GetChassisPath = "/Chassis/$($RedfishSession.Id)" $Chassis = Invoke-RedfishRequest $RedfishSession $GetChassisPath | ConvertFrom-WebResponse $Health = New-Object PSObject -Property @{ Host = $RedfishSession.Address; Summary = $Chassis.Oem.huawei.DriveSummary.Status; } $StatusPropertyOrder = @("Health", "State") $Chassis.Links.Drives | ForEach-Object { $OdataId = $_."@odata.id" $Drive = Invoke-RedfishRequest $RedfishSession $OdataId | ConvertFrom-WebResponse $Status = Copy-ObjectProperties $Drive.Status $StatusPropertyOrder $Status | Add-member Noteproperty "Name" $Drive.Name $Health | Add-Member Noteproperty "ID#$($Drive.ID)" $Status } return $Health } try { $tasks = New-Object System.Collections.ArrayList $pool = New-RunspacePool $Session.Count for ($idx = 0; $idx -lt $Session.Count; $idx++) { $RedfishSession = $Session[$idx] $Logger.info($(Trace-Session $RedfishSession "Submit Get iBMC Drive health task")) [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock @($RedfishSession))) } $Results = Get-AsyncTaskResults $tasks return ,$Results } finally { Close-Pool $pool } } end { } } function Set-iBMCDrive { <# .SYNOPSIS Modify properties of the specified drive of a server. .DESCRIPTION Modify properties of the specified drive of a server. .PARAMETER Session iBMC redfish session object which is created by Connect-iBMC cmdlet. A session object identifies an iBMC server to which this cmdlet will be executed. .PARAMETER DriveId Indicates the identifier of the drive to modify. The Id properties of "Get-iBMCDrives" cmdlet's return value represents Drive ID. .PARAMETER State Indicates the state of a drive. NOTE: Before setting the drive status to JBOD, need to enable JBOD for the RAID controller first. Drive state can be alternated between the following status: - Online and Offline - UnconfiguredGood and JBOD - UnconfigureBad and UnconfiguredGood .PARAMETER LEDState Indicates the location indicator state of a drive. Support value set: Off, Blinking. .PARAMETER HotSpareType Indicates the hot spare state of a drive. Support value set: None, Global, Dedicated. .PARAMETER VolumeId Indicates the ID of the associated volume if the drive is a dedicated hot spare drive. The Id properties of "Get-iBMCLogicDrive" cmdlet's return value represents volume ID, example: LogicalDrive. NOTE: - When HotSpareType is None or Global, VolumeId is redundant. - When HotSpareType is Dedicated, VolumeId is mandatory. .OUTPUTS Null Returns null if cmdlet executes successfully. In case of an error or warning, exception will be returned. .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> Set-iBMCDrive -Session $session -DriveId HDDPlaneDisk0 -State JBOD This example shows how to set drive's state to "JBOD" .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> Set-iBMCDrive -Session $session -DriveId HDDPlaneDisk0 -LEDState Blinking This example shows how to blinking drive's led .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> Set-iBMCDrive -Session $session -DriveId HDDPlaneDisk0 -HotSpareType Dedicated -VolumeId LogicalDrive0 This example shows how to set drive's hot-spare type to "Dedicated" to volume "LogicalDrive0" .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> Set-iBMCDrive -Session $session -DriveId HDDPlaneDisk0 -HotSpareType Global This example shows how to set drive's hot-spare type to "Global" .EXAMPLE PS C:\> $credential = Get-Credential PS C:\> $Session = Connect-iBMC -Address 10.1.1.2 -Credential $credential -TrustCert PS C:\> Set-iBMCDrive -Session $session -DriveId HDDPlaneDisk0 -HotSpareType None This example shows how to set drive's hot-spare type to "None" .LINK https://github.com/Huawei/Huawei-iBMC-Cmdlets Get-iBMCDrives Get-iBMCDrivesHealth Connect-iBMC Disconnect-iBMC #> [CmdletBinding()] param ( [RedfishSession[]] [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $Session, [String[]] [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $DriveId, [DriveState[]] [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $State, [DriveLEDState[]] [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $LEDState, [HotSpareType[]] [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $HotSpareType, [String[]] [parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $VolumeId ) begin { } process { Assert-ArrayNotNull $Session 'Session' Assert-ArrayNotNull $DriveId 'DriveId' $DriveIdList = Get-MatchedSizeArray $Session $DriveId $StateList = Get-OptionalMatchedSizeArray $Session $State $LEDStateList = Get-OptionalMatchedSizeArray $Session $LEDState $HotSpareTypeList = Get-OptionalMatchedSizeArray $Session $HotSpareType $VolumeIdList = Get-OptionalMatchedSizeArray $Session $VolumeId $Logger.info("Invoke Set iBMC drive resources function") $ScriptBlock = { param($RedfishSession, $DriveId, $Payload) $Logger.info($(Trace-Session $RedfishSession "Invoke Set iBMC drive now")) $Path = "/Chassis/$($RedfishSession.Id)/Drives/$DriveId" # fetch logical dirves if ($null -ne $Payload.Oem -and $null -ne $Payload.Oem.Huawei.SpareforLogicalDrives) { $VolumeOdataId = Get-VolumeOdataId $RedfishSession $Payload.Oem.Huawei.SpareforLogicalDrives if ($null -ne $VolumeOdataId) { $Payload.Oem.Huawei.SpareforLogicalDrives = @( @{ "@odata.id" = $VolumeOdataId; } ) } } $Logger.info($(Trace-Session $RedfishSession "Sending payload: $($Payload | ConvertTo-Json -Depth 5)")) $Response = Invoke-RedfishRequest $RedfishSession $Path 'PATCH' $Payload Resolve-RedfishPartialSuccessResponse $RedfishSession $Response | Out-Null return $null } try { $ParametersList = New-Object System.Collections.ArrayList for ($idx = 0; $idx -lt $Session.Count; $idx++) { $RedfishSession = $Session[$idx] $_HotSpareType = $HotspareTypeList[$idx] $_VolumeId = $VolumeIdList[$idx] $_State = $StateList[$idx] $_LEDState = $LEDStateList[$idx] if ($_HotSpareType -eq [HotSpareType]::Dedicated -and $null -eq $_VolumeId) { throw $(Get-i18n ERROR_VOLUMEID_MANDATORY) } $Oem = @{ "FirmwareStatus" = $_State; "SpareforLogicalDrives" = $_VolumeId; } | Remove-EmptyValues | Resolve-EnumValues $Payload = @{ "IndicatorLED" = $_LEDState; "HotspareType" = $_HotSpareType; } | Remove-EmptyValues | Resolve-EnumValues if ($Oem.Count -gt 0) { $Payload.Oem = @{ "Huawei" = $Oem; } } if ($Payload.Count -eq 0) { throw $(Get-i18n ERROR_NO_UPDATE_PAYLOAD) } $Parameters = @($RedfishSession, $DriveIdList[$idx], $Payload) [Void] $ParametersList.Add($Parameters) } $pool = New-RunspacePool $Session.Count $tasks = New-Object System.Collections.ArrayList for ($idx = 0; $idx -lt $Session.Count; $idx++) { $Logger.info($(Trace-Session $RedfishSession "Submit Set iBMC drive task")) [Void] $tasks.Add($(Start-ScriptBlockThread $pool $ScriptBlock $ParametersList[$idx])) } $Results = Get-AsyncTaskResults $tasks return ,$Results } finally { Close-Pool $pool } } end { } } |