findmnt returns 'flash/boot' for a ZFS dataset, not a /dev/* path. lsblk -no pkname then fails, leaving transport as 'unknown'. Resolve ZFS pools to a backing device via zpool before checking transport.
171 lines
7.2 KiB
PHP
171 lines
7.2 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
require_once dirname(__DIR__) . '/include/config.php';
|
|
|
|
$action = $_GET['action'] ?? $_POST['action'] ?? '';
|
|
|
|
// ── Boot device detection ─────────────────────────────────────────────────────
|
|
function vv_storage_detect_transport(): string {
|
|
$src = trim(shell_exec("findmnt -n -o SOURCE /boot 2>/dev/null") ?: '');
|
|
if (!$src) return 'unknown';
|
|
|
|
if (str_starts_with($src, '/dev/')) {
|
|
// Block device partition — walk up to whole disk
|
|
$disk = trim(shell_exec("lsblk -no pkname " . escapeshellarg($src) . " 2>/dev/null") ?: '');
|
|
if (!$disk) return 'unknown';
|
|
} else {
|
|
// ZFS dataset (pool/dataset) — find a backing device via zpool
|
|
$pool = explode('/', $src)[0];
|
|
$dev = trim(shell_exec("zpool list -vHp " . escapeshellarg($pool) . " 2>/dev/null | awk 'NR>1 && \$1~/^[a-z]/ && \$1!~/mirror|raidz|spare/{print \$1; exit}'") ?: '');
|
|
if (!$dev) return 'unknown';
|
|
// Strip partition suffix to get the whole-disk name
|
|
$disk = trim(shell_exec("lsblk -no pkname /dev/" . escapeshellarg($dev) . " 2>/dev/null") ?: $dev);
|
|
}
|
|
|
|
return strtolower(trim(shell_exec("lsblk -dno TRAN /dev/" . escapeshellarg($disk) . " 2>/dev/null") ?: 'unknown'));
|
|
}
|
|
|
|
// ── Current mode status ───────────────────────────────────────────────────────
|
|
if ($action === 'status') {
|
|
$transport = vv_storage_detect_transport();
|
|
$detected = ($transport === 'usb') ? 'flash' : 'internal';
|
|
$currentDir = SCRIPTS_DIR;
|
|
$internalDir = '/boot/config/plugins/varaverk';
|
|
$flashDir = '/mnt/user/appdata/Varaverk';
|
|
$currentMode = ($currentDir === $internalDir) ? 'internal'
|
|
: ($currentDir === $flashDir ? 'flash' : 'custom');
|
|
|
|
$myHost = vv_detect_host();
|
|
$vars = vv_conf_vars();
|
|
$confKey = strtoupper($myHost) . '_STORAGE_MODE_INTERNAL';
|
|
$confVal = $vars[$confKey] ?? null;
|
|
|
|
// Boot device name for display
|
|
$bootSrc = trim(shell_exec("findmnt -n -o SOURCE /boot 2>/dev/null") ?: '');
|
|
$bootDisk = '';
|
|
if (str_starts_with($bootSrc, '/dev/')) {
|
|
$bootDisk = trim(shell_exec("lsblk -no pkname " . escapeshellarg($bootSrc) . " 2>/dev/null") ?: '');
|
|
$bootDisk = $bootDisk ? '/dev/' . $bootDisk : '';
|
|
} elseif ($bootSrc) {
|
|
$bootDisk = $bootSrc; // ZFS: show "flash/boot"
|
|
}
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'current_mode' => $currentMode,
|
|
'current_dir' => $currentDir,
|
|
'internal_dir' => $internalDir,
|
|
'flash_dir' => $flashDir,
|
|
'transport' => $transport,
|
|
'detected' => $detected,
|
|
'boot_disk' => $bootDisk ? '/dev/' . $bootDisk : 'unknown',
|
|
'conf_key' => $confKey,
|
|
'conf_val' => $confVal,
|
|
'array_started'=> is_dir('/mnt/user') && count(scandir('/mnt/user')) > 2,
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// ── Run migration ─────────────────────────────────────────────────────────────
|
|
if ($action === 'migrate' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$to = trim($_POST['to'] ?? '');
|
|
if (!in_array($to, ['internal', 'flash'], true)) {
|
|
echo json_encode(['ok' => false, 'error' => 'Invalid target: must be internal or flash']);
|
|
exit;
|
|
}
|
|
|
|
$script = dirname(__DIR__) . '/Tools/storage_migrate.sh';
|
|
if (!file_exists($script)) {
|
|
echo json_encode(['ok' => false, 'error' => 'storage_migrate.sh not found']);
|
|
exit;
|
|
}
|
|
|
|
set_time_limit(300);
|
|
$output = [];
|
|
$exit = 0;
|
|
exec('bash ' . escapeshellarg($script) . ' --to=' . escapeshellarg($to) . ' 2>&1', $output, $exit);
|
|
|
|
echo json_encode([
|
|
'ok' => $exit === 0,
|
|
'exit' => $exit,
|
|
'output' => implode("\n", $output),
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// ── Auto-detect and write to conf ─────────────────────────────────────────────
|
|
if ($action === 'detect' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$transport = vv_storage_detect_transport();
|
|
$detected = ($transport === 'usb') ? 'false' : 'true';
|
|
$myHost = vv_detect_host();
|
|
$confKey = strtoupper($myHost) . '_STORAGE_MODE_INTERNAL';
|
|
$confFile = $myHost . '.conf';
|
|
|
|
$results = vv_conf_write_changes([[
|
|
'file' => $confFile,
|
|
'key' => $confKey,
|
|
'value' => $detected,
|
|
'type' => 'scalar',
|
|
]]);
|
|
|
|
$ok = !in_array(false, $results, true);
|
|
echo json_encode(['ok' => $ok, 'detected' => $detected, 'transport' => $transport]);
|
|
exit;
|
|
}
|
|
|
|
// ── Unraid API key status ─────────────────────────────────────────────────────
|
|
if ($action === 'api_status') {
|
|
require_once dirname(__DIR__) . '/include/unraid_api.php';
|
|
$localStatus = vv_api_get_status();
|
|
$vars = vv_conf_vars();
|
|
$myHost = vv_detect_host();
|
|
$myId = strtoupper($myHost);
|
|
$hn = trim((string)shell_exec("hostname -s 2>/dev/null | sed 's/^[Uu][Nn][Rr][Aa][Ii][Dd]-//'")) ?: 'Varaverk';
|
|
$localKeyName = 'Varaverk ' . $hn;
|
|
|
|
$hosts = [];
|
|
foreach ($vars as $k => $v) {
|
|
if (!preg_match('/^HOST(\d+)$/', $k, $m) || !$v) continue;
|
|
$id = 'HOST' . $m[1];
|
|
$keyVar = $id . '_UNRAID_API_KEY';
|
|
$key = $vars[$keyVar] ?? '';
|
|
$isLocal = ($id === $myId);
|
|
$hosts[] = [
|
|
'host_id' => $id,
|
|
'hostname' => $v,
|
|
'is_local' => $isLocal,
|
|
'key_var' => $keyVar,
|
|
'key_present' => !empty($key),
|
|
'key_preview' => $key ? substr($key, 0, 8) . '...' . substr($key, -4) : null,
|
|
'api_ok' => $isLocal
|
|
? (!$localStatus['key_missing'] && $localStatus['available'])
|
|
: !empty($key),
|
|
];
|
|
}
|
|
usort($hosts, fn($a, $b) => strcmp($a['host_id'], $b['host_id']));
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'my_id' => $myId,
|
|
'key_name' => $localKeyName,
|
|
'hosts' => $hosts,
|
|
'fallbacks' => $localStatus['fallbacks'],
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// ── Setup/renew API keys (local + all partners via SSH) ───────────────────────
|
|
if ($action === 'setup_apikeys' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$script = SCRIPTS_DIR . '/Plugin/unraid/System_Essentials/unraid_api_key_renew.sh';
|
|
if (!file_exists($script)) {
|
|
echo json_encode(['ok' => false, 'error' => 'unraid_api_key_renew.sh not found']); exit;
|
|
}
|
|
set_time_limit(60);
|
|
$output = []; $exit = 0;
|
|
exec('bash ' . escapeshellarg($script) . ' 2>&1', $output, $exit);
|
|
echo json_encode(['ok' => $exit === 0, 'exit' => $exit, 'output' => implode("\n", $output)]);
|
|
exit;
|
|
}
|
|
|
|
echo json_encode(['ok' => false, 'error' => 'Unknown action']);
|