mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2025-12-13 13:11:43 +00:00
feat: add kubevirt migration setting (#577)
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
This commit is contained in:
parent
5fae6c3087
commit
7e0a9dcd80
154
pkg/harvester/components/settings/kubevirt-migration.vue
Normal file
154
pkg/harvester/components/settings/kubevirt-migration.vue
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
<script>
|
||||||
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||||
|
import { RadioGroup } from '@components/Form/Radio';
|
||||||
|
import UnitInput from '@shell/components/form/UnitInput';
|
||||||
|
import { MEBIBYTE } from '../../utils/unit';
|
||||||
|
import { Banner } from '@components/Banner';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'KubevirtMigration',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
LabeledInput,
|
||||||
|
UnitInput,
|
||||||
|
RadioGroup,
|
||||||
|
Banner
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
registerBeforeHook: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
value: '',
|
||||||
|
default: '{}'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const migration = this.parseJSON(this.value?.value) || this.parseJSON(this.value?.default) || {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
MEBIBYTE,
|
||||||
|
migration,
|
||||||
|
parseError: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.registerBeforeHook?.(this.willSave, 'willSave');
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
parseJSON(string) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(string);
|
||||||
|
} catch (e) {
|
||||||
|
this.parseError = this.t('kubevirtMigration.parseError', { error: e.message });
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('Failed to parse JSON:', e.message);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateValue() {
|
||||||
|
if (this.value) {
|
||||||
|
this.value.value = JSON.stringify(this.migration);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
useDefault() {
|
||||||
|
if (this.value?.default) {
|
||||||
|
const defaultMigration = this.parseJSON(this.value.default) || {};
|
||||||
|
|
||||||
|
this.migration = defaultMigration;
|
||||||
|
this.updateValue();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async willSave() {
|
||||||
|
this.updateValue();
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Banner
|
||||||
|
v-if="parseError"
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
|
{{ parseError }}
|
||||||
|
</Banner>
|
||||||
|
|
||||||
|
<div class="migration-field">
|
||||||
|
<LabeledInput
|
||||||
|
v-model:value.number="migration.parallelMigrationsPerCluster"
|
||||||
|
:label="t('harvester.setting.kubevirtMigration.parallelMigrationsPerCluster')"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
/>
|
||||||
|
<LabeledInput
|
||||||
|
v-model:value.number="migration.parallelOutboundMigrationsPerNode"
|
||||||
|
:label="t('harvester.setting.kubevirtMigration.parallelOutboundMigrationsPerNode')"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
/>
|
||||||
|
<UnitInput
|
||||||
|
v-model:value="migration.bandwidthPerMigration"
|
||||||
|
min="0"
|
||||||
|
:label="t('harvester.setting.kubevirtMigration.bandwidthPerMigration')"
|
||||||
|
:mode="mode"
|
||||||
|
:suffix="MEBIBYTE"
|
||||||
|
:tooltip="t('harvester.setting.kubevirtMigration.bandwidthPerMigrationTooltip', _, true)"
|
||||||
|
/>
|
||||||
|
<UnitInput
|
||||||
|
v-model:value="migration.completionTimeoutPerGiB"
|
||||||
|
:label="t('harvester.setting.kubevirtMigration.completionTimeoutPerGiB')"
|
||||||
|
:mode="mode"
|
||||||
|
:suffix="migration.completionTimeoutPerGiB === 1 ? 'Second' : 'Seconds'"
|
||||||
|
min="10"
|
||||||
|
/>
|
||||||
|
<UnitInput
|
||||||
|
v-model:value="migration.progressTimeout"
|
||||||
|
:label="t('harvester.setting.kubevirtMigration.progressTimeout')"
|
||||||
|
:mode="mode"
|
||||||
|
:suffix="migration.progressTimeout === 1 ? 'Second' : 'Seconds'"
|
||||||
|
min="10"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-for="field in ['allowAutoConverge','allowPostCopy','unsafeMigrationOverride','allowWorkloadDisruption','disableTLS','matchSELinuxLevelOnMigration']"
|
||||||
|
:key="field"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="mb-5"
|
||||||
|
:for="field"
|
||||||
|
>{{ t(`harvester.setting.kubevirtMigration.${field}`) }}</label>
|
||||||
|
<RadioGroup
|
||||||
|
:id="field"
|
||||||
|
v-model:value="migration[field]"
|
||||||
|
:options="[
|
||||||
|
{ label: t('advancedSettings.edit.trueOption'), value: true },
|
||||||
|
{ label: t('advancedSettings.edit.falseOption'), value: false },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.migration-field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -52,7 +52,8 @@ const FEATURE_FLAGS = {
|
|||||||
'v1.7.0': [
|
'v1.7.0': [
|
||||||
'vmMachineTypeAuto',
|
'vmMachineTypeAuto',
|
||||||
'lhV2VolExpansion',
|
'lhV2VolExpansion',
|
||||||
'l2VlanTrunkMode'
|
'l2VlanTrunkMode',
|
||||||
|
'kubevirtMigration'
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,8 @@ export const HCI_SETTING = {
|
|||||||
UPGRADE_CONFIG: 'upgrade-config',
|
UPGRADE_CONFIG: 'upgrade-config',
|
||||||
VM_MIGRATION_NETWORK: 'vm-migration-network',
|
VM_MIGRATION_NETWORK: 'vm-migration-network',
|
||||||
RANCHER_CLUSTER: 'rancher-cluster',
|
RANCHER_CLUSTER: 'rancher-cluster',
|
||||||
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio'
|
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio',
|
||||||
|
KUBEVIRT_MIGRATION: 'kubevirt-migration'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HCI_ALLOWED_SETTINGS = {
|
export const HCI_ALLOWED_SETTINGS = {
|
||||||
@ -115,6 +116,9 @@ export const HCI_ALLOWED_SETTINGS = {
|
|||||||
[HCI_SETTING.VM_MIGRATION_NETWORK]: {
|
[HCI_SETTING.VM_MIGRATION_NETWORK]: {
|
||||||
kind: 'json', from: 'import', canReset: true, featureFlag: 'vmNetworkMigration',
|
kind: 'json', from: 'import', canReset: true, featureFlag: 'vmNetworkMigration',
|
||||||
},
|
},
|
||||||
|
[HCI_SETTING.KUBEVIRT_MIGRATION]: {
|
||||||
|
kind: 'json', from: 'import', canReset: true, featureFlag: 'kubevirtMigration',
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HCI_SINGLE_CLUSTER_ALLOWED_SETTING = {
|
export const HCI_SINGLE_CLUSTER_ALLOWED_SETTING = {
|
||||||
|
|||||||
@ -296,4 +296,9 @@ export default {
|
|||||||
:deep() .edit-help code {
|
:deep() .edit-help code {
|
||||||
padding: 1px 5px;
|
padding: 1px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::v-deep(.banner__content.closable) {
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1268,6 +1268,21 @@ harvester:
|
|||||||
ntpServers:
|
ntpServers:
|
||||||
isNotIPV4: The address you entered is not IPv4 or host. Please enter a valid IPv4 address or a host address.
|
isNotIPV4: The address you entered is not IPv4 or host. Please enter a valid IPv4 address or a host address.
|
||||||
isDuplicate: There are duplicate NTP server configurations.
|
isDuplicate: There are duplicate NTP server configurations.
|
||||||
|
kubevirtMigration:
|
||||||
|
parseError: "Failed to parse configuration: {error}"
|
||||||
|
parallelMigrationsPerCluster: "Parallel Migrations Per Cluster"
|
||||||
|
parallelOutboundMigrationsPerNode: "Parallel Outbound Migrations Per Node"
|
||||||
|
bandwidthPerMigration: "Bandwidth Per Migration"
|
||||||
|
bandwidthPerMigrationTooltip: '0 is KubeVirt default, representing unlimited bandwidth'
|
||||||
|
completionTimeoutPerGiB: "Completion Timeout Per GiB"
|
||||||
|
progressTimeout: "Progress Timeout"
|
||||||
|
allowAutoConverge: "Allow Auto Converge"
|
||||||
|
allowPostCopy: "Allow Post Copy"
|
||||||
|
unsafeMigrationOverride: "Unsafe Migration Override"
|
||||||
|
allowWorkloadDisruption: "Allow Workload Disruption"
|
||||||
|
disableTLS: "Disable TLS"
|
||||||
|
matchSELinuxLevelOnMigration: "Match SELinux Level On Migration"
|
||||||
|
|
||||||
cloudTemplate:
|
cloudTemplate:
|
||||||
label: Cloud Configuration Templates
|
label: Cloud Configuration Templates
|
||||||
templateType: Template Type
|
templateType: Template Type
|
||||||
@ -1782,6 +1797,7 @@ advancedSettings:
|
|||||||
'harv-vm-migration-network': 'Segregated network for VM migration traffic.'
|
'harv-vm-migration-network': 'Segregated network for VM migration traffic.'
|
||||||
'harv-rancher-cluster': 'Configure Rancher cluster integration settings for guest cluster management.'
|
'harv-rancher-cluster': 'Configure Rancher cluster integration settings for guest cluster management.'
|
||||||
'harv-max-hotplug-ratio': 'The ratio for kubevirt to limit the maximum CPU and memory that can be hotplugged to a VM. The value could be an integer between 1 and 20, default to 4.'
|
'harv-max-hotplug-ratio': 'The ratio for kubevirt to limit the maximum CPU and memory that can be hotplugged to a VM. The value could be an integer between 1 and 20, default to 4.'
|
||||||
|
'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.'
|
||||||
|
|
||||||
typeLabel:
|
typeLabel:
|
||||||
kubevirt.io.virtualmachine: |-
|
kubevirt.io.virtualmachine: |-
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user