mirror of
https://github.com/gyptazy/ProxLB.git
synced 2026-04-06 04:41:58 +02:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8a154abde | ||
|
|
554a3eaf72 | ||
|
|
0b35987403 | ||
|
|
d93048db69 | ||
|
|
2aba7dbe23 | ||
|
|
ba388dfd7c | ||
|
|
5aa8257d40 | ||
|
|
99fefe20bf | ||
|
|
b9fb3a60e1 | ||
|
|
88b3288eb7 | ||
|
|
fa0113f112 | ||
|
|
0039ae9093 | ||
|
|
e3bbf31fdd | ||
|
|
bf393c6bbf | ||
|
|
7e5b72cfc7 | ||
|
|
0ba76f80f3 | ||
|
|
b48ff9d677 | ||
|
|
b5c11af474 | ||
|
|
af2992747d |
2
.changelogs/1.1.7/304_add_graceful_shutdown_sigint.yml
Normal file
2
.changelogs/1.1.7/304_add_graceful_shutdown_sigint.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
added:
|
||||
- Add graceful shutdown for SIGINT (e.g., CTRL + C abort). (@gyptazy). [#304]
|
||||
@@ -0,0 +1,2 @@
|
||||
added:
|
||||
- Add conntrack state aware migrations of VMs (@gyptazy). [#305]
|
||||
2
.changelogs/1.1.7/308_fix_only_validate_valid_jobids.yml
Normal file
2
.changelogs/1.1.7/308_fix_only_validate_valid_jobids.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix crash when validating absent migration job ids. (@gyptazy). [#308]
|
||||
@@ -0,0 +1,2 @@
|
||||
fixed:
|
||||
- Fix guest object names are not being evaluated in debug log. (@gyptazy). [#310]
|
||||
1
.changelogs/1.1.7/release_meta.yml
Normal file
1
.changelogs/1.1.7/release_meta.yml
Normal file
@@ -0,0 +1 @@
|
||||
date: 2025-09-19
|
||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -6,7 +6,25 @@ 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.1.6] - 2027-09-04
|
||||
## [1.1.7] - 2025-09-19
|
||||
|
||||
### Added
|
||||
|
||||
- Add conntrack state aware migrations of VMs (@gyptazy). [#305]
|
||||
- Add graceful shutdown for SIGINT (e.g., CTRL + C abort). (@gyptazy). [#304]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix crash when validating absent migration job ids. (@gyptazy). [#308]
|
||||
- Fix guest object names are not being evaluated in debug log. (@gyptazy). [#310]
|
||||
|
||||
## [1.1.6.1] - 2025-09-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- Validate for node presence when pinning VMs to avoid crashing (@gyptazy). [#296]
|
||||
|
||||
## [1.1.6] - 2025-09-04
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
@@ -165,6 +165,8 @@ docker run -it --rm -v $(pwd)/proxlb.yaml:/etc/proxlb/proxlb.yaml proxlb
|
||||
| Version | Image |
|
||||
|------|:------:|
|
||||
| latest | cr.gyptazy.com/proxlb/proxlb:latest |
|
||||
| v1.1.7 | cr.gyptazy.com/proxlb/proxlb:v1.1.7 |
|
||||
| v1.1.6.1 | cr.gyptazy.com/proxlb/proxlb:v1.1.6.1 |
|
||||
| v1.1.6 | cr.gyptazy.com/proxlb/proxlb:v1.1.6 |
|
||||
| v1.1.5 | cr.gyptazy.com/proxlb/proxlb:v1.1.5 |
|
||||
| v1.1.4 | cr.gyptazy.com/proxlb/proxlb:v1.1.4 |
|
||||
@@ -266,6 +268,7 @@ The following options can be set in the configuration file `proxlb.yaml`:
|
||||
| | parallel_jobs | | 5 | `Int` | The amount if parallel jobs when migrating guests. (default: `5`)|
|
||||
| | live | | True | `Bool` | If guests should be moved live or shutdown.|
|
||||
| | with_local_disks | | True | `Bool` | If balancing of guests should include local disks.|
|
||||
| | with_conntrack_state | | True | `Bool` | If balancing of guests should including the conntrack state.|
|
||||
| | balance_types | | ['vm', 'ct'] | `List` | Defined the types of guests that should be honored. [values: `vm`, `ct`]|
|
||||
| | max_job_validation | | 1800 | `Int` | How long a job validation may take in seconds. (default: 1800) |
|
||||
| | balanciness | | 10 | `Int` | The maximum delta of resource usage between node with highest and lowest usage. |
|
||||
@@ -309,6 +312,7 @@ balancing:
|
||||
parallel: False
|
||||
live: True
|
||||
with_local_disks: True
|
||||
with_conntrack_state: True
|
||||
balance_types: ['vm', 'ct']
|
||||
max_job_validation: 1800
|
||||
balanciness: 5
|
||||
|
||||
@@ -25,6 +25,7 @@ balancing:
|
||||
parallel_jobs: 1
|
||||
live: True
|
||||
with_local_disks: True
|
||||
with_conntrack_state: True
|
||||
balance_types: ['vm', 'ct']
|
||||
max_job_validation: 1800
|
||||
balanciness: 5
|
||||
|
||||
16
debian/changelog
vendored
16
debian/changelog
vendored
@@ -1,3 +1,19 @@
|
||||
proxlb (1.1.7) stable; urgency=medium
|
||||
|
||||
* Add conntrack state aware migrations of VMs. (Closes: #305)
|
||||
* Add graceful shutdown for SIGINT command. (Closes: #304)
|
||||
* Fix crash when validating absent migration job ids. (Closes: #308)
|
||||
* Fix guest object names are not being evaluated in debug log. (Closes: #310)
|
||||
* Note: Have a great Dutch Proxmox Day 2025!
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Thu, 04 Sep 2025 19:23:51 +0000
|
||||
|
||||
proxlb (1.1.6.1) stable; urgency=medium
|
||||
|
||||
* Validate for node presence when pinning VMs to avoid crashing. (Closes: #296)
|
||||
|
||||
-- Florian Paul Azim Hoberg <gyptazy@gyptazy.com> Thu, 04 Sep 2025 19:23:51 +0000
|
||||
|
||||
proxlb (1.1.6) stable; urgency=medium
|
||||
|
||||
* Add validation for provided API user token id to avoid confusions. (Closes: #291)
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
apiVersion: v3
|
||||
name: proxlb
|
||||
description: A Helm chart for self-hosted ProxLB
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: "1.1.6"
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "v1.1.6"
|
||||
version: "1.1.7"
|
||||
appVersion: "v1.1.7"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
image:
|
||||
registry: cr.gyptazy.com
|
||||
repository: proxlb/proxlb
|
||||
tag: v1.1.5
|
||||
tag: v1.1.7
|
||||
pullPolicy: IfNotPresent
|
||||
imagePullSecrets: [ ]
|
||||
|
||||
@@ -43,6 +43,7 @@ configmap:
|
||||
parallel_jobs: 1
|
||||
live: True
|
||||
with_local_disks: True
|
||||
with_conntrack_state: True
|
||||
balance_types: [ 'vm', 'ct' ]
|
||||
max_job_validation: 1800
|
||||
balanciness: 5
|
||||
@@ -57,4 +58,4 @@ configmap:
|
||||
enable: False
|
||||
time: 1
|
||||
format: "hours"
|
||||
log_level: INFO
|
||||
log_level: INFO
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
VERSION="1.1.4"
|
||||
VERSION="1.1.7"
|
||||
|
||||
# ProxLB
|
||||
sed -i "s/^__version__ = .*/__version__ = \"$VERSION\"/" "proxlb/utils/version.py"
|
||||
|
||||
@@ -33,8 +33,9 @@ def main():
|
||||
# Initialize logging handler
|
||||
logger = SystemdLogger(level=logging.INFO)
|
||||
|
||||
# Signal handler for SIGHUP
|
||||
# Initialize handlers
|
||||
signal.signal(signal.SIGHUP, Helper.handler_sighup)
|
||||
signal.signal(signal.SIGINT, Helper.handler_sigint)
|
||||
|
||||
# Parses arguments passed from the CLI
|
||||
cli_parser = CliParser()
|
||||
|
||||
@@ -91,7 +91,7 @@ class Balancing:
|
||||
# VM Balancing
|
||||
if guest_meta["type"] == "vm":
|
||||
if 'vm' in proxlb_data["meta"]["balancing"].get("balance_types", []):
|
||||
logger.debug("Balancing: Balancing for guest {guest_name} of type VM started.")
|
||||
logger.debug(f"Balancing: Balancing for guest {guest_name} of type VM started.")
|
||||
job_id = self.exec_rebalancing_vm(proxmox_api, proxlb_data, guest_name)
|
||||
else:
|
||||
logger.debug(
|
||||
@@ -101,7 +101,7 @@ class Balancing:
|
||||
# CT Balancing
|
||||
elif guest_meta["type"] == "ct":
|
||||
if 'ct' in proxlb_data["meta"]["balancing"].get("balance_types", []):
|
||||
logger.debug("Balancing: Balancing for guest {guest_name} of type CT started.")
|
||||
logger.debug(f"Balancing: Balancing for guest {guest_name} of type CT started.")
|
||||
job_id = self.exec_rebalancing_ct(proxmox_api, proxlb_data, guest_name)
|
||||
else:
|
||||
logger.debug(
|
||||
@@ -122,7 +122,8 @@ class Balancing:
|
||||
|
||||
# Wait for all jobs in the current chunk to complete
|
||||
for guest_name, node, job_id in jobs_to_wait:
|
||||
self.get_rebalancing_job_status(proxmox_api, proxlb_data, guest_name, node, job_id)
|
||||
if job_id:
|
||||
self.get_rebalancing_job_status(proxmox_api, proxlb_data, guest_name, node, job_id)
|
||||
|
||||
def exec_rebalancing_vm(self, proxmox_api: any, proxlb_data: Dict[str, Any], guest_name: str) -> None:
|
||||
"""
|
||||
@@ -143,6 +144,7 @@ class Balancing:
|
||||
guest_id = proxlb_data["guests"][guest_name]["id"]
|
||||
guest_node_current = proxlb_data["guests"][guest_name]["node_current"]
|
||||
guest_node_target = proxlb_data["guests"][guest_name]["node_target"]
|
||||
job_id = None
|
||||
|
||||
if proxlb_data["meta"]["balancing"].get("live", True):
|
||||
online_migration = 1
|
||||
@@ -154,10 +156,16 @@ class Balancing:
|
||||
else:
|
||||
with_local_disks = 0
|
||||
|
||||
if proxlb_data["meta"]["balancing"].get("with_conntrack_state", True):
|
||||
with_conntrack_state = 1
|
||||
else:
|
||||
with_conntrack_state = 0
|
||||
|
||||
migration_options = {
|
||||
'target': {guest_node_target},
|
||||
'target': guest_node_target,
|
||||
'online': online_migration,
|
||||
'with-local-disks': with_local_disks
|
||||
'with-local-disks': with_local_disks,
|
||||
'with-conntrack-state': with_conntrack_state,
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -166,6 +174,7 @@ class Balancing:
|
||||
except proxmoxer.core.ResourceException as proxmox_api_error:
|
||||
logger.critical(f"Balancing: Failed to migrate guest {guest_name} of type VM due to some Proxmox errors. Please check if resource is locked or similar.")
|
||||
logger.debug(f"Balancing: Failed to migrate guest {guest_name} of type VM due to some Proxmox errors: {proxmox_api_error}")
|
||||
|
||||
logger.debug("Finished: exec_rebalancing_vm.")
|
||||
return job_id
|
||||
|
||||
@@ -188,6 +197,7 @@ class Balancing:
|
||||
guest_id = proxlb_data["guests"][guest_name]["id"]
|
||||
guest_node_current = proxlb_data["guests"][guest_name]["node_current"]
|
||||
guest_node_target = proxlb_data["guests"][guest_name]["node_target"]
|
||||
job_id = None
|
||||
|
||||
try:
|
||||
logger.info(f"Balancing: Starting to migrate CT guest {guest_name} from {guest_node_current} to {guest_node_target}.")
|
||||
@@ -195,6 +205,7 @@ class Balancing:
|
||||
except proxmoxer.core.ResourceException as proxmox_api_error:
|
||||
logger.critical(f"Balancing: Failed to migrate guest {guest_name} of type CT due to some Proxmox errors. Please check if resource is locked or similar.")
|
||||
logger.debug(f"Balancing: Failed to migrate guest {guest_name} of type CT due to some Proxmox errors: {proxmox_api_error}")
|
||||
|
||||
logger.debug("Finished: exec_rebalancing_ct.")
|
||||
return job_id
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class Guests:
|
||||
guests['guests'][guest['name']]['affinity_groups'] = Tags.get_affinity_groups(guests['guests'][guest['name']]['tags'])
|
||||
guests['guests'][guest['name']]['anti_affinity_groups'] = Tags.get_anti_affinity_groups(guests['guests'][guest['name']]['tags'])
|
||||
guests['guests'][guest['name']]['ignore'] = Tags.get_ignore(guests['guests'][guest['name']]['tags'])
|
||||
guests['guests'][guest['name']]['node_relationships'] = Tags.get_node_relationships(guests['guests'][guest['name']]['tags'])
|
||||
guests['guests'][guest['name']]['node_relationships'] = Tags.get_node_relationships(guests['guests'][guest['name']]['tags'], nodes)
|
||||
guests['guests'][guest['name']]['type'] = 'vm'
|
||||
|
||||
logger.debug(f"Resources of Guest {guest['name']} (type VM) added: {guests['guests'][guest['name']]}")
|
||||
|
||||
@@ -16,6 +16,7 @@ import time
|
||||
import utils.version
|
||||
from utils.logger import SystemdLogger
|
||||
from typing import Dict, Any
|
||||
from types import FrameType
|
||||
|
||||
logger = SystemdLogger()
|
||||
|
||||
@@ -200,7 +201,7 @@ class Helper:
|
||||
logger.debug("Finished: print_json.")
|
||||
|
||||
@staticmethod
|
||||
def handler_sighup(signum, frame):
|
||||
def handler_sighup(signum: int, frame: FrameType) -> None:
|
||||
"""
|
||||
Signal handler for SIGHUP.
|
||||
|
||||
@@ -217,6 +218,23 @@ class Helper:
|
||||
Helper.proxlb_reload = True
|
||||
logger.debug("Finished: handle_sighup.")
|
||||
|
||||
@staticmethod
|
||||
def handler_sigint(signum: int, frame: FrameType) -> None:
|
||||
"""
|
||||
Signal handler for SIGINT. (triggered by CTRL+C).
|
||||
|
||||
Args:
|
||||
signum (int): The signal number (e.g., SIGINT).
|
||||
frame (FrameType): The current stack frame when the signal was received.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
exit_message = "ProxLB has been successfully terminated by user."
|
||||
logger.debug(exit_message)
|
||||
print(f"\n {exit_message}")
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def get_host_port_from_string(host_object):
|
||||
"""
|
||||
|
||||
@@ -3,5 +3,5 @@ __app_desc__ = "A DRS alike loadbalancer for Proxmox clusters."
|
||||
__author__ = "Florian Paul Azim Hoberg <gyptazy>"
|
||||
__copyright__ = "Copyright (C) 2025 Florian Paul Azim Hoberg (@gyptazy)"
|
||||
__license__ = "GPL-3.0"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.1.7"
|
||||
__url__ = "https://github.com/gyptazy/ProxLB"
|
||||
|
||||
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup
|
||||
|
||||
setup(
|
||||
name="proxlb",
|
||||
version="1.1.6",
|
||||
version="1.1.7",
|
||||
description="A DRS alike loadbalancer for Proxmox clusters.",
|
||||
long_description="An advanced DRS alike loadbalancer for Proxmox clusters that also supports maintenance modes and affinity/anti-affinity rules.",
|
||||
author="Florian Paul Azim Hoberg",
|
||||
|
||||
Reference in New Issue
Block a user