mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2025-12-13 21:21:44 +00:00
chore: disable vmstate-persistence and longhorn-static StorageClasses (#377)
* chore: disable vmstate-persistence and longhorn-static StorageClasses Signed-off-by: Nick Chung <nick.chung@suse.com> * chore: allow internal storage class deletions in image and volumn Signed-off-by: Nick Chung <nick.chung@suse.com> * chore: remove deletion tooltips in image and volume pages Signed-off-by: Nick Chung <nick.chung@suse.com> * chore: rollback style changes of image and volume lists Signed-off-by: Nick Chung <nick.chung@suse.com> --------- Signed-off-by: Nick Chung <nick.chung@suse.com>
This commit is contained in:
parent
193d4536e3
commit
b775ce5f50
@ -17,4 +17,9 @@ export const VOLUME_MODE = {
|
|||||||
export const NETWORK_PROTOCOL = {
|
export const NETWORK_PROTOCOL = {
|
||||||
IPv4: 'IPv4',
|
IPv4: 'IPv4',
|
||||||
IPv6: 'IPv6',
|
IPv6: 'IPv6',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const INTERNAL_STORAGE_CLASS = {
|
||||||
|
VMSTATE_PERSISTENCE: 'vmstate-persistence',
|
||||||
|
LONGHORN_STATIC: 'longhorn-static',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { LabeledInput } from '@components/Form/LabeledInput';
|
|||||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||||
import { NAMESPACE, STORAGE_CLASS } from '@shell/config/types';
|
import { NAMESPACE, STORAGE_CLASS } from '@shell/config/types';
|
||||||
import { allHash } from '@shell/utils/promise';
|
import { allHash } from '@shell/utils/promise';
|
||||||
|
import { isInternalStorageClass } from '../utils/storage-class';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HarvesterExportImageDialog',
|
name: 'HarvesterExportImageDialog',
|
||||||
@ -105,11 +106,17 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options = storages.filter((s) => !s.parameters?.backingImage).map((s) => {
|
const options = storages.filter((s) => !s.parameters?.backingImage).map((s) => {
|
||||||
const label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
let label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
||||||
|
const isInternal = isInternalStorageClass(s.metadata?.name);
|
||||||
|
|
||||||
|
if (isInternal) {
|
||||||
|
label += ` (${ this.t('harvester.storage.internal.label') })`;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: s.name,
|
value: s.name,
|
||||||
|
disabled: isInternal,
|
||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import { VM_IMAGE_FILE_FORMAT } from '../validators/vm-image';
|
|||||||
import { OS } from '../mixins/harvester-vm';
|
import { OS } from '../mixins/harvester-vm';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass';
|
import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass';
|
||||||
|
import { isInternalStorageClass } from '../utils/storage-class';
|
||||||
|
|
||||||
const ENCRYPT = 'encrypt';
|
const ENCRYPT = 'encrypt';
|
||||||
const DECRYPT = 'decrypt';
|
const DECRYPT = 'decrypt';
|
||||||
@ -168,11 +169,18 @@ export default {
|
|||||||
|
|
||||||
return filteredStorages
|
return filteredStorages
|
||||||
.map((s) => {
|
.map((s) => {
|
||||||
const label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
let label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
||||||
|
let disabled = false;
|
||||||
|
|
||||||
|
if (isInternalStorageClass(s.name)) {
|
||||||
|
label += ` (${ this.t('harvester.storage.internal.label') })`;
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: s.name,
|
value: s.name,
|
||||||
|
disabled
|
||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { LVM_DRIVER } from '../models/harvester/storage.k8s.io.storageclass';
|
|||||||
import { DATA_ENGINE_V2 } from '../models/harvester/persistentvolumeclaim';
|
import { DATA_ENGINE_V2 } from '../models/harvester/persistentvolumeclaim';
|
||||||
import { GIBIBYTE } from '../utils/unit';
|
import { GIBIBYTE } from '../utils/unit';
|
||||||
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
||||||
|
import { isInternalStorageClass } from '../utils/storage-class';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HarvesterVolume',
|
name: 'HarvesterVolume',
|
||||||
@ -206,11 +207,18 @@ export default {
|
|||||||
|
|
||||||
storageClassOptions() {
|
storageClassOptions() {
|
||||||
return this.storageClasses.filter((s) => !s.parameters?.backingImage).map((s) => {
|
return this.storageClasses.filter((s) => !s.parameters?.backingImage).map((s) => {
|
||||||
const label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
let label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
||||||
|
let disabled = false;
|
||||||
|
|
||||||
|
if (isInternalStorageClass(s.name)) {
|
||||||
|
label += ` (${ this.t('harvester.storage.internal.label') })`;
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: s.name,
|
value: s.name,
|
||||||
|
disabled
|
||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -13,6 +13,7 @@ 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 '../../../../models/harvester/persistentvolumeclaim';
|
import { DATA_ENGINE_V2 } from '../../../../models/harvester/persistentvolumeclaim';
|
||||||
import { GIBIBYTE } from '../../../../utils/unit';
|
import { GIBIBYTE } from '../../../../utils/unit';
|
||||||
|
import { isInternalStorageClass } from '../../../../utils/storage-class';
|
||||||
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -118,11 +119,18 @@ export default {
|
|||||||
|
|
||||||
storageClassOptions() {
|
storageClassOptions() {
|
||||||
return this.storageClasses.filter((s) => !s.parameters?.backingImage).map((s) => {
|
return this.storageClasses.filter((s) => !s.parameters?.backingImage).map((s) => {
|
||||||
const label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
let label = s.isDefault ? `${ s.name } (${ this.t('generic.default') })` : s.name;
|
||||||
|
let disabled = false;
|
||||||
|
|
||||||
|
if (isInternalStorageClass(s.name)) {
|
||||||
|
label += ` (${ this.t('harvester.storage.internal.label') })`;
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: s.name,
|
value: s.name,
|
||||||
|
disabled
|
||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1369,6 +1369,10 @@ harvester:
|
|||||||
allowedTopologies:
|
allowedTopologies:
|
||||||
title: Allowed Topologies
|
title: Allowed Topologies
|
||||||
tooltip: Allowed Topologies helps scheduling virtual machines on hosts which match all of below expressions.
|
tooltip: Allowed Topologies helps scheduling virtual machines on hosts which match all of below expressions.
|
||||||
|
internal:
|
||||||
|
label: Internal Storage Class
|
||||||
|
cannotDeleteTooltip: Internal storage class volumes cannot be deleted
|
||||||
|
cannotDeleteOrDefaultTooltip: Internal storage classes cannot be deleted or set as default
|
||||||
|
|
||||||
vlanConfig:
|
vlanConfig:
|
||||||
title: Network Configuration
|
title: Network Configuration
|
||||||
|
|||||||
@ -83,6 +83,34 @@ export default {
|
|||||||
:rows="rows"
|
:rows="rows"
|
||||||
:schema="schema"
|
:schema="schema"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
|
>
|
||||||
|
<template #cell:name="{ row }">
|
||||||
|
<td>
|
||||||
|
<div>
|
||||||
|
<router-link
|
||||||
|
v-if="row?.detailLocation"
|
||||||
|
:to="row.detailLocation"
|
||||||
|
>
|
||||||
|
{{ row.nameDisplay }}
|
||||||
|
<i
|
||||||
|
v-if="row.isInternalStorageClass && typeof row.isInternalStorageClass === 'function' ? row.isInternalStorageClass() : false"
|
||||||
|
v-clean-tooltip="t('harvester.storage.internal.cannotDeleteOrDefaultTooltip')"
|
||||||
|
class="icon icon-info text-info"
|
||||||
|
style="margin-left: 0.4em;"
|
||||||
/>
|
/>
|
||||||
|
</router-link>
|
||||||
|
<span v-else>
|
||||||
|
{{ row.nameDisplay }}
|
||||||
|
<i
|
||||||
|
v-if="row.isInternalStorageClass && typeof row.isInternalStorageClass === 'function' ? row.isInternalStorageClass() : false"
|
||||||
|
v-clean-tooltip="t('harvester.storage.internal.cannotDeleteOrDefaultTooltip')"
|
||||||
|
class="icon icon-info text-info"
|
||||||
|
style="margin-left: 0.4em;"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</template>
|
||||||
|
</ResourceTable>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import ResourceTable from '@shell/components/ResourceTable';
|
|||||||
import { Banner } from '@components/Banner';
|
import { Banner } from '@components/Banner';
|
||||||
import { defaultTableSortGenerationFn } from '@shell/components/ResourceTable.vue';
|
import { defaultTableSortGenerationFn } from '@shell/components/ResourceTable.vue';
|
||||||
import FilterLabel from '../components/FilterLabel';
|
import FilterLabel from '../components/FilterLabel';
|
||||||
|
import { HCI as HCI_ANNOTATIONS } from '../config/labels-annotations';
|
||||||
|
import { isInternalStorageClass } from '../utils/storage-class';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ListHarvesterImage',
|
name: 'ListHarvesterImage',
|
||||||
@ -53,6 +55,13 @@ export default {
|
|||||||
|
|
||||||
return base;
|
return base;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isInternalStorageClass(row) {
|
||||||
|
const name = row?.spec?.targetStorageClassName ||
|
||||||
|
row?.metadata?.annotations?.[HCI_ANNOTATIONS.STORAGE_CLASS];
|
||||||
|
|
||||||
|
return isInternalStorageClass(name);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { STATE, AGE, NAME, NAMESPACE } from '@shell/config/table-headers';
|
|||||||
import HarvesterVolumeState from '../formatters/HarvesterVolumeState';
|
import HarvesterVolumeState from '../formatters/HarvesterVolumeState';
|
||||||
import { allSettled } from '../utils/promise';
|
import { allSettled } from '../utils/promise';
|
||||||
import { HCI, VOLUME_SNAPSHOT } from '../types';
|
import { HCI, VOLUME_SNAPSHOT } from '../types';
|
||||||
|
import { INTERNAL_STORAGE_CLASS } from '../config/types';
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
id: HCI.VOLUME,
|
id: HCI.VOLUME,
|
||||||
@ -130,6 +131,10 @@ export default {
|
|||||||
|
|
||||||
getVMName(row) {
|
getVMName(row) {
|
||||||
return row.attachVM?.metadata?.name || '';
|
return row.attachVM?.metadata?.name || '';
|
||||||
|
},
|
||||||
|
|
||||||
|
isInternalStorageClass(storageClassName) {
|
||||||
|
return this.$store.getters['type-map/labelFor'](INTERNAL_STORAGE_CLASS, storageClassName);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -170,7 +175,7 @@ export default {
|
|||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #col:name="{row}">
|
<template #col:name="{ row }">
|
||||||
<td>
|
<td>
|
||||||
<span>
|
<span>
|
||||||
<router-link
|
<router-link
|
||||||
|
|||||||
@ -4,6 +4,7 @@ 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 '../../models/harvester/persistentvolumeclaim';
|
import { DATA_ENGINE_V1, DATA_ENGINE_V2 } from '../../models/harvester/persistentvolumeclaim';
|
||||||
|
import { isInternalStorageClass } from '../../utils/storage-class';
|
||||||
|
|
||||||
export const LVM_DRIVER = 'lvm.driver.harvesterhci.io';
|
export const LVM_DRIVER = 'lvm.driver.harvesterhci.io';
|
||||||
|
|
||||||
@ -85,4 +86,22 @@ export default class HciStorageClass extends StorageClass {
|
|||||||
get thirdPartyStorageFeatureEnabled() {
|
get thirdPartyStorageFeatureEnabled() {
|
||||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('thirdPartyStorage');
|
return this.$rootGetters['harvester-common/getFeatureEnabled']('thirdPartyStorage');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isInternalStorageClass() {
|
||||||
|
return isInternalStorageClass(this.metadata?.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
get availableActions() {
|
||||||
|
let out = super.availableActions || [];
|
||||||
|
|
||||||
|
out = out.map((action) => {
|
||||||
|
if ((action.action === 'setDefault' || action.action === 'setAsDefault' || action.action === 'promptRemove') && this.isInternalStorageClass()) {
|
||||||
|
return { ...action, enabled: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
return action;
|
||||||
|
});
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
pkg/harvester/utils/storage-class.js
Normal file
6
pkg/harvester/utils/storage-class.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { INTERNAL_STORAGE_CLASS } from '../config/types';
|
||||||
|
|
||||||
|
export function isInternalStorageClass(name) {
|
||||||
|
return name === INTERNAL_STORAGE_CLASS.VMSTATE_PERSISTENCE ||
|
||||||
|
name === INTERNAL_STORAGE_CLASS.LONGHORN_STATIC;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user