mirror of
https://github.com/gyptazy/ProxLB.git
synced 2026-04-06 04:41:58 +02:00
Compare commits
11 Commits
feature/91
...
fix/106-fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e87e2d478 | ||
|
|
2593b87d3f | ||
|
|
6310262e97 | ||
|
|
38712e90a3 | ||
|
|
c2b2f62462 | ||
|
|
adde04639e | ||
|
|
a4b1f4af24 | ||
|
|
55c714a888 | ||
|
|
3cd631db20 | ||
|
|
d44da076cc | ||
|
|
95e8fc5737 |
2
.changelogs/1.0.4/75_fix_cpu_balancing.yml
Normal file
2
.changelogs/1.0.4/75_fix_cpu_balancing.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix CPU balancing where calculations are done in float instead of int. (by @glitchvern) [#75]
|
||||
@@ -1 +1 @@
|
||||
date: TBD
|
||||
date: 2024-10-11
|
||||
|
||||
2
.changelogs/1.0.5/104_docs_bool_adjustment.yml
Normal file
2
.changelogs/1.0.5/104_docs_bool_adjustment.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
changed:
|
||||
- Change docs to make bool usage in configs more clear. [#104]
|
||||
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix evaluation of maintenance mode where comparing list & string resulted in a crash (by @glitchvern). [#106]
|
||||
2
.changelogs/1.0.5/107_fix_offline_node_eval.yml
Normal file
2
.changelogs/1.0.5/107_fix_offline_node_eval.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix node (and its objects) evaluation when not reachable (e.g., maintenance). [#107]
|
||||
1
.changelogs/1.0.5/release_meta.yml
Normal file
1
.changelogs/1.0.5/release_meta.yml
Normal file
@@ -0,0 +1 @@
|
||||
date: TBD
|
||||
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report
|
||||
title: "`Bug`:"
|
||||
labels: bug, needs-analysis
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## General
|
||||
<-- Describe the bug from a high level perspective. -->
|
||||
|
||||
## Weighting
|
||||
Score: <-- Define a scoring from 0-10 (10 highest, most urgent) -->
|
||||
|
||||
## Config
|
||||
<-- Attach the ProxLB configuration for further analysis. Please take car to NOT publish your API credentials! -->
|
||||
|
||||
## Log
|
||||
<-- Attach the ProxLB debug log for further analysis. Please take car to NOT publish your API credentials! -->
|
||||
|
||||
## Meta
|
||||
Please provide some more information about your setup. This includes where you obtained ProxLB (e.g., as a `.deb` file, from the repository or container image) and also which version you're running in which mode. You can obtain the used version from you image version, your local repository information or by running `proxlb -v`.
|
||||
|
||||
Version: <-- DEFINE_VERSION -->
|
||||
Installed from: <-- DEFINE_INSTALL_SOURCE -->
|
||||
Running as: <-- Container, local on Proxmox, local on all Proxmox, dedicated -->
|
||||
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Create a new request for a missing feature
|
||||
title: "`Feature`: "
|
||||
labels: feature, needs-analysis
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## General
|
||||
<-- Describe the feature idea from a high level perspective. -->
|
||||
|
||||
## Details
|
||||
<-- Provide some more details about the new feature request and provide examples. -->
|
||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -6,61 +6,82 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [1.0.4] - 2024-10-11
|
||||
|
||||
### Added
|
||||
|
||||
- Add feature to make API timeout configureable. [#91]
|
||||
- Add maintenance mode to evacuate a node and move workloads for other nodes in the cluster. [#58]
|
||||
- Add version output cli arg. [#89]
|
||||
|
||||
### Changed
|
||||
|
||||
- Run storage balancing only on supported shared storages. [#79]
|
||||
- Run storage balancing only when needed to save time. [#79]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix CPU balancing where calculations are done in float instead of int. (by @glitchvern) [#75]
|
||||
- Fix documentation for the underlying infrastructure. [#81]
|
||||
|
||||
|
||||
## [1.0.3] - 2024-09-12
|
||||
|
||||
### Added
|
||||
|
||||
- Add storage balancing function. [#51]
|
||||
- Add a convert function to cast all bool alike options from configparser to bools. [#53]
|
||||
- Add a config parser options for future features. [#53]
|
||||
- Add a config versio schema that must be supported by ProxLB. [#53]
|
||||
- Add feature to allow the API hosts being provided as a comma separated list. [#60]
|
||||
- Add storage balancing function. [#51]
|
||||
- Add doc how to add dedicated user for authentication. (by @Dulux-Oz)
|
||||
- Add feature to allow the API hosts being provided as a comma separated list. [#60]
|
||||
- Add cli arg `-b` to return the next best node for next VM/CT placement. [#8]
|
||||
|
||||
### Changed
|
||||
|
||||
- Provide a more reasonable output when HA services are not active in a Proxmox cluster. [#68]
|
||||
- Improve the underlying code base for future implementations. [#53]
|
||||
- Provide a more reasonable output when HA services are not active in a Proxmox cluster. [#68]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix documentation for the master_only parameter placed in the wrong config section. [#74]
|
||||
- Fixed `master_only` function by inverting the condition.
|
||||
- Improved the overall validation and error handling. [#64]
|
||||
- Fix bug in the `proxlb.conf` in the vm_balancing section.
|
||||
- Fix handling of unset `ignore_nodes` and `ignore_vms` resulted in an attribute error. [#71]
|
||||
- Fix anti-affinity rules not evaluating a new and different node. [#67]
|
||||
- Fix documentation for the master_only parameter placed in the wrong config section. [#74]
|
||||
- Fix handling of unset `ignore_nodes` and `ignore_vms` resulted in an attribute error. [#71]
|
||||
|
||||
|
||||
## [1.0.2] - 2024-08-13
|
||||
|
||||
### Added
|
||||
|
||||
- Add option to run migration in parallel or sequentially. [#41]
|
||||
- Add option to run ProxLB only on the Proxmox's master node in the cluster (reg. HA feature). [#40]
|
||||
- Add option to run migrations in parallel or sequentially. [#41]
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix daemon timer to use hours instead of minutes. [#45]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix CMake packaging for Debian package to avoid overwriting the config file. [#49]
|
||||
- Fix wonkey code style.
|
||||
|
||||
|
||||
## [1.0.0] - 2024-08-01
|
||||
|
||||
### Added
|
||||
|
||||
- Add feature to prevent VMs from being relocated by defining a wildcard pattern. [#7]
|
||||
- Add feature to make log verbosity configurable [#17].
|
||||
- Add option_mode to rebalance by node's free resources in percent (instead of bytes). [#29]
|
||||
- Add option to rebalance by assigned VM resources to avoid over provisioning. [#16]
|
||||
- Add Docker/Podman support. [#10 by @daanbosch]
|
||||
- Add exclude grouping feature to rebalance VMs from being located together to new nodes. [#4]
|
||||
- Add feature to prevent VMs from being relocated by defining the 'plb_ignore_vm' tag. [#7]
|
||||
- Add dry-run support to see what kind of rebalancing would be done. [#6]
|
||||
- Add LXC/Container integration. [#27]
|
||||
- Add exclude grouping feature to rebalance VMs from being located together to new nodes. [#4]
|
||||
- Add dry-run support to see what kind of rebalancing would be done. [#6]
|
||||
- Add Docker/Podman support. [#10 by @daanbosch]
|
||||
- Add feature to prevent VMs from being relocated by defining a wildcard pattern. [#7]
|
||||
- Add feature to prevent VMs from being relocated by defining the 'plb_ignore_vm' tag. [#7]
|
||||
- Add include grouping feature to rebalance VMs bundled to new nodes. [#3]
|
||||
- Add option to rebalance by assigned VM resources to avoid overprovisioning. [#16]
|
||||
- Add feature to make log verbosity configurable [#17].
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Before submitting a pull request, ensure that your changes sucessfully perform t
|
||||
|
||||
1. **Install pytest if you haven't already:**
|
||||
```sh
|
||||
pip install fake8
|
||||
pip install flake8
|
||||
```
|
||||
|
||||
2. **Run the lintin:**
|
||||
@@ -118,4 +118,4 @@ By participating in this project, you agree to abide by our [Code of Conduct](CO
|
||||
|
||||
If you need help or have any questions, feel free to reach out by creating an issue or by joining our [discussion forum](https://github.com/gyptazy/proxlb/discussions). You can also refer to our [documentation](https://github.com/gyptazy/ProxLB/tree/main/docs) for more information about the project or join our [chat room](https://matrix.to/#/#proxlb:gyptazy.ch) in Matrix.
|
||||
|
||||
Thank you for contributing to ProxLB! Together, we can enhance the efficiency and performance of Proxmox clusters.
|
||||
Thank you for contributing to ProxLB! Together, we can enhance the efficiency and performance of Proxmox clusters.
|
||||
|
||||
19
README.md
19
README.md
@@ -113,7 +113,7 @@ The following options can be set in the `proxlb.conf` file:
|
||||
| `proxmox` | api_host | hypervisor01.gyptazy.com | Host or IP address (or comma separated list) of the remote Proxmox API. |
|
||||
| | api_user | root@pam | Username for the API. |
|
||||
| | api_pass | FooBar | Password for the API. |
|
||||
| | verify_ssl | 1 | Validate SSL certificates (1) or ignore (0). (default: 1) |
|
||||
| | verify_ssl | 1 | Validate SSL certificates (1) or ignore (0). (default: 1, type: bool) |
|
||||
| | timeout | 10 | Timeout for the Proxmox API in sec. (default: 10) |
|
||||
| `vm_balancing` | enable | 1 | Enables VM/CT balancing. |
|
||||
| | method | memory | Defines the balancing method (default: memory) where you can use `memory`, `disk` or `cpu`. |
|
||||
@@ -121,19 +121,19 @@ The following options can be set in the `proxlb.conf` file:
|
||||
| | mode_option | byte | Rebalance by node's resources in `bytes` or `percent`. (default: bytes) |
|
||||
| | type | vm | Rebalance only `vm` (virtual machines), `ct` (containers) or `all` (virtual machines & containers). (default: vm)|
|
||||
| | balanciness | 10 | Value of the percentage of lowest and highest resource consumption on nodes may differ before rebalancing. (default: 10) |
|
||||
| | parallel_migrations | 1 | Defines if migrations should be done parallely or sequentially. (default: 1) |
|
||||
| | parallel_migrations | 1 | Defines if migrations should be done parallely or sequentially. (default: 1, type: bool) |
|
||||
| | maintenance_nodes | dummynode03,dummynode04 | Defines a comma separated list of nodes to set them into maintenance mode and move VMs/CTs to other nodes. |
|
||||
| | ignore_nodes | dummynode01,dummynode02,test* | Defines a comma separated list of nodes to exclude. |
|
||||
| | ignore_vms | testvm01,testvm02 | Defines a comma separated list of VMs to exclude. (`*` as suffix wildcard or tags are also supported) |
|
||||
| `storage_balancing` | enable | 0 | Enables storage balancing. |
|
||||
| | balanciness | 10 | Value of the percentage of lowest and highest storage consumption may differ before rebalancing. (default: 10) |
|
||||
| | parallel_migrations | 1 | Defines if migrations should be done parallely or sequentially. (default: 1) |
|
||||
| `update_service` | enable | 0 | Enables the automated update service (rolling updates). |
|
||||
| | parallel_migrations | 1 | Defines if migrations should be done parallely or sequentially. (default: 1, type: bool) |
|
||||
| `update_service` | enable | 0 | Enables the automated update service (rolling updates). (default: 0, type: bool) |
|
||||
| `api` | enable | 0 | Enables the ProxLB API. |
|
||||
| `service`| daemon | 1 | Run as a daemon (1) or one-shot (0). (default: 1) |
|
||||
| `service`| daemon | 1 | Run as a daemon (1) or one-shot (0). (default: 1, type: bool) |
|
||||
| | schedule | 24 | Hours to rebalance in hours. (default: 24) |
|
||||
| | master_only | 0 | Defines is this should only be performed (1) on the cluster master node or not (0). (default: 0) |
|
||||
| | log_verbosity | INFO | Defines the log level (default: CRITICAL) where you can use `INFO`, `WARN` or `CRITICAL` |
|
||||
| | master_only | 0 | Defines is this should only be performed (1) on the cluster master node or not (0). (default: 0, type: bool) |
|
||||
| | log_verbosity | INFO | Defines the log level (default: CRITICAL) where you can use `INFO` or `CRITICAL` |
|
||||
| | config_version | 3 | Defines the current config version schema for ProxLB |
|
||||
|
||||
An example of the configuration file looks like:
|
||||
@@ -270,8 +270,8 @@ The executable must be able to read the config file, if no dedicated config file
|
||||
The easiest way to get started is by using the ready-to-use packages that I provide on my CDN and to run it on a Linux Debian based system. This can also be one of the Proxmox nodes itself.
|
||||
|
||||
```
|
||||
wget https://cdn.gyptazy.com/files/os/debian/proxlb/proxlb_1.0.3_amd64.deb
|
||||
dpkg -i proxlb_1.0.3_amd64.deb
|
||||
wget https://cdn.gyptazy.com/files/os/debian/proxlb/proxlb_1.0.4_amd64.deb
|
||||
dpkg -i proxlb_1.0.4_amd64.deb
|
||||
# Adjust your config
|
||||
vi /etc/proxlb/proxlb.conf
|
||||
systemctl restart proxlb
|
||||
@@ -368,6 +368,7 @@ Container Images for Podman, Docker etc., can be found at:
|
||||
| Version | Image |
|
||||
|------|:------:|
|
||||
| latest | cr.gyptazy.com/proxlb/proxlb:latest |
|
||||
| v1.0.4 | cr.gyptazy.com/proxlb/proxlb:v1.0.4 |
|
||||
| v1.0.3 | cr.gyptazy.com/proxlb/proxlb:v1.0.3 |
|
||||
| v1.0.2 | cr.gyptazy.com/proxlb/proxlb:v1.0.2 |
|
||||
| v1.0.0 | cr.gyptazy.com/proxlb/proxlb:v1.0.0 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(proxmox-rebalancing-service VERSION 1.0.3)
|
||||
project(proxmox-rebalancing-service VERSION 1.0.4)
|
||||
|
||||
install(PROGRAMS ../proxlb DESTINATION /bin)
|
||||
install(FILES ../proxlb.conf DESTINATION /etc/proxlb)
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
proxlb (1.0.4) unstable; urgency=low
|
||||
|
||||
* Add feature to make API timeout configureable.
|
||||
* Add maintenance mode to evacuate a node and move workloads for other nodes in the cluster.
|
||||
* Add version output cli arg.
|
||||
* Run storage balancing only on supported shared storages.
|
||||
* Run storage balancing only when needed to save time.
|
||||
* Fix CPU balancing where calculations are done in float instead of int. (by @glitchvern)
|
||||
* Fix documentation for the underlying infrastructure.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> Fri, 11 Oct 2024 06:14:13 +0200
|
||||
|
||||
proxlb (1.0.3) unstable; urgency=low
|
||||
|
||||
* Add a convert function to cast all bool alike options from configparser to bools.
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
* Fri Oct 11 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
- Add feature to make API timeout configureable.
|
||||
- Add maintenance mode to evacuate a node and move workloads for other nodes in the cluster.
|
||||
- Add version output cli arg.
|
||||
- Run storage balancing only on supported shared storages.
|
||||
- Run storage balancing only when needed to save time.
|
||||
- Fix CPU balancing where calculations are done in float instead of int. (by @glitchvern)
|
||||
- Fix documentation for the underlying infrastructure.
|
||||
|
||||
* Wed Sep 12 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
- Add a convert function to cast all bool alike options from configparser to bools.
|
||||
- Add a config parser options for future features.
|
||||
|
||||
241
proxlb
241
proxlb
@@ -42,7 +42,7 @@ import urllib3
|
||||
|
||||
# Constants
|
||||
__appname__ = "ProxLB"
|
||||
__version__ = "1.0.4b"
|
||||
__version__ = "1.0.5b"
|
||||
__config_version__ = 3
|
||||
__author__ = "Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> @gyptazy"
|
||||
__errors__ = False
|
||||
@@ -338,7 +338,7 @@ def api_connect(proxmox_api_host, proxmox_api_user, proxmox_api_pass, proxmox_ap
|
||||
proxmox_api_host = __api_connect_get_host(proxmox_api_host)
|
||||
|
||||
try:
|
||||
api_object = proxmoxer.ProxmoxAPI(proxmox_api_host, user=proxmox_api_user, password=proxmox_api_pass, verify_ssl=proxmox_api_ssl_v, timeout=proxmox_api_timeout)
|
||||
api_object = proxmoxer.ProxmoxAPI(proxmox_api_host, user=proxmox_api_user, password=proxmox_api_pass, verify_ssl=proxmox_api_ssl_v, timeout=int(proxmox_api_timeout))
|
||||
except proxmoxer.backends.https.AuthenticationError as proxmox_api_error:
|
||||
logging.critical(f'{error_prefix} Provided credentials do not work: {proxmox_api_error}')
|
||||
sys.exit(2)
|
||||
@@ -487,11 +487,11 @@ def get_node_statistics(api_object, ignore_nodes, maintenance_nodes):
|
||||
node_statistics[node['node']]['maintenance'] = False
|
||||
node_statistics[node['node']]['ignore'] = False
|
||||
node_statistics[node['node']]['cpu_total'] = node['maxcpu']
|
||||
node_statistics[node['node']]['cpu_assigned'] = node['cpu']
|
||||
node_statistics[node['node']]['cpu_assigned'] = 0
|
||||
node_statistics[node['node']]['cpu_assigned_percent'] = int((node_statistics[node['node']]['cpu_assigned']) / int(node_statistics[node['node']]['cpu_total']) * 100)
|
||||
node_statistics[node['node']]['cpu_assigned_percent_last_run'] = 0
|
||||
node_statistics[node['node']]['cpu_used'] = 0
|
||||
node_statistics[node['node']]['cpu_free'] = int(node['maxcpu']) - int(node['cpu'])
|
||||
node_statistics[node['node']]['cpu_used'] = node['cpu']
|
||||
node_statistics[node['node']]['cpu_free'] = (node['maxcpu']) - (node['cpu'] * node['maxcpu'])
|
||||
node_statistics[node['node']]['cpu_free_percent'] = int((node_statistics[node['node']]['cpu_free']) / int(node['maxcpu']) * 100)
|
||||
node_statistics[node['node']]['cpu_free_percent_last_run'] = 0
|
||||
node_statistics[node['node']]['memory_total'] = node['maxmem']
|
||||
@@ -543,133 +543,136 @@ def get_vm_statistics(api_object, ignore_vms, balancing_type):
|
||||
|
||||
for node in api_object.nodes.get():
|
||||
|
||||
# Add all virtual machines if type is vm or all.
|
||||
if balancing_type == 'vm' or balancing_type == 'all':
|
||||
for vm in api_object.nodes(node['node']).qemu.get():
|
||||
# Get VM/CT objects only when the node is online and reachable.
|
||||
if node['status'] == 'online':
|
||||
|
||||
# Get the VM tags from API.
|
||||
vm_tags = __get_vm_tags(api_object, node, vm['vmid'], 'vm')
|
||||
if vm_tags is not None:
|
||||
group_include, group_exclude, vm_ignore = __get_proxlb_groups(vm_tags)
|
||||
# Add all virtual machines if type is vm or all.
|
||||
if balancing_type == 'vm' or balancing_type == 'all':
|
||||
for vm in api_object.nodes(node['node']).qemu.get():
|
||||
|
||||
# Get wildcard match for VMs to ignore if a wildcard pattern was
|
||||
# previously found. Wildcards may slow down the task when using
|
||||
# many patterns in the ignore list. Therefore, run this only if
|
||||
# a wildcard pattern was found. We also do not need to validate
|
||||
# this if the VM is already being ignored by a defined tag.
|
||||
if vm_ignore_wildcard and not vm_ignore:
|
||||
vm_ignore = __check_vm_name_wildcard_pattern(vm['name'], ignore_vms_list)
|
||||
# Get the VM tags from API.
|
||||
vm_tags = __get_vm_tags(api_object, node, vm['vmid'], 'vm')
|
||||
if vm_tags is not None:
|
||||
group_include, group_exclude, vm_ignore = __get_proxlb_groups(vm_tags)
|
||||
|
||||
if vm['status'] == 'running' and vm['name'] not in ignore_vms_list and not vm_ignore:
|
||||
vm_statistics[vm['name']] = {}
|
||||
vm_statistics[vm['name']]['group_include'] = group_include
|
||||
vm_statistics[vm['name']]['group_exclude'] = group_exclude
|
||||
vm_statistics[vm['name']]['cpu_total'] = vm['cpus']
|
||||
vm_statistics[vm['name']]['cpu_used'] = vm['cpu']
|
||||
vm_statistics[vm['name']]['memory_total'] = vm['maxmem']
|
||||
vm_statistics[vm['name']]['memory_used'] = vm['mem']
|
||||
vm_statistics[vm['name']]['disk_total'] = vm['maxdisk']
|
||||
vm_statistics[vm['name']]['disk_used'] = vm['disk']
|
||||
vm_statistics[vm['name']]['vmid'] = vm['vmid']
|
||||
vm_statistics[vm['name']]['node_parent'] = node['node']
|
||||
vm_statistics[vm['name']]['node_rebalance'] = node['node']
|
||||
vm_statistics[vm['name']]['storage'] = {}
|
||||
vm_statistics[vm['name']]['type'] = 'vm'
|
||||
# Get wildcard match for VMs to ignore if a wildcard pattern was
|
||||
# previously found. Wildcards may slow down the task when using
|
||||
# many patterns in the ignore list. Therefore, run this only if
|
||||
# a wildcard pattern was found. We also do not need to validate
|
||||
# this if the VM is already being ignored by a defined tag.
|
||||
if vm_ignore_wildcard and not vm_ignore:
|
||||
vm_ignore = __check_vm_name_wildcard_pattern(vm['name'], ignore_vms_list)
|
||||
|
||||
# Get disk details of the related object.
|
||||
_vm_details = api_object.nodes(node['node']).qemu(vm['vmid']).config.get()
|
||||
logging.info(f'{info_prefix} Getting disk information for vm {vm["name"]}.')
|
||||
if vm['status'] == 'running' and vm['name'] not in ignore_vms_list and not vm_ignore:
|
||||
vm_statistics[vm['name']] = {}
|
||||
vm_statistics[vm['name']]['group_include'] = group_include
|
||||
vm_statistics[vm['name']]['group_exclude'] = group_exclude
|
||||
vm_statistics[vm['name']]['cpu_total'] = vm['cpus']
|
||||
vm_statistics[vm['name']]['cpu_used'] = vm['cpu']
|
||||
vm_statistics[vm['name']]['memory_total'] = vm['maxmem']
|
||||
vm_statistics[vm['name']]['memory_used'] = vm['mem']
|
||||
vm_statistics[vm['name']]['disk_total'] = vm['maxdisk']
|
||||
vm_statistics[vm['name']]['disk_used'] = vm['disk']
|
||||
vm_statistics[vm['name']]['vmid'] = vm['vmid']
|
||||
vm_statistics[vm['name']]['node_parent'] = node['node']
|
||||
vm_statistics[vm['name']]['node_rebalance'] = node['node']
|
||||
vm_statistics[vm['name']]['storage'] = {}
|
||||
vm_statistics[vm['name']]['type'] = 'vm'
|
||||
|
||||
for vm_detail_key, vm_detail_value in _vm_details.items():
|
||||
# vm_detail_key_validator = re.sub('\d+$', '', vm_detail_key)
|
||||
vm_detail_key_validator = re.sub(r'\d+$', '', vm_detail_key)
|
||||
# Get disk details of the related object.
|
||||
_vm_details = api_object.nodes(node['node']).qemu(vm['vmid']).config.get()
|
||||
logging.info(f'{info_prefix} Getting disk information for vm {vm["name"]}.')
|
||||
|
||||
if vm_detail_key_validator in _vm_details_storage_allowed:
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key] = {}
|
||||
match = re.match(r'([^:]+):[^/]+/(.+),iothread=\d+,size=(\d+G)', _vm_details[vm_detail_key])
|
||||
for vm_detail_key, vm_detail_value in _vm_details.items():
|
||||
# vm_detail_key_validator = re.sub('\d+$', '', vm_detail_key)
|
||||
vm_detail_key_validator = re.sub(r'\d+$', '', vm_detail_key)
|
||||
|
||||
# Create an efficient match group and split the strings to assign them to the storage information.
|
||||
if match:
|
||||
_volume = match.group(1)
|
||||
_disk_name = match.group(2)
|
||||
_disk_size = match.group(3)
|
||||
if vm_detail_key_validator in _vm_details_storage_allowed:
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key] = {}
|
||||
match = re.match(r'([^:]+):[^/]+/(.+),iothread=\d+,size=(\d+G)', _vm_details[vm_detail_key])
|
||||
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['name'] = _disk_name
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['device_name'] = vm_detail_key
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['volume'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_parent'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_rebalance'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['size'] = _disk_size[:-1]
|
||||
logging.info(f'{info_prefix} Added disk for {vm["name"]}: Name {_disk_name} on volume {_volume} with size {_disk_size}.')
|
||||
else:
|
||||
logging.info(f'{info_prefix} No (or unsupported) disk(s) for {vm["name"]} found.')
|
||||
# Create an efficient match group and split the strings to assign them to the storage information.
|
||||
if match:
|
||||
_volume = match.group(1)
|
||||
_disk_name = match.group(2)
|
||||
_disk_size = match.group(3)
|
||||
|
||||
logging.info(f'{info_prefix} Added vm {vm["name"]}.')
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['name'] = _disk_name
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['device_name'] = vm_detail_key
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['volume'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_parent'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_rebalance'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['size'] = _disk_size[:-1]
|
||||
logging.info(f'{info_prefix} Added disk for {vm["name"]}: Name {_disk_name} on volume {_volume} with size {_disk_size}.')
|
||||
else:
|
||||
logging.info(f'{info_prefix} No (or unsupported) disk(s) for {vm["name"]} found.')
|
||||
|
||||
# Add all containers if type is ct or all.
|
||||
if balancing_type == 'ct' or balancing_type == 'all':
|
||||
for vm in api_object.nodes(node['node']).lxc.get():
|
||||
logging.info(f'{info_prefix} Added vm {vm["name"]}.')
|
||||
|
||||
logging.warning(f'{warn_prefix} Rebalancing on LXC containers (CT) always requires them to shut down.')
|
||||
logging.warning(f'{warn_prefix} {vm["name"]} is from type CT and cannot be live migrated!')
|
||||
# Get the VM tags from API.
|
||||
vm_tags = __get_vm_tags(api_object, node, vm['vmid'], 'ct')
|
||||
if vm_tags is not None:
|
||||
group_include, group_exclude, vm_ignore = __get_proxlb_groups(vm_tags)
|
||||
# Add all containers if type is ct or all.
|
||||
if balancing_type == 'ct' or balancing_type == 'all':
|
||||
for vm in api_object.nodes(node['node']).lxc.get():
|
||||
|
||||
# Get wildcard match for VMs to ignore if a wildcard pattern was
|
||||
# previously found. Wildcards may slow down the task when using
|
||||
# many patterns in the ignore list. Therefore, run this only if
|
||||
# a wildcard pattern was found. We also do not need to validate
|
||||
# this if the VM is already being ignored by a defined tag.
|
||||
if vm_ignore_wildcard and not vm_ignore:
|
||||
vm_ignore = __check_vm_name_wildcard_pattern(vm['name'], ignore_vms_list)
|
||||
logging.warning(f'{warn_prefix} Rebalancing on LXC containers (CT) always requires them to shut down.')
|
||||
logging.warning(f'{warn_prefix} {vm["name"]} is from type CT and cannot be live migrated!')
|
||||
# Get the VM tags from API.
|
||||
vm_tags = __get_vm_tags(api_object, node, vm['vmid'], 'ct')
|
||||
if vm_tags is not None:
|
||||
group_include, group_exclude, vm_ignore = __get_proxlb_groups(vm_tags)
|
||||
|
||||
if vm['status'] == 'running' and vm['name'] not in ignore_vms_list and not vm_ignore:
|
||||
vm_statistics[vm['name']] = {}
|
||||
vm_statistics[vm['name']]['group_include'] = group_include
|
||||
vm_statistics[vm['name']]['group_exclude'] = group_exclude
|
||||
vm_statistics[vm['name']]['cpu_total'] = vm['cpus']
|
||||
vm_statistics[vm['name']]['cpu_used'] = vm['cpu']
|
||||
vm_statistics[vm['name']]['memory_total'] = vm['maxmem']
|
||||
vm_statistics[vm['name']]['memory_used'] = vm['mem']
|
||||
vm_statistics[vm['name']]['disk_total'] = vm['maxdisk']
|
||||
vm_statistics[vm['name']]['disk_used'] = vm['disk']
|
||||
vm_statistics[vm['name']]['vmid'] = vm['vmid']
|
||||
vm_statistics[vm['name']]['node_parent'] = node['node']
|
||||
vm_statistics[vm['name']]['node_rebalance'] = node['node']
|
||||
vm_statistics[vm['name']]['storage'] = {}
|
||||
vm_statistics[vm['name']]['type'] = 'ct'
|
||||
# Get wildcard match for VMs to ignore if a wildcard pattern was
|
||||
# previously found. Wildcards may slow down the task when using
|
||||
# many patterns in the ignore list. Therefore, run this only if
|
||||
# a wildcard pattern was found. We also do not need to validate
|
||||
# this if the VM is already being ignored by a defined tag.
|
||||
if vm_ignore_wildcard and not vm_ignore:
|
||||
vm_ignore = __check_vm_name_wildcard_pattern(vm['name'], ignore_vms_list)
|
||||
|
||||
# Get disk details of the related object.
|
||||
_vm_details = api_object.nodes(node['node']).lxc(vm['vmid']).config.get()
|
||||
logging.info(f'{info_prefix} Getting disk information for vm {vm["name"]}.')
|
||||
if vm['status'] == 'running' and vm['name'] not in ignore_vms_list and not vm_ignore:
|
||||
vm_statistics[vm['name']] = {}
|
||||
vm_statistics[vm['name']]['group_include'] = group_include
|
||||
vm_statistics[vm['name']]['group_exclude'] = group_exclude
|
||||
vm_statistics[vm['name']]['cpu_total'] = vm['cpus']
|
||||
vm_statistics[vm['name']]['cpu_used'] = vm['cpu']
|
||||
vm_statistics[vm['name']]['memory_total'] = vm['maxmem']
|
||||
vm_statistics[vm['name']]['memory_used'] = vm['mem']
|
||||
vm_statistics[vm['name']]['disk_total'] = vm['maxdisk']
|
||||
vm_statistics[vm['name']]['disk_used'] = vm['disk']
|
||||
vm_statistics[vm['name']]['vmid'] = vm['vmid']
|
||||
vm_statistics[vm['name']]['node_parent'] = node['node']
|
||||
vm_statistics[vm['name']]['node_rebalance'] = node['node']
|
||||
vm_statistics[vm['name']]['storage'] = {}
|
||||
vm_statistics[vm['name']]['type'] = 'ct'
|
||||
|
||||
for vm_detail_key, vm_detail_value in _vm_details.items():
|
||||
# vm_detail_key_validator = re.sub('\d+$', '', vm_detail_key)
|
||||
vm_detail_key_validator = re.sub(r'\d+$', '', vm_detail_key)
|
||||
# Get disk details of the related object.
|
||||
_vm_details = api_object.nodes(node['node']).lxc(vm['vmid']).config.get()
|
||||
logging.info(f'{info_prefix} Getting disk information for vm {vm["name"]}.')
|
||||
|
||||
if vm_detail_key_validator in _vm_details_storage_allowed:
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key] = {}
|
||||
match = re.match(r'(?P<volume>[^:]+):(?P<disk_name>[^,]+),size=(?P<disk_size>\S+)', _vm_details[vm_detail_key])
|
||||
for vm_detail_key, vm_detail_value in _vm_details.items():
|
||||
# vm_detail_key_validator = re.sub('\d+$', '', vm_detail_key)
|
||||
vm_detail_key_validator = re.sub(r'\d+$', '', vm_detail_key)
|
||||
|
||||
# Create an efficient match group and split the strings to assign them to the storage information.
|
||||
if match:
|
||||
_volume = match.group(1)
|
||||
_disk_name = match.group(2)
|
||||
_disk_size = match.group(3)
|
||||
if vm_detail_key_validator in _vm_details_storage_allowed:
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key] = {}
|
||||
match = re.match(r'(?P<volume>[^:]+):(?P<disk_name>[^,]+),size=(?P<disk_size>\S+)', _vm_details[vm_detail_key])
|
||||
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['name'] = _disk_name
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['device_name'] = vm_detail_key
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['volume'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_parent'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_rebalance'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['size'] = _disk_size[:-1]
|
||||
logging.info(f'{info_prefix} Added disk for {vm["name"]}: Name {_disk_name} on volume {_volume} with size {_disk_size}.')
|
||||
else:
|
||||
logging.info(f'{info_prefix} No disks for {vm["name"]} found.')
|
||||
# Create an efficient match group and split the strings to assign them to the storage information.
|
||||
if match:
|
||||
_volume = match.group(1)
|
||||
_disk_name = match.group(2)
|
||||
_disk_size = match.group(3)
|
||||
|
||||
logging.info(f'{info_prefix} Added vm {vm["name"]}.')
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['name'] = _disk_name
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['device_name'] = vm_detail_key
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['volume'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_parent'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['storage_rebalance'] = _volume
|
||||
vm_statistics[vm['name']]['storage'][vm_detail_key]['size'] = _disk_size[:-1]
|
||||
logging.info(f'{info_prefix} Added disk for {vm["name"]}: Name {_disk_name} on volume {_volume} with size {_disk_size}.')
|
||||
else:
|
||||
logging.info(f'{info_prefix} No disks for {vm["name"]} found.')
|
||||
|
||||
logging.info(f'{info_prefix} Added vm {vm["name"]}.')
|
||||
|
||||
logging.info(f'{info_prefix} Created VM statistics.')
|
||||
return vm_statistics
|
||||
@@ -834,6 +837,11 @@ def balancing_vm_calculations(balancing_method, balancing_mode, balancing_mode_o
|
||||
resources_vm_most_used, processed_vms = __get_most_used_resources_vm(balancing_method, balancing_mode, vm_statistics, processed_vms)
|
||||
resources_node_most_free = __get_most_free_resources_node(balancing_method, balancing_mode, balancing_mode_option, node_statistics)
|
||||
|
||||
# If most used vm is on most free node then skip it and get another one.
|
||||
while resources_vm_most_used[1]['node_parent'] == resources_node_most_free[0] and len(processed_vms) < len(vm_statistics):
|
||||
resources_vm_most_used, processed_vms = __get_most_used_resources_vm(balancing_method, balancing_mode, vm_statistics, processed_vms)
|
||||
logging.debug(f'{info_prefix} processed {len(processed_vms)} out of {len(vm_statistics)} vms.')
|
||||
|
||||
# Update resource statistics for VMs and nodes.
|
||||
node_statistics, vm_statistics = __update_vm_resource_statistics(resources_vm_most_used, resources_node_most_free,
|
||||
vm_statistics, node_statistics, balancing_method, balancing_mode)
|
||||
@@ -877,7 +885,7 @@ def balancing_vm_maintenance(proxlb_config, app_args, node_statistics, vm_statis
|
||||
return node_statistics, vm_statistics
|
||||
|
||||
for node_name in maintenance_nodes_list:
|
||||
node_vms = sorted(vm_statistics.items(), key=lambda item: item[0] if item[1]['node_parent'] == node_name else [])
|
||||
node_vms = list(filter(lambda item: item[0] if item[1]['node_parent'] == node_name else [], vm_statistics.items()))
|
||||
# Update resource statistics for VMs and nodes.
|
||||
for vm in node_vms:
|
||||
resources_node_most_free = __get_most_free_resources_node(balancing_method, balancing_mode, balancing_mode_option, node_statistics)
|
||||
@@ -949,8 +957,9 @@ def __validate_balanciness(balanciness, balancing_method, balancing_mode, node_s
|
||||
return False
|
||||
|
||||
# Add node information to resource list.
|
||||
node_resource_percent_list.append(int(node_info[f'{balancing_method}_{node_resource_selector}_percent']))
|
||||
logging.debug(f'{info_prefix} Node: {node_name} with values: {node_info}')
|
||||
if not node_statistics[node_name]['maintenance']:
|
||||
node_resource_percent_list.append(int(node_info[f'{balancing_method}_{node_resource_selector}_percent']))
|
||||
logging.debug(f'{info_prefix} Node: {node_name} with values: {node_info}')
|
||||
|
||||
# Create a sorted list of the delta + balanciness between the node resources.
|
||||
node_resource_percent_list_sorted = sorted(node_resource_percent_list)
|
||||
|
||||
Reference in New Issue
Block a user