
1. 项目背景与核心需求在虚拟化运维工作中管理员经常需要批量获取vCenter管理的所有ESXi主机信息。传统的手动登录vSphere Web Client逐台查看的方式效率低下尤其当集群规模达到数十甚至上百台主机时这种操作模式会消耗大量时间且容易出错。VMware官方提供了多种自动化接口方案其中基于Python的PyVmomi SDK是最灵活的选择之一。通过编写Python脚本我们可以实现自动连接vCenter ServerVC递归遍历所有数据中心、集群和主机提取关键配置信息CPU/内存/存储/网络等生成结构化报告CSV/Excel/JSON等这种自动化方式特别适合以下场景定期资产盘点合规性检查容量规划数据收集故障排查前的环境快照2. 环境准备与依赖安装2.1 基础环境要求建议使用Python 3.6环境主要依赖库包括pip install pyvmomi requests six注意PyVmomi对不同版本vCenter的兼容性存在差异建议使用与vCenter版本匹配的SDK版本。例如vCenter 7.0对应pyvmomi 7.0.3。2.2 认证信息配置创建config.ini文件存储连接信息[vcenter] server vc01.example.com username automationvsphere.local password your_secure_password port 4432.3 证书处理可选对于自签名证书环境需添加证书验证豁免import ssl context ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode ssl.CERT_NONE3. 核心代码实现3.1 建立vCenter连接from pyVim.connect import SmartConnect, Disconnect def get_vc_connection(config): try: si SmartConnect( hostconfig[server], userconfig[username], pwdconfig[password], portint(config[port]), sslContextcontext ) return si except Exception as e: print(fConnection failed: {str(e)}) return None3.2 遍历主机信息def get_all_esxi_info(service_instance): content service_instance.RetrieveContent() host_info [] for datacenter in content.rootFolder.childEntity: if hasattr(datacenter, hostFolder): cluster datacenter.hostFolder while hasattr(cluster, childEntity): cluster cluster.childEntity[0] for host in cluster.host: h { name: host.name, vendor: host.summary.hardware.vendor, model: host.summary.hardware.model, cpu_cores: host.summary.hardware.numCpuCores, memory_mb: host.summary.hardware.memorySize//1024//1024, version: host.summary.config.product.version, connection_state: host.summary.runtime.connectionState, ip_address: host.summary.managementServerIp } host_info.append(h) return host_info3.3 数据输出处理生成CSV报告示例import csv def save_to_csv(host_data, filenameesxi_inventory.csv): with open(filename, w, newline) as f: writer csv.DictWriter(f, fieldnameshost_data[0].keys()) writer.writeheader() writer.writerows(host_data)4. 高级功能扩展4.1 性能指标采集通过PerformanceManager获取实时指标def get_perf_metrics(si, host, metric_names): perf_manager si.content.perfManager metric_ids [ pm.MetricId(counterIdcounter.key, instance*) for counter in perf_manager.perfCounter if counter.groupInfo.key cpu and counter.nameInfo.key in metric_names ] query pm.QuerySpec( entityhost, metricIdmetric_ids, intervalId20, maxSample1 ) return perf_manager.QueryPerf(querySpec[query])4.2 批量配置检查验证NTP配置一致性def check_ntp_config(host): ntp_config host.configManager.dateTimeSystem.dateTimeInfo return { ntp_configured: ntp_config.ntpConfig.server ! [], ntp_servers: ,.join(ntp_config.ntpConfig.server) }5. 异常处理与优化建议5.1 常见错误处理from pyVmomi import vim, vmodl try: # 主逻辑代码 except vmodl.MethodFault as e: print(fVMware API error: {e.msg}) except Exception as e: print(fGeneral error: {str(e)}) finally: if si in locals(): Disconnect(si)5.2 性能优化技巧批量查询使用PropertyCollector代替逐属性获取pc si.content.propertyCollector filter_spec vmodl.query.PropertyCollector.FilterSpec() result pc.RetrieveContents([filter_spec])并行处理对大型环境使用多线程from concurrent.futures import ThreadPoolExecutor with ThreadPoolExecutor(max_workers10) as executor: results list(executor.map(process_host, host_list))6. 实际应用案例6.1 自动化巡检报告结合HTML模板生成可视化报告from jinja2 import Template def generate_html_report(host_data): with open(template.html) as f: template Template(f.read()) return template.render(hostshost_data)6.2 与CMDB集成通过REST API将数据写入CMDBimport requests def update_cmdb(host_data): url https://cmdb-api.example.com/hosts headers {Authorization: Bearer xxxx} for host in host_data: requests.post(url, jsonhost, headersheaders)7. 安全注意事项认证信息应使用加密存储如Vault实施最小权限原则只读账户足够敏感数据输出需脱敏处理def mask_password(text): return re.sub(r(password[\]?\s*:\s*[\])(.?)([\]), r\1*****\3, text)8. 完整脚本示例#!/usr/bin/env python3 VMware ESXi信息收集工具 功能从vCenter获取所有ESXi主机详细信息 输出CSV格式报告 import configparser import csv from pyVim.connect import SmartConnect, Disconnect import ssl # 禁用证书验证生产环境应使用正式证书 context ssl._create_unverified_context() def main(): config configparser.ConfigParser() config.read(config.ini) si SmartConnect( hostconfig[vcenter][server], userconfig[vcenter][username], pwdconfig[vcenter][password], portint(config[vcenter][port]), sslContextcontext ) content si.RetrieveContent() host_data [] for dc in content.rootFolder.childEntity: if not hasattr(dc, hostFolder): continue for cluster in dc.hostFolder.childEntity: for host in cluster.host: host_data.append({ Datacenter: dc.name, Cluster: cluster.name, Hostname: host.name, IP: host.summary.managementServerIp, CPU Cores: host.summary.hardware.numCpuCores, Memory (GB): round(host.summary.hardware.memorySize/1024**3, 1), Version: host.summary.config.product.version, Status: host.summary.runtime.connectionState }) with open(esxi_report.csv, w) as f: writer csv.DictWriter(f, fieldnameshost_data[0].keys()) writer.writeheader() writer.writerows(host_data) Disconnect(si) if __name__ __main__: main()9. 后续扩展方向与Prometheus集成将采集数据转换为metrics格式from prometheus_client import start_http_server, Gauge cpu_usage Gauge(esxi_cpu_usage, CPU usage percent, [host]) for host in host_data: cpu_usage.labels(hosthost[name]).set(host[cpu_usage])自动化修复功能基于检查结果执行修复操作def fix_ntp_config(host, ntp_servers): time_system host.configManager.dateTimeSystem time_system.UpdateDateTimeConfig( configvim.host.DateTimeConfig( ntpConfigvim.host.NtpConfig(serverntp_servers) ) )历史数据对比使用SQLite存储时间序列数据import sqlite3 from datetime import datetime conn sqlite3.connect(inventory.db) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS host_history ( date TEXT, hostname TEXT, cpu_cores INTEGER, memory_gb REAL, PRIMARY KEY (date, hostname) ) )