133 lines
5.0 KiB
Python
133 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Simple ZeroTier helper for joining networks and discovering peers.
|
|
|
|
Usage:
|
|
python scripts/zerotier_setup.py --join <network_id>
|
|
python scripts/zerotier_setup.py --list
|
|
python scripts/zerotier_setup.py --discover <network_id>
|
|
|
|
This is a convenience tool to exercise the API/zerotier.py functionality while
|
|
prototyping and bringing up remote peers for store testing.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from SYS.logger import log
|
|
|
|
try:
|
|
from API import zerotier
|
|
except Exception:
|
|
zerotier = None
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description="ZeroTier helper for Medios-Macina")
|
|
parser.add_argument("--list", action="store_true", help="List local ZeroTier networks")
|
|
parser.add_argument("--join", type=str, help="Join a ZeroTier network by ID")
|
|
parser.add_argument("--leave", type=str, help="Leave a ZeroTier network by ID")
|
|
parser.add_argument("--discover", type=str, help="Discover services on a ZeroTier network ID")
|
|
parser.add_argument("--upload", type=str, help="Upload a file to a discovered 'remote' service on this ZeroTier network ID")
|
|
parser.add_argument("--file", type=str, help="Local file to upload (used with --upload)")
|
|
parser.add_argument("--tag", action="append", help="Tag to attach (repeatable)", default=[])
|
|
parser.add_argument("--url", action="append", help="URL to associate (repeatable)", default=[])
|
|
parser.add_argument("--api-key", type=str, help="API key to use for uploads (optional)")
|
|
parser.add_argument("--json", action="store_true", help="Output JSON when appropriate")
|
|
args = parser.parse_args(argv)
|
|
|
|
if zerotier is None:
|
|
log("ZeroTier API module not available; ensure API/zerotier.py is importable and zerotier or zerotier-cli is installed")
|
|
return 1
|
|
|
|
if args.list:
|
|
nets = zerotier.list_networks()
|
|
if args.json:
|
|
print(json.dumps([n.__dict__ for n in nets], indent=2))
|
|
else:
|
|
for n in nets:
|
|
print(f"{n.id}\t{name:=}{n.name}\t{n.status}\t{n.assigned_addresses}")
|
|
return 0
|
|
|
|
if args.join:
|
|
try:
|
|
ok = zerotier.join_network(args.join)
|
|
print("Joined" if ok else "Failed to join")
|
|
return 0 if ok else 2
|
|
except Exception as exc:
|
|
log(f"Join failed: {exc}")
|
|
print(f"Join failed: {exc}")
|
|
return 2
|
|
|
|
if args.leave:
|
|
try:
|
|
ok = zerotier.leave_network(args.leave)
|
|
print("Left" if ok else "Failed to leave")
|
|
return 0 if ok else 2
|
|
except Exception as exc:
|
|
log(f"Leave failed: {exc}")
|
|
print(f"Leave failed: {exc}")
|
|
return 2
|
|
|
|
if args.discover:
|
|
probes = zerotier.discover_services_on_network(args.discover)
|
|
if args.json:
|
|
print(json.dumps([p.__dict__ for p in probes], indent=2, default=str))
|
|
else:
|
|
for p in probes:
|
|
print(f"{p.address}:{p.port}{p.path} -> status={p.status_code} hint={p.service_hint}")
|
|
return 0
|
|
|
|
if args.upload:
|
|
# Upload a file to the first discovered remote service on the network
|
|
if not args.file:
|
|
print("ERROR: --file is required for --upload")
|
|
return 2
|
|
|
|
probe = zerotier.find_peer_service(args.upload, service_hint="remote")
|
|
if not probe:
|
|
print("No remote service found on network")
|
|
return 2
|
|
|
|
base = f"http://{probe.address}:{probe.port}"
|
|
try:
|
|
import httpx
|
|
url = base.rstrip("/") + "/files/upload"
|
|
headers = {}
|
|
if args.api_key:
|
|
headers["X-API-Key"] = args.api_key
|
|
with open(args.file, "rb") as fh:
|
|
files = {"file": (Path(args.file).name, fh)}
|
|
data = []
|
|
for t in (args.tag or []):
|
|
data.append(("tag", t))
|
|
for u in (args.url or []):
|
|
data.append(("url", u))
|
|
resp = httpx.post(url, files=files, data=data, headers=headers, timeout=30)
|
|
print(resp.status_code, resp.text)
|
|
return 0 if resp.status_code in (200, 201) else 2
|
|
except Exception:
|
|
import requests
|
|
url = base.rstrip("/") + "/files/upload"
|
|
headers = {}
|
|
if args.api_key:
|
|
headers["X-API-Key"] = args.api_key
|
|
with open(args.file, "rb") as fh:
|
|
files = {"file": (Path(args.file).name, fh)}
|
|
data = []
|
|
for t in (args.tag or []):
|
|
data.append(("tag", t))
|
|
for u in (args.url or []):
|
|
data.append(("url", u))
|
|
resp = requests.post(url, files=files, data=data, headers=headers, timeout=30)
|
|
print(resp.status_code, resp.text)
|
|
return 0 if resp.status_code in (200, 201) else 2
|
|
|
|
parser.print_help()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |