schedule and route
parent
587134e5c6
commit
b4fe3ec8db
|
@ -96,14 +96,14 @@ export const constantRoutes = [
|
|||
]
|
||||
},
|
||||
{
|
||||
path: '/guide',
|
||||
path: '/schedule',
|
||||
component: Layout,
|
||||
redirect: '/guide/index',
|
||||
redirect: '/schedule/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/guide/index'),
|
||||
name: 'Guide',
|
||||
component: () => import('@/views/schedule/index'),
|
||||
name: 'Schedule',
|
||||
meta: { title: '调度决策', icon: 'guide', noCache: true }
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,49 +3,61 @@
|
|||
import Layout from '@/layout'
|
||||
|
||||
const chartsRouter = {
|
||||
path: '/charts',
|
||||
path: '/route',
|
||||
component: Layout,
|
||||
redirect: 'noRedirect',
|
||||
name: 'Charts',
|
||||
name: 'Route',
|
||||
meta: {
|
||||
title: '路由控制',
|
||||
icon: 'tree'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'keyboard',
|
||||
component: () => import('@/views/charts/keyboard'),
|
||||
name: 'KeyboardChart',
|
||||
path: 'show_paths',
|
||||
component: () => import('@/views/route/show_paths'),
|
||||
name: 'ShowPaths',
|
||||
meta: { title: '查看最短路径', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'keyboard',
|
||||
component: () => import('@/views/charts/keyboard'),
|
||||
name: 'KeyboardChart',
|
||||
path: 'show_sid',
|
||||
component: () => import('@/views/route/show_sid'),
|
||||
name: 'ShowSID',
|
||||
meta: { title: '查看SID', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'line',
|
||||
component: () => import('@/views/charts/line'),
|
||||
name: 'LineChart',
|
||||
path: 'show_policy',
|
||||
component: () => import('@/views/route/show_policy.vue'),
|
||||
name: 'ShowPolicy',
|
||||
meta: { title: '查看路由', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'mix-chart',
|
||||
component: () => import('@/views/charts/mix-chart'),
|
||||
name: 'MixChart',
|
||||
path: 'show_steer',
|
||||
component: () => import('@/views/route/show_steer'),
|
||||
name: 'ShowSteer',
|
||||
meta: { title: '查看引导', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'add_policy',
|
||||
component: () => import('@/views/route/add_policy.vue'),
|
||||
name: 'AddPolicy',
|
||||
meta: { title: '添加路由', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'mix-chart',
|
||||
component: () => import('@/views/charts/mix-chart'),
|
||||
name: 'MixChart',
|
||||
path: 'steer',
|
||||
component: () => import('@/views/route/steer.vue'),
|
||||
name: 'Steer',
|
||||
meta: { title: '更新引导', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'mix-chart',
|
||||
component: () => import('@/views/charts/mix-chart'),
|
||||
name: 'MixChart',
|
||||
path: 'del_steer',
|
||||
component: () => import('@/views/route/del_steer.vue'),
|
||||
name: 'DelSteer',
|
||||
meta: { title: '删除引导', noCache: true }
|
||||
},
|
||||
{
|
||||
path: 'del_policy',
|
||||
component: () => import('@/views/route/del_policy.vue'),
|
||||
name: 'DelPolicy',
|
||||
meta: { title: '删除路由', noCache: true }
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
<template>
|
||||
<div class="add-policy">
|
||||
<h2>添加SRv6路由策略</h2>
|
||||
|
||||
<!-- 输入表单 -->
|
||||
<form @submit.prevent="submitPolicy">
|
||||
<div class="form-group">
|
||||
<label for="router">路由器</label>
|
||||
<select id="router" v-model="router" required>
|
||||
<option disabled value="">选择路由器</option>
|
||||
<option value="r0">路由器r0</option>
|
||||
<option value="r3">路由器r3</option>
|
||||
<option value="r6">路由器r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="bsid">绑定 SID (BSID)</label>
|
||||
<input id="bsid" v-model="bsid" type="text" required placeholder="fe00::1a">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sids">SIDs (逗号分隔)</label>
|
||||
<input id="sids" v-model="sids" type="text" required placeholder="fc00:1::a,fc00:2::a">
|
||||
</div>
|
||||
|
||||
<button type="submit">添加路由</button>
|
||||
</form>
|
||||
|
||||
<!-- 显示结果 -->
|
||||
<div v-if="resultMessage" class="result-message">
|
||||
<p><strong>{{ resultMessage }}</strong></p>
|
||||
<pre>{{ result }}</pre>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
router: '', // 路由器选择
|
||||
bsid: '', // BSID
|
||||
sids: '', // SIDs
|
||||
resultMessage: '', // 返回的消息
|
||||
result: '', // 返回的详细结果
|
||||
error: null // 错误消息
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submitPolicy() {
|
||||
try {
|
||||
const data = {
|
||||
bsid: this.bsid,
|
||||
sids: this.sids
|
||||
}
|
||||
|
||||
const response = await axios.post(`http://localhost:5060/route/add_policy?router=${this.router}`, data, {
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
|
||||
this.resultMessage = response.data.message
|
||||
this.result = response.data.result.join('\n') // 格式化结果信息
|
||||
this.error = null
|
||||
} catch (error) {
|
||||
this.error = error.message
|
||||
this.resultMessage = ''
|
||||
this.result = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.add-policy {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-group input, .form-group select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.result-message, .error-message {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.result-message {
|
||||
background-color: #e7f4e4;
|
||||
color: #3c763d;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<div class="del-policy">
|
||||
<h2>删除 SRv6 策略</h2>
|
||||
|
||||
<!-- 表单 -->
|
||||
<form @submit.prevent="submitDelPolicy">
|
||||
<div class="form-group">
|
||||
<label for="router">选择路由器</label>
|
||||
<select id="router" v-model="router" required>
|
||||
<option disabled value="">选择路由器</option>
|
||||
<option value="r0">路由器r0</option>
|
||||
<option value="r3">路由器r3</option>
|
||||
<option value="r6">路由器r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="bsid">BSID</label>
|
||||
<input
|
||||
id="bsid"
|
||||
v-model="bsid"
|
||||
type="text"
|
||||
required
|
||||
placeholder="请输入 Binding SID,如 fe00:1::1"
|
||||
>
|
||||
</div>
|
||||
|
||||
<button type="submit">删除策略</button>
|
||||
</form>
|
||||
|
||||
<!-- 显示结果 -->
|
||||
<div v-if="resultMessage" class="result-message">
|
||||
<p><strong>{{ resultMessage }}</strong></p>
|
||||
<pre>{{ result }}</pre>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>错误: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
router: '', // 选择的路由器
|
||||
bsid: '', // Binding SID
|
||||
resultMessage: '', // 返回的消息
|
||||
result: '', // 返回的详细结果
|
||||
error: null // 错误消息
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submitDelPolicy() {
|
||||
try {
|
||||
// 删除请求需要的 body 数据
|
||||
const data = {
|
||||
bsid: this.bsid
|
||||
}
|
||||
|
||||
// 发送 DELETE 请求
|
||||
const response = await axios.delete(
|
||||
`http://localhost:5060/route/del_policy?router=${this.router}`,
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
}
|
||||
)
|
||||
|
||||
// 处理返回结果
|
||||
this.resultMessage = response.data.message
|
||||
this.result = response.data.result.join('\n') // 格式化返回结果
|
||||
this.error = null
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
this.error = error.message
|
||||
this.resultMessage = ''
|
||||
this.result = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.del-policy {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.result-message,
|
||||
.error-message {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.result-message {
|
||||
background-color: #e7f4e4;
|
||||
color: #3c763d;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,144 @@
|
|||
<template>
|
||||
<div class="del-steer-policy">
|
||||
<h2>删除引导策略</h2>
|
||||
|
||||
<!-- 表单 -->
|
||||
<form @submit.prevent="submitDelSteerPolicy">
|
||||
<div class="form-group">
|
||||
<label for="router">选择路由器</label>
|
||||
<select id="router" v-model="router" required>
|
||||
<option disabled value="">选择路由器</option>
|
||||
<option value="r0">路由器r0</option>
|
||||
<option value="r3">路由器r3</option>
|
||||
<option value="r6">路由器r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ip_prefix">目标IP</label>
|
||||
<input
|
||||
id="ip_prefix"
|
||||
v-model="ip_prefix"
|
||||
type="text"
|
||||
required
|
||||
placeholder="请输入目标 IP,如 10.10.0.0/24"
|
||||
>
|
||||
</div>
|
||||
|
||||
<button type="submit">删除引导策略</button>
|
||||
</form>
|
||||
|
||||
<!-- 显示结果 -->
|
||||
<div v-if="resultMessage" class="result-message">
|
||||
<p><strong>{{ resultMessage }}</strong></p>
|
||||
<pre>{{ result }}</pre>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>错误: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
router: '', // 选择的路由器
|
||||
ip_prefix: '', // IP 前缀
|
||||
resultMessage: '', // 返回的消息
|
||||
result: '', // 返回的详细结果
|
||||
error: null // 错误消息
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submitDelSteerPolicy() {
|
||||
try {
|
||||
// 删除请求需要的 body 数据
|
||||
const data = {
|
||||
ip_prefix: this.ip_prefix
|
||||
}
|
||||
|
||||
// 发送 DELETE 请求
|
||||
const response = await axios.delete(
|
||||
`http://localhost:5060/route/del_steer?router=${this.router}`,
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data
|
||||
}
|
||||
)
|
||||
|
||||
// 处理返回结果
|
||||
this.resultMessage = response.data.message
|
||||
this.result = response.data.result.join('\n') // 格式化返回结果
|
||||
this.error = null
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
this.error = error.message
|
||||
this.resultMessage = ''
|
||||
this.result = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.del-steer-policy {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.result-message,
|
||||
.error-message {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.result-message {
|
||||
background-color: #e7f4e4;
|
||||
color: #3c763d;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<div class="show-paths">
|
||||
<h2>最短路径信息</h2>
|
||||
<!-- 检查是否在加载状态 -->
|
||||
<div v-if="loading">加载中...</div>
|
||||
|
||||
<!-- 如果有路径数据则显示 -->
|
||||
<div v-else>
|
||||
<ul v-if="paths.length > 0">
|
||||
<li v-for="(path, index) in paths" :key="index">{{ path }}</li>
|
||||
</ul>
|
||||
|
||||
<!-- 如果没有路径数据则显示消息 -->
|
||||
<div v-else>
|
||||
<p>未找到</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>加载路径错误: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShowPaths',
|
||||
data() {
|
||||
return {
|
||||
paths: [],
|
||||
loading: false,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 组件挂载时请求路径数据
|
||||
this.fetchPaths()
|
||||
},
|
||||
methods: {
|
||||
// 请求 API 以获取路径信息
|
||||
fetchPaths() {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
axios
|
||||
.get('http://localhost:5060/route/show_paths')
|
||||
.then((response) => {
|
||||
// 检查响应中是否有 paths 数据
|
||||
if (response.data && response.data.paths) {
|
||||
this.paths = response.data.paths
|
||||
} else {
|
||||
this.error = 'No paths data found in the response.'
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.error = error.message || 'An error occurred while fetching paths.'
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.show-paths {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="show-policy">
|
||||
<h2>SRv6路径: {{ selectedRouter }}</h2>
|
||||
|
||||
<!-- 路由器选择器 -->
|
||||
<div class="router-selector">
|
||||
<label for="router">选择路由器:</label>
|
||||
<select v-model="selectedRouter" @change="fetchPolicyInfo">
|
||||
<option value="r0">r0</option>
|
||||
<option value="r3">r3</option>
|
||||
<option value="r6">r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 显示加载状态 -->
|
||||
<div v-if="loading">加载路径信息...</div>
|
||||
|
||||
<!-- 列表形式展示策略信息 -->
|
||||
<ul v-if="!loading && policyData.length > 0" class="policy-list">
|
||||
<li v-for="(policy, index) in policyData" :key="index">
|
||||
{{ policy }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- 如果没有策略信息 -->
|
||||
<div v-else-if="!loading && policyData.length === 0">
|
||||
<p>No policy information available for the selected router.</p>
|
||||
</div>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error loading policy information: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShowPolicy',
|
||||
data() {
|
||||
return {
|
||||
selectedRouter: 'r0', // 默认选择 r0
|
||||
policyData: [],
|
||||
loading: false,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 组件挂载时请求默认路由器的策略信息
|
||||
this.fetchPolicyInfo()
|
||||
},
|
||||
methods: {
|
||||
// 请求 API 以获取策略信息
|
||||
fetchPolicyInfo() {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
axios
|
||||
.get(`http://localhost:5060/route/show_policy`, { params: { router: this.selectedRouter }})
|
||||
.then((response) => {
|
||||
if (response.data && response.data.policies) {
|
||||
this.policyData = response.data.policies // 保存策略数据
|
||||
} else {
|
||||
this.policyData = []
|
||||
this.error = 'No policy data found in the response.'
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.error = error.message || 'An error occurred while fetching policy data.'
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.show-policy {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.router-selector {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul.policy-list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.policy-list li {
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div class="show-sid">
|
||||
<h2>SID信息</h2>
|
||||
|
||||
<!-- 下拉选择路由器 -->
|
||||
<div class="router-selector">
|
||||
<label for="router">选择路由器:</label>
|
||||
<select v-model="selectedRouter" @change="fetchSIDInfo">
|
||||
<option value="r0">r0</option>
|
||||
<option value="r3">r3</option>
|
||||
<option value="r6">r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 显示加载提示 -->
|
||||
<div v-if="loading">加载SID信息...</div>
|
||||
|
||||
<!-- 列表形式展示 SID 信息 -->
|
||||
<ul v-if="!loading && sidData.length > 0" class="sid-list">
|
||||
<li v-for="(sid, index) in sidData" :key="index">
|
||||
{{ sid }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- 如果没有 SID 数据则显示消息 -->
|
||||
<div v-else-if="!loading && sidData.length === 0">
|
||||
<p>No SID information available for the selected router.</p>
|
||||
</div>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error loading SID information: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShowSID',
|
||||
data() {
|
||||
return {
|
||||
selectedRouter: 'r0', // 默认选择 r0
|
||||
sidData: [],
|
||||
loading: false,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 组件挂载时请求默认路由器的 SID 信息
|
||||
this.fetchSIDInfo()
|
||||
},
|
||||
methods: {
|
||||
// 请求 API 以获取 SID 信息
|
||||
fetchSIDInfo() {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
axios
|
||||
.get(`http://localhost:5060/route/show_sid`, { params: { router: this.selectedRouter }})
|
||||
.then((response) => {
|
||||
if (response.data && response.data.localsids) {
|
||||
this.sidData = response.data.localsids // 保存 SID 数据
|
||||
} else {
|
||||
this.sidData = []
|
||||
this.error = 'No SID data found in the response.'
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.error = error.message || 'An error occurred while fetching SID data.'
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.show-sid {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.router-selector {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul.sid-list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.sid-list li {
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="show-steer">
|
||||
<h2>流量引导: {{ selectedRouter }}</h2>
|
||||
|
||||
<!-- 路由器选择器 -->
|
||||
<div class="router-selector">
|
||||
<label for="router">选择路由器:</label>
|
||||
<select v-model="selectedRouter" @change="fetchSteerInfo">
|
||||
<option value="r0">r0</option>
|
||||
<option value="r3">r3</option>
|
||||
<option value="r6">r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 显示加载状态 -->
|
||||
<div v-if="loading">加载引导信息...</div>
|
||||
|
||||
<!-- 列表形式展示策略信息 -->
|
||||
<ul v-if="!loading && policyData.length > 0" class="steer-list">
|
||||
<li v-for="(policy, index) in policyData" :key="index">
|
||||
{{ policy }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- 如果没有策略信息 -->
|
||||
<div v-else-if="!loading && policyData.length === 0">
|
||||
<p>No steer information available for the selected router.</p>
|
||||
</div>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error loading steer information: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ShowSteer',
|
||||
data() {
|
||||
return {
|
||||
selectedRouter: 'r0', // 默认选择 r0
|
||||
policyData: [],
|
||||
loading: false,
|
||||
error: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 组件挂载时请求默认路由器的策略信息
|
||||
this.fetchSteerInfo()
|
||||
},
|
||||
methods: {
|
||||
// 请求 API 以获取策略信息
|
||||
fetchSteerInfo() {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
axios
|
||||
.get(`http://localhost:5060/route/show_steer`, { params: { router: this.selectedRouter }})
|
||||
.then((response) => {
|
||||
if (response.data && response.data.steering_policies) {
|
||||
this.policyData = response.data.steering_policies // 保存策略数据
|
||||
} else {
|
||||
this.policyData = []
|
||||
this.error = 'No policy data found in the response.'
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.error = error.message || 'An error occurred while fetching policy data.'
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.show-steer {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.router-selector {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul.steer-list {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ul.steer-list li {
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,135 @@
|
|||
<template>
|
||||
<div class="steer-policy">
|
||||
<h2>更新引导策略</h2>
|
||||
|
||||
<!-- 输入表单 -->
|
||||
<form @submit.prevent="submitSteerPolicy">
|
||||
<div class="form-group">
|
||||
<label for="router">路由器</label>
|
||||
<select id="router" v-model="router" required>
|
||||
<option disabled value="">选择路由器</option>
|
||||
<option value="r0">路由器r0</option>
|
||||
<option value="r3">路由器r3</option>
|
||||
<option value="r6">路由器r6</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="bsid">绑定SID (BSID)</label>
|
||||
<input id="bsid" v-model="bsid" type="text" required placeholder="fe00::1a">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ip_prefix">目标IP</label>
|
||||
<input id="ip_prefix" v-model="ip_prefix" type="text" required placeholder="10.10.0.0/24">
|
||||
</div>
|
||||
|
||||
<button type="submit">添加引导策略</button>
|
||||
</form>
|
||||
|
||||
<!-- 显示结果 -->
|
||||
<div v-if="resultMessage" class="result-message">
|
||||
<p><strong>{{ resultMessage }}</strong></p>
|
||||
<pre>{{ result }}</pre>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
router: '', // 路由器选择
|
||||
bsid: '', // BSID
|
||||
ip_prefix: '', // IP Prefix
|
||||
resultMessage: '', // 返回的消息
|
||||
result: '', // 返回的详细结果
|
||||
error: null // 错误消息
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async submitSteerPolicy() {
|
||||
try {
|
||||
const data = {
|
||||
bsid: this.bsid,
|
||||
ip_prefix: this.ip_prefix
|
||||
}
|
||||
|
||||
const response = await axios.post(`http://localhost:5060/route/steer?router=${this.router}`, data, {
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
|
||||
this.resultMessage = response.data.message
|
||||
this.result = response.data.result.join('\n') // 格式化结果信息
|
||||
this.error = null
|
||||
} catch (error) {
|
||||
this.error = error.message
|
||||
this.resultMessage = ''
|
||||
this.result = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.steer-policy {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.form-group input, .form-group select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.result-message, .error-message {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.result-message {
|
||||
background-color: #e7f4e4;
|
||||
color: #3c763d;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div class="schedule-decision">
|
||||
<h2>调度决策</h2>
|
||||
|
||||
<!-- 表格展示平均资源和评分 -->
|
||||
<table class="decision-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>集群</th>
|
||||
<th>平均空闲CPU (%)</th>
|
||||
<th>平均空闲内存 (bytes)</th>
|
||||
<th>平均空闲存储 (bytes)</th>
|
||||
<th>分数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(resource, index) in averageResources" :key="index" :class="{ best: clusters[index] === bestCluster }">
|
||||
<td>{{ clusters[index] }}</td>
|
||||
<td>{{ resource[0].toFixed(2) }}</td>
|
||||
<td>{{ resource[1].toFixed(0).toLocaleString() }}</td>
|
||||
<td>{{ resource[2].toFixed(0).toLocaleString() }}</td>
|
||||
<td>{{ scores[index].toFixed(2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 最佳集群展示 -->
|
||||
<div class="best-cluster">
|
||||
<h3>最佳集群: {{ bestCluster }}</h3>
|
||||
</div>
|
||||
|
||||
<!-- 错误消息 -->
|
||||
<div v-if="error" class="error-message">
|
||||
<p>Error loading schedule data: {{ error }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'ScheduleDecision',
|
||||
data() {
|
||||
return {
|
||||
clusters: ['hosta', 'hostb'],
|
||||
averageResources: [],
|
||||
scores: [],
|
||||
bestCluster: '',
|
||||
error: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchScheduleDecision()
|
||||
},
|
||||
methods: {
|
||||
fetchScheduleDecision() {
|
||||
axios
|
||||
.get('http://localhost:5060/schedule')
|
||||
.then((response) => {
|
||||
const data = response.data
|
||||
this.averageResources = data.average_resource || []
|
||||
this.scores = data.scores || []
|
||||
this.bestCluster = data.best_cluster || ''
|
||||
})
|
||||
.catch((error) => {
|
||||
this.error = error.message || 'An error occurred while fetching schedule data.'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.schedule-decision {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
table.decision-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
table.decision-table th, table.decision-table td {
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.decision-table tr.best {
|
||||
background-color: #e0f7fa;
|
||||
}
|
||||
|
||||
.best-cluster h3 {
|
||||
color: #00796b;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue