Skip to content

Commit

Permalink
Merge pull request #3 from infrasonar/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
joente authored Sep 4, 2023
2 parents fcab4e5 + 217e988 commit bcb2210
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 377 deletions.
291 changes: 28 additions & 263 deletions lib/check/host_vms.py
Original file line number Diff line number Diff line change
@@ -1,183 +1,7 @@
import logging
import os
from libprobe.asset import Asset
from pyVmomi import vim # type: ignore
from ..utils import datetime_to_timestamp
from ..vmwarequery import vmwarequery, vmwarequery_perf


COLLECT_PERFORMANCE_METRICS = int(os.getenv('COLLECT_PERFORMANCE_METRICS', '1'))


def on_guest_info(obj):
# vim.vm.GuestInfo
return {
'appHeartbeatStatus': obj.appHeartbeatStatus, # str
'appState': obj.appState, # str/null
'guestFamily': obj.guestFamily, # str
'guestFullName': obj.guestFullName, # str
'guestId': obj.guestId, # str
'guestKernelCrashed': obj.guestKernelCrashed, # bool/null
'guestOperationsReady': obj.guestOperationsReady, # bool
'guestState': obj.guestState, # str
'guestStateChangeSupported': obj.guestStateChangeSupported, # bool
'hostName': obj.hostName, # str
'interactiveGuestOperationsReady':
obj.interactiveGuestOperationsReady, # bool
'ipAddress': obj.ipAddress, # str
'toolsInstallType': obj.toolsInstallType, # str/null
'toolsRunningStatus': obj.toolsRunningStatus, # str
'toolsStatus': obj.toolsStatus, # str
'toolsVersion': obj.toolsVersion, # str
'toolsVersionStatus': obj.toolsVersionStatus, # str
'toolsVersionStatus2': obj.toolsVersionStatus2, # str
}


def on_runtime_info(obj):
# vim.vm.RuntimeInfo
return {
'bootTime': datetime_to_timestamp(obj.bootTime), # int/null
'cleanPowerOff': obj.cleanPowerOff, # bool
'connectionState': obj.connectionState, # str
'consolidationNeeded': obj.consolidationNeeded, # str
'cryptoState': obj.cryptoState, # str/null
'faultToleranceState': obj.faultToleranceState, # str
'instantCloneFrozen': obj.instantCloneFrozen, # bool/null
'maxCpuUsage': obj.maxCpuUsage, # int/null
'maxMemoryUsage': obj.maxMemoryUsage, # int
'memoryOverhead': obj.memoryOverhead, # int
'minRequiredEVCModeKey': obj.minRequiredEVCModeKey, # str
'needSecondaryReason': obj.needSecondaryReason, # str/null
'numMksConnections': obj.numMksConnections, # int
'onlineStandby': obj.onlineStandby, # bool
'paused': obj.paused, # bool
'powerState': obj.powerState, # str
'quiescedForkParent': obj.quiescedForkParent, # bool/null
'recordReplayState': obj.recordReplayState, # str
'snapshotInBackground': obj.snapshotInBackground, # bool
'suspendInterval': obj.suspendInterval, # int
'suspendTime': datetime_to_timestamp(obj.suspendTime),
'toolsInstallerMounted': obj.toolsInstallerMounted, # bool
'vFlashCacheAllocation': obj.vFlashCacheAllocation, # int
}


def on_virtual_hardware(obj):
# vim.vm.VirtualHardware
return {
'memoryMB': obj.memoryMB,
'numCPU': obj.numCPU,
'numCoresPerSocket': obj.numCoresPerSocket,
'virtualICH7MPresent': obj.virtualICH7MPresent,
'virtualSMCPresent': obj.virtualSMCPresent,
}


def on_config_info(obj):
# vim.vm.ConfigInfo
return {
**on_virtual_hardware(obj.hardware),
'alternateGuestName': obj.alternateGuestName, # str
'annotation': obj.annotation, # str
'changeTrackingEnabled': obj.changeTrackingEnabled, # bool
'changeVersion': obj.changeVersion, # str
'createDate': datetime_to_timestamp(obj.createDate), # int/null
'cpuHotAddEnabled': obj.cpuHotAddEnabled, # bool
'cpuHotRemoveEnabled': obj.cpuHotRemoveEnabled, # bool
'firmware': obj.firmware, # str
'guestAutoLockEnabled': obj.guestAutoLockEnabled, # bool
'guestFullNameConfig': obj.guestFullName, # str
'guestIdConfig': obj.guestId, # str
'hotPlugMemoryIncrementSize': obj.hotPlugMemoryIncrementSize, # str
'hotPlugMemoryLimit': obj.hotPlugMemoryLimit, # str
'instanceUuid': obj.instanceUuid, # str
'locationId': obj.locationId, # str
'maxMksConnections': obj.maxMksConnections, # int
'memoryHotAddEnabled': obj.memoryHotAddEnabled, # bool
'memoryReservationLockedToMax':
obj.memoryReservationLockedToMax, # bool
'messageBusTunnelEnabled': obj.messageBusTunnelEnabled, # bool
'migrateEncryption': obj.migrateEncryption, # str
'modified': datetime_to_timestamp(obj.modified),
# 'name': obj.name, # str
'nestedHVEnabled': obj.nestedHVEnabled, # bool
'npivDesiredNodeWwns': obj.npivDesiredNodeWwns, # int/null
'npivDesiredPortWwns': obj.npivDesiredPortWwns, # int/null
'migrateEncryption': obj.migrateEncryption, # str
'npivOnNonRdmDisks': obj.npivOnNonRdmDisks, # bool
'npivTemporaryDisabled': obj.npivTemporaryDisabled, # bool
'npivWorldWideNameType': obj.npivWorldWideNameType, # str
'swapPlacement': obj.swapPlacement, # str
'swapStorageObjectId': obj.swapStorageObjectId, # str
'template': obj.template, # bool
'uuid': obj.uuid, # str
'vAssertsEnabled': obj.vAssertsEnabled, # bool
'vFlashCacheReservation': obj.vFlashCacheReservation, # int
'vPMCEnabled': obj.vPMCEnabled, # bool
'version': obj.version, # str
'vmStorageObjectId': obj.vmStorageObjectId, # str
}


def on_virtual_disk_backing_info(obj):
# vim.vm.device.VirtualDisk.FlatVer2BackingInfo
return {
'changeId': obj.changeId, # str/null
'contentId': obj.contentId, # str/null
'deltaDiskFormat': obj.deltaDiskFormat, # str/null
'deltaDiskFormatVariant': obj.deltaDiskFormatVariant, # str/null
'deltaGrainSize': obj.deltaGrainSize, # int/null
'digestEnabled': obj.digestEnabled, # bool
'diskMode': obj.diskMode, # str
'eagerlyScrub': obj.eagerlyScrub, # bool/null
'fileName': obj.fileName, # str
'sharing': obj.sharing, # str
'split': obj.split, # bool
'thinProvisioned': obj.thinProvisioned, # bool
'uuid': obj.uuid, # str
'writeThrough': obj.writeThrough, # bool
}


def on_virtual_disk(obj):
# vim.vm.device.VirtualDisk
return {
**on_virtual_disk_backing_info(obj.backing),
'capacityInBytes': obj.capacityInBytes, # int
'diskObjectId': obj.diskObjectId, # str/null
'nativeUnmanagedLinkedClone':
obj.nativeUnmanagedLinkedClone, # bool/null
}


def on_snapshot_tree(obj):
# vim.vm.SnapshotTree
return {
'backupManifest': obj.backupManifest, # str
'createTime': datetime_to_timestamp(obj.createTime),
'description': obj.description, # str
'id': obj.id, # int
# 'name': obj.name, # str
'quiesced': obj.quiesced, # xsd:boolean
'replaySupported': obj.replaySupported, # xsd:boolean
'state': obj.state, # str
}


def snapshot_flat(snapshots, vm_name):
for snapshot in snapshots:
snapshot_dct = on_snapshot_tree(snapshot)
snapshot_dct['name'] = f'{vm_name}/{snapshot.id}'
snapshot_dct['snapshotName'] = snapshot.name
snapshot_dct['snapshotId'] = snapshot.id
snapshot_dct['vm'] = vm_name
yield snapshot_dct
for item in snapshot_flat(
snapshot.childSnapshotList, vm_name):
item['parentSnapshotName'] = snapshot.name
item['parentSnapshotId'] = snapshot.id
yield item
from ..vmwarequery import vmwarequery


async def check_host_vms(
Expand All @@ -190,48 +14,25 @@ async def check_host_vms(
asset_config,
check_config,
vim.Datastore,
['name', 'summary.capacity', 'info'],
)

hypervisors_ = await vmwarequery(
asset,
asset_config,
check_config,
vim.HostSystem,
['name'],
['name', 'summary.capacity'],
)

vms_ = await vmwarequery(
asset,
asset_config,
check_config,
vim.VirtualMachine,
['name', 'config', 'guest', 'snapshot', 'runtime'],
['name', 'config', 'guest', 'runtime'],
)

if COLLECT_PERFORMANCE_METRICS:
vms_perf = await vmwarequery_perf(
asset,
asset_config,
check_config,
vim.VirtualMachine,
[('cpu', 'ready'), ('disk', 'busResets')],
)
else:
vms_perf = {}

stores_lookup = {
store.obj: {p.name: p.val for p in store.propSet} for store in stores_}
hypervisors_lookup = {
hyp.obj: {p.name: p.val for p in hyp.propSet} for hyp in hypervisors_}
vms_retrieved = {
vm.obj: {p.name: p.val for p in vm.propSet} for vm in vms_}

guests = []
virtual_disks = []
snapshots = []
virtual_storage_capacities = {}

running_guest_count = 0
virtual_storage_dct = {}
for moref, vm in vms_retrieved.items():
if 'config' not in vm:
logging.info(
Expand All @@ -241,76 +42,40 @@ async def check_host_vms(
if vm['config'].template:
continue

# CHECK HOST VMS
info_dct = on_guest_info(vm['guest'])
info_dct.update(on_config_info(vm['config']))
info_dct.update(on_runtime_info(vm['runtime']))
info_dct['name'] = instanceuuid = vm['config'].instanceUuid
info_dct['instanceName'] = vm['name']

# aggregate performance metrics per guest
perf = vms_perf.get(instanceuuid)
if perf is not None:
path = ('cpu', 'ready')
total_name = ''
values = perf[path].get(total_name)
if values:
info_dct['cpuReadiness'] = max(values) / 20_000 * 100
# number of disk bus reset commands by the virtual machine
path = ('disk', 'busResets')
info_dct['busResets'] = sum(
sum(values)
for values in perf[path].values()
)
guests.append({
'name': vm['config'].instanceUuid,
'instanceName': vm['name'],
'powerState': vm['runtime'].powerState,
'currentHypervisor':
# vm.runtime.host is empty when vm is off
vm['runtime'].host and vm['runtime'].host.name,
})

hyp = hypervisors_lookup.get(vm['runtime'].host)
if hyp:
info_dct['currentHypervisor'] = hyp['name']
guests.append(info_dct)

# SNAPSHOTS
if 'snapshot' in vm:
snapshots.extend(
snapshot_flat(
vm['snapshot'].rootSnapshotList, vm['name']))
if vm['guest'].guestState == 'running':
running_guest_count += 1

for device in vm['config'].hardware.device:
if (device.key >= 2000) and (device.key < 3000):
# DISKS
disk_dct = on_virtual_disk(device)
disk_dct['name'] = device.backing.fileName

if isinstance(device, vim.vm.device.VirtualDisk):
datastore_name = device.backing.datastore.name
datastore = stores_lookup[device.backing.datastore]
datastore_name = datastore['name']
disk_dct['datastore'] = datastore['name']
if hasattr(device, 'deviceInfo') and device.deviceInfo:
disk_dct['label'] = device.deviceInfo.label
if disk_dct['capacityInBytes'] and \
disk_dct['datastore']:
if datastore_name not in \
virtual_storage_capacities:
virtual_storage_capacities[datastore_name] = {
'virtualCapacity': 0,
'name': datastore_name,
'actualCapacity': datastore[
'summary.capacity']}
virtual_storage_capacities[datastore_name][
'virtualCapacity'] += disk_dct[
'capacityInBytes']
virtual_disks.append(disk_dct)
if datastore_name not in virtual_storage_dct:
virtual_storage_dct[datastore_name] = {
'name': datastore_name,
'actualCapacity': datastore['summary.capacity'],
'virtualCapacity': 0
}
virtual_storage_dct[datastore_name]['virtualCapacity'] += \
device.capacityInBytes

guest_count = [{
'name': 'guestCount',
'guestCount': len(guests),
'runningGuestCount': sum(
guest.get('guestState') == 'running'
for guest in guests)
'runningGuestCount': running_guest_count
}]
virtual_storage = list(virtual_storage_dct.values())

return {
'guests': guests,
'guestCount': guest_count,
'virtualDisks': virtual_disks,
'snapshots': snapshots,
'virtualStorage': list(virtual_storage_capacities.values())
'virtualStorage': virtual_storage,
}
2 changes: 1 addition & 1 deletion lib/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Version string. Examples:
# '3.0.0'
# '3.0.0-alpha1'
__version__ = '3.0.2-alpha2'
__version__ = '3.0.2-alpha4'
Loading

0 comments on commit bcb2210

Please sign in to comment.