From ec2cc72a7599ce26da40b4a6f635a8f2faf303bc Mon Sep 17 00:00:00 2001 From: The-Coding-Kiddo Date: Thu, 19 Jun 2025 21:02:02 +0300 Subject: [PATCH] instructions added --- README.md | 70 +++++++++ src/pages/Test.tsx | 378 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+) create mode 100644 src/pages/Test.tsx diff --git a/README.md b/README.md index 9e6e007..5848cdb 100644 --- a/README.md +++ b/README.md @@ -1 +1,71 @@ # AyposWeb + +AyposWeb is a web-based monitoring and management system for virtual machines and compute resources. + +## Prerequisites + +Before running this project, make sure you have the following installed: +- Node.js (version 16 or higher) +- npm (Node Package Manager) + +## Installation + +1. Clone the repository: +```bash +git clone +cd AyposWeb +``` + +2. Install dependencies: +```bash +npm install +``` + +## Development + +To run the project in development mode: + +```bash +npm run dev +``` + +This will start the development server at `http://localhost:5173` (or another available port if 5173 is in use). + +## Building for Production + +To create a production build: + +```bash +npm run build +``` + +The build output will be in the `dist` directory. + +## Running Production Build + +To preview the production build: + +```bash +npm run preview +``` + +## Features + +- Virtual Machine Monitoring +- Stress Testing +- Migration Management +- Temperature Monitoring +- Resource Distribution Visualization +- System Maintenance + +## API Configuration + +The application connects to an API server at `http://141.196.83.136:8003`. Make sure this endpoint is accessible from your network. + +## Environment Variables + +No additional environment variables are required to run the application in development mode. + +## Browser Support + +The application is optimized for modern browsers that support ES6+ features. diff --git a/src/pages/Test.tsx b/src/pages/Test.tsx new file mode 100644 index 0000000..5911f7a --- /dev/null +++ b/src/pages/Test.tsx @@ -0,0 +1,378 @@ +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://141.196.83.136: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; \ No newline at end of file