fix: save state in deploy_all, discover nodes from systemd

This commit is contained in:
admin 2026-08-03 12:28:01 +00:00
parent d28d77661d
commit 1974fd0293

View file

@ -218,15 +218,18 @@ def remove_node(name):
# ─── Status ──────────────────────────────────────────────────────────── # ─── Status ────────────────────────────────────────────────────────────
def show_status(): def show_status():
s = load_state() # Check systemd for running instances if state is empty
if not s.get("nodes"): r = run("systemctl list-units 'wallarm-node@*' --no-legend 2>/dev/null")
print("No nodes deployed.") if not r.stdout.strip():
print("No nodes running.")
return return
print("\n─── Node Status ───") print("\n─── Node Status ───")
for n in s["nodes"]: for line in r.stdout.strip().split("\n"):
r = run(f"systemctl is-active wallarm-node@{n['name']}") parts = line.split()
status = "" if r.stdout.strip() == "active" else "" if len(parts) >= 4:
print(f" {status} {n['name']}{r.stdout.strip()}{n.get('address','')}") name = parts[0].replace("wallarm-node@", "").replace(".service", "")
status = "" if parts[3] == "running" else ""
print(f" {status} {name}{parts[3]}")
# ─── Tunnel ──────────────────────────────────────────────────────────── # ─── Tunnel ────────────────────────────────────────────────────────────
@ -301,19 +304,34 @@ def deploy_menu():
# ─── Edit Menu ───────────────────────────────────────────────────────── # ─── Edit Menu ─────────────────────────────────────────────────────────
def edit_menu(): def list_nodes():
"""Discover nodes from systemd if state is empty."""
s = load_state() s = load_state()
if not s.get("nodes"): if s.get("nodes"):
return s["nodes"]
# Fall back to systemd discovery
r = run("systemctl list-units 'wallarm-node@*' --no-legend 2>/dev/null")
nodes = []
for line in r.stdout.strip().split("\n"):
parts = line.split()
if len(parts) >= 4:
name = parts[0].replace("wallarm-node@", "").replace(".service", "")
nodes.append({"name": name, "address": "", "upstream_ip": "", "upstream_port": 0})
return nodes
def edit_menu():
nodes = list_nodes()
if not nodes:
print("No nodes.") print("No nodes.")
return return
print("\n─── Edit Node ───") print("\n─── Edit Node ───")
for i, n in enumerate(s["nodes"]): for i, n in enumerate(nodes):
r = run(f"systemctl is-active wallarm-node@{n['name']}") r = run(f"systemctl is-active wallarm-node@{n['name']}")
st = "" if r.stdout.strip() == "active" else "" st = "" if r.stdout.strip() == "active" else ""
print(f" [{i+1}] {st} {n['name']} {n.get('address','')}{n.get('upstream_ip','')}:{n.get('upstream_port','')}") print(f" [{i+1}] {st} {n['name']} {n.get('address','')}{n.get('upstream_ip','')}:{n.get('upstream_port','')}")
c = input("\nSelect: ").strip() c = input("\nSelect: ").strip()
if not c.isdigit(): return if not c.isdigit() or int(c) < 1 or int(c) > len(nodes): return
n = s["nodes"][int(c)-1] n = nodes[int(c)-1]
port = input(f"Port [{n['address'].split(':')[-1]}]: ").strip() port = input(f"Port [{n['address'].split(':')[-1]}]: ").strip()
ip = input(f"Upstream IP [{n.get('upstream_ip','')}]: ").strip() ip = input(f"Upstream IP [{n.get('upstream_ip','')}]: ").strip()
@ -341,18 +359,18 @@ def edit_menu():
# ─── Remove Menu ─────────────────────────────────────────────────────── # ─── Remove Menu ───────────────────────────────────────────────────────
def remove_menu(): def remove_menu():
s = load_state() nodes = list_nodes()
if not s.get("nodes"): if not nodes:
print("No nodes.") print("No nodes.")
return return
print("\n─── Remove Node ───") print("\n─── Remove Node ───")
for i, n in enumerate(s["nodes"]): for i, n in enumerate(nodes):
r = run(f"systemctl is-active wallarm-node@{n['name']}") r = run(f"systemctl is-active wallarm-node@{n['name']}")
st = "" if r.stdout.strip() == "active" else "" st = "" if r.stdout.strip() == "active" else ""
print(f" [{i+1}] {st} {n['name']} {n.get('address','')}") print(f" [{i+1}] {st} {n['name']} {n.get('address','')}")
c = input("\nSelect: ").strip() c = input("\nSelect: ").strip()
if not c.isdigit(): return if not c.isdigit() or int(c) < 1 or int(c) > len(nodes): return
n = s["nodes"][int(c)-1] n = nodes[int(c)-1]
remove_node(n["name"]) remove_node(n["name"])
# ─── Main ────────────────────────────────────────────────────────────── # ─── Main ──────────────────────────────────────────────────────────────
@ -403,10 +421,20 @@ def deploy_all():
print(f"{name} already deployed") print(f"{name} already deployed")
continue continue
print(f"\nDeploying {name}...") print(f"\nDeploying {name}...")
install_node(name, nc["token"], nc.get("cloud","EU"), try:
str(nc.get("port","8081")), nc.get("upstream_ip","127.0.0.1"), install_node(name, nc["token"], nc.get("cloud","EU"),
str(nc.get("upstream_port","80")), nc.get("labels",f"group={name}"), str(nc.get("port","8081")), nc.get("upstream_ip","127.0.0.1"),
nc.get("mode","monitoring")) str(nc.get("upstream_port","80")), nc.get("labels",f"group={name}"),
nc.get("mode","monitoring"))
s = load_state()
s.setdefault("nodes", []).append({
"name": name, "type": "native", "address": f"0.0.0.0:{nc.get('port','8081')}",
"upstream_ip": nc.get("upstream_ip",""), "upstream_port": int(nc.get("upstream_port",80)),
"status": "running", "created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ")
})
save_state(s)
except Exception as e:
print(f"{name}: {e}")
# Clean up # Clean up
if os.path.islink("/opt/wallarm"): if os.path.islink("/opt/wallarm"):
os.remove("/opt/wallarm") os.remove("/opt/wallarm")