fuel-ccp/fuel_ccp/status.py

125 lines
4.0 KiB
Python

from __future__ import print_function
import copy
import logging
import sys
from fuel_ccp import config
from fuel_ccp import kubernetes
CONF = config.CONF
LOG = logging.getLogger(__name__)
EXT_LINK_TEMPLATE = "http://{ext_ip}:{port}"
STATE_TEMPLATE = {
"pod_total": 0,
"pod_running": 0,
"job_total": 0,
"job_completed": 0,
"links": []
}
COLORS = {
"green": "\033[92m%s\033[39m",
"yellow": "\033[93m%s\033[39m"
}
def colorized(color, s):
if sys.stdout.isatty():
return COLORS[color] % s
else:
return s
ST_OK = colorized("green", "ok")
ST_WIP = colorized("yellow", "wip")
def is_app_ready(state):
return (state["pod_total"] == state["pod_running"]
and state["job_total"] == state["job_completed"])
def repr_state(state):
return ST_OK if is_app_ready(state) else ST_WIP
def get_pod_states(components=None):
ext_ip = CONF.configs.get("k8s_external_ip", "")
states = {}
selector = "app in (%s)" % ','.join(components) if components else None
for dp in kubernetes.list_cluster_deployments(selector):
states.setdefault(dp.name, copy.deepcopy(STATE_TEMPLATE))
dp_st = dp.obj["status"]
states[dp.name]["pod_total"] = dp.obj["spec"]["replicas"]
states[dp.name]["pod_running"] = min(
dp_st.get("availableReplicas", 0), dp_st.get("updatedReplicas", 0))
for job in kubernetes.list_cluster_jobs(selector):
app_name = job.obj["metadata"]["labels"].get("app")
states.setdefault(app_name, copy.deepcopy(STATE_TEMPLATE))
states[app_name]["job_total"] += job.obj["spec"]["completions"]
states[app_name]["job_completed"] += (
job.obj["status"].get("succeeded", 0))
for ss in kubernetes.list_cluster_statefulsets(selector):
states.setdefault(ss.name, copy.deepcopy(STATE_TEMPLATE))
states[ss.name]["pod_total"] = ss.obj["spec"]["replicas"]
for pod in kubernetes.list_cluster_pods(ss.name):
if not pod.obj.get("status", {}).get("containerStatuses"):
continue
if all((cont.get("ready", False) for cont in
pod.obj["status"]["containerStatuses"])):
states[ss.name]["pod_running"] += 1
if CONF.configs.ingress.enabled:
url_template = "https://%s"
if CONF.configs.ingress.get("port"):
url_template += ":%d" % CONF.configs.ingress.port
for ing in kubernetes.list_cluster_ingress():
if components and ing.name not in components:
continue
states.setdefault(ing.name, copy.deepcopy(STATE_TEMPLATE))
for rule in ing.obj['spec']['rules']:
states[ing.name]['links'].append(url_template % rule['host'])
else:
for svc in kubernetes.list_cluster_services():
svc_name = svc.obj["metadata"]["name"]
if components and svc_name not in components:
continue
states.setdefault(svc_name, copy.deepcopy(STATE_TEMPLATE))
for port in svc.obj["spec"]["ports"]:
if port.get('nodePort'):
states[svc_name]["links"].append(EXT_LINK_TEMPLATE.format(
ext_ip=ext_ip,
port=port["nodePort"]))
return states
def show_long_status(components=None):
states = get_pod_states(components)
columns = ("service", "pod", "job", "ready", "links")
formatted_states = []
for state in sorted(states):
formatted_states.append((
state,
"{pod_running}/{pod_total}".format(**states[state]),
"{job_completed}/{job_total}".format(**states[state]),
repr_state(states[state]),
"\n".join(states[state]["links"])))
return columns, formatted_states
def show_short_status(components=None):
states = get_pod_states(components)
if not states:
status = "not deployed"
else:
status = ST_OK if all(map(is_app_ready, states.values())) else ST_WIP
return ("status",), ((status,),)