Files
virt-dashboard/frontend/src/components/reports/VmwareDecomissionDatatable.vue
2023-09-08 19:05:37 +03:00

442 lines
13 KiB
Vue

<template>
<div class="row md12 justify--space-between">
<va-input
class="flex mb-1"
placeholder="Search..."
v-model="filterTmp"
@keyup="clickFilterEnter"
:bordered="false"
>
<template #prependInner class="row">
<va-icon class="material-icons" color="secondary">search</va-icon>
</template>
<template #appendInner class="row">
<va-chip
v-for="(item, index) in this.filters"
class="ml-2 filterTag"
size="small"
>
{{ item }}
<va-button icon="clear" size="small" class="ml-1 mr-0" @click="clickFilterClear(index)" />
</va-chip>
</template>
</va-input>
<div class="flex mb-1">
<va-button
@click="updateReport"
class="update_btn mr-2"
flat
>
<va-icon
name="loop"
:spin="isLoading"
/>
</va-button>
<va-button
class="justify--end mr-2"
outline
icon="save_alt"
@click="clickCSV(this.filteredItems, this.columns)"
>
CSV
</va-button>
<va-button-dropdown
class="justify--end mr-2"
outline
label="Columns"
:close-on-content-click="false"
>
<div>
<va-checkbox class="mb-2" v-for="(item, index) in this.columnsAll" :label="item.label" v-model="this.columnsAll[index].visible" @update:model-value="calcColumns" />
</div>
</va-button-dropdown>
</div>
</div>
<va-data-table
:items="items"
:columns="columns"
:filter="filter"
:hoverable="true"
@filtered="filteredItems = $event.items"
:loading="isLoading"
sticky-header
class="flex md12 tableReport"
:row-bind="getRowBind"
>
<template #cell(vcenter_hostname)="{ value }">
<a :href="`https://${ value }/ui`" target="_blank" class="link">{{ value }}</a>
</template>
<template #cell(environment)="{ value,rowData }">
<va-badge right :text="value" :color="rowData.environment.attributes?.color"/>
</template>
<template #cell(hosts)="{ value,rowData }">
<va-badge right color="warning" v-if="rowData.maintenance.length > 0">
<template #text>
<router-link :to="{ name:'vmware-mmhosts', params: { filters: [`cluster/${rowData.attributes.cluster_name.toLowerCase()}`] } }">{{ rowData.maintenance.length }}</router-link>
</template>
<span class="fixedWidth2ch">{{ value }}</span>
</va-badge>
<span v-else>{{ value }}</span>
</template>
<template #cell(hosts_maintenance)="{ value,rowData }">
{{ rowData.maintenance.length }}
</template>
<template #cell(cpu_cap_use)="{ value }" >
{{ value }}%
</template>
<template #cell(pcpu_retire_target)="{ value }" >
{{ value*100 }}%
</template>
</va-data-table>
<va-alert class="mt-3" color="info" outline>
<div class="row md-12 justify--space-between reportFooter">
<span>
Number of filtered items:
<va-chip>{{ filteredItems.length }}</va-chip>
</span>
<span class="reportDate mr-3">
<va-badge right class="transparentBadge dangerBadge">
<template #text v-if="checkReportDate(this.timestamp)">
<va-icon name="warning_amber_icon" />
</template>
Data collected: {{ timestamp }}
</va-badge>
</span>
</div>
</va-alert>
</template>
<script>
import { defineComponent } from 'vue';
import ReportsService from '@/api/report-service';
import { sortingBase } from '@/scripts/sorters';
import { formatBytes, pickClass, checkReportDate } from '@/scripts/formatters';
import { clickCSV } from '@/scripts/exporters';
export default defineComponent({
data () {
const columnsAll = [
{
key: 'attributes.contour_name',
label: 'Contour',
sortable: true,
visible: true,
},
{
key: 'attributes.vcenter_hostname',
label: 'vCenter',
sortable: true,
name: 'vcenter_hostname',
},
{
key: 'attributes.cluster_name',
label: 'Cluster',
sortable: true,
name: 'cluster',
visible: true,
},
{
key: 'attributes.environment_name',
label: 'Environment',
tdAlign: 'center',
thAlign: 'center',
sortable: true,
name: 'environment',
visible: true,
},
{
key: 'attributes.hosts_total',
label: 'Hosts',
sortable: true,
name: 'hosts',
sortingFn: (a,b) => this.sortingBase(a,b),
visible: true,
filterable: false,
},
{
key: 'attributes.hosts_to_decomiss',
label: 'Hosts to decomission',
sortable: true,
name: 'hosts_to_decomiss',
sortingFn: (a,b) => this.sortingBase(a,b),
visible: true,
filterable: false,
},
{
key: 'attributes.pcpu_to_decomiss',
label: 'pCPU to decomiss',
sortable: true,
name: 'pcpu_to_decomiss',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.hosts_staged_dcm',
label: 'Staged to decomission',
sortable: true,
name: 'hosts_staged_dcm',
sortingFn: (a,b) => this.sortingBase(a,b),
visible: true,
filterable: false,
},
{
key: 'maintenance',
label: 'MM',
sortable: true,
name: 'hosts_maintenance',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.hosts_reserved',
label: 'Reserved',
sortable: true,
name: 'hosts_reserved',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.vms_total',
label: 'VMs',
sortable: true,
sortingFn: (a,b) => this.sortingBase(a,b),
visible: true,
filterable: false,
},
{
key: 'attributes.sockets_total',
label: 'Sockets',
sortable: true,
name: 'sockets_total',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.cpu_cap_used',
label: 'CPU provisioned',
sortable: true,
name: 'cpu_cap_use',
sortingFn: (a,b) => this.sortingBase(a,b),
visible: true,
filterable: false,
},
{
key: 'attributes.pcpu_ovp_target',
label: 'CPU Target',
sortable: true,
name: 'pcpu_ovp_target',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.pcpu_ovp_current',
label: 'CPU Current',
sortable: true,
name: 'pcpu_ovp_current',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.pcpu_retire_target',
label: 'CPU Decomission target',
sortable: true,
name: 'pcpu_retire_target',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.pcpu_total',
label: 'pCPU Total',
sortable: true,
name: 'pcpu_total',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
{
key: 'attributes.vcpu_provisioned',
label: 'vCPU Provisioned',
sortable: true,
name: 'vcpu_provisioned',
sortingFn: (a,b) => this.sortingBase(a,b),
filterable: false,
},
]
return {
items: [],
itemsAll: [],
columns: [],
columnsAll,
filterTimeout: 0,
filterTmp: '',
filter: '',
filters: [],
isLoading: true,
filteredItems: [],
timestamp: 0,
showBlock: false,
};
},
created() {
if(localStorage.decomissionVisibleColumns) {
let visibleColumns = JSON.parse(localStorage.decomissionVisibleColumns)
this.columnsAll.forEach( item =>
visibleColumns.includes(item.key) ? item.visible = true : item.visible = false
)
} else {
localStorage.decomissionVisibleColumns = JSON.stringify(
this.columnsAll.filter(item => item.visible).map(a => a.key)
)
}
this.columns = this.columnsAll.filter(item => item.visible);
this.retreiveReport();
if (this.$route.params?.filters) {
this.filters = this.$route.params.filters
this.columnsAll[2].visible = true
}
this.columns = this.columnsAll.filter(item => item.visible);
},
methods: {
checkReportDate,
sortingBase,
formatBytes,
pickClass,
clickCSV,
calcColumns () {
localStorage.decomissionVisibleColumns = JSON.stringify(
this.columnsAll.filter(item => item.visible).map(a => a.key)
)
this.columns = this.columnsAll.filter(item => item.visible);
},
getRowBind (row) {
const classes = []
if (row.attributes.hosts_staged_dcm >= 16) {
classes.push('rowCritical')
}
return { class: classes }
},
clickFilterEnter (event) {
if ((event.keyCode > 111 && event.keyCode < 136) || (event.keyCode > 15 && event.keyCode < 19)) { return }
if (event.keyCode === 13) {
if (this.filterTmp !== '') {
this.filters.unshift(this.filterTmp.toLowerCase())
this.items = this.filterItems(this.items, this.filters)
this.filterTmp = ''
this.filter = ''
}
} else {
this.isLoading = true
clearTimeout(this.filterTimeout)
this.filterTimeout = setTimeout(() => {
this.filter = this.filterTmp
this.isLoading = false
},300)
}
},
clickFilterClear (index) {
this.filters.splice(index,1)
this.items = this.filterItems(this.itemsAll, this.filters)
},
filterItems(items, filters) {
filters.forEach(filter => {
items = items.filter(item => {
return Object.values(item.attributes).some( value => {
if (typeof value === 'string') {
return value.toLowerCase().includes(filter)
} else {
false
}
})
})
})
return items
},
retreiveReport() {
ReportsService.getLastFrame().then(response => {
this.timestamp = response?.attributes?.timestamp.slice(0,response.attributes.timestamp.length-10) ?? 0
ReportsService.getLastVmWareCapacityReport(response.id).then(response => {
let clusters = response.data.included.filter(x => x.type === "cluster");
let vcenters = response.data.included.filter(x => x.type === "vcenter");
let contours = response.data.included.filter(x => x.type === "contour");
let environments = response.data.included.filter(x => x.type === "environment");
let maintenance = response.data.included.filter(x => x.type === "maintenance");
response.data.data.forEach(element => {
element["cluster"] = clusters.find(x => x.id == element.attributes.cluster_id)
element["vcenter"] = vcenters.find(x => x.id == element.cluster?.attributes.vcenter_id)
element["contour"] = contours.find(x => x.id == element.vcenter?.attributes.contour_id)
element["environment"] = environments.find(x => x.id == element.cluster?.attributes.environment_id) ?? ""
element["maintenance"] = maintenance.filter(x => x.attributes.cluster_id == element.attributes.cluster_id) ?? 0
element.attributes["cluster_name"] = element.cluster?.attributes.name
element.attributes["contour_name"] = element.contour?.attributes.name
element.attributes["environment_name"] = element?.environment?.attributes?.name ?? ""
element.attributes["vcenter_hostname"] = element.vcenter?.attributes.hostname
var pcpu = ((element.attributes.pcpu_total*element.attributes.pcpu_retire_target | 0) - ((element.attributes.vcpu_provisioned/element.attributes.pcpu_ovp_target) | 0)) ?? 0
if (pcpu > 0) {
element.attributes["pcpu_to_decomiss"] = pcpu
} else {
element.attributes["pcpu_to_decomiss"] = 0
}
element.attributes["hosts_to_decomiss"] = (element.attributes?.pcpu_to_decomiss/(element.attributes.pcpu_host_max) | 0) ?? 0
delete element.attributes.cluster_id
delete element.attributes.frame_id
delete element.relationships
delete element.links
});
response.data.data = response.data.data.filter(item => item.attributes.contour_name != 'VDI')
this.items = this.filterItems(response.data.data, this.filters);
this.itemsAll = response.data.data;
this.isLoading = false
}).catch(e => {
console.log(e);
})
}).catch(e => {
console.log(e);
})
},
updateReport() {
this.isLoading = true
this.retreiveReport()
},
},
})
</script>
<style lang="scss">
</style>