HARVESTER: add Node Scheduling to VM edit page

This commit is contained in:
yuzeng 2021-08-17 10:09:01 +08:00 committed by wujun
parent f6264c81b0
commit 6fdc7e974e
5 changed files with 86 additions and 9 deletions

View File

@ -1,11 +1,13 @@
<script>
import { _VIEW } from '@/config/query-params';
import { mapGetters } from 'vuex';
import { get, isEmpty, clone } from '@/utils/object';
import { NODE } from '@/config/types';
import MatchExpressions from '@/components/form/MatchExpressions';
import LabeledSelect from '@/components/form/LabeledSelect';
import { randomStr } from '@/utils/string';
import ArrayListGrouped from '@/components/form/ArrayListGrouped';
import { NAME as VIRTUAL } from '@/config/product/virtual';
export default {
components: {
@ -55,6 +57,7 @@ export default {
},
computed: {
...mapGetters({ t: 'i18n/t' }),
isView() {
return this.mode === _VIEW;
},
@ -64,6 +67,27 @@ export default {
node() {
return NODE;
},
isHarvester() {
return this.$store.getters['currentProduct'].inStore === VIRTUAL;
},
defaultAddValue() {
const out = { matchExpressions: [] };
if (this.isHarvester) {
out.weight = 1;
}
return out;
},
affinityOptions() {
const out = [this.t('workload.scheduling.affinity.preferred')];
if (!this.isHarvester) {
out.push(this.t('workload.scheduling.affinity.required'));
}
return out;
}
},
methods: {
@ -102,7 +126,7 @@ export default {
},
priorityDisplay(term) {
return term.weight ? this.t('workload.scheduling.affinity.preferred') : this.t('workload.scheduling.affinity.required');
return term.weight || this.isHarvester ? this.t('workload.scheduling.affinity.preferred') : this.t('workload.scheduling.affinity.required');
},
get,
@ -116,12 +140,12 @@ export default {
<template>
<div class="row" @input="update">
<div class="col span-12">
<ArrayListGrouped v-model="allSelectorTerms" class="mt-20" :default-add-value="{matchExpressions:[]}" :add-label="t('workload.scheduling.affinity.addNodeSelector')">
<ArrayListGrouped v-model="allSelectorTerms" class="mt-20" :mode="mode" :default-add-value="defaultAddValue" :add-label="t('workload.scheduling.affinity.addNodeSelector')">
<template #default="props">
<div class="row">
<div class="col span-6">
<LabeledSelect
:options="[t('workload.scheduling.affinity.preferred'),t('workload.scheduling.affinity.required')]"
:options="affinityOptions"
:value="priorityDisplay(props.row.value)"
:label="t('workload.scheduling.affinity.priority')"
:mode="mode"

View File

@ -1,7 +1,9 @@
<script>
import { mapGetters } from 'vuex';
import RadioGroup from '@/components/form/RadioGroup';
import LabeledSelect from '@/components/form/LabeledSelect';
import NodeAffinity from '@/components/form/NodeAffinity';
import { NAME as VIRTUAL } from '@/config/product/virtual';
import { _VIEW } from '@/config/query-params';
import { isEmpty } from '@/utils/object';
@ -56,10 +58,36 @@ export default {
},
computed: {
...mapGetters({ t: 'i18n/t' }),
isView() {
return this.mode === _VIEW;
},
isHarvester() {
return this.$store.getters['currentProduct'].inStore === VIRTUAL;
},
selectNodeOptions() {
const out = [{
label: this.t('workload.scheduling.affinity.anyNode'),
value: null
},
{
label: this.t('workload.scheduling.affinity.specificNode'),
value: 'nodeSelector'
},
{
label: this.t('workload.scheduling.affinity.schedulingRules'),
value: 'affinity'
}];
if (this.isHarvester) {
out.splice(1, 1);
}
return out;
},
},
methods: {
update() {
@ -100,8 +128,7 @@ export default {
<RadioGroup
v-model="selectNode"
name="selectNode"
:options="[null, 'nodeSelector', 'affinity']"
:labels="[ t('workload.scheduling.affinity.anyNode'), t('workload.scheduling.affinity.specificNode'), t('workload.scheduling.affinity.schedulingRules') ]"
:options="selectNodeOptions"
:mode="mode"
@input="update"
/>

View File

@ -1,10 +1,11 @@
<script>
import Tabbed from '@/components/Tabbed';
import Tab from '@/components/Tabbed/Tab';
import { EVENT, HCI, SERVICE } from '@/config/types';
import { EVENT, HCI, SERVICE, NODE } from '@/config/types';
import CreateEditView from '@/mixins/create-edit-view';
import HarvesterMetrics from '@/components/HarvesterMetrics';
import { allHash } from '@/utils/promise';
import NodeScheduling from '@/components/form/NodeScheduling';
import OverviewBasics from './tabs/details/basics';
import OverviewDisks from './tabs/details/disks';
import OverviewNetworks from './tabs/details/networks';
@ -27,6 +28,7 @@ export default {
OverviewNetworks,
OverviewKeypairs,
OverviewCloudConfigs,
NodeScheduling,
Migration,
HarvesterMetrics,
},
@ -70,11 +72,19 @@ export default {
return vmi;
},
nodesIdOptions() {
const nodes = this.$store.getters['virtual/all'](NODE) || [];
return nodes.map(node => node.id);
},
allEvents() {
const inStore = this.$store.getters['currentProduct'].inStore;
return this.$store.getters[`${ inStore }/all`](EVENT);
},
events() {
return this.allEvents.filter((e) => {
const { name, creationTimestamp } = this.value?.metadata || {};
@ -120,14 +130,18 @@ export default {
<OverviewBasics v-model="value" :resource="vmi" mode="view" />
</Tab>
<Tab name="disks" :label="t('harvester.tab.volume')" class="bordered-table" :weight="5">
<Tab name="disks" :label="t('harvester.tab.volume')" class="bordered-table" :weight="6">
<OverviewDisks v-model="value" />
</Tab>
<Tab name="networks" :label="t('harvester.virtualMachine.detail.tabs.networks')" class="bordered-table" :weight="4">
<Tab name="networks" :label="t('harvester.virtualMachine.detail.tabs.networks')" class="bordered-table" :weight="5">
<OverviewNetworks v-model="value" />
</Tab>
<Tab :label="t('workload.container.titles.nodeScheduling')" name="nodeScheduling" :weight="4">
<NodeScheduling :mode="mode" :value="value.spec.template.spec" :nodes="nodesIdOptions" />
</Tab>
<Tab name="keypairs" :label="t('harvester.virtualMachine.detail.tabs.keypairs')" class="bordered-table" :weight="3">
<OverviewKeypairs v-model="value" />
</Tab>

View File

@ -19,6 +19,7 @@ import Network from '@/edit/kubevirt.io.virtualmachine/network';
import ImageSelect from '@/edit/kubevirt.io.virtualmachine/Image';
import CpuMemory from '@/edit/kubevirt.io.virtualmachine/CpuMemory';
import CloudConfig from '@/edit/kubevirt.io.virtualmachine/CloudConfig';
import NodeScheduling from '@/components/form/NodeScheduling';
import { clone } from '@/utils/object';
import { HCI } from '@/config/types';
@ -47,6 +48,7 @@ export default {
CpuMemory,
ImageSelect,
CloudConfig,
NodeScheduling,
},
mixins: [CreateEditView, VM_MIXIN],
@ -465,10 +467,14 @@ export default {
<Network v-model="networkRows" :mode="mode" />
</Tab>
<Tab :label="t('workload.container.titles.nodeScheduling')" name="nodeScheduling" :weight="-3">
<NodeScheduling :mode="mode" :value="spec.template.spec" :nodes="nodesIdOptions" />
</Tab>
<Tab
name="advanced"
:label="t('harvester.tab.advanced')"
:weight="-3"
:weight="-4"
>
<div class="row mb-20">
<div class="col span-6">

View File

@ -132,6 +132,12 @@ export default {
return this.$store.getters['virtual/all'](HCI.VM_TEMPLATE) || [];
},
nodesIdOptions() {
const nodes = this.$store.getters['virtual/all'](NODE) || [];
return nodes.map(node => node.id);
},
memory: {
get() {
return this.spec.template.spec.domain.resources.requests.memory;