接近完善的代码,待生产环境测试。

This commit is contained in:
panjunlan
2026-02-21 14:26:14 +08:00
parent 9024e9c8e4
commit 17e9e0c3bc
11 changed files with 357 additions and 293 deletions

127
core/remove_snapshots.py Normal file
View File

@@ -0,0 +1,127 @@
import os, time, yaml
from pyVmomi import vim
from pyVim.connect import Disconnect
from core.vm_connector import connect_vcenter
from config.settings import YAML_OUTPUT_PATH
from utils.logger import logger
def load_old_snapshots(file_path):
"""从 YAML 文件中加载旧快照"""
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as yaml_file:
return yaml.safe_load(yaml_file)
else:
logger.error(f"{file_path} 文件不存在.")
return []
def remove_snapshot(dele_snapshots):
"""根据 YAML 信息删除旧快照"""
# print(dele_snapshots)
if not dele_snapshots:
logger.info("没有需要删除的快照")
return
# 按 NodeHost 分组,避免重复连接
grouped = {}
for snapshot in dele_snapshots:
if snapshot['is_old']:
grouped.setdefault(snapshot['NodeHost'], []).append(snapshot)
# print(grouped)
for host, snapshots in grouped.items():
logger.info(f"连接 {host} 进行删除快照...")
try:
si = connect_vcenter(host)
try:
for snapshot in snapshots:
# print(snapshot)
delete_snapshot(si, snapshot) # 调用删除快照函数
finally:
Disconnect(si)
except Exception as e:
logger.error(f"快照删除失败,因为连接 {host} 失败:{e}" )
# 执行快照删除的(核心)函数
def delete_snapshot(si, snapshot_info):
""" 执行快照删除 """
content = si.RetrieveContent()
snap_name = f"{snapshot_info['VMName']}-{snapshot_info['Snapshot Name']}-({snapshot_info['MOID']})"
vm = find_vm_by_name(content, snapshot_info['VMName']) # 根据快照名,查找出相应的虚拟机
# print(snap_name,vm)
if not vm:
logger.info(f"未找到 VM: {snapshot_info['VMName']}")
return
# 检查该虚拟机是否有快照
if not vm.snapshot:
logger.warning(f"{snap_name}:快照不存在")
return
# 调用函数获取虚拟机快照的 MOID 信息
snapshot_obj = find_snapshot_by_moid(
vm.snapshot.rootSnapshotList,
snapshot_info['MOID']
)
# print(snapshot_obj)
if not snapshot_obj:
logger.warning(snap_name,":未找到")
return
try:
"""删除快照核心代码,调用快照对象的 RemoveSnapshot_Task 方法执行。removeChildren = False表示删除该快照时不删除其子快照。"""
logger.info(f"正在删除 Snapshot: {snap_name}")
task = snapshot_obj.RemoveSnapshot_Task(removeChildren=False)
# 改进的等待逻辑
while task.info.state in [vim.TaskInfo.State.running, vim.TaskInfo.State.queued]:
time.sleep(1) # 每秒检查一次
# 更完整的状态判断
if task.info.state == vim.TaskInfo.State.success:
logger.info(f"✅ 删除成功: {snap_name}")
elif task.info.state == vim.TaskInfo.State.error:
error_msg = task.info.error.msg if task.info.error else "未知错误"
logger.error(f"❌ 删除失败: {snap_name}, 错误: {error_msg}")
else:
# 处理其他状态(如 cancelled
logger.warning(f"⚠️ 任务未成功完成,状态: {task.info.state}")
except Exception as e:
logger.exception(f"删除快照时发生异常: {snap_name}")
raise
"""根据 VM 名称查找虚拟机"""
def find_vm_by_name(content, vm_name):
container = content.viewManager.CreateContainerView(
content.rootFolder, [vim.VirtualMachine], True
)
for vm in container.view:
if vm.name == vm_name:
container.Destroy()
return vm
container.Destroy()
return None
""" 递归查找 snapshot 对象 """
def find_snapshot_by_moid(snapshot_tree, moid):
for snapshot in snapshot_tree:
if snapshot.snapshot._moId == moid:
return snapshot.snapshot
if snapshot.childSnapshotList:
result = find_snapshot_by_moid(snapshot.childSnapshotList, moid)
if result:
return result
return None
if __name__ == "__main__":
old_snapshots = load_old_snapshots(YAML_OUTPUT_PATH) # 获取待删除的快照信息
remove_snapshot(old_snapshots)