Files
AyposWeb/src/components/Migration/SummaryStats.tsx

102 lines
3.2 KiB
TypeScript

import React, { useState, useEffect, useCallback } from 'react';
import { Grid, Paper, Typography, Box, Divider } from '@mui/material';
import StorageIcon from '@mui/icons-material/Storage';
import ComputerIcon from '@mui/icons-material/Computer';
import { config } from '../../config/env';
import { VMPlacementData } from './types';
import { useSmartPolling } from './hooks';
const ENDPOINT = `${config.apiUrl}/prom/get_chart_data/vm_placement`;
const SummaryStats: React.FC = () => {
const fetchData = useCallback(async (): Promise<VMPlacementData> => {
const response = await fetch(ENDPOINT);
if (!response.ok) {
throw new Error(`Failed to fetch data: ${response.status}`);
}
const jsonData = await response.json();
console.log('SummaryStats - Raw API response:', jsonData);
return jsonData;
}, []);
const { data, pollingInterval } = useSmartPolling<VMPlacementData>(
fetchData,
null,
5000, // min interval: 5 seconds
30000 // max interval: 30 seconds
);
const stats = React.useMemo(() => {
if (!data) {
return {
activeComputes: 0,
totalComputes: 0,
activeVMs: 0,
inactiveVMs: 0,
};
}
// Count from vm_placement object
let totalPMs = Object.keys(data.vm_placement).length;
let activePMs = Object.values(data.vm_placement).filter(pm => pm.power > 0).length;
let totalActiveVMs = 0;
let totalInactiveVMs = 0;
Object.values(data.vm_placement).forEach(pm => {
const vms = Object.values(pm.vms);
totalActiveVMs += vms.filter(vm => vm.state === 'active').length;
totalInactiveVMs += vms.filter(vm => vm.state === 'inactive').length;
});
return {
activeComputes: activePMs,
totalComputes: totalPMs,
activeVMs: totalActiveVMs,
inactiveVMs: totalInactiveVMs,
};
}, [data]);
return (
<Grid item xs={12} md={8}>
<Paper
sx={{
p: 2,
bgcolor: 'background.paper',
boxShadow: 3,
borderRadius: 1,
display: 'flex',
alignItems: 'center',
gap: 3
}}
>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<StorageIcon sx={{ color: 'primary.main', fontSize: 28 }} />
<Box>
<Typography variant="body2" color="textSecondary" sx={{ mb: 0.5 }}>
Compute Nodes
</Typography>
<Typography variant="h6" sx={{ lineHeight: 1, fontWeight: 500 }}>
{stats.activeComputes}/{stats.totalComputes}
</Typography>
</Box>
</Box>
<Divider orientation="vertical" flexItem />
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<ComputerIcon sx={{ color: 'info.main', fontSize: 28 }} />
<Box>
<Typography variant="body2" color="textSecondary" sx={{ mb: 0.5 }}>
Virtual Machines
</Typography>
<Typography variant="h6" sx={{ lineHeight: 1, fontWeight: 500 }}>
{stats.activeVMs}/{stats.activeVMs + stats.inactiveVMs}
</Typography>
</Box>
</Box>
</Paper>
</Grid>
);
};
export default SummaryStats;