can add syncthing public address; refactorings
This commit is contained in:
parent
afb1a2f7bd
commit
9f4084fb53
|
@ -21,7 +21,9 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- sync1config:/config
|
- sync1config:/config
|
||||||
environment:
|
environment:
|
||||||
- SYNCTHING_PUBLIC_HOST=sync1
|
- SYNCTHING_HOSTNAME=sync1
|
||||||
|
- SYNCTHING_ADDRESS=tcp4://sync1
|
||||||
|
- SYNCTHING_DATA_PATH=/data
|
||||||
networks:
|
networks:
|
||||||
- syncnet
|
- syncnet
|
||||||
|
|
||||||
|
@ -45,7 +47,9 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- sync2config:/config
|
- sync2config:/config
|
||||||
environment:
|
environment:
|
||||||
- SYNCTHING_PUBLIC_HOST=sync2
|
- SYNCTHING_HOSTNAME=sync2
|
||||||
|
- SYNCTHING_ADDRESS=tcp4://sync2
|
||||||
|
- SYNCTHING_DATA_PATH=/data
|
||||||
networks:
|
networks:
|
||||||
- syncnet
|
- syncnet
|
||||||
|
|
||||||
|
|
|
@ -2,27 +2,35 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from retrying import retry
|
||||||
|
|
||||||
import syncthing_monitor.config_xml as xml
|
import syncthing_monitor.config_xml as xml
|
||||||
from .etcd_client import EtcdClient
|
from .etcd_client import EtcdClient
|
||||||
from .syncthing_client import SyncthingClient
|
from .syncthing_client import SyncthingClient
|
||||||
|
|
||||||
|
SHARED_FOLDER_ID = "data"
|
||||||
|
SHARED_FOLDER_LABEL = "syncthing_monitor_data"
|
||||||
SYNCTHING_CONFIG_XML_PATH = '/config/config.xml'
|
SYNCTHING_CONFIG_XML_PATH = '/config/config.xml'
|
||||||
SYNCTHING_GUI_PORT = 8384
|
SYNCTHING_GUI_PORT = 8384
|
||||||
ETCD_PORT = 2379
|
ETCD_PORT = 2379
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
program = Program(os.getenv('SYNCTHING_PUBLIC_HOST'),
|
syncthing_mon = SyncthingMonitor(os.getenv('SYNCTHING_HOSTNAME'),
|
||||||
SYNCTHING_CONFIG_XML_PATH, "sync", SYNCTHING_GUI_PORT,
|
os.getenv('SYNCTHING_ADDRESS'),
|
||||||
"etcd", ETCD_PORT)
|
os.getenv('SYNCTHING_DATA_PATH'),
|
||||||
program.start()
|
SYNCTHING_CONFIG_XML_PATH, "sync", SYNCTHING_GUI_PORT,
|
||||||
|
"etcd", ETCD_PORT)
|
||||||
|
syncthing_mon.start()
|
||||||
|
|
||||||
|
|
||||||
class Program:
|
class SyncthingMonitor:
|
||||||
def __init__(self, syncthing_public_host,
|
def __init__(self, syncthing_public_host, syncthing_address, syncthing_data_path,
|
||||||
syncthing_config_xml_path, syncthing_hostname, syncthing_gui_port,
|
syncthing_config_xml_path, syncthing_hostname, syncthing_gui_port,
|
||||||
etcd_hostname, etcd_port):
|
etcd_hostname, etcd_port):
|
||||||
self.syncthing_public_host = syncthing_public_host
|
self.syncthing_hostname = syncthing_public_host
|
||||||
|
self.syncthing_address = syncthing_address
|
||||||
|
self.syncthing_data_path = syncthing_data_path
|
||||||
self.my_device_id = None
|
self.my_device_id = None
|
||||||
self.syncthing = None
|
self.syncthing = None
|
||||||
self.etcd = EtcdClient(etcd_hostname, etcd_port)
|
self.etcd = EtcdClient(etcd_hostname, etcd_port)
|
||||||
|
@ -30,6 +38,7 @@ class Program:
|
||||||
self.syncthing_hostname = syncthing_hostname
|
self.syncthing_hostname = syncthing_hostname
|
||||||
self.syncthing_config_xml_path = syncthing_config_xml_path
|
self.syncthing_config_xml_path = syncthing_config_xml_path
|
||||||
|
|
||||||
|
@retry
|
||||||
def initialize_syncthing(self):
|
def initialize_syncthing(self):
|
||||||
api_key = xml.parse_api_key(self.syncthing_config_xml_path)
|
api_key = xml.parse_api_key(self.syncthing_config_xml_path)
|
||||||
print("Found API Key: {0}".format(api_key))
|
print("Found API Key: {0}".format(api_key))
|
||||||
|
@ -41,20 +50,20 @@ class Program:
|
||||||
|
|
||||||
self.syncthing = SyncthingClient(api_key, self.syncthing_hostname, self.syncthing_gui_port)
|
self.syncthing = SyncthingClient(api_key, self.syncthing_hostname, self.syncthing_gui_port)
|
||||||
|
|
||||||
|
@retry
|
||||||
def start(self):
|
def start(self):
|
||||||
self.initialize_syncthing()
|
self.initialize_syncthing()
|
||||||
|
|
||||||
self.my_device_id = self.syncthing.get_my_device_id()
|
self.my_device_id = self.syncthing.get_my_device_id()
|
||||||
print("Found My Device ID: {0}".format(self.my_device_id))
|
print("Found My Device ID: {0}".format(self.my_device_id))
|
||||||
|
|
||||||
self.syncthing.patch_config()
|
self.syncthing.disable_announce_discovery_and_relay()
|
||||||
self.syncthing.create_shared_folder("GXWxf-3zgnU", "SharedFolder", "/data", [{'id': self.my_device_id}])
|
self.syncthing.create_shared_folder(SHARED_FOLDER_ID, SHARED_FOLDER_LABEL, self.syncthing_data_path,
|
||||||
|
[{'id': self.my_device_id}])
|
||||||
if not self.syncthing.config_is_in_sync():
|
self.syncthing.sync_config()
|
||||||
self.syncthing.restart()
|
|
||||||
|
|
||||||
self.etcd.register_device_update_handler(self.update_devices)
|
self.etcd.register_device_update_handler(self.update_devices)
|
||||||
self.etcd.add_device_to_cluster(self.my_device_id, self.syncthing_public_host)
|
self.etcd.add_device_to_cluster(self.my_device_id, self.syncthing_hostname, self.syncthing_address)
|
||||||
|
|
||||||
self.loop()
|
self.loop()
|
||||||
|
|
||||||
|
@ -68,12 +77,11 @@ class Program:
|
||||||
def update_devices(self, event):
|
def update_devices(self, event):
|
||||||
device_list = self.etcd.get_device_list()
|
device_list = self.etcd.get_device_list()
|
||||||
self.syncthing.add_devices(device_list)
|
self.syncthing.add_devices(device_list)
|
||||||
self.syncthing.create_shared_folder("GXWxf-3zgnU", "SharedFolder", "/data", device_list)
|
self.syncthing.create_shared_folder(SHARED_FOLDER_ID, SHARED_FOLDER_LABEL, self.syncthing_data_path,
|
||||||
|
device_list)
|
||||||
|
self.syncthing.sync_config()
|
||||||
self.syncthing.print_config()
|
self.syncthing.print_config()
|
||||||
|
|
||||||
if not self.syncthing.config_is_in_sync():
|
|
||||||
self.syncthing.restart()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -17,7 +17,7 @@ class EtcdClient:
|
||||||
return json.loads(raw_value)
|
return json.loads(raw_value)
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
def add_device_to_cluster(self, device_id, public_host):
|
def add_device_to_cluster(self, device_id, hostname, address):
|
||||||
with self.etcd.lock('syncthing_monitor'):
|
with self.etcd.lock('syncthing_monitor'):
|
||||||
cluster_info = self.load_cluster_info()
|
cluster_info = self.load_cluster_info()
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ class EtcdClient:
|
||||||
|
|
||||||
new_device = {
|
new_device = {
|
||||||
'id': device_id,
|
'id': device_id,
|
||||||
'hostname': public_host
|
'hostname': hostname,
|
||||||
|
'address': address
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster_info['devices'].append(new_device)
|
cluster_info['devices'].append(new_device)
|
||||||
|
|
|
@ -11,24 +11,30 @@ class SyncthingClient:
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.headers = {'X-API-Key': self.api_key}
|
self.headers = {'X-API-Key': self.api_key}
|
||||||
|
self.myID = None
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
def get_my_device_id(self):
|
def get_my_device_id(self):
|
||||||
response = requests.get(self.make_url("/rest/system/status"), headers=self.headers)
|
if self.myID is None:
|
||||||
return json.loads(response.content)["myID"]
|
response = self.get("/rest/system/status")
|
||||||
|
status = json.loads(response.content)
|
||||||
|
self.myID = status["myID"]
|
||||||
|
|
||||||
|
return self.myID
|
||||||
|
|
||||||
def add_devices(self, device_list):
|
def add_devices(self, device_list):
|
||||||
for device in device_list:
|
for device in device_list:
|
||||||
self.add_device(device)
|
self.add_device(device)
|
||||||
|
|
||||||
def add_device(self, device):
|
def add_device(self, device):
|
||||||
|
device_address = device['address']
|
||||||
|
if device['id'] == self.myID:
|
||||||
|
device_address = 'dynamic'
|
||||||
|
|
||||||
post_data = {
|
post_data = {
|
||||||
"deviceID": device['id'],
|
"deviceID": device['id'],
|
||||||
"name": device['hostname'],
|
"name": device['hostname'],
|
||||||
"addresses": [
|
"addresses": [device_address],
|
||||||
"dynamic",
|
|
||||||
"tcp://{0}:22000".format(device['hostname'])
|
|
||||||
],
|
|
||||||
"compression": "metadata",
|
"compression": "metadata",
|
||||||
"certName": "",
|
"certName": "",
|
||||||
"introducer": False,
|
"introducer": False,
|
||||||
|
@ -43,9 +49,7 @@ class SyncthingClient:
|
||||||
"pendingFolders": [],
|
"pendingFolders": [],
|
||||||
"maxRequestKiB": 0
|
"maxRequestKiB": 0
|
||||||
}
|
}
|
||||||
response = requests.post(self.make_url("/rest/config/devices"),
|
response = self.post("/rest/config/devices", json.dumps(post_data))
|
||||||
headers=self.headers, data=json.dumps(post_data))
|
|
||||||
|
|
||||||
print("Attempt to add device {0} to syncthing: {1}".format(device, response.content))
|
print("Attempt to add device {0} to syncthing: {1}".format(device, response.content))
|
||||||
|
|
||||||
def create_shared_folder(self, folder_id, label, path, devices):
|
def create_shared_folder(self, folder_id, label, path, devices):
|
||||||
|
@ -95,40 +99,52 @@ class SyncthingClient:
|
||||||
}
|
}
|
||||||
post_data['devices'].append(folder_device)
|
post_data['devices'].append(folder_device)
|
||||||
|
|
||||||
response = requests.post(self.make_url("/rest/config/folders"),
|
response = self.post("/rest/config/folders", json.dumps(post_data))
|
||||||
headers=self.headers, data=json.dumps(post_data))
|
|
||||||
|
|
||||||
print("Attempt to add shared folder to syncthing: {0}".format(response.content))
|
print("Attempt to add shared folder to syncthing: {0}".format(response.content))
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
def print_config(self):
|
def print_config(self):
|
||||||
response = requests.get(self.make_url("/rest/config/devices"), headers=self.headers)
|
response = self.get("/rest/config/devices")
|
||||||
print("/rest/config/devices: {0}".format(response.content))
|
print("/rest/config/devices: {0}".format(response.content))
|
||||||
response = requests.get(self.make_url("/rest/config/folders"), headers=self.headers)
|
|
||||||
|
response = self.get("/rest/config/folders")
|
||||||
print("/rest/config/folders: {0}".format(response.content))
|
print("/rest/config/folders: {0}".format(response.content))
|
||||||
response = requests.get(self.make_url("/rest/config/options"), headers=self.headers)
|
|
||||||
|
response = self.get("/rest/config/options")
|
||||||
print("/rest/config/options: {0}".format(response.content))
|
print("/rest/config/options: {0}".format(response.content))
|
||||||
|
|
||||||
|
@retry
|
||||||
def config_is_in_sync(self):
|
def config_is_in_sync(self):
|
||||||
response = requests.get(self.make_url("/rest/config/insync"), headers=self.headers)
|
response = self.get("/rest/config/insync")
|
||||||
return bool(json.loads(response.content)['configInSync'])
|
return bool(json.loads(response.content)['configInSync'])
|
||||||
|
|
||||||
|
@retry
|
||||||
def restart(self):
|
def restart(self):
|
||||||
response = requests.post(self.make_url("/rest/system/restart"), headers=self.headers, data='')
|
response = self.post("/rest/system/restart", '')
|
||||||
print("System reset: {0}".format(response.content))
|
print("System reset: {0}".format(response.content))
|
||||||
|
|
||||||
|
def sync_config(self):
|
||||||
|
if not self.config_is_in_sync():
|
||||||
|
self.restart()
|
||||||
|
|
||||||
@retry
|
def disable_announce_discovery_and_relay(self):
|
||||||
def patch_config(self):
|
|
||||||
config_patch = {
|
config_patch = {
|
||||||
"globalAnnounceEnabled": False,
|
"globalAnnounceEnabled": False,
|
||||||
"localAnnounceEnabled": False,
|
"localAnnounceEnabled": False,
|
||||||
"relaysEnabled": False,
|
"relaysEnabled": False,
|
||||||
"announceLANAddresses": False,
|
"announceLANAddresses": False,
|
||||||
}
|
}
|
||||||
response = requests.patch(self.make_url("/rest/config/options"),
|
response = self.patch("/rest/config/options", json.dumps(config_patch))
|
||||||
headers=self.headers, data=json.dumps(config_patch))
|
|
||||||
print("Patched syncthing configuration: {0}".format(response.content))
|
print("Patched syncthing configuration: {0}".format(response.content))
|
||||||
|
|
||||||
def make_url(self, endpoint):
|
def make_url(self, endpoint):
|
||||||
return "http://{0}:{1}{2}".format(self.host, self.port, endpoint)
|
return "http://{0}:{1}{2}".format(self.host, self.port, endpoint)
|
||||||
|
|
||||||
|
def get(self, endpoint):
|
||||||
|
return requests.get(self.make_url(endpoint), headers=self.headers)
|
||||||
|
|
||||||
|
def post(self, endpoint, data):
|
||||||
|
return requests.post(self.make_url(endpoint), headers=self.headers, data=data)
|
||||||
|
|
||||||
|
def patch(self, endpoint, data):
|
||||||
|
return requests.patch(self.make_url(endpoint), headers=self.headers, data=data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user