Skip to content

Commit

Permalink
healthcheck: add support exact label match
Browse files Browse the repository at this point in the history
So far loopback ips was looking for the corresponding interface by
checking whether the label starts with the desired input.
By providing --label-exact-match it checks whether the label
exactly matches the desired input.

Signed-off-by: Seena Fallah <[email protected]>
  • Loading branch information
clwluvw committed Jun 24, 2024
1 parent 9b83c0f commit 001873c
Showing 1 changed file with 16 additions and 12 deletions.
28 changes: 16 additions & 12 deletions src/exabgp/application/healthcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def setargs(parser):
g.add_argument("--no-ip-setup", action="store_false", dest="ip_setup", help="don't setup missing IP addresses")
g.add_argument("--dynamic-ip-setup", default=False, action="store_true", dest="ip_dynamic", help="delete existing loopback ips on state down and " "disabled, then restore loopback when up")
g.add_argument("--label", default=None, help="use the provided label to match loopback addresses")
g.add_argument("--label-exact-match", default=False, action="store_true", help="use the provided label to exactly match loopback addresses, not a prefix match")
g.add_argument("--start-ip", metavar='N', type=int, default=0, help="index of the first IP in the list of IP addresses")
g.add_argument("--up-metric", metavar='M', type=int, default=100, help="first IP get the metric M when the service is up")
g.add_argument("--down-metric", metavar='M', type=int, default=1000, help="first IP get the metric M when the service is down")
Expand Down Expand Up @@ -180,15 +181,15 @@ def syslog_address():
logger.addHandler(ch)


def loopback_ips(label, label_only):
def loopback_ips(label, label_only, label_exact_match):
"""Retrieve loopback IP addresses"""
logger.debug("Retrieve loopback IP addresses")
addresses = []

if sys.platform.startswith("linux"):
# Use "ip" (ifconfig is not able to see all addresses)
ipre = re.compile(r"^(?P<index>\d+):\s+(?P<name>\S+)\s+inet6?\s+" r"(?P<ip>[\da-f.:]+)/(?P<mask>\d+)\s+.*")
labelre = re.compile(r".*\s+lo:(?P<label>\S+).*")
labelre = re.compile(r".*\s+lo:(?P<label>[^\\\s]+).*")
cmd = subprocess.Popen("/sbin/ip -o address show dev lo".split(), shell=False, stdout=subprocess.PIPE)
else:
# Try with ifconfig
Expand Down Expand Up @@ -217,7 +218,10 @@ def loopback_ips(label, label_only):
lmo = labelre.match(line)
if not lmo:
continue
if lmo.groupdict().get("label", "").startswith(label):
if label_exact_match:
if lmo.groupdict().get("label", "") == label:
addresses.append(ip)
elif lmo.groupdict().get("label", "").startswith(label):
addresses.append(ip)
elif not label_only or label is None:
addresses.append(ip)
Expand All @@ -233,10 +237,10 @@ def loopback():
return lo


def setup_ips(ips, label, sudo=False):
def setup_ips(ips, label, label_exact_match, sudo=False):
"""Setup missing IP on loopback interface"""

existing = set(loopback_ips(label, False))
existing = set(loopback_ips(label, False, label_exact_match))
toadd = set([ip_network(ip) for net in ips for ip in net]) - existing
for ip in toadd:
logger.debug("Setup loopback IP address %s", ip)
Expand All @@ -255,9 +259,9 @@ def setup_ips(ips, label, sudo=False):
raise e


def remove_ips(ips, label, sudo=False):
def remove_ips(ips, label, label_exact_match, sudo=False):
"""Remove added IP on loopback interface"""
existing = set(loopback_ips(label, True))
existing = set(loopback_ips(label, True, label_exact_match))

# Get intersection of IPs (ips setup, and IPs configured by ExaBGP)
toremove = set([ip_network(ip) for net in ips for ip in net]) & existing
Expand Down Expand Up @@ -366,7 +370,7 @@ def exabgp(target):
# if ips was deleted with dyn ip, re-setup them
if target == states.UP and options.ip_dynamic:
logger.info("service up, restoring loopback ips")
setup_ips(options.ips, options.label, options.sudo)
setup_ips(options.ips, options.label, options.label_exact_match, options.sudo)

logger.info("send announces for %s state to ExaBGP", target)
metric = vars(options).get("{0}_metric".format(str(target).lower()), 0)
Expand Down Expand Up @@ -427,11 +431,11 @@ def exabgp(target):
# dynamic ip management. When the service fail, remove the loopback
if target in (states.EXIT,) and (options.ip_dynamic or options.ip_setup):
logger.info("exiting, deleting loopback ips")
remove_ips(options.ips, options.label, options.sudo)
remove_ips(options.ips, options.label, options.label_exact_match, options.sudo)
# dynamic ip management. When the service fail, remove the loopback
if target in (states.DOWN, states.DISABLED) and options.ip_dynamic:
logger.info("service down, deleting loopback ips")
remove_ips(options.ips, options.label, options.sudo)
remove_ips(options.ips, options.label, options.label_exact_match, options.sudo)

def trigger(target):
"""Trigger a state change and execute the appropriate commands"""
Expand Down Expand Up @@ -551,12 +555,12 @@ def main():
options.pid.close()
try:
# Setup IP to use
options.ips = options.ips or loopback_ips(options.label, False)
options.ips = options.ips or loopback_ips(options.label, False, options.label_exact_match)
if not options.ips:
logger.error("No IP found")
sys.exit(1)
if options.ip_setup:
setup_ips(options.ips, options.label, options.sudo)
setup_ips(options.ips, options.label, options.label_exact_match, options.sudo)
drop_privileges(options.user, options.group)

# Parse defined networks into a list of IPs for advertisement
Expand Down

0 comments on commit 001873c

Please sign in to comment.