mirror of
https://github.com/Jerryplusy/AI-powered-switches.git
synced 2025-10-14 17:59:19 +00:00
Compare commits
No commits in common. "c74d55e62bbe7c94326ff42921276ce065752543" and "da5743e27a8e934d42ea9adbb9a3fd7ff7efac05" have entirely different histories.
c74d55e62b
...
da5743e27a
@ -1,4 +1,3 @@
|
|||||||
import socket
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from fastapi import (APIRouter, HTTPException, Response, WebSocket, WebSocketDisconnect)
|
from fastapi import (APIRouter, HTTPException, Response, WebSocket, WebSocketDisconnect)
|
||||||
from typing import List
|
from typing import List
|
||||||
@ -8,8 +7,6 @@ from fastapi.responses import HTMLResponse
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import io
|
import io
|
||||||
import base64
|
import base64
|
||||||
import psutil
|
|
||||||
import ipaddress
|
|
||||||
|
|
||||||
from ..services.switch_traffic_monitor import get_switch_monitor
|
from ..services.switch_traffic_monitor import get_switch_monitor
|
||||||
from ..utils import logger
|
from ..utils import logger
|
||||||
@ -274,7 +271,7 @@ async def get_switch_current_traffic(switch_ip: str, interface: str = None):
|
|||||||
try:
|
try:
|
||||||
monitor = get_switch_monitor(switch_ip)
|
monitor = get_switch_monitor(switch_ip)
|
||||||
|
|
||||||
|
# 如果没有指定接口,获取所有接口的流量
|
||||||
if not interface:
|
if not interface:
|
||||||
traffic_data = {}
|
traffic_data = {}
|
||||||
for iface in monitor.interface_oids:
|
for iface in monitor.interface_oids:
|
||||||
@ -284,6 +281,7 @@ async def get_switch_current_traffic(switch_ip: str, interface: str = None):
|
|||||||
"traffic": traffic_data
|
"traffic": traffic_data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 获取指定接口的流量
|
||||||
return await get_interface_current_traffic(switch_ip, interface)
|
return await get_interface_current_traffic(switch_ip, interface)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"获取交换机流量失败: {str(e)}")
|
logger.error(f"获取交换机流量失败: {str(e)}")
|
||||||
@ -294,7 +292,7 @@ async def get_interface_current_traffic(switch_ip: str, interface: str) -> dict:
|
|||||||
"""获取指定交换机接口的当前流量数据"""
|
"""获取指定交换机接口的当前流量数据"""
|
||||||
try:
|
try:
|
||||||
with SessionLocal() as session:
|
with SessionLocal() as session:
|
||||||
|
# 获取最新记录
|
||||||
record = session.query(SwitchTrafficRecord).filter(
|
record = session.query(SwitchTrafficRecord).filter(
|
||||||
SwitchTrafficRecord.switch_ip == switch_ip,
|
SwitchTrafficRecord.switch_ip == switch_ip,
|
||||||
SwitchTrafficRecord.interface == interface
|
SwitchTrafficRecord.interface == interface
|
||||||
@ -329,21 +327,26 @@ async def get_switch_traffic_history(switch_ip: str, interface: str = None, minu
|
|||||||
try:
|
try:
|
||||||
monitor = get_switch_monitor(switch_ip)
|
monitor = get_switch_monitor(switch_ip)
|
||||||
|
|
||||||
|
# 如果没有指定接口,返回所有接口的历史数据
|
||||||
if not interface:
|
if not interface:
|
||||||
return {
|
return {
|
||||||
"switch_ip": switch_ip,
|
"switch_ip": switch_ip,
|
||||||
"history": monitor.get_traffic_history()
|
"history": monitor.get_traffic_history()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 获取指定接口的历史数据
|
||||||
with SessionLocal() as session:
|
with SessionLocal() as session:
|
||||||
|
# 计算时间范围
|
||||||
time_threshold = datetime.now() - timedelta(minutes=minutes)
|
time_threshold = datetime.now() - timedelta(minutes=minutes)
|
||||||
|
|
||||||
|
# 查询历史记录
|
||||||
records = session.query(SwitchTrafficRecord).filter(
|
records = session.query(SwitchTrafficRecord).filter(
|
||||||
SwitchTrafficRecord.switch_ip == switch_ip,
|
SwitchTrafficRecord.switch_ip == switch_ip,
|
||||||
SwitchTrafficRecord.interface == interface,
|
SwitchTrafficRecord.interface == interface,
|
||||||
SwitchTrafficRecord.timestamp >= time_threshold
|
SwitchTrafficRecord.timestamp >= time_threshold
|
||||||
).order_by(SwitchTrafficRecord.timestamp.asc()).all()
|
).order_by(SwitchTrafficRecord.timestamp.asc()).all()
|
||||||
|
|
||||||
|
# 提取数据
|
||||||
history_data = {
|
history_data = {
|
||||||
"in": [record.rate_in for record in records],
|
"in": [record.rate_in for record in records],
|
||||||
"out": [record.rate_out for record in records],
|
"out": [record.rate_out for record in records],
|
||||||
@ -368,10 +371,13 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa
|
|||||||
monitor = get_switch_monitor(switch_ip)
|
monitor = get_switch_monitor(switch_ip)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
# 获取流量数据
|
||||||
if interface:
|
if interface:
|
||||||
|
# 单个接口
|
||||||
traffic_data = await get_interface_current_traffic(switch_ip, interface)
|
traffic_data = await get_interface_current_traffic(switch_ip, interface)
|
||||||
await websocket.send_json(traffic_data)
|
await websocket.send_json(traffic_data)
|
||||||
else:
|
else:
|
||||||
|
# 所有接口
|
||||||
traffic_data = {}
|
traffic_data = {}
|
||||||
for iface in monitor.interface_oids:
|
for iface in monitor.interface_oids:
|
||||||
traffic_data[iface] = await get_interface_current_traffic(switch_ip, iface)
|
traffic_data[iface] = await get_interface_current_traffic(switch_ip, iface)
|
||||||
@ -381,6 +387,7 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa
|
|||||||
"traffic": traffic_data
|
"traffic": traffic_data
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# 每秒更新一次
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
except WebSocketDisconnect:
|
except WebSocketDisconnect:
|
||||||
logger.info(f"客户端断开交换机流量连接: {switch_ip}")
|
logger.info(f"客户端断开交换机流量连接: {switch_ip}")
|
||||||
@ -388,17 +395,22 @@ async def websocket_switch_traffic(websocket: WebSocket, switch_ip: str, interfa
|
|||||||
logger.error(f"交换机流量WebSocket错误: {str(e)}")
|
logger.error(f"交换机流量WebSocket错误: {str(e)}")
|
||||||
await websocket.close(code=1011, reason=str(e))
|
await websocket.close(code=1011, reason=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
# 交换机流量可视化
|
||||||
@router.get("/traffic/switch/plot", response_class=HTMLResponse, summary="交换机流量可视化")
|
@router.get("/traffic/switch/plot", response_class=HTMLResponse, summary="交换机流量可视化")
|
||||||
async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10):
|
async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10):
|
||||||
"""生成交换机流量图表"""
|
"""生成交换机流量图表"""
|
||||||
try:
|
try:
|
||||||
|
# 获取历史数据
|
||||||
history = await get_switch_traffic_history(switch_ip, interface, minutes)
|
history = await get_switch_traffic_history(switch_ip, interface, minutes)
|
||||||
history_data = history["history"]
|
history_data = history["history"]
|
||||||
|
|
||||||
|
# 提取数据点
|
||||||
time_points = [datetime.fromisoformat(t) for t in history_data["time"]]
|
time_points = [datetime.fromisoformat(t) for t in history_data["time"]]
|
||||||
in_rates = history_data["in"]
|
in_rates = history_data["in"]
|
||||||
out_rates = history_data["out"]
|
out_rates = history_data["out"]
|
||||||
|
|
||||||
|
# 创建图表
|
||||||
plt.figure(figsize=(12, 6))
|
plt.figure(figsize=(12, 6))
|
||||||
plt.plot(time_points, in_rates, label="流入流量 (B/s)")
|
plt.plot(time_points, in_rates, label="流入流量 (B/s)")
|
||||||
plt.plot(time_points, out_rates, label="流出流量 (B/s)")
|
plt.plot(time_points, out_rates, label="流出流量 (B/s)")
|
||||||
@ -409,6 +421,8 @@ async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10)
|
|||||||
plt.grid(True)
|
plt.grid(True)
|
||||||
plt.xticks(rotation=45)
|
plt.xticks(rotation=45)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
|
||||||
|
# 转换为HTML图像
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
plt.savefig(buf, format="png")
|
plt.savefig(buf, format="png")
|
||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
@ -436,29 +450,3 @@ async def plot_switch_traffic(switch_ip: str, interface: str, minutes: int = 10)
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"生成流量图表失败: {str(e)}")
|
logger.error(f"生成流量图表失败: {str(e)}")
|
||||||
return HTMLResponse(content=f"<h1>错误</h1><p>{str(e)}</p>", status_code=500)
|
return HTMLResponse(content=f"<h1>错误</h1><p>{str(e)}</p>", status_code=500)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/network_adapters", summary="获取网络适配器网段")
|
|
||||||
async def get_network_adapters():
|
|
||||||
try:
|
|
||||||
net_if_addrs = psutil.net_if_addrs()
|
|
||||||
|
|
||||||
networks = []
|
|
||||||
for interface, addrs in net_if_addrs.items():
|
|
||||||
for addr in addrs:
|
|
||||||
if addr.family == socket.AF_INET:
|
|
||||||
ip = addr.address
|
|
||||||
netmask = addr.netmask
|
|
||||||
|
|
||||||
network = ipaddress.IPv4Network(f"{ip}/{netmask}", strict=False)
|
|
||||||
networks.append({
|
|
||||||
"adapter": interface,
|
|
||||||
"network": str(network),
|
|
||||||
"ip": ip,
|
|
||||||
"subnet_mask": netmask
|
|
||||||
})
|
|
||||||
|
|
||||||
return {"networks": networks}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return {"error": f"获取网络适配器信息失败: {str(e)}"}
|
|
@ -30,9 +30,9 @@ class AIService:
|
|||||||
2. 必须包含'commands'字段,包含可直接执行的命令列表
|
2. 必须包含'commands'字段,包含可直接执行的命令列表
|
||||||
3. 其他参数根据配置类型动态添加
|
3. 其他参数根据配置类型动态添加
|
||||||
4. 不要包含解释性文本、步骤说明或注释
|
4. 不要包含解释性文本、步骤说明或注释
|
||||||
5.要包含使用ssh连接交换机后的完整命令包括但不完全包括system-view,退出,保存等完整操作,注意保存还需要输入Y和回车
|
5.要包含使用ssh连接交换机后的完整命令包括但不完全包括system-view,退出,保存等完整操作
|
||||||
示例命令:'创建VLAN 100,名称为TEST'
|
示例命令:'创建VLAN 100,名称为TEST'
|
||||||
示例返回:{"type": "vlan", "vlan_id": 100, "name": "TEST", "commands": ["system-view\n","vlan 100\n", "name TEST\n","quit\n","\x1A\n","save\n","Y\n"]}
|
示例返回:{"type": "vlan", "vlan_id": 100, "name": "TEST", "commands": ["vlan 100", "name TEST"]}
|
||||||
注意:这里生成的commands中需包含登录交换机和保存等所有操作命令,我们使ssh连接交换机,你不需要给出连接ssh的命令,你只需要给出使用ssh连接到交换机后所输入的全部命令
|
注意:这里生成的commands中需包含登录交换机和保存等所有操作命令,我们使ssh连接交换机,你不需要给出连接ssh的命令,你只需要给出使用ssh连接到交换机后所输入的全部命令
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ pysnmp==7.1.21
|
|||||||
aiofiles==23.2.1
|
aiofiles==23.2.1
|
||||||
|
|
||||||
loguru==0.7.2
|
loguru==0.7.2
|
||||||
|
|
||||||
tenacity==8.2.3
|
tenacity==8.2.3
|
||||||
|
|
||||||
asyncio==3.4.3
|
asyncio==3.4.3
|
||||||
|
@ -8,7 +8,7 @@ import { Box } from '@chakra-ui/react';
|
|||||||
*/
|
*/
|
||||||
const PageContainer = ({ children }) => {
|
const PageContainer = ({ children }) => {
|
||||||
return (
|
return (
|
||||||
<Box pt={'85px'} px={6}>
|
<Box pt={'80px'} px={6}>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
VStack,
|
VStack,
|
||||||
@ -7,13 +7,9 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Text,
|
Text,
|
||||||
Spinner,
|
Spinner,
|
||||||
Table,
|
|
||||||
Badge,
|
Badge,
|
||||||
HStack,
|
HStack,
|
||||||
Select,
|
Table,
|
||||||
Field,
|
|
||||||
Portal,
|
|
||||||
createListCollection,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import DocumentTitle from '@/components/system/pages/DocumentTitle';
|
import DocumentTitle from '@/components/system/pages/DocumentTitle';
|
||||||
import PageContainer from '@/components/system/PageContainer';
|
import PageContainer from '@/components/system/PageContainer';
|
||||||
@ -32,29 +28,22 @@ import scanEffect from '@/libs/script/scanPage/scanEffect';
|
|||||||
*/
|
*/
|
||||||
const ScanPage = () => {
|
const ScanPage = () => {
|
||||||
const [subnet, setSubnet] = useState('');
|
const [subnet, setSubnet] = useState('');
|
||||||
const [networkAdapters, setNetworkAdapters] = useState(createListCollection({ items: [] }));
|
const [devices, setDevices] = useState([]);
|
||||||
const [scannedDevices, setScannedDevices] = useState([]);
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [localIp, setLocalIp] = useState('');
|
const [localIp, setLocalIp] = useState('');
|
||||||
const [selectedNetwork, setSelectedNetwork] = useState('');
|
|
||||||
const [inputMode, setInputMode] = useState(false);
|
|
||||||
|
|
||||||
const config = ConfigTool.load();
|
const config = ConfigTool.load();
|
||||||
const testMode = config.testMode;
|
const testMode = config.testMode;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.getNetworkAdapters().then((response) => {
|
scanEffect
|
||||||
const { networks } = response.data;
|
.fetchLocalInfo({
|
||||||
const networkCollection = createListCollection({
|
setLocalIp: setLocalIp,
|
||||||
items: networks.map((network) => ({
|
setSubnet: setSubnet,
|
||||||
label: `${network.adapter} (${network.network})`,
|
subnet: subnet,
|
||||||
value: network.network,
|
})
|
||||||
})),
|
.then();
|
||||||
});
|
}, [subnet, Notification]);
|
||||||
setNetworkAdapters(networkCollection);
|
|
||||||
setLocalIp(config.backendUrl);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleScan = async () => {
|
const handleScan = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -68,18 +57,17 @@ const ScanPage = () => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const res = await api.scan(subnet);
|
const res = await api.scan(subnet);
|
||||||
console.log(`res:${JSON.stringify(res)}`);
|
scanDevices = res.devices || [];
|
||||||
scanDevices = res.data.devices || [];
|
|
||||||
Notification.success({
|
Notification.success({
|
||||||
title: '扫描子网设备成功!',
|
title: '扫描子网设备成功!',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log(`device:${JSON.stringify(scanDevices)}`);
|
|
||||||
scanDevices = scanDevices.map((d, idx) => ({
|
scanDevices = scanDevices.map((d, idx) => ({
|
||||||
...d,
|
...d,
|
||||||
name: `交换机 ${idx + 1}`,
|
name: `交换机 ${idx + 1}`,
|
||||||
}));
|
}));
|
||||||
setScannedDevices(scanDevices);
|
setDevices(scanDevices);
|
||||||
const updatedStats = {
|
const updatedStats = {
|
||||||
totalDevices: scanDevices.length,
|
totalDevices: scanDevices.length,
|
||||||
onlineDevices: scanDevices.length,
|
onlineDevices: scanDevices.length,
|
||||||
@ -109,20 +97,15 @@ const ScanPage = () => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const res = await api.listDevices();
|
const res = await api.listDevices();
|
||||||
scanDevices = res.data.devices || [];
|
scanDevices = res.devices || [];
|
||||||
}
|
}
|
||||||
setScannedDevices(scanDevices);
|
setDevices(scanDevices);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Notification.error({ title: '获取上次扫描记录失败' });
|
Notification.error({ title: '获取上次扫描记录失败' });
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNetworkChange = ({ value }) => {
|
|
||||||
setSelectedNetwork(value[0] ?? '');
|
|
||||||
setSubnet(value[0] ?? '');
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DocumentTitle title={'网络扫描'}>
|
<DocumentTitle title={'网络扫描'}>
|
||||||
<DashboardBackground />
|
<DashboardBackground />
|
||||||
@ -149,67 +132,13 @@ const ScanPage = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
<HStack mb={4} spacing={4}>
|
<HStack mb={4} spacing={4}>
|
||||||
<Field.Root>
|
<Input
|
||||||
<Field.Label fontWeight={'bold'} mb={1} fontSize="sm">
|
placeholder={'输入子网 (如 192.168.1.0/24)'}
|
||||||
{'选择网段'}
|
value={subnet}
|
||||||
</Field.Label>
|
onChange={(e) => setSubnet(e.target.value)}
|
||||||
<Select.Root
|
width={'300px'}
|
||||||
collection={networkAdapters}
|
bg={'whiteAlpha.200'}
|
||||||
value={selectedNetwork ? [selectedNetwork] : []}
|
/>
|
||||||
onValueChange={handleNetworkChange}
|
|
||||||
placeholder={'请选择网段'}
|
|
||||||
size={'sm'}
|
|
||||||
colorPalette={'teal'}
|
|
||||||
>
|
|
||||||
<Select.HiddenSelect />
|
|
||||||
<Select.Control>
|
|
||||||
<Select.Trigger>
|
|
||||||
<Select.ValueText />
|
|
||||||
</Select.Trigger>
|
|
||||||
<Select.IndicatorGroup>
|
|
||||||
<Select.Indicator />
|
|
||||||
<Select.ClearTrigger />
|
|
||||||
</Select.IndicatorGroup>
|
|
||||||
</Select.Control>
|
|
||||||
<Portal>
|
|
||||||
<Select.Positioner>
|
|
||||||
<Select.Content>
|
|
||||||
{networkAdapters.items.map((item, index) => (
|
|
||||||
<Select.Item key={`${item.value}-${index}`} item={item}>
|
|
||||||
{' '}
|
|
||||||
{item.label}
|
|
||||||
</Select.Item>
|
|
||||||
))}
|
|
||||||
</Select.Content>
|
|
||||||
</Select.Positioner>
|
|
||||||
</Portal>
|
|
||||||
</Select.Root>
|
|
||||||
</Field.Root>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
mb={-7}
|
|
||||||
onClick={() => setInputMode(!inputMode)}
|
|
||||||
colorPalette={'blue'}
|
|
||||||
variant={'outline'}
|
|
||||||
>
|
|
||||||
{inputMode ? '关闭自定义' : '自定义网段'}
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
|
|
||||||
{inputMode ? (
|
|
||||||
<FadeInWrapper delay={0.1} yOffset={-2}>
|
|
||||||
<Input
|
|
||||||
mb={4}
|
|
||||||
placeholder={'输入子网 (如 192.168.1.0/24)'}
|
|
||||||
value={subnet}
|
|
||||||
onChange={(e) => setSubnet(e.target.value)}
|
|
||||||
width={'300px'}
|
|
||||||
bg={'whiteAlpha.200'}
|
|
||||||
/>
|
|
||||||
</FadeInWrapper>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<HStack mb={5} spacing={4}>
|
|
||||||
<Button
|
<Button
|
||||||
onClick={handleScan}
|
onClick={handleScan}
|
||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
@ -235,7 +164,7 @@ const ScanPage = () => {
|
|||||||
</HStack>
|
</HStack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!loading && scannedDevices.length > 0 && (
|
{!loading && devices.length > 0 && (
|
||||||
<FadeInWrapper delay={0.2} yOffset={-5}>
|
<FadeInWrapper delay={0.2} yOffset={-5}>
|
||||||
<Table.Root
|
<Table.Root
|
||||||
variant={'outline'}
|
variant={'outline'}
|
||||||
@ -264,7 +193,7 @@ const ScanPage = () => {
|
|||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{scannedDevices.map((d) => (
|
{devices.map((d) => (
|
||||||
<Table.Row
|
<Table.Row
|
||||||
key={d.ip}
|
key={d.ip}
|
||||||
_hover={{
|
_hover={{
|
||||||
@ -282,7 +211,7 @@ const ScanPage = () => {
|
|||||||
</FadeInWrapper>
|
</FadeInWrapper>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!loading && scannedDevices.length === 0 && (
|
{!loading && devices.length === 0 && (
|
||||||
<Text color={'gray.400'}>{'暂无扫描结果,请执行扫描..'}</Text>
|
<Text color={'gray.400'}>{'暂无扫描结果,请执行扫描..'}</Text>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -52,12 +52,6 @@ export const api = {
|
|||||||
applyConfig: (switch_ip, commands) =>
|
applyConfig: (switch_ip, commands) =>
|
||||||
axios.post(buildUrl('/api/execute_cli_commands'), { switch_ip: switch_ip, commands: commands }),
|
axios.post(buildUrl('/api/execute_cli_commands'), { switch_ip: switch_ip, commands: commands }),
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取网络适配器信息
|
|
||||||
* @returns {Promise<axios.AxiosResponse<any>>}
|
|
||||||
*/
|
|
||||||
getNetworkAdapters: () => axios.get(buildUrl('/api/network_adapters')),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新基础URL
|
* 更新基础URL
|
||||||
* @param url
|
* @param url
|
||||||
|
Loading…
x
Reference in New Issue
Block a user