114 lines
3.8 KiB
Python
114 lines
3.8 KiB
Python
import configparser
|
|
import json
|
|
import pandas as pd
|
|
import paramiko
|
|
import os
|
|
from tabulate import tabulate
|
|
|
|
|
|
class Cluster:
|
|
def __init__(self, config_path: str, abs_path: str, use_key=False) -> None:
|
|
self.abs_path = abs_path
|
|
self.config = configparser.ConfigParser()
|
|
self.config.read(config_path)
|
|
self.auth_data = dict(self.config.items("CLUSTER"))
|
|
self.ssh = paramiko.SSHClient()
|
|
self.use_key = use_key
|
|
|
|
def connect(self) -> None:
|
|
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
if self.use_key:
|
|
k = paramiko.RSAKey.from_private_key_file(
|
|
os.path.join(self.abs_path, self.auth_data["key"])
|
|
)
|
|
self.ssh.connect(
|
|
hostname=self.auth_data["host"],
|
|
username=self.auth_data["user"],
|
|
pkey=k,
|
|
port=self.auth_data["port"],
|
|
)
|
|
else:
|
|
self.ssh.connect(
|
|
hostname=self.auth_data["host"],
|
|
username=self.auth_data["user"],
|
|
password=self.auth_data["password"],
|
|
port=self.auth_data["port"],
|
|
)
|
|
|
|
def get_state(self) -> list:
|
|
self.connect()
|
|
get_state = "docker node ls"
|
|
try:
|
|
ssh_stdin, ssh_stdout, ssh_stderr = self.ssh.exec_command(get_state)
|
|
except Exception as e:
|
|
print(ssh_stderr)
|
|
print(e)
|
|
return 1
|
|
ssh_stdout.channel.set_combine_stderr(True)
|
|
output = ssh_stdout.readlines()
|
|
self.ssh.close()
|
|
return output
|
|
|
|
def run_ansible_command(self, command: str, use_configs=False) -> list:
|
|
self.connect()
|
|
if use_configs:
|
|
command = "cd devops-configs/ansible && " + command
|
|
print(command)
|
|
try:
|
|
ssh_stdin, ssh_stdout, ssh_stderr = self.ssh.exec_command(command)
|
|
ssh_stdout.channel.set_combine_stderr(True)
|
|
output = ssh_stdout.readlines()
|
|
except Exception as e:
|
|
print(ssh_stderr)
|
|
print(e)
|
|
output = ssh_stderr.readlines()
|
|
|
|
self.ssh.close()
|
|
# formatted_output = "".join(output)
|
|
# return json.loads(formatted_output)
|
|
return output
|
|
|
|
def format_state(self, as_json=False) -> str:
|
|
state = self.get_state()
|
|
keys = state[0].split()
|
|
f_state = []
|
|
try:
|
|
for node in state[1:-1]:
|
|
buffer = {}
|
|
line = node.split()
|
|
for i, j in zip(line, keys):
|
|
buffer.update({j: i})
|
|
f_state.append(buffer)
|
|
df = pd.DataFrame(f_state)
|
|
df = df.rename(columns={"MANAGER": "ENGINE"})
|
|
df["MANAGER"] = ""
|
|
leader = state[-1].split()
|
|
df2 = pd.DataFrame(
|
|
{
|
|
"ID": leader[0],
|
|
"HOSTNAME": leader[2],
|
|
"STATUS": leader[3],
|
|
"AVAILABILITY": leader[4],
|
|
"ENGINE": leader[6],
|
|
"MANAGER": leader[5],
|
|
},
|
|
index=[0],
|
|
)
|
|
df = pd.concat([df, df2], ignore_index=True)
|
|
print(tabulate(df, headers="keys", tablefmt="psql"))
|
|
if not as_json:
|
|
return df.to_json(orient="records")
|
|
else:
|
|
# return tabulate(df, headers="keys", tablefmt="psql")
|
|
return df.to_dict("records")
|
|
except Exception as e:
|
|
print(e)
|
|
return "Format failed"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cluster = Cluster(
|
|
os.path.join(os.path.dirname(os.path.realpath(__file__)), "config.ini"),
|
|
os.path.dirname(os.path.realpath(__file__)),
|
|
)
|
|
print(cluster.format_state())
|