From 55ecb254181bf9fc8d522702489a26cabfae1896 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Mon, 16 Mar 2026 17:00:45 +0100 Subject: [PATCH 1/3] Add vm-status command --- checkvsphere/vcmd/vmstatus.py | 133 ++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 checkvsphere/vcmd/vmstatus.py diff --git a/checkvsphere/vcmd/vmstatus.py b/checkvsphere/vcmd/vmstatus.py new file mode 100644 index 0000000..f97530f --- /dev/null +++ b/checkvsphere/vcmd/vmstatus.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2023 ConSol Consulting & Solutions Software GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +""" +check vms status +""" + +__cmd__ = "vm-status" + +import logging +from pyVmomi import vim +from monplugin import Check, Status +from ..tools import cli, service_instance +from ..tools.helper import ( + CheckArgument, + find_entity_views, + isbanned, + isallowed, +) + +check = None +args = None + + +def get_argparser(): + parser = cli.Parser() + + parser.add_optional_arguments(CheckArgument.BANNED("regex")) + parser.add_optional_arguments(CheckArgument.ALLOWED("regex")) + + return parser + + +def run(): + global check + global args + + parser = get_argparser() + args = parser.get_args() + + check = Check() + + args._si = service_instance.connect(args) + + esxi_hosts = find_entity_views( + args._si, + vim.HostSystem, + begin_entity=args._si.content.rootFolder, + properties=["name", "configManager.autoStartManager"], + ) + vms_autostart = { + vm_power_info.key._moId: vm_power_info.startAction + for esxi_host in esxi_hosts + for vm_power_info in esxi_host["props"][ + "configManager.autoStartManager" + ].config.powerInfo + } + vms = find_entity_views( + args._si, + vim.VirtualMachine, + begin_entity=args._si.content.rootFolder, + properties=["name", "runtime.powerState"], + ) + + for vm in vms: + name = vm["props"]["name"] + vm_id = vm["obj"].obj._moId + isTemplate = vm["props"].get("config.template", None) + autoStart = vms_autostart.get(vm_id, None) == "powerOn" + powerState = vm["props"].get("runtime.powerState", None) + logging.debug( + "VM %s (#%s) is %s (autoStart=%s)", name, vm_id, powerState, autoStart + ) + + if isTemplate: + logging.debug(f"{name} is a template vm, ignoring ...") + continue + + if isbanned(args, name): + logging.debug(("banned", name)) + continue + + if not isallowed(args, name): + logging.debug(("not allowed", name)) + continue + + if powerState == "poweredOff" and autoStart: + check.add_message(Status.CRITICAL, f"{name} is powered off") + elif powerState == "poweredOff" and not autoStart: + check.add_message(Status.OK, f"{name} is powered off (auto-start disabled)") + elif powerState == "suspended": + check.add_message(Status.WARNING, f"{name} is suspended") + elif powerState == "poweredOn": + check.add_message(Status.OK, f"{name} is running") + else: + check.add_message( + Status.UNKNOWN, + f"{name} status is unknown ({powerState}, " + f"autoStart: {'enabled' if autoStart else 'disabled'})" + ) + + (code, message) = check.check_messages(separator="\n", separator_all="\n") + check.exit( + code=code, + message="all auto-started VMs are running" if code == Status.OK else message, + ) + + +if __name__ == "__main__": + try: + run() + except SystemExit as e: + if e.code > 3 or e.code < 0: + print("UNKNOWN EXIT CODE") + raise SystemExit(Status.UNKNOWN) + except Exception as e: + print("UNKNOWN - " + str(e)) + raise SystemExit(Status.UNKNOWN) From 624ead5a18ae108049016fd037fd760862ccc4a8 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Thu, 25 Jun 2026 09:55:35 +0200 Subject: [PATCH 2/3] Fix fetching config.template about VMs --- checkvsphere/vcmd/vmstatus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkvsphere/vcmd/vmstatus.py b/checkvsphere/vcmd/vmstatus.py index f97530f..d4862b2 100644 --- a/checkvsphere/vcmd/vmstatus.py +++ b/checkvsphere/vcmd/vmstatus.py @@ -74,7 +74,7 @@ def run(): args._si, vim.VirtualMachine, begin_entity=args._si.content.rootFolder, - properties=["name", "runtime.powerState"], + properties=["name", "config.template", "runtime.powerState"], ) for vm in vms: From 973a688ada1d494b83c8f4d5b1d65be6bff688cd Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Thu, 25 Jun 2026 09:57:37 +0200 Subject: [PATCH 3/3] Raise WARNING message instead of UNKNOWN message on VM unknown power state --- checkvsphere/vcmd/vmstatus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkvsphere/vcmd/vmstatus.py b/checkvsphere/vcmd/vmstatus.py index d4862b2..b3134e2 100644 --- a/checkvsphere/vcmd/vmstatus.py +++ b/checkvsphere/vcmd/vmstatus.py @@ -109,7 +109,7 @@ def run(): check.add_message(Status.OK, f"{name} is running") else: check.add_message( - Status.UNKNOWN, + Status.WARNING, f"{name} status is unknown ({powerState}, " f"autoStart: {'enabled' if autoStart else 'disabled'})" )