接近完善的代码,待生产环境测试。
This commit is contained in:
509
README.md
509
README.md
@@ -9,24 +9,13 @@ Vmware 虚拟机自动化程序:自动化导出虚拟机和快照信息,自
|
|||||||
- [x] 获取所有 snapshots
|
- [x] 获取所有 snapshots
|
||||||
- [x] 筛选出15天(半个月)前的 snapshots
|
- [x] 筛选出15天(半个月)前的 snapshots
|
||||||
- [x] 以上内容以 Excel 表格的形式导出,超出 15 天的快照蓝色底填充标识
|
- [x] 以上内容以 Excel 表格的形式导出,超出 15 天的快照蓝色底填充标识
|
||||||
|
- [x] 最后删除 15 天前的 snapshot,并同时记录删除的 snapshot 日志信息
|
||||||
|
- [x] 设置计划任务,每周六(或 每15 天)执行一次
|
||||||
- [ ] 增加排除不能删除的 snapshots 信息,用红色底填充标识
|
- [ ] 增加排除不能删除的 snapshots 信息,用红色底填充标识
|
||||||
- [ ] Outlook 邮箱发送统计超过 15 天的 snapshots 信息(即要删除的快照列表)
|
- [ ] Outlook 邮箱发送统计超过 15 天的 snapshots 信息(即要删除的快照列表)
|
||||||
- [ ] 需要控制每台 vCenter 不可以同时删除超过 4 个快照(需要同时获取删除成功的信息)
|
- [ ] 需要控制每台 vCenter 不可以同时删除超过 4 个快照
|
||||||
- [x] 最后删除 15 天前的 snapshot,并同时记录删除的 snapshot 日志信息
|
- [ ] 删除前后发送邮件通知
|
||||||
- [ ] 删除成功后发送邮件通知
|
- [ ] 多线程删除
|
||||||
- [ ] 设置计划任务,每 2 周(半个月)执行一次
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
✅ 多线程删除
|
|
||||||
|
|
||||||
✅ 任务进度显示
|
|
||||||
|
|
||||||
✅ 自动重试机制
|
|
||||||
|
|
||||||
✅ 企业级日志
|
|
||||||
|
|
||||||
✅ 删除前后发送邮件通知
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -138,153 +127,153 @@ print(vm.summary)
|
|||||||
```
|
```
|
||||||
|
|
||||||
> (vim.vm.Summary) {
|
> (vim.vm.Summary) {
|
||||||
|
> dynamicType = <unset>,
|
||||||
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
|
> vm = 'vim.VirtualMachine:1',
|
||||||
|
> runtime = (vim.vm.RuntimeInfo) {
|
||||||
> dynamicType = <unset>,
|
> dynamicType = <unset>,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> vm = 'vim.VirtualMachine:1',
|
> device = (vim.vm.DeviceRuntimeInfo) [
|
||||||
> runtime = (vim.vm.RuntimeInfo) {
|
> (vim.vm.DeviceRuntimeInfo) {
|
||||||
> dynamicType = <unset>,
|
> dynamicType = <unset>,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> device = (vim.vm.DeviceRuntimeInfo) [
|
> runtimeState = (vim.vm.DeviceRuntimeInfo.VirtualEthernetCardRuntimeState) {
|
||||||
> (vim.vm.DeviceRuntimeInfo) {
|
|
||||||
> dynamicType = <unset>,
|
> dynamicType = <unset>,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> runtimeState = (vim.vm.DeviceRuntimeInfo.VirtualEthernetCardRuntimeState) {
|
> vmDirectPathGen2Active = false,
|
||||||
> dynamicType = <unset>,
|
> vmDirectPathGen2InactiveReasonVm = (str) [
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> 'vmNptDisabledOrDisconnectedAdapter'
|
||||||
> vmDirectPathGen2Active = false,
|
> ],
|
||||||
> vmDirectPathGen2InactiveReasonVm = (str) [
|
> vmDirectPathGen2InactiveReasonOther = (str) [],
|
||||||
> 'vmNptDisabledOrDisconnectedAdapter'
|
> vmDirectPathGen2InactiveReasonExtended = <unset>,
|
||||||
> ],
|
> uptv2Active = <unset>,
|
||||||
> vmDirectPathGen2InactiveReasonOther = (str) [],
|
> uptv2InactiveReasonVm = (str) [],
|
||||||
> vmDirectPathGen2InactiveReasonExtended = <unset>,
|
> uptv2InactiveReasonOther = (str) [],
|
||||||
> uptv2Active = <unset>,
|
> reservationStatus = <unset>,
|
||||||
> uptv2InactiveReasonVm = (str) [],
|
> attachmentStatus = 'red',
|
||||||
> uptv2InactiveReasonOther = (str) [],
|
> featureRequirement = (vim.vm.FeatureRequirement) []
|
||||||
> reservationStatus = <unset>,
|
> },
|
||||||
> attachmentStatus = 'red',
|
> key = 4000
|
||||||
> featureRequirement = (vim.vm.FeatureRequirement) []
|
> }
|
||||||
> },
|
> ],
|
||||||
> key = 4000
|
> host = 'vim.HostSystem:ha-host',
|
||||||
> }
|
> connectionState = 'connected',
|
||||||
> ],
|
> powerState = 'poweredOff',
|
||||||
> host = 'vim.HostSystem:ha-host',
|
> vmFailoverInProgress = <unset>,
|
||||||
> connectionState = 'connected',
|
> faultToleranceState = 'notConfigured',
|
||||||
> powerState = 'poweredOff',
|
> dasVmProtection = <unset>,
|
||||||
> vmFailoverInProgress = <unset>,
|
> toolsInstallerMounted = false,
|
||||||
> faultToleranceState = 'notConfigured',
|
> suspendTime = <unset>,
|
||||||
> dasVmProtection = <unset>,
|
> bootTime = <unset>,
|
||||||
> toolsInstallerMounted = false,
|
> suspendInterval = 0,
|
||||||
> suspendTime = <unset>,
|
> question = <unset>,
|
||||||
> bootTime = <unset>,
|
> memoryOverhead = <unset>,
|
||||||
> suspendInterval = 0,
|
> maxCpuUsage = 5184,
|
||||||
> question = <unset>,
|
> maxMemoryUsage = 4096,
|
||||||
> memoryOverhead = <unset>,
|
> numMksConnections = 0,
|
||||||
> maxCpuUsage = 5184,
|
> recordReplayState = 'inactive',
|
||||||
> maxMemoryUsage = 4096,
|
> cleanPowerOff = false,
|
||||||
> numMksConnections = 0,
|
> needSecondaryReason = <unset>,
|
||||||
> recordReplayState = 'inactive',
|
> onlineStandby = false,
|
||||||
> cleanPowerOff = false,
|
> minRequiredEVCModeKey = <unset>,
|
||||||
> needSecondaryReason = <unset>,
|
> consolidationNeeded = false,
|
||||||
> onlineStandby = false,
|
> offlineFeatureRequirement = (vim.vm.FeatureRequirement) [
|
||||||
> minRequiredEVCModeKey = <unset>,
|
> (vim.vm.FeatureRequirement) {
|
||||||
> consolidationNeeded = false,
|
> dynamicType = <unset>,
|
||||||
> offlineFeatureRequirement = (vim.vm.FeatureRequirement) [
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> (vim.vm.FeatureRequirement) {
|
> key = 'cpuid.lm',
|
||||||
> dynamicType = <unset>,
|
> featureName = 'cpuid.lm',
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> value = 'Bool:Min:1'
|
||||||
> key = 'cpuid.lm',
|
> }
|
||||||
> featureName = 'cpuid.lm',
|
> ],
|
||||||
> value = 'Bool:Min:1'
|
> featureRequirement = (vim.vm.FeatureRequirement) [],
|
||||||
> }
|
> featureMask = (vim.host.FeatureMask) [],
|
||||||
> ],
|
> vFlashCacheAllocation = <unset>,
|
||||||
> featureRequirement = (vim.vm.FeatureRequirement) [],
|
> paused = false,
|
||||||
> featureMask = (vim.host.FeatureMask) [],
|
> snapshotInBackground = false,
|
||||||
> vFlashCacheAllocation = <unset>,
|
> quiescedForkParent = <unset>,
|
||||||
> paused = false,
|
> instantCloneFrozen = false,
|
||||||
> snapshotInBackground = false,
|
> cryptoState = <unset>,
|
||||||
> quiescedForkParent = <unset>,
|
> suspendedToMemory = <unset>,
|
||||||
> instantCloneFrozen = false,
|
> opNotificationTimeout = <unset>,
|
||||||
> cryptoState = <unset>,
|
> iommuActive = <unset>
|
||||||
> suspendedToMemory = <unset>,
|
> },
|
||||||
> opNotificationTimeout = <unset>,
|
> guest = (vim.vm.Summary.GuestSummary) {
|
||||||
> iommuActive = <unset>
|
> dynamicType = <unset>,
|
||||||
> },
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> guest = (vim.vm.Summary.GuestSummary) {
|
> guestId = <unset>,
|
||||||
> dynamicType = <unset>,
|
> guestFullName = <unset>,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> toolsStatus = 'toolsNotRunning',
|
||||||
> guestId = <unset>,
|
> toolsVersionStatus = 'guestToolsUnmanaged',
|
||||||
> guestFullName = <unset>,
|
> toolsVersionStatus2 = 'guestToolsUnmanaged',
|
||||||
> toolsStatus = 'toolsNotRunning',
|
> toolsRunningStatus = 'guestToolsNotRunning',
|
||||||
> toolsVersionStatus = 'guestToolsUnmanaged',
|
> hostName = <unset>,
|
||||||
> toolsVersionStatus2 = 'guestToolsUnmanaged',
|
> ipAddress = <unset>,
|
||||||
> toolsRunningStatus = 'guestToolsNotRunning',
|
> hwVersion = <unset>
|
||||||
> hostName = <unset>,
|
> },
|
||||||
> ipAddress = <unset>,
|
> config = (vim.vm.Summary.ConfigSummary) {
|
||||||
> hwVersion = <unset>
|
> dynamicType = <unset>,
|
||||||
> },
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> config = (vim.vm.Summary.ConfigSummary) {
|
> name = 'VMware vCenter Server Appliance',
|
||||||
> dynamicType = <unset>,
|
> template = false,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> vmPathName = '[datastore1] VMware vCenter Server Appliance/VMware vCenter Server Appliance.vmx',
|
||||||
> name = 'VMware vCenter Server Appliance',
|
> memorySizeMB = 4096,
|
||||||
> template = false,
|
> cpuReservation = 0,
|
||||||
> vmPathName = '[datastore1] VMware vCenter Server Appliance/VMware vCenter Server Appliance.vmx',
|
> memoryReservation = 0,
|
||||||
> memorySizeMB = 4096,
|
> numCpu = 2,
|
||||||
> cpuReservation = 0,
|
> numEthernetCards = 1,
|
||||||
> memoryReservation = 0,
|
> numVirtualDisks = 13,
|
||||||
> numCpu = 2,
|
> uuid = '564d7d77-f37f-64a7-47f2-a131a337c070',
|
||||||
> numEthernetCards = 1,
|
> instanceUuid = '529e8be2-58ca-617c-ad7e-7f66de667471',
|
||||||
> numVirtualDisks = 13,
|
> guestId = 'other3xLinux64Guest',
|
||||||
> uuid = '564d7d77-f37f-64a7-47f2-a131a337c070',
|
> guestFullName = 'Other 3.x Linux (64-bit)',
|
||||||
> instanceUuid = '529e8be2-58ca-617c-ad7e-7f66de667471',
|
> annotation = 'VMware vCenter Server Appliance',
|
||||||
> guestId = 'other3xLinux64Guest',
|
> product = <unset>,
|
||||||
> guestFullName = 'Other 3.x Linux (64-bit)',
|
> installBootRequired = <unset>,
|
||||||
> annotation = 'VMware vCenter Server Appliance',
|
> ftInfo = <unset>,
|
||||||
> product = <unset>,
|
> managedBy = <unset>,
|
||||||
> installBootRequired = <unset>,
|
> tpmPresent = false,
|
||||||
> ftInfo = <unset>,
|
> numVmiopBackings = 0,
|
||||||
> managedBy = <unset>,
|
> hwVersion = <unset>
|
||||||
> tpmPresent = false,
|
> },
|
||||||
> numVmiopBackings = 0,
|
> storage = (vim.vm.Summary.StorageSummary) {
|
||||||
> hwVersion = <unset>
|
> dynamicType = <unset>,
|
||||||
> },
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> storage = (vim.vm.Summary.StorageSummary) {
|
> committed = 37476296711,
|
||||||
> dynamicType = <unset>,
|
> uncommitted = 303123661815,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> unshared = 37476296711,
|
||||||
> committed = 37476296711,
|
> timestamp = 2026-02-19T09:11:27.701184Z
|
||||||
> uncommitted = 303123661815,
|
> },
|
||||||
> unshared = 37476296711,
|
> quickStats = (vim.vm.Summary.QuickStats) {
|
||||||
> timestamp = 2026-02-19T09:11:27.701184Z
|
> dynamicType = <unset>,
|
||||||
> },
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
> quickStats = (vim.vm.Summary.QuickStats) {
|
> overallCpuUsage = <unset>,
|
||||||
> dynamicType = <unset>,
|
> overallCpuDemand = <unset>,
|
||||||
> dynamicProperty = (vmodl.DynamicProperty) [],
|
> overallCpuReadiness = <unset>,
|
||||||
> overallCpuUsage = <unset>,
|
> guestMemoryUsage = <unset>,
|
||||||
> overallCpuDemand = <unset>,
|
> hostMemoryUsage = <unset>,
|
||||||
> overallCpuReadiness = <unset>,
|
> guestHeartbeatStatus = 'gray',
|
||||||
> guestMemoryUsage = <unset>,
|
> distributedCpuEntitlement = <unset>,
|
||||||
> hostMemoryUsage = <unset>,
|
> distributedMemoryEntitlement = <unset>,
|
||||||
> guestHeartbeatStatus = 'gray',
|
> staticCpuEntitlement = <unset>,
|
||||||
> distributedCpuEntitlement = <unset>,
|
> staticMemoryEntitlement = <unset>,
|
||||||
> distributedMemoryEntitlement = <unset>,
|
> grantedMemory = <unset>,
|
||||||
> staticCpuEntitlement = <unset>,
|
> privateMemory = <unset>,
|
||||||
> staticMemoryEntitlement = <unset>,
|
> sharedMemory = <unset>,
|
||||||
> grantedMemory = <unset>,
|
> swappedMemory = <unset>,
|
||||||
> privateMemory = <unset>,
|
> balloonedMemory = <unset>,
|
||||||
> sharedMemory = <unset>,
|
> consumedOverheadMemory = <unset>,
|
||||||
> swappedMemory = <unset>,
|
> ftLogBandwidth = <unset>,
|
||||||
> balloonedMemory = <unset>,
|
> ftSecondaryLatency = <unset>,
|
||||||
> consumedOverheadMemory = <unset>,
|
> ftLatencyStatus = <unset>,
|
||||||
> ftLogBandwidth = <unset>,
|
> compressedMemory = <unset>,
|
||||||
> ftSecondaryLatency = <unset>,
|
> uptimeSeconds = <unset>,
|
||||||
> ftLatencyStatus = <unset>,
|
> ssdSwappedMemory = <unset>,
|
||||||
> compressedMemory = <unset>,
|
> activeMemory = <unset>,
|
||||||
> uptimeSeconds = <unset>,
|
> memoryTierStats = (vim.vm.Summary.QuickStats.MemoryTierStats) []
|
||||||
> ssdSwappedMemory = <unset>,
|
> },
|
||||||
> activeMemory = <unset>,
|
> overallStatus = 'green',
|
||||||
> memoryTierStats = (vim.vm.Summary.QuickStats.MemoryTierStats) []
|
> customValue = (vim.CustomFieldsManager.Value) []
|
||||||
> },
|
|
||||||
> overallStatus = 'green',
|
|
||||||
> customValue = (vim.CustomFieldsManager.Value) []
|
|
||||||
> }
|
> }
|
||||||
|
|
||||||
|
|
||||||
@@ -297,126 +286,95 @@ print(vm.summary)
|
|||||||
print(vm.snapshot)
|
print(vm.snapshot)
|
||||||
```
|
```
|
||||||
|
|
||||||
``` json
|
>(vim.vm.SnapshotInfo) {
|
||||||
(vim.vm.SnapshotInfo) {
|
>dynamicType = <unset>,
|
||||||
dynamicType = <unset>,
|
>dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
dynamicProperty = (vmodl.DynamicProperty) [],
|
>currentSnapshot = 'vim.vm.Snapshot:1-snapshot-3',
|
||||||
currentSnapshot = 'vim.vm.Snapshot:1-snapshot-3',
|
>rootSnapshotList = (vim.vm.SnapshotTree) [
|
||||||
rootSnapshotList = (vim.vm.SnapshotTree) [
|
>(vim.vm.SnapshotTree) {
|
||||||
(vim.vm.SnapshotTree) {
|
> dynamicType = <unset>,
|
||||||
dynamicType = <unset>,
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
dynamicProperty = (vmodl.DynamicProperty) [],
|
> snapshot = 'vim.vm.Snapshot:1-snapshot-1',
|
||||||
snapshot = 'vim.vm.Snapshot:1-snapshot-1',
|
> vm = 'vim.VirtualMachine:1',
|
||||||
vm = 'vim.VirtualMachine:1',
|
> name = 'snap-01', # 第一层快照
|
||||||
name = 'snap-01', # 第一层快照
|
> description = 'Ansible snapshot',
|
||||||
description = 'Ansible snapshot',
|
> id = 1,
|
||||||
id = 1,
|
> createTime = 2026-02-17T03:26:08.834505Z,
|
||||||
createTime = 2026-02-17T03:26:08.834505Z,
|
> state = 'poweredOff',
|
||||||
state = 'poweredOff',
|
> quiesced = false,
|
||||||
quiesced = false,
|
> backupManifest = <unset>,
|
||||||
backupManifest = <unset>,
|
> childSnapshotList = (vim.vm.SnapshotTree) [
|
||||||
childSnapshotList = (vim.vm.SnapshotTree) [
|
> (vim.vm.SnapshotTree) {
|
||||||
(vim.vm.SnapshotTree) {
|
> dynamicType = <unset>,
|
||||||
dynamicType = <unset>,
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
dynamicProperty = (vmodl.DynamicProperty) [],
|
> snapshot = 'vim.vm.Snapshot:1-snapshot-2',
|
||||||
snapshot = 'vim.vm.Snapshot:1-snapshot-2',
|
> vm = 'vim.VirtualMachine:1',
|
||||||
vm = 'vim.VirtualMachine:1',
|
> name = 'snap-02', # 第二层快照
|
||||||
name = 'snap-02', # 第二层快照
|
> description = 'test-Ansible snapshot',
|
||||||
description = 'test-Ansible snapshot',
|
> id = 2,
|
||||||
id = 2,
|
> createTime = 2026-02-17T08:57:39.122511Z,
|
||||||
createTime = 2026-02-17T08:57:39.122511Z,
|
> state = 'poweredOff',
|
||||||
state = 'poweredOff',
|
> quiesced = false,
|
||||||
quiesced = false,
|
> backupManifest = <unset>,
|
||||||
backupManifest = <unset>,
|
> childSnapshotList = (vim.vm.SnapshotTree) [
|
||||||
childSnapshotList = (vim.vm.SnapshotTree) [
|
> (vim.vm.SnapshotTree) {
|
||||||
(vim.vm.SnapshotTree) {
|
> dynamicType = <unset>,
|
||||||
dynamicType = <unset>,
|
> dynamicProperty = (vmodl.DynamicProperty) [],
|
||||||
dynamicProperty = (vmodl.DynamicProperty) [],
|
> snapshot = 'vim.vm.Snapshot:1-snapshot-3',
|
||||||
snapshot = 'vim.vm.Snapshot:1-snapshot-3',
|
> vm = 'vim.VirtualMachine:1',
|
||||||
vm = 'vim.VirtualMachine:1',
|
> name = '虚拟机快照 2026%252f2%252f19 12:28:36', # 第二层快照
|
||||||
name = '虚拟机快照 2026%252f2%252f19 12:28:36', # 第二层快照
|
> description = '',
|
||||||
description = '',
|
> id = 3,
|
||||||
id = 3,
|
> createTime = 2026-02-19T04:28:38.007703Z,
|
||||||
createTime = 2026-02-19T04:28:38.007703Z,
|
> state = 'poweredOn',
|
||||||
state = 'poweredOn',
|
> quiesced = false,
|
||||||
quiesced = false,
|
> backupManifest = <unset>,
|
||||||
backupManifest = <unset>,
|
> childSnapshotList = (vim.vm.SnapshotTree) [],
|
||||||
childSnapshotList = (vim.vm.SnapshotTree) [],
|
> replaySupported = false
|
||||||
replaySupported = false
|
> }
|
||||||
}
|
> ],
|
||||||
],
|
> replaySupported = false
|
||||||
replaySupported = false
|
> }
|
||||||
}
|
> ],
|
||||||
],
|
> replaySupported = false
|
||||||
replaySupported = false
|
>}
|
||||||
}
|
>]
|
||||||
]
|
>}
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 打印快照树
|
## PY 文件作用
|
||||||
|
|
||||||
``` python
|
|
||||||
def print_snapshot_tree(snapshot_info, level=0):
|
|
||||||
"""递归打印快照树(辅助函数)"""
|
|
||||||
indent = " " * level
|
|
||||||
print(f"{indent}├─ {snapshot_info['name']}")
|
|
||||||
print(f"{indent}│ ├─ 创建时间: {snapshot_info['createTime']}")
|
|
||||||
print(f"{indent}│ ├─ 描述: {snapshot_info['description']}")
|
|
||||||
print(f"{indent}│ ├─ 状态: {snapshot_info['state']}")
|
|
||||||
if snapshot_info['sizeMB']:
|
|
||||||
print(f"{indent}│ ├─ 大小: {snapshot_info['sizeMB']} MB")
|
|
||||||
|
|
||||||
for child in snapshot_info['children']:
|
|
||||||
print_snapshot_tree(child, level + 1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
vms = get_all_vms()
|
|
||||||
|
|
||||||
# 打印示例:显示每个VM的快照信息
|
|
||||||
for vm in vms:
|
|
||||||
print(f"\nVM: {vm['name']}")
|
|
||||||
if vm['snapshots']:
|
|
||||||
print(f"快照数量: {len(vm['snapshots'])}")
|
|
||||||
for snapshot in vm['snapshots']:
|
|
||||||
print_snapshot_tree(snapshot)
|
|
||||||
else:
|
|
||||||
print("无快照")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## PY 文件作用描述
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
``` powershell
|
``` powershell
|
||||||
PS D:\PycharmProjects\RemoveWeeklyShapshot> tree /F
|
PS D:\PycharmProjects\RemoveWeeklySnapshot> tree /F
|
||||||
卷 Date 的文件夹 PATH 列表
|
卷 Date 的文件夹 PATH 列表
|
||||||
卷序列号为 0E45-0F72
|
卷序列号为 0E45-0F72
|
||||||
D:.
|
D:.
|
||||||
│ README.md # 项目描述
|
│ main.py
|
||||||
│
|
│ README.md
|
||||||
├─config # 项目程序配置文件
|
│ requirements.txt
|
||||||
│ │ config.yaml # 配置文件
|
│
|
||||||
│ │ settings.py # 配置加载和全局变量
|
├─config
|
||||||
│
|
│ │ config.yaml
|
||||||
├─core # 核心程序
|
│ │ settings.py
|
||||||
│ │ deleteSnapshots.py
|
│
|
||||||
│ │ getVmsSnapshots.py
|
├─core
|
||||||
│
|
│ │ data_exporter.py
|
||||||
├─logs # 日志文件
|
│ │ get_vm_snapshots.py
|
||||||
│ 20260220-RemoveWeeklyShapshot.log
|
│ │ remove_snapshots.py
|
||||||
│
|
│ │ vm_connector.py
|
||||||
├─output # 数据输出文件
|
│
|
||||||
│ 2026-02-20-old_snapshots.yaml
|
├─logs
|
||||||
│ 2026-02-20_20-36-45-VMsSnapShots_report.xlsx
|
│ 2026-02-21-vm_snapshot_cleanup.log
|
||||||
│
|
│
|
||||||
├─utils # 工具函数
|
├─output
|
||||||
│ │ logger.py # 日志配置
|
│ old_snapshots-2026-02-21.yaml
|
||||||
|
│ vm_snapshots_report-2026-02-21.xlsx
|
||||||
|
│
|
||||||
|
├─utils
|
||||||
|
│ │ logger.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -425,11 +383,11 @@ D:.
|
|||||||
|
|
||||||
``` powershell
|
``` powershell
|
||||||
PS D:\PycharmProjects\RemoveWeeklyShapshot> pip freeze > requirements.txt
|
PS D:\PycharmProjects\RemoveWeeklyShapshot> pip freeze > requirements.txt
|
||||||
|
APScheduler==3.11.2
|
||||||
openpyxl==3.2.0b1
|
openpyxl==3.2.0b1
|
||||||
pandas==3.0.1
|
pandas==3.0.1
|
||||||
pyvmomi==9.0.0.0
|
pyvmomi==9.0.0.0
|
||||||
PyYAML==6.0.3
|
PyYAML==6.0.3
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
@@ -438,12 +396,11 @@ pip install -r requirements.txt
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## **定时执行**(Linux crontab):
|
## 构建 Docker 镜像
|
||||||
|
|
||||||
```bash
|
|
||||||
# 每月1号凌晨2点执行
|
|
||||||
0 2 1 * * /usr/bin/python3 /var/RemoveWeeklyShapshot/main.py 2>&1
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user