如何通过PowerShell调用vSphere REST API精准获取指定数据存储下的虚拟机列表
我明白你现在的困扰——想通过PowerShell结合vSphere REST API关联数据存储与它下面的虚拟机,但用filter.datastores参数好像没得到预期结果。让我帮你排查问题并修正脚本,确保能精准拿到每个数据存储对应的VM列表。
问题分析
你的核心逻辑方向是对的:先获取所有数据存储,再遍历每个存储的ID去过滤虚拟机。可能导致filter.datastores不生效的原因主要有两个:
- 部分vSphere版本中,
filter.datastores需要严格遵循数组参数格式(哪怕只传单个ID) - 脚本中未初始化全局累加变量,会导致使用率计算异常
- 缺少错误处理,单个请求失败会直接中断整个脚本
修正后的完整可运行脚本
# 辅助函数:MiB转MB(保留两位小数,符合日常认知的MB单位) function Convert-MiBtoMB { param ( [double]$MiBValue ) $MBValue = $MiBValue * ([Math]::Pow(2, 20) / [Math]::Pow(10, 6)) return [Math]::Round($MBValue, 2) } # -------------------------- 配置参数区 -------------------------- $server = "your-vcenter-server.fqdn" # 替换为你的vCenter地址 $user = "your-admin-account" # 替换为有权限的账号 $pass = "your-password" # 替换为对应密码 $threshold = 80 # 存储使用率告警阈值(百分比) # ---------------------------------------------------------------- # 1. 获取vCenter会话ID(替代Basic Auth,更安全合规) $basicAuthHeaders = @{ "Authorization" = "Basic $([Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$user`:$pass")))" } # 处理自签名证书警告(生产环境建议导入vCenter的CA证书,不要用这个临时方案) Add-Type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 -bor [System.Net.SecurityProtocolType]::Tls13 try { $sessionId = Invoke-RestMethod -Method POST -Uri "https://$server/api/session" -Headers $basicAuthHeaders -UseBasicParsing $sessionHeaders = @{ "vmware-api-session-id" = $sessionId } Write-Host "✅ 成功获取vCenter会话ID" } catch { Write-Error "❌ 获取vCenter会话失败:$($_.Exception.Message)" exit 1 } # 2. 获取所有数据存储基础信息 try { $dataStores = (Invoke-RestMethod -Method GET -Uri "https://$server/rest/vcenter/datastore" -Headers $sessionHeaders -UseBasicParsing).value Write-Host "✅ 成功获取$($dataStores.Count)个数据存储" } catch { Write-Error "❌ 获取数据存储列表失败:$($_.Exception.Message)" exit 1 } # 3. 遍历每个数据存储,关联虚拟机并计算使用率 $alertMessages = @() foreach ($ds in $dataStores) { $dsId = $ds.datastore $dsName = $ds.name # 用PowerShell内置单位转换简化计算,比手动算幂更直观 $dsFreeSpaceMiB = $ds.free_space / 1MiB $dsCapacityMiB = $ds.capacity / 1MiB $dsUsedSpaceMiB = $dsCapacityMiB - $dsFreeSpaceMiB $dsUsedPercent = [Math]::Round(($dsUsedSpaceMiB / $dsCapacityMiB) * 100, 2) # 3.1 精准获取当前存储下的虚拟机(修复Filter参数格式) try { # 注意:部分vCenter版本需要加[]明确数组参数,去掉[]也能生效可根据环境调整 $vmUri = "https://$server/rest/vcenter/vm?filter.datastores[]=$dsId" $dsVms = (Invoke-RestMethod -Method GET -Uri $vmUri -Headers $sessionHeaders -UseBasicParsing).value Write-Host `n📦 数据存储[$dsName] 已找到$($dsVms.Count)台虚拟机 } catch { Write-Warning "⚠️ 获取数据存储[$dsName]的虚拟机列表失败:$($_.Exception.Message)" $dsVms = @() } # 3.2 遍历输出当前存储下的VM信息 $totalVmMemoryTB = 0 foreach ($vm in $dsVms) { $vmName = $vm.name $vmMemoryMiB = $vm.memory_size_MiB $vmMemoryTB = $vmMemoryMiB / 1TiB $totalVmMemoryTB += $vmMemoryTB Write-Host " └─ $vmName | 内存:$([Math]::Round($vmMemoryMiB,0)) MiB" } # 3.3 检查使用率是否触发阈值告警 if ($dsUsedPercent -ge $threshold) { $freeSpaceMB = Convert-MiBtoMB $dsFreeSpaceMiB $alertMessages += "⚠️ 数据存储[$dsName]使用率超标:$dsUsedPercent% | 剩余空间:$freeSpaceMB MB" } } # 4. 输出最终告警汇总 Write-Host "`n==================== 告警汇总 ====================" if ($alertMessages.Count -eq 0) { Write-Host "✅ 所有数据存储使用率均在阈值范围内" } else { foreach ($msg in $alertMessages) { Write-Host $msg } } # 5. 清理会话(符合vCenter安全最佳实践) try { Invoke-RestMethod -Method DELETE -Uri "https://$server/api/session" -Headers $sessionHeaders -UseBasicParsing Write-Host "`n✅ 已销毁vCenter会话" } catch { Write-Warning "⚠️ 销毁会话失败:$($_.Exception.Message)" }
关键修改点说明
修复Filter参数有效性:
部分vCenter的REST框架要求数组参数带[]后缀,所以用filter.datastores[]=$dsId替代原格式,确保过滤逻辑精准生效。如果你的环境去掉[]也能拿到正确结果,也可以直接调整。简化单位计算:
用PowerShell内置的单位后缀(1MiB、1TiB)替代手动计算[Math]::Pow,代码更易读且不易出错。完善错误处理:
给每个API请求加try/catch,单个存储或VM请求失败不会中断整个脚本,还会给出明确的警告信息。会话安全优化:
脚本末尾调用DELETE /api/session销毁会话,避免无效会话残留;同时用会话ID认证替代全程Basic Auth,更符合vCenter安全规范。
快速验证方法
如果想单独测试Filter参数是否生效,可以直接在Postman或浏览器中发请求:
GET https://your-vcenter/rest/vcenter/vm?filter.datastores[]=datastore-123 Headers: vmware-api-session-id=你的会话ID
如果返回的VM列表正确,说明参数格式没问题;如果返回所有VM,大概率是当前用户没有该存储下VM的读取权限,或者数据存储ID填写错误。
扩展建议
如果需要更精准的存储使用率统计(比如VM的磁盘实际占用),可以调用/rest/vcenter/vm/{vm-id}/hardware/disk接口,获取每个VM的磁盘大小和对应的存储信息,这样计算的存储使用情况会比内存统计更贴合实际。




