Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4511607
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/heartbeat/ibmcloud-vpc-cr-vip.in b/heartbeat/ibmcloud-vpc-cr-vip.in
index 287d94b46..b568f024c 100644
--- a/heartbeat/ibmcloud-vpc-cr-vip.in
+++ b/heartbeat/ibmcloud-vpc-cr-vip.in
@@ -1,245 +1,245 @@
#!@PYTHON@ -tt
# ------------------------------------------------------------------------
# Description: Resource Agent to move a IBM Cloud VIP based on Custom Route
# Nxet-hop Change from one virtual network interface (VNI) to
# the Second virtual network interface (VNI)
#
# Authors: Eran Gampel
#
# Copyright (c) 2024 International Business Machines, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ------------------------------------------------------------------------
import subprocess
import ipaddress
import os
import sys
import textwrap
import time
OCF_FUNCTIONS_DIR = os.environ.get(
"OCF_FUNCTIONS_DIR", "%s/lib/heartbeat" % os.environ.get("OCF_ROOT")
)
sys.path.append(OCF_FUNCTIONS_DIR)
RETRY_COUNT = 1
SLEEP_TIME = 1
try:
import ocf
except ImportError:
sys.stderr.write("ImportError: ocf module import failed.")
sys.exit(5)
try:
import ibm_cloud_fail_over
except ImportError:
sys.stderr.write("ImportError: import ibm_cloud_fail_over module import failed.")
pass
def os_ip(ip):
"""Check if VSI own this IP address."""
command = ["ip", "a"]
response = subprocess.run(command, capture_output=True, text=True)
return ip in response.stdout
def ip_address_validator(ip):
"""validate ip address string
Args:
ip (string): ip address
Returns:
bool: true if the strig is a valid ipv4 ip address
"""
try:
ipaddress.ip_address(ip)
return True
except ValueError:
return False
def validate_all_action(
vpc_url="",
ext_ip_1="",
ext_ip_2="",
api_key="",
):
"""validate all paramters
Args:
vpc_url (str, mandatory): vpc_url for the region.
ext_ip_1 (str, mandatory): First Instance IP.
ext_ip_2 (str, mandatory): Second Instance IP.
api_key (str, optional): IBM Cloud API access key. Defaults to "".
Returns:
_type_: _description_
"""
if not ip_address_validator(ext_ip_1):
return ocf.OCF_ERR_CONFIGURED
if not ip_address_validator(ext_ip_2):
return ocf.OCF_ERR_CONFIGURED
ocf.logger.debug(f"validate_all_action: {vpc_url} {api_key}")
return ocf.OCF_SUCCESS
def stop_action(
vpc_url="",
ext_ip_1="",
ext_ip_2="",
api_key="",
):
"""Stop VIP
Args:
vpc_url (str, mandatory): vpc_url for the region.
ext_ip_1 (str, mandatory): First Instance IP.
ext_ip_2 (str, mandatory): Secound Instance IP.
api_key (str, optional): IBM Cloud API acsess key. Defaults to "".
Returns:
_type_: _description_
"""
ocf.logger.info("stop_action: stopping")
res = monitor_action(vpc_url, ext_ip_1, ext_ip_2, api_key)
if res == ocf.OCF_NOT_RUNNING:
ocf.logger.info("Resource is already stopped")
if res == ocf.OCF_SUCCESS:
for i in range(0,RETRY_COUNT):
time.sleep(SLEEP_TIME)
res = monitor_action(vpc_url, ext_ip_1, ext_ip_2, api_key)
if res == ocf.OCF_NOT_RUNNING:
break
return ocf.OCF_SUCCESS
def start_action(
vpc_url="",
ext_ip_1="",
ext_ip_2="",
api_key="",
):
"""start_action: redirect the service ip.
Args:
- vpc_url (str, mandatory): vpc_url for teh region .
+ vpc_url (str, mandatory): vpc_url for the region .
ext_ip_1 (str, mandatory): First Instance IP.
ext_ip_2 (str, mandatory): Secound Instance IP.
api_key (str, optional): IBM Cloud API acsess key. Defaults to "".
Change custom route nexthop to point to this endpoint.
In case of a cross AZ Active Passive the route advertize zone will
be changed to the new active zone
"""
try:
ibm_cloud_fail_over.fail_over_cr_vip("SET", vpc_url , ext_ip_1,
ext_ip_2, api_key)
active_ip = ibm_cloud_fail_over.fail_over_cr_vip("GET", vpc_url ,
ext_ip_1, ext_ip_2, api_key)
ocf.logger.info(f"start_action: active_ip: {active_ip}")
except Exception as e:
ocf.logger.error('Couldn\'t connect with IBM Cloud api: ' + str(e))
sys.exit(ocf.OCF_ERR_GENERIC)
return ocf.OCF_SUCCESS
def monitor_action(
vpc_url="",
ext_ip_1="",
ext_ip_2="",
api_key="",
):
"""monitor_action: check if service ip and gateway are responding."""
ocf.logger.debug("monitor_action:")
try:
active_ip = ibm_cloud_fail_over.fail_over_cr_vip("GET", vpc_url , ext_ip_1,
ext_ip_2, api_key)
if ip_address_validator(active_ip):
if os_ip(active_ip):
return ocf.OCF_SUCCESS
return ocf.OCF_NOT_RUNNING
except Exception as e:
ocf.logger.error('Couldn\'t connect with IBM Cloud api: ' + str(e))
sys.exit(ocf.OCF_ERR_GENERIC)
def main():
"""Instantiate the resource agent."""
agent_description = textwrap.dedent("""\
Resource Agent to move a IBM Cloud VIP based on Custom Route
from one virtual network interface (VNI) to another.
The prerequisites for the use of this resource agent are as follows:
1. A two-node (VSI or BM) cluster distributed in same Avilability zone or across.
2. Enable Instance Metadata enabled on the two nodes
3. allow_ip_spoofing enabled on the Virtual network interface
3. IBM Cloud API Key or Trused profile:
""")
agent = ocf.Agent(
"ibm-cloud-vpc-cr-vip",
shortdesc="Manages moving an IBM Cloud VIP based on Custom Route",
longdesc=agent_description
)
agent.add_parameter(
"vpc_url",
shortdesc="VPC_URL",
longdesc="IBM Cloud Public VPC URL for your region or a VPE URL for IBM Cloud VPC",
content_type="string",
required=True,
)
agent.add_parameter(
"ext_ip_1",
shortdesc="Ip address for first instance.",
longdesc="predefined private ip address for first instance.",
content_type="string",
required=True,
)
agent.add_parameter(
"ext_ip_2",
shortdesc="Ip address for second instance.",
longdesc="predefined private ip address for second instance.",
content_type="string",
required=True,
)
agent.add_parameter(
"api_key",
shortdesc="API Key or @API_KEY_FILE_PATH",
longdesc=(
"API Key or @API_KEY_FILE_PATH for IBM Cloud access. "
"The API key content or the path of an API key file that is indicated by the @ symbol."
"Not needed if trusted profile is used"
),
content_type="string",
required=False,
)
agent.add_action("start", timeout=30, handler=start_action)
agent.add_action("stop", timeout=30, handler=stop_action)
agent.add_action(
"monitor", depth=0, timeout=60, interval=60, handler=monitor_action
)
agent.add_action("validate-all", timeout=30, handler=validate_all_action)
agent.run()
if __name__ == "__main__":
main()
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Jun 25, 1:58 AM (9 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1947637
Default Alt Text
(7 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment