diff --git a/README.md b/README.md index 76338dba90754a28bb382a51c78e0192b17e172d..b5a342b31e48d2b4cad8ac2eebe262b2652a46da 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/mkp/vsphere_topo-0.0.5-20240717.mkp "vsphere_topo-0.0.5-20240717.mkp" +[PACKAGE]: ../../raw/master/mkp/vsphere_topo-0.0.6-20240729.mkp "vsphere_topo-0.0.6-20240729.mkp" # vSphere Topology Visualization This plugin uses the data from the _VMware ESX via vSphere_ special agent to create a topology of the vSphere environment.\ diff --git a/mkp/vsphere_topo-0.0.6-20240729.mkp b/mkp/vsphere_topo-0.0.6-20240729.mkp new file mode 100644 index 0000000000000000000000000000000000000000..04691eaa5f72279a5fdc38e49ce65eaecc02a435 Binary files /dev/null and b/mkp/vsphere_topo-0.0.6-20240729.mkp differ diff --git a/source/cmk_addons_plugins/vsphere_topo/agent_based/packages.py b/source/cmk_addons_plugins/vsphere_topo/agent_based/vsphere_topo.py similarity index 82% rename from source/cmk_addons_plugins/vsphere_topo/agent_based/packages.py rename to source/cmk_addons_plugins/vsphere_topo/agent_based/vsphere_topo.py index f03291ece65591596d2a031be484a4ce31d0c034..791db5fc7b4521b98208ea6fee50b2dbb39b5cb1 100644 --- a/source/cmk_addons_plugins/vsphere_topo/agent_based/packages.py +++ b/source/cmk_addons_plugins/vsphere_topo/agent_based/vsphere_topo.py @@ -18,10 +18,15 @@ # 2024-07-13: refactoring save topology/make default and add dummy's logic # 2024-07-16: moved add_host/add_service/add_connection to lib/utils/TopoObjects/TopoConnections # moved ruleset name constants to utils/ruleset_names.py +# 2024-07-25: fixed crash if VM has no data store +# 2024-07-29: added option to ignore powered off VMs +# added option to ignore VMs by name (regex) from collections.abc import Mapping, Sequence +from re import compile as re_compile from time import time_ns + from cmk.agent_based.v2 import ( CheckPlugin, CheckResult, @@ -43,6 +48,8 @@ from cmk_addons.plugins.vsphere_topo.constants import ( PARAM_DATA_STORE, PARAM_DATA_STORE_AS_SERVICE, PARAM_HOST_SYSTEMS, + PARAM_IGNORE_POWERED_OFF_VMS, + PARAM_IGNORE_VM_NAME_REGEX, PARAM_MAKE_DEFAULT, PARAM_VCENTER, PARAM_VM_NAMES, @@ -79,8 +86,14 @@ def check_vsphere_topo( section_esx_vsphere_datastores: Section | None, ) -> CheckResult: start_time = time_ns() - objects = TopoObjects() - connections = TopoConnections() + objects: TopoObjects = TopoObjects() + connections: TopoConnections = TopoConnections() + ignored_powered_off_vms: int = 0 + ignored_by_name_vms: int = 0 + if ignore_by_name_str := ')|('.join(params.get(PARAM_IGNORE_VM_NAME_REGEX, [])): + re_ignore_vms = re_compile(f'({ignore_by_name_str})') + else: + re_ignore_vms = None if section_esx_vsphere_clusters is not None: __clusters = { @@ -161,10 +174,16 @@ def check_vsphere_topo( } ] for vm in section_esx_vsphere_virtual_machines: - vm_name: str = adjust_name(vm['vm_name'], params.get(PARAM_VM_NAMES, {})) - host_system: str = adjust_name(vm['hostsystem'], params.get(PARAM_HOST_SYSTEMS, {})) - objects.add_host(host=vm_name) - connections.add_connection(vm_name, host_system) + if params.get(PARAM_IGNORE_POWERED_OFF_VMS) is not True or vm.get('powerstate') != 'poweredOff': + vm_name: str = adjust_name(vm['vm_name'], params.get(PARAM_VM_NAMES, {})) + if re_ignore_vms is None or re_ignore_vms.match(vm_name) is None: + host_system: str = adjust_name(vm['hostsystem'], params.get(PARAM_HOST_SYSTEMS, {})) + objects.add_host(host=vm_name) + connections.add_connection(vm_name, host_system) + else: + ignored_by_name_vms += 1 + else: + ignored_powered_off_vms += 1 service_prefix: str = '' ds_services = None @@ -217,13 +236,17 @@ def check_vsphere_topo( if vm_name in objects.topo_objects: data_stores = data_stores.split(',') for data_store in data_stores: - ds_name = data_store.strip().split(' ')[2] - if ds_services is not None: - service_name = f'{service_prefix}{ds_name}' - service_id = f'{service_name}@{vsphere_host}' - connections.add_connection(service_id, vm_name) + try: + ds_name = data_store.strip().split(' ')[2] + except IndexError: + continue else: - connections.add_connection(ds_name, vm_name) + if ds_services is not None: + service_name = f'{service_prefix}{ds_name}' + service_id = f'{service_name}@{vsphere_host}' + connections.add_connection(service_id, vm_name) + else: + connections.add_connection(ds_name, vm_name) connections.topo_connections.sort() data_set = { @@ -241,6 +264,10 @@ def check_vsphere_topo( yield Result(state=State.OK, summary=f'Objects: {len(objects.topo_objects)}') yield Result(state=State.OK, summary=f'Connections: {len(connections.topo_connections)}') + if params.get(PARAM_IGNORE_POWERED_OFF_VMS) is True: + yield Result(state=State.OK, summary=f'Ignored powered off VMs: {ignored_powered_off_vms}') + if re_ignore_vms is not None: + yield Result(state=State.OK, summary=f'Ignored VMs by name: {ignored_by_name_vms}') yield Result( state=State.OK, notice=f'Written to: {BASE_TOPO_PATH}/{raw_vsphere_host}/data_{TOPOLOGY_NAME.lower()}.json', diff --git a/source/cmk_addons_plugins/vsphere_topo/constants.py b/source/cmk_addons_plugins/vsphere_topo/constants.py index e58585f259bce4965acac724785e3c0a5a9d6d33..2036aeada4f97b35bb7f1933dde2e41758103e0d 100644 --- a/source/cmk_addons_plugins/vsphere_topo/constants.py +++ b/source/cmk_addons_plugins/vsphere_topo/constants.py @@ -16,7 +16,8 @@ EMBLEM_DATA_STORE: Final[str] = 'icon_services_green' ICON_VCENTER: Final[str] = 'icon_topic_hosts' -PARAM_ADD_DUMMY_TOPOLOGIES: Final[str] = 'add_dummy_topologies' +# PARAM_ADD_DUMMY_TOPOLOGIES: Final[str] = 'add_dummy_topologies' +# PARAM_DONT_ADD_VC_AS_VM: Final[str] = 'dont_add_vc_as_vm' PARAM_CHANGE_CASE: Final[str] = 'change_case' PARAM_CLUSTER: Final[str] = 'cluster' PARAM_CUSTOM_EMBLEM: Final[str] = 'custom_emblem' @@ -24,8 +25,9 @@ PARAM_DATA_CENTER: Final[str] = 'data_center' PARAM_DATA_STORE: Final[str] = 'data_store' PARAM_DATA_STORE_AS_SERVICE: Final[str] = 'data_sore_as_service' PARAM_DEFAULT_EMBLEM: Final[str] = 'default_emblem' -PARAM_DONT_ADD_VC_AS_VM: Final[str] = 'dont_add_vc_as_vm' PARAM_HOST_SYSTEMS: Final[str] = 'host_systems' +PARAM_IGNORE_POWERED_OFF_VMS: Final[str] = 'ignore_powered_off_vms' +PARAM_IGNORE_VM_NAME_REGEX: Final[str] = 'ignore_vms_by_name' PARAM_KEEP_DOMAIN: Final[str] = 'keep_domain' PARAM_LOWER: Final[str] = 'lower' PARAM_MAKE_DEFAULT: Final[str] = 'make_default' diff --git a/source/cmk_addons_plugins/vsphere_topo/graphing/packages.py b/source/cmk_addons_plugins/vsphere_topo/graphing/vsphere_topo.py similarity index 100% rename from source/cmk_addons_plugins/vsphere_topo/graphing/packages.py rename to source/cmk_addons_plugins/vsphere_topo/graphing/vsphere_topo.py diff --git a/source/cmk_addons_plugins/vsphere_topo/rulesets/packages.py b/source/cmk_addons_plugins/vsphere_topo/rulesets/vsphere_topo.py similarity index 76% rename from source/cmk_addons_plugins/vsphere_topo/rulesets/packages.py rename to source/cmk_addons_plugins/vsphere_topo/rulesets/vsphere_topo.py index e541adba74fcf20b36266d4a25806e3df88ea197..4ce336730ac249e685c1fc744a6d2d2221687fa5 100644 --- a/source/cmk_addons_plugins/vsphere_topo/rulesets/packages.py +++ b/source/cmk_addons_plugins/vsphere_topo/rulesets/vsphere_topo.py @@ -8,6 +8,8 @@ # Date : 2024-07-06 # File : vsphere_topo/rulesets/packages.py +# removed PARAM_ADD_DUMMY_TOPOLOGIES and PARAM_DONT_ADD_VC_AS_VM + from collections.abc import Mapping, Sequence from cmk.rulesets.v1 import Help, Label, Title @@ -21,15 +23,17 @@ from cmk.rulesets.v1.form_specs import ( SingleChoice, SingleChoiceElement, String, + List, ) from cmk.rulesets.v1.form_specs.validators import LengthInRange from cmk.rulesets.v1.rule_specs import CheckParameters, HostCondition, Topic from cmk_addons.plugins.vsphere_topo.constants import ( + # PARAM_ADD_DUMMY_TOPOLOGIES, + # PARAM_DONT_ADD_VC_AS_VM, EMBLEM_CLUSTER, EMBLEM_DATA_CENTER, EMBLEM_DATA_STORE, ICON_VCENTER, - PARAM_ADD_DUMMY_TOPOLOGIES, PARAM_CHANGE_CASE, PARAM_CLUSTER, PARAM_CUSTOM_EMBLEM, @@ -37,8 +41,9 @@ from cmk_addons.plugins.vsphere_topo.constants import ( PARAM_DATA_STORE, PARAM_DATA_STORE_AS_SERVICE, PARAM_DEFAULT_EMBLEM, - PARAM_DONT_ADD_VC_AS_VM, PARAM_HOST_SYSTEMS, + PARAM_IGNORE_POWERED_OFF_VMS, + PARAM_IGNORE_VM_NAME_REGEX, PARAM_KEEP_DOMAIN, PARAM_LOWER, PARAM_MAKE_DEFAULT, @@ -177,28 +182,48 @@ def _parameter_form() -> Dictionary: ), value=True )), - PARAM_DONT_ADD_VC_AS_VM: DictElement( - render_only=True, + PARAM_IGNORE_POWERED_OFF_VMS: DictElement( parameter_form=FixedValue( - title=Title('Don\'t add vCenter as VM'), - label=Label('The vCenter will not be added as VM'), + title=Title('Ignore powered off VMs'), + label=Label('enabled'), help_text=Help( - 'Use this option if the vCenter is also a VM within the managed datacenter.' - 'This will create a clearer topology, but you lose the info where the vCenter is running.' + 'Powered off VMs will not be added to the topology' ), - value=True + value=True, )), - PARAM_ADD_DUMMY_TOPOLOGIES: DictElement( - render_only=True, - parameter_form=FixedValue( - title=Title('Add dummy topologies'), - label=Label('Adds empty CDP, LLDP, L3v4 and STATIC topology'), + PARAM_IGNORE_VM_NAME_REGEX: DictElement( + parameter_form=List( + title=Title('Ignore VMs by name (regex)'), + element_template=String( + title=Title('add regex string') + ), help_text=Help( - 'Use this option if you are also using the NVDCT. This is a workaround, as the backend ' - 'only picks up layers that are present in the default topology folder.' + 'The regex strings will be applied after the upper/lower case and prefix ' + 'change to the VM names. If there more than one regex string the will be "OR" connected.' ), - value=True )), + # PARAM_DONT_ADD_VC_AS_VM: DictElement( + # render_only=True, + # parameter_form=FixedValue( + # title=Title('Don\'t add vCenter as VM'), + # label=Label('The vCenter will not be added as VM'), + # help_text=Help( + # 'Use this option if the vCenter is also a VM within the managed datacenter.' + # 'This will create a clearer topology, but you lose the info where the vCenter is running.' + # ), + # value=True + # )), + # PARAM_ADD_DUMMY_TOPOLOGIES: DictElement( + # render_only=True, + # parameter_form=FixedValue( + # title=Title('Add dummy topologies'), + # label=Label('Adds empty CDP, LLDP, L3v4 and STATIC topology'), + # help_text=Help( + # 'Use this option if you are also using the NVDCT. This is a workaround, as the backend ' + # 'only picks up layers that are present in the default topology folder.' + # ), + # value=True + # )), } ) diff --git a/source/packages/vsphere_topo b/source/packages/vsphere_topo index 2215409ee4e4ec46a2ba7b29d63a08e126166653..8ec8c4e2fba6e6fd1052d67c5ad4960e8459baba 100644 --- a/source/packages/vsphere_topo +++ b/source/packages/vsphere_topo @@ -6,14 +6,14 @@ 'Topolgy is created by: vCenter -> data center(s) ' '->Cluster(s) -> ESX host(s) -> VM(s)\n', 'download_url': 'https://thl-cmk.hopto.org/gitlab/checkmk/various/vsphere_topo', - 'files': {'cmk_addons_plugins': ['vsphere_topo/agent_based/packages.py', - 'vsphere_topo/rulesets/packages.py', - 'vsphere_topo/lib/utils.py', - 'vsphere_topo/graphing/packages.py', - 'vsphere_topo/constants.py']}, + 'files': {'cmk_addons_plugins': ['vsphere_topo/lib/utils.py', + 'vsphere_topo/constants.py', + 'vsphere_topo/agent_based/vsphere_topo.py', + 'vsphere_topo/graphing/vsphere_topo.py', + 'vsphere_topo/rulesets/vsphere_topo.py']}, 'name': 'vsphere_topo', 'title': 'vSphere Topologie', - 'version': '0.0.5-20240717', + 'version': '0.0.6-20240729', 'version.min_required': '2.3.0b1', 'version.packaged': 'cmk-mkp-tool 0.2.0', 'version.usable_until': '2.4.0b1'}