如何使用Ruby在vCenter中筛选指定网络网段下的所有虚拟机
Ruby实现vCenter指定网段下虚拟机筛选方法
前置准备
- 提前安装适配对应vCenter版本的
rbvmomiRuby SDK,可通过gem install rbvmomi完成安装 - 准备具备全局只读权限的vCenter登录账号、目标xxx-segment对应的网络名称、需要匹配的目标CIDR格式网段值(如192.168.10.0/24)
实现逻辑
整体流程对齐vCenter控制台的展示逻辑:建立vCenter API连接 -> 拉取全量虚拟机实例 -> 逐台读取虚拟机关联的网络配置 -> 匹配目标segment网络归属与IP网段范围 -> 输出符合条件的虚拟机清单
核心实现代码
首先引入依赖并初始化vCenter连接:
require 'rbvmomi' require 'ipaddr' # 替换为实际环境的配置值 VCENTER_ENDPOINT = '你的vCenter服务访问地址' VCENTER_ACCOUNT = '具备查询权限的登录账号' VCENTER_SECRET = '账号对应的登录密码' TARGET_SEGMENT_NAME = '需要筛选的xxx-segment网络名称' TARGET_SUBNET_CIDR = '目标匹配的网段CIDR格式值' # 建立vCenter API连接 vcenter_conn = RbVmomi::VIM.connect( host: VCENTER_ENDPOINT, user: VCENTER_ACCOUNT, password: VCENTER_SECRET, insecure: true # 测试环境可开启跳过证书校验,生产环境建议配置有效证书路径 )
拉取全量虚拟机并执行筛选逻辑:
# 获取vCenter根目录下的所有虚拟机对象 root_folder = vcenter_conn.serviceContent.rootFolder all_vm_instances = root_folder.children.grep(RbVmomi::VIM::VirtualMachine) target_subnet = IPAddr.new(TARGET_SUBNET_CIDR) matched_result = [] all_vm_instances.each do |vm| # 遍历当前VM关联的所有网络对象 vm.network.each do |network| # 跳过不属于目标segment的网络 next unless network.name == TARGET_SEGMENT_NAME # 读取VM网卡的实际IP,过滤回环、链路本地地址避免误判 attached_ips = vm.guest.net.flat_map(&:ipAddress).reject { |ip| ip.match?(/^fe80|^127\./) } # 筛选出IP落在目标网段的条目 valid_ips = attached_ips.select { |ip| target_subnet.include?(IPAddr.new(ip)) } # 没有匹配IP就跳过 next if valid_ips.empty? matched_result << { vm_name: vm.name, object_ref: vm._ref, network: network.name, matched_ips: valid_ips } end end # 打印最终筛选结果 puts "目标网段匹配的虚拟机清单:" matched_result.each do |item| puts "VM名称:#{item[:vm_name]} | 所属网络:#{item[:network]} | 匹配IP:#{item[:matched_ips].join(', ')}" end
注意事项
- 版本兼容性:老版本
rbvmomi对vSphere 7以上的NSX-T逻辑段(即常见的xxx-segment类网络)存在识别兼容问题,需升级SDK到对应支持版本,否则会出现网络名称读取为空的情况 - VMware Tools依赖:如果目标VM未安装VMware Tools,接口将无法读取到网卡的实际IP信息,此时仅能通过匹配网络名称完成筛选,无法校验IP网段范围
- 敏感信息处理:生产环境禁止将账号密码硬编码在代码中,建议从环境变量或加密配置文件读取敏感信息
- 性能优化:如果环境内VM规模超过千台,可配合SDK的分页查询接口减少全量拉取的性能消耗
内容的提问来源于stack exchange,提问作者Peter Ruan
相关产品推荐
相关产品推荐

