Latest changes from Harvester master - e6796a6fc0cffe03f47f6081c09469d59b97faf9

Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
Francesco Torchia 2024-11-08 10:28:47 +01:00
parent 78ca1e2f49
commit 9a7ca75b74
No known key found for this signature in database
GPG Key ID: E6D011B7415D4393
10 changed files with 93 additions and 63 deletions

View File

@ -13,21 +13,18 @@ import Loading from '@shell/components/Loading';
import { _CREATE, _VIEW } from '@shell/config/query-params'; import { _CREATE, _VIEW } from '@shell/config/query-params';
import { mapFeature, UNSUPPORTED_STORAGE_DRIVERS } from '@shell/store/features'; import { mapFeature, UNSUPPORTED_STORAGE_DRIVERS } from '@shell/store/features';
import { import {
STORAGE_CLASS, LONGHORN, LONGHORN_DRIVER, SECRET, NAMESPACE STORAGE_CLASS, LONGHORN, LONGHORN_DRIVER, SECRET, NAMESPACE
} from '@shell/config/types'; } from '@shell/config/types';
import { allHash } from '@shell/utils/promise'; import { allHash } from '@shell/utils/promise';
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
import { CSI_DRIVER } from '../../types'; import { CSI_DRIVER } from '../../types';
import Tags from '../../components/DiskTags'; import Tags from '../../components/DiskTags';
import { DATA_ENGINE_V1, DATA_ENGINE_V2 } from '../../models/harvester/persistentvolumeclaim';
import { LVM_DRIVER } from '../../models/harvester/storage.k8s.io.storageclass'; import { LVM_DRIVER } from '../../models/harvester/storage.k8s.io.storageclass';
const LONGHORN_V2_DATA_ENGINE = 'longhorn-system/v2-data-engine'; const LONGHORN_V2_DATA_ENGINE = 'longhorn-system/v2-data-engine';
export const DATA_ENGINE_V1 = 'v1';
export const DATA_ENGINE_V2 = 'v2';
export const LVM_TOPOLOGY_LABEL = 'topology.lvm.csi/node'; export const LVM_TOPOLOGY_LABEL = 'topology.lvm.csi/node';
const VOLUME_BINDING_MODE_IMMEDIATE = 'Immediate'; const VOLUME_BINDING_MODE_IMMEDIATE = 'Immediate';
@ -304,10 +301,10 @@ export default {
class="mb-20" class="mb-20"
/> />
<Tabbed :side-tabs="true"> <Tabbed :side-tabs="true">
<Tab <Tab
name="parameters" name="parameters"
:label="t('storageClass.parameters.label')" :label="t('storageClass.parameters.label')"
:weight="2" :weight="2"
> >
<component <component
:is="getComponent(provisioner)" :is="getComponent(provisioner)"
@ -317,9 +314,9 @@ export default {
:real-mode="realMode" :real-mode="realMode"
/> />
</Tab> </Tab>
<Tab <Tab
name="customize" name="customize"
:label="t('storageClass.customize.label')" :label="t('storageClass.customize.label')"
> >
<div class="row mt-20"> <div class="row mt-20">
<div class="col span-6"> <div class="col span-6">

View File

@ -8,7 +8,7 @@ import { _CREATE, _VIEW } from '@shell/config/query-params';
import { CSI_SECRETS } from '@pkg/harvester/config/harvester-map'; import { CSI_SECRETS } from '@pkg/harvester/config/harvester-map';
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
import { uniq } from '@shell/utils/array'; import { uniq } from '@shell/utils/array';
import { DATA_ENGINE_V1 } from '../index.vue'; import { DATA_ENGINE_V1 } from '../../../models/harvester/persistentvolumeclaim';
// UI components for Longhorn storage class parameters // UI components for Longhorn storage class parameters
const DEFAULT_PARAMETERS = [ const DEFAULT_PARAMETERS = [
@ -282,9 +282,9 @@ export default {
:mode="mode" :mode="mode"
> >
<template #no-options="{ searching }"> <template #no-options="{ searching }">
<span <span
v-if="!searching" v-if="!searching"
class="text-muted" class="text-muted"
> >
{{ t('harvester.storage.parameters.nodeSelector.no-options', null, true) }} {{ t('harvester.storage.parameters.nodeSelector.no-options', null, true) }}
</span> </span>
@ -301,9 +301,9 @@ export default {
:mode="mode" :mode="mode"
> >
<template #no-options="{ searching }"> <template #no-options="{ searching }">
<span <span
v-if="!searching" v-if="!searching"
class="text-muted" class="text-muted"
> >
{{ t('harvester.storage.parameters.diskSelector.no-options', null, true) }} {{ t('harvester.storage.parameters.diskSelector.no-options', null, true) }}
</span> </span>
@ -329,9 +329,9 @@ export default {
:options="volumeEncryptionOptions" :options="volumeEncryptionOptions"
/> />
</div> </div>
<div <div
v-if="value.parameters.encrypted === 'true'" v-if="value.parameters.encrypted === 'true'"
class="row mt-20" class="row mt-20"
> >
<div class="col span-6"> <div class="col span-6">
<LabeledSelect <LabeledSelect

View File

@ -8,7 +8,7 @@ import { _CREATE, _VIEW } from '@shell/config/query-params';
import { CSI_SECRETS } from '@pkg/harvester/config/harvester-map'; import { CSI_SECRETS } from '@pkg/harvester/config/harvester-map';
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
import { uniq } from '@shell/utils/array'; import { uniq } from '@shell/utils/array';
import { DATA_ENGINE_V2 } from '../index.vue'; import { DATA_ENGINE_V2 } from '../../../models/harvester/persistentvolumeclaim';
// UI components for Longhorn storage class parameters // UI components for Longhorn storage class parameters
const DEFAULT_PARAMETERS = [ const DEFAULT_PARAMETERS = [
@ -282,9 +282,9 @@ export default {
:mode="mode" :mode="mode"
> >
<template #no-options="{ searching }"> <template #no-options="{ searching }">
<span <span
v-if="!searching" v-if="!searching"
class="text-muted" class="text-muted"
> >
{{ t('harvester.storage.parameters.nodeSelector.no-options', null, true) }} {{ t('harvester.storage.parameters.nodeSelector.no-options', null, true) }}
</span> </span>
@ -301,9 +301,9 @@ export default {
:mode="mode" :mode="mode"
> >
<template #no-options="{ searching }"> <template #no-options="{ searching }">
<span <span
v-if="!searching" v-if="!searching"
class="text-muted" class="text-muted"
> >
{{ t('harvester.storage.parameters.diskSelector.no-options', null, true) }} {{ t('harvester.storage.parameters.diskSelector.no-options', null, true) }}
</span> </span>
@ -331,9 +331,9 @@ export default {
:disabled="true" :disabled="true"
/> />
</div> </div>
<div <div
v-if="value.parameters.encrypted === 'true'" v-if="value.parameters.encrypted === 'true'"
class="row mt-20" class="row mt-20"
> >
<div class="col span-6"> <div class="col span-6">
<LabeledSelect <LabeledSelect

View File

@ -20,7 +20,7 @@ import { STATE, NAME, AGE, NAMESPACE } from '@shell/config/table-headers';
import { InterfaceOption, VOLUME_DATA_SOURCE_KIND } from '../config/harvester-map'; import { InterfaceOption, VOLUME_DATA_SOURCE_KIND } from '../config/harvester-map';
import { HCI, VOLUME_SNAPSHOT } from '../types'; import { HCI, VOLUME_SNAPSHOT } from '../types';
import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass'; import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass';
import { DATA_ENGINE_V2 } from './harvesterhci.io.storage/index.vue'; import { DATA_ENGINE_V2 } from '../models/harvester/persistentvolumeclaim';
export default { export default {
name: 'HarvesterVolume', name: 'HarvesterVolume',
@ -228,14 +228,22 @@ export default {
rebuildStatus() { rebuildStatus() {
return this.value.longhornEngine?.status?.rebuildStatus; return this.value.longhornEngine?.status?.rebuildStatus;
},
isLonghornV2() {
return this.value.storageClass?.isLonghornV2;
} }
}, },
methods: { methods: {
getAccessMode() {
const storageClassName = this.value.spec.storageClassName;
const storageClass = this.storageClasses.find((sc) => sc.name === storageClassName);
let readWriteOnce = this.value.isLvm || this.value.isLonghornV2;
if (storageClass) {
readWriteOnce = storageClass.provisioner === LVM_DRIVER || storageClass.parameters?.dataEngine === DATA_ENGINE_V2;
}
return readWriteOnce ? ['ReadWriteOnce'] : ['ReadWriteMany'];
},
willSave() { willSave() {
this.update(); this.update();
}, },
@ -243,10 +251,6 @@ export default {
let imageAnnotations = ''; let imageAnnotations = '';
let storageClassName = this.value.spec.storageClassName; let storageClassName = this.value.spec.storageClassName;
const storageClass = this.storageClasses.find((sc) => sc.name === storageClassName);
const storageClassProvisioner = storageClass?.provisioner;
const storageClassDataEngine = storageClass?.parameters?.dataEngine;
if (this.isVMImage && this.imageId) { if (this.isVMImage && this.imageId) {
const images = this.$store.getters['harvester/all'](HCI.IMAGE); const images = this.$store.getters['harvester/all'](HCI.IMAGE);
@ -263,7 +267,7 @@ export default {
...this.value.spec, ...this.value.spec,
resources: { requests: { storage: this.storage } }, resources: { requests: { storage: this.storage } },
storageClassName, storageClassName,
accessModes: storageClassProvisioner === LVM_DRIVER || storageClassDataEngine === DATA_ENGINE_V2 ? ['ReadWriteOnce'] : ['ReadWriteMany'], accessModes: this.getAccessMode(),
}; };
this.value.setAnnotations(imageAnnotations); this.value.setAnnotations(imageAnnotations);
@ -362,14 +366,14 @@ export default {
:output-modifier="true" :output-modifier="true"
:increment="1024" :increment="1024"
:mode="mode" :mode="mode"
:disabled="isLonghornV2 && isEdit" :disabled="value?.isLonghornV2 && isEdit"
required required
class="mb-20" class="mb-20"
@update:value="update" @update:value="update"
/> />
<Banner <Banner
v-if="isLonghornV2 && isEdit" v-if="value?.isLonghornV2 && isEdit"
color="warning" color="warning"
> >
<span>{{ t('harvester.volume.longhorn.disableResize') }}</span> <span>{{ t('harvester.volume.longhorn.disableResize') }}</span>

View File

@ -259,7 +259,7 @@ export default {
}, },
isLonghornV2(volume) { isLonghornV2(volume) {
return volume?.pvc?.storageClass?.isLonghornV2; return volume?.pvc?.isLonghornV2 || volume?.pvc?.storageClass?.isLonghornV2;
} }
}, },
}; };

View File

@ -117,7 +117,7 @@ export default {
}, },
isLonghornV2() { isLonghornV2() {
return this.value.pvc?.storageClass?.isLonghornV2; return this.value.pvc?.isLonghornV2 || this.value.pvc?.storageClass?.isLonghornV2;
} }
}, },

View File

@ -11,7 +11,7 @@ import { _VIEW } from '@shell/config/query-params';
import LabelValue from '@shell/components/LabelValue'; import LabelValue from '@shell/components/LabelValue';
import { ucFirst } from '@shell/utils/string'; import { ucFirst } from '@shell/utils/string';
import { LVM_DRIVER } from '../../../../models/harvester/storage.k8s.io.storageclass'; import { LVM_DRIVER } from '../../../../models/harvester/storage.k8s.io.storageclass';
import { DATA_ENGINE_V2 } from '../../../../edit/harvesterhci.io.storage/index.vue'; import { DATA_ENGINE_V2 } from '../../../../models/harvester/persistentvolumeclaim';
export default { export default {
name: 'HarvesterEditVolume', name: 'HarvesterEditVolume',
@ -105,7 +105,7 @@ export default {
}, },
isLonghornV2() { isLonghornV2() {
return this.value.pvc?.storageClass?.isLonghornV2; return this.value.pvc?.isLonghornV2 || this.value.pvc?.storageClass?.isLonghornV2;
} }
}, },
@ -113,11 +113,7 @@ export default {
'value.storageClassName': { 'value.storageClassName': {
immediate: true, immediate: true,
handler(neu) { handler(neu) {
const storageClass = this.storageClasses.find((sc) => sc.name === neu); this.value.accessMode = this.getAccessMode(neu);
const provisioner = storageClass?.provisioner;
const engine = storageClass?.parameters?.dataEngine;
this.value.accessMode = provisioner === LVM_DRIVER || engine === DATA_ENGINE_V2 ? 'ReadWriteOnce' : 'ReadWriteMany';
} }
}, },
@ -149,6 +145,18 @@ export default {
}, },
methods: { methods: {
getAccessMode(storageClassName) {
const storageClass = this.storageClasses.find((sc) => sc.name === storageClassName);
let readWriteOnce = this.value.pvc?.isLvm || this.value.pvc?.isLonghornV2;
if (storageClass) {
readWriteOnce = storageClass.provisioner === LVM_DRIVER || storageClass.parameters?.dataEngine === DATA_ENGINE_V2;
}
return readWriteOnce ? 'ReadWriteOnce' : 'ReadWriteMany';
},
update() { update() {
this.$emit('update'); this.$emit('update');
}, },

View File

@ -9,11 +9,13 @@ import { colorForState } from '@shell/plugins/dashboard-store/resource-class';
import { HCI, VOLUME_SNAPSHOT } from '../../types'; import { HCI, VOLUME_SNAPSHOT } from '../../types';
import HarvesterResource from '../harvester'; import HarvesterResource from '../harvester';
import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../../config/harvester'; import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../../config/harvester';
import { LVM_DRIVER } from './storage.k8s.io.storageclass';
import { DATA_ENGINE_V2 } from '../../edit/harvesterhci.io.storage/index.vue';
const DEGRADED_ERRORS = ['replica scheduling failed', 'precheck new replica failed']; const DEGRADED_ERRORS = ['replica scheduling failed', 'precheck new replica failed'];
export const DATA_ENGINE_V1 = 'v1';
export const DATA_ENGINE_V2 = 'v2';
export default class HciPv extends HarvesterResource { export default class HciPv extends HarvesterResource {
applyDefaults(_, realMode) { applyDefaults(_, realMode) {
const accessModes = realMode === _CLONE ? this.spec.accessModes : []; const accessModes = realMode === _CLONE ? this.spec.accessModes : [];
@ -34,7 +36,7 @@ export default class HciPv extends HarvesterResource {
let out = super._availableActions; let out = super._availableActions;
// Longhorn V2 provisioner do not support volume clone feature yet // Longhorn V2 provisioner do not support volume clone feature yet
if (this.storageClass.longhornVersion === DATA_ENGINE_V2) { if (this.isLonghornV2) {
out = out.filter((action) => action.action !== 'goToClone'); out = out.filter((action) => action.action !== 'goToClone');
} else { } else {
const clone = out.find((action) => action.action === 'goToClone'); const clone = out.find((action) => action.action === 'goToClone');
@ -44,7 +46,7 @@ export default class HciPv extends HarvesterResource {
} }
} }
if (this.storageClass.provisioner !== LONGHORN_DRIVER || this.storageClass.longhornVersion !== DATA_ENGINE_V2) { if (!this.isLonghorn || !this.isLonghornV2) {
out = [ out = [
{ {
action: 'exportImage', action: 'exportImage',
@ -303,6 +305,26 @@ export default class HciPv extends HarvesterResource {
return this.$rootGetters['harvester/all'](PV).find((pv) => pv.metadata?.name === this.spec?.volumeName); return this.$rootGetters['harvester/all'](PV).find((pv) => pv.metadata?.name === this.spec?.volumeName);
} }
get volumeProvider() {
return this.relatedPV?.spec.csi?.driver;
}
get dataEngine() {
return this.relatedPV?.spec.csi?.volumeAttributes?.dataEngine;
}
get isLvm() {
return this.volumeProvider === LVM_DRIVER;
}
get isLonghorn() {
return this.volumeProvider === LONGHORN_DRIVER;
}
get isLonghornV2() {
return this.dataEngine === DATA_ENGINE_V2;
}
get resourceExternalLink() { get resourceExternalLink() {
const host = window.location.host; const host = window.location.host;
const { params } = this.currentRoute(); const { params } = this.currentRoute();

View File

@ -3,7 +3,7 @@ import StorageClass from '@shell/models/storage.k8s.io.storageclass';
import { HCI } from '../../types'; import { HCI } from '../../types';
import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../../config/harvester'; import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../../config/harvester';
import { LONGHORN_DRIVER } from '@shell/config/types'; import { LONGHORN_DRIVER } from '@shell/config/types';
import { DATA_ENGINE_V1, DATA_ENGINE_V2 } from '../../edit/harvesterhci.io.storage/index.vue'; import { DATA_ENGINE_V1, DATA_ENGINE_V2 } from '../../models/harvester/persistentvolumeclaim';
export const LVM_DRIVER = 'lvm.driver.harvesterhci.io'; export const LVM_DRIVER = 'lvm.driver.harvesterhci.io';
@ -55,7 +55,7 @@ export default class HciStorageClass extends StorageClass {
key = `harvester.storage.storageClass.lvm.label`; key = `harvester.storage.storageClass.lvm.label`;
} }
return this.$rootGetters['i18n/t'](key); return key ? this.$rootGetters['i18n/t'](key) : null;
} }
get isLonghornV2() { get isLonghornV2() {

View File

@ -13,7 +13,6 @@ import { parseVolumeClaimTemplates } from '@pkg/utils/vm';
import { BACKUP_TYPE } from '../config/types'; import { BACKUP_TYPE } from '../config/types';
import { HCI } from '../types'; import { HCI } from '../types';
import HarvesterResource from './harvester'; import HarvesterResource from './harvester';
import { LVM_DRIVER } from './harvester/storage.k8s.io.storageclass';
import { featureEnabled } from '../utils/feature-flags'; import { featureEnabled } from '../utils/feature-flags';
export const OFF = 'Off'; export const OFF = 'Off';
@ -613,11 +612,11 @@ export default class VirtVm extends HarvesterResource {
} }
get lvmVolumes() { get lvmVolumes() {
return this.volumes.filter((volume) => volume.storageClass.provisioner === LVM_DRIVER); return this.volumes.filter((volume) => volume?.isLvm);
} }
get longhornV2Volumes() { get longhornV2Volumes() {
return this.volumes.filter((volume) => volume.storageClass.isLonghornV2); return this.volumes.filter((volume) => volume?.isLonghornV2);
} }
get encryptedVolumeType() { get encryptedVolumeType() {