|
| 1 | +import Vue from 'vue' |
1 | 2 | import { typeClouds } from '@/utils/common/hypervisor' |
2 | 3 | import i18n from '@/locales' |
| 4 | +import { sizestr } from '@/utils/utils' |
| 5 | + |
| 6 | +const __cpuNumaPinHVm = new Vue() |
| 7 | +const _cpuNumaPinH = (...args) => __cpuNumaPinHVm.$createElement(...args) |
3 | 8 |
|
4 | 9 | const hypervisorMap = typeClouds.hypervisorMap |
5 | 10 |
|
@@ -924,3 +929,75 @@ export const validateRescueMode = (val) => { |
924 | 929 | } |
925 | 930 | return ret |
926 | 931 | } |
| 932 | + |
| 933 | +/** cpu_numa_pin:每项一行;内存 sizestr;绑定 CPU 取全部 pcpu 排序后合并连续区间 */ |
| 934 | +export const formatSortedPcpuRanges = (sortedPcpus) => { |
| 935 | + if (!sortedPcpus.length) return '-' |
| 936 | + const parts = [] |
| 937 | + let start = sortedPcpus[0] |
| 938 | + let end = sortedPcpus[0] |
| 939 | + for (let i = 1; i < sortedPcpus.length; i++) { |
| 940 | + const cur = sortedPcpus[i] |
| 941 | + if (cur === end + 1) { |
| 942 | + end = cur |
| 943 | + } else { |
| 944 | + parts.push(start === end ? String(start) : `${start}-${end}`) |
| 945 | + start = cur |
| 946 | + end = cur |
| 947 | + } |
| 948 | + } |
| 949 | + parts.push(start === end ? String(start) : `${start}-${end}`) |
| 950 | + return parts.join(',') |
| 951 | +} |
| 952 | + |
| 953 | +const getCpuNumaPinLineData = (item) => { |
| 954 | + const nodeId = item.node_id |
| 955 | + const sizeMb = item.size_mb |
| 956 | + const pin = item.vcpu_pin || [] |
| 957 | + const pcpus = [...new Set( |
| 958 | + pin |
| 959 | + .filter(p => p && typeof p.pcpu === 'number') |
| 960 | + .map(p => p.pcpu), |
| 961 | + )].sort((a, b) => a - b) |
| 962 | + const cpuStr = formatSortedPcpuRanges(pcpus) |
| 963 | + const memStr = sizestr(sizeMb, 'M', 1024) |
| 964 | + return { nodeId, memStr, cpuStr } |
| 965 | +} |
| 966 | + |
| 967 | +export const formatCpuNumaPinLine = (item) => { |
| 968 | + const { nodeId, memStr, cpuStr } = getCpuNumaPinLineData(item) |
| 969 | + return `node:${nodeId} mem: ${memStr} cpu: ${cpuStr}` |
| 970 | +} |
| 971 | + |
| 972 | +const CPU_NUMA_PIN_LINE_GAP = '12px' |
| 973 | + |
| 974 | +export const formatCpuNumaPin = (row) => { |
| 975 | + const raw = row.cpu_numa_pin |
| 976 | + if (raw === undefined || raw === null || raw === '') return '-' |
| 977 | + let arr = raw |
| 978 | + if (typeof raw === 'string') { |
| 979 | + try { |
| 980 | + arr = JSON.parse(raw) |
| 981 | + } catch (e) { |
| 982 | + return '-' |
| 983 | + } |
| 984 | + } |
| 985 | + if (!Array.isArray(arr) || arr.length === 0) return '-' |
| 986 | + return _cpuNumaPinH('div', arr.map((item, idx) => { |
| 987 | + const { nodeId, memStr, cpuStr } = getCpuNumaPinLineData(item) |
| 988 | + return _cpuNumaPinH('div', { |
| 989 | + key: idx, |
| 990 | + style: { |
| 991 | + display: 'flex', |
| 992 | + flexWrap: 'wrap', |
| 993 | + alignItems: 'center', |
| 994 | + columnGap: CPU_NUMA_PIN_LINE_GAP, |
| 995 | + rowGap: '4px', |
| 996 | + }, |
| 997 | + }, [ |
| 998 | + _cpuNumaPinH('span', `node: ${nodeId}`), |
| 999 | + _cpuNumaPinH('span', `mem: ${memStr}`), |
| 1000 | + _cpuNumaPinH('span', `cpu: ${cpuStr}`), |
| 1001 | + ]) |
| 1002 | + })) |
| 1003 | +} |
0 commit comments