Files
RemoveWeeklyShapshot/README.md
2026-02-19 23:23:51 +08:00

383 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RemoveWeeklySnapshot
> 以下需求需要每周执行一次
- [x] 连接vCenter/Esxi/Hyper-V
- [x] 获取所有 vms
- [x] 获取所有 snapshots
- [x] 筛选出15天半个月前的 snapshots
- [x] 以上内容以 Excel 表格的形式导出,超出 15 天的快照填充蓝色底标识
- [ ] Outlook 邮箱发送超出 15 天的快照
- [ ] 增加排除不能删除的快照
- [ ] 需要控制每台 vCenter 不可以同时删除超过 4 个快照
- [ ] 最后删除 15 天前的 snapshot并同时记录删除的 snapshot 日志信息
| 你想获取 | 代码 | 示例输出 |
| ------------ | ----------------------------------- | ---------------------------------------------- |
| **名称** | `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.config.createDate # 虚拟机的创建时间
vm.runtime.bootTime # 虚拟机上次启动的时间
```
>以下这些方法和属性主要用于操作虚拟机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 实时性能数据
>
>1. **AcquireMksTicket / AcquireTicket**:获取访问虚拟机控制台的票据,允许用户通过 Web 界面访问 VM。
>2. **Clone / CloneVM_Task**:克隆一个虚拟机,创建其副本。
>3. **CreateSnapshot / CreateSnapshot_Task**:创建虚拟机快照,以保存当前 VM 的状态。
>4. **Destroy / Destroy_Task**:删除虚拟机及其所有数据。
>5. **PowerOn / PowerOnVM_Task**:启动虚拟机。
>6. **PowerOff / PowerOffVM_Task**:关闭虚拟机。
>7. **Reset / ResetVM_Task**:重置虚拟机,相当于按下重启按钮。
>8. **RevertToCurrentSnapshot / RevertToCurrentSnapshot_Task**:将虚拟机恢复到当前快照的状态。
>9. **Migrate / MigrateVM_Task**:迁移虚拟机到不同的主机或数据存储。
>10. **SetCustomValue**:设置自定义属性值,以便在虚拟机上存储额外信息。
>
>### 属性列表
>
>这些属性通常包含关于虚拟机或其他资源的状态和配置信息。以下是一些关键属性的说明:
>
>1. **name**:虚拟机的名称。
>2. **guest**:关于虚拟机操作系统的信息,如操作系统类型、版本等。
>3. **config**:虚拟机的配置详情,例如 CPU、内存、硬盘等。
>4. **runtime**:虚拟机的运行时状态,包括电源状态(开机、关机、挂起等)。
>5. **snapshot**:当前虚拟机的快照信息。
>6. **summary**:虚拟机的概述信息,包括状态、资源使用情况等。
>7. **resourcePool**:虚拟机所在的资源池。
>8. **datastore**:虚拟机的存储位置,指向其使用的存储库。
>9. **overallStatus**:虚拟机的总体状态,可能是正常、警告、错误等。
>10. **recentTask**:最近执行的任务列表。
>
>### 其他属性
>
>- **capability**:虚拟机支持的功能,如支持的虚拟硬件版本。
>- **declaredAlarmState**:声明的警报状态,用于监控虚拟机的健康状况。
>- **triggeredAlarmState**:触发的警报状态,显示当前激活的警报。
```python
for vm in vm_view.view:
print(dir(vm)) # 输出所有可用的属性和方法
# print(vm.summary)
# print(vm.snapshot)
# print(vars(vm.summary))
```
``` json
['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地址等。
```python
print(vm.summary)
```
> (vim.vm.Summary) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> vm = 'vim.VirtualMachine:1',
> runtime = (vim.vm.RuntimeInfo) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> device = (vim.vm.DeviceRuntimeInfo) [
> (vim.vm.DeviceRuntimeInfo) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> runtimeState = (vim.vm.DeviceRuntimeInfo.VirtualEthernetCardRuntimeState) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> vmDirectPathGen2Active = false,
> vmDirectPathGen2InactiveReasonVm = (str) [
> 'vmNptDisabledOrDisconnectedAdapter'
> ],
> vmDirectPathGen2InactiveReasonOther = (str) [],
> vmDirectPathGen2InactiveReasonExtended = <unset>,
> uptv2Active = <unset>,
> uptv2InactiveReasonVm = (str) [],
> uptv2InactiveReasonOther = (str) [],
> reservationStatus = <unset>,
> attachmentStatus = 'red',
> featureRequirement = (vim.vm.FeatureRequirement) []
> },
> key = 4000
> }
> ],
> host = 'vim.HostSystem:ha-host',
> connectionState = 'connected',
> powerState = 'poweredOff',
> vmFailoverInProgress = <unset>,
> faultToleranceState = 'notConfigured',
> dasVmProtection = <unset>,
> toolsInstallerMounted = false,
> suspendTime = <unset>,
> bootTime = <unset>,
> suspendInterval = 0,
> question = <unset>,
> memoryOverhead = <unset>,
> maxCpuUsage = 5184,
> maxMemoryUsage = 4096,
> numMksConnections = 0,
> recordReplayState = 'inactive',
> cleanPowerOff = false,
> needSecondaryReason = <unset>,
> onlineStandby = false,
> minRequiredEVCModeKey = <unset>,
> consolidationNeeded = false,
> offlineFeatureRequirement = (vim.vm.FeatureRequirement) [
> (vim.vm.FeatureRequirement) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> key = 'cpuid.lm',
> featureName = 'cpuid.lm',
> value = 'Bool:Min:1'
> }
> ],
> featureRequirement = (vim.vm.FeatureRequirement) [],
> featureMask = (vim.host.FeatureMask) [],
> vFlashCacheAllocation = <unset>,
> paused = false,
> snapshotInBackground = false,
> quiescedForkParent = <unset>,
> instantCloneFrozen = false,
> cryptoState = <unset>,
> suspendedToMemory = <unset>,
> opNotificationTimeout = <unset>,
> iommuActive = <unset>
> },
> guest = (vim.vm.Summary.GuestSummary) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> guestId = <unset>,
> guestFullName = <unset>,
> toolsStatus = 'toolsNotRunning',
> toolsVersionStatus = 'guestToolsUnmanaged',
> toolsVersionStatus2 = 'guestToolsUnmanaged',
> toolsRunningStatus = 'guestToolsNotRunning',
> hostName = <unset>,
> ipAddress = <unset>,
> hwVersion = <unset>
> },
> config = (vim.vm.Summary.ConfigSummary) {
> dynamicType = <unset>,
> 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 = <unset>,
> installBootRequired = <unset>,
> ftInfo = <unset>,
> managedBy = <unset>,
> tpmPresent = false,
> numVmiopBackings = 0,
> hwVersion = <unset>
> },
> storage = (vim.vm.Summary.StorageSummary) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> committed = 37476296711,
> uncommitted = 303123661815,
> unshared = 37476296711,
> timestamp = 2026-02-19T09:11:27.701184Z
> },
> quickStats = (vim.vm.Summary.QuickStats) {
> dynamicType = <unset>,
> dynamicProperty = (vmodl.DynamicProperty) [],
> overallCpuUsage = <unset>,
> overallCpuDemand = <unset>,
> overallCpuReadiness = <unset>,
> guestMemoryUsage = <unset>,
> hostMemoryUsage = <unset>,
> guestHeartbeatStatus = 'gray',
> distributedCpuEntitlement = <unset>,
> distributedMemoryEntitlement = <unset>,
> staticCpuEntitlement = <unset>,
> staticMemoryEntitlement = <unset>,
> grantedMemory = <unset>,
> privateMemory = <unset>,
> sharedMemory = <unset>,
> swappedMemory = <unset>,
> balloonedMemory = <unset>,
> consumedOverheadMemory = <unset>,
> ftLogBandwidth = <unset>,
> ftSecondaryLatency = <unset>,
> ftLatencyStatus = <unset>,
> compressedMemory = <unset>,
> uptimeSeconds = <unset>,
> ssdSwappedMemory = <unset>,
> activeMemory = <unset>,
> memoryTierStats = (vim.vm.Summary.QuickStats.MemoryTierStats) []
> },
> overallStatus = 'green',
> customValue = (vim.CustomFieldsManager.Value) []
> }
### 获取快照属性
输出快照所有信息
```python
print(vm.snapshot)
```
``` json
(vim.vm.SnapshotInfo) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
currentSnapshot = 'vim.vm.Snapshot:1-snapshot-3',
rootSnapshotList = (vim.vm.SnapshotTree) [
(vim.vm.SnapshotTree) {
dynamicType = <unset>,
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 = <unset>,
childSnapshotList = (vim.vm.SnapshotTree) [
(vim.vm.SnapshotTree) {
dynamicType = <unset>,
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 = <unset>,
childSnapshotList = (vim.vm.SnapshotTree) [
(vim.vm.SnapshotTree) {
dynamicType = <unset>,
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 = <unset>,
childSnapshotList = (vim.vm.SnapshotTree) [],
replaySupported = false
}
],
replaySupported = false
}
],
replaySupported = false
}
]
}
```
### 打印快照树
``` 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("无快照")
```