-
Notifications
You must be signed in to change notification settings - Fork 0
/
sync.py
executable file
·143 lines (116 loc) · 4.39 KB
/
sync.py
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python3
import time
import paramiko
import threading
import yaml
def string_to_float(data):
return float(data.strip().split(' ', 2)[0].strip())
def parse_top_string(data):
rows = data.splitlines()
load = rows[0].split('load average: ', 2)[1]
cpu_data = rows[1].split(':', 2)[1].strip().split(',')
cpu_percent = 100.0 - float(cpu_data[3].strip().split(' ', 2)[0].strip()) - float(cpu_data[7].strip().split(' ', 2)[0].strip())
if (cpu_percent < 0):
cpu_percent = 0
ram_unit, ram_data = rows[2].split(':', 2)
ram_factor = 1
if ram_unit[0] == 'K':
ram_factor = 1024 * 1024
elif ram_unit[0] == 'M':
ram_factor = 1024
elif ram_unit[0] == 'G':
ram_factor = 1
ram_data = ram_data.strip().split(',')
ram_total = float(ram_data[0].strip().split(' ', 2)[0].strip()) / ram_factor
ram_free = float(ram_data[1].strip().split(' ', 2)[0].strip()) / ram_factor
return load, cpu_percent, ram_total, ram_free
class Host(threading.Thread):
def __init__(self, host, port, user, keys, host_length):
threading.Thread.__init__(self)
self.host = host
self.port = port
self.user = user
self.keys = keys
self.host_length = host_length
self.status = 'none'
self.row = ''
def render_status(self):
if self.status == 'none':
return '[ .. ] '
elif self.status == 'ok':
return '[ \033[92mok\033[0m ] '
elif self.status == 'fail':
return '[\033[91mfail\033[0m] '
def render_row(self):
self.row = self.render_status() + self.host.ljust(self.host_length + 3) + self.user
def run(self):
try:
self.status = 'none'
self.render_row()
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
self.client.connect(self.host, port = self.port, username = self.user, timeout = 1)
self.client.exec_command('echo "###\n# Warning this file has been generated and will be overwritten!\n###\n' + '\n'.join(self.keys) + '" > ~/.ssh/authorized_keys2')
self.status = 'ok'
except Exception as e:
#print(e)
self.status = 'fail'
self.render_row()
def read_config():
with open('config.yaml', 'r') as stream:
return yaml.safe_load(stream)
def main():
config = read_config()
hosts = []
host_length = 0
for host in config['hosts']:
if len(host['host']) > host_length:
host_length = len(host['host'])
#print('Host'.center(7 + host_length + 3) + 'User')
config_hosts = config['hosts']
config_hosts.sort(key=lambda x: x['host'])
for i, host in enumerate(config_hosts):
for user_name, user_data in host['users'].items():
host_keys = []
if 'groups' in user_data.keys():
for group in user_data['groups']:
if group not in config['groups'].keys():
print('WARNING: Key-group "' + group + '" not found!')
continue
for key_name in config['groups'][group]:
host_keys.append(config['keys'][key_name])
if 'keys' in user_data.keys():
for key_name in user_data['keys']:
if key_name not in config['keys'].keys():
print('WARNING: Key "' + key_name + '" not found!')
continue
host_keys.append(config['keys'][key_name])
host_keys = list(set(host_keys)) # Filter duplicates
if not host_keys:
continue
if not 'port' in host:
host['port'] = 22
hosts.append(Host(host['host'], host['port'] or 22, user_name, host_keys, host_length))
for host in hosts:
host.start()
end = False
first = True
while True:
screen = []
for host in hosts:
screen.append(host.row)
if first:
first = False
else:
print('\033[' + str(len(screen)) + 'F', end = '')
print('\n'.join(screen))
if end:
break
states = []
for host in hosts:
states.append(not host.is_alive())
if all(states):
end = True
time.sleep(0.1)
if __name__ == '__main__':
main()