From 185eb9df54426e1c83dd154110a671075d1a350e Mon Sep 17 00:00:00 2001 From: Florian Paul Azim Hoberg Date: Mon, 8 Jul 2024 17:22:09 +0200 Subject: [PATCH] feature(grouping): Add grouping feature to rebalance VMs together if defined. Fixes: #3 --- .../1.0.0/3_feature_add_vm_grouping.yaml | 2 ++ .changelogs/1.0.0/release_meta.yml | 1 + README.md | 18 ++++++++++- docs/03_FAQ.md | 15 +++++++++ proxlb | 31 ++++++++++++++++++- 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 .changelogs/1.0.0/3_feature_add_vm_grouping.yaml create mode 100644 .changelogs/1.0.0/release_meta.yml diff --git a/.changelogs/1.0.0/3_feature_add_vm_grouping.yaml b/.changelogs/1.0.0/3_feature_add_vm_grouping.yaml new file mode 100644 index 0000000..37a55f9 --- /dev/null +++ b/.changelogs/1.0.0/3_feature_add_vm_grouping.yaml @@ -0,0 +1,2 @@ +added: + - Add VM grouping feature to migrate vm workload groups together. [#3] diff --git a/.changelogs/1.0.0/release_meta.yml b/.changelogs/1.0.0/release_meta.yml new file mode 100644 index 0000000..c19765d --- /dev/null +++ b/.changelogs/1.0.0/release_meta.yml @@ -0,0 +1 @@ +date: TBD diff --git a/README.md b/README.md index b430f57..5802318 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ * Manuel * Proxmox GUI Integration * Quick Start + * VM Grouping * Motivation * References * Packages @@ -114,7 +115,7 @@ A manual installation is possible and also supports BSD based systems. Proxmox R The executable must be able to read the config file, if no dedicated config file is given by the `-c` argument, PLB tries to read it from `/etc/proxlb/proxlb.conf`. ### Proxmox GUI Integration - PLB can also be directly be used from the Proxmox Web UI by installing the optional package `pve-proxmoxlb-service-ui` package which has a dependency on the `proxlb` package. For the Web UI integration, it requires to be installed (in addition) on the nodes on the cluster. Afterwards, a new menu item is present in the HA chapter called `Rebalancing`. This chapter provides two possibilities: + PLB can also be directly be used from the Proxmox Web UI by installing the optional package `pve-proxlb-ui` package which has a dependency on the `proxlb` package. For the Web UI integration, it requires to be installed (in addition) on the nodes on the cluster. Afterwards, a new menu item is present in the HA chapter called `Rebalancing`. This chapter provides two possibilities: * Rebalancing VM workloads * Migrate VM workloads away from a defined node (e.g. maintenance preparation) @@ -130,6 +131,21 @@ systemctl restart proxlb systemctl status proxlb ``` +### VM Grouping + In the Proxmox WEB UI, you can group VMs using the notes field. While Proxmox doesn't natively support tagging or flagging VMs, you can utilize the VM's notes/description field for this purpose. You can still include any other notes and comments in the description field, but to enable grouping, you must add a new line starting with `proxlb-grouping:` followed by the group name. + +Example: +``` +This is a great VM +proxlb-grouping: db-gyptazy01-workload-group01 + +foo bar With some more text. +Important is only the proxlb-grouping line with a name and +we can still use this field. +``` + +The notes field is evaluated for each VM. All VMs with the same group name (e.g., `db-gyptazy01-workload-group01`) will be rebalanced together on the same host. + ### Logging ProxLB uses the `SystemdHandler` for logging. You can find all your logs in your systemd unit log or in the journalctl. diff --git a/docs/03_FAQ.md b/docs/03_FAQ.md index f1af9d8..8875555 100644 --- a/docs/03_FAQ.md +++ b/docs/03_FAQ.md @@ -21,3 +21,18 @@ Jul 06 10:25:16 build01 proxlb[7285]: proxlb: Error: [python-imports]: Could no Debian/Ubuntu: apt-get install python3-proxmoxer If the package is not provided by your systems repository, you can also install it by running `pip3 install proxmoxer`. + +### VM Grouping + In the Proxmox WEB UI, you can group VMs using the notes field. While Proxmox doesn't natively support tagging or flagging VMs, you can utilize the VM's notes/description field for this purpose. You can still include any other notes and comments in the description field, but to enable grouping, you must add a new line starting with `proxlb-grouping:` followed by the group name. + +Example: +``` +This is a great VM +proxlb-grouping: db-gyptazy01-workload-group01 + +foo bar With some more text. +Important is only the proxlb-grouping line with a name and +we can still use this field. +``` + +The notes field is evaluated for each VM. All VMs with the same group name (e.g., `db-gyptazy01-workload-group01`) will be rebalanced together on the same host. \ No newline at end of file diff --git a/proxlb b/proxlb index 236dba6..3728295 100755 --- a/proxlb +++ b/proxlb @@ -29,6 +29,7 @@ try: _imports = True except ImportError as error: _imports = False +import re import requests import sys import time @@ -250,8 +251,13 @@ def get_vm_statistics(api_object, ignore_vms): for node in api_object.nodes.get(): for vm in api_object.nodes(node['node']).qemu.get(): + # Get the comment field for the VM for VM grouping + vm_comment = __get_vm_comment(api_object, node, vm['vmid']) + vm_grouping = __get_vm_grouping(vm_comment) + if vm['status'] == 'running' and vm['name'] not in ignore_vms_list: vm_statistics[vm['name']] = {} + vm_statistics[vm['name']]['grouping'] = vm_grouping vm_statistics[vm['name']]['cpu_total'] = vm['cpus'] vm_statistics[vm['name']]['cpu_used'] = vm['cpu'] vm_statistics[vm['name']]['memory_total'] = vm['maxmem'] @@ -270,6 +276,30 @@ def get_vm_statistics(api_object, ignore_vms): return vm_statistics +def __get_vm_comment(api_object, node, vmid): + """ Get a comment for a VM from a given VMID. """ + info_prefix = 'Info: [api-get-vm-comment]:' + + vm_config = api_object.nodes(node['node']).qemu(vmid).config.get() + logging.info(f'{info_prefix} Got VM comment from API.') + return vm_config.get('description', None) + + +def __get_vm_grouping(vm_comment): + """ Get the grouping name from the comment field for each VM if present. """ + info_prefix = 'Info: [api-get-vm-grouping-comment]:' + + if vm_comment is None: + logging.info(f'{info_prefix} No grouping comment for VM found.') + return None + + _comment = re.split("\n", vm_comment) + for line in _comment: + if line.startswith('proxlb-grouping:'): + logging.info(f'{info_prefix} Got grouping comment {line.strip("proxlb-grouping: ")} for VM found.') + return line.strip('proxlb-grouping: ') + + def balancing_calculations(balancing_method, node_statistics, vm_statistics): """ Calculate re-balancing of VMs on present nodes across the cluster. """ error_prefix = 'Error: [rebalancing-calculator]:' @@ -278,7 +308,6 @@ def balancing_calculations(balancing_method, node_statistics, vm_statistics): if balancing_method not in ['memory', 'disk', 'cpu']: logging.error(f'{error_prefix} Invalid balancing method: {balancing_method}') sys.exit(2) - return node_statistics, vm_statistics sorted_vms = sorted(vm_statistics.items(), key=lambda item: item[1][f'{balancing_method}_used'], reverse=True) logging.info(f'{info_prefix} Balancing will be done for {balancing_method} efficiency.')