【问题标题】:Updating value in array with PowerShell使用 PowerShell 更新数组中的值
【发布时间】:2017-01-11 07:34:58
【问题描述】:

我正在为 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 中有多个 VM 时,存储磁盘始终相同,因为可用磁盘空间未更新(因为尚未部署任何 VM)。

我自己做了一些调查:

我必须想办法更新FreeSpaceGB 列,但这是一个只读属性。 然后,我将每个项目都推送到我自己创建的另一个数组中,但这也不起作用。仍然是只读属性。 然后我考虑使用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 建议的哈希表。当我手动尝试它时,它工作得很好,但在我的脚本中却不是。 当我在一个阵列中有多个虚拟机时,之前的数据存储正在被使用并且剩余的空间被更新。

例子:

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

根据最大可用空间,两个 VM 都获得了建议的 VM-105。

VM-105 应该还剩 299 - 130 = 160GB 是脚本工作正常,但不知何故 $FreeSpace 被更新,或者 $max 被覆盖,我不知道这是怎么发生的。

【问题讨论】:

  • 你需要一个数组列表。你必须添加那个。检查我对数组列表的回答ArrayList
  • @RanadipDutta,谢谢,但我仍然遇到无法更新值的问题。当我这样做时: $array_list[1].FreeSpaceMB = '1' 我的错误; 'FreeSpaceMB' 是只读属性。或者我不完全了解如何更新:),很抱歉,但没有 SetValue 方法。
  • 有关更新代码的帮助:显示更新后的代码。我刚刚在我的代码中修改了一个逻辑错误并再次测试,它完全符合我的预期。

标签: arrays powershell powercli


【解决方案1】:

您需要跟踪可用空间的变化,同时还要保持磁盘与计算出的剩余可用空间之间的关联。为此,将您的存储读取到将磁盘与可用空间相关联的哈希表中。然后使用该哈希表来选择磁盘并在放置 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
    }
}

【讨论】:

  • 关于您的答案@Ansgar 的微小变化;我不得不在 $threshold 和 VMSize 中使用双引号。否则它不能正常工作
  • 仍在搞清楚哈希表的工作。我可以在存储中使用 -xxx(因此没有剩余存储空间),但试图弄清楚它是怎么来的 :)
  • 我已经更新了我的问题,因为我现在有另一个问题
  • 循环中确定使用哪个磁盘的第二个条件错误。必须是 -lt,而不是 -gt。更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多