merge from private

This commit is contained in:
ann 2022-04-01 09:56:37 +08:00
parent b91b7e53f3
commit 8cba583c2e
14 changed files with 28052 additions and 4195 deletions

23724
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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'

View File

@ -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>

View File

@ -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

View File

@ -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 }
// }
// ]
// }
]
}
]

View File

@ -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 }
// }
// ]
// }
]
}]
}

View File

@ -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 }
// }
// ]
}
]
},

View File

@ -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 }

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

7540
yarn.lock

File diff suppressed because it is too large Load Diff