diff --git a/AD/LocalAdmins.php b/AD/LocalAdmins.php
new file mode 100644
index 0000000..9401cc7
--- /dev/null
+++ b/AD/LocalAdmins.php
@@ -0,0 +1,1582 @@
+
+
+
+
+
+
+
+
+
+ Web Infra Reports IT - Local Administrators
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $server,
+ 'admins' => array_values($serverAdmins)
+ ];
+
+
+ /* ------------------------------------------------------------------------
+ Construction de la vue inverse :
+ admin -> serveurs
+ ------------------------------------------------------------------------ */
+
+ foreach ($serverAdmins as $admin) {
+
+ $key = strtolower($admin);
+
+ if (!isset($admins[$key])) {
+
+ $admins[$key] = [
+ 'name' => $admin,
+ 'servers' => []
+ ];
+
+ }
+
+ /*
+ * Tableau associatif pour éviter les doublons de serveurs.
+ */
+ $admins[$key]['servers'][strtolower($server)] = $server;
+ }
+ }
+
+
+ /* ============================================================================
+ Tri des serveurs
+ ========================================================================== */
+
+ usort($servers, function ($a, $b) {
+
+ return strnatcasecmp(
+ $a['server'],
+ $b['server']
+ );
+
+ });
+
+
+ /* ============================================================================
+ Tri des admins et de leurs serveurs
+ ========================================================================== */
+
+ foreach ($admins as &$admin) {
+
+ natcasesort($admin['servers']);
+
+ $admin['servers'] = array_values($admin['servers']);
+ }
+
+ unset($admin);
+
+
+ uasort($admins, function ($a, $b) {
+
+ return strnatcasecmp(
+ $a['name'],
+ $b['name']
+ );
+
+ });
+
+
+ /* ============================================================================
+ Compteurs
+ ========================================================================== */
+
+ $totalServers = count($servers);
+ $totalAdmins = count($admins);
+
+
+ /*
+ * Nombre total d'affectations :
+ *
+ * 1 admin sur 10 serveurs = 10 affectations.
+ */
+ $totalAssignments = 0;
+
+ foreach ($admins as $admin) {
+ $totalAssignments += count($admin['servers']);
+ }
+
+
+ /* ============================================================================
+ JSON utilisé par la modal
+ ========================================================================== */
+
+ $adminsForJavascript = [];
+
+ foreach ($admins as $key => $admin) {
+
+ $adminsForJavascript[$key] = [
+ 'name' => $admin['name'],
+ 'servers' => $admin['servers']
+ ];
+ }
+
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Local Administrators —
+
+
+ serveurs
+
+
+ —
+
+
+ administrateurs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Serveurs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Administrateurs distincts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Affectations admin / serveur
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Serveurs sans admin renseigné
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Par serveur
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Par administrateur
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Serveur
+
+
+
+ Administrateurs locaux
+
+
+
+ Nombre
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Aucun administrateur renseigné
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Administrateur
+
+
+
+ Serveurs
+
+
+
+ Détail
+
+
+
+
+
+
+
+
+
+ $admin) : ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Voir les serveurs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Astreinte/Liens.php b/Astreinte/Liens.php
new file mode 100644
index 0000000..622ce11
--- /dev/null
+++ b/Astreinte/Liens.php
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+ Web Infra Reports IT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Documents & Suivis
+
+
+
+
+
+
+
+
+
+
Planning d'astreinte = $currentYear ?>
+
Accès direct au fichier SharePoint mis à jour.
+
Ouvrir le Planning
+
+
+
+
+
+
+
+
+
+
+
+
+
Suivi des appels
+
Accès direct à la liste SharePoint de suivi des appels d'astreinte.
+
Ouvrir le Suivi
+
+
+
+
+
+
+
+
Supervision Zabbix
+
+
+
+
+
+
+
+
+
+
Zabbix Infra/Réseau IT
+
Tableaux de bord de l'infrastructure et du réseau IT.
+
Accéder au Zabbix IT
+
+
+
+
+
+
+
+
+
+
+
+
Canaux Teams - Lignes Rouges
+
+
+
+
+
+
+
+
+
+
+
+
Ligne Rouge - DV
+
Incidents système & réseaux Mardyck / Florange.
+
Rejoindre le canal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Astreinte/p1-p2.php b/Astreinte/p1-p2.php
new file mode 100644
index 0000000..2a59df1
--- /dev/null
+++ b/Astreinte/p1-p2.php
@@ -0,0 +1,213 @@
+ $query,
+ 'sysparm_display_value' => 'true',
+ 'sysparm_fields' => 'sys_id,number,assignment_group,short_description,assigned_to,priority,opened_at',
+ 'sysparm_order_byDESC' => 'opened_at',
+ ];
+
+ $url = $baseUrl . '?' . http_build_query($params);
+
+ $ch = curl_init($url);
+
+ curl_setopt_array($ch, [
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_USERPWD => $snowUser . ':' . $snowPass,
+ CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
+ CURLOPT_HTTPHEADER => [
+ 'Accept: application/json'
+ ],
+ CURLOPT_SSL_VERIFYPEER => false,
+ CURLOPT_SSL_VERIFYHOST => 2,
+ CURLOPT_PROXY => 'gateway.zscalertwo.net:10299',
+ ]);
+
+ $response = curl_exec($ch);
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ $error = curl_error($ch);
+
+ curl_close($ch);
+
+ $incidents = [];
+ $errorMessage = null;
+
+ if ($error) {
+ $errorMessage = "Erreur cURL : " . $error;
+ } elseif ($httpCode !== 200) {
+ $errorMessage = "Erreur ServiceNow HTTP " . $httpCode;
+ } else {
+ $data = json_decode($response, true);
+ $incidents = $data['result'] ?? [];
+ }
+?>
+
+
+
+
+
+
+
+
+
+ Web Infra Reports IT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = htmlspecialchars($errorMessage) ?>
+
+
+
+
+
+
+
+
+ = count($incidents) ?> = $w_incFound ?> :
+ P1 : = $p1 ?>
+ P2 : = $p2 ?>
+
+
+
+
+
+
+
+ INC
+ P1/P2
+ = $w_group ?>
+ = $w_assigned ?>
+ = $w_opened ?>
+ Description
+
+
+
+
+
+
+
+
+ Aucun incident trouvé.
+
+
+
+
+
+
+ 'badge bg-danger text-white',
+ str_contains($priority, '2') => 'badge bg-warning text-black',
+ default => 'secondary'
+ };
+ ?>
+
+
+
+
+ = htmlspecialchars($incident['number'] ?? '') ?>
+
+
+
+
+
+ = htmlspecialchars($priority) ?>
+
+
+
+ = htmlspecialchars(snowValue($incident['assignment_group']) ?? '') ?>
+ = htmlspecialchars(snowValue($incident['assigned_to']) ?? '') ?>
+ format('d-m H:i'));
+ }
+ ?>
+ = htmlspecialchars($incident['short_description'] ?? '') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Inventory/Server-Detail.php b/Inventory/Server-Detail.php
index f7cb2ff..d529f54 100644
--- a/Inventory/Server-Detail.php
+++ b/Inventory/Server-Detail.php
@@ -49,11 +49,17 @@
if(is_array($Qw)){
$OSType = "Windows"; $OSName = $Qw[0]['os']; $OSKernel = "";
}else{
- if($Qx[0]['Type'] == "AIX"){
- $OSType = "AIX"; $OSName = "AIX ".$Qx[0]['OSVersion'] ; $OSKernel = "";
- }else{
- $OSType = "Linux"; $OSName = $Qx[0]['Type']." ".$Qx[0]['OSVersion'] ; $OSKernel = $Qx[0]['Kernel'];
- }
+ if(is_array($Qx) ){
+ if ($Qx[0]['Type'] == "AIX") {
+ $OSType = "AIX";
+ $OSName = "AIX " . $Qx[0]['OSVersion'];
+ $OSKernel = "";
+ } else {
+ $OSType = "Linux";
+ $OSName = $Qx[0]['Type'] . " " . $Qx[0]['OSVersion'];
+ $OSKernel = $Qx[0]['Kernel'];
+ }
+ }else{$OSType='';}
}
echo "
";
echo "
";
@@ -62,13 +68,14 @@
if($OSType == "Windows"){
$memory = $Qw[0]['memory']." GB";$cpu = $Qw[0]['cpu'];
}else{
+ if(is_array($Qx) ){
$cpu = $Qx[0]['CPU'] ;
if($OSType == "AIX"){
$memory = round(str_replace(" Mo","",$Qx[0]['Memory'])/1024,2)." GB";
}else{
$memory = $Qvm[0]['Memory'] ?? $Qx[0]['Memory'] ;
}
- }
+ }}
echo "
";
echo "
";
?>
@@ -254,9 +261,12 @@
}
}
if($OSType == "Linux"){
- $date = Invoke_Infra("select Next from rollup_linux_calendar where Server='$server'")[0]['Next'];
- if($date != ""){
- echo " $w_nextRollup : $date ";
+ $dr = Invoke_Infra("select Next from rollup_linux_calendar where Server='$server'");
+ if(is_array($dr)){
+ $date = $dr[0]['Next'];
+ if($date != ""){
+ echo " $w_nextRollup : $date ";
+ }
}
}
?>
diff --git a/Network/dhcp_detail.php b/Network/dhcp_detail.php
index 14f28d2..caf4c88 100644
--- a/Network/dhcp_detail.php
+++ b/Network/dhcp_detail.php
@@ -1,27 +1,29 @@
' . $xmlString;
-}
+ libxml_use_internal_errors(true);
+ $xml = simplexml_load_string($xmlRaw);
+ if ($xml === false) {
+ echo '';
+ foreach (libxml_get_errors() as $e) {
+ echo trim($e->message) . " (ligne {$e->line}, col {$e->column})\n";
+ }
+ libxml_clear_errors();
+ exit;
+ }
-try {
- $xml = new SimpleXMLElement($xmlString);
-} catch (Exception $e) {
- echo "Erreur de parsing XML : " . $e->getMessage();
- exit;
-}
$definitions = [];
foreach ($xml->xpath("//OptionDefinition") as $optDef) {
diff --git a/Network/dhcp_servers.php b/Network/dhcp_servers.php
index 8a02f6f..5a87ce8 100644
--- a/Network/dhcp_servers.php
+++ b/Network/dhcp_servers.php
@@ -3,7 +3,7 @@
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
$ts = date("Y-m-d");
-$serversData = Invoke_Entry01("SELECT Server,TS FROM dump_dhcp where ts ='$ts' order by server asc");
+$serversData = Invoke_Infra("SELECT Server,TS FROM dump_dhcp where ts ='$ts' order by server asc");
?>
diff --git a/Storage/VIO.php b/Storage/VIO.php
new file mode 100644
index 0000000..f6fe90e
--- /dev/null
+++ b/Storage/VIO.php
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+ Infra Reports IT - VIO FC Status
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "dun1vio"
+function vio_couple_key($vio) {
+ return preg_replace('/\d+$/', '', strtolower(trim($vio)));
+}
+
+// Parity of a physical fc port (fcname): "fcs0" -> even, "fcs1" -> odd, ...
+function fcs_parity($fcs) {
+ if (preg_match('/(\d+)\s*$/', $fcs, $m)) {
+ return (intval($m[1]) % 2 === 0) ? 'even' : 'odd';
+ }
+ return 'unknown';
+}
+
+// Balancing rule for one client on a given couple.
+// Returns null when balanced, otherwise a short problem label (FR).
+// Expected: exactly 2 paths, on the 2 different VIOs, one even fcs + one odd fcs.
+function evaluate_client_balance($paths) {
+ $nRows = count($paths);
+ $vios = array_unique(array_map(fn($p) => $p['vio'], $paths));
+ $evens = array_filter($paths, fn($p) => $p['parity'] === 'even');
+ $odds = array_filter($paths, fn($p) => $p['parity'] === 'odd');
+ $unknown = array_filter($paths, fn($p) => $p['parity'] === 'unknown');
+
+ if (count($unknown) > 0) {
+ return 'fcs illisible';
+ }
+ if ($nRows > 2) {
+ return $nRows . ' chemins (plus de 2)';
+ }
+ if (count($vios) < 2) {
+ return $nRows === 1 ? 'présent sur un seul VIO (chemin manquant)' : 'les 2 chemins sur le même VIO';
+ }
+ if (count($evens) !== 1 || count($odds) !== 1) {
+ return 'même parité sur les 2 VIO';
+ }
+ return null;
+}
+
+// Human-readable current distribution of a client's paths.
+function format_client_paths($paths) {
+ $parts = [];
+ foreach ($paths as $p) {
+ $lbl = $p['parity'] === 'even' ? 'pair' : ($p['parity'] === 'odd' ? 'impair' : '?');
+ $parts[] = strtoupper($p['vio']) . ':' . $p['fcname'] . ' (' . $lbl . ')';
+ }
+ return implode(' | ', $parts);
+}
+
+// ---------------------------------------------------------------------------
+// Data: FC status per VIO
+// ---------------------------------------------------------------------------
+
+$vioRows = Invoke_Infra("select * from X_fcstat_vio");
+
+$groupedVios = [];
+if (!empty($vioRows)) {
+ foreach ($vioRows as $row) {
+ $vioName = trim($row['vio'] ?? 'UNKNOWN');
+ $groupedVios[$vioName][] = $row;
+ }
+}
+
+// Group the VIOs into couples, and keep couples + members naturally sorted.
+$couples = [];
+foreach ($groupedVios as $vioName => $rows) {
+ $couples[vio_couple_key($vioName)][$vioName] = $rows;
+}
+ksort($couples, SORT_NATURAL | SORT_FLAG_CASE);
+foreach ($couples as $ck => &$members) {
+ ksort($members, SORT_NATURAL | SORT_FLAG_CASE);
+}
+unset($members);
+
+// ---------------------------------------------------------------------------
+// Data: client mapping for the balancing check
+// Error lines (inerr <> 0 or VIOErr <> 0) are excluded (shown on a dedicated page).
+// ---------------------------------------------------------------------------
+
+$cmdbRows = Invoke_Infra("select vio, clintname, fcname, vfcclientname, inerr, VIOErr from X_cmdb_VIO");
+
+$clientPaths = []; // [coupleKey][clintname][] = ['vio','vfc','parity']
+if (!empty($cmdbRows)) {
+ foreach ($cmdbRows as $r) {
+ if (intval($r['inerr'] ?? 0) !== 0 || intval($r['VIOErr'] ?? 0) !== 0) {
+ continue;
+ }
+
+ $vio = strtolower(trim($r['vio'] ?? ''));
+ $client = trim($r['clintname'] ?? '');
+ if ($vio === '' || $client === '') {
+ continue;
+ }
+
+ // Redundancy is driven by the PHYSICAL fc port on the VIO (fcname),
+ // not by vfcclientname (client-side virtual adapter, almost always fcs0/fcs1).
+ $fcname = strtolower(trim($r['fcname'] ?? ''));
+ $vfc = strtolower(trim($r['vfcclientname'] ?? ''));
+
+ $clientPaths[vio_couple_key($vio)][$client][] = [
+ 'vio' => $vio,
+ 'fcname' => $fcname,
+ 'vfc' => $vfc,
+ 'parity' => fcs_parity($fcname),
+ ];
+ }
+}
+?>
+
+
+
+
+
+
+
+
+
+
+
+ VIO FC Status
+
+
+
+
+
+
+
+
+
+
+
+ $coupleVios): ?>
+
+
+ $rows): ?>
+
+
+
+ getTimestamp() - $tsDate->getTimestamp();
+ $tsIsOld = $diffSeconds > 86400;
+ } catch (Exception $e) {
+ $tsIsOld = false;
+ }
+ }
+
+ if ($typeIsDown || $tsIsOld) {
+ $vioHasAlert = true;
+ break;
+ }
+ }
+
+ $cardColor = $vioHasAlert ? 'red' : 'green';
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ FCS
+ FW
+ Speed
+ Type
+ Uports
+ Last
+ TFrames
+ RFrames
+ Fail
+ LossC
+ LossS
+ InvWord
+ InvCRC
+ TS
+
+
+
+
+
+ getTimestamp() - $tsDate->getTimestamp();
+ $tsIsOld = $diffSeconds > 86400;
+ } catch (Exception $e) {
+ $tsIsOld = false;
+ }
+ }
+
+ $rowClass = ($typeIsDown || $tsIsOld) ? 'table-danger fw-bold' : '';
+ $typeClass = $typeIsDown ? 'bg-danger text-white fw-bold' : '';
+ $tsClass = $tsIsOld ? 'bg-danger text-white fw-bold' : '';
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $paths) {
+ $problem = evaluate_client_balance($paths);
+ if ($problem === null) {
+ $okCount++;
+ } else {
+ $flagged[$clientName] = ['problem' => $problem, 'paths' => $paths];
+ }
+ }
+ ksort($flagged, SORT_NATURAL | SORT_FLAG_CASE);
+
+ $hasData = !empty($coupleClients);
+ $balOk = $hasData && empty($flagged);
+ $balColor = !$hasData ? '#6c757d' : ($balOk ? 'green' : 'red');
+ ?>
+
+
+
+
+
+
+
+
+
+
+ Client
+ Répartition actuelle
+ Problème
+
+
+
+ $info): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No VIO FC data available.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Veeam/veeam.php b/Veeam/veeam.php
new file mode 100644
index 0000000..ccd4771
--- /dev/null
+++ b/Veeam/veeam.php
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+ Web Infra Reports IT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Veeam
+
+
+
+
+
+
+
+
+
+ (GB)
+ Duration
+
+ Message
+
+
+
+
+ DATEADD(DAY, -2, GETDATE()) ";
+ $rs_vms = odbc_exec($conn, $sql_vms);
+ $vmsae = [];
+ while ($row = odbc_fetch_array($rs_vms)){
+ $vmsae[] = $row['name'];
+ }
+
+ $conn = DB_INFRA();
+ $sql = "SELECT * FROM Veeam_Reporting";
+ $rs = odbc_exec($conn, $sql);
+
+ $total = 0; $er = 0; $outdated = 0; $excluded = 0; $success = 0; $war = 0;
+ $reportData = [];
+
+ // 1. Stockage et pré-calcul des poids de tri
+ while ($row = odbc_fetch_array($rs)) {
+ if(!in_array($row['ClientName'], $vmsae)) continue;
+
+ $total++;
+ $rowClass = "";
+ $sortWeight = 4; // Par défaut Success
+ $LastGoodStr = "NEVER";
+
+ // Calcul de l'ancienneté
+ $diffDays = 999;
+ if (!empty($row['LastSuccess']) && $row['LastSuccess'] != '1900-01-01') {
+ $date1 = date_create($row['LastSuccess']);
+ $diff = date_diff($date1, date_create(date("Y-m-d")));
+ $diffDays = (int)$diff->format("%R%a");
+ $LastGoodStr = date('Y-m-d H:i', strtotime($row['LastSuccess'])) . " (".$diffDays."J)";
+ if($diffDays > 365){$LastGoodStr = "NEVER";}
+ }
+
+ // Nouvelle logique de tri hiérarchique
+ if ($row['LastStatus'] == 'Failed' || $row['LastStatus'] == 'Unknown') {
+ $rowClass = "table-danger";
+ $sortWeight = 0;
+ $er++;
+ } elseif ($row['LastStatus'] == 'Warning') {
+ $rowClass = "table-warning";
+ $sortWeight = 1;
+ $war++;
+ } elseif ($diffDays >= 2) {
+ $rowClass = "table-info";
+ $sortWeight = 2;
+ $outdated++;
+ } elseif ($row['LastStatus'] == 'In Progress') {
+ $rowClass = "table-info";
+ $sortWeight = 3;
+ } else {
+ $rowClass = "table-success";
+ $sortWeight = 4;
+ $success++;
+ }
+
+ // On stocke les infos pour le tri PHP multiniveau
+ $reportData[] = [
+ 'sort_weight' => $sortWeight,
+ 'client_name' => $row['ClientName'],
+ 'row_class' => $rowClass,
+ 'last_run' => $row['LastRun'],
+ 'last_status' => $row['LastStatus'],
+ 'last_good' => $LastGoodStr,
+ 'size' => $row['SizeGB'],
+ 'duration' => $row['Duration'],
+ 'policy_name' => $row['PolicyName'],
+ 'error_message'=> $row['ErrorMessage']
+ ];
+ }
+
+ // 2. Tri multiniveau en PHP : par poids d'abord, puis par nom de VM
+ usort($reportData, function($a, $b) {
+ if ($a['sort_weight'] === $b['sort_weight']) {
+ return strcasecmp($a['client_name'], $b['client_name']); // Tri alphabétique A-Z de la VM
+ }
+ return $a['sort_weight'] <=> $b['sort_weight']; // Tri ascendant du poids (0 à 4)
+ });
+
+ // 3. Rendu HTML des lignes triées
+ foreach ($reportData as $data) {
+ echo "";
+ echo "{$data['client_name']} ";
+ echo "" . date('Y-m-d H:i', strtotime($data['last_run'])) . " ";
+ // Conserve le data-sort pour permettre à l'utilisateur de retrier via bootstrap-table s'il clique sur la colonne
+ echo "{$data['last_status']} ";
+ echo "{$data['last_good']} ";
+ echo "{$data['size']} ";
+ echo "{$data['duration']} ";
+ echo "{$data['policy_name']} ";
+ echo "{$data['error_message']} ";
+ echo " ";
+ }
+ ?>
+
+
+
+
+
+
+
+$success OK - $er Error - $war Warning - $outdated $w_outdated )";
+?>
+
+
+
+
+
+
+
+
diff --git a/X/Backups.php b/X/Backups.php
index 8f830ba..7e1920e 100644
--- a/X/Backups.php
+++ b/X/Backups.php
@@ -84,7 +84,7 @@
$ts = $s['ts'];
$lastBackup = (explode(".",$s['LastBackup'] ?? ''))[0];
$location = $s['Location'];
- $log = $s['Log'];
+ $log = $s['Log'] ?? '';
$backuptype = $s['BackupType'];
if(str_contains($log, "Length")) {
diff --git a/X/Inventory.php b/X/Inventory.php
index 4180ad6..dc36e9e 100644
--- a/X/Inventory.php
+++ b/X/Inventory.php
@@ -35,6 +35,7 @@
// Construction de la requête SQL
$base_sql = "SELECT * FROM x_inventory WHERE type IS NOT NULL and hostname not in ('DUNAPPDNIM51','DUNAPPDNIM52') ";
+ $base_sql = "SELECT * FROM x_inventory WHERE hostname not in ('DUNAPPDNIM51','DUNAPPDNIM52') AND hostname not like '%VIO%' ";
$conditions = [];
if ($show_aix) {
@@ -43,7 +44,7 @@
}
if ($show_linux) {
// D'après votre code, tout ce qui n'est pas 'AIX' est considéré comme Linux
- $conditions[] = "type <> 'AIX'";
+ $conditions[] = "(type <> 'AIX' OR type IS NULL)";
}
if (!empty($conditions)) {
@@ -66,6 +67,7 @@
usort($versions, 'version_compare');
$UTDBES = end($versions);
$UTDFI = (Invoke_Infra("select max(Ver) as utd from X_cmdb_Product where Name = 'fi'"))[0]['utd'];
+ $UTDxs = (Invoke_Infra("select max(Ver) as utd from X_cmdb_Product where Name = 'xs'"))[0]['utd'];
?>
@@ -108,6 +110,7 @@
Zabbix
BES
Fusion Inv.
+ XenSam
@@ -319,6 +322,26 @@
} else {
echo " ";
}
+ //XenSam
+ $s1s = $s['xsState'];
+ $s1v = $s['xsVersion'];
+ if ($typ == "LINUX") {
+ if ($s1s == "Y") {
+ if ($s1v == $UTDxs) {
+ echo "$s1v $s1s ";
+ } else {
+ echo "$s1v $s1s ";
+ }
+ } else {
+ if ($s1v == "") {
+ echo "MISSING ";
+ } else {
+ echo "$s1v $s1s ";
+ }
+ }
+ } else {
+ echo " ";
+ }
echo "";
}
diff --git a/X/VIO.php b/X/VIO.php
index 94a44a1..aa4bfdd 100644
--- a/X/VIO.php
+++ b/X/VIO.php
@@ -40,6 +40,14 @@
// 1. DATA PROCESSING (PHP)
// ==========================================
+// Parity of a physical fc port (fcname): "fcs0" -> even, "fcs1" -> odd, ...
+function fcs_parity($fcs) {
+ if (preg_match('/(\d+)\s*$/', strtolower(trim((string)$fcs)), $m)) {
+ return (intval($m[1]) % 2 === 0) ? 'even' : 'odd';
+ }
+ return 'unknown';
+}
+
$rawRows = Invoke_Infra("SELECT * FROM x_cmdb_VIO");
if (!$rawRows) $rawRows = [];
@@ -68,6 +76,7 @@ foreach ($groupedData as $clientKey => $rows) {
$names = []; $inerrs = []; $vfcs = []; $vios = [];
$clintids = []; $fcnames = []; $tss = []; $vioerrs = [];
+ $parities = [];
$hasError = false;
$maxVioErr = 0;
@@ -89,28 +98,45 @@ foreach ($groupedData as $clientKey => $rows) {
$clintids[] = $r['clintid'] ?? '-';
$fcnames[] = $r['fcname'] ?? '-';
$tss[] = $r['ts'] ?? '-';
+
+ // Redundancy check is on the physical fc port (fcname).
+ $parities[] = fcs_parity($r['fcname'] ?? '');
+ }
+
+ // Parity issue = exactly 2 known fcs parities and they are identical
+ // (both even or both odd -> no fabric redundancy).
+ $hasParityIssue = false;
+ $knownParities = array_values(array_filter($parities, fn($p) => $p !== 'unknown'));
+ if (count($knownParities) === 2 && $knownParities[0] === $knownParities[1]) {
+ $hasParityIssue = true;
}
$displayRows[] = [
- 'clintname' => $clientKey,
- 'hasError' => $hasError,
- 'maxVioErr' => $maxVioErr,
- 'name' => implode(' ', $names),
- 'inerr' => implode(' ', $inerrs),
- 'vfc' => implode(' ', $vfcs),
- 'vio' => implode(' ', $vios),
- 'clintid' => implode(' ', $clintids),
- 'fcname' => implode(' ', $fcnames),
- 'ts' => implode(' ', $tss),
- 'vioerr' => implode(' ', $vioerrs),
+ 'clintname' => $clientKey,
+ 'hasError' => $hasError,
+ 'hasParityIssue' => $hasParityIssue,
+ 'maxVioErr' => $maxVioErr,
+ 'name' => implode(' ', $names),
+ 'inerr' => implode(' ', $inerrs),
+ 'vfc' => implode(' ', $vfcs),
+ 'vio' => implode(' ', $vios),
+ 'clintid' => implode(' ', $clintids),
+ 'fcname' => implode(' ', $fcnames),
+ 'ts' => implode(' ', $tss),
+ 'vioerr' => implode(' ', $vioerrs),
];
}
-// 4. Final Sort: 1. Warning (inerr), 2. VIOErr > 0, 3. Alpha
+// 4. Final Sort:
+// 1. Top tier: InErr (table-warning) OR parity issue (table-danger)
+// 2. VIOErr > 0
+// 3. Alpha
usort($displayRows, function($a, $b) {
- // Priority 1: InErr (table-warning)
- if ($a['hasError'] && !$b['hasError']) return -1;
- if (!$a['hasError'] && $b['hasError']) return 1;
+ // Priority 1: warning OR parity issue -> floated to the top, same standing
+ $aTop = $a['hasError'] || $a['hasParityIssue'];
+ $bTop = $b['hasError'] || $b['hasParityIssue'];
+ if ($aTop && !$bTop) return -1;
+ if (!$aTop && $bTop) return 1;
// Priority 2: VIOErr count
if ($a['maxVioErr'] > 0 && $b['maxVioErr'] == 0) return -1;
@@ -155,7 +181,17 @@ usort($displayRows, function($a, $b) {
-
+
@@ -164,7 +200,12 @@ usort($displayRows, function($a, $b) {
-
+
+
+
+ même parité
+
+
@@ -188,4 +229,4 @@ usort($displayRows, function($a, $b) {
$(window).resize(function () { adjustTableHeight(); });
});
-