syncthing-monitor/syncthing_monitor/etcd_client.py

73 lines
2.7 KiB
Python
Raw Normal View History

2021-01-29 08:28:35 +00:00
import json
import etcd3 as etcd3
from retrying import retry
2021-01-29 08:28:35 +00:00
CLUSTER_INFO_KEY = '/syncthing_monitor/cluster_info'
class EtcdClient:
def __init__(self, host, port, key=CLUSTER_INFO_KEY):
2021-01-29 10:56:51 +00:00
self.etcd = etcd3.client(host=host, port=port)
self.key = key
2021-01-29 08:28:35 +00:00
@retry(stop_max_delay=60000, wait_fixed=500)
2021-01-29 10:56:51 +00:00
def load_cluster_info(self):
2021-02-02 08:48:19 +00:00
print("Retrieving cluster info from etcd...", flush=True)
raw_value = self.etcd.get(self.key)[0]
2021-01-29 10:56:51 +00:00
if raw_value is None:
return {'devices': []}
return json.loads(raw_value)
2021-01-29 08:28:35 +00:00
def add_device_to_cluster(self, device_id, node_name, address):
2021-01-29 10:56:51 +00:00
with self.etcd.lock('syncthing_monitor'):
cluster_info = self.load_cluster_info()
2021-01-29 08:28:35 +00:00
print("Checking for existing device with node name '{0}'...".format(node_name), flush=True)
existing_device = next(
(device for device in cluster_info['devices'] if node_name in device['node_name']),
None)
if existing_device is not None:
self.update_existing_device(cluster_info, existing_device, device_id, node_name, address)
return
print(
"Existing device not found; Creating new cluster_info entry for node name: '{0}'...".format(node_name),
flush=True)
new_device = {
'id': device_id,
'node_name': node_name,
'address': address
}
cluster_info['devices'].append(new_device)
2021-01-29 09:59:59 +00:00
self.do_cluster_info_update(cluster_info)
def update_existing_device(self, cluster_info, existing_device, device_id, node_name, address):
if device_id == existing_device['id']:
print("Existing device contains up-to-date ID! No need to update.".format(node_name), flush=True)
return
print("Existing device with my node name '{0}' contains stale info! Updating...".format(node_name), flush=True)
existing_device['id'] = device_id
existing_device['address'] = address
self.do_cluster_info_update(cluster_info)
@retry(stop_max_delay=60000, wait_fixed=500)
def do_cluster_info_update(self, cluster_info):
print("Updating etcd value for '{0}': {1}".format(self.key, json.dumps(cluster_info)), flush=True)
self.etcd.put(self.key, json.dumps(cluster_info))
2021-01-29 09:59:59 +00:00
2021-01-29 10:56:51 +00:00
def get_device_list(self):
device_list = self.load_cluster_info()['devices']
2021-02-01 14:50:03 +00:00
print("Obtained device_list devices from etcd: {0}".format(json.dumps(device_list)), flush=True)
2021-01-29 10:56:51 +00:00
return device_list
def register_device_update_handler(self, device_update_handler):
self.etcd.add_watch_callback(self.key, device_update_handler)