使用PowerShell

时间:2017-01-11 07:34:58

标签: arrays powershell powercli

我正在为VMWare平台上的虚拟机部署脚本工作,但我已经陷入困境。

基本上,我的脚本会这样做:

从Excel接收信息并首先运行一些检查。在创建任何VM之前,它会为每行代表VM信息。

验证所有虚拟机后,将创建第一个虚拟机,然后创建下一个虚拟机等。

我的一个功能是计算最佳可用存储磁盘。它返回具有最多可用磁盘空间的第一个存储磁盘。

该功能如下所示:

Function Get-AvailableStorage {
    $Threshold = "80" # GB
    $TotalFreeSpace = Get-Cluster -Name Management |
                      Get-Datastore |
                      where Name -notlike "*local*" |
                      sort FreeSpaceGB -Descending
    if ($SqlServices -notlike "NONE") {
        $VMSize = 30 + $VMStorage + 10
    } else {
        $VMSize = 30 + $VMStorage
    }

    foreach ($StorageDisk in $TotalFreeSpace) {
        [math]::floor($StorageDisk.FreeSpaceGB) | Set-Variable RoundedSpace
        $FreeAfter =  $RoundedSpace - $VMSize | sort -Descending
        if ($FreeAfter -lt $Threshold) {
            return $StoragePool = "VSAN"
        } else {
            return $StorageDisk.Name
        }
    }
}

问题

当我的Excel中有多个虚拟机时,存储磁盘始终相同,因为可用磁盘空间未更新(因为尚未部署任何虚拟机)。

我自己做了一些调查:

我必须想办法更新列FreeSpaceGB,但这是一个ReadOnly属性。 然后,我会推动我自己创建的另一个阵列中的每个项目,但这也不起作用。还是Readonly财产。 然后我考虑将PSObjectAdd-Member一起使用,但我也无法解决这个问题(或者我做错了)。

$ownarray= @()
$item = New-Object PSObject

$Global:TotalFreeSpaceManagement = Get-Cluster -Name Management |
    Get-Datastore |
    where Name -notlike "*local*" |
    sort FreeSpaceGB -Descending

foreach ($StorageDisk in $Global:TotalFreeSpaceManagement) {
    $item | Add-Member -Type NoteProperty -Name "$($StorageDisk.Name)" -Value "$($StorageDisk.FreeSpaceGB)" 
    $ownarray += $item
}

更新

我使用像@Ansgar建议的哈希表。当我手动尝试它时,它完美地工作,但在我的脚本中却没有。 当我在阵列中有多个VM时,正在使用先前的数据存储区,并且剩下的空间是更新的。

示例:

VM1为120GB并使用VM-105。该磁盘剩余299GB VM2为130GB,使用VM-105。然后磁盘剩下289GB。

两个虚拟机都根据最多可用空间获得建议的VM-105。

VM-105应该有299 - 130 = 160GB左边是脚本工作正常但不知何故$FreeSpace被更新,或$max被覆盖,我无法弄清楚这是怎么发生的。

1 个答案:

答案 0 :(得分:0)

您需要跟踪可用空间的更改,同时还要保持磁盘与计算的剩余可用空间之间的关联。为此,请将存储读入哈希表,该哈希表将磁盘与可用空间相关联。然后使用该哈希表选择磁盘并在放置VM时更新相应的可用空间值。

$threshold = 80   # GB

# initialize global hashtable
$storage = @{}
Get-Cluster -Name Management | Get-Datastore | Where-Object {
    $_.Name -notlike '*local*'
} | ForEach-Object {
    $script:storage[$_.Name] = [Math]::Floor($_.FreeSpaceGB)
}

function Get-AvailableStorage([int]$VMSize) {
    # find disk that currently has the most free space
    $disk = ''
    $max  = 0
    foreach ($key in $script:storage.Keys) {
        $freespace = $script:storage[$key]   # just to shorten condition below
        if ($freespace -gt $max -and $threshold -lt ($freespace - $VMSize)) {
            $max  = $freespace
            $disk = $key
        }
    }

    # return storage and update global hashtable
    if (-not $disk) {
        return 'VSAN'   # fallback if no suitable disk was found
    } else {
        $script:storage[$disk] -= $VMSize
        return $disk
    }
}