28 KiB
RemoveWeeklySnapshot
Vmware 虚拟机自动化程序:自动化导出虚拟机和快照信息,自动化删除旧快照。
Todo List
- Yaml 文件保存配置信息
- 通过 Yaml 文件信息连接vCenter/Esxi
- 文件获取所有 vms
- 获取所有 snapshots
- 筛选出15天(半个月)前的 snapshots
- 以上内容以 Excel 表格的形式导出,超出 15 天的快照蓝色底填充标识
- 最后删除 15 天前的 snapshot,并同时记录删除的 snapshot 日志信息
- 设置计划任务,每周六(或 每15 天)执行一次
- 增加排除不能删除的 snapshots 信息,用红色底填充标识
- 删除快照前/后发送邮件通知
- 多线程删除(控制每台 vCenter 不可以同时删除超过 4 个快照)
- 改用数据库保存管理节点账号密码(加密)
输出所有可用的属性和方法
| 你想获取 | 代码 | 示例输出 |
|---|---|---|
| 名称 | vm.name |
"WebServer-01" |
| MOID | vm._moId |
"vm-12" |
| 电源状态 | vm.runtime.powerState |
poweredOn / poweredOff |
| 开机时间 | vm.runtime.bootTime |
datetime 对象 |
| CPU数 | vm.config.hardware.numCPU |
4 |
| 内存(MB) | vm.config.hardware.memoryMB |
8192 |
| 操作系统 | vm.config.guestFullName |
"CentOS 7 (64-bit)" |
| IP地址 | vm.guest.ipAddress |
"192.168.1.100" |
| 主机名 | vm.guest.hostName |
"webserver01.local" |
| 存储路径 | vm.config.files.vmPathName |
"[Datastore1] WebServer-01/WebServer-01.vmx" |
| 快照数量 | len(vm.snapshot.rootSnapshotList) |
3 |
以下这些方法和属性主要用于操作虚拟机(VM)、快照、存储和其他资源。
vm ├── 基础标识 │ ├── name VM名称 │ └── _moId 内部ID (vm-12) │ ├── runtime 【运行状态】 │ ├── powerState poweredOn/Off/Suspended │ ├── bootTime 开机时间 │ └── host 所在物理机 │ ├── config 【硬件配置】 │ ├── hardware CPU/内存/硬盘 │ ├── guestFullName 操作系统 │ └── files VMX文件路径 │ ├── guest 【客户机内部信息】 │ ├── hostName 主机名 │ ├── ipAddress IP地址 │ └── toolsStatus VMware Tools状态 │ ├── snapshot 【快照】 │ └── rootSnapshotList 快照树 │ ├── storage 【存储】 │ └── perDatastoreUsage 各数据存储用量 │ ├── network 【网络】 │ └── [Network] 连接的端口组 │ └── summary 【快速汇总】 ├── overallStatus 整体健康状态 └── quickStats 实时性能数据
- AcquireMksTicket / AcquireTicket:获取访问虚拟机控制台的票据,允许用户通过 Web 界面访问 VM。
- Clone / CloneVM_Task:克隆一个虚拟机,创建其副本。
- CreateSnapshot / CreateSnapshot_Task:创建虚拟机快照,以保存当前 VM 的状态。
- Destroy / Destroy_Task:删除虚拟机及其所有数据。
- PowerOn / PowerOnVM_Task:启动虚拟机。
- PowerOff / PowerOffVM_Task:关闭虚拟机。
- Reset / ResetVM_Task:重置虚拟机,相当于按下重启按钮。
- RevertToCurrentSnapshot / RevertToCurrentSnapshot_Task:将虚拟机恢复到当前快照的状态。
- Migrate / MigrateVM_Task:迁移虚拟机到不同的主机或数据存储。
- SetCustomValue:设置自定义属性值,以便在虚拟机上存储额外信息。
属性列表
这些属性通常包含关于虚拟机或其他资源的状态和配置信息。以下是一些关键属性的说明:
- name:虚拟机的名称。
- guest:关于虚拟机操作系统的信息,如操作系统类型、版本等。
- config:虚拟机的配置详情,例如 CPU、内存、硬盘等。
- runtime:虚拟机的运行时状态,包括电源状态(开机、关机、挂起等)。
- snapshot:当前虚拟机的快照信息。
- summary:虚拟机的概述信息,包括状态、资源使用情况等。
- resourcePool:虚拟机所在的资源池。
- datastore:虚拟机的存储位置,指向其使用的存储库。
- overallStatus:虚拟机的总体状态,可能是正常、警告、错误等。
- recentTask:最近执行的任务列表。
其他属性
- capability:虚拟机支持的功能,如支持的虚拟硬件版本。
- declaredAlarmState:声明的警报状态,用于监控虚拟机的健康状况。
- triggeredAlarmState:触发的警报状态,显示当前激活的警报。
for vm in vm_view.view:
print(dir(vm)) # 输出所有可用的属性和方法
# print(vm.summary)
# print(vm.snapshot)
# print(vars(vm.summary))
['AcquireMksTicket', 'AcquireTicket', 'Answer', 'AnswerVM', 'ApplyEvcMode', 'ApplyEvcModeVM_Task', 'Array', 'AttachDisk', 'AttachDisk_Task', 'CheckCustomizationSpec', 'Clone', 'CloneVM_Task', 'ConsolidateDisks', 'ConsolidateVMDisks_Task', 'CreateScreenshot', 'CreateScreenshot_Task', 'CreateSecondary', 'CreateSecondaryEx', 'CreateSecondaryVMEx_Task', 'CreateSecondaryVM_Task', 'CreateSnapshot', 'CreateSnapshotEx', 'CreateSnapshotEx_Task', 'CreateSnapshot_Task', 'CryptoUnlock', 'CryptoUnlock_Task', 'Customize', 'CustomizeVM_Task', 'DefragmentAllDisks', 'Destroy', 'Destroy_Task', 'DetachDisk', 'DetachDisk_Task', 'DisableSecondary', 'DisableSecondaryVM_Task', 'DropConnections', 'EnableSecondary', 'EnableSecondaryVM_Task', 'EstimateStorageForConsolidateSnapshots_Task', 'EstimateStorageRequirementForConsolidate', 'ExportVm', 'ExtractOvfEnvironment', 'InstantClone', 'InstantClone_Task', 'MakePrimary', 'MakePrimaryVM_Task', 'MarkAsTemplate', 'MarkAsVirtualMachine', 'Migrate', 'MigrateVM_Task', 'MountToolsInstaller', 'PowerOff', 'PowerOffVM_Task', 'PowerOn', 'PowerOnVM_Task', 'PromoteDisks', 'PromoteDisks_Task', 'PutUsbScanCodes', 'QueryChangedDiskAreas', 'QueryConnections', 'QueryFaultToleranceCompatibility', 'QueryFaultToleranceCompatibilityEx', 'QueryUnownedFiles', 'RebootGuest', 'ReconfigVM_Task', 'Reconfigure', 'RefreshStorageInfo', 'Reload', 'ReloadFromPath', 'Relocate', 'RelocateVM_Task', 'RemoveAllSnapshots', 'RemoveAllSnapshots_Task', 'Rename', 'Rename_Task', 'Reset', 'ResetGuestInformation', 'ResetVM_Task', 'RevertToCurrentSnapshot', 'RevertToCurrentSnapshot_Task', 'SendNMI', 'SetCustomValue', 'SetDisplayTopology', 'SetScreenResolution', 'ShutdownGuest', 'StandbyGuest', 'StartRecording', 'StartRecording_Task', 'StartReplaying', 'StartReplaying_Task', 'StopRecording', 'StopRecording_Task', 'StopReplaying', 'StopReplaying_Task', 'Suspend', 'SuspendVM_Task', 'Terminate', 'TerminateFaultTolerantVM', 'TerminateFaultTolerantVM_Task', 'TerminateVM', 'TurnOffFaultTolerance', 'TurnOffFaultToleranceForVM_Task', 'UnmountToolsInstaller', 'Unregister', 'UnregisterVM', 'UpgradeTools', 'UpgradeTools_Task', 'UpgradeVM_Task', 'UpgradeVirtualHardware', '_GetMethodInfo', '_GetMethodList', '_GetMoId', '_GetPropertyInfo', '_GetPropertyList', '_GetServerGuid', '_GetStub', '_InvokeAccessor', '_InvokeMethod', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__firstlineno__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__static_attributes__', '__str__', '__subclasshook__', '__weakref__', '_methodInfo', '_moId', '_propInfo', '_propList', '_serverGuid', '_stub', '_version', '_wsdlName', 'alarmActionsEnabled', 'availableField', 'capability', 'config', 'configIssue', 'configStatus', 'customValue', 'datastore', 'declaredAlarmState', 'disabledMethod', 'effectiveRole', 'environmentBrowser', 'guest', 'guestHeartbeatStatus', 'layout', 'layoutEx', 'name', 'network', 'overallStatus', 'parent', 'parentVApp', 'permission', 'recentTask', 'reloadVirtualMachineFromPath_Task', 'resourceConfig', 'resourcePool', 'rootSnapshot', 'runtime', 'setCustomValue', 'snapshot', 'storage', 'summary', 'tag', 'triggeredAlarmState', 'value']
获取虚拟机属性
获取和打印出虚拟机 (VM) 概要信息的所有属性,提供了关于虚拟机的基本信息,vm.summary 会返回一个字典,包含常见属性。可以使用 vm.guest.ipAddress 方法获取到虚拟机的IP地址等。
print(vm.summary)
(vim.vm.Summary) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], vm = 'vim.VirtualMachine:1', runtime = (vim.vm.RuntimeInfo) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], device = (vim.vm.DeviceRuntimeInfo) [ (vim.vm.DeviceRuntimeInfo) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], runtimeState = (vim.vm.DeviceRuntimeInfo.VirtualEthernetCardRuntimeState) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], vmDirectPathGen2Active = false, vmDirectPathGen2InactiveReasonVm = (str) [ 'vmNptDisabledOrDisconnectedAdapter' ], vmDirectPathGen2InactiveReasonOther = (str) [], vmDirectPathGen2InactiveReasonExtended = , uptv2Active = , uptv2InactiveReasonVm = (str) [], uptv2InactiveReasonOther = (str) [], reservationStatus = , attachmentStatus = 'red', featureRequirement = (vim.vm.FeatureRequirement) [] }, key = 4000 } ], host = 'vim.HostSystem:ha-host', connectionState = 'connected', powerState = 'poweredOff', vmFailoverInProgress = , faultToleranceState = 'notConfigured', dasVmProtection = , toolsInstallerMounted = false, suspendTime = , bootTime = , suspendInterval = 0, question = , memoryOverhead = , maxCpuUsage = 5184, maxMemoryUsage = 4096, numMksConnections = 0, recordReplayState = 'inactive', cleanPowerOff = false, needSecondaryReason = , onlineStandby = false, minRequiredEVCModeKey = , consolidationNeeded = false, offlineFeatureRequirement = (vim.vm.FeatureRequirement) [ (vim.vm.FeatureRequirement) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], key = 'cpuid.lm', featureName = 'cpuid.lm', value = 'Bool:Min:1' } ], featureRequirement = (vim.vm.FeatureRequirement) [], featureMask = (vim.host.FeatureMask) [], vFlashCacheAllocation = , paused = false, snapshotInBackground = false, quiescedForkParent = , instantCloneFrozen = false, cryptoState = , suspendedToMemory = , opNotificationTimeout = , iommuActive = }, guest = (vim.vm.Summary.GuestSummary) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], guestId = , guestFullName = , toolsStatus = 'toolsNotRunning', toolsVersionStatus = 'guestToolsUnmanaged', toolsVersionStatus2 = 'guestToolsUnmanaged', toolsRunningStatus = 'guestToolsNotRunning', hostName = , ipAddress = , hwVersion = }, config = (vim.vm.Summary.ConfigSummary) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], name = 'VMware vCenter Server Appliance', template = false, vmPathName = '[datastore1] VMware vCenter Server Appliance/VMware vCenter Server Appliance.vmx', memorySizeMB = 4096, cpuReservation = 0, memoryReservation = 0, numCpu = 2, numEthernetCards = 1, numVirtualDisks = 13, uuid = '564d7d77-f37f-64a7-47f2-a131a337c070', instanceUuid = '529e8be2-58ca-617c-ad7e-7f66de667471', guestId = 'other3xLinux64Guest', guestFullName = 'Other 3.x Linux (64-bit)', annotation = 'VMware vCenter Server Appliance', product = , installBootRequired = , ftInfo = , managedBy = , tpmPresent = false, numVmiopBackings = 0, hwVersion = }, storage = (vim.vm.Summary.StorageSummary) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], committed = 37476296711, uncommitted = 303123661815, unshared = 37476296711, timestamp = 2026-02-19T09:11:27.701184Z }, quickStats = (vim.vm.Summary.QuickStats) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], overallCpuUsage = , overallCpuDemand = , overallCpuReadiness = , guestMemoryUsage = , hostMemoryUsage = , guestHeartbeatStatus = 'gray', distributedCpuEntitlement = , distributedMemoryEntitlement = , staticCpuEntitlement = , staticMemoryEntitlement = , grantedMemory = , privateMemory = , sharedMemory = , swappedMemory = , balloonedMemory = , consumedOverheadMemory = , ftLogBandwidth = , ftSecondaryLatency = , ftLatencyStatus = , compressedMemory = , uptimeSeconds = , ssdSwappedMemory = , activeMemory = , memoryTierStats = (vim.vm.Summary.QuickStats.MemoryTierStats) [] }, overallStatus = 'green', customValue = (vim.CustomFieldsManager.Value) [] }
获取快照属性
输出快照所有信息
print(vm.snapshot)
(vim.vm.SnapshotInfo) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], currentSnapshot = 'vim.vm.Snapshot:1-snapshot-3', rootSnapshotList = (vim.vm.SnapshotTree) [ (vim.vm.SnapshotTree) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], snapshot = 'vim.vm.Snapshot:1-snapshot-1', vm = 'vim.VirtualMachine:1', name = 'snap-01', # 第一层快照 description = 'Ansible snapshot', id = 1, createTime = 2026-02-17T03:26:08.834505Z, state = 'poweredOff', quiesced = false, backupManifest = , childSnapshotList = (vim.vm.SnapshotTree) [ (vim.vm.SnapshotTree) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], snapshot = 'vim.vm.Snapshot:1-snapshot-2', vm = 'vim.VirtualMachine:1', name = 'snap-02', # 第二层快照 description = 'test-Ansible snapshot', id = 2, createTime = 2026-02-17T08:57:39.122511Z, state = 'poweredOff', quiesced = false, backupManifest = , childSnapshotList = (vim.vm.SnapshotTree) [ (vim.vm.SnapshotTree) { dynamicType = , dynamicProperty = (vmodl.DynamicProperty) [], snapshot = 'vim.vm.Snapshot:1-snapshot-3', vm = 'vim.VirtualMachine:1', name = '虚拟机快照 2026%252f2%252f19 12:28:36', # 第二层快照 description = '', id = 3, createTime = 2026-02-19T04:28:38.007703Z, state = 'poweredOn', quiesced = false, backupManifest = , childSnapshotList = (vim.vm.SnapshotTree) [], replaySupported = false } ], replaySupported = false } ], replaySupported = false } ] }
PY 文件作用
PS D:\PycharmProjects\RemoveWeeklySnapshot> tree /F
卷 Date 的文件夹 PATH 列表
卷序列号为 0E45-0F72
D:.
│ main.py
│ README.md
│ requirements.txt
│
├─config
│ │ config.yaml
│ │ settings.py
│
├─core
│ │ data_exporter.py
│ │ get_vm_snapshots.py
│ │ remove_snapshots.py
│ │ vm_connector.py
│
├─logs
│ 2026-02-21-vm_snapshot_cleanup.log
│
├─output
│ old_snapshots-2026-02-21.yaml
│ vm_snapshots_report-2026-02-21.xlsx
│
├─utils
│ │ logger.py
所用到的 Python 库
PS D:\PycharmProjects\RemoveWeeklyShapshot> pip freeze > requirements.txt
APScheduler==3.11.2
openpyxl==3.2.0b1
pandas==3.0.1
pyvmomi==9.0.0.0
PyYAML==6.0.3
pip install -r requirements.txt
构建 Docker 镜像
新建数据目录
mkdir -p ~/removeweeklysnapshot/{config,logs,output} && cd ~/removeweeklysnapshot
安装 Docker
sudo curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker.repo
sudo dnf install docker-ce -y && docker -v
sudo systemctl enable --now docker && systemctl status docker
Dockerfile 文件
cat << 'EOF' > Dockerfile
FROM python:3.14.3-slim
# 配置时区
ENV TZ=Asia/Shanghai
RUN ln -fs /usr/share/zoneinfo/$TZ /etc/localtime && dpkg-reconfigure -f noninteractive tzdata
# 下载代码
ADD https://gitcode.junlan.site/junlan/RemoveWeeklyShapshot/archive/Dev.tar.gz /app/
# 解压压缩文件(最后 mv 命令改名)
RUN tar -xzf /app/Dev.tar.gz -C /app/ && rm /app/Dev.tar.gz && mv /app/removeweeklyshapshot /app/removeweeklysnapshot
# 设置工作目录
WORKDIR /app/removeweeklysnapshot
# 安装必要的软件和 python 库
RUN apt-get update && apt-get install procps tzdata -y && pip install -r requirements.txt && chmod +x main.py
# 添加项目根目录到 Python 路径
ENV PYTHONPATH=/app/removeweeklysnapshot
# 容器内执行启动程序
CMD ["python3", "/app/removeweeklysnapshot/main.py"]
EOF
执行构建 Docker 镜像
sudo docker build --no-cache -t removeweeklysnapshot .
构建 Compose 文件
cat << 'EOF' > compose.yaml
services:
removeweeklysnapshot:
container_name: removeweeklysnapshot
image: removeweeklysnapshot
volumes:
- /home/junlan/removeweeklysnapshot/logs:/app/removeweeklysnapshot/logs
- /home/junlan/removeweeklysnapshot/output:/app/removeweeklysnapshot/output
# - /home/junlan/removeweeklysnapshot/config/config.yaml:/app/removeweeklysnapshot/config/config.yaml
restart: always
stdin_open: true
tty: true
EOF
运行容器
sudo docker compose up -d
查看状态
# 查看镜像构建历史记录
[junlan@localhost ~]$ sudo docker history removeweeklysnapshot
IMAGE CREATED CREATED BY SIZE COMMENT
ff84aa4fde3b 35 minutes ago CMD ["python3" "/app/removeweeklysnapshot/ma… 0B buildkit.dockerfile.v0
<missing> 35 minutes ago ENV PYTHONPATH=/app/removeweeklysnapshot 0B buildkit.dockerfile.v0
<missing> 35 minutes ago RUN /bin/sh -c apt-get update && apt-get ins… 216MB buildkit.dockerfile.v0
<missing> 36 minutes ago WORKDIR /app/removeweeklysnapshot 0B buildkit.dockerfile.v0
<missing> 36 minutes ago RUN /bin/sh -c tar -xzf /app/Dev.tar.gz -C /… 51.4kB buildkit.dockerfile.v0
<missing> 36 minutes ago ADD https://gitcode.junlan.site/junlan/Remov… 16.6kB buildkit.dockerfile.v0
<missing> 36 minutes ago RUN /bin/sh -c ln -fs /usr/share/zoneinfo/$T… 1.65MB buildkit.dockerfile.v0
<missing> 36 minutes ago ENV TZ=Asia/Shanghai 0B buildkit.dockerfile.v0
<missing> 2 weeks ago CMD ["python3"] 0B buildkit.dockerfile.v0
<missing> 2 weeks ago RUN /bin/sh -c set -eux; for src in idle3 p… 36B buildkit.dockerfile.v0
<missing> 2 weeks ago RUN /bin/sh -c set -eux; savedAptMark="$(a… 36.6MB buildkit.dockerfile.v0
<missing> 2 weeks ago ENV PYTHON_SHA256=a97d5549e9ad81fe17159ed02c… 0B buildkit.dockerfile.v0
<missing> 2 weeks ago ENV PYTHON_VERSION=3.14.3 0B buildkit.dockerfile.v0
<missing> 2 weeks ago RUN /bin/sh -c set -eux; apt-get update; a… 3.81MB buildkit.dockerfile.v0
<missing> 2 weeks ago ENV PATH=/usr/local/bin:/usr/local/sbin:/usr… 0B buildkit.dockerfile.v0
<missing> 2 weeks ago # debian.sh --arch 'amd64' out/ 'trixie' '@1… 78.6MB debuerreotype 0.17
[junlan@localhost removeweeklyshapshot]$ sudo docker images
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
python:3.14.3-slim 486b8092bfb1 176MB 45.5MB
removeweeklysnapshot:latest 6f17fcaaef99 512MB 140MB
[junlan@localhost removeweeklyshapshot]$ sudo docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
removeweeklysnapshot removeweeklysnapshot "python3 /removeweek…" removeweeklysnapshot 34 seconds ago Up 15 seconds
[junlan@localhost removeweeklyshapshot]$ sudo docker compose logs removeweeklysnapshot -f
removeweeklysnapshot | 2026-02-22 16:01:50,113 - INFO - ✅ 成功加载配置,共 1 个管理节点
removeweeklysnapshot | 2026-02-22 16:01:50,954 - INFO - ✓ 导出任务已设置: 每周 sun 16:05
removeweeklysnapshot | 2026-02-22 16:01:50,954 - INFO - ✓ 删除任务已设置: 每周 sun 16:10
removeweeklysnapshot | 2026-02-22 16:01:50,956 - INFO - 调度器已启动,等待执行任务...
removeweeklysnapshot | 2026-02-22 16:05:00,002 - INFO - 🔍 开始收集VM和快照信息...
removeweeklysnapshot | 2026-02-22 16:05:00,269 - INFO - 成功连接到节点: vcsa8.snimay.com
removeweeklysnapshot | 2026-02-22 16:05:01,251 - INFO - 获取到 5 台虚拟机
removeweeklysnapshot | 2026-02-22 16:05:01,252 - INFO - 📝 开始导出Excel报表...
removeweeklysnapshot | 2026-02-22 16:05:01,257 - INFO - 总共有 4 个快照
removeweeklysnapshot | 2026-02-22 16:05:01,377 - DEBUG - Excel 文件已生成: /app/removeweeklysnapshot/output/vm_snapshots_report-2026-02-22.xlsx
removeweeklysnapshot | 2026-02-22 16:05:01,377 - INFO - 📝 开始导出 Yaml 文件...
removeweeklysnapshot | 2026-02-22 16:05:01,378 - INFO - 可删除的快照有 0 个
removeweeklysnapshot | 2026-02-22 16:05:01,379 - DEBUG - YAML 文件已生成: /app/removeweeklysnapshot/output/old_snapshots-2026-02-22.yaml
removeweeklysnapshot | 2026-02-22 16:05:01,379 - INFO - ========== Excel和Yaml文件导出完成 ==========
[junlan@localhost removeweeklyshapshot]$ sudo docker exec -it removeweeklysnapshot bash
root@07c30da6408a:/removeweeklysnapshot# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 15:12 pts/0 00:00:01 python3 /removeweeklysnapshot/main.py
root 11 0 0 15:15 pts/1 00:00:00 bash
root 17 11 0 15:15 pts/1 00:00:00 ps -ef
修改代码进行临时测试
- 修改 ==config.yaml== 文件
snapshot_retention_days: 0:定义删除多少天前的快照schedule:自定义改参数下的时间
cat << 'EOF' > ~/removeweeklysnapshot/config/config.yaml
# 管理节点配置(包含vCenter和ESXi)
management_nodes:
# vCenter节点
- type: vcenter # 标记类型为vcenter
name: vc1 # 节点名称(用于日志)
host: vcsa8.xxx.com # 地址
user: administrator@vcsa.local
password: Root@2020
max_delete_concurrent: 4 # 该节点最大并发删除数
# 全局策略配置
global:
disable_ssl_verify: true # ESXi连接特殊配置(禁用SSL验证,ESXi默认自签证书)
snapshot_retention_days: 1 # 可选,默认值 15 天
# 定时任务配置
schedule:
export: # 导出 Excel 和 Yaml 文件的时间
day_of_week: 'sun' # 星期几:mon,tue,wed,thu,fri,sat,sun
hour: 15 # 小时 (0-23)
minute: 58 # 分钟 (0-59)
second: 0 # 秒 (可选)
delete: # 删除快照的时间
day_of_week: 'sun'
hour: 15
minute: 59
second: 0
EOF
==================================================================================================
cat << 'EOF' > compose.yaml
services:
removeweeklysnapshot:
container_name: removeweeklysnapshot
image: removeweeklysnapshot
volumes:
- ~/removeweeklysnapshot/logs:/app/removeweeklysnapshot/logs
- ~/removeweeklysnapshot/output:/app/removeweeklysnapshot/output
- ~/removeweeklysnapshot/config/config.yaml:/app/removeweeklysnapshot/config/config.yaml
restart: always
stdin_open: true
tty: true
EOF
进入容器测试
手动执行 main.py 运行
[junlan@localhost removeweeklysnapshot]$ sudo docker exec -it removeweeklysnapshot bash
root@63869672d333:/app/removeweeklyshapshot# python main.py
2026-02-21 15:42:56,070 - INFO - ✅ 成功加载配置,共 2 个管理节点
2026-02-21 15:42:56,556 - INFO - 定时任务已设置:每周六凌晨4点导出文件,晚上7点删除快照
2026-02-21 15:43:00,000 - INFO - 🔍 开始收集VM和快照信息...
2026-02-21 15:43:00,054 - INFO - 成功连接到节点: 192.168.40.133
2026-02-21 15:43:03,319 - ERROR - 处理节点 192.168.40.135 失败:[Errno 113] No route to host
2026-02-21 15:43:03,319 - INFO - 获取到 2 台虚拟机
2026-02-21 15:43:03,319 - INFO - 📝 开始导出Excel报表...
2026-02-21 15:43:03,322 - INFO - 总共有 3 个快照
2026-02-21 15:43:03,340 - DEBUG - Excel 文件已生成: /removeweeklysnapshot/output/vm_snapshots_report.xlsx
2026-02-21 15:43:03,340 - INFO - 📝 开始导出 Yaml 文件...
2026-02-21 15:43:03,340 - INFO - 可删除的快照有 3 个
2026-02-21 15:43:03,342 - DEBUG - YAML 文件已生成: /removeweeklysnapshot/output/old_snapshots.yaml
2026-02-21 15:43:03,342 - INFO - ========== Excel和Yaml文件导出完成 ==========
2026-02-21 15:44:00,001 - INFO - 🗑️ 开始删除过旧快照...
2026-02-21 15:44:00,004 - INFO - 连接 192.168.40.133 进行删除快照...
2026-02-21 15:44:00,050 - INFO - 成功连接到节点: 192.168.40.133
2026-02-21 15:44:00,081 - INFO - 正在删除 Snapshot: VMware vCenter Server Appliance-快照测试-(1-snapshot-7)
2026-02-21 15:44:01,100 - INFO - ✅ 删除成功: VMware vCenter Server Appliance-快照测试-(1-snapshot-7)
2026-02-21 15:44:01,125 - INFO - 正在删除 Snapshot: VMware vCenter Server Appliance-快照测试-第二层快照-(1-snapshot-8)
2026-02-21 15:44:02,139 - INFO - ✅ 删除成功: VMware vCenter Server Appliance-快照测试-第二层快照-(1-snapshot-8)
2026-02-21 15:44:02,164 - INFO - 正在删除 Snapshot: test-vm-01-snap-01-(4-snapshot-9)
2026-02-21 15:44:03,178 - INFO - ✅ 删除成功: test-vm-01-snap-01-(4-snapshot-9)
2026-02-21 15:44:03,184 - INFO - ========== VM快照清理任务执行完成 ==========