Compare commits

..
Author SHA1 Message Date
renovate[bot] 4542301d6e deps: update minor dependencies 2026-10-05 14:47:31 +00:00
19 changed files with 72 additions and 239 deletions
@@ -53,7 +53,7 @@ jobs:
- name: Setup Helm - name: Setup Helm
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3 uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3
with: with:
version: v3.8.0 version: v3.22.0
- name: Setup Nodejs with yarn install - name: Setup Nodejs with yarn install
uses: ./.github/actions/setup uses: ./.github/actions/setup
@@ -78,7 +78,7 @@ jobs:
- name: Setup Helm - name: Setup Helm
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3 uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3
with: with:
version: v3.8.0 version: v3.22.0
- name: Build Helm charts - name: Build Helm charts
run: | run: |
+1 -1
View File
@@ -22,7 +22,7 @@
"@xterm/addon-webgl": "0.19.0", "@xterm/addon-webgl": "0.19.0",
"@xterm/addon-canvas": "0.7.0", "@xterm/addon-canvas": "0.7.0",
"node-polyfill-webpack-plugin": "^3.0.0", "node-polyfill-webpack-plugin": "^3.0.0",
"elkjs": "^0.11.0", "elkjs": "^0.12.0",
"vue-draggable-next": "^2.2.1", "vue-draggable-next": "^2.2.1",
"yaml": "^2.5.1" "yaml": "^2.5.1"
}, },
+2 -5
View File
@@ -76,15 +76,12 @@ const FEATURE_FLAGS = {
'longhornV2HugepageSettings', 'longhornV2HugepageSettings',
'staticIPForVM', 'staticIPForVM',
'fsFreezeDeadline', 'fsFreezeDeadline',
'highPerformanceStorage',
], ],
'v1.9.1': [ 'v1.9.1': [
'lvmDmThinOnly', 'lvmDmThinOnly',
'highPerformanceStorage',
],
'v1.10.0': [
'maintenanceModeConditions',
'maintenanceModeDrainTimeoutSetting',
], ],
'v1.10.0': [],
}; };
const generateFeatureFlags = () => { const generateFeatureFlags = () => {
+1 -1
View File
@@ -22,7 +22,7 @@ export const HCI = {
VM_NAME_PREFIX: 'harvesterhci.io/vmNamePrefix', VM_NAME_PREFIX: 'harvesterhci.io/vmNamePrefix',
VM_DISPLAY_NAME: 'harvesterhci.io/vmDisplayName', VM_DISPLAY_NAME: 'harvesterhci.io/vmDisplayName',
VM_RESERVED_MEMORY: 'harvesterhci.io/reservedMemory', VM_RESERVED_MEMORY: 'harvesterhci.io/reservedMemory',
MAINTENANCE_STATUS: 'harvesterhci.io/maintain-status', // Deprecated >= v1.10.0 MAINTENANCE_STATUS: 'harvesterhci.io/maintain-status',
HOST_CUSTOM_NAME: 'harvesterhci.io/host-custom-name', HOST_CUSTOM_NAME: 'harvesterhci.io/host-custom-name',
HOST_CONSOLE_URL: 'harvesterhci.io/host-console-url', HOST_CONSOLE_URL: 'harvesterhci.io/host-console-url',
RESTORE_NAME: 'restore.harvesterhci.io/name', RESTORE_NAME: 'restore.harvesterhci.io/name',
+1 -5
View File
@@ -45,8 +45,7 @@ export const HCI_SETTING = {
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio', MAX_HOTPLUG_RATIO: 'max-hotplug-ratio',
KUBEVIRT_MIGRATION: 'kubevirt-migration', KUBEVIRT_MIGRATION: 'kubevirt-migration',
INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources', INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources',
CLUSTER_POD_SECURITY_STANDARD: 'cluster-pod-security-standard', CLUSTER_POD_SECURITY_STANDARD: 'cluster-pod-security-standard'
MAINTENANCE_MODE_DRAIN_TIMEOUT: 'maintenance-mode-drain-timeout'
}; };
export const HCI_ALLOWED_SETTINGS = { export const HCI_ALLOWED_SETTINGS = {
@@ -149,9 +148,6 @@ export const HCI_ALLOWED_SETTINGS = {
}, },
[HCI_SETTING.CLUSTER_POD_SECURITY_STANDARD]: { [HCI_SETTING.CLUSTER_POD_SECURITY_STANDARD]: {
kind: 'json', from: 'import', canReset: true, featureFlag: 'clusterPodSecurityStandardSetting' kind: 'json', from: 'import', canReset: true, featureFlag: 'clusterPodSecurityStandardSetting'
},
[HCI_SETTING.MAINTENANCE_MODE_DRAIN_TIMEOUT]: {
kind: 'number', canReset: true, featureFlag: 'maintenanceModeDrainTimeoutSetting'
} }
}; };
@@ -15,7 +15,6 @@ import OverviewKeypairs from '../kubevirt.io.virtualmachine/VirtualMachineTabs/V
import Volume from '../../edit/kubevirt.io.virtualmachine/VirtualMachineVolume'; import Volume from '../../edit/kubevirt.io.virtualmachine/VirtualMachineVolume';
import Network from '../../edit/kubevirt.io.virtualmachine/VirtualMachineNetwork'; import Network from '../../edit/kubevirt.io.virtualmachine/VirtualMachineNetwork';
import CloudConfig from '../../edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig'; import CloudConfig from '../../edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig';
import { getBootDevices } from '../../utils/vm';
const UNDEFINED = 'n/a'; const UNDEFINED = 'n/a';
export default { export default {
@@ -75,8 +74,18 @@ export default {
return image?.spec?.displayName || '-'; return image?.spec?.displayName || '-';
}, },
bootDevices() { disks() {
return getBootDevices(this?.spec?.template?.spec?.domain?.devices); const disks = this?.spec?.template?.spec?.domain?.devices?.disks || [];
return disks.filter((disk) => {
return !!disk.bootOrder;
}).sort((a, b) => {
if (a.bootOrder < b.bootOrder) {
return -1;
}
return 1;
});
}, },
cdroms() { cdroms() {
@@ -92,10 +101,8 @@ export default {
getDeviceType(o) { getDeviceType(o) {
if (o.disk) { if (o.disk) {
return 'Disk'; return 'Disk';
} else if (o.cdrom) {
return 'CD-ROM';
} else { } else {
return 'Network'; return 'CD-ROM';
} }
}, },
isEmpty(o) { isEmpty(o) {
@@ -177,10 +184,10 @@ export default {
<div> <div>
<ul> <ul>
<li <li
v-for="(device, i) in bootDevices" v-for="(disk, i) in disks"
:key="i" :key="i"
> >
{{ device.bootOrder }}. {{ device.name }} ({{ getDeviceType(device) }}) {{ disk.bootOrder }}. {{ disk.name }} ({{ getDeviceType(disk) }})
</li> </li>
</ul> </ul>
</div> </div>
@@ -226,7 +233,6 @@ export default {
> >
<Network <Network
v-model:value="networkRows" v-model:value="networkRows"
:network-boot-first="networkBootFirst"
:mode="mode" :mode="mode"
/> />
</Tab> </Tab>
@@ -15,7 +15,6 @@ import OverviewKeypairs from '../kubevirt.io.virtualmachine/VirtualMachineTabs/V
import Volume from '../../edit/kubevirt.io.virtualmachine/VirtualMachineVolume'; import Volume from '../../edit/kubevirt.io.virtualmachine/VirtualMachineVolume';
import Network from '../../edit/kubevirt.io.virtualmachine/VirtualMachineNetwork'; import Network from '../../edit/kubevirt.io.virtualmachine/VirtualMachineNetwork';
import CloudConfig from '../../edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig'; import CloudConfig from '../../edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig';
import { getBootDevices } from '../../utils/vm';
const UNDEFINED = 'n/a'; const UNDEFINED = 'n/a';
export default { export default {
@@ -75,8 +74,18 @@ export default {
return image?.spec?.displayName || '-'; return image?.spec?.displayName || '-';
}, },
bootDevices() { disks() {
return getBootDevices(this?.spec?.template?.spec?.domain?.devices); const disks = this?.spec?.template?.spec?.domain?.devices?.disks || [];
return disks.filter((disk) => {
return !!disk.bootOrder;
}).sort((a, b) => {
if (a.bootOrder < b.bootOrder) {
return -1;
}
return 1;
});
}, },
cdroms() { cdroms() {
@@ -92,10 +101,8 @@ export default {
getDeviceType(o) { getDeviceType(o) {
if (o.disk) { if (o.disk) {
return 'Disk'; return 'Disk';
} else if (o.cdrom) {
return 'CD-ROM';
} else { } else {
return 'Network'; return 'CD-ROM';
} }
}, },
isEmpty(o) { isEmpty(o) {
@@ -177,10 +184,10 @@ export default {
<div> <div>
<ul> <ul>
<li <li
v-for="(device, i) in bootDevices" v-for="(disk, i) in disks"
:key="i" :key="i"
> >
{{ device.bootOrder }}. {{ device.name }} ({{ getDeviceType(device) }}) {{ disk.bootOrder }}. {{ disk.name }} ({{ getDeviceType(disk) }})
</li> </li>
</ul> </ul>
</div> </div>
@@ -227,7 +234,6 @@ export default {
> >
<Network <Network
v-model:value="networkRows" v-model:value="networkRows"
:network-boot-first="networkBootFirst"
:mode="mode" :mode="mode"
/> />
</Tab> </Tab>
@@ -6,7 +6,6 @@ import HarvesterIpAddress from '../../../formatters/HarvesterIpAddress';
import VMConsoleBar from '../../../components/VMConsoleBar'; import VMConsoleBar from '../../../components/VMConsoleBar';
import { HCI } from '../../../types'; import { HCI } from '../../../types';
import { getVmCPUMemoryValues } from '../../../utils/cpuMemory'; import { getVmCPUMemoryValues } from '../../../utils/cpuMemory';
import { getBootDevices } from '../../../utils/vm';
const UNDEFINED = 'n/a'; const UNDEFINED = 'n/a';
@@ -70,8 +69,18 @@ export default {
return image?.spec?.displayName || 'N/A'; return image?.spec?.displayName || 'N/A';
}, },
bootDevices() { disks() {
return getBootDevices(this.value?.spec?.template?.spec?.domain?.devices); const disks = this.value?.spec?.template?.spec?.domain?.devices?.disks || [];
return disks.filter((disk) => {
return !!disk.bootOrder;
}).sort((a, b) => {
if (a.bootOrder < b.bootOrder) {
return -1;
}
return 1;
});
}, },
cdroms() { cdroms() {
@@ -113,10 +122,8 @@ export default {
getDeviceType(o) { getDeviceType(o) {
if (o.disk) { if (o.disk) {
return 'Disk'; return 'Disk';
} else if (o.cdrom) {
return 'CD-ROM';
} else { } else {
return 'Network'; return 'CD-ROM';
} }
}, },
isEmpty(o) { isEmpty(o) {
@@ -212,16 +219,16 @@ export default {
<div class="col span-6"> <div class="col span-6">
<InputOrDisplay <InputOrDisplay
:name="t('harvester.virtualMachine.detail.details.bootOrder')" :name="t('harvester.virtualMachine.detail.details.bootOrder')"
:value="bootDevices" :value="disks"
:mode="mode" :mode="mode"
> >
<template #value> <template #value>
<ul> <ul>
<li <li
v-for="(device, i) in bootDevices" v-for="(disk, i) in disks"
:key="i" :key="i"
> >
{{ device.bootOrder }}. {{ device.name }} ({{ getDeviceType(device) }}) {{ disk.bootOrder }}. {{ disk.name }} ({{ getDeviceType(disk) }})
</li> </li>
</ul> </ul>
</template> </template>
@@ -214,7 +214,6 @@ export default {
this['diskRows'] = diskRows; this['diskRows'] = diskRows;
this['networkRows'] = this.getNetworkRows(neu, { fromTemplate: false, init: false }); this['networkRows'] = this.getNetworkRows(neu, { fromTemplate: false, init: false });
this['networkBootFirst'] = this.isNetworkBootFirst(neu.spec);
// getInitConfig() seeds these on created(); refresh them here too so the // getInitConfig() seeds these on created(); refresh them here too so the
// VM-wide performance panel does not go stale when the spec changes. // VM-wide performance panel does not go stale when the spec changes.
@@ -277,7 +276,6 @@ export default {
> >
<Network <Network
v-model:value="networkRows" v-model:value="networkRows"
:network-boot-first="networkBootFirst"
mode="view" mode="view"
:vm="value" :vm="value"
/> />
@@ -324,7 +324,6 @@ export default {
> >
<Network <Network
v-model:value="networkRows" v-model:value="networkRows"
v-model:network-boot-first="networkBootFirst"
:mode="mode" :mode="mode"
/> />
</Tab> </Tab>
@@ -2,7 +2,6 @@
import InputOrDisplay from '@shell/components/InputOrDisplay'; import InputOrDisplay from '@shell/components/InputOrDisplay';
import { LabeledInput } from '@components/Form/LabeledInput'; import { LabeledInput } from '@components/Form/LabeledInput';
import LabeledSelect from '@shell/components/form/LabeledSelect'; import LabeledSelect from '@shell/components/form/LabeledSelect';
import { Checkbox } from '@components/Form/Checkbox';
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
import { _CREATE, _VIEW } from '@shell/config/query-params'; import { _CREATE, _VIEW } from '@shell/config/query-params';
@@ -34,7 +33,7 @@ export default {
emits: ['update'], emits: ['update'],
components: { components: {
LabeledInput, LabeledSelect, InputOrDisplay, Checkbox LabeledInput, LabeledSelect, InputOrDisplay
}, },
props: { props: {
@@ -170,7 +169,6 @@ export default {
this.value.isPod = true; this.value.isPod = true;
this.value.macAddress = ''; this.value.macAddress = '';
this.value.staticIp = ''; this.value.staticIp = '';
this.value.networkBoot = false;
} else { } else {
this.value.isPod = false; this.value.isPod = false;
} }
@@ -287,22 +285,6 @@ export default {
</div> </div>
</div> </div>
<div
v-if="!isMasquerade"
data-testid="input-hen-networkBoot"
class="row mb-20"
>
<div class="col span-12">
<Checkbox
v-model:value="value.networkBoot"
:label="t('harvester.virtualMachine.network.networkBoot.label')"
:tooltip="t('harvester.virtualMachine.network.networkBoot.tip')"
:mode="mode"
@update:value="update"
/>
</div>
</div>
<div v-if="!isMasquerade && isSingle"> <div v-if="!isMasquerade && isSingle">
<div class="row mb-20"> <div class="row mb-20">
<a <a
@@ -1,6 +1,5 @@
<script> <script>
import InfoBox from '@shell/components/InfoBox'; import InfoBox from '@shell/components/InfoBox';
import { RadioGroup } from '@components/Form/Radio';
import { NETWORK_ATTACHMENT } from '@shell/config/types'; import { NETWORK_ATTACHMENT } from '@shell/config/types';
import { sortBy } from '@shell/utils/sort'; import { sortBy } from '@shell/utils/sort';
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
@@ -11,11 +10,7 @@ import { HCI as HCI_ANNOTATIONS } from '../../../config/labels-annotations';
import Base from './base'; import Base from './base';
export default { export default {
components: { components: { InfoBox, Base },
InfoBox, Base, RadioGroup
},
emits: ['update:value', 'update:networkBootFirst'],
props: { props: {
vm: { vm: {
@@ -40,11 +35,6 @@ export default {
isSingle: { isSingle: {
type: Boolean, type: Boolean,
default: true default: true
},
networkBootFirst: {
type: Boolean,
default: true
} }
}, },
@@ -92,20 +82,6 @@ export default {
vmState() { vmState() {
return this.vm?.stateDisplay; return this.vm?.stateDisplay;
},
hasNetworkBoot() {
return this.rows.some((R) => R.networkBoot);
},
networkBootOrderOptions() {
return [{
label: this.t('harvester.virtualMachine.network.networkBoot.first'),
value: true
}, {
label: this.t('harvester.virtualMachine.network.networkBoot.last'),
value: false
}];
} }
}, },
@@ -242,22 +218,6 @@ export default {
/> />
</InfoBox> </InfoBox>
<div
v-if="hasNetworkBoot"
data-testid="input-hen-networkBootFirst"
class="mb-20"
>
<RadioGroup
:value="networkBootFirst"
name="networkBootFirst"
:label="t('harvester.virtualMachine.network.networkBoot.order')"
:options="networkBootOrderOptions"
:mode="mode"
:row="true"
@update:value="$emit('update:networkBootFirst', $event)"
/>
</div>
<button <button
v-if="!isView" v-if="!isView"
type="button" type="button"
@@ -791,7 +791,6 @@ export default {
> >
<Network <Network
v-model:value="networkRows" v-model:value="networkRows"
v-model:network-boot-first="networkBootFirst"
:mode="mode" :mode="mode"
:is-single="isSingle" :is-single="isSingle"
/> />
-8
View File
@@ -286,7 +286,6 @@ harvester:
createTemplate: Generate Template createTemplate: Generate Template
enableMaintenance: Enable Maintenance Mode enableMaintenance: Enable Maintenance Mode
disableMaintenance: Disable Maintenance Mode disableMaintenance: Disable Maintenance Mode
clearMaintenance: Clear Maintenance Mode Error
enableCPUManager: Enable CPU Manager enableCPUManager: Enable CPU Manager
disableCPUManager: Disable CPU Manager disableCPUManager: Disable CPU Manager
cordon: Cordon cordon: Cordon
@@ -872,12 +871,6 @@ harvester:
title: Network title: Network
addNetwork: Add Network addNetwork: Add Network
addPort: Add Port addPort: Add Port
networkBoot:
label: Enable network boot (PXE)
tip: Adds this interface to the VM boot order so the guest firmware can boot from the network. Requires a DHCP/TFTP (PXE) server reachable on the selected network; the management network does not provide one.
order: Network boot order
first: Before volumes
last: After volumes
cloudConfig: cloudConfig:
title: Cloud Configuration title: Cloud Configuration
createTemplateTitle: 'Create {name}' createTemplateTitle: 'Create {name}'
@@ -2542,7 +2535,6 @@ advancedSettings:
'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.' 'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.'
'harv-instance-manager-resources': 'Configure resource percentage reservations for Longhorn instance manager V1 and V2. Valid instance manager CPU range between 0 - 40.' 'harv-instance-manager-resources': 'Configure resource percentage reservations for Longhorn instance manager V1 and V2. Valid instance manager CPU range between 0 - 40.'
'harv-cluster-pod-security-standard': 'Enforce Kubernetes Pod Security Standards (PSS) at the cluster level.' 'harv-cluster-pod-security-standard': 'Enforce Kubernetes Pod Security Standards (PSS) at the cluster level.'
'harv-maintenance-mode-drain-timeout': 'Maintenance mode drain timeout in minutes. Use 0 to disable the timeout.'
typeLabel: typeLabel:
kubevirt.io.virtualmachine: |- kubevirt.io.virtualmachine: |-
+3 -35
View File
@@ -160,7 +160,6 @@ export default {
imageId: '', imageId: '',
diskRows: [], diskRows: [],
networkRows: [], networkRows: [],
networkBootFirst: true,
filesystemRows: [], filesystemRows: [],
machineType: '', machineType: '',
machineTypes: [], machineTypes: [],
@@ -385,7 +384,6 @@ export default {
const diskRows = this.getDiskRows(vm, volumeBackups); const diskRows = this.getDiskRows(vm, volumeBackups);
const networkRows = this.getNetworkRows(vm, { fromTemplate, init }); const networkRows = this.getNetworkRows(vm, { fromTemplate, init });
const networkBootFirst = this.isNetworkBootFirst(spec);
const hasCreateVolumes = this.getHasCreatedVolumes(spec) || []; const hasCreateVolumes = this.getHasCreatedVolumes(spec) || [];
let { userData = undefined, networkData = undefined } = this.getCloudInitNoCloud(spec); let { userData = undefined, networkData = undefined } = this.getCloudInitNoCloud(spec);
@@ -463,7 +461,6 @@ export default {
this['hasCreateVolumes'] = hasCreateVolumes; this['hasCreateVolumes'] = hasCreateVolumes;
this['networkRows'] = networkRows; this['networkRows'] = networkRows;
this['networkBootFirst'] = networkBootFirst;
this['imageId'] = imageId; this['imageId'] = imageId;
this['diskRows'] = diskRows; this['diskRows'] = diskRows;
@@ -679,29 +676,12 @@ export default {
model: I.model, model: I.model,
networkName: isPod ? MANAGEMENT_NETWORK : network?.multus?.networkName, networkName: isPod ? MANAGEMENT_NETWORK : network?.multus?.networkName,
staticIp: annotations[`${ staticIpPrefix }${ I.name }`] || '', staticIp: annotations[`${ staticIpPrefix }${ I.name }`] || '',
networkBoot: !!I.bootOrder,
}; };
}); });
return out; return out;
}, },
/**
* Network boot devices are placed either before or after all volumes in the boot sequence.
* Derive which one from an existing spec, so a round trip through the form keeps it.
*/
isNetworkBootFirst(spec) {
const devices = spec?.template?.spec?.domain?.devices || {};
const nicOrders = (devices.interfaces || []).map((I) => I.bootOrder).filter(Boolean);
const diskOrders = (devices.disks || []).map((D) => D.bootOrder).filter(Boolean);
if (nicOrders.length === 0 || diskOrders.length === 0) {
return true;
}
return Math.min(...nicOrders) < Math.min(...diskOrders);
},
parseVM() { parseVM() {
this.userData = this.getUserData({ osType: this.osType, installAgent: this.installAgent }); this.userData = this.getUserData({ osType: this.osType, installAgent: this.installAgent });
this.parseOther(); this.parseOther();
@@ -914,10 +894,9 @@ export default {
const disks = []; const disks = [];
const volumes = []; const volumes = [];
const volumeClaimTemplates = []; const volumeClaimTemplates = [];
const bootOrderOffset = this.networkBootFirst ? this.networkRows.filter((R) => R.networkBoot).length : 0;
disk.forEach( (R, index) => { disk.forEach( (R, index) => {
const _disk = this.parseDisk(R, index + bootOrderOffset); const _disk = this.parseDisk(R, index);
disks.push(_disk); disks.push(_disk);
@@ -1175,11 +1154,9 @@ export default {
const networks = []; const networks = [];
const interfaces = []; const interfaces = [];
let bootOrder = this.networkBootFirst ? 1 : this.diskRows.length + 1;
networkRow.forEach( (R) => { networkRow.forEach( (R) => {
const _network = this.parseNetwork(R); const _network = this.parseNetwork(R);
const _interface = this.parseInterface(R, R.networkBoot ? bootOrder++ : undefined); const _interface = this.parseInterface(R);
networks.push(_network); networks.push(_network);
interfaces.push(_interface); interfaces.push(_interface);
@@ -1435,7 +1412,7 @@ export default {
return arr.map( (id) => this.getSSHValue(id)).filter( (O) => O !== undefined); return arr.map( (id) => this.getSSHValue(id)).filter( (O) => O !== undefined);
}, },
parseInterface(R, bootOrder) { parseInterface(R) {
const _interface = {}; const _interface = {};
const type = R.type; const type = R.type;
@@ -1445,10 +1422,6 @@ export default {
_interface.macAddress = R.macAddress; _interface.macAddress = R.macAddress;
} }
if (bootOrder) {
_interface.bootOrder = bootOrder;
}
_interface.model = R.model; _interface.model = R.model;
_interface.name = R.name; _interface.name = R.name;
@@ -1956,11 +1929,6 @@ export default {
delete merged['bridge']; delete merged['bridge'];
} }
// boot order is owned by the form, don't inherit a stale one from the old spec
if (!iface.bootOrder) {
delete merged.bootOrder;
}
return merged; return merged;
} }
+8 -66
View File
@@ -23,13 +23,6 @@ const ALLOW_SYSTEM_LABEL_KEYS = [
const HEALTHY = 'healthy'; const HEALTHY = 'healthy';
const WARNING = 'warning'; const WARNING = 'warning';
const MAINTENANCE_MODE = 'MaintenanceMode';
const MAINTENANCE_ERROR = 'Error';
const MAINTENANCE_ENTERING_REASONS = ['Validating', 'Draining', 'Evacuating'];
const MAINTENANCE_COMPLETED = 'Completed';
// Legacy `harvesterhci.io/maintain-status` annotation values (clusters < v1.10)
const LEGACY_MAINTENANCE_RUNNING = 'running';
const LEGACY_MAINTENANCE_COMPLETED = 'completed';
export default class HciNode extends HarvesterResource { export default class HciNode extends HarvesterResource {
get _availableActions() { get _availableActions() {
@@ -65,14 +58,6 @@ export default class HciNode extends HarvesterResource {
total: 1 total: 1
}; };
const clearMaintenance = {
action: 'clearMaintenanceMode',
enabled: this.hasAction('clearMaintenanceMode'),
icon: 'icon icon-fw icon-close',
label: this.t('harvester.action.clearMaintenance'),
total: 1
};
const enableCPUManager = { const enableCPUManager = {
action: 'enableCPUManager', action: 'enableCPUManager',
enabled: this.cpuPinningFeatureEnabled && this.hasAction('enableCPUManager') && !this.isCPUManagerEnableInProgress && !this.isCPUManagerEnabled && !this.isEtcd, // witness node doesn't have CPU manager enabled: this.cpuPinningFeatureEnabled && this.hasAction('enableCPUManager') && !this.isCPUManagerEnableInProgress && !this.isCPUManagerEnabled && !this.isEtcd, // witness node doesn't have CPU manager
@@ -118,7 +103,6 @@ export default class HciNode extends HarvesterResource {
uncordon, uncordon,
enableMaintenance, enableMaintenance,
disableMaintenance, disableMaintenance,
clearMaintenance,
enableCPUManager, enableCPUManager,
disableCPUManager, disableCPUManager,
shutDown, shutDown,
@@ -214,10 +198,6 @@ export default class HciNode extends HarvesterResource {
} }
get stateDisplay() { get stateDisplay() {
if (this.isMaintenanceModeError) {
return super.stateDisplay;
}
if (this.isEnteringMaintenance) { if (this.isEnteringMaintenance) {
return 'Entering maintenance mode'; return 'Entering maintenance mode';
} }
@@ -266,10 +246,6 @@ export default class HciNode extends HarvesterResource {
} }
get stateDescription() { get stateDescription() {
if (this.isMaintenanceModeError) {
return super.stateDescription;
}
const currentIP = this.metadata?.annotations?.[HCI_ANNOTATIONS.CURRENT_IP]; const currentIP = this.metadata?.annotations?.[HCI_ANNOTATIONS.CURRENT_IP];
const initIP = this.metadata?.annotations?.[HCI_ANNOTATIONS.INIT_IP]; const initIP = this.metadata?.annotations?.[HCI_ANNOTATIONS.INIT_IP];
@@ -349,11 +325,7 @@ export default class HciNode extends HarvesterResource {
} }
disableMaintenanceMode() { disableMaintenanceMode() {
this.doActionGrowl('disableMaintenanceMode', {}); this.doAction('disableMaintenanceMode', {});
}
clearMaintenanceMode() {
this.doActionGrowl('clearMaintenanceMode', {});
} }
enableCPUManager() { enableCPUManager() {
@@ -371,32 +343,11 @@ export default class HciNode extends HarvesterResource {
); );
} }
get maintenanceModeCondition() {
return (this.status?.conditions || []).find(
(c) => c.type === MAINTENANCE_MODE
);
}
get maintenanceModeConditionsEnabled() {
return this.$rootGetters['harvester-common/getFeatureEnabled']('maintenanceModeConditions');
}
// Clusters < v1.10 only expose the `harvesterhci.io/maintain-status` annotation
get legacyMaintenanceStatus() {
return this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS];
}
get isMaintenanceModeError() {
return this.maintenanceModeConditionsEnabled && this.maintenanceModeCondition?.reason === MAINTENANCE_ERROR;
}
get isMigratable() { get isMigratable() {
const states = ['in-progress', 'unavailable']; const states = ['in-progress', 'unavailable'];
const engaged = this.maintenanceModeConditionsEnabled ? this.maintenanceModeCondition?.status === 'True' : !!this.legacyMaintenanceStatus;
return ( return (
!engaged && !this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] &&
!this.isUnSchedulable && !this.isUnSchedulable &&
!states.includes(this.state) !states.includes(this.state)
); );
@@ -411,26 +362,17 @@ export default class HciNode extends HarvesterResource {
} }
get isEnteringMaintenance() { get isEnteringMaintenance() {
if (!this.maintenanceModeConditionsEnabled) {
return this.legacyMaintenanceStatus === LEGACY_MAINTENANCE_RUNNING;
}
const cond = this.maintenanceModeCondition;
return ( return (
cond?.status === 'True' && this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] ===
MAINTENANCE_ENTERING_REASONS.includes(cond?.reason) 'running'
); );
} }
get isMaintenance() { get isMaintenance() {
if (!this.maintenanceModeConditionsEnabled) { return (
return this.legacyMaintenanceStatus === LEGACY_MAINTENANCE_COMPLETED; this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] ===
} 'completed'
);
const cond = this.maintenanceModeCondition;
return cond?.status === 'True' && cond?.reason === MAINTENANCE_COMPLETED;
} }
get cpuPinningFeatureEnabled() { get cpuPinningFeatureEnabled() {
-9
View File
@@ -11,12 +11,3 @@ export function parseVolumeClaimTemplates(data) {
} }
export const EMPTY_IMAGE = 'EMPTY_IMAGE'; export const EMPTY_IMAGE = 'EMPTY_IMAGE';
/**
* Disks and interfaces that take part in the boot sequence, sorted by boot order.
*/
export function getBootDevices(devices = {}) {
return [...(devices.disks || []), ...(devices.interfaces || [])]
.filter((device) => !!device.bootOrder)
.sort((a, b) => a.bootOrder - b.bootOrder);
}
+6 -16
View File
@@ -3099,16 +3099,11 @@
"@typescript-eslint/types" "8.62.0" "@typescript-eslint/types" "8.62.0"
"@typescript-eslint/visitor-keys" "8.62.0" "@typescript-eslint/visitor-keys" "8.62.0"
"@typescript-eslint/tsconfig-utils@8.62.0": "@typescript-eslint/tsconfig-utils@8.62.0", "@typescript-eslint/tsconfig-utils@^8.62.0":
version "8.62.0" version "8.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.0.tgz#9440a673581c6d9de308c4d5803dd52ed5d71729" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.62.0.tgz#9440a673581c6d9de308c4d5803dd52ed5d71729"
integrity sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g== integrity sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==
"@typescript-eslint/tsconfig-utils@^8.62.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz#594d7a3c5952055b3c431fc563ca7fd1defcce18"
integrity sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==
"@typescript-eslint/type-utils@8.62.0": "@typescript-eslint/type-utils@8.62.0":
version "8.62.0" version "8.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.62.0.tgz#6f64d813ed9f340d796baed40cdab86b8e9a491a" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.62.0.tgz#6f64d813ed9f340d796baed40cdab86b8e9a491a"
@@ -3120,16 +3115,11 @@
debug "^4.4.3" debug "^4.4.3"
ts-api-utils "^2.5.0" ts-api-utils "^2.5.0"
"@typescript-eslint/types@8.62.0": "@typescript-eslint/types@8.62.0", "@typescript-eslint/types@^8.62.0":
version "8.62.0" version "8.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.62.0.tgz#601427c10203d9f0f34f0b3e474df735eb12b593" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.62.0.tgz#601427c10203d9f0f34f0b3e474df735eb12b593"
integrity sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg== integrity sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==
"@typescript-eslint/types@^8.62.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.68.0.tgz#3f9d4e62fbe5728f09403cdc7b4d58af842ac1af"
integrity sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==
"@typescript-eslint/typescript-estree@8.62.0": "@typescript-eslint/typescript-estree@8.62.0":
version "8.62.0" version "8.62.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.0.tgz#b96b55d02e26aa09434421c3fa678e525ca09a4c" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.62.0.tgz#b96b55d02e26aa09434421c3fa678e525ca09a4c"
@@ -6126,10 +6116,10 @@ element-matches@^0.1.2:
resolved "https://registry.yarnpkg.com/element-matches/-/element-matches-0.1.2.tgz#7345cb71e965bd2b12f725e524591c102198361a" resolved "https://registry.yarnpkg.com/element-matches/-/element-matches-0.1.2.tgz#7345cb71e965bd2b12f725e524591c102198361a"
integrity sha512-yWh1otcs3OKUWDvu/IxyI36ZI3WNaRZlI0uG/DK6fu0pap0VYZ0J5pEGTk1zakme+hT0OKHwhlHc0N5TJhY6yQ== integrity sha512-yWh1otcs3OKUWDvu/IxyI36ZI3WNaRZlI0uG/DK6fu0pap0VYZ0J5pEGTk1zakme+hT0OKHwhlHc0N5TJhY6yQ==
elkjs@^0.11.0: elkjs@^0.12.0:
version "0.11.1" version "0.12.0"
resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.11.1.tgz#d27fcdbbf5a8aeeff80420d17d1666f78cfc8544" resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.12.0.tgz#7dc1bc71ab8f402d1b6564e2fa509ca1caee276c"
integrity sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg== integrity sha512-YZcKynxVxYoKIOEpywEPwCFdg+BTbxQRNf3pbwdDCvc8O3kQD8bmIwSxKU1eOTVc4Xo+VG9Te+575mlfvOrhEQ==
elliptic@^6.5.3, elliptic@^6.6.1: elliptic@^6.5.3, elliptic@^6.6.1:
version "6.6.1" version "6.6.1"