こんにちは。
前回の記事でAzure Stack HCI OS 21H2 をNested で構築する方法をご紹介しました。
今回は、構築する中で、めちゃくちゃ便利なスクリプトをご紹介します。
構築中に あ!間違えた!とか入力ミスして構築をしてしまったことがある人は結構いるとおもいます。構築したあとに フェールオーバークラスタ名が違っていた、とか、
構築に失敗して、ファイルシステムのゴミがいっぱい生まれて、次構築しようとしたらうまく構築ができず四苦八苦、、、などエンジニアのみなさまなら想像がつくかとおもいます。
そんなときに使えるスクリプトを 海外のMicrosoft MVP の方が作ってくれていて、これがめちゃくちゃ重宝します。
私のチームではこのスクリプトを "魔法のスクリプト" と呼んでいます 笑
https://github.com/dkawula/Operations/blob/master/S2D/FactoryReset-Clear-SDSConfig.ps1
【私が試して動作問題なかったOS】
Windows Server 2019 のS2D
Azure Stack HCI OS 21H2
Azure Stack HCI OS 20H2
【ハードウェア環境】
ESXi 上で作成したNested 環境で実行 → 普通に使えた
AX6515(Dell のS2D ReadyNode) → 普通に使えた
BOSS Boot Device 240GB x 2 (Raid1)
SSD 960GB x 4 本(All Flash 構成)
想定トラブル時1
実際に私が困って使った状況をご紹介します。
現在、AX6515 というDell Technologiesの S2D Ready Node を使って検証をしているのですが、いざ構成しようとしたら、以前に誰かが使っていてファイルシステムが残っていてこのような状態になっていました。
これは Get-physicaldisk コマンドレットを実行した結果なのですが、このマシンは SSD 4本とBoot Devce(BOSS)を積んでいるのみのマシンにもかかわらず、過去に誰かが検証した際のゴミが残っています。
OS をインストールするときのセットアップウィザードで消したらいいのでは?という方もいらっしゃるかもしれませんが、残念ながらその画面では消せませんでした。
(状況によりますが)
みて頂くとわかりますが、CanPool 列 が False になっていますよね。
False になっていると S2D を構成できないのでここを True にする必要があるわけです。
そのため、魔法のスクリプトを実行します。
その前にスクリーンショットの環境は Azure Stack HCI OS 21H2 で実行しているので、Server Core (CLI) のみのOSですので、ネットワーク上に共有ファイルを作って、そこにスクリプトを置いて、ASH OS 側にコピーして実行しました。
172.31.90.5 のCドライブの共有設定して、そこに魔法スクリプトを置いています。
置いた魔法スクリプトを Azue Stack HCI OS の Cドライブ配下にコピーしています。
コピーしてきた、スクリプトを実際に実行します。
※元のスクリプト名が長いので 短いスクリプト名に名前変更だけしています。
実行開始します。
途中で エラーなども多く表示されますが、無視して大丈夫です。
理由は最後に記載します。
ディスクがクリーニングされているのがわかります。
4本のディスクとBootDevice が削除されていることが表示されています。
では実際に、Get−Physicaldisk を実行してみましょう。
ゴミが消えて、SSD 4本とBoot Devce(BOSS) のみ表示されるようになりました。
また、CanPool の値が True になっているので、Azure Stack HCI の構成ができるDisk になっているのがわかります!
想定トラブル時2
構築が終わったあとに、再構築する必要がでた場合にも魔法スクリプトは素晴らしい活躍をします 笑
一度2ノードでも、3ノードでもいいのですが、構築し終わったあとの Azure Stack HCI は、フェールオーバークラスタが構成され、S2D(Storage Space Direct)も構成されている状況です。もちろんクラスターが構成されているわけですから、クラスターディスクも作成されているので、再構築になると猛烈にダルい作業が発生します。
エンジニアの人だと「OS再インストールからなのか…?」「ファイルシステムにゴミが残る…」「IP Address 振り直し…?」いろいろ思い浮かぶと思います。
それらの一気に解消するのも魔法スクリプトです。😋
先程、ここでエラーがでていましたよね。
ここで何をしているか、というとクラスターの削除やクラスターディスクの削除をしています。
つまり、この魔法スクリプトは、クラスターを削除し、S2D 機能をオフにしたのち、
ディスクを綺麗サッパリしてくれるということです。
注意点
もし仮想スイッチが作成されている場合は、仮想スイッチだけコマンドで削除する必要があります。そのときは Remove-VMSwitch コマンドレットで削除をお願いします!
コマンドだるいな。。。というときはWindows Admin Centerからホストに接続して仮想スイッチの削除もできます。
最後に
個人的にすばらしいとおもったのは、IP Address の設定は初期化されないですし、ドメインに参加している場合はドメインから離脱することもありません。
つまり、魔法スクリプトを各ノードで実行するだけで再度Azure Stack HCI の構築を開始することができます。
ESXi の Nested とかでここまでの便利なものはみたことが個人的になかったので感動的でした…検証時や実際の構築時に困ったらつかってみてはいかがでしょうか。
一応念の為申し上げておくと、使用については自己責任でお願いしますね😋
Microsoft MVP の方が善意で公開してくれてるものですので。
よい Azure Stack HCI 生活を!!!
一応スクリプト内容をそのまま張っておきます。
-------------------------------------
# # | |
# *** USE AT YOUR OWN RISK *** # | |
# PERMANANT DATA LOSS WILL OCCUR # | |
# # | |
# This script completely clears any existing Storage Spaces configuration # | |
# and all data on EVERY non-system drive PERMANENTLY! # | |
# # | |
# Notes: # | |
# # | |
# If certain drives cannot be cleared and the reason given is # | |
# 'Redundant Path' then MPIO may need to be installed and/or configured. # | |
# # | |
# Power cycling the JBOD enclosures can also remove additional # | |
# errors encountered during the run. # | |
# # | |
# Run cmdlet with Administrator rights. # | |
# # | |
################################## WARNING ################################ | |
################################# Change Log ################################ | |
# # | |
# 02/13/2014: Changed logic to remove SAS-connected boot/system disks # | |
# 02/13/2014: Changed output for clearing disks and tracking runtime # | |
# 04/07/2014: Corrected logic to deal boot and system drives # | |
# 04/07/2014: Added logic to deal with non-core cluster objects # | |
# 07/23/2015: Changes to better support Storage Spaces Direct # | |
# # | |
############################################################################# | |
#Script has been tested and verified to work to Factory Reset Storage Spaces Direct by Dave Kawula# | |
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")] | |
param() | |
if ($PSCmdlet.ShouldProcess("localhost","Clear Storage Spaces configuration and wipe disks")) | |
{ | |
Write-Host "" | |
Write-Host Clearing existing Storage Spaces configuration and wiping disks... | |
Write-Host "" | |
$runStart = [DateTime]::Now | |
# Install necessary tools if needed | |
$toolsInstalled = $false | |
if (!(Get-WindowsFeature -Name "RSAT-Clustering-PowerShell").Installed) | |
{ | |
Write-Host Installing required tools... -ForegroundColor Cyan -NoNewline | |
Install-WindowsFeature -Name "RSAT-Clustering-PowerShell" | |
$toolsInstalled = $true | |
Write-Host Done. | |
Write-Host "" | |
} | |
# Remove any cluster objects if present | |
Write-Host "Removing any cluster objects" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
foreach ($clusterGroup in (Get-ClusterGroup -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) | |
{ | |
if (!$clusterGroup.IsCoreGroup) | |
{ | |
Remove-ClusterGroup -Name $clusterGroup.Name -Force:$true -RemoveResources:$true -ErrorAction SilentlyContinue | |
} | |
} | |
Remove-Cluster -Force -CleanupAD -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | |
Write-Host "Done." | |
$disks = Get-PhysicalDisk | Where-Object {($_.BusType -EQ "SAS") -or ($_.BusType -EQ "SATA")} # -or ($_.BusType -EQ "RAID")} | |
Write-Host "" | |
Write-Host "Removing any stale PRs" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
foreach ($disk in $disks) | |
{ | |
Clear-ClusterDiskReservation -Disk $disk.DeviceId -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | |
} | |
Write-Host "Done." | |
Write-Host "" | |
Write-Host "Updating the storage provider cache (x2)" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Start-Sleep 1 | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Write-Host "Done." | |
# Remove virtual disks and storage pools | |
Write-Host "" | |
Write-Host "Removing Virtual Disks and Pools" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
$storagePools = Get-StoragePool | ? FriendlyName -NE "primordial" | |
$storagePools | Set-StoragePool -IsReadOnly:$false | |
Get-VirtualDisk | Set-VirtualDisk -IsManualAttach:$false | |
Get-VirtualDisk | Remove-VirtualDisk -Confirm:$false | |
$storagePools | Remove-StoragePool -Confirm:$false | |
Write-Host "Done." | |
Write-Host "" | |
Write-Host "Updating the storage provider cache (x2)" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Start-Sleep 1 | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Write-Host "Done." | |
Write-Host "" | |
# Collect IDs of any system/boot disks | |
$disks = Get-Disk | |
$diskIdsToRemove = @() | |
foreach ($disk in $disks) | |
{ | |
if ($disk.IsBoot -or $disk.IsSystem) | |
{ | |
$diskIdsToRemove += $disk.UniqueId | |
} | |
} | |
# Get collection of physical disks | |
$allPhysicalDisks = Get-PhysicalDisk | Where-Object {($_.BusType -EQ "SAS") -or ($_.BusType -EQ "SATA")} # -or ($_.BusType -EQ "RAID")} | |
# Create a new collection of physical disks without any system/boot disks | |
$physicalDisks = @() | |
foreach ($physicalDisk in $allPhysicalDisks) | |
{ | |
$addDisk = $true | |
foreach ($diskIdToRemove in $diskIdsToRemove) | |
{ | |
if ($physicalDisk.UniqueId -eq $diskIdToRemove) | |
{ | |
$addDisk = $false | |
} | |
} | |
if ($addDisk) | |
{ | |
$physicalDisks += $physicalDisk | |
} | |
} | |
# Iterate through all remaining physcial disks and wipe | |
Write-Host "Cleaning disks" -ForegroundColor Cyan -NoNewline | |
Write-Host "..." | |
$totalDisks = $physicalDisks.Count | |
$counter = 1 | |
foreach ($physicalDisk in $physicalDisks) | |
{ | |
$disk = $physicalDisk | Get-Disk | |
# Make sure disk is Online and not ReadOnly otherwise, display reason | |
# and continue | |
$disk | Set-Disk –IsOffline:$false -ErrorAction SilentlyContinue | |
$disk | Set-Disk –IsReadOnly:$false -ErrorAction SilentlyContinue | |
# Re-instantiate disks to update changes | |
$disk = $physicalDisk | Get-Disk | |
if ($disk.IsOffline -or $disk.IsReadOnly) | |
{ | |
Write-Host "Warning: " -NoNewline -ForegroundColor Yellow | |
Write-Host "Unable to process disk " -NoNewline | |
Write-Host $disk.Number -NoNewline | |
Write-Host ": Offline Reason: " -NoNewline | |
Write-Host ($disk.OfflineReason) -NoNewline -ForegroundColor Yellow | |
Write-Host ", HealthStatus: " -NoNewline | |
Write-Host $disk.HealthStatus -ForegroundColor Yellow | |
} | |
else | |
{ | |
Write-Host "Cleaning disk " -NoNewline | |
Write-Host $disk.Number -NoNewline -ForegroundColor Cyan | |
Write-Host " (" -NoNewline | |
Write-Host $counter -NoNewline -ForegroundColor Cyan | |
Write-Host " of " -NoNewline | |
Write-Host $totalDisks -NoNewline -ForegroundColor Cyan | |
Write-Host ")..." -NoNewline | |
# Wipe disk and initialize | |
$disk | ? PartitionStyle -NE "RAW" | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false | |
$disk | Initialize-Disk -PartitionStyle GPT | |
Write-Host Done. | |
} | |
$counter++ | |
} | |
# Remove any installed roles/tools | |
if ($toolsInstalled) | |
{ | |
Write-Host Uninstalling Failover Cluster tool... -NoNewline -ForegroundColor Cyan | |
Remove-WindowsFeature -Name "Failover-Clustering","RSAT-Clustering-PowerShell" | |
Write-Host Done. | |
} | |
Write-Host "" | |
Write-Host "Updating the storage provider cache (x2)" -NoNewline -ForegroundColor Cyan | |
Write-Host "..." -NoNewline | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Start-Sleep 1 | |
Update-StorageProviderCache -DiscoveryLevel Full | |
Write-Host "Done." | |
# Output physical disk counts | |
Write-Host "" | |
Write-Host Physical Disks: | |
Get-PhysicalDisk | Group-Object Manufacturer,Model,MediaType,Size | ft Count,Name -AutoSize | |
Write-Host Configuration and data cleared! | |
Write-Host "" | |
Write-Host "Run duration: " -NoNewline | |
Write-Host ([Math]::Round((([DateTime]::Now).Subtract($runStart)).TotalMinutes,2)) -ForegroundColor Yellow -NoNewline | |
Write-Host " minutes" | |
} |