mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-07 22:56:07 +08:00
feat: Make use of status conditions when activating maintenance mode (#1145)
Related to: https://github.com/harvester/harvester/issues/9022 Signed-off-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
@@ -81,7 +81,10 @@ const FEATURE_FLAGS = {
|
|||||||
'lvmDmThinOnly',
|
'lvmDmThinOnly',
|
||||||
'highPerformanceStorage',
|
'highPerformanceStorage',
|
||||||
],
|
],
|
||||||
'v1.10.0': [],
|
'v1.10.0': [
|
||||||
|
'maintenanceModeConditions',
|
||||||
|
'maintenanceModeDrainTimeoutSetting',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateFeatureFlags = () => {
|
const generateFeatureFlags = () => {
|
||||||
|
|||||||
@@ -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',
|
MAINTENANCE_STATUS: 'harvesterhci.io/maintain-status', // Deprecated >= v1.10.0
|
||||||
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',
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ 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 = {
|
||||||
@@ -148,6 +149,9 @@ 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'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ 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
|
||||||
@@ -2541,6 +2542,7 @@ 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: |-
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ 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() {
|
||||||
@@ -58,6 +65,14 @@ 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
|
||||||
@@ -103,6 +118,7 @@ export default class HciNode extends HarvesterResource {
|
|||||||
uncordon,
|
uncordon,
|
||||||
enableMaintenance,
|
enableMaintenance,
|
||||||
disableMaintenance,
|
disableMaintenance,
|
||||||
|
clearMaintenance,
|
||||||
enableCPUManager,
|
enableCPUManager,
|
||||||
disableCPUManager,
|
disableCPUManager,
|
||||||
shutDown,
|
shutDown,
|
||||||
@@ -198,6 +214,10 @@ 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';
|
||||||
}
|
}
|
||||||
@@ -246,6 +266,10 @@ 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];
|
||||||
|
|
||||||
@@ -325,7 +349,11 @@ export default class HciNode extends HarvesterResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableMaintenanceMode() {
|
disableMaintenanceMode() {
|
||||||
this.doAction('disableMaintenanceMode', {});
|
this.doActionGrowl('disableMaintenanceMode', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMaintenanceMode() {
|
||||||
|
this.doActionGrowl('clearMaintenanceMode', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
enableCPUManager() {
|
enableCPUManager() {
|
||||||
@@ -343,11 +371,32 @@ 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 (
|
||||||
!this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] &&
|
!engaged &&
|
||||||
!this.isUnSchedulable &&
|
!this.isUnSchedulable &&
|
||||||
!states.includes(this.state)
|
!states.includes(this.state)
|
||||||
);
|
);
|
||||||
@@ -362,17 +411,26 @@ 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 (
|
||||||
this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] ===
|
cond?.status === 'True' &&
|
||||||
'running'
|
MAINTENANCE_ENTERING_REASONS.includes(cond?.reason)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isMaintenance() {
|
get isMaintenance() {
|
||||||
return (
|
if (!this.maintenanceModeConditionsEnabled) {
|
||||||
this.metadata?.annotations?.[HCI_ANNOTATIONS.MAINTENANCE_STATUS] ===
|
return this.legacyMaintenanceStatus === LEGACY_MAINTENANCE_COMPLETED;
|
||||||
'completed'
|
}
|
||||||
);
|
|
||||||
|
const cond = this.maintenanceModeCondition;
|
||||||
|
|
||||||
|
return cond?.status === 'True' && cond?.reason === MAINTENANCE_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
get cpuPinningFeatureEnabled() {
|
get cpuPinningFeatureEnabled() {
|
||||||
|
|||||||
Reference in New Issue
Block a user