diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/services/Proxmox.vue | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/components/services/Proxmox.vue b/src/components/services/Proxmox.vue new file mode 100644 index 0000000..38d09d3 --- /dev/null +++ b/src/components/services/Proxmox.vue | |||
@@ -0,0 +1,101 @@ | |||
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="error"> | ||
11 | <strong class="danger">Error loading info!</strong> | ||
12 | </div> | ||
13 | <div v-else class="metrics"> | ||
14 | <span>VMs: <strong class="is-number">{{ vms.running }}</strong></span> | ||
15 | <span>Disk: <strong class="is-number" :class="statusClass(diskUsed)">{{ diskUsed }}%</strong></span> | ||
16 | <span>Mem: <strong class="is-number" :class="statusClass(memoryUsed)">{{ memoryUsed }}%</strong></span> | ||
17 | <span>CPU: <strong class="is-number" :class="statusClass(cpuUsed)">{{ cpuUsed }}%</strong></span> | ||
18 | </div> | ||
19 | </template> | ||
20 | </p> | ||
21 | </template> | ||
22 | </Generic> | ||
23 | </template> | ||
24 | |||
25 | <script> | ||
26 | import service from "@/mixins/service.js"; | ||
27 | import Generic from "./Generic.vue"; | ||
28 | |||
29 | export default { | ||
30 | name: "Proxmox", | ||
31 | mixins: [service], | ||
32 | props: { | ||
33 | item: Object, | ||
34 | }, | ||
35 | components: { | ||
36 | Generic, | ||
37 | }, | ||
38 | data: () => ({ | ||
39 | vms: { | ||
40 | total: 0, | ||
41 | running: 0 | ||
42 | }, | ||
43 | memoryUsed: 0, | ||
44 | diskUsed: 0, | ||
45 | cpuUsed: 0, | ||
46 | error: false | ||
47 | }), | ||
48 | created() { | ||
49 | this.fetchStatus(); | ||
50 | }, | ||
51 | methods: { | ||
52 | statusClass(value) { | ||
53 | if (value > this.item.danger_value) return 'danger'; | ||
54 | if (value > this.item.warning_value) return 'warning'; | ||
55 | return 'healthy' | ||
56 | }, | ||
57 | fetchStatus: async function () { | ||
58 | try { | ||
59 | const options = { | ||
60 | headers: { | ||
61 | "Authorization": this.item.api_token | ||
62 | } | ||
63 | } | ||
64 | const status = await this.fetch(`/api2/json/nodes/${this.item.node}/status`, options); | ||
65 | // main metrics: | ||
66 | this.memoryUsed = ( (status.data.memory.used * 100) / status.data.memory.total ).toFixed(1); | ||
67 | this.diskUsed = ( (status.data.rootfs.used * 100) / status.data.rootfs.total ).toFixed(1); | ||
68 | this.cpuUsed = (status.data.cpu * 100).toFixed(1); | ||
69 | // vms: | ||
70 | const vms = await this.fetch(`/api2/json/nodes/${this.item.node}/qemu`, options); | ||
71 | this.vms.total += vms.data.length; | ||
72 | this.vms.running += vms.data.filter( i => i.status === 'running' ).length; | ||
73 | this.error = false; | ||
74 | } catch(err) { | ||
75 | console.log(err); | ||
76 | this.error = true; | ||
77 | } | ||
78 | }, | ||
79 | }, | ||
80 | }; | ||
81 | </script> | ||
82 | |||
83 | <style scoped lang="scss"> | ||
84 | .is-number { | ||
85 | font-family: "Lato" | ||
86 | } | ||
87 | .healthy { | ||
88 | color: green | ||
89 | } | ||
90 | .warning { | ||
91 | color: orange | ||
92 | } | ||
93 | .danger { | ||
94 | color: red | ||
95 | } | ||
96 | .metrics { | ||
97 | display: flex; | ||
98 | justify-content: space-between; | ||
99 | } | ||
100 | </style> | ||
101 | \ No newline at end of file | ||