feat: Visualize active iSCSI sessions

This commit is contained in:
2025-12-10 14:48:16 +00:00
parent 4f28dfbc11
commit 8c9d1cc8d4
8 changed files with 249 additions and 27 deletions

View File

@@ -177,7 +177,8 @@ switch ($action) {
function listTargets() {
$output = [];
$returnCode = 0;
exec('sudo tgtadm --lld iscsi --mode target --op show 2>&1', $output, $returnCode);
// Use absolute path
exec('sudo /usr/sbin/tgtadm --lld iscsi --mode target --op show 2>&1', $output, $returnCode);
if ($returnCode !== 0) {
echo json_encode([
@@ -189,34 +190,86 @@ function listTargets() {
$targets = [];
$currentTarget = null;
$inACLSection = false;
$currentSession = null;
$section = ''; // 'acl', 'nexus', 'account', etc.
foreach ($output as $line) {
// Check for new Target start
if (preg_match('/^Target (\d+): (.+)$/', $line, $matches)) {
// Save previous target and session
if ($currentTarget) {
if ($currentSession) {
$currentTarget['sessions'][] = $currentSession;
$currentSession = null;
}
$targets[] = $currentTarget;
}
$currentTarget = [
'tid' => intval($matches[1]),
'name' => trim($matches[2]),
'luns' => 0,
'acls' => 0
'acls' => 0,
'sessions' => []
];
$inACLSection = false;
} elseif ($currentTarget && preg_match('/^\s+LUN: (\d+)/', $line)) {
$currentTarget['luns']++;
$inACLSection = false;
} elseif ($currentTarget && preg_match('/^\s+ACL information:/', $line)) {
$inACLSection = true;
} elseif ($currentTarget && $inACLSection && preg_match('/^\s+(.+)$/', $line, $matches)) {
$acl = trim($matches[1]);
if (!empty($acl) && !preg_match('/^(Account|I_T nexus|LUN|System)/', $acl)) {
$currentTarget['acls']++;
$section = '';
} elseif ($currentTarget) {
// Check for LUNs (also simple check for count)
if (preg_match('/^\s+LUN: (\d+)/', $line)) {
$currentTarget['luns']++;
// If we were parsing a session, save it as LUN info usually means we left nexus section or are in LUN section
if ($currentSession) {
$currentTarget['sessions'][] = $currentSession;
$currentSession = null;
}
}
// Section Headers
elseif (preg_match('/^\s+ACL information:/', $line)) {
$section = 'acl';
if ($currentSession) { $currentTarget['sessions'][] = $currentSession; $currentSession = null; }
}
elseif (preg_match('/^\s+I_T nexus information:/', $line)) {
$section = 'nexus';
}
elseif (preg_match('/^\s+Account information:/', $line)) {
$section = 'account'; // Ignore or handle if needed
if ($currentSession) { $currentTarget['sessions'][] = $currentSession; $currentSession = null; }
}
// ACL Section Content
elseif ($section === 'acl' && preg_match('/^\s+(.+)$/', $line, $matches)) {
$content = trim($matches[1]);
// Filter out headers if regex matches them by accident (though section logic prevents this usually)
if (!empty($content) && !preg_match('/^(Account|I_T nexus|LUN|System)/', $content)) {
$currentTarget['acls']++;
}
}
// I_T Nexus Section Content (Sessions)
elseif ($section === 'nexus') {
if (preg_match('/^\s+I_T nexus: (\d+)/', $line, $matches)) {
// New session found
if ($currentSession) {
$currentTarget['sessions'][] = $currentSession;
}
$currentSession = [
'nexus_id' => $matches[1],
'initiator' => 'Unknown',
'ip' => 'Unknown'
];
} elseif ($currentSession && preg_match('/^\s+Initiator: (.+)$/', $line, $matches)) {
$currentSession['initiator'] = trim($matches[1]);
} elseif ($currentSession && preg_match('/^\s+IP Address: (.+)$/', $line, $matches)) {
$currentSession['ip'] = trim($matches[1]);
}
}
}
}
// Save last items
if ($currentTarget) {
if ($currentSession) {
$currentTarget['sessions'][] = $currentSession;
}
$targets[] = $currentTarget;
}