480 lines
15 KiB
Vue
480 lines
15 KiB
Vue
|
<template>
|
|||
|
<div>
|
|||
|
<cb-advance-table title="" :data="data" :params="params" :columns="columns" :get-list="getList" :total="total" @select="handleSelectItem" @select-all="handleSelectAll" :loading="loading" :search-configs="searchConfigs">
|
|||
|
<template v-slot:action>
|
|||
|
<el-button type="primary" @click="handleAdd()"> 新增 </el-button>
|
|||
|
</template>
|
|||
|
<template #instanceId="val, record">
|
|||
|
<span class="detail-href" @click="getDiskList(record)">{{ val }}</span>
|
|||
|
</template>
|
|||
|
<template #state="val">
|
|||
|
<cb-status-icon :type="val | bareMetalColor">{{ val | bareMetalState }}</cb-status-icon>
|
|||
|
</template>
|
|||
|
<template #operate="val, record">
|
|||
|
<el-button type="text" @click="reboot(record)"> 重启 </el-button>
|
|||
|
<div class="action-divider"></div>
|
|||
|
<el-button type="text" @click="bootup(record)"> 开机 </el-button>
|
|||
|
<div class="action-divider"></div>
|
|||
|
<el-button type="text" @click="stop(record)"> 关机 </el-button>
|
|||
|
<div class="action-divider"></div>
|
|||
|
<el-dropdown trigger="click">
|
|||
|
<span class="el-dropdown-link"> 更多<i class="el-icon-arrow-down el-icon--right"></i> </span>
|
|||
|
<el-dropdown-menu slot="dropdown">
|
|||
|
<el-dropdown-item @click.native="edt(record)" :disabled="record.status == 'PENDING'"> 退还 </el-dropdown-item>
|
|||
|
<el-dropdown-item @click.native="reload(record)"> 重装 </el-dropdown-item>
|
|||
|
<el-dropdown-item @click.native="edit(record)"> 改名 </el-dropdown-item>
|
|||
|
<el-dropdown-item @click.native="edit(record)" disabled> 分配 </el-dropdown-item>
|
|||
|
<el-dropdown-item @click.native="edit(record)" disabled> 回收 </el-dropdown-item>
|
|||
|
</el-dropdown-menu>
|
|||
|
</el-dropdown>
|
|||
|
</template>
|
|||
|
</cb-advance-table>
|
|||
|
<!-- 更改名称 -->
|
|||
|
<el-dialog width="30%" title="更改名称" :close-on-click-modal="false" v-if="editData.dialog" :visible.sync="editData.dialog">
|
|||
|
<cb-form :model="editData.data" ref="editData" label-width="50px">
|
|||
|
<cb-form-item label="名称" prop="newName">
|
|||
|
<el-input v-model="editData.data.newName"></el-input>
|
|||
|
</cb-form-item>
|
|||
|
</cb-form>
|
|||
|
<div slot="footer" class="dialog-footer">
|
|||
|
<el-button type="ghost" @click.native="editData.dialog = false">取消</el-button>
|
|||
|
<el-button type="primary" @click.native="editSubmit">确定</el-button>
|
|||
|
</div>
|
|||
|
</el-dialog>
|
|||
|
<!-- 硬盘列表 -->
|
|||
|
<el-dialog width="50%" title="硬盘列表" :close-on-click-modal="false" v-if="diskSign" :visible.sync="diskSign">
|
|||
|
<cb-smart-table ref="list" :data="diskData" :rows="5" style="margin-top: 10px">
|
|||
|
<el-table-column show-overflow-tooltip label="硬盘ID" prop="diskId"></el-table-column>
|
|||
|
<el-table-column show-overflow-tooltip label="硬盘名称" prop="diskName"></el-table-column>
|
|||
|
<el-table-column show-overflow-tooltip label="硬盘大小" prop="diskSize"></el-table-column>
|
|||
|
<el-table-column show-overflow-tooltip label="硬盘类型" prop="diskType"></el-table-column>
|
|||
|
<el-table-column show-overflow-tooltip label="创建时间" prop="createdTime"></el-table-column>
|
|||
|
</cb-smart-table>
|
|||
|
<div slot="footer" class="dialog-footer">
|
|||
|
<el-button type="ghost" @click.native="diskSign = false">取消</el-button>
|
|||
|
<el-button type="primary" @click.native="diskSign = false">确定</el-button>
|
|||
|
</div>
|
|||
|
</el-dialog>
|
|||
|
<!-- 重装 -->
|
|||
|
<el-dialog width="45%" title="重装" :close-on-click-modal="false" v-if="Reloading" :visible.sync="Reloading" :append-to-body="true">
|
|||
|
<cb-form :model="reloadData.data" ref="reloadData" label-width="140px">
|
|||
|
<h3>当前配置</h3>
|
|||
|
<cb-form-item label="镜像名称">{{ reloadData.row.operatingSystemType }}</cb-form-item>
|
|||
|
<cb-form-item label="RAID类型">{{ reloadData.row.raidType }}</cb-form-item>
|
|||
|
<h3>重装为</h3>
|
|||
|
<cb-form-item label="镜像类型">{{ reloadData.row.operatingSystemType }}</cb-form-item>
|
|||
|
<cb-form-item label="镜像">
|
|||
|
<el-select v-model="reloadData.data.operatingSystem" placeholder="请选择镜像">
|
|||
|
<el-option v-for="item in selectCombo.operatingSystem.linux" :key="item" :label="item" :value="item"> </el-option>
|
|||
|
</el-select>
|
|||
|
</cb-form-item>
|
|||
|
<cb-form-item label="RAID类型" prop="raidType">
|
|||
|
<el-select v-model="reloadData.data.raidType" placeholder="请选择类型">
|
|||
|
<el-option v-for="item in selectCombo.raidType" :key="item" :label="item" :value="item"> </el-option>
|
|||
|
</el-select>
|
|||
|
</cb-form-item>
|
|||
|
<cb-form-item label="主机安全agent">
|
|||
|
<el-radio v-model="reloadData.data.enhancedService.SecurityService.Enabled" label="true">开启</el-radio>
|
|||
|
<el-radio v-model="reloadData.data.enhancedService.SecurityService.Enabled" label="false">关闭</el-radio>
|
|||
|
</cb-form-item>
|
|||
|
<cb-form-item label="新密码" prop="loginSettings.Password" validate="required,tceClusterPassword" required-message="请输入密码">
|
|||
|
<el-input v-model="reloadData.data.loginSettings.Password" show-password></el-input>
|
|||
|
<span style="display: block; font-size: 8px">请输入8~16位密码,密码需要包含字母,数字和特殊符号三种中的三种</span>
|
|||
|
</cb-form-item>
|
|||
|
<cb-form-item label="确认密码" prop="loginSettings.Password_config" validate="required,tceClusterPassword" required-message="请输入确认密码">
|
|||
|
<el-input v-model="reloadData.data.loginSettings.Password_config" show-password></el-input>
|
|||
|
</cb-form-item>
|
|||
|
</cb-form>
|
|||
|
<div slot="footer" class="dialog-footer">
|
|||
|
<el-button type="ghost" @click.native="Reloading = false">取消</el-button>
|
|||
|
<el-button type="primary" :loading="subLoading" @click.native="ok">确定</el-button>
|
|||
|
</div>
|
|||
|
</el-dialog>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import { bareMetalState, bareMetalColor } from 'filters'
|
|||
|
import { getBareMetalList, modifyBareMetal, bmsReboot, bmsBootUp, bmsStop, bmsedt, getDisk, getCombo, bmsReload } from 'views/resource/ctstack/services/bms.js'
|
|||
|
import { removeVmUsers } from 'views/resource/ctstack/services/vm.js'
|
|||
|
const columns = [
|
|||
|
{
|
|||
|
type: 'selection'
|
|||
|
},
|
|||
|
{
|
|||
|
label: 'ID',
|
|||
|
prop: 'instanceId',
|
|||
|
disabled: true,
|
|||
|
scopedSlots: { customRender: 'instanceId' }
|
|||
|
},
|
|||
|
{
|
|||
|
label: '名称',
|
|||
|
prop: 'instanceName',
|
|||
|
disabled: true
|
|||
|
},
|
|||
|
{
|
|||
|
label: '状态',
|
|||
|
prop: 'status',
|
|||
|
scopedSlots: { customRender: 'state' }
|
|||
|
},
|
|||
|
{
|
|||
|
label: '机型',
|
|||
|
prop: 'flavorName'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '可用区',
|
|||
|
prop: 'zone'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '私有网络',
|
|||
|
prop: 'vpcId'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '子网',
|
|||
|
prop: 'subnetId'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '公网IP',
|
|||
|
prop: ''
|
|||
|
},
|
|||
|
{
|
|||
|
label: '内网IP',
|
|||
|
prop: ''
|
|||
|
},
|
|||
|
{
|
|||
|
label: '操作系统',
|
|||
|
prop: 'operatingSystemType'
|
|||
|
},
|
|||
|
{
|
|||
|
label: 'RAID类型',
|
|||
|
prop: 'raidType'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '操作',
|
|||
|
disabled: true,
|
|||
|
width: '220px',
|
|||
|
scopedSlots: { customRender: 'operate' }
|
|||
|
}
|
|||
|
]
|
|||
|
export default {
|
|||
|
components: {},
|
|||
|
props: {
|
|||
|
platformObject: {
|
|||
|
type: Object,
|
|||
|
default: function () {
|
|||
|
return {
|
|||
|
huaweiId: -1,
|
|||
|
operate: -1
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
columns,
|
|||
|
loading: false,
|
|||
|
subLoading: false,
|
|||
|
params: {
|
|||
|
page: 1,
|
|||
|
rows: 10
|
|||
|
},
|
|||
|
data: [],
|
|||
|
total: 0,
|
|||
|
searchConfigs: [{ type: 'Const', value: 'vendorId', initValue: this.platformObject.vendorId }],
|
|||
|
// 编辑数据
|
|||
|
editData: {
|
|||
|
dialog: false,
|
|||
|
data: {}
|
|||
|
},
|
|||
|
diskSign: false,
|
|||
|
diskData: [],
|
|||
|
// 重装
|
|||
|
Reloading: false,
|
|||
|
ruleForm: {},
|
|||
|
reloadData: {
|
|||
|
data: {
|
|||
|
instanceId: '',
|
|||
|
raidType: '',
|
|||
|
operatingSystemType: '',
|
|||
|
operatingSystem: '',
|
|||
|
loginSettings: {
|
|||
|
Password: '',
|
|||
|
Password_config: ''
|
|||
|
},
|
|||
|
enhancedService: {
|
|||
|
SecurityService: {
|
|||
|
Enabled: ''
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
row: {}
|
|||
|
},
|
|||
|
comboData: '',
|
|||
|
selectCombo: {},
|
|||
|
assignData: {
|
|||
|
dialog: false,
|
|||
|
data: {}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
methods: {
|
|||
|
// 重装
|
|||
|
ok() {
|
|||
|
this.$refs.reloadData.validate(valid => {
|
|||
|
if (valid) {
|
|||
|
this.subLoading = true
|
|||
|
if (this.reloadData.data.loginSettings.Password !== this.reloadData.data.loginSettings.Password_config) {
|
|||
|
this.$message.error('两次密码输入不一致')
|
|||
|
this.subLoading = false
|
|||
|
} else {
|
|||
|
this.reloadData.data.loginSettings.Password = window.btoa(this.reloadData.data.loginSettings.Password)
|
|||
|
bmsReload(this.platformObject.vendorId, this.reloadData.data).then(res => {
|
|||
|
this.subLoading = false
|
|||
|
if (res.success) {
|
|||
|
this.$message.success(res.message)
|
|||
|
this.Reloading = false
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
reload(row) {
|
|||
|
const params = {
|
|||
|
zone: ['yfm14az1']
|
|||
|
}
|
|||
|
getCombo(this.platformObject.vendorId, params).then(res => {
|
|||
|
this.comboData = res.data.flavorSet
|
|||
|
this.Reloading = true
|
|||
|
this.reloadData.row = row
|
|||
|
this.reloadData.data = {
|
|||
|
instanceId: row.instanceId,
|
|||
|
raidType: row.raidType,
|
|||
|
operatingSystemType: row.operatingSystemType,
|
|||
|
operatingSystem: row.operatingSystem,
|
|||
|
loginSettings: {
|
|||
|
Password: ''
|
|||
|
},
|
|||
|
enhancedService: {
|
|||
|
SecurityService: {
|
|||
|
Enabled: 'false'
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
this.comboData.forEach(item => {
|
|||
|
if (item.flavorId == row.flavorId) {
|
|||
|
this.selectCombo = item
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
},
|
|||
|
// 获取套参
|
|||
|
getArea() {
|
|||
|
// 获取套餐
|
|||
|
const params = {
|
|||
|
zone: ['yfm14az1']
|
|||
|
}
|
|||
|
getCombo(this.platformObject.vendorId, params).then(res => {
|
|||
|
this.comboData = res.data.flavorSet
|
|||
|
})
|
|||
|
},
|
|||
|
// 获取硬盘列表
|
|||
|
getDiskList(row) {
|
|||
|
this.diskSign = true
|
|||
|
getDisk({ id: row.id }).then(res => {
|
|||
|
this.diskData = res.data
|
|||
|
})
|
|||
|
},
|
|||
|
handleAdd() {
|
|||
|
this.$router.push({ name: 'ctstackAddBareMetal', query: { vendorId: this.platformObject.vendorId } })
|
|||
|
},
|
|||
|
// 退还实例
|
|||
|
edt(row) {
|
|||
|
this.$confirm('此操作将退还实例,退回后,磁盘将被格式化且不可恢复,请提前备份数据。物理服务器关联的网络资源将自动解除。是否继续?', '提示', {
|
|||
|
confirmButtonText: '退还',
|
|||
|
cancelButtonText: '取消',
|
|||
|
type: 'warning'
|
|||
|
}).then(() => {
|
|||
|
this.$cmpDelete(close => {
|
|||
|
bmsedt([row.instanceId]).then(data => {
|
|||
|
if (data.success) {
|
|||
|
this.$message({
|
|||
|
type: 'success',
|
|||
|
message: data.message
|
|||
|
})
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 5000)
|
|||
|
close()
|
|||
|
}
|
|||
|
})
|
|||
|
})
|
|||
|
})
|
|||
|
},
|
|||
|
reboot(row) {
|
|||
|
bmsReboot({ id: row.id }).then(data => {
|
|||
|
if (data.success) {
|
|||
|
this.$message({
|
|||
|
type: 'success',
|
|||
|
message: data.message
|
|||
|
})
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 2000)
|
|||
|
}
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 70000)
|
|||
|
})
|
|||
|
},
|
|||
|
bootup(row) {
|
|||
|
bmsBootUp({ id: row.id }).then(data => {
|
|||
|
if (data.success) {
|
|||
|
this.$message({
|
|||
|
type: 'success',
|
|||
|
message: data.message
|
|||
|
})
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 2000)
|
|||
|
}
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 25000)
|
|||
|
})
|
|||
|
},
|
|||
|
stop(row) {
|
|||
|
bmsStop({ id: row.id }).then(data => {
|
|||
|
if (data.success) {
|
|||
|
this.$message({
|
|||
|
type: 'success',
|
|||
|
message: data.message
|
|||
|
})
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 2000)
|
|||
|
}
|
|||
|
setTimeout(() => {
|
|||
|
this.getList()
|
|||
|
}, 45000)
|
|||
|
})
|
|||
|
},
|
|||
|
edit(row) {
|
|||
|
this.editData = {
|
|||
|
dialog: true,
|
|||
|
data: {
|
|||
|
id: row.id,
|
|||
|
instanceId: row.instanceId,
|
|||
|
newName: row.instanceName
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
editSubmit() {
|
|||
|
this.$refs.editData.validate(valid => {
|
|||
|
if (valid) {
|
|||
|
modifyBareMetal(this.editData.data).then(res => {
|
|||
|
if (res.success) {
|
|||
|
this.$message.success(res.message)
|
|||
|
this.editData.dialog = false
|
|||
|
this.getList()
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
// 全选
|
|||
|
handleSelectAll(selection) {
|
|||
|
this.refreshId()
|
|||
|
if (selection.length) {
|
|||
|
// 全选情况下
|
|||
|
selection.forEach(item => {
|
|||
|
if (this.idList.indexOf(item.id) == -1) {
|
|||
|
this.selectList.push(item)
|
|||
|
}
|
|||
|
})
|
|||
|
} else {
|
|||
|
// 全不选情况下
|
|||
|
this.list.forEach(item => {
|
|||
|
if (this.idList.indexOf(item.id) > -1) {
|
|||
|
for (let j = 0; j < this.selectList.length; j++) {
|
|||
|
const row = this.selectList[j]
|
|||
|
if (item.id == row.id) {
|
|||
|
this.selectList.splice(j, 1)
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
assign(row) {
|
|||
|
this.assignData = {
|
|||
|
dialog: true,
|
|||
|
data: {
|
|||
|
type: 'tenant',
|
|||
|
ids: [row.id],
|
|||
|
resourceCategory: 'Bms',
|
|||
|
vendorType: 'CTSTACK'
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
recycle(row) {
|
|||
|
this.$confirm('确认回收该资源嘛?', '提示', {
|
|||
|
confirmButtonText: '确定',
|
|||
|
cancelButtonText: '取消',
|
|||
|
type: 'warning'
|
|||
|
}).then(() => {
|
|||
|
const params = {
|
|||
|
ids: [row.id],
|
|||
|
resourceCategory: 'Bms',
|
|||
|
vendorType: 'CTSTACK'
|
|||
|
}
|
|||
|
removeVmUsers(params).then(data => {
|
|||
|
this.$message.success(data.message)
|
|||
|
this.getList()
|
|||
|
})
|
|||
|
})
|
|||
|
},
|
|||
|
getList() {
|
|||
|
this.loading = true
|
|||
|
// const params = {
|
|||
|
// page: this.params.page,
|
|||
|
// rows: this.params.rows,
|
|||
|
// params: JSON.stringify([{
|
|||
|
// param: {
|
|||
|
// vendorId: this.platformObject.vendorId,
|
|||
|
// },
|
|||
|
// sign: 'EQ'
|
|||
|
// }])
|
|||
|
// }
|
|||
|
getBareMetalList(this.params)
|
|||
|
.then(res => {
|
|||
|
if (res.success) {
|
|||
|
this.data = res.data.rows
|
|||
|
this.total = res.data.total
|
|||
|
}
|
|||
|
})
|
|||
|
.finally(() => {
|
|||
|
this.loading = false
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
watch: {
|
|||
|
platformObject: {
|
|||
|
handler(newVal, oldVal) {
|
|||
|
this.searchConfigs = [{ type: 'Const', value: 'vendorId', initValue: this.platformObject.vendorId }]
|
|||
|
},
|
|||
|
deep: true
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
<style lang="scss" scoped>
|
|||
|
.el-select {
|
|||
|
width: 300px;
|
|||
|
}
|
|||
|
.el-input {
|
|||
|
width: 300px;
|
|||
|
}
|
|||
|
</style>
|