需求:想要购买cvm时初始化数据盘
解决方案:购买cvm的时候,选公共镜像,在cvm购买界面上一并加购数据盘并勾选初始化复选框,然后就会自动化分好区;自定义镜像不行,平台的考虑是:自定义镜像千差万别,平台无法确认客户自定义镜像的init环境,因此前端才没设计那个勾选按钮,不过初始化数据盘本质上是通过init的userdata起作用的,理论上在userdata里传入选公共镜像时勾选初始化数据盘后userdata部分的代码的话,自定义镜像也可以实现初始化数据盘,前提是自定义镜像的init是ok的(linux对应cloudinit,windows对应cloudbase-init)
优化后的windows数据盘初始化代码如下
原本代码里没有匹配上大小是TB的情况,所以大盘不会被初始化,然后我加了匹配大盘的逻辑,把日志输出弄细了些方便出现异常的时候可以回溯定位问题,并增加了≥16TB盘的逻辑:超过16T的盘应该按8192的块大小分区,默认块大小4096最大只能支持到16T分区,超过16TB的那部分空白空间用不上
目前在2008R2、2012R2、2016、2019、2022中文版测试挂20块32000GB的盘进行极限测试是可以顺利初始化的
代码语言:javascript复制#ps1
$Global:UserMount = 'E'
$Global:TotalDataDisk = 0
$disks =Get-WmiObject Win32_DiskDrive | Where {$_.Partitions -eq 0} | select DeviceID,Size|findstr /i PHYSICALDRIVE | ForEach-Object { ($_.split("E ")[1].PadLeft(2)) ',' ($_.Split(" ")[-1]) }|sort
function SetAllDiskOnline {
Write-Output 'SetAllDiskOnline' >> C:disk_init.txt
$DiskList = 'list disk' | diskpart.exe
Write-Output $DiskList >> C:disk_init.txt
foreach ($Disk in $DiskList) {
if ($Disk -match 'Disks (?<DiskIdx>d ) | u78c1u76d8s (?<DiskIdx>d )') {
$DiskIdx = $Matches.DiskIdx
Write-Output "Setting disk $DiskIdx online" >> C:disk_init.txt
if ([int]$DiskIdx -ge 1) {
$Global:TotalDataDisk = $Global:TotalDataDisk 1
$DiskOps = @"
select disk $DiskIdx
online disk
san policy=OnlineAll
exit
"@
$DiskOps | diskpart.exe | Out-Null
Start-Sleep -Seconds 0.1
}
}
}
}
function CheckShouldInit {
Write-Output 'CheckShouldInit' >> C:disk_init.txt
$VolumeList = 'list volume' | diskpart.exe
$TotalVolume = 0
foreach ($Volume in $VolumeList) {
if ($Volume -match 'Volumes (?<VolumeIdx>d ) | u5377s (?<VolumeIdx>d )') {
$TotalVolume = $TotalVolume 1
}
}
if ($TotalVolume -gt 3) {
Write-Output 'Not a new instance, exit' >> C:disk_init.txt
exit
}
Write-Output 'New instance to be initilized' >> C:disk_init.txt
}
function InitDataDisk {
Write-Output 'InitDataDisk' >> C:disk_init.txt
$DiskList = 'list disk' | diskpart.exe
$DriverLetterList = [char[]](69..90)
$Idx = 0
foreach ($Disk in $DiskList) {
if ($Disk -match 'Disks (?<DiskIdx>d )s (Online|Offline)s (?<Size>d )s GBs (?<Free>d )|u78c1u76d8s (?<DiskIdx>d )s (u8054u673a|u8131u673a)s (?<Size>d )s GBs (?<Free>d )|Disks (?<DiskIdx>d )s (Online|Offline)s (?<Size>d )s TBs (?<Free>d )|u78c1u76d8s (?<DiskIdx>d )s (u8054u673a|u8131u673a)s (?<Size>d )s TBs (?<Free>d )') {
$DiskIdx = $Matches.DiskIdx
if ($DiskIdx -ge 1) {
$DriverLetter = $DriverLetterList[$Idx]
if ($Global:TotalDataDisk -le 1) {
$DriverLetter = $Global:UserMount
}
$disktype="mbr"
if(([Math]::Round($disks[$DiskIdx-1].split(",")[1]/1024/1024/1024)) -gt 2048)
{
$disktype="gpt"
}
$unit=4096
if(([Math]::Round($disks[$DiskIdx-1].split(",")[1]/1024/1024/1024)) -gt 16384)
{
$unit=8192
}
$DiskOps = @"
SELECT DISK $DiskIdx
online disk NOERR
attr disk clear readonly NOERR
convert $disktype NOERR
CREATE PARTITION PRIMARY NOERR
format fs=ntfs unit=$unit quick NOERR
ASSIGN LETTER=$DriverLetter
san policy=onlineall
EXIT
"@
Write-Output "Start initializing disk $DiskIdx" >> C:disk_init.txt
$DiskOps | diskpart.exe >> C:disk_init.txt
Start-Sleep -Seconds 0.1
Write-Output "DataDisk $DiskIdx is assigned to driver: $DriverLetter" >> C:disk_init.txt
$Idx = $Idx 1
}
}
}
}
Write-Output 'Initializing data disks' >> C:disk_init.txt
SetAllDiskOnline
CheckShouldInit
InitDataDisk