aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/services/Proxmox.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/services/Proxmox.vue')
-rw-r--r--src/components/services/Proxmox.vue314
1 files changed, 186 insertions, 128 deletions
diff --git a/src/components/services/Proxmox.vue b/src/components/services/Proxmox.vue
index 2b533db..8136050 100644
--- a/src/components/services/Proxmox.vue
+++ b/src/components/services/Proxmox.vue
@@ -1,135 +1,193 @@
1<template> 1<template>
2 <Generic :item="item"> 2 <Generic :item="item">
3 <template #content> 3 <template #content>
4 <p class="title is-4">{{ item.name }}</p> 4 <p class="title is-4">{{ item.name }}</p>
5 <p class="subtitle is-6"> 5 <p class="subtitle is-6">
6 <template v-if="item.subtitle"> 6 <template v-if="item.subtitle">
7 {{ item.subtitle }} 7 {{ item.subtitle }}
8 </template> 8 </template>
9 <template v-else-if="vms"> 9 <template v-else-if="vms">
10 <div v-if="loading"> 10 <div v-if="loading">
11 <strong>Loading...</strong> 11 <strong>Loading...</strong>
12 </div> 12 </div>
13 <div v-else-if="error"> 13 <div v-else-if="error">
14 <strong class="danger">Error loading info</strong> 14 <strong class="danger">Error loading info</strong>
15 </div> 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}"> 16 <div
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> 17 v-else
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> 18 class="metrics"
19 <span v-if="isValueShown('disk')" class="margined">Disk: <span class="has-text-weight-bold is-number" :class="statusClass(diskUsed)">{{ diskUsed }}%</span></span> 19 :class="{
20 <span v-if="isValueShown('mem')" class="margined">Mem: <span class="has-text-weight-bold is-number" :class="statusClass(memoryUsed)">{{ memoryUsed }}%</span></span> 20 'is-size-7-mobile': item.small_font_on_small_screens,
21 <span v-if="isValueShown('cpu')" class="margined">CPU: <span class="has-text-weight-bold is-number" :class="statusClass(cpuUsed)">{{ cpuUsed }}%</span></span> 21 'is-small': item.small_font_on_desktop,
22 </div> 22 }"
23 </template> 23 >
24 </p> 24 <span v-if="isValueShown('vms')" class="margined"
25 </template> 25 >VMs:
26 <template #indicator> 26 <span class="is-number"
27 <i v-if="loading" class="fa fa-circle-notch fa-spin fa-2xl"></i> 27 ><span class="has-text-weight-bold">{{ vms.running }}</span
28 <i v-if="error" class="fa fa-exclamation-circle fa-2xl danger"></i> 28 ><span v-if="isValueShown('vms_total')"
29 </template> 29 >/{{ vms.total }}</span
30 </Generic> 30 ></span
31 </template> 31 ></span
32 32 >
33 <script> 33 <span v-if="isValueShown('lxcs')" class="margined"
34 import service from "@/mixins/service.js"; 34 >LXCs:
35 import Generic from "./Generic.vue"; 35 <span class="is-number"
36 36 ><span class="has-text-weight-bold">{{ lxcs.running }}</span
37 export default { 37 ><span v-if="isValueShown('lxcs_total')"
38 name: "Proxmox", 38 >/{{ lxcs.total }}</span
39 mixins: [service], 39 ></span
40 props: { 40 ></span
41 item: Object, 41 >
42 <span v-if="isValueShown('disk')" class="margined"
43 >Disk:
44 <span
45 class="has-text-weight-bold is-number"
46 :class="statusClass(diskUsed)"
47 >{{ diskUsed }}%</span
48 ></span
49 >
50 <span v-if="isValueShown('mem')" class="margined"
51 >Mem:
52 <span
53 class="has-text-weight-bold is-number"
54 :class="statusClass(memoryUsed)"
55 >{{ memoryUsed }}%</span
56 ></span
57 >
58 <span v-if="isValueShown('cpu')" class="margined"
59 >CPU:
60 <span
61 class="has-text-weight-bold is-number"
62 :class="statusClass(cpuUsed)"
63 >{{ cpuUsed }}%</span
64 ></span
65 >
66 </div>
67 </template>
68 </p>
69 </template>
70 <template #indicator>
71 <i v-if="loading" class="fa fa-circle-notch fa-spin fa-2xl"></i>
72 <i v-if="error" class="fa fa-exclamation-circle fa-2xl danger"></i>
73 </template>
74 </Generic>
75</template>
76
77<script>
78import service from "@/mixins/service.js";
79import Generic from "./Generic.vue";
80
81export default {
82 name: "Proxmox",
83 mixins: [service],
84 props: {
85 item: Object,
86 },
87 components: {
88 Generic,
89 },
90 data: () => ({
91 vms: {
92 total: 0,
93 running: 0,
42 }, 94 },
43 components: { 95 lxcs: {
44 Generic, 96 total: 0,
97 running: 0,
45 }, 98 },
46 data: () => ({ 99 memoryUsed: 0,
47 vms: { 100 diskUsed: 0,
48 total: 0, 101 cpuUsed: 0,
49 running: 0 102 hide: [],
50 }, 103 error: false,
51 lxcs: { 104 loading: true,
52 total: 0, 105 }),
53 running: 0 106 created() {
54 }, 107 if (this.item.hide) this.hide = this.item.hide;
55 memoryUsed: 0, 108 this.fetchStatus();
56 diskUsed: 0, 109 },
57 cpuUsed: 0, 110 methods: {
58 hide: [], 111 statusClass(value) {
59 error: false, 112 if (value > this.item.danger_value) return "danger";
60 loading: true 113 if (value > this.item.warning_value) return "warning";
61 }), 114 return "healthy";
62 created() {
63 if (this.item.hide) this.hide = this.item.hide;
64 this.fetchStatus();
65 }, 115 },
66 methods: { 116 fetchStatus: async function () {
67 statusClass(value) { 117 try {
68 if (value > this.item.danger_value) return 'danger'; 118 const options = {
69 if (value > this.item.warning_value) return 'warning'; 119 headers: {
70 return 'healthy' 120 Authorization: this.item.api_token,
71 }, 121 },
72 fetchStatus: async function () { 122 };
73 try { 123 const status = await this.fetch(
74 const options = { 124 `/api2/json/nodes/${this.item.node}/status`,
75 headers: { 125 options
76 "Authorization": this.item.api_token 126 );
77 } 127 // main metrics:
78 } 128 const decimalsToShow = this.item.hide_decimals ? 0 : 1;
79 const status = await this.fetch(`/api2/json/nodes/${this.item.node}/status`, options); 129 this.memoryUsed = (
80 // main metrics: 130 (status.data.memory.used * 100) /
81 const decimalsToShow = this.item.hide_decimals ? 0 : 1; 131 status.data.memory.total
82 this.memoryUsed = ( (status.data.memory.used * 100) / status.data.memory.total ).toFixed(decimalsToShow); 132 ).toFixed(decimalsToShow);
83 this.diskUsed = ( (status.data.rootfs.used * 100) / status.data.rootfs.total ).toFixed(decimalsToShow); 133 this.diskUsed = (
84 this.cpuUsed = (status.data.cpu * 100).toFixed(decimalsToShow); 134 (status.data.rootfs.used * 100) /
85 // vms: 135 status.data.rootfs.total
86 if (this.isValueShown('vms')) { 136 ).toFixed(decimalsToShow);
87 const vms = await this.fetch(`/api2/json/nodes/${this.item.node}/qemu`, options); 137 this.cpuUsed = (status.data.cpu * 100).toFixed(decimalsToShow);
88 this.parseVMsAndLXCs(vms, this.vms); 138 // vms:
89 } 139 if (this.isValueShown("vms")) {
90 // lxc containers: 140 const vms = await this.fetch(
91 if (this.isValueShown('lxcs')) { 141 `/api2/json/nodes/${this.item.node}/qemu`,
92 const lxcs = await this.fetch(`/api2/json/nodes/${this.item.node}/lxc`, options); 142 options
93 this.parseVMsAndLXCs(lxcs, this.lxcs); 143 );
94 } 144 this.parseVMsAndLXCs(vms, this.vms);
95 this.error = false;
96 } catch(err) {
97 console.log(err);
98 this.error = true;
99 } 145 }
100 this.loading = false; 146 // lxc containers:
101 }, 147 if (this.isValueShown("lxcs")) {
102 parseVMsAndLXCs(items, value) { 148 const lxcs = await this.fetch(
103 value.total += items.data.length; 149 `/api2/json/nodes/${this.item.node}/lxc`,
104 value.running += items.data.filter( i => i.status === 'running' ).length; 150 options
105 // if no vms, hide this value: 151 );
106 if (value.total == 0) this.hide.push('lxcs'); 152 this.parseVMsAndLXCs(lxcs, this.lxcs);
107 }, 153 }
108 isValueShown(value) { 154 this.error = false;
109 return this.hide.indexOf(value) == -1; 155 } catch (err) {
156 console.log(err);
157 this.error = true;
110 } 158 }
159 this.loading = false;
160 },
161 parseVMsAndLXCs(items, value) {
162 value.total += items.data.length;
163 value.running += items.data.filter((i) => i.status === "running").length;
164 // if no vms, hide this value:
165 if (value.total == 0) this.hide.push("lxcs");
166 },
167 isValueShown(value) {
168 return this.hide.indexOf(value) == -1;
111 }, 169 },
112 }; 170 },
113 </script> 171};
114 172</script>
115 <style scoped lang="scss"> 173
116 .is-number { 174<style scoped lang="scss">
117 font-family: "Lato" 175.is-number {
118 } 176 font-family: "Lato";
119 .healthy { 177}
120 color: green 178.healthy {
121 } 179 color: green;
122 .warning { 180}
123 color: orange 181.warning {
124 } 182 color: orange;
125 .danger { 183}
126 color: red 184.danger {
127 } 185 color: red;
128 .metrics .margined:not(:first-child) { 186}
129 margin-left: 0.3rem; 187.metrics .margined:not(:first-child) {
130 } 188 margin-left: 0.3rem;
131 .is-small { 189}
132 font-size: small; 190.is-small {
133 } 191 font-size: small;
134 </style> 192}
135 \ No newline at end of file 193</style>