add hostname provisioning step
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import ipaddress, os, re, subprocess, tempfile, json, datetime
|
||||
import ipaddress, os, re, subprocess, tempfile, json, datetime, shlex
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import load_dotenv
|
||||
@@ -111,13 +111,66 @@ def step_wireguard_provision(iot_host: str, client_name: str):
|
||||
return {"wg_name": name, "wg_iface": iface}
|
||||
|
||||
def step_set_hostname(iot_host: str, hostname: str | None):
|
||||
"""Placeholder: set hostname on the device via custom script under /home/caster/bumble-auracast/src/server.
|
||||
"""Set hostname on the device by running the project's provision script over SSH.
|
||||
|
||||
Intention: SSH into device and run a script, e.g. /home/caster/bumble-auracast/src/server/set-hostname <hostname>.
|
||||
Currently does nothing.
|
||||
Executes: /home/caster/bumble-auracast/src/auracast/server/provision_domain_hostname.sh <hostname> <domain>
|
||||
Domain is always 'local'. Returns a dict including whether the hostname appears changed.
|
||||
"""
|
||||
print("⏭️ [placeholder] Skipping hostname change (no-op). Intended hostname:", hostname)
|
||||
return {"hostname": hostname}
|
||||
if not hostname:
|
||||
print("⏭️ hostname: no hostname provided, skipping")
|
||||
return {"hostname": None, "changed": False}
|
||||
|
||||
# Known locations where the script might live on the device
|
||||
candidates = [
|
||||
"/home/caster/bumble-auracast/src/auracast/server/provision_domain_hostname.sh",
|
||||
"/home/caster/bumble-auracast/src/server/provision_domain_hostname.sh",
|
||||
]
|
||||
domain = "local"
|
||||
|
||||
# Build remote command. Use sudo since hostname changes typically require elevated privileges.
|
||||
quoted_name = shlex.quote(hostname)
|
||||
quoted_domain = shlex.quote(domain)
|
||||
# Build a remote snippet that picks the first existing candidate and runs it via bash
|
||||
# Using bash avoids executable-bit/shebang issues.
|
||||
remote_candidates = " ".join(shlex.quote(c) for c in candidates)
|
||||
remote = (
|
||||
"set -e\n"
|
||||
f"for p in {remote_candidates}; do\n"
|
||||
" if [ -f \"$p\" ]; then sp=\"$p\"; break; fi\n"
|
||||
"done\n"
|
||||
"if [ -z \"${sp:-}\" ]; then echo 'script not found in any candidate path' >&2; exit 1; fi\n"
|
||||
f"sudo bash \"$sp\" {quoted_name} {quoted_domain}\n"
|
||||
"hostname 2>/dev/null || true\n"
|
||||
)
|
||||
|
||||
ssh_cmd = ["ssh", "-p", str(SSH_PORT)]
|
||||
if SSH_KEY:
|
||||
ssh_cmd += ["-i", SSH_KEY]
|
||||
ssh_cmd += [f"{SSH_USER}@{iot_host}", remote]
|
||||
|
||||
proc = subprocess.run(ssh_cmd, check=False, capture_output=True, text=True)
|
||||
stdout = (proc.stdout or "").strip()
|
||||
stderr = (proc.stderr or "").strip()
|
||||
|
||||
# After running the script, re-check the hostname from the device
|
||||
facts_post = get_device_facts(iot_host)
|
||||
new_hostname = facts_post.get("hostname")
|
||||
|
||||
changed = bool(new_hostname) and (new_hostname == hostname)
|
||||
if proc.returncode != 0:
|
||||
print(f"❌ hostname: remote script failed rc={proc.returncode}: {stderr}")
|
||||
else:
|
||||
print(f"✅ hostname: script executed. device hostname now '{new_hostname}' (rc={proc.returncode})")
|
||||
|
||||
return {
|
||||
"hostname": hostname,
|
||||
"domain": domain,
|
||||
"device_hostname": new_hostname,
|
||||
"changed": changed,
|
||||
"rc": proc.returncode,
|
||||
"out": stdout[-500:], # tail to keep logs compact
|
||||
"err": stderr[-500:],
|
||||
}
|
||||
|
||||
def step_update_app(iot_host: str, services: list[str] | None = None):
|
||||
"""Placeholder: start/enable required system services on the device.
|
||||
|
||||
Reference in New Issue
Block a user