forked from BLC/AyposWeb
environment variables fixed
This commit is contained in:
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
# API Configuration
|
||||
VITE_API_URL=http://141.196.166.241:8003
|
||||
|
||||
# Add other environment variables as needed
|
||||
18
README.md
18
README.md
@@ -69,3 +69,21 @@ No additional environment variables are required to run the application in devel
|
||||
## Browser Support
|
||||
|
||||
The application is optimized for modern browsers that support ES6+ features.
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
The application uses environment variables for configuration. To set up your environment:
|
||||
|
||||
1. Copy `.env.example` to `.env`:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Edit `.env` and set your environment variables:
|
||||
```env
|
||||
VITE_API_URL=http://your-api-server:port
|
||||
```
|
||||
|
||||
The following environment variables are available:
|
||||
|
||||
- `VITE_API_URL`: The URL of the API server (default: http://141.196.166.241:8003)
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useEffect } 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';
|
||||
|
||||
interface VM {
|
||||
name: string;
|
||||
@@ -21,7 +22,7 @@ interface VMPlacementData {
|
||||
}>;
|
||||
}
|
||||
|
||||
const ENDPOINT = 'http://141.196.166.241:8003/prom/get_chart_data/vm_placement';
|
||||
const ENDPOINT = `${config.apiUrl}/prom/get_chart_data/vm_placement`;
|
||||
const REFRESH_INTERVAL = 30000; // 30 seconds
|
||||
|
||||
const SummaryStats: React.FC = () => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { VMDetails, GainBeforeData, MigrationAdviceData } from './types';
|
||||
import { config } from '../../config/env';
|
||||
|
||||
const API_BASE_URL = 'http://141.196.166.241:8003';
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
const REFRESH_INTERVAL = 30000; // 30 seconds
|
||||
|
||||
interface GainAfterData {
|
||||
@@ -23,13 +24,20 @@ export const useMigrationData = () => {
|
||||
try {
|
||||
setIsLoadingGainData(true);
|
||||
|
||||
// Log the request start
|
||||
console.log('Fetching migration data...');
|
||||
|
||||
const [gainResponse, migrationResponse] = await Promise.all([
|
||||
fetch(`${API_BASE_URL}/prom/get_chart_data/gain_before`),
|
||||
fetch(`${API_BASE_URL}/prom/get_chart_data/migration`)
|
||||
]);
|
||||
|
||||
// Log the response status
|
||||
console.log('Gain Response Status:', gainResponse.status);
|
||||
console.log('Migration Response Status:', migrationResponse.status);
|
||||
|
||||
if (!gainResponse.ok || !migrationResponse.ok) {
|
||||
throw new Error('Failed to fetch migration data');
|
||||
throw new Error(`Failed to fetch migration data: Gain Status ${gainResponse.status}, Migration Status ${migrationResponse.status}`);
|
||||
}
|
||||
|
||||
const [gainData, migrationData] = await Promise.all([
|
||||
@@ -37,10 +45,26 @@ export const useMigrationData = () => {
|
||||
migrationResponse.json()
|
||||
]);
|
||||
|
||||
// Log the received data
|
||||
console.log('Received Gain Data:', gainData);
|
||||
console.log('Received Migration Data:', migrationData);
|
||||
|
||||
if (!gainData || typeof gainData.cur_power === 'undefined') {
|
||||
console.error('Invalid gain data format:', gainData);
|
||||
throw new Error('Invalid gain data format');
|
||||
}
|
||||
|
||||
if (!migrationData || Object.keys(migrationData).length === 0) {
|
||||
console.warn('No migration advice available:', migrationData);
|
||||
}
|
||||
|
||||
setGainBeforeData(gainData);
|
||||
setMigrationAdviceData(migrationData);
|
||||
} catch (error) {
|
||||
console.error('Error fetching migration data:', error);
|
||||
// Clear the data on error to prevent showing stale data
|
||||
setGainBeforeData(null);
|
||||
setMigrationAdviceData(null);
|
||||
} finally {
|
||||
setIsLoadingGainData(false);
|
||||
}
|
||||
|
||||
9
src/config/env.ts
Normal file
9
src/config/env.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// Environment configuration
|
||||
const getApiUrl = (): string => {
|
||||
// Use environment variable if available, fallback to development URL
|
||||
return import.meta.env.VITE_API_URL || 'http://141.196.166.241:8003';
|
||||
};
|
||||
|
||||
export const config = {
|
||||
apiUrl: getApiUrl(),
|
||||
} as const;
|
||||
9
src/env.d.ts
vendored
Normal file
9
src/env.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_API_URL: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
|
||||
import { Box, Paper, Typography, Fade, useTheme, AppBar, Toolbar, Chip } from '@mui/material';
|
||||
import Plot from 'react-plotly.js';
|
||||
import { Layout, PlotData } from 'plotly.js';
|
||||
import { config } from '../config/env';
|
||||
|
||||
interface DataItem {
|
||||
now_timestamp: string;
|
||||
@@ -15,6 +16,8 @@ interface DataItem {
|
||||
flag: string;
|
||||
}
|
||||
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
|
||||
const Maintenance = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -24,7 +27,7 @@ const Maintenance = () => {
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/get_chart_data/maintenance/20');
|
||||
const response = await fetch(`${API_BASE_URL}/prom/get_chart_data/maintenance/20`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.data && result.data.length > 0) {
|
||||
|
||||
@@ -29,9 +29,10 @@ import ResourceDistributionChart from '../components/Migration/ResourceDistribut
|
||||
import MigrationAdviceCard from '../components/Migration/MigrationAdviceCard';
|
||||
import VerifiedMigration from '../components/Migration/VerifiedMigration';
|
||||
import { useMigrationData, useGainAfterData } from '../components/Migration/hooks';
|
||||
import { config } from '../config/env';
|
||||
|
||||
// Constants
|
||||
const API_BASE_URL = 'http://141.196.166.241:8003';
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
const REFRESH_INTERVAL = 30000; // 30 seconds
|
||||
|
||||
interface VMPlacementData {
|
||||
@@ -412,8 +413,7 @@ const Migration = () => {
|
||||
setMigrationProgress([]);
|
||||
setHasProgress(true);
|
||||
|
||||
// First, send the POST request for migration approval
|
||||
const approvalResponse = await fetch('http://141.196.166.241:8003/prom/migration/decisions4?run_migration=true', {
|
||||
const approvalResponse = await fetch(`${API_BASE_URL}/prom/migration/decisions4?run_migration=true`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'accept': 'application/json'
|
||||
@@ -455,7 +455,7 @@ const Migration = () => {
|
||||
try {
|
||||
setIsProcessing(true);
|
||||
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/migration/decisions4?run_migration=false', {
|
||||
const response = await fetch(`${API_BASE_URL}/prom/migration/decisions4?run_migration=false`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'accept': 'application/json'
|
||||
|
||||
@@ -23,6 +23,9 @@ import ComputerIcon from '@mui/icons-material/Computer';
|
||||
import MemoryIcon from '@mui/icons-material/Memory';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import { config } from '../config/env';
|
||||
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
|
||||
// Define the structure of our tree nodes
|
||||
interface TreeNode {
|
||||
@@ -108,7 +111,7 @@ const MonitoringSystem: React.FC<MonitoringSystemProps> = ({
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/monitoring');
|
||||
const response = await fetch(`${API_BASE_URL}/prom/monitoring`);
|
||||
const result: ApiResponse = await response.json();
|
||||
|
||||
// Create hierarchical structure
|
||||
|
||||
@@ -5,6 +5,7 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import Plot from 'react-plotly.js';
|
||||
import { Layout, PlotData, Config } from 'plotly.js';
|
||||
import { config } from '../config/env';
|
||||
|
||||
// Extend the Window interface to include Google Charts
|
||||
declare global {
|
||||
@@ -26,6 +27,8 @@ interface ChartData {
|
||||
power_future_min: string;
|
||||
}
|
||||
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
|
||||
const Temperature = () => {
|
||||
const theme = useTheme();
|
||||
const [data, setData] = useState<ChartData[]>([]);
|
||||
@@ -52,7 +55,7 @@ const Temperature = () => {
|
||||
setRefreshing(true);
|
||||
}
|
||||
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/get_chart_data/temperature/20');
|
||||
const response = await fetch(`${API_BASE_URL}/prom/get_chart_data/temperature/20`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.data && result.data.length > 0) {
|
||||
@@ -337,7 +340,7 @@ const Temperature = () => {
|
||||
const handleTemperatureDecision = async (approval: boolean) => {
|
||||
try {
|
||||
setDecisionLoading(true);
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/temperature/decisions?approval=' + approval, {
|
||||
const response = await fetch(`${API_BASE_URL}/prom/temperature/decisions?approval=${approval}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
|
||||
@@ -25,6 +25,7 @@ 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';
|
||||
import { config } from '../config/env';
|
||||
|
||||
const PageTitle = styled(Typography)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
@@ -78,6 +79,8 @@ interface VM {
|
||||
ip: string;
|
||||
}
|
||||
|
||||
const API_BASE_URL = config.apiUrl;
|
||||
|
||||
const Test = () => {
|
||||
const [stressLevel, setStressLevel] = useState<'low' | 'medium' | 'high'>('low');
|
||||
const [stressedVMs, setStressedVMs] = useState<string[]>([]);
|
||||
@@ -106,7 +109,7 @@ const Test = () => {
|
||||
const fetchVMs = async () => {
|
||||
setIsLoadingVMs(true);
|
||||
try {
|
||||
const response = await fetch('http://141.196.166.241:8003/prom/monitoring');
|
||||
const response = await fetch(`${API_BASE_URL}/prom/monitoring`);
|
||||
const data: MonitoringResponse = await response.json();
|
||||
|
||||
// Extract VMs from the optimization space
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../config/env';
|
||||
|
||||
const BASE_URL = 'http://141.196.166.241:8003';
|
||||
const BASE_URL = config.apiUrl;
|
||||
|
||||
export interface MonitoringConfig {
|
||||
migration: {
|
||||
@@ -71,11 +72,46 @@ class MonitoringService {
|
||||
throw new Error('Invalid configuration: Missing required sections');
|
||||
}
|
||||
|
||||
// Ensure script_time_unit has valid values
|
||||
if (!config.migration.script_time_unit ||
|
||||
!config.environmental.script_time_unit ||
|
||||
!config.preventive.script_time_unit) {
|
||||
throw new Error('Invalid configuration: Missing script_time_unit values');
|
||||
// Validate migration configuration
|
||||
const { migration } = config;
|
||||
if (!migration.script_time_unit ||
|
||||
!migration.virtual_machine_estimation ||
|
||||
!migration.migration_advices ||
|
||||
!migration.block_list) {
|
||||
throw new Error('Invalid migration configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Validate estimation configuration
|
||||
const { virtual_machine_estimation } = migration;
|
||||
if (!virtual_machine_estimation.estimation_method || !virtual_machine_estimation.model_type) {
|
||||
throw new Error('Invalid estimation configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Validate migration advice configuration
|
||||
const { migration_advices } = migration;
|
||||
if (!migration_advices.migration_method || !migration_advices.migration_weights) {
|
||||
throw new Error('Invalid migration advice configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Validate weights
|
||||
const { migration_weights } = migration_advices;
|
||||
if (!migration_weights.power || !migration_weights.balance ||
|
||||
!migration_weights.overload || !migration_weights.allocation) {
|
||||
throw new Error('Invalid weights configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Validate environmental configuration
|
||||
if (!config.environmental.script_time_unit ||
|
||||
!config.environmental.number_of_steps ||
|
||||
!config.environmental.model_type) {
|
||||
throw new Error('Invalid environmental configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Validate preventive configuration
|
||||
if (!config.preventive.script_time_unit ||
|
||||
!config.preventive.number_of_steps ||
|
||||
!config.preventive.model_type) {
|
||||
throw new Error('Invalid preventive configuration: Missing required fields');
|
||||
}
|
||||
|
||||
// Log the configuration being sent
|
||||
@@ -103,7 +139,9 @@ class MonitoringService {
|
||||
throw new Error(`Failed to start monitoring: Status ${response.status}`);
|
||||
}
|
||||
|
||||
console.log('Monitoring started successfully:', response.data);
|
||||
// Log the response data
|
||||
console.log('Monitoring started successfully. Response:', response.data);
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
if (axios.isCancel(error)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../config/env';
|
||||
|
||||
const BASE_URL = 'http://141.196.166.241:8003';
|
||||
const BASE_URL = config.apiUrl;
|
||||
|
||||
export interface StressConfig {
|
||||
vms: string[];
|
||||
|
||||
Reference in New Issue
Block a user