#!/usr/bin/python3

import json
import requests
import subprocess
import sys
import time


SPP_CTL_SERVICE = "spp_ctl.service"
SPP_PRIMATY_SERVICE = "spp_primary.service"
SPP_VF_SERVICE = "spp_vf-{sec_id}.service"
SPP_MIRROR_SERVICE = "spp_mirror.service"
SPP_WAIT_TIMEOUT = 300


def _is_service_active(service):
    args = ["systemctl", "is-active", service, "--quiet"]
    return subprocess.call(args) == 0


def _service_start(service):
    args = ["sudo", "systemctl", "start", service]
    subprocess.call(args)


def _get_procs(api_ip_port):
    path = "http://%s/v1/processes" % api_ip_port
    r = requests.get(path)
    if r.status_code >= 400:
        print("get processes failed: %s" % r.text)
        return
    return r.json()


def wait_primary_initialized(api_ip_port):
    timeout = SPP_WAIT_TIMEOUT
    while timeout > 0:
        try:
            procs = _get_procs(api_ip_port)
            if procs is None:
                return False
            for proc in procs:
                if proc["type"] == "primary":
                    return True
        except Exception as e:
            if "Connection refused" in str(e):
                # spp-ctl is not initialized yet.
                pass
            else:
                print("get processes failed: %s" % e)
                return False
        time.sleep(3)
        timeout = timeout - 3
    print("waiting primary initialization timeout.")
    return False


def wait_secondary_initialized(api_ip_port, sec_id):
    timeout = SPP_WAIT_TIMEOUT
    while timeout > 0:
        procs = _get_procs(api_ip_port)
        if procs is None:
            return False
        for proc in procs:
            if proc.get("client-id") == sec_id:
                return True
        time.sleep(3)
        timeout = timeout - 3
    print("waiting secondary(%d) initialization timeout." % sec_id)
    return False


def start_primary(num_sec):
    service = SPP_PRIMATY_SERVICE
    if _is_service_active(service):
        print("%s already active." % service)
    else:
        for sec_id in range(1, num_sec + 1):
            if _is_service_active(SPP_VF_SERVICE.format(sec_id=sec_id)):
                print("spp_primary does not restart "
                      "because spp_vf is running.")
                return False
        _service_start(service)
        print("%s started." % service)
    return True


def service_start(service):
    if _is_service_active(service):
        print("%s already active." % service)
    else:
        _service_start(service)
        print("%s started." % service)


def main():
    try:
        num_sec = int(sys.argv[1])
        mirror_support = int(sys.argv[2])
        api_ip_port = sys.argv[3]
    except:
        print("usage: start-spp-services num_secondary mirror_support"
              " api_ip:port")
        return 1

    service_start(SPP_CTL_SERVICE)

    if start_primary(num_sec):
        print("waiting primary initialization. it may take times.")
        if not wait_primary_initialized(api_ip_port):
            return 1

    for sec_id in range(1, num_sec + 1):
        service = SPP_VF_SERVICE.format(sec_id=sec_id)
        service_start(service)
        if not wait_secondary_initialized(api_ip_port, sec_id):
            return 1

    if mirror_support:
        service_start(SPP_MIRROR_SERVICE)
        if not wait_secondary_initialized(api_ip_port, num_sec + 1):
            return 1

    return 0


if __name__ == "__main__":
    sys.exit(main())
