You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于govmomi库的VM按资源池过滤及跨DC查询技术问询

解决govmomi中资源池名称显示、按名称过滤VM及跨所有DC搜索的问题

针对你提出的两个核心问题,以及当前输出资源池标识符而非实际名称的痛点,我整理了具体的解决方案和优化后的代码:

1. 按资源池名称过滤VM的简洁实现

govc的逻辑是先定位资源池再过滤VM,govmomi里可以复刻这个思路,而且更高效:

  • 先用Finder.ResourcePoolList搜索匹配目标名称的资源池(支持通配符)
  • 直接获取这些资源池下关联的VM,避免遍历所有VM后再过滤,节省性能

2. 无需指定DC名称,自动搜索所有数据中心

可以通过Finder.DatacenterList传入*通配符,一次性获取当前vSphere环境下的所有数据中心,完全不用硬编码DC名称,适配不同vSphere实例的差异。

额外修复:显示资源池实际名称

原代码只获取了VM关联的资源池引用,需要通过属性收集器批量查询这些引用对应的资源池名称,建立「引用ID-名称」的映射表,就能替换掉输出里的标识符。

修改后的完整代码

package main

import (
	"flag"
	"fmt"
	"net/url"
	"os"
	"sync"

	"github.com/vmware/govmomi"
	"github.com/vmware/govmomi/find"
	"github.com/vmware/govmomi/property"
	"github.com/vmware/govmomi/vim25/mo"
	"github.com/vmware/govmomi/vim25/types"
	"golang.org/x/net/context"
)

var vsphereUrl = "https://name:pass@vsphere/sdk"
var insecureFlag = false
var targetPoolName = "YourTargetPoolName" // 替换为你的目标资源池名称

func exit(err error) {
	fmt.Fprintf(os.Stderr, "Error: %s\n", err)
	os.Exit(1)
}

// 批量获取资源池引用对应的名称,建立映射表
func getResourcePoolNameMap(ctx context.Context, pc *property.Collector, poolRefs []types.ManagedObjectReference) map[string]string {
	nameMap := make(map[string]string)
	if len(poolRefs) == 0 {
		return nameMap
	}

	var pools []mo.ResourcePool
	err := pc.Retrieve(ctx, poolRefs, []string{"name"}, &pools)
	if err != nil {
		exit(err)
	}

	for _, pool := range pools {
		nameMap[pool.Reference().Value] = pool.Name
	}
	return nameMap
}

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	flag.Parse()

	u, err := url.Parse(vsphereUrl)
	if err != nil {
		exit(err)
	}

	c, err := govmomi.NewClient(ctx, u, insecureFlag)
	if err != nil {
		exit(err)
	}

	f := find.NewFinder(c.Client, true)

	// 获取当前vSphere下的所有DC,无需硬编码名称
	dcs, err := f.DatacenterList(ctx, "*")
	if err != nil {
		exit(err)
	}

	var group sync.WaitGroup

	for _, dc := range dcs {
		group.Add(1)
		// 启动goroutine处理每个DC的查询
		go func(ctx context.Context, dc mo.Datacenter, f *find.Finder, c *govmomi.Client, group *sync.WaitGroup, targetPool string) {
			defer group.Done()

			f.SetDatacenter(&dc)

			// 查找当前DC下匹配目标名称的资源池
			targetPools, err := f.ResourcePoolList(ctx, targetPool)
			if err != nil {
				fmt.Fprintf(os.Stderr, "DC %s: 查找资源池%s失败: %s\n", dc.Name, targetPool, err)
				return
			}

			if len(targetPools) == 0 {
				fmt.Printf("DC %s: 未找到名称为%s的资源池\n", dc.Name, targetPool)
				return
			}

			pc := property.DefaultCollector(c.Client)
			var allVMs []mo.VirtualMachine

			// 遍历每个目标资源池,获取池内的VM
			for _, pool := range targetPools {
				var poolObj mo.ResourcePool
				err := pc.RetrieveOne(ctx, pool.Reference(), []string{"vm"}, &poolObj)
				if err != nil {
					fmt.Fprintf(os.Stderr, "DC %s: 获取资源池%s下的VM失败: %s\n", dc.Name, pool.Name, err)
					continue
				}

				if len(poolObj.Vm) == 0 {
					continue
				}

				// 获取这些VM的名称和关联资源池信息
				var vms []mo.VirtualMachine
				err = pc.Retrieve(ctx, poolObj.Vm, []string{"name", "resourcePool"}, &vms)
				if err != nil {
					fmt.Fprintf(os.Stderr, "DC %s: 获取VM信息失败: %s\n", dc.Name, err)
					continue
				}

				allVMs = append(allVMs, vms...)
			}

			// 建立资源池ID到名称的映射
			poolRefs := make([]types.ManagedObjectReference, 0, len(allVMs))
			for _, vm := range allVMs {
				poolRefs = append(poolRefs, vm.ResourcePool)
			}
			poolNameMap := getResourcePoolNameMap(ctx, pc, poolRefs)

			// 输出格式化结果
			fmt.Printf("\n=== DC: %s ===\n", dc.Name)
			for _, vm := range allVMs {
				poolName := poolNameMap[vm.ResourcePool.Value]
				fmt.Printf("VM名称: %s | 资源池: %s\n", vm.Name, poolName)
			}
		}(ctx, dc, f, c, &group, targetPoolName)
	}

	group.Wait()
	fmt.Println("\n所有查询完成。")
}

关键优化点说明

  • 自动遍历所有DC:通过f.DatacenterList(ctx, "*")动态获取所有数据中心,适配不同vSphere环境的DC名称差异
  • 精准过滤VM:先定位目标资源池,再直接获取池内VM,比全局遍历VM后过滤效率更高
  • 资源池名称显示:通过批量查询资源池属性建立映射表,彻底替换输出中的标识符
  • 健壮的错误处理:单个DC的查询失败不会导致整个程序退出,同时输出明确的错误提示

内容的提问来源于stack exchange,提问作者Alex Nikitin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:22:25