forked from JointCloud/JCC-RIP
merge from private
This commit is contained in:
parent
b91b7e53f3
commit
8cba583c2e
File diff suppressed because it is too large
Load Diff
|
@ -305,6 +305,13 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
getVirtualStorage() {
|
||||
return request({
|
||||
url: '/virtual/v1/harvester/longhorn.io.nodes',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
|
||||
// 工作负载创建 --> 容器镜像获取数据 get
|
||||
|
||||
// 获取应用名称列表 http://119.45.100.73:30880/kapis/resources.kubesphere.io/v1alpha3/deployments?limit=-1&sortBy=updateTime&page=1
|
||||
|
|
|
@ -25,7 +25,7 @@ export function harvesterLogin(data) {
|
|||
}
|
||||
export function harvesterFirstLogin(data) {
|
||||
return request({
|
||||
url: '/virtual/v3/settings/first-login',
|
||||
url: '/virtual/v3-public/authProviders',
|
||||
method: 'get',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div>
|
||||
<vue-json-editor
|
||||
v-model="yaml"
|
||||
:show-btns="isEdit"
|
||||
:mode="'code'"
|
||||
lang="zh"
|
||||
style="height: 720px"
|
||||
@json-change="onJsonChange"
|
||||
@json-save="onJsonSave"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getDataVolumeYaml, putDataVolumeYaml } from '@/api/one-class-page/virtualMachine'
|
||||
import vueJsonEditor from 'vue-json-editor'
|
||||
export default {
|
||||
components: {
|
||||
vueJsonEditor
|
||||
},
|
||||
props: {
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
yaml: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
getDataVolumeYaml(this.$route.query.name).then(res => {
|
||||
// console.log(res)
|
||||
this.yaml = res
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onJsonChange() {
|
||||
|
||||
},
|
||||
onJsonSave() {
|
||||
putDataVolumeYaml(this.$route.query.name, this.yaml).then(res => {
|
||||
console.log(res)
|
||||
this.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.jsoneditor-vue{
|
||||
height: 90%;
|
||||
}
|
||||
</style>
|
|
@ -28,7 +28,7 @@ import appApi from '@/api/operations/actions'
|
|||
|
||||
import './icons' // icon
|
||||
import './permission' // permission control
|
||||
import './utils/error-log' // error log
|
||||
// import './utils/error-log' // error log
|
||||
|
||||
import * as filters from './filters'
|
||||
import HandleFunc from '@/utils/get-Kube-List' // global filters
|
||||
|
|
|
@ -54,37 +54,6 @@ const blockChainRouter = {
|
|||
meta: { title: '数据可信核验', icon: 'el-icon-success', affix: true },
|
||||
hidden: false
|
||||
}
|
||||
// {
|
||||
|
||||
// path: 'detail',
|
||||
// component: () => import('@/views/virtualMachine/hostDetailPanel'),
|
||||
// name: 'detail',
|
||||
// meta: { activeMenu: '/virtual/host' },
|
||||
// hidden: true,
|
||||
// children: [
|
||||
// {
|
||||
// path: '',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'overview',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'config',
|
||||
// component: () => import('@/views/virtualMachine/hostConfig'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
|
||||
// {
|
||||
// path: 'yaml',
|
||||
// component: () => import('@/views/virtualMachine/hostYAML'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -27,36 +27,6 @@ const functionsRouter = {
|
|||
meta: { title: '函数列表', icon: 'el-icon-s-opportunity', affix: true },
|
||||
hidden: false
|
||||
}
|
||||
// {
|
||||
// path: 'detail',
|
||||
// component: () => import('@/views/virtualMachine/hostDetailPanel'),
|
||||
// name: 'detail',
|
||||
// meta: { activeMenu: '/virtual/host' },
|
||||
// hidden: true,
|
||||
// children: [
|
||||
// {
|
||||
// path: '',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'overview',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'config',
|
||||
// component: () => import('@/views/virtualMachine/hostConfig'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
|
||||
// {
|
||||
// path: 'yaml',
|
||||
// component: () => import('@/views/virtualMachine/hostYAML'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
]
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -22,40 +22,46 @@ const virtualMachineRouter = {
|
|||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/virtualMachine/virtualHost'),
|
||||
component: () => import('@/views/virtualMachine/host/list'),
|
||||
name: 'host',
|
||||
meta: { title: '主机', icon: 'el-icon-s-platform', affix: true },
|
||||
hidden: false
|
||||
},
|
||||
{
|
||||
path: 'detail',
|
||||
component: () => import('@/views/virtualMachine/hostDetailPanel'),
|
||||
path: 'edit',
|
||||
component: () => import('@/views/virtualMachine/host/edit'),
|
||||
meta: { activeMenu: '/virtual/host' },
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'hostDetail',
|
||||
component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'overview',
|
||||
component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
component: () => import('@/views/virtualMachine/hostConfig'),
|
||||
meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
},
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: 'detail',
|
||||
component: () => import('@/views/virtualMachine/host/detail'),
|
||||
meta: { activeMenu: '/virtual/host' },
|
||||
hidden: true
|
||||
// children: [
|
||||
// {
|
||||
// path: '',
|
||||
// name: 'hostDetail',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'overview',
|
||||
// component: () => import('@/views/virtualMachine/hostDetail'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
// {
|
||||
// path: 'config',
|
||||
// component: () => import('@/views/virtualMachine/hostConfig'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// },
|
||||
|
||||
{
|
||||
path: 'yaml',
|
||||
component: () => import('@/views/virtualMachine/hostYAML'),
|
||||
meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
}
|
||||
]
|
||||
// {
|
||||
// path: 'yaml',
|
||||
// component: () => import('@/views/virtualMachine/hostYAML'),
|
||||
// meta: { activeMenu: '/virtual/host', keepAlive: true }
|
||||
// }
|
||||
// ]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -269,10 +269,10 @@ const getSystemProjectList = (clusterName, params) => {
|
|||
})
|
||||
})
|
||||
}
|
||||
// TODO: 主机详情页面的虚拟机列表
|
||||
const getHostVirtualMachineList = (clusterName, params) => {
|
||||
return new Promise(function(resolve) {})
|
||||
}
|
||||
// // 主机详情页面的虚拟机列表
|
||||
// const getHostVirtualMachineList = (clusterName, params) => {
|
||||
// return new Promise(function(resolve) {})
|
||||
// }
|
||||
const getVirtualMachineList = (clusterName, params) => {
|
||||
return new Promise(function(resolve) {
|
||||
let listResult = []
|
||||
|
@ -442,4 +442,4 @@ const getImagesList = () => {
|
|||
})
|
||||
}
|
||||
|
||||
export default { getClusterHosts, getClusterMembers, getVolumeList, getNodeStatusList, getServiceList, getPodList, getDeploymentList, getStatefulSetList, getDaemonSetList, getUserProjectList, getSystemProjectList, getVirtualMachineList, getVirtualHostList, getDataVolumeList, getImagesList, getHostVirtualMachineList }
|
||||
export default { getClusterHosts, getClusterMembers, getVolumeList, getNodeStatusList, getServiceList, getPodList, getDeploymentList, getStatefulSetList, getDaemonSetList, getUserProjectList, getSystemProjectList, getVirtualMachineList, getVirtualHostList, getDataVolumeList, getImagesList }
|
||||
|
|
|
@ -0,0 +1,419 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card shadow="never">
|
||||
<el-page-header content="详情" @back="goBack" />
|
||||
<h2>主机:{{ $route.query.name }} <el-tag type="success">{{ $route.query.state }} </el-tag> <el-dropdown @command="handleDropdown">
|
||||
<el-button class-name="el-dropdown-link" size="mini" icon="el-icon-more" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="1"> 开启维护模式 </el-dropdown-item>
|
||||
<el-dropdown-item command="2"> 编辑设置 </el-dropdown-item>
|
||||
<el-dropdown-item command="3"> 编辑YAML </el-dropdown-item>
|
||||
<el-dropdown-item command="4"> 下载YAML </el-dropdown-item>
|
||||
<el-dropdown-item command="5"> 删除 </el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown> </h2>
|
||||
<h6>存活时间:{{ $route.query.aliveTime }}</h6>
|
||||
<el-tabs style="height: 600px;">
|
||||
<el-tab-pane key="" label="基本信息">
|
||||
<h5>概览</h5>
|
||||
<FormData :data="formData" :data-map="dataMap" />
|
||||
<h5>网络设置</h5>
|
||||
<FormData :data="formData" :data-map="dataMap2" />
|
||||
<h5>监控数据</h5>
|
||||
<el-row style=" color: #999999;font-size:0.8rem">
|
||||
<el-col :span="8"><span>CPU <br> 已使用 {{ formData.cpuAll }}C 中的 {{ formData.cpuUsed }}<el-progress :percentage="Number(formData.cpuUsePercentage)" /></span></el-col>
|
||||
<el-col :span="8"><span>内存 <br> 已使用 {{ formData.memoryAll }} GiB 中的 {{ formData.memoryUsed }}<el-progress :percentage="Number(formData.memoryUsePercentage)" /></span></el-col>
|
||||
<el-col :span="8"><span>存储空间 <br> 已使用 {{ formData.storageAll }} TiB 中的 {{ formData.storageUsed }}<el-progress :percentage="Number(formData.storageUsePercentage)" /></span></el-col>
|
||||
</el-row>
|
||||
<h5>更多数据</h5>
|
||||
<FormData :data="formData" :data-map="dataMap3" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane key="virtual" label="虚拟机">
|
||||
<List
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:columns="columns"
|
||||
:table-list-data="virtualMachineList"
|
||||
:cluster-name="clusterName"
|
||||
:pagination="true"
|
||||
tooltip-effect="dark"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane key="network" label="网络">
|
||||
<FormData v-for="(item, ind) in networkStatusList" :key="ind" :data="item" :data-map="dataMap4" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane key="hardware" label="硬盘">
|
||||
<FormData :data="formData5" :data-map="dataMap5" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FormData } from '@/components/FormData'
|
||||
import { getVirtualHosts, getNodeNetworks, getUsageStatusByName } from '@/api/one-class-page/virtualMachine'
|
||||
import List from '@/components/list'
|
||||
import { getHostYaml } from '@/api/one-class-page/virtualMachine'
|
||||
|
||||
export default {
|
||||
components: { FormData, List },
|
||||
data() {
|
||||
return {
|
||||
index: '',
|
||||
enableConfig: false,
|
||||
filterMap: {
|
||||
project: {
|
||||
label: '项目',
|
||||
type: 'select'
|
||||
}
|
||||
},
|
||||
virtualMachineList: [],
|
||||
columns: [
|
||||
{ prop: 'state', label: '状态', formatter: (row) => { return <el-tag type='success'>{row.state}</el-tag> } },
|
||||
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
|
||||
{ prop: 'cpu', label: 'CPU' },
|
||||
{ prop: 'memory', label: '内存' },
|
||||
{ prop: 'ipAddress', label: 'IP地址' },
|
||||
{ prop: 'aliveTime', label: '存活时间' }
|
||||
// { prop: 'more', label: '更多操作', formatter: (row) => {
|
||||
// return <div>
|
||||
// <el-dropdown>
|
||||
// <el-button className='el-dropdown-link' type='primary' icon='el-icon-more' circle>
|
||||
// </el-button>
|
||||
// <el-dropdown-menu slot='dropdown'>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 暂停 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 开始 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 备份 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 恢复 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 生成模板 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 编辑设置 </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 编辑YAML </el-dropdown-item> </span>
|
||||
// <span onClick={() => this.clickOption(row)}> <el-dropdown-item> 下载YAML </el-dropdown-item> </span>
|
||||
// </el-dropdown-menu>
|
||||
// </el-dropdown>
|
||||
// </div>
|
||||
// } }
|
||||
],
|
||||
formData: {
|
||||
index: '',
|
||||
customName: '',
|
||||
hostIP: '172.17.0.2',
|
||||
operatingSystem: 'Ubuntu 18.04.5 LTS',
|
||||
role: 'Management Node',
|
||||
creationTime: '2021-06-22T03:25:33Z',
|
||||
lastUpdateTime: '2021-06-22T03:25:47Z',
|
||||
type: '',
|
||||
physicalNIC: '',
|
||||
uuid: '',
|
||||
memoryUsePercentage: 0,
|
||||
memoryUsed: 0,
|
||||
memoryAll: 0,
|
||||
cpuUsePercentage: 0,
|
||||
cpuUsed: 0,
|
||||
cpuAll: 0,
|
||||
storageUsePercentage: 0,
|
||||
storageUsed: 0,
|
||||
storageAll: 0
|
||||
},
|
||||
dataMap: {
|
||||
customName: '自定义名称',
|
||||
hostIP: '主机IP',
|
||||
operatingSystem: '操作系统',
|
||||
role: '角色',
|
||||
creationTime: '创建时间',
|
||||
lastUpdateTime: '最近更新时间'
|
||||
},
|
||||
dataMap2: {
|
||||
type: '类型',
|
||||
physicalNIC: '物理NIC'
|
||||
},
|
||||
dataMap3: {
|
||||
uuid: 'UUID',
|
||||
kernel: '内核',
|
||||
containerRuntime: '容器运行时'
|
||||
},
|
||||
networkStatusList: [],
|
||||
dataMap4: {
|
||||
name: '名称',
|
||||
state: '状态',
|
||||
type: '类型',
|
||||
mac: 'MAC地址',
|
||||
ipv4Address: 'IPv4地址',
|
||||
promiscuous: 'Promiscuous'
|
||||
},
|
||||
formData5: {
|
||||
conditions: '',
|
||||
storageAvailable: '',
|
||||
storageScheduled: '',
|
||||
storageMaximum: '',
|
||||
name: '',
|
||||
path: ''
|
||||
},
|
||||
dataMap5: {
|
||||
conditions: '状态',
|
||||
storageAvailable: 'Storage Available',
|
||||
storageScheduled: 'Storage Scheduled',
|
||||
storageMaximum: 'Storage Max',
|
||||
name: '名称',
|
||||
path: '路径'
|
||||
},
|
||||
activeName: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
// console.log(this.$store.getters)
|
||||
// return this.$store.getters.clusterName
|
||||
return localStorage.getItem('clusterName')
|
||||
},
|
||||
addTagNumCheck() {
|
||||
let flag = false
|
||||
this.editTagForm.tags.forEach(e => {
|
||||
if (e.key === '') {
|
||||
flag = true
|
||||
}
|
||||
})
|
||||
return flag
|
||||
},
|
||||
addTaintNumCheck() {
|
||||
let flag = false
|
||||
this.editTaintForm.taints.forEach(e => {
|
||||
if (e.key === '') {
|
||||
flag = true
|
||||
}
|
||||
})
|
||||
return flag
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.formData.index = this.$route.query.index
|
||||
this.formData.customName = this.$route.query.name
|
||||
this.getFormData()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.push({ path: '/virtual/host' })
|
||||
},
|
||||
getRoles(labels) {
|
||||
let roles = ''
|
||||
for (const key in labels) {
|
||||
if (Object.prototype.hasOwnProperty.call(labels, key)) {
|
||||
if (key.match('node-role.kubernetes.io/')) {
|
||||
roles += key.toString().slice(24)
|
||||
roles += ', '
|
||||
}
|
||||
}
|
||||
}
|
||||
roles = roles.substr(0, roles.length - 2)
|
||||
return roles
|
||||
},
|
||||
getFormData() {
|
||||
getNodeNetworks().then(res => {
|
||||
this.formData.type = res.data[this.formData.index].spec.type
|
||||
this.formData.physicalNIC = res.data[this.formData.index].spec.nic
|
||||
|
||||
const { networkLinkStatus } = res.data[this.formData.index].status
|
||||
|
||||
Object.keys(networkLinkStatus).forEach(e => {
|
||||
this.networkStatusList.push({
|
||||
name: e,
|
||||
mac: networkLinkStatus[e].mac,
|
||||
ipv4Address: networkLinkStatus[e].ipv4Address.join(','),
|
||||
promiscuous: networkLinkStatus[e].promiscuous ? '是' : '否',
|
||||
type: networkLinkStatus[e].type,
|
||||
state: networkLinkStatus[e].state
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$HandleFunc.getVirtualMachineList().then(res => {
|
||||
res.rows.forEach(e => {
|
||||
if (e.state === 'Running' && e.node === this.formData.customName) {
|
||||
this.virtualMachineList.push(e)
|
||||
}
|
||||
})
|
||||
})
|
||||
getUsageStatusByName(this.formData.customName).then(usage => {
|
||||
getVirtualHosts().then(res => {
|
||||
this.formData.customName = res.data[this.formData.index].metadata.name
|
||||
this.formData.hostIP = res.data[this.formData.index].metadata.fields[5]
|
||||
this.formData.operatingSystem = res.data[this.formData.index].metadata.fields[7]
|
||||
this.formData.role = res.data[this.formData.index].metadata.fields[2]
|
||||
this.formData.creationTime = res.data[this.formData.index].metadata.creationTimestamp
|
||||
this.formData.lastUpdateTime = res.data[this.formData.index].status.conditions[0].lastUpdateTime
|
||||
this.formData.uuid = res.data[this.formData.index].status.nodeInfo.systemUUID
|
||||
this.formData.kernel = res.data[this.formData.index].status.nodeInfo.kernelVersion
|
||||
this.formData.containerRuntime = res.data[this.formData.index].status.nodeInfo.containerRuntimeVersion
|
||||
|
||||
this.formData.cpuUsed = this.$route.query.cpuUsed
|
||||
this.formData.cpuAll = this.$route.query.cpuAll
|
||||
this.formData.cpuUsePercentage = this.$route.query.cpuUsePercentage
|
||||
this.formData.memoryUsed = this.$route.query.memoryUsed
|
||||
this.formData.memoryAll = this.$route.query.memoryAll
|
||||
this.formData.memoryUsePercentage = this.$route.query.memoryUsePercentage
|
||||
this.formData.storageUsed = this.$route.query.storageUsed
|
||||
this.formData.storageAll = this.$route.query.storageAll
|
||||
this.formData.storageUsePercentage = this.$route.query.storageUsePercentage
|
||||
})
|
||||
})
|
||||
this.$Api.getVirtualStorage().then(res => {
|
||||
const { diskStatus } = res.data[this.formData.index].status
|
||||
const conditions = []
|
||||
Object.keys(diskStatus[Object.keys(diskStatus)].conditions).forEach(e => {
|
||||
if (diskStatus[Object.keys(diskStatus)].conditions[e].status === 'True') {
|
||||
conditions.push(diskStatus[Object.keys(diskStatus)].conditions[e].type)
|
||||
}
|
||||
})
|
||||
this.formData5.conditions = conditions.join(',')
|
||||
this.formData5.storageAvailable = parseInt(diskStatus[Object.keys(diskStatus)].storageAvailable / 1024 / 1024 / 1024) + 'GiB'
|
||||
this.formData5.storageScheduled = parseInt(diskStatus[Object.keys(diskStatus)].storageScheduled / 1024 / 1024 / 1024) + 'GiB'
|
||||
this.formData5.storageMaximum = parseInt(diskStatus[Object.keys(diskStatus)].storageMaximum / 1024 / 1024 / 1024) + 'GiB'
|
||||
this.formData5.name = Object.keys(diskStatus)
|
||||
this.formData5.path = res.data[this.formData.index].spec.disks[Object.keys(diskStatus)].path
|
||||
})
|
||||
},
|
||||
switchDispatch() {
|
||||
this.switchLoading = true
|
||||
setTimeout(() => {
|
||||
this.switchLoading = false
|
||||
this.status = !this.status
|
||||
}, 2000)
|
||||
},
|
||||
handleCommand(command) {
|
||||
if (command === 'edit') {
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
if (command === 'taintManagement') {
|
||||
this.dialogTaintFormVisible = true
|
||||
}
|
||||
},
|
||||
submitTagEdit() {
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
addTag() {
|
||||
this.editTagForm.tags.push({ key: '', value: '' })
|
||||
},
|
||||
removeTag(tag, index) {
|
||||
this.editTagForm.tags.splice(index, 1)
|
||||
},
|
||||
submitTaintEdit() {
|
||||
this.dialogTaintFormVisible = false
|
||||
},
|
||||
addTaint() {
|
||||
this.editTaintForm.taints.push({ key: '', value: '' })
|
||||
},
|
||||
removeTaint(taint, index) {
|
||||
this.editTaintForm.taints.splice(index, 1)
|
||||
},
|
||||
handleDropdown(command) {
|
||||
switch (command) {
|
||||
case '1':
|
||||
break
|
||||
case '2':
|
||||
this.$refs.detail.disableConfig = false
|
||||
this.$route.query.disableConfig = false
|
||||
this.activeName = '1'
|
||||
this.$router.push({ path: '/virtual/host/edit', query: this.$route.query })
|
||||
break
|
||||
case '3':
|
||||
this.$refs.detail.editYaml = true
|
||||
this.$route.query.editYaml = true
|
||||
this.activeName = '2'
|
||||
this.$router.push({ path: '/virtual/host/detail/yaml', query: this.$route.query })
|
||||
break
|
||||
case '4':
|
||||
this.downloadHostYaml(this.$route.query.name)
|
||||
break
|
||||
default:
|
||||
}
|
||||
},
|
||||
downloadHostYaml(name) {
|
||||
getHostYaml(name).then(res => {
|
||||
var data = JSON.stringify(res)
|
||||
// encodeURIComponent解决中文乱码
|
||||
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(data)
|
||||
// 通过创建a标签实现
|
||||
const link = document.createElement('a')
|
||||
link.href = uri
|
||||
// 对下载的文件命名
|
||||
link.download = name + '.json'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.jcce-terminal{
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
border-radius: 5px;
|
||||
padding: 7px;
|
||||
border: 1px solid #eee;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.jcce-terminal,
|
||||
.jcce-terminal .terminal-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
outline: medium none;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background: #181d28;
|
||||
/* padding: 2px 0 2px 2px; */
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal .xterm-viewport::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
overflow: visible;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.1),
|
||||
inset 0 -1px 0 rgba(255, 255, 255, 0.07);
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb:active,
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal-actions {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: 34px;
|
||||
top: 10px;
|
||||
vertical-align: top;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,182 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card class="basicInfo" shadow="never">
|
||||
<el-page-header content="详情" @back="goBack" />
|
||||
<el-form ref="formData" :rules="rules" :model="formData">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="name"><el-input
|
||||
v-model="formData.name"
|
||||
placeholder="请输入内容"
|
||||
:disabled="disableConfig"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="描述" prop="description"><el-input
|
||||
v-model="formData.description"
|
||||
placeholder="请输入内容"
|
||||
:disabled="disableConfig"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item></el-col>
|
||||
</el-row>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-tab-pane label="基本信息"><el-form-item label="用户自定义名称" prop="customName"><el-input
|
||||
v-model="formData.customName"
|
||||
placeholder="请输入内容"
|
||||
:disabled="disableConfig"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item></el-tab-pane>
|
||||
<el-tab-pane label="网络">
|
||||
<el-row :gutter="10">
|
||||
|
||||
<el-col :span="12"> <el-form-item label="类型" prop="type"><el-input
|
||||
v-model="formData.type"
|
||||
placeholder="请输入内容"
|
||||
:disabled="disableConfig"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item></el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
|
||||
<el-form-item label="物理网卡" prop="physicalNIC">
|
||||
<br><el-select v-model="formData.physicalNIC" :disabled="disableConfig">
|
||||
<el-option
|
||||
v-for="item in physicalNICList"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item></el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<el-row>
|
||||
<el-col :span="20"><div class="grid-content" /></el-col>
|
||||
<el-col :span="4"><div class="button"><el-button v-if="!disableConfig" type="primary" @click="saveForm()">保存</el-button><el-button v-if="!disableConfig" type="primary">取消</el-button></div></el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getHostYaml,
|
||||
// getHostNetwork,
|
||||
putHostYaml,
|
||||
putHostNetwork,
|
||||
getNodeNetworks
|
||||
} from '@/api/one-class-page/virtualMachine'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
disableConfig: true,
|
||||
physicalNICList: ['eth0'],
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
customName: '',
|
||||
physicalNIC: '',
|
||||
type: ''
|
||||
},
|
||||
yamlData: '',
|
||||
vlanData: '',
|
||||
// 校验规则
|
||||
rules: {
|
||||
name: [
|
||||
{
|
||||
required: true, // 是否必填
|
||||
message: '名称不能为空', // 规则提示
|
||||
trigger: 'blur' // 何事件触发
|
||||
}
|
||||
]
|
||||
},
|
||||
columns: [
|
||||
{ prop: 'state', label: '状态', formatter: (row) => { return <el-tag type='success'>{row.state}</el-tag> } },
|
||||
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
|
||||
{ prop: 'cpu', label: 'CPU' },
|
||||
{ prop: 'memory', label: '内存' },
|
||||
{ prop: 'ipAddress', label: 'IP地址' },
|
||||
{ prop: 'aliveTime', label: '存活时间' },
|
||||
{ prop: 'more', label: '更多操作', formatter: (row) => {
|
||||
return <div>
|
||||
<el-dropdown>
|
||||
<el-button className='el-dropdown-link' type='primary' icon='el-icon-more' circle>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot='dropdown'>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 暂停 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 开始 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 备份 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 恢复 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 生成模板 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 编辑设置 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 编辑YAML </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row)}> <el-dropdown-item> 下载YAML </el-dropdown-item> </span>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
} }
|
||||
],
|
||||
filterMap: {
|
||||
project: {
|
||||
label: '项目',
|
||||
type: 'select'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$route.query.disableConfig != null && typeof (this.$route.query.disableConfig) !== 'undefined') {
|
||||
if (this.$route.query.disableConfig === 'true') {
|
||||
this.disableConfig = true
|
||||
} else {
|
||||
this.disableConfig = false
|
||||
}
|
||||
}
|
||||
getHostYaml(this.$route.query.name).then(res => {
|
||||
this.formData.name = res.metadata.name
|
||||
this.formData.description = res.metadata.annotations['field.cattle.io/description']
|
||||
this.formData.customName = res.metadata.annotations['harvesterhci.io/host-custom-name']
|
||||
this.yamlData = res
|
||||
})
|
||||
// getHostNetwork(this.$route.query.name).then(res => {
|
||||
// this.formData.type = res.spec.type
|
||||
// this.formData.physicalNIC = res.spec.nic
|
||||
// this.vlanData = res
|
||||
// })
|
||||
getNodeNetworks().then(res => {
|
||||
this.physicalNICList = res.data[this.$route.query.index].status.physicalNICs
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
saveForm() {
|
||||
this.yamlData.metadata.name = this.formData.name
|
||||
this.yamlData.metadata.annotations['field.cattle.io/description'] = this.formData.description
|
||||
this.yamlData.metadata.annotations['harvesterhci.io/host-custom-name'] = this.formData.customName
|
||||
this.yamlData.id = this.yamlData.metadata.name
|
||||
this.vlanData.spec.type = this.formData.type
|
||||
this.vlanData.spec.nic = this.formData.physicalNIC
|
||||
putHostYaml(this.formData.name, this.yamlData).then(res => {
|
||||
this.$notify({
|
||||
message: '成功'
|
||||
})
|
||||
})
|
||||
putHostNetwork(this.formData.name, this.vlanData).then(res => {
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.grid-content {
|
||||
border-radius: 4px;
|
||||
min-height: 36px;
|
||||
}
|
||||
.button{
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,158 @@
|
|||
<template>
|
||||
<div class="podInfo">
|
||||
<el-card class="basicInfo" shadow="never">
|
||||
<img src="@/assets/img/service.png" class="sidebar-logo" alt="容器组">
|
||||
<h4>主机</h4>
|
||||
<span class="tips" />
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<List
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:columns="columns"
|
||||
func-name="getVirtualHostList"
|
||||
:cluster-name="clusterName"
|
||||
:pagination="true"
|
||||
tooltip-effect="dark"
|
||||
/>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
title="开启节点维护模式"
|
||||
:visible.sync="maintainDialogVisible"
|
||||
width="30%"
|
||||
>
|
||||
<p>注意!此操作会迁移当前节点上的所有虚拟机!</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="maintainDialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="maintainEnable()">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import List from '@/components/list'
|
||||
import { getHostYaml, hostAction } from '@/api/one-class-page/virtualMachine'
|
||||
|
||||
export default {
|
||||
components: { List },
|
||||
data() {
|
||||
return {
|
||||
timer: null,
|
||||
timeInterval: 10000,
|
||||
maintainName: '',
|
||||
maintainDialogVisible: false,
|
||||
filterMap: {
|
||||
name: {
|
||||
label: '名称'
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{ prop: 'state', label: '状态', formatter: (row) => { return <el-tag type='success'>{row.state}</el-tag> } },
|
||||
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
|
||||
{ prop: 'hostIP', label: '主机IP' },
|
||||
{ prop: 'cpu', label: 'CPU', formatter: (row) => { return <div>已使用{row.cpuAll}C中的{row.cpuUsed}<el-progress percentage={Number(row.cpuUsePercentage)} ></el-progress></div> } },
|
||||
{ prop: 'memory', label: '内存', formatter: (row) => { return <div>已使用{row.memoryAll}GiB中的{row.memoryUsed}<el-progress percentage={Number(row.memoryUsePercentage)} ></el-progress></div> } },
|
||||
{ prop: 'storageSize', label: '存储空间', formatter: (row) => { return <div>已使用{row.storageAll}TiB中的{row.storageUsed}<el-progress percentage={Number(row.storageUsePercentage)} ></el-progress></div> } },
|
||||
{ prop: 'aliveTime', label: '存活时间' },
|
||||
{ prop: 'more', label: '更多操作', formatter: (row) => {
|
||||
var maintainName = row.isMaintenance ? '关闭维护模式' : '开启维护模式'
|
||||
return <div>
|
||||
<el-dropdown>
|
||||
<el-button size='mini' className='el-dropdown-link' icon='el-icon-more' circle>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot='dropdown'>
|
||||
<span onClick={() => this.clickOption(row, 1)}> <el-dropdown-item> {maintainName}</el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 2)}> <el-dropdown-item> 编辑设置 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 3)}> <el-dropdown-item> 编辑YAML </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 4)}> <el-dropdown-item> 下载YAML </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 5)}> <el-dropdown-item> 删除 </el-dropdown-item> </span>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
} }
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
if (localStorage.getItem('clusterName') === 'default') {
|
||||
return ''
|
||||
} else {
|
||||
return '/clusters/' + localStorage.getItem('clusterName')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.$Api.getUsageStatus().then(usage => {
|
||||
// console.log(usage)
|
||||
// })
|
||||
},
|
||||
beforeDestroy() {
|
||||
// clearInterval(this.timer)
|
||||
// this.timer = null
|
||||
},
|
||||
methods: {
|
||||
viewDetail(row) {
|
||||
this.$router.push({ path: `host/detail`, query: row })
|
||||
},
|
||||
maintainEnable() {
|
||||
this.maintainDialogVisible = false
|
||||
hostAction(this.maintainName, 'enableMaintenanceMode').then(res => {
|
||||
alert('成功')
|
||||
location.reload()
|
||||
})
|
||||
},
|
||||
maintainDisable() {
|
||||
hostAction(this.maintainName, 'disableMaintenanceMode').then(res => {
|
||||
alert('成功')
|
||||
location.reload()
|
||||
})
|
||||
},
|
||||
clickOption(row, command) {
|
||||
switch (command) {
|
||||
case 1:
|
||||
if (row.isMaintenance) {
|
||||
this.maintainName = row.name
|
||||
this.maintainDisable()
|
||||
} else {
|
||||
this.maintainDialogVisible = true
|
||||
this.maintainName = row.name
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
row.disableConfig = false
|
||||
this.$router.push({ path: `host/edit`, query: row })
|
||||
break
|
||||
case 3:
|
||||
row.editYaml = true
|
||||
this.$router.push({ path: `host/detail/yaml`, query: row })
|
||||
break
|
||||
case 4:
|
||||
this.downloadHostYaml(row.name)
|
||||
break
|
||||
default:
|
||||
}
|
||||
},
|
||||
downloadHostYaml(name) {
|
||||
getHostYaml(name).then(res => {
|
||||
var data = JSON.stringify(res)
|
||||
// encodeURIComponent解决中文乱码
|
||||
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(data)
|
||||
// 通过创建a标签实现
|
||||
const link = document.createElement('a')
|
||||
link.href = uri
|
||||
// 对下载的文件命名
|
||||
link.download = name + '.json'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tabs type="border-card" tab-position="left" style="height: 600px;">
|
||||
<el-tab-pane key="" label="基本信息"> <el-card shadow="never">
|
||||
<el-tabs style="height: 600px;">
|
||||
<el-tab-pane key="" label="基本信息">
|
||||
<h5>概览</h5>
|
||||
<FormData :data="formData" :data-map="dataMap" />
|
||||
<el-divider />
|
||||
|
@ -17,19 +17,17 @@
|
|||
<el-divider />
|
||||
<h5>更多数据</h5>
|
||||
<FormData :data="formData" :data-map="dataMap3" />
|
||||
</el-card></el-tab-pane>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane key="virtual" label="虚拟机">
|
||||
<el-card shadow="never">
|
||||
<List
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:columns="columns"
|
||||
func-name="getHostVirtualMachineList"
|
||||
:cluster-name="clusterName"
|
||||
:pagination="true"
|
||||
tooltip-effect="dark"
|
||||
/>
|
||||
</el-card>
|
||||
<List
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:columns="columns"
|
||||
func-name="getHostVirtualMachineList"
|
||||
:cluster-name="clusterName"
|
||||
:pagination="true"
|
||||
tooltip-effect="dark"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
|
|
Loading…
Reference in New Issue