mirror of
https://github.com/gyptazy/ProxLB.git
synced 2026-04-06 04:41:58 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5542b9bc6c | ||
|
|
16c5ee4d74 | ||
|
|
21a73b71df | ||
|
|
d3c055cbad | ||
|
|
24b7d2c860 | ||
|
|
6e87e2d478 | ||
|
|
2593b87d3f | ||
|
|
6310262e97 |
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 (by @gyptazy). [#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 (by @gyptazy). [#107]
|
||||
2
.changelogs/1.0.5/113_fix_migration_from_local_disk.yml
Normal file
2
.changelogs/1.0.5/113_fix_migration_from_local_disk.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix migration from local disks (by @greenlogles). [#113]
|
||||
2
.changelogs/1.0.5/98_fix_log_verbosity_opts.yml
Normal file
2
.changelogs/1.0.5/98_fix_log_verbosity_opts.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix allowed values (add DEBUG, WARNING) for log verbosity (by @gyptazy). [#98]
|
||||
1
.changelogs/1.0.5/release_meta.yml
Normal file
1
.changelogs/1.0.5/release_meta.yml
Normal file
@@ -0,0 +1 @@
|
||||
date: 2024-10-30
|
||||
1
.changelogs/1.0.6/release_meta.yml
Normal file
1
.changelogs/1.0.6/release_meta.yml
Normal file
@@ -0,0 +1 @@
|
||||
date: TBD
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -6,6 +6,20 @@ 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.5] - 2024-10-30
|
||||
|
||||
### Changed
|
||||
|
||||
- Change docs to make bool usage in configs more clear. [#104]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix migration from local disks (by @greenlogles). [#113]
|
||||
- Fix allowed values (add DEBUG, WARNING) for log verbosity. [#98]
|
||||
- Fix node (and its objects) evaluation when not reachable (e.g., maintenance). [#107]
|
||||
- Fix evaluation of maintenance mode where comparing list & string resulted in a crash (by @glitchvern). [#106]
|
||||
|
||||
|
||||
## [1.0.4] - 2024-10-11
|
||||
|
||||
### Added
|
||||
|
||||
@@ -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 `DEBUG`, `INFO`, `WARNING` 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.4_amd64.deb
|
||||
dpkg -i proxlb_1.0.4_amd64.deb
|
||||
wget https://cdn.gyptazy.com/files/os/debian/proxlb/proxlb_1.0.5_amd64.deb
|
||||
dpkg -i proxlb_1.0.5_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.5 | cr.gyptazy.com/proxlb/proxlb:v1.0.5 |
|
||||
| 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 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(proxmox-rebalancing-service VERSION 1.0.4)
|
||||
project(proxmox-rebalancing-service VERSION 1.0.5)
|
||||
|
||||
install(PROGRAMS ../proxlb DESTINATION /bin)
|
||||
install(FILES ../proxlb.conf DESTINATION /etc/proxlb)
|
||||
@@ -9,8 +9,8 @@ install(FILES proxlb.service DESTINATION /etc/systemd/system)
|
||||
set(CPACK_PACKAGE_NAME "proxlb")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/../README.md")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Florian Paul Azim <gyptazy> Hoberg <gyptazy@gyptazy.ch>")
|
||||
set(CPACK_PACKAGE_CONTACT "Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Florian Paul Azim <gyptazy> Hoberg <gyptazy@gyptazy.com>")
|
||||
set(CPACK_PACKAGE_CONTACT "Florian Paul Azim Hoberg <gyptazy@gyptazy.com>")
|
||||
set(CPACK_PACKAGE_VENDOR "gyptazy")
|
||||
|
||||
# RPM packaging
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
proxlb (1.0.5) unstable; urgency=low
|
||||
|
||||
* Fix migration from local disks.
|
||||
* Fix allowed values (add DEBUG, WARNING) for log verbosity.
|
||||
* Fix node (and its objects) evaluation when not reachable (e.g., maintenance).
|
||||
* Fix evaluation of maintenance mode where comparing list & string resulted in a crash.
|
||||
* Change docs to make bool usage in configs more clear.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Wed, 30 Oct 2024 17:02:31 +0100
|
||||
|
||||
proxlb (1.0.4) unstable; urgency=low
|
||||
|
||||
* Add feature to make API timeout configureable.
|
||||
@@ -8,7 +18,7 @@ proxlb (1.0.4) unstable; urgency=low
|
||||
* 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
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Fri, 11 Oct 2024 06:14:13 +0200
|
||||
|
||||
proxlb (1.0.3) unstable; urgency=low
|
||||
|
||||
@@ -28,7 +38,7 @@ proxlb (1.0.3) unstable; urgency=low
|
||||
* Fix handling of unset `ignore_nodes` and `ignore_vms` resulted in an attribute error.
|
||||
* Fix anti-affinity rules not evaluating a new and different node.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> Wed, 11 Sep 2024 17:31:03 +0200
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Wed, 11 Sep 2024 17:31:03 +0200
|
||||
|
||||
proxlb (1.0.2) unstable; urgency=low
|
||||
|
||||
@@ -38,16 +48,16 @@ proxlb (1.0.2) unstable; urgency=low
|
||||
* Fix CMake packaging for Debian package to avoid overwriting the config file.
|
||||
* Fix some wonkey code styles.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> Tue, 13 Aug 2024 17:28:14 +0200
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Tue, 13 Aug 2024 17:28:14 +0200
|
||||
|
||||
proxlb (1.0.0) unstable; urgency=low
|
||||
|
||||
* Initial release of ProxLB.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> Thu, 01 Aug 2024 17:04:12 +0200
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Thu, 01 Aug 2024 17:04:12 +0200
|
||||
|
||||
proxlb (0.9.0) unstable; urgency=low
|
||||
|
||||
* Initial development release of ProxLB as a tech preview.
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> Sun, 07 Jul 2024 05:38:41 +0200
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Sun, 07 Jul 2024 05:38:41 +0200
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
* Fri Oct 11 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
* Wed Oct 30 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- Fix migration from local disks.
|
||||
- Fix allowed values (add DEBUG, WARNING) for log verbosity.
|
||||
- Fix node (and its objects) evaluation when not reachable (e.g., maintenance).
|
||||
- Fix evaluation of maintenance mode where comparing list & string resulted in a crash.
|
||||
- Change docs to make bool usage in configs more clear.
|
||||
|
||||
* Fri Oct 11 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- 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.
|
||||
@@ -7,7 +14,7 @@
|
||||
- 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>
|
||||
* Wed Sep 12 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- Add a convert function to cast all bool alike options from configparser to bools.
|
||||
- Add a config parser options for future features.
|
||||
- Add a config versio schema that must be supported by ProxLB.
|
||||
@@ -24,14 +31,14 @@
|
||||
- Fix handling of unset `ignore_nodes` and `ignore_vms` resulted in an attribute error.
|
||||
- Fix anti-affinity rules not evaluating a new and different node.
|
||||
|
||||
* Tue Aug 13 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
* Tue Aug 13 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- Add option to run migration in parallel or sequentially.
|
||||
- Add option to run ProxLB only on a Proxmox cluster master (req. HA feature).
|
||||
- Fixed daemon timer to use hours instead of minutes.
|
||||
- Fixed some wonkey code styles.
|
||||
|
||||
* Thu Aug 01 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
* Thu Aug 01 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- Initial release of ProxLB.
|
||||
|
||||
* Sun Jul 07 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.ch>
|
||||
* Sun Jul 07 2024 Florian Paul Azim Hoberg <gyptazy@gyptazy.com>
|
||||
- Initial development release of ProxLB as a tech preview.
|
||||
|
||||
235
proxlb
235
proxlb
@@ -42,9 +42,9 @@ import urllib3
|
||||
|
||||
# Constants
|
||||
__appname__ = "ProxLB"
|
||||
__version__ = "1.0.4"
|
||||
__version__ = "1.0.5"
|
||||
__config_version__ = 3
|
||||
__author__ = "Florian Paul Azim Hoberg <gyptazy@gyptazy.ch> @gyptazy"
|
||||
__author__ = "Florian Paul Azim Hoberg <gyptazy@gyptazy.com> @gyptazy"
|
||||
__errors__ = False
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ def __validate_config_content(proxlb_config):
|
||||
'vm_balancing_mode_option': ['bytes', 'percent'],
|
||||
'vm_balancing_type': ['vm', 'ct', 'all'],
|
||||
'storage_balancing_method': ['disk_space'],
|
||||
'log_verbosity': ['INFO', 'CRITICAL']
|
||||
'log_verbosity': ['DEBUG', 'INFO', 'WARNING', 'CRITICAL']
|
||||
}
|
||||
|
||||
for string_val in validate_string_options:
|
||||
@@ -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
|
||||
@@ -882,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)
|
||||
@@ -954,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)
|
||||
@@ -1185,7 +1189,8 @@ def __run_vm_rebalancing(api_object, _vm_vm_statistics, app_args, parallel_migra
|
||||
# Migrate type VM (live migration).
|
||||
if value['type'] == 'vm':
|
||||
logging.info(f'{info_prefix} Rebalancing VM {vm} from node {value["node_parent"]} to node {value["node_rebalance"]}.')
|
||||
job_id = api_object.nodes(value['node_parent']).qemu(value['vmid']).migrate().post(target=value['node_rebalance'],online=1)
|
||||
options = {'target': value['node_rebalance'], 'online': 1, 'with-local-disks': 1}
|
||||
job_id = api_object.nodes(value['node_parent']).qemu(value['vmid']).migrate().post(**options)
|
||||
|
||||
# Migrate type CT (requires restart of container).
|
||||
if value['type'] == 'ct':
|
||||
|
||||
Reference in New Issue
Block a user