Add VIO FC Status monitoring page and enhance server inventory filtering

- Introduced `Storage/VIO.php` for monitoring VIO Fibre Channel status with client balancing checks and table sorting.
- Updated `/include/en.php` and `/include/fr.php` to include new translations for ServiceNow and VIO-related navigation elements.
- Improved SQL query and filtering logic in `/X/Inventory.php` to exclude VIO entries and add XenSam version data.
- Enhanced `/reports/heartbeat.php` with a new mechanism for handling server heartbeat status, allowing better granularity and readability.
This commit is contained in:
2026-09-14 10:32:15 +02:00
parent 1f1b7dcd22
commit c185d099d6
25 changed files with 6646 additions and 437 deletions

203
Astreinte/Liens.php Normal file
View File

@@ -0,0 +1,203 @@
<?php
// Récupération dynamique de l'année en cours pour le planning d'astreinte
$currentYear = date('Y');
$planningUrl = "https://arcelormittal.sharepoint.com/sites/AMAL_AIM_INFRASTRUCTURES-EquipesystmeDK/_layouts/15/Doc.aspx?sourcedoc=%7BD5D491BE-0788-4F29-8888-B1F3720F125D%7D&file=Planning%20d%27astreinte%20" . $currentYear . ".xlsx&action=default&mobileredirect=true&DefaultItemOpen=1";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<script src="/js/jquery-3.6.1.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css">
<link rel="stylesheet" href="/css/preloader.css">
<script src="/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap-table.min.css">
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/bootstrap-table-fr-FR.min.js"></script>
<script src="/js/tableExport.min.js"></script>
<script src="/js/bootstrap-table-export.min.js"></script>
<script src="/js/libs/js-xlsx/xlsx.core.min.js"></script>
<style>
/* Petits ajustements de style pour les cartes de liens */
.link-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
/* Force une bordure grise à 50% d'opacité/luminosité, stable en clair et sombre */
border: 1px solid rgba(128, 128, 128, 0.5) !important;
}
.link-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 15px rgba(0,0,0,0.15) !important;
}
.icon-box {
font-size: 2.5rem;
}
</style>
</head>
<body class="bg-light text-dark">
<?php
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
?>
<div class="container-fluid" id="content">
<div class="row flex-nowrap">
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="-ms-flex: 0 0 230px;flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?>
</div>
<div class="col py-3">
<h1><span class="badge text-bg-secondary font-weight-bold" style="width:100%;"><?php echo $nav_links ?? "Ressources & Canaux Utiles"; ?></span></h1>
<div class="container-fluid mt-4">
<h3 class="mb-3 text-muted"><i class="bi bi-file-earmark-spreadsheet-fill text-success"></i> Documents & Suivis</h3>
<div class="row mb-5">
<div class="col-12 col-md-6 col-xl-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-success me-3">
<i class="bi bi-filetype-xlsx"></i>
</div>
<div>
<h5 class="card-title mb-1">Planning d'astreinte <?= $currentYear ?></h5>
<p class="card-text text-muted small mb-2">Accès direct au fichier SharePoint mis à jour.</p>
<a href="<?= $planningUrl ?>" target="_blank" class="btn btn-sm btn-outline-success stretched-link">Ouvrir le Planning</a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-6 col-xl-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-warning me-3">
<i class="bi bi-journal-check"></i>
</div>
<div>
<h5 class="card-title mb-1">Suivi des appels</h5>
<p class="card-text text-muted small mb-2">Accès direct à la liste SharePoint de suivi des appels d'astreinte.</p>
<a href="https://arcelormittal.sharepoint.com/sites/AMAL_AIM_INFRASTRUCTURES-EquipesystmeDK/Lists/Suivi%20des%20appels%20dastreinte/AllItems.aspx" target="_blank" class="btn btn-sm btn-outline-warning stretched-link">Ouvrir le Suivi</a>
</div>
</div>
</div>
</div>
</div>
<h3 class="mb-3 text-muted"><i class="bi bi-activity text-danger"></i> Supervision Zabbix</h3>
<div class="row mb-5">
<div class="col-12 col-md-6 col-xl-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-danger me-3">
<i class="bi bi-speedometer2"></i>
</div>
<div>
<h5 class="card-title mb-1">Zabbix Infra/Réseau IT</h5>
<p class="card-text text-muted small mb-2">Tableaux de bord de l'infrastructure et du réseau IT.</p>
<a href="https://web-zabbix02.appliarmony.net/zabbix.php?action=dashboard.list" target="_blank" class="btn btn-sm btn-outline-danger stretched-link">Accéder au Zabbix IT</a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-6 col-xl-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-danger me-3">
<i class="bi bi-cpu"></i>
</div>
<div>
<h5 class="card-title mb-1">Zabbix Infra OT</h5>
<p class="card-text text-muted small mb-2">Vue du dashboard de l'infrastructure OT (Dunkerque).</p>
<a href="https://web-zabbix.process.dkm/zabbix.php?action=dashboard.view&dashboardid=226&from=now-24h&to=now" target="_blank" class="btn btn-sm btn-outline-danger stretched-link">Accéder au Zabbix Infra OT</a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-6 col-xl-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-danger me-3">
<i class="bi bi-diagram-3"></i>
</div>
<div>
<h5 class="card-title mb-1">Zabbix Réseau OT</h5>
<p class="card-text text-muted small mb-2">Liste des tableaux de bord du réseau OT (Dunkerque).</p>
<a href="https://web-zabbix-netdkm.process.dkm/zabbix/zabbix.php?action=dashboard.list" target="_blank" class="btn btn-sm btn-outline-danger stretched-link">Accéder au Zabbix Réseau OT</a>
</div>
</div>
</div>
</div>
</div>
<h3 class="mb-3 text-muted"><i class="bi bi-microsoft-teams text-primary"></i> Canaux Teams - Lignes Rouges</h3>
<div class="row">
<div class="col-12 col-md-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-primary me-3">
<i class="bi bi-chat-left-text-fill"></i>
</div>
<div>
<h5 class="card-title mb-1">Ligne Rouge - DK</h5>
<p class="card-text text-muted small mb-2">Incidents système & réseaux Dunkerque.</p>
<a href="https://teams.microsoft.com/l/channel/19%3Aff678d50cd6b4628a927c34dbcba9fb2%40thread.tacv2/Ligne%20rouge%20-%20incidents%20syst%C3%A8me%2C%20r%C3%A9seaux%20DK?groupId=794700e9-307f-49cc-9de5-3fd08b933793&tenantId=37cd273a-1cec-4aae-a297-41480ea54f8d" target="_blank" class="btn btn-sm btn-outline-primary stretched-link">Rejoindre le canal</a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-primary me-3">
<i class="bi bi-chat-left-text-fill"></i>
</div>
<div>
<h5 class="card-title mb-1">Ligne Rouge - DV</h5>
<p class="card-text text-muted small mb-2">Incidents système & réseaux Mardyck / Florange.</p>
<a href="https://teams.microsoft.com/l/channel/19%3A06a26356276049d48d90347c0a744434%40thread.tacv2/Ligne%20rouge%20-%20incidents%20syst%C3%A8me%2C%20r%C3%A9seaux%20DV?groupId=794700e9-307f-49cc-9de5-3fd08b933793&tenantId=37cd273a-1cec-4aae-a297-41480ea54f8d" target="_blank" class="btn btn-sm btn-outline-primary stretched-link">Rejoindre le canal</a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-3">
<div class="card h-100 shadow-sm link-card bg-light border-2 border-dark">
<div class="card-body d-flex align-items-center">
<div class="icon-box text-primary me-3">
<i class="bi bi-chat-left-text-fill"></i>
</div>
<div>
<h5 class="card-title mb-1">Ligne Rouge - MK</h5>
<p class="card-text text-muted small mb-2">Incidents système & réseaux Montataire.</p>
<a href="https://teams.microsoft.com/l/channel/19%3Aa5cd4954d623410c8b03115431979788%40thread.tacv2/Ligne%20rouge%20-%20incidents%20syst%C3%A8me%2C%20r%C3%A9seaux%20MK?groupId=794700e9-307f-49cc-9de5-3fd08b933793&tenantId=37cd273a-1cec-4aae-a297-41480ea54f8d" target="_blank" class="btn btn-sm btn-outline-primary stretched-link">Rejoindre le canal</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="/js/switch.js"></script>
</html>
<script src="/js/tableResize2.js"></script>

213
Astreinte/p1-p2.php Normal file
View File

@@ -0,0 +1,213 @@
<?php
// ServiceNow credentials
$snowUser = '9000056';
$snowPass = 'tQNpID6m$';
$baseUrl = 'https://arcelormittalprod.service-now.com/api/now/table/incident';
function snowValue($value): string
{
if (is_array($value)) {
return $value['display_value']
?? $value['value']
?? json_encode($value);
}
return (string)$value;
}
$query = implode('^', [
'active=true',
'incident_stateNOT IN7,6',
'priorityIN1,2',
'opened_atRELATIVEGE@hour@ago@72'
]);
$params = [
'sysparm_query' => $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'] ?? [];
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-t">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<script src="/js/jquery-3.6.1.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css">
<link rel="stylesheet" href="/css/preloader.css">
<script src="/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/css/bootstrap-table.min.css">
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/bootstrap-table-fr-FR.min.js"></script>
<script src="/js/tableExport.min.js"></script>
<script src="/js/bootstrap-table-export.min.js"></script>
<script src="/js/libs/js-xlsx/xlsx.core.min.js"></script>
</head>
<body class="bg-light text-dark">
<?php
include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php";
?>
<div class="container-fluid" id="content">
<div class="row flex-nowrap">
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="-ms-flex: 0 0 230px;flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?>
</div>
<div class="col py-3">
<h1><span class="badge text-bg-secondary font-weight-bold" style="width:100%;"><?php echo $ti_20;?></span></h1>
<div class="container-fluid">
<?php if ($errorMessage): ?>
<div class="alert alert-danger">
<?= htmlspecialchars($errorMessage) ?>
</div>
<?php else: ?>
<?php
$p1 = 0; $p2 = 0;
foreach ($incidents as $inc) {
$p = $inc['priority'] ?? '';
if (str_contains($p, '1')) $p1++;
if (str_contains($p, '2')) $p2++;
}
?>
<div class="alert alert-info text-center">
<div class="d-inline-flex align-items-center justify-content-center gap-3">
<span><strong><?= count($incidents) ?></strong> <?= $w_incFound ?> :</span>
<span class="badge bg-danger text-white">P1 : <?= $p1 ?></span>
<span class="badge bg-warning text-black">P2 : <?= $p2 ?></span>
</div>
</div>
<table class='table table-bordered table-hover table-sm' id='t1' data-toggle="table" data-search="true"
data-show-columns="true" data-export-types="['xlsx','csv','json']"
data-show-export="true" data-sortable="true" data-sort-name="Opened" data-sort-order="desc">
<thead class="table-dark">
<tr>
<th data-field="Ticket" data-sortable="true">INC</th>
<th data-field="Priority" data-sortable="true">P1/P2</th>
<th data-field="Group" data-sortable="true"><?= $w_group ?></th>
<th data-field="Assigned" data-sortable="true"><?= $w_assigned ?></th>
<th data-field="Opened" data-sortable="true"><?= $w_opened ?></th>
<th data-field="Descr" data-sortable="true">Description</th>
</tr>
</thead>
<tbody>
<?php if (empty($incidents)): ?>
<tr>
<td colspan="6" class="text-center text-muted p-4">
Aucun incident trouvé.
</td>
</tr>
<?php else: ?>
<?php foreach ($incidents as $incident): ?>
<?php
$priority = $incident['priority'] ?? '';
$badgeClass = match (true) {
str_contains($priority, '1') => 'badge bg-danger text-white',
str_contains($priority, '2') => 'badge bg-warning text-black',
default => 'secondary'
};
?>
<tr>
<td>
<strong><a
href="https://arcelormittalprod.service-now.com/incident.do?sys_id=<?= urlencode($incident['sys_id']) ?>"
target="_blank"
class="fw-bold text-decoration-none"
>
<?= htmlspecialchars($incident['number'] ?? '') ?>
</a></strong>
</td>
<td>
<span class="<?= $badgeClass ?>">
<?= htmlspecialchars($priority) ?>
</span>
</td>
<td><small><?= htmlspecialchars(snowValue($incident['assignment_group']) ?? '') ?></small></td>
<td><small><?= htmlspecialchars(snowValue($incident['assigned_to']) ?? '') ?></small></td>
<td><?php
if (!empty($incident['opened_at'])) {
$date = new DateTime($incident['opened_at']);
echo htmlspecialchars($date->format('d-m H:i'));
}
?></td>
<td><?= htmlspecialchars($incident['short_description'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</body>
<script src="/js/switch.js"></script>
</HTML>
<script src="/js/tableResize2.js"></script>