aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/customservices.md18
-rw-r--r--src/components/services/Proxmox.vue101
2 files changed, 119 insertions, 0 deletions
diff --git a/docs/customservices.md b/docs/customservices.md
index df97cc9..67baed0 100644
--- a/docs/customservices.md
+++ b/docs/customservices.md
@@ -21,6 +21,7 @@ within Homer:
21+ [Tautulli](#tautulli) 21+ [Tautulli](#tautulli)
22+ [Mealie](#mealie) 22+ [Mealie](#mealie)
23+ [Healthchecks](#healthchecks) 23+ [Healthchecks](#healthchecks)
24+ [Proxmox](#proxmox)
24 25
25If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. 26If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page.
26 27
@@ -244,3 +245,20 @@ Two lines are needed in the config.yml :
244 245
245The url must be the root url of the Healthchecks application. 246The url must be the root url of the Healthchecks application.
246The Healthchecks API key can be found in Settings > API Access > API key (read-only). The key is needed to access Healthchecks API. 247The Healthchecks API key can be found in Settings > API Access > API key (read-only). The key is needed to access Healthchecks API.
248
249## Proxmox
250
251This service displays status information of a Proxmox node (VMs running and disk, memory and cpu used). It uses the proxmox API and [API Tokens](https://pve.proxmox.com/pve-docs/pveum-plain.html) for authorization so you need to generate one to set in the yaml config. You can set it up in Proxmox under Permissions > API Tokens. You also need to know the realm the user of the API Token is assigned to (by default pam).
252
253Configuration example:
254
255```yaml
256- name: "Proxmox - Node"
257 logo: "https://www.google.com/url?sa=i&url=https%3A%2F%2Fgithub.com%2FandOTP%2FandOTP%2Fissues%2F337&psig=AOvVaw2YKVuEUIBeTUikr7kAjm8D&ust=1665323538747000&source=images&cd=vfe&ved=0CAkQjRxqFwoTCPCTruLj0PoCFQAAAAAdAAAAABAN"
258 type: "Proxmox"
259 url: "https://your.proxmox.server"
260 node: "your-node-name"
261 warning_value: 50
262 danger_value: 80
263 api_token: "PVEAPIToken=root@pam!your-api-token-name=your-api-token-key"
264``` \ No newline at end of file
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