devops-configs/master-node/src/cluster.py
2025-10-09 18:42:11 +03:00

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())