mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2025-12-15 14:11:46 +00:00
feat: online Volume Resizing from the VM Page (#568)
* feat: add conditions tab * feat: ignore restart for resizing * refactor: remove unused code --------- Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
This commit is contained in:
parent
1a3822881e
commit
e6dd8d6771
@ -7,6 +7,7 @@ import ResourceTabs from '@shell/components/form/ResourceTabs';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
||||
import Conditions from '@shell/components/form/Conditions';
|
||||
import { Banner } from '@components/Banner';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
import { get } from '@shell/utils/object';
|
||||
@ -40,6 +41,7 @@ export default {
|
||||
LabeledSelect,
|
||||
LabeledInput,
|
||||
NameNsDescription,
|
||||
Conditions
|
||||
},
|
||||
|
||||
mixins: [CreateEditView],
|
||||
@ -593,6 +595,15 @@ export default {
|
||||
:label="t('nameNsDescription.name.label')"
|
||||
/>
|
||||
</Tab>
|
||||
<Tab
|
||||
v-if="!isCreate"
|
||||
name="conditions"
|
||||
:label="t('harvester.volume.tabs.conditions')"
|
||||
class="bordered-table"
|
||||
:mode="mode"
|
||||
>
|
||||
<Conditions :value="value" />
|
||||
</Tab>
|
||||
</ResourceTabs>
|
||||
</CruResource>
|
||||
</template>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { isEqual } from 'lodash';
|
||||
import { mapGetters } from 'vuex';
|
||||
import Tabbed from '@shell/components/Tabbed';
|
||||
import { clone, set } from '@shell/utils/object';
|
||||
import { clone } from '@shell/utils/object';
|
||||
import Tab from '@shell/components/Tabbed/Tab';
|
||||
import { Checkbox } from '@components/Form/Checkbox';
|
||||
import CruResource from '@shell/components/CruResource';
|
||||
@ -434,38 +434,44 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
_compareDisksIgnoreStorage(disksA = [], disksB = []) {
|
||||
if (disksA.length !== disksB.length) return false;
|
||||
|
||||
const sortedA = [...disksA].sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));
|
||||
const sortedB = [...disksB].sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));
|
||||
|
||||
for (let i = 0; i < sortedA.length; i++) {
|
||||
const cloneA = clone(sortedA[i]);
|
||||
const cloneB = clone(sortedB[i]);
|
||||
|
||||
// remove the storage field before comparison
|
||||
delete cloneA?.spec?.resources?.requests?.storage;
|
||||
delete cloneB?.spec?.resources?.requests?.storage;
|
||||
|
||||
if (!isEqual(cloneA, cloneB)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_shouldPromptRestart(oldVM, newVM) {
|
||||
const specChanged = !isEqual(oldVM?.spec, newVM?.spec);
|
||||
|
||||
// check if the disk defined in annotations has changed, ignoring storage size
|
||||
const oldDisks = parseVolumeClaimTemplates(oldVM);
|
||||
const newDisks = parseVolumeClaimTemplates(newVM);
|
||||
const diskChanged = !this._compareDisksIgnoreStorage(oldDisks, newDisks);
|
||||
|
||||
return specChanged || diskChanged;
|
||||
},
|
||||
|
||||
restartVM() {
|
||||
if (this.mode !== 'edit') {
|
||||
return;
|
||||
}
|
||||
if (!this.value.isRunning) {
|
||||
return;
|
||||
}
|
||||
const cloneDeepNewVM = clone(this.value);
|
||||
if (this.mode !== 'edit' || !this.value.isRunning) return;
|
||||
|
||||
// new VM
|
||||
delete cloneDeepNewVM?.metadata;
|
||||
delete cloneDeepNewVM?.__clone;
|
||||
const needsRestart = this._shouldPromptRestart(this.cloneVM, this.value);
|
||||
|
||||
// old VM
|
||||
delete this.cloneVM?.metadata;
|
||||
delete this.cloneVM?.__clone;
|
||||
|
||||
// add empty hostDevices to old VM as CRD does not have it.
|
||||
const devicesObj = this.cloneVM?.spec?.template?.spec?.domain?.devices;
|
||||
|
||||
if (devicesObj && devicesObj.hostDevices === undefined) {
|
||||
set(devicesObj, 'hostDevices', []);
|
||||
}
|
||||
|
||||
const oldVM = JSON.parse(JSON.stringify(this.cloneVM));
|
||||
const newVM = JSON.parse(JSON.stringify(cloneDeepNewVM));
|
||||
|
||||
// we won't show restart dialog in yaml page as we don't have a way to detect change in yaml editor.
|
||||
// only check VM is changed in form page.
|
||||
if (isEqual(oldVM, newVM)) {
|
||||
return;
|
||||
}
|
||||
// if no restart is needed (either no changes or only size changed)
|
||||
if (!needsRestart) return;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.isOpen = true;
|
||||
|
||||
@ -837,6 +837,7 @@ harvester:
|
||||
snapshots: Snapshots
|
||||
datasource: Data Source
|
||||
details: Details
|
||||
conditions: Conditions
|
||||
size: Size
|
||||
volumeMode: Volume Mode
|
||||
source: Source
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user