198 lines
6.7 KiB
Diff
198 lines
6.7 KiB
Diff
From a4e496e5e6d9abde1b071fa2dfa1c6e7ba899cf1 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Edmund=20H=C3=A4fele?= <edmund.haefele@de.ibm.com>
|
|
Date: Thu, 30 Oct 2025 13:03:22 +0100
|
|
Subject: [PATCH] Update powervs-move-ip
|
|
|
|
- Add `iflabel` argument.
|
|
- Increase maximum number of retries for HTTP requests to four.
|
|
---
|
|
heartbeat/powervs-move-ip.in | 66 +++++++++++++++++++++++++-----------
|
|
1 file changed, 47 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/heartbeat/powervs-move-ip.in b/heartbeat/powervs-move-ip.in
|
|
index d55979e52..e2250c998 100755
|
|
--- a/heartbeat/powervs-move-ip.in
|
|
+++ b/heartbeat/powervs-move-ip.in
|
|
@@ -50,11 +50,13 @@ RESOURCE_OPTIONS = (
|
|
"use_token_cache",
|
|
"monitor_api",
|
|
"device",
|
|
+ "iflabel",
|
|
"proxy",
|
|
)
|
|
IP_CMD = "/usr/sbin/ip"
|
|
+IFLABEL_MAX_LEN = 15 # Maximum character limit for interface labels
|
|
REQUESTS_TIMEOUT = 5 # Timeout for requests calls
|
|
-HTTP_MAX_RETRIES = 3 # Maximum number of retries for HTTP requests
|
|
+HTTP_MAX_RETRIES = 4 # Maximum number of retries for HTTP requests
|
|
HTTP_BACKOFF_FACTOR = 0.3 # Sleep (factor * (2^number of previous retries)) secs
|
|
HTTP_STATUS_FORCE_RETRIES = (500, 502, 503, 504) # HTTP status codes to retry on
|
|
HTTP_RETRY_ALLOWED_METHODS = frozenset({"GET", "POST", "PUT", "DELETE"})
|
|
@@ -154,13 +156,13 @@ def ip_check_device(device):
|
|
return False
|
|
|
|
|
|
-def ip_alias_add(ip, device):
|
|
+def ip_alias_add(ip, device, label=None):
|
|
"""Add an IP alias to the given device."""
|
|
ip_cidr = f"{ip}/{CIDR_NETMASK}"
|
|
ocf.logger.debug(
|
|
- f"[ip_alias_add]: adding IP alias '{ip_cidr}' to interface '{device}'"
|
|
+ f"[ip_alias_add]: adding IP alias '{ip_cidr}' with label '{label}' to interface '{device}'"
|
|
)
|
|
- _ = ip_address_add(ip_cidr, device)
|
|
+ _ = ip_address_add(ip_cidr, device, label)
|
|
|
|
|
|
def ip_alias_remove(ip):
|
|
@@ -522,6 +524,7 @@ class PowerCloudRoute(PowerCloudAPI):
|
|
region="",
|
|
route_host_map="",
|
|
device="",
|
|
+ iflabel="",
|
|
proxy="",
|
|
monitor_api="",
|
|
use_token_cache="",
|
|
@@ -543,6 +546,7 @@ class PowerCloudRoute(PowerCloudAPI):
|
|
self.route_info = self._get_route_info()
|
|
self.route_name = self.route_info["name"]
|
|
self.device = self._get_device_name(device)
|
|
+ self.iflabel = self._make_iflabel(iflabel)
|
|
|
|
def _get_ip_info(self, ip):
|
|
"""Validate the given IP address and return its standard form."""
|
|
@@ -588,7 +592,7 @@ class PowerCloudRoute(PowerCloudAPI):
|
|
nodename = (
|
|
hostname
|
|
if not self._is_remote_route
|
|
- else next((h for h in route_map if h != hostname), None)
|
|
+ else next((host for host in route_map if host != hostname), None)
|
|
)
|
|
|
|
if not nodename or nodename not in route_map:
|
|
@@ -646,6 +650,21 @@ class PowerCloudRoute(PowerCloudAPI):
|
|
ocf.OCF_ERR_CONFIGURED,
|
|
)
|
|
|
|
+ def _make_iflabel(self, label=None):
|
|
+ """Constructs an interface label in the format 'device:label' if both are provided."""
|
|
+ if not label or self._is_remote_route:
|
|
+ return None
|
|
+
|
|
+ iflabel = f"{self.device}:{label}"
|
|
+
|
|
+ if len(iflabel) > IFLABEL_MAX_LEN:
|
|
+ raise PowerCloudRouteError(
|
|
+ f"_make_iflabel: interface label '{iflabel}' exceeds limit of {IFLABEL_MAX_LEN} characters",
|
|
+ ocf.OCF_ERR_CONFIGURED,
|
|
+ )
|
|
+
|
|
+ return iflabel
|
|
+
|
|
def _set_route_enabled(self, enabled: bool):
|
|
"""Enable or disable the PowerVS network route."""
|
|
resource = f"/v1/routes/{self.route_id}"
|
|
@@ -706,6 +725,7 @@ def start_action(
|
|
use_token_cache="",
|
|
monitor_api="",
|
|
device="",
|
|
+ iflabel="",
|
|
proxy="",
|
|
):
|
|
"""Assign the service IP.
|
|
@@ -730,7 +750,7 @@ def start_action(
|
|
local_route = create_route_instance(resource_options)
|
|
|
|
# Add IP alias
|
|
- ip_alias_add(ip, local_route.device)
|
|
+ ip_alias_add(ip, local_route.device, local_route.iflabel)
|
|
|
|
# Enable local route
|
|
ocf.logger.debug(f"[start_action]: enabling local route '{local_route.route_name}'")
|
|
@@ -758,6 +778,7 @@ def stop_action(
|
|
use_token_cache="",
|
|
monitor_api="",
|
|
device="",
|
|
+ iflabel="",
|
|
proxy="",
|
|
):
|
|
"""Remove the service IP.
|
|
@@ -810,6 +831,7 @@ def monitor_action(
|
|
use_token_cache="",
|
|
monitor_api="",
|
|
device="",
|
|
+ iflabel="",
|
|
proxy="",
|
|
):
|
|
"""Monitor the service IP.
|
|
@@ -829,15 +851,11 @@ def monitor_action(
|
|
interface_name = ip_find_device(ip)
|
|
|
|
if not use_extended_monitor:
|
|
- if interface_name:
|
|
- ocf.logger.debug(
|
|
- f"[monitor_action]: IP alias '{ip}' is active'"
|
|
- )
|
|
+ if interface_name:
|
|
+ ocf.logger.debug(f"[monitor_action]: IP alias '{ip}' is active'")
|
|
return ocf.OCF_SUCCESS
|
|
- else:
|
|
- ocf.logger.debug(
|
|
- f"[monitor_action]: IP alias '{ip}' is not active"
|
|
- )
|
|
+ else:
|
|
+ ocf.logger.debug(f"[monitor_action]: IP alias '{ip}' is not active")
|
|
return ocf.OCF_NOT_RUNNING
|
|
|
|
remote_route = create_route_instance(
|
|
@@ -893,6 +911,7 @@ def validate_all_action(
|
|
use_token_cache="",
|
|
monitor_api="",
|
|
device="",
|
|
+ iflabel="",
|
|
proxy="",
|
|
):
|
|
"""Validate resource agent parameters.
|
|
@@ -914,12 +933,10 @@ def main():
|
|
Resource Agent to move an IP address from one Power Virtual Server instance to another.
|
|
|
|
Prerequisites:
|
|
- 1. Red Hat Enterprise Linux 9.4 or higher
|
|
-
|
|
- 2. Two-node cluster
|
|
+ 1. Two-node cluster
|
|
- Distributed across two PowerVS workspaces in separate data centers within the same region.
|
|
|
|
- 3. IBM Cloud API Key:
|
|
+ 2. IBM Cloud API Key:
|
|
- Create a service API key with privileges for both workspaces.
|
|
- Save the key in a file and copy it to both cluster nodes using the same path and filename.
|
|
- Reference the key file path in the resource definition.
|
|
@@ -932,7 +949,7 @@ def main():
|
|
"powervs-move-ip",
|
|
shortdesc="Manages Power Virtual Server overlay IP routes.",
|
|
longdesc=agent_description,
|
|
- version=1.00,
|
|
+ version=1.01,
|
|
)
|
|
|
|
agent.add_parameter(
|
|
@@ -1011,6 +1028,17 @@ def main():
|
|
default="",
|
|
required=False,
|
|
)
|
|
+ agent.add_parameter(
|
|
+ "iflabel",
|
|
+ shortdesc="Network interface label",
|
|
+ longdesc=(
|
|
+ "A custom suffix for the IP address label. "
|
|
+ "It is appended to the interface name in the format device:label. "
|
|
+ "The full label must not exceed 15 characters. "
|
|
+ ),
|
|
+ content_type="string",
|
|
+ required=False,
|
|
+ )
|
|
agent.add_parameter(
|
|
"proxy",
|
|
shortdesc="Proxy",
|