nova_bfd_monitor.py 2.76 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#!/usr/bin/env python
import os.path
import requests
import time
import subprocess
import logging
import argparse
from daemonize import Daemonize

APP = "nova_bfd_monitor"
DESCRIPTION = "Check that everything is ok, and signal link down via bfd otherwise"
ADMIN_DOWN_MARKER = "/etc/admin_down"
HAPROXY_CHECK_URL = "http://localhost:1936/haproxy_up"


def check_state(interface):
    try:
        response = requests.get(HAPROXY_CHECK_URL, timeout=1)
        response.raise_for_status()
    except:
        return "down"
    ifstate_filename = "/sys/class/net/{}/operstate".format(interface)
    if not os.path.exists(ifstate_filename) or open(ifstate_filename).read().strip() != "up":
        return "down"
    if os.path.exists(ADMIN_DOWN_MARKER):
        return "admin"
    return "up"


def set_state(new_state):
    if new_state not in ("up", "down", "admin"):
        raise ValueError("Invalid new state: {}".format(new_state))
33
    subprocess.call(["/usr/local/bin/bfdd-control", "session", "all", "state", new_state])
34 35 36 37 38


def main(logfile, interface):
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(name)s %(levelname)s %(message)s')
39
    logging.getLogger("requests").setLevel(logging.WARNING)
40 41 42 43 44
    if logfile:
        handler = logging.handlers.RotatingFileHandler(logfile,
                                                       maxBytes=10*1024**3, backupCount=5)
        handler.setFormatter(logging.getLogger("").handlers[0].formatter)
        logging.getLogger("").addHandler(handler)
Sigmund Augdal's avatar
Sigmund Augdal committed
45

46
    logging.info("Process starting")
Sigmund Augdal's avatar
Sigmund Augdal committed
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    state = check_state(interface)
    set_state(state)
    logging.info("bfd-check starting, initial state: %s", state)
    while True:
        time.sleep(1)
        new_state = check_state(interface)
        if new_state != state:
            set_state(new_state)
            logging.info("state changed from %s to %s", state, new_state)
            state = new_state


def parse_args():
    parser = argparse.ArgumentParser(description=DESCRIPTION)
    parser.add_argument('-d', '--daemonize', default=False, action='store_true',
                        help="Run as daemon")
    parser.add_argument('--pidfile', type=str, default="/var/run/{}.pid".format(APP),
                        help="pidfile when run as daemon")
    parser.add_argument('--logfile', default='/var/log/{}.log'.format(APP),
                        help="logfile to use")
    parser.add_argument('--interface', help="Downstream interface to monitor status of")

    return parser.parse_args()

if __name__ == '__main__':
    args = parse_args()
    if args.daemonize:
        daemon_main = lambda: main(args.logfile, args.interface)
        daemon = Daemonize(app=APP, pid=args.pidfile, action=daemon_main)
        daemon.start()
    else:
        main(None, args.interface)