feat: improve inspur parsing and pci.ids integration
This commit is contained in:
@@ -834,10 +834,29 @@ function renderConfig(data) {
|
||||
|
||||
// GPU tab
|
||||
html += '<div class="config-tab-content" id="config-gpu">';
|
||||
if (config.gpus && config.gpus.length > 0) {
|
||||
const gpuCount = config.gpus.length;
|
||||
const gpuModel = config.gpus[0].model || '-';
|
||||
const gpuVendor = config.gpus[0].manufacturer || '-';
|
||||
const gpuRows = (config.gpus && config.gpus.length > 0)
|
||||
? config.gpus
|
||||
: (config.pcie_devices || [])
|
||||
.filter((p) => {
|
||||
const cls = String(p.device_class || '').toLowerCase();
|
||||
const mfr = String(p.manufacturer || '').toLowerCase();
|
||||
return cls.includes('gpu') || cls.includes('display') || cls.includes('3d') || mfr.includes('nvidia') || p.vendor_id === 0x10de;
|
||||
})
|
||||
.map((p) => ({
|
||||
slot: p.slot,
|
||||
model: p.part_number || p.device_class,
|
||||
manufacturer: p.manufacturer,
|
||||
bdf: p.bdf,
|
||||
serial_number: p.serial_number,
|
||||
current_link_width: p.link_width,
|
||||
current_link_speed: p.link_speed,
|
||||
max_link_width: p.max_link_width,
|
||||
max_link_speed: p.max_link_speed
|
||||
}));
|
||||
if (gpuRows.length > 0) {
|
||||
const gpuCount = gpuRows.length;
|
||||
const gpuModel = gpuRows[0].model || '-';
|
||||
const gpuVendor = gpuRows[0].manufacturer || '-';
|
||||
html += `<h3>Графические процессоры</h3>
|
||||
<div class="section-overview">
|
||||
<div class="stat-box"><span class="stat-value">${gpuCount}</span><span class="stat-label">Всего GPU</span></div>
|
||||
@@ -845,7 +864,7 @@ function renderConfig(data) {
|
||||
<div class="stat-box model-box"><span class="stat-value">${escapeHtml(gpuModel)}</span><span class="stat-label">Модель</span></div>
|
||||
</div>
|
||||
<table class="config-table"><thead><tr><th>Слот</th><th>Модель</th><th>Производитель</th><th>BDF</th><th>PCIe</th><th>Серийный номер</th></tr></thead><tbody>`;
|
||||
config.gpus.forEach(gpu => {
|
||||
gpuRows.forEach(gpu => {
|
||||
const pcieLink = formatPCIeLink(
|
||||
gpu.current_link_width || gpu.link_width,
|
||||
gpu.current_link_speed || gpu.link_speed,
|
||||
@@ -869,11 +888,27 @@ function renderConfig(data) {
|
||||
|
||||
// Network tab
|
||||
html += '<div class="config-tab-content" id="config-network">';
|
||||
if (config.network_adapters && config.network_adapters.length > 0) {
|
||||
const nicCount = config.network_adapters.length;
|
||||
const totalPorts = config.network_adapters.reduce((sum, n) => sum + (n.port_count || 0), 0);
|
||||
const nicTypes = [...new Set(config.network_adapters.map(n => n.port_type).filter(t => t))];
|
||||
const nicModels = [...new Set(config.network_adapters.map(n => n.model).filter(m => m))];
|
||||
const networkRows = (config.network_adapters && config.network_adapters.length > 0)
|
||||
? config.network_adapters
|
||||
: (config.pcie_devices || [])
|
||||
.filter((p) => {
|
||||
const cls = String(p.device_class || '').toLowerCase();
|
||||
return cls.includes('network') || cls.includes('ethernet') || cls.includes('gigabit');
|
||||
})
|
||||
.map((p) => ({
|
||||
location: p.slot,
|
||||
model: p.part_number || p.device_class,
|
||||
vendor: p.manufacturer,
|
||||
port_count: 0,
|
||||
port_type: '',
|
||||
mac_addresses: p.mac_addresses || [],
|
||||
status: p.status || ''
|
||||
}));
|
||||
if (networkRows.length > 0) {
|
||||
const nicCount = networkRows.length;
|
||||
const totalPorts = networkRows.reduce((sum, n) => sum + (n.port_count || 0), 0);
|
||||
const nicTypes = [...new Set(networkRows.map(n => n.port_type).filter(t => t))];
|
||||
const nicModels = [...new Set(networkRows.map(n => n.model).filter(m => m))];
|
||||
html += `<h3>Сетевые адаптеры</h3>
|
||||
<div class="section-overview">
|
||||
<div class="stat-box"><span class="stat-value">${nicCount}</span><span class="stat-label">Адаптеров</span></div>
|
||||
@@ -882,7 +917,7 @@ function renderConfig(data) {
|
||||
<div class="stat-box model-box"><span class="stat-value">${escapeHtml(nicModels.join(', ') || '-')}</span><span class="stat-label">Модели</span></div>
|
||||
</div>
|
||||
<table class="config-table"><thead><tr><th>Слот</th><th>Модель</th><th>Производитель</th><th>Порты</th><th>Тип</th><th>MAC адреса</th><th>Статус</th></tr></thead><tbody>`;
|
||||
config.network_adapters.forEach(nic => {
|
||||
networkRows.forEach(nic => {
|
||||
const macs = nic.mac_addresses ? nic.mac_addresses.join(', ') : '-';
|
||||
const statusClass = nic.status === 'OK' ? '' : 'status-warning';
|
||||
html += `<tr>
|
||||
@@ -906,22 +941,40 @@ function renderConfig(data) {
|
||||
const hasPCIe = config.pcie_devices && config.pcie_devices.length > 0;
|
||||
const hasGPUs = config.gpus && config.gpus.length > 0;
|
||||
if (hasPCIe || hasGPUs) {
|
||||
html += '<h3>PCIe устройства</h3><table class="config-table"><thead><tr><th>Слот</th><th>BDF</th><th>Тип</th><th>Модель</th><th>Производитель</th><th>Vendor:Device ID</th><th>PCIe Link</th></tr></thead><tbody>';
|
||||
html += '<h3>PCIe устройства</h3><table class="config-table"><thead><tr><th>Слот</th><th>BDF</th><th>Модель</th><th>Производитель</th><th>Vendor:Device ID</th><th>PCIe Link</th><th>Серийный номер</th><th>Прошивка</th></tr></thead><tbody>';
|
||||
const pcieRowKey = (slot, bdf, vendorId, deviceId) => {
|
||||
const normalizedBDF = (bdf || '').trim().toLowerCase();
|
||||
if (normalizedBDF) return `bdf:${normalizedBDF}`;
|
||||
const normalizedSlot = (slot || '').trim().toLowerCase();
|
||||
if (normalizedSlot) return `slot:${normalizedSlot}`;
|
||||
return `id:${vendorId || 0}:${deviceId || 0}`;
|
||||
};
|
||||
const gpuByKey = new Map();
|
||||
(config.gpus || []).forEach(gpu => {
|
||||
gpuByKey.set(pcieRowKey(gpu.slot, gpu.bdf, gpu.vendor_id, gpu.device_id), gpu);
|
||||
});
|
||||
|
||||
(config.pcie_devices || []).forEach(p => {
|
||||
const key = pcieRowKey(p.slot, p.bdf, p.vendor_id, p.device_id);
|
||||
const matchedGPU = gpuByKey.get(key);
|
||||
|
||||
const pcieLink = formatPCIeLink(
|
||||
p.link_width,
|
||||
p.link_speed,
|
||||
p.max_link_width,
|
||||
p.max_link_speed
|
||||
);
|
||||
const serial = p.serial_number || (matchedGPU ? matchedGPU.serial_number : '');
|
||||
const firmware = p.firmware || (matchedGPU ? matchedGPU.firmware : '') || findPCIeFirmwareVersion(config.firmware, p);
|
||||
html += `<tr>
|
||||
<td>${escapeHtml(p.slot || '-')}</td>
|
||||
<td><code>${escapeHtml(p.bdf || '-')}</code></td>
|
||||
<td>${escapeHtml(p.device_class || '-')}</td>
|
||||
<td>${escapeHtml(p.part_number || '-')}</td>
|
||||
<td>${escapeHtml(p.manufacturer || '-')}</td>
|
||||
<td><code>${p.vendor_id ? p.vendor_id.toString(16) : '-'}:${p.device_id ? p.device_id.toString(16) : '-'}</code></td>
|
||||
<td>${pcieLink}</td>
|
||||
<td><code>${escapeHtml(serial || '-')}</code></td>
|
||||
<td><code>${escapeHtml(firmware || '-')}</code></td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
@@ -935,11 +988,12 @@ function renderConfig(data) {
|
||||
html += `<tr>
|
||||
<td>${escapeHtml(gpu.slot || '-')}</td>
|
||||
<td><code>${escapeHtml(gpu.bdf || '-')}</code></td>
|
||||
<td>GPU</td>
|
||||
<td>${escapeHtml(gpu.model || gpu.part_number || '-')}</td>
|
||||
<td>${escapeHtml(gpu.manufacturer || '-')}</td>
|
||||
<td><code>${gpu.vendor_id ? gpu.vendor_id.toString(16) : '-'}:${gpu.device_id ? gpu.device_id.toString(16) : '-'}</code></td>
|
||||
<td>${pcieLink}</td>
|
||||
<td><code>${escapeHtml(gpu.serial_number || '-')}</code></td>
|
||||
<td><code>${escapeHtml(gpu.firmware || '-')}</code></td>
|
||||
</tr>`;
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
@@ -1229,6 +1283,24 @@ function escapeHtml(text) {
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function findPCIeFirmwareVersion(firmwareEntries, pcieDevice) {
|
||||
if (!Array.isArray(firmwareEntries) || !pcieDevice) return '';
|
||||
|
||||
const slot = (pcieDevice.slot || '').trim().toLowerCase();
|
||||
const model = (pcieDevice.part_number || '').trim().toLowerCase();
|
||||
if (!slot && !model) return '';
|
||||
|
||||
for (const fw of firmwareEntries) {
|
||||
const name = (fw.device_name || '').trim().toLowerCase();
|
||||
const version = (fw.version || '').trim();
|
||||
if (!name || !version) continue;
|
||||
if (slot && name.includes(slot)) return version;
|
||||
if (model && name.includes(model)) return version;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function formatPCIeLink(currentWidth, currentSpeed, maxWidth, maxSpeed) {
|
||||
// Helper to convert speed to generation
|
||||
function speedToGen(speed) {
|
||||
|
||||
Reference in New Issue
Block a user