This commit is contained in:
jhnine 2024-11-15 17:26:57 +08:00
parent 63296475e5
commit 3ae57a365c
11 changed files with 260 additions and 35 deletions

View File

@ -238,6 +238,7 @@
"password": "Password",
"createVirtualmachine": "Create Virtual Machine",
"createHpcbase": "Create Supercomputing Base Template",
"createVasp": "Create Vasp Task",
"createAibase": "Create Intelligent Computing Task",
"createAiCard": "Create Specific Computing Power Card Task",
"dict": "Dictionary",
@ -568,6 +569,11 @@
"application": "Application",
"deployment": "Deployment",
"instanceCenter": "Instance Center",
"instanceType": "Instance Type"
"instanceType": "Instance Type",
"createVaspTask": "Create Vasp Task",
"partition": "Partition",
"cmdScript": "Script",
"fileUpload": "File Upload",
"uploadSuccess": "Upload Success"
}
}

View File

@ -238,8 +238,9 @@
"password": "密码",
"createVirtualmachine": "创建虚拟机",
"createHpcbase": "创建超算基础模板",
"createVasp": "中国算力网-创建Vasp任务",
"createAibase": "创建智算训练任务",
"createAiCard": "创建指定算力卡训练任务",
"createAiCard": "中国算力网-创建指定算力卡训练任务",
"dict": "字典",
"dictName": "字典名称",
"dictCode": "code",
@ -568,6 +569,11 @@
"application": "应用",
"deployment": "部署",
"instanceCenter": "实例中心",
"instanceType": "实例类型"
"instanceType": "实例类型",
"createVaspTask": "创建Vasp任务",
"partition": "分区",
"cmdScript": "脚本",
"fileUpload": "文件上传",
"uploadSuccess": "上传成功"
}
}

View File

@ -19,3 +19,8 @@ export const getHomeOverview = () => {
export const getSituation = () => {
return request({ url: '/pcm/v1/monitoring/schedule/situation', method: 'get' })
}
export const getCpList = () => {
return request({ url: '/ai4m/v1/screen/resources', method: 'get' })
}

View File

@ -47,6 +47,12 @@ export const addApp = (data) => {
export const addHpcTask = (data) => {
return request({ url: '/pcm/v1/hpc/commitHpcTask', method: 'post', data })
}
export const uploadVaspContent = (data) => {
return request({ url: '/ai4m/v1/sftp/upload', method: 'post', data })
}
export const downloadVaspContent = (params) => {
return request({ url: '/ai4m/v1/sftp/download', method: 'get', params })
}
export const addVirtualMachine = (data) => {
return request({ url: '/pcm/v1/core/commitVmTask', method: 'post', data })
}

View File

@ -99,6 +99,11 @@ export const constantRoutes = [
component: () => import('@/views/monitorSelectPcm/index'),
meta: { title: 'monitorSelectPcm' },
hidden: true
},
{
path: '/resourceList',
component: () => import('@/views/cluster/resourceList'),
hidden: true
}
// {
// path: '/resourceList',

View File

@ -2,13 +2,14 @@
<div>
<Navbar />
<el-card class="list-detail">
<el-page-header content="资源清单" @back="goBack" />
<el-page-header content="算力清单" @back="goBack" />
<List
ref="multipleTable"
class="multipleTable"
:columns="columns"
:pagination="false"
func-name="getServerResourceData"
list-key="data"
:get-list-action="getCpList"
/>
</el-card>
</div>
@ -17,34 +18,38 @@
<script>
import List from '@/components/list'
import Navbar from '@/layout/components/Navbar'
import { getCpList } from '@/api/pcm/dashboard'
export default {
components: { List, Navbar },
data() {
return {
getCpList,
columns: [
{ prop: 'name', label: '资产名称' },
{ prop: 'ip', label: 'ip' },
{ prop: 'publicIp', label: '公网ip' },
{ prop: 'hpcPartition', label: '超算队列' },
{ prop: 'cpuName', label: 'cpu名称' },
{ prop: 'cpuGHz', label: 'cpu单核主频' },
{ prop: 'cpuCores', label: 'cpu单节点核心数' },
{ prop: 'cpuSingleCycle', label: 'cpu单周期指令执行数' },
{ prop: 'cpuGFlops', label: 'cpu理论峰值/GFlops' },
{ prop: 'totalThreads', label: 'cpu单节点线程数' },
{ prop: 'gpuDcu', label: 'gpu或dcu名称' },
{ prop: 'gpuGFlops', label: 'gpu理论峰值/GFlops' },
{ prop: 'memory', label: this.$t('page.memory') },
{ prop: 'num', label: '节点数' },
{ prop: 'region', label: '地域' },
{ prop: 'flops', width: 140, label: '理论峰值/GFlops' }
{ prop: 'name', label: '名称' },
// { prop: 'ip', label: 'ip' },
// { prop: 'publicIp', label: 'ip' },
// { prop: 'hpcPartition', label: '' },
// { prop: 'cpuName', label: 'cpu' },
// { prop: 'cpuGHz', label: 'cpu' },
// { prop: 'cpuCores', label: 'cpu' },
// { prop: 'cpuSingleCycle', label: 'cpu' },
// { prop: 'cpuGFlops', label: 'cpu/GFlops' },
// { prop: 'totalThreads', label: 'cpu线' },
// { prop: 'gpuDcu', label: 'gpudcu' },
// { prop: 'gpuGFlops', label: 'gpu/GFlops' },
// { prop: 'memory', label: '' },
{ prop: 'resourceType', label: '算力资源类型' },
{ prop: 'num', label: '卡数(张)' },
{ prop: 'singleTFLOPS', label: '单卡算力(TFLOPS@FP32)' },
// { prop: 'region', label: '' },
{ prop: 'totalPFLOPS', width: 140, label: '算力总量(PFLOPS@FP32)' }
]
}
},
methods: {
goBack() {
this.$router.push('/cluster/clusterMapViews')
this.$router.push('/monitorSelectPcm')
}
}

View File

@ -2,7 +2,7 @@
<!-- 算力中心总数 -->
<div>
<div class="two">
<div v-for="(item, index) in dataArray" :key="'data'+index">
<div v-for="(item, index) in dataArray" :key="'data'+index" style="cursor: pointer;" @click="item.path && viewMenu(item.path)">
<p class="title">{{ item.name }}</p>
<div class="num">{{ item.value }}</div>
</div>
@ -23,11 +23,13 @@ export default {
dataArray: [
{
name: '算力中心总数(计算域)',
value: '-'
value: '-',
path: 'resourceList'
},
{
name: '已接入算力 POps@FP16',
value: '-'
value: '-',
path: 'resourceList'
},
{
name: '接入集群数',
@ -47,7 +49,10 @@ export default {
}
},
methods: {
viewMenu(path) {
path ? this.$store.dispatch('user/setRouteType', path.split('/')[0]) : {}
this.$router.push({ path: path || `/monitorSelectBk` })
}
}
}

View File

@ -0,0 +1,146 @@
<template>
<div>
<h3> {{ $t('page.createVaspTask') }} </h3>
<el-form
ref="formData"
class="form-wrap"
label-position="left"
:model="formData"
:rules="formDataRules"
>
<el-form-item :label="$t('page.taskName')" prop="name">
<el-input
v-model="formData.name"
:placeholder="$t('page.inputWarn')"
:max-length="30"
/>
</el-form-item>
<el-form-item :label="$t('page.partition')" prop="partition">
<el-input
v-model="formData.partition"
:max-length="30"
/>
</el-form-item>
<el-form-item :label="$t('page.nodeNum')" prop="nNode">
<el-input
v-model="formData.nNode"
/>
</el-form-item>
<el-form-item :label="$t('page.commandContent')" prop="cmdScript">
<el-input
v-model="formData.cmdScript"
type="textarea"
/>
</el-form-item>
<el-form-item :label="$t('page.workMenu')" prop="workDir">
<el-input
v-model="formData.workDir"
/>
</el-form-item>
<el-form-item :label="$t('page.fileUpload')">
<!-- <el-input v-model="taskInput" type="textarea" rows="10" /> -->
<el-upload
ref="upload"
class="upload-demo"
:file-list="fileList"
:auto-upload="false"
action="#"
:multiple="true"
>
<el-button slot="trigger" size="small">选取文件</el-button>
<!-- <el-button size="small" type="primary" @click="confirmUpload">确认上传</el-button> -->
</el-upload>
</el-form-item>
</el-form>
</div>
</template>
<script>
import generate from 'nanoid/generate'
export default {
data() {
return {
formData: {
'name': 'vasptask-' + generate('abcdefghijklmnopqrstuvwxyz', 12),
'partition': 'C64T1',
'nNode': '1',
'workDir': '/vasp',
'cmdScript': '#!/bin/bash\n sbatch vasp.sh'
},
fileList: [],
settingFlag: false
}
},
computed: {
formDataRules() {
return {
name: [
{ required: true, message: this.$t('check.input') + this.$t('message.name') },
{
pattern: /^[a-z]([-a-z0-9]*[a-z0-9])?$/,
message: this.$t('check.inputInvalid')
}
// { validator: this.nameValidator }
],
partition: [
{ required: true, message: this.$t('check.input') + this.$t('page.partition') }
],
cmdScript: [
{ required: true, message: this.$t('check.input') + this.$t('page.cmdScript') }
],
workDir: [
{ required: true, message: this.$t('check.input') + this.$t('page.workMenu') }
],
nNode: [
{ required: true, message: this.$t('check.input') + this.$t('page.nodeNum') }
]
}
}
},
methods: {
submitUpload() {
// console.log(formData)
//
return false
},
checkForm() {
let returnVal
this.$refs.formData.validate((valid) => {
if (valid) {
const form = new FormData()
this.$refs.upload.uploadFiles.forEach((file, index) => {
form.append(`files`, file.raw)
})
form.set('clusterId', '1830873903296155648')
form.set('workDir', this.formData.workDir)
// uploadVaspContent(form).then((e) => {
// if (e.code === 0) {
// this.$message.success(this.$t('page.uploadSuccess'))
const params = {
...this.formData,
fileData: form
}
returnVal = params
// } else {
// this.$message.error(e.data)
// // this.submitLoading = false
// }
// }).catch(e => {
// // this.submitLoading = false
// })
} else {
returnVal = false
}
})
return returnVal
}
}
}
</script>
<style lang="scss">
.form-wrap .el-form-item__label-wrap .el-form-item__label{
text-indent: -1rem!important;
}
</style>

View File

@ -43,7 +43,8 @@
<div class="taskForm">
<div v-show="!selectCluster&&!strategySetting">
<application-form v-show="cpType === 'cloud'&&taskType === 'application'" ref="application" />
<hpc-create v-if="cpType === 'hpc'" ref="hpcBase" />
<hpc-create v-if="cpType === 'hpc'&&taskType === 'hpcBase'" ref="hpcBase" />
<vasp-create v-if="cpType === 'hpc'&&taskType === 'hpcVasp'" ref="hpcVasp" />
<ai-create v-if="cpType === 'ai'&&taskType!=='deductive'" ref="aiBase" :type="taskType" :adapter-id="formData.adapterId" />
<vm-form v-if="taskType === 'virtualmachine'" ref="virtualmachine" />
<deductive-form v-if="taskType === 'deductive'" ref="deductive" :adapter-id="formData.adapterId" />
@ -203,11 +204,11 @@
<el-row type="flex" justify="end">
<el-col :span="2.5">
<el-button size="medium" @click="goBack">{{ $t("message.cancel") }}</el-button>
<el-button v-if="!selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'" size="medium" type="primary" @click="next">{{ $t('message.next') }}</el-button>
<el-button v-if="!selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'&&taskType!=='hpcVasp'" size="medium" type="primary" @click="next">{{ $t('message.next') }}</el-button>
<el-button v-if="selectCluster" size="medium" type="primary" @click="selectCluster=false">{{ $t('message.before') }}</el-button>
<el-button v-if="selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'" size="medium" type="primary" @click="setStrategy">{{ $t('message.next') }}</el-button>
<el-button v-if="strategySetting" size="medium" type="primary" @click="strategySetting=false;selectCluster=true">{{ $t('message.before') }}</el-button>
<el-button v-if="strategySetting || taskType==='aiCard' || taskType==='deductive'" v-loading="submitLoading" size="medium" type="primary" @click="saveForm">{{ $t('message.create') }}</el-button>
<el-button v-if="strategySetting || taskType==='aiCard' || taskType==='deductive' || taskType==='hpcVasp'" v-loading="submitLoading" size="medium" type="primary" @click="saveForm">{{ $t('message.create') }}</el-button>
<!-- <el-button size="medium" type="primary" @click="saveForm">{{ $t("message.easyCreate") }}</el-button> -->
</el-col>
</el-row>
@ -216,9 +217,10 @@
<script>
import List from '@/components/list'
import { addApp, addHpcTask, addAITask, addVirtualMachine, getBalanceById, addDeductiveImageTask, addDeductiveTextTask } from '@/api/task/task'
import { addApp, addHpcTask, addAITask, addVirtualMachine, getBalanceById, addDeductiveImageTask, addDeductiveTextTask, uploadVaspContent } from '@/api/task/task'
import applicationForm from './components/applicationForm'
import hpcCreate from './components/hpcCreate.vue'
import vaspCreate from './components/hpcVasp.vue'
import { getClusterList } from '@/api/container/cluster'
import aiCreate from './components/aiCreate.vue'
import { getAdapterList } from '@/api/pcm/adapter'
@ -228,7 +230,7 @@ import { mapGetters } from 'vuex'
// import jobForm from './components/jobForm.vue'
export default {
components: { applicationForm, List, hpcCreate, aiCreate, vmForm, deductiveForm },
components: { applicationForm, List, hpcCreate, aiCreate, vmForm, deductiveForm, vaspCreate },
data() {
return {
getClusterList,
@ -255,7 +257,8 @@ export default {
'virtualmachine': 'createVirtualmachine'
},
'hpc': {
'hpcBase': 'createHpcbase'
'hpcBase': 'createHpcbase',
'hpcVasp': 'createVasp'
},
'ai': {
'aiBase': 'createAibase',
@ -373,6 +376,10 @@ export default {
list[i] = e.data.list.filter(r => r.type === '2')
break
}
case 'hpcVasp': {
list[i] = e.data.list.filter(r => r.id === '1830873578531196928')
break
}
case 'aiBase': {
list[i] = e.data.list.filter(r => r.type === '1')
break
@ -396,7 +403,7 @@ export default {
},
methods: {
getCluster() {
const query = { 'type': this.taskType === 'application' ? '0' : (this.taskType === 'aiBase' || this.taskType === 'aiCard') ? '1' : this.taskType === 'hpcBase' ? '2' : '0', 'adapterId': this.formData.adapterId, pageNum: 1, pageSize: 1000 }
const query = { 'type': this.taskType === 'application' ? '0' : (this.taskType === 'aiBase' || this.taskType === 'aiCard') ? '1' : (this.taskType === 'hpcBase' || this.taskType === 'hpcVasp') ? '2' : '0', 'adapterId': this.formData.adapterId, pageNum: 1, pageSize: 1000 }
this.getClusterList(query).then(e => {
this.currentClusterList = e.data.list || []
})
@ -498,6 +505,29 @@ export default {
})
break
}
case 'hpcVasp': {
delete formHook.adapterIds
delete formHook.aiClusterIds
formHook.clusterId = '1830873903296155648'
uploadVaspContent(formHook.fileData).then((e) => {
if (e.code === 0) {
// this.$message.success(this.$t('page.uploadSuccess'))
delete formHook.fileData
addHpcTask(formHook).then(() => {
this.$message.success(this.$t('page.createdSuccess'))
this.$router.push({ path: '/taskManagement/taskList' })
}).catch(e => {
this.submitLoading = false
})
} else {
this.$message.error(e.data)
this.submitLoading = false
}
}).catch(() => {
this.submitLoading = false
})
break
}
case 'aiBase': {
formHook.adapterId = formHook.adapterIds[0]
delete formHook.adapterIds

View File

@ -28,7 +28,7 @@
</el-tab-pane> -->
<el-tab-pane v-if="formData.clusterInfos && formData.taskTypeDict !== '11' && formData.taskTypeDict !== '12'" :label="$t('page.taskLog')">
<el-select v-model="cluster" style="width:70%" @change="selectCluster(cluster)">
<el-select v-if="!formData.subTaskInfos[0].workDir" v-model="cluster" style="width:70%" @change="selectCluster(cluster)">
<el-option
v-for="item in formData.clusterInfos"
:key="item.id"
@ -89,7 +89,7 @@
<script>
import List from '@/components/list'
import { FormData } from '@/components/FormData'
import { getTaskDetail, getTaskLog, getDeductiveDetail } from '@/api/task/task'
import { getTaskDetail, getTaskLog, getDeductiveDetail, downloadVaspContent } from '@/api/task/task'
import { mapGetters } from 'vuex'
import bootChart from './components/boot'
@ -168,6 +168,11 @@ export default {
if (this.formData.taskTypeDict === '12') {
this.inferId = this.formData.subTaskInfos[0].id
}
if (res.data.subTaskInfos[0].workDir) {
downloadVaspContent({ workDir: res.data.subTaskInfos[0].workDir, fileName: 'demo.out', clusterId: this.formData.clusterInfos[0].id }).then(e => {
this.log = e
})
}
}
})
},

View File

@ -63,6 +63,12 @@ module.exports = {
changeOrigin: true,
secure: false
},
'^/ai4m': {
ws: false,
target: 'https://ai4m.jointcloud.net:443/',
changeOrigin: true,
secure: false
},
'^/auth': {
ws: false,
target: 'https://comnet.jointcloud.net/',