import { useState, useEffect } from 'react'; import { Box, Typography, Paper, styled, FormControl, InputLabel, Select, MenuItem, Button, Grid, CircularProgress, Chip, Alert, Snackbar, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Checkbox } from '@mui/material'; import ScienceIcon from '@mui/icons-material/Science'; import SpeedIcon from '@mui/icons-material/Speed'; import ComputerIcon from '@mui/icons-material/Computer'; import { stressService } from '../services/stressService'; const StyledPaper = styled(Paper)(({ theme }) => ({ padding: theme.spacing(3), borderRadius: theme.spacing(2), height: '100%', })); const PageTitle = styled(Typography)(({ theme }) => ({ display: 'flex', alignItems: 'center', gap: theme.spacing(1), marginBottom: theme.spacing(3), '& svg': { color: theme.palette.primary.main, }, })); const StressTestingCard = styled(Paper)(({ theme }) => ({ padding: theme.spacing(3), borderRadius: theme.spacing(2), backgroundColor: theme.palette.background.paper, marginBottom: theme.spacing(3), })); const VMSelectionCard = styled(Paper)(({ theme }) => ({ padding: theme.spacing(3), borderRadius: theme.spacing(2), backgroundColor: theme.palette.background.paper, marginBottom: theme.spacing(3), })); const StressLevelChip = styled(Chip)<{ level: 'low' | 'medium' | 'high' }>(({ theme, level }) => ({ borderRadius: theme.spacing(1), fontWeight: 500, backgroundColor: level === 'low' ? theme.palette.success.light : level === 'medium' ? theme.palette.warning.light : theme.palette.error.light, color: level === 'low' ? theme.palette.success.dark : level === 'medium' ? theme.palette.warning.dark : theme.palette.error.dark, })); interface ComputeNode { host_ip: string; hosted_vms: Record; } interface MonitoringResponse { optimization_space: Record; } interface VM { id: string; name: string; ip: string; } const Test = () => { const [stressLevel, setStressLevel] = useState<'low' | 'medium' | 'high'>('low'); const [stressedVMs, setStressedVMs] = useState([]); const [isStressTesting, setIsStressTesting] = useState(false); const [isLoadingStress, setIsLoadingStress] = useState(false); const [alert, setAlert] = useState<{ open: boolean; message: string; severity: 'success' | 'error' | 'info' }>({ open: false, message: '', severity: 'info', }); const [selectedVMs, setSelectedVMs] = useState([]); const [availableVMs, setAvailableVMs] = useState([]); const [isLoadingVMs, setIsLoadingVMs] = useState(false); // Load optimization state from localStorage useEffect(() => { const savedState = localStorage.getItem('optimizationState'); if (savedState) { const { selectedVMs: optimizedVMs } = JSON.parse(savedState); setSelectedVMs(optimizedVMs || []); } }, []); // Fetch available VMs useEffect(() => { const fetchVMs = async () => { setIsLoadingVMs(true); try { const response = await fetch('http://10.150.1.167:8003/prom/monitoring'); const data: MonitoringResponse = await response.json(); // Extract VMs from the optimization space const vms: VM[] = []; if (data.optimization_space) { Object.entries(data.optimization_space).forEach(([computeName, computeData]) => { Object.entries(computeData.hosted_vms).forEach(([vmName, vmIp]) => { vms.push({ id: `${computeName}-${vmName}`, name: vmName, ip: vmIp }); }); }); } setAvailableVMs(vms); } catch (error) { console.error('Error fetching VMs:', error); setAlert({ open: true, message: 'Failed to fetch available VMs', severity: 'error' }); } finally { setIsLoadingVMs(false); } }; fetchVMs(); }, []); // Add status polling for stress test useEffect(() => { let interval: NodeJS.Timeout; const pollStressStatus = async () => { try { if (selectedVMs.length > 0) { const status = await stressService.getStressStatus(selectedVMs); setStressedVMs(status); setIsStressTesting(status.length > 0); } else { setStressedVMs([]); setIsStressTesting(false); } } catch (error) { console.error('Error polling stress status:', error); setStressedVMs([]); setIsStressTesting(false); } }; if (isStressTesting) { interval = setInterval(pollStressStatus, 5000); } return () => { if (interval) { clearInterval(interval); } }; }, [isStressTesting, selectedVMs]); const handleToggleVM = (vmIp: string) => { setSelectedVMs(prev => prev.includes(vmIp) ? prev.filter(ip => ip !== vmIp) : [...prev, vmIp] ); }; const handleStartStressTest = async () => { try { setIsLoadingStress(true); if (selectedVMs.length === 0) { setAlert({ open: true, message: 'Please select at least one VM to stress test', severity: 'error', }); return; } await stressService.startStressTest({ vms: selectedVMs, level: stressLevel, force: true, }); setIsStressTesting(true); setAlert({ open: true, message: 'Stress test started successfully', severity: 'success', }); } catch (error) { console.error('Error in handleStartStressTest:', error); setAlert({ open: true, message: error instanceof Error ? error.message : 'Failed to start stress test', severity: 'error', }); } finally { setIsLoadingStress(false); } }; const handleStopStressTest = async () => { try { setIsLoadingStress(true); await stressService.stopStressTest(selectedVMs); setIsStressTesting(false); setStressedVMs([]); setAlert({ open: true, message: 'Stress test stopped successfully', severity: 'success', }); } catch (error) { console.error('Error in handleStopStressTest:', error); setAlert({ open: true, message: error instanceof Error ? error.message : 'Failed to stop stress test', severity: 'error', }); } finally { setIsLoadingStress(false); } }; return ( Test Page Virtual Machines {isLoadingVMs ? ( ) : ( <> Select VMs from your optimization space to run stress tests. {availableVMs.map((vm) => ( handleToggleVM(vm.ip)} > ))} )} Stress Testing Stress Level {stressedVMs.length > 0 && ( Currently Stressed VMs: {stressedVMs.map((vm) => ( ))} )} setAlert({ ...alert, open: false })} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} > setAlert({ ...alert, open: false })} severity={alert.severity} variant="filled" sx={{ width: '100%' }} > {alert.message} ); }; export default Test;