Latest changes from harvester/master

Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
Francesco Torchia
2024-10-23 17:01:03 +02:00
parent deeccf3db6
commit ec3d88aeb7
56 changed files with 1498 additions and 2197 deletions
@@ -134,15 +134,16 @@ export default {
const inStore = this.$store.getters['currentProduct'].inStore;
const hash = {
vms: this.fetchClusterResources(HCI.VM),
nodes: this.fetchClusterResources(NODE),
events: this.fetchClusterResources(EVENT),
metricNodes: this.fetchClusterResources(METRIC.NODE),
settings: this.fetchClusterResources(HCI.SETTING),
services: this.fetchClusterResources(SERVICE),
metric: this.fetchClusterResources(METRIC.NODE),
longhornNode: this.fetchClusterResources(LONGHORN.NODES) || [],
_pods: this.$store.dispatch('harvester/findAll', { type: POD }),
vms: this.fetchClusterResources(HCI.VM),
nodes: this.fetchClusterResources(NODE),
events: this.fetchClusterResources(EVENT),
metricNodes: this.fetchClusterResources(METRIC.NODE),
settings: this.fetchClusterResources(HCI.SETTING),
services: this.fetchClusterResources(SERVICE),
metric: this.fetchClusterResources(METRIC.NODE),
longhornNodes: this.fetchClusterResources(LONGHORN.NODES),
longhornSettings: this.fetchClusterResources(LONGHORN.SETTINGS),
_pods: this.$store.dispatch('harvester/findAll', { type: POD }),
};
(this.accessibleResources || []).map((a) => {
@@ -155,6 +156,10 @@ export default {
hash.addons = this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.ADD_ONS });
}
if (this.$store.getters[`${ inStore }/schemaFor`](LONGHORN.NODES)) {
this.hasLonghornSchema = true;
}
const res = await allHash(hash);
for ( const k in res ) {
@@ -226,6 +231,7 @@ export default {
showClusterMetrics: false,
showVmMetrics: false,
enabledMonitoringAddon: false,
hasLonghornSchema: false,
};
},
@@ -305,8 +311,7 @@ export default {
currentVersion() {
const inStore = this.$store.getters['currentProduct'].inStore;
const settings = this.$store.getters[`${ inStore }/all`](HCI.SETTING);
const setting = settings.find( S => S.id === 'server-version');
const setting = this.$store.getters[`${ inStore }/byId`](HCI.SETTING, 'server-version');
return setting?.value || setting?.default;
},
@@ -364,53 +369,46 @@ export default {
return out;
},
storageUsage() {
const inStore = this.$store.getters['currentProduct'].inStore;
const longhornNodes = this.$store.getters[`${ inStore }/all`](LONGHORN.NODES) || [];
return longhornNodes.filter(node => node.spec?.allowScheduling).reduce((total, node) => {
return total + node.used;
}, 0);
},
storageReservedTotal() {
let out = 0;
(this.longhornNode || []).filter(node => node.spec?.allowScheduling).forEach((node) => {
storageStats() {
const storageOverProvisioningPercentageSetting = this.longhornSettings.find(s => s.id === 'longhorn-system/storage-over-provisioning-percentage');
const stats = this.longhornNodes.reduce((total, node) => {
const disks = node?.spec?.disks || {};
Object.values(disks).map((disk) => {
if (disk.allowScheduling) {
out += disk.storageReserved;
}
});
});
return out;
},
storageTotal() {
let out = 0;
(this.longhornNode || []).forEach((node) => {
const diskStatus = node?.status?.diskStatus || {};
Object.values(diskStatus).map((disk) => {
if (disk?.storageMaximum) {
out += disk.storageMaximum;
}
total.used += node?.spec?.allowScheduling ? node.used : 0;
Object.keys(disks).map((key) => {
total.scheduled += node?.spec?.allowScheduling ? (diskStatus[key]?.storageScheduled || 0) : 0;
total.reserved += disks[key]?.storageReserved || 0;
});
Object.values(diskStatus).map((diskStat) => {
total.maximum += diskStat?.storageMaximum || 0;
});
return total;
}, {
used: 0,
scheduled: 0,
maximum: 0,
reserved: 0,
total: 0
});
return out;
stats.total = ((stats.maximum - stats.reserved) * Number(storageOverProvisioningPercentageSetting?.value ?? 0)) / 100;
return stats;
},
storageUsed() {
return this.createMemoryValues(this.storageTotal, this.storageUsage);
const stats = this.storageStats;
return this.createMemoryValues(stats.maximum, stats.used);
},
storageReserved() {
return this.createMemoryValues(this.storageTotal, this.storageReservedTotal);
storageAllocated() {
const stats = this.storageStats;
return this.createMemoryValues(stats.total, stats.scheduled);
},
vmEvents() {
@@ -644,7 +642,7 @@ export default {
<div
class="hardware-resource-gauges"
:class="{
live: !storageTotal,
live: !hasLonghornSchema,
}"
>
<HardwareResourceGauge
@@ -658,10 +656,11 @@ export default {
:used="ramUsed"
/>
<HardwareResourceGauge
v-if="storageTotal"
v-if="hasLonghornSchema"
:name="t('harvester.dashboard.hardwareResourceGauge.storage')"
:used="storageUsed"
:reserved="storageReserved"
:reserved="storageAllocated"
:reserved-title="t('clusterIndexPage.hardwareResourceGauge.allocated')"
/>
</div>
</template>
+41 -7
View File
@@ -8,6 +8,7 @@ import {
import { allHash } from '@shell/utils/promise';
import metricPoller from '@shell/mixins/metric-poller';
import { HCI } from '../types';
import { DOC_LINKS } from '../config/doc-links';
const schema = {
id: HCI.HOST,
@@ -91,6 +92,7 @@ export default {
value: 'internalIp',
formatter: 'CopyToClipboard',
sort: ['internalIp'],
align: 'center',
},
];
@@ -98,7 +100,7 @@ export default {
const metricCol = [
{
name: 'cpu',
labelKey: 'tableHeaders.cpu',
labelKey: 'node.detail.glance.consumptionGauge.cpu',
value: 'id',
formatter: 'HarvesterCPUUsed',
formatterOpts: { showUsed: true },
@@ -121,12 +123,23 @@ export default {
labelKey: 'tableHeaders.storage',
value: 'id',
formatter: 'HarvesterStorageUsed',
formatterOpts: { showReserved: true },
formatterOpts: { showAllocated: true },
};
out.splice(-1, 0, storageHeader);
}
out.push({
name: 'cpuManager',
labelKey: 'harvester.tableHeaders.cpuManager',
value: 'id',
formatter: 'HarvesterCPUPinning',
formatterOpts: { rows: this.rows },
width: 150,
align: 'center',
});
if (this.hasLonghornSchema) {
out.push({
name: 'diskState',
@@ -143,7 +156,7 @@ export default {
name: 'console',
label: ' ',
align: 'right',
width: 65,
width: 80,
});
return out;
@@ -151,6 +164,10 @@ export default {
schema() {
return schema;
},
consoleDocLink() {
return DOC_LINKS.CONSOLE_URL;
}
},
methods: {
@@ -169,7 +186,15 @@ export default {
goto(row) {
window.open(row.consoleUrl, '_blank');
}
},
consoleTooltip(row) {
if (!row.consoleUrl) {
return this.t('harvester.host.noConsoleUrl');
}
return '';
},
},
typeDisplay() {
@@ -199,10 +224,19 @@ export default {
>
<template #cell:console="{row}">
<button type="button" class="btn btn-sm role-primary" :disabled="!row.consoleUrl" @click="goto(row)">
{{ t('harvester.host.console') }}
</button>
<div class="console-button">
<button v-clean-tooltip="consoleTooltip(row)" type="button" class="mr-5 btn btn-sm role-primary" :disabled="!row.consoleUrl" @click="goto(row)">
{{ t('harvester.host.console') }}
</button>
<a v-if="!row.consoleUrl" :href="consoleDocLink" target="_blank"><i class="icon icon-info" /></a>
</div>
</template>
</ResourceTable>
</div>
</template>
<style lang="scss" scoped>
.console-button {
display: flex;
}
</style>
@@ -103,7 +103,6 @@ export default {
:schema="schema"
:rows="rows"
key-field="_key"
/>
</div>
</template>
+10 -12
View File
@@ -56,8 +56,6 @@ export default {
this.$store.dispatch('type-map/configureType', { match: HCI.VOLUME, isCreatable: false });
}
console.log('ppppppppppp', hash);
this.rows = hash.pvcs;
},
@@ -151,23 +149,23 @@ export default {
>
<template
cell:state="scope"
>
cell:state="scope"
>
<div class="state">
<HarvesterVolumeState
class="vmstate"
:row="scope.row"
/>
class="vmstate"
:row="scope.row"
/>
</div>
</template>
<template
cell:AttachedVM="scope"
>
cell:AttachedVM="scope"
>
<div>
<router-link
v-if="getVMName(scope.row)"
:to="goTo(scope.row)"
>
v-if="getVMName(scope.row)"
:to="goTo(scope.row)"
>
{{ getVMName(scope.row) }}
</router-link>
</div>
@@ -81,6 +81,10 @@ export default {
backups: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.BACKUP }),
};
if (this.$store.getters[`${ inStore }/schemaFor`](HCI.RESOURCE_QUOTA)) {
_hash.resourceQuotas = this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.RESOURCE_QUOTA });
}
if (this.$store.getters[`${ inStore }/schemaFor`](NODE)) {
_hash.nodes = this.$store.dispatch(`${ inStore }/findAll`, { type: NODE });
this.hasNode = true;
@@ -116,7 +120,7 @@ export default {
headers() {
const restoreCol = {
name: 'restoreProgress',
labelKey: 'tableHeaders.restore',
labelKey: 'harvester.tableHeaders.restore',
value: 'restoreProgress',
align: 'left',
formatter: 'HarvesterBackupProgressBar',
@@ -128,7 +132,7 @@ export default {
value: 'nodeName',
sort: ['realAttachNodeName'],
formatter: 'HarvesterHost',
labelKey: 'tableHeaders.node'
labelKey: 'harvester.tableHeaders.vm.node'
};
const cols = clone(VM_HEADERS);
@@ -137,7 +141,7 @@ export default {
cols.splice(-1, 0, nodeCol);
}
if (this.hasRestoredVMs) {
if (this.hasBackUpRestoreInProgress) {
cols.splice(-1, 0, restoreCol);
}
@@ -150,8 +154,11 @@ export default {
return [...this.allVMs, ...matchVMIs];
},
hasRestoredVMs() {
return !!this.rows.find(r => !!r.restoreResource);
/**
* We want to show the progress bar only for Backup's restore; snapshot's restore is immediate.
*/
hasBackUpRestoreInProgress() {
return !!this.rows.find(r => r.restoreResource && !r.restoreResource.fromSnapshot && !r.restoreResource.isComplete);
}
},
@@ -179,7 +186,7 @@ export default {
key-field="_key"
>
<template cell:state="scope">
<template cell:state="scope" class="state-col">
<div class="state">
<HarvesterVmState class="vmstate" :row="scope.row" :all-node-network="allNodeNetworks" :all-cluster-network="allClusterNetworks" />
</div>