]> git.immae.eu Git - github/bastienwirtz/homer.git/blob - src/components/services/Proxmox.vue
2b533db673e1b0ed5d2527a2d3cad9814f40e0c1
[github/bastienwirtz/homer.git] / src / components / services / Proxmox.vue
1 <template>
2 <Generic :item="item">
3 <template #content>
4 <p class="title is-4">{{ item.name }}</p>
5 <p class="subtitle is-6">
6 <template v-if="item.subtitle">
7 {{ item.subtitle }}
8 </template>
9 <template v-else-if="vms">
10 <div v-if="loading">
11 <strong>Loading...</strong>
12 </div>
13 <div v-else-if="error">
14 <strong class="danger">Error loading info</strong>
15 </div>
16 <div v-else class="metrics" :class="{'is-size-7-mobile': item.small_font_on_small_screens, 'is-small': item.small_font_on_desktop}">
17 <span v-if="isValueShown('vms')" class="margined">VMs: <span class="is-number"><span class="has-text-weight-bold">{{ vms.running }}</span><span v-if="isValueShown('vms_total')">/{{vms.total}}</span></span></span>
18 <span v-if="isValueShown('lxcs')" class="margined">LXCs: <span class="is-number"><span class="has-text-weight-bold">{{ lxcs.running }}</span><span v-if="isValueShown('lxcs_total')">/{{lxcs.total}}</span></span></span>
19 <span v-if="isValueShown('disk')" class="margined">Disk: <span class="has-text-weight-bold is-number" :class="statusClass(diskUsed)">{{ diskUsed }}%</span></span>
20 <span v-if="isValueShown('mem')" class="margined">Mem: <span class="has-text-weight-bold is-number" :class="statusClass(memoryUsed)">{{ memoryUsed }}%</span></span>
21 <span v-if="isValueShown('cpu')" class="margined">CPU: <span class="has-text-weight-bold is-number" :class="statusClass(cpuUsed)">{{ cpuUsed }}%</span></span>
22 </div>
23 </template>
24 </p>
25 </template>
26 <template #indicator>
27 <i v-if="loading" class="fa fa-circle-notch fa-spin fa-2xl"></i>
28 <i v-if="error" class="fa fa-exclamation-circle fa-2xl danger"></i>
29 </template>
30 </Generic>
31 </template>
32
33 <script>
34 import service from "@/mixins/service.js";
35 import Generic from "./Generic.vue";
36
37 export default {
38 name: "Proxmox",
39 mixins: [service],
40 props: {
41 item: Object,
42 },
43 components: {
44 Generic,
45 },
46 data: () => ({
47 vms: {
48 total: 0,
49 running: 0
50 },
51 lxcs: {
52 total: 0,
53 running: 0
54 },
55 memoryUsed: 0,
56 diskUsed: 0,
57 cpuUsed: 0,
58 hide: [],
59 error: false,
60 loading: true
61 }),
62 created() {
63 if (this.item.hide) this.hide = this.item.hide;
64 this.fetchStatus();
65 },
66 methods: {
67 statusClass(value) {
68 if (value > this.item.danger_value) return 'danger';
69 if (value > this.item.warning_value) return 'warning';
70 return 'healthy'
71 },
72 fetchStatus: async function () {
73 try {
74 const options = {
75 headers: {
76 "Authorization": this.item.api_token
77 }
78 }
79 const status = await this.fetch(`/api2/json/nodes/${this.item.node}/status`, options);
80 // main metrics:
81 const decimalsToShow = this.item.hide_decimals ? 0 : 1;
82 this.memoryUsed = ( (status.data.memory.used * 100) / status.data.memory.total ).toFixed(decimalsToShow);
83 this.diskUsed = ( (status.data.rootfs.used * 100) / status.data.rootfs.total ).toFixed(decimalsToShow);
84 this.cpuUsed = (status.data.cpu * 100).toFixed(decimalsToShow);
85 // vms:
86 if (this.isValueShown('vms')) {
87 const vms = await this.fetch(`/api2/json/nodes/${this.item.node}/qemu`, options);
88 this.parseVMsAndLXCs(vms, this.vms);
89 }
90 // lxc containers:
91 if (this.isValueShown('lxcs')) {
92 const lxcs = await this.fetch(`/api2/json/nodes/${this.item.node}/lxc`, options);
93 this.parseVMsAndLXCs(lxcs, this.lxcs);
94 }
95 this.error = false;
96 } catch(err) {
97 console.log(err);
98 this.error = true;
99 }
100 this.loading = false;
101 },
102 parseVMsAndLXCs(items, value) {
103 value.total += items.data.length;
104 value.running += items.data.filter( i => i.status === 'running' ).length;
105 // if no vms, hide this value:
106 if (value.total == 0) this.hide.push('lxcs');
107 },
108 isValueShown(value) {
109 return this.hide.indexOf(value) == -1;
110 }
111 },
112 };
113 </script>
114
115 <style scoped lang="scss">
116 .is-number {
117 font-family: "Lato"
118 }
119 .healthy {
120 color: green
121 }
122 .warning {
123 color: orange
124 }
125 .danger {
126 color: red
127 }
128 .metrics .margined:not(:first-child) {
129 margin-left: 0.3rem;
130 }
131 .is-small {
132 font-size: small;
133 }
134 </style>
135