]> git.immae.eu Git - github/bastienwirtz/homer.git/commitdiff
Adds custom service for Proxmox
authorluixal <luixal@gmail.com>
Sat, 8 Oct 2022 13:54:37 +0000 (15:54 +0200)
committerBastien Wirtz <bastien.wirtz@gmail.com>
Sun, 9 Oct 2022 08:23:32 +0000 (10:23 +0200)
docs/customservices.md
src/components/services/Proxmox.vue [new file with mode: 0644]

index df97cc9dcd686c5a4541ad9d3fb7db4352328c1a..67baed0402e85c8b9bbc9a1db9e8656a69bc64f7 100644 (file)
@@ -21,6 +21,7 @@ within Homer:
 + [Tautulli](#tautulli)
 + [Mealie](#mealie)
 + [Healthchecks](#healthchecks)
++ [Proxmox](#proxmox)
 
 If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page.
 
@@ -244,3 +245,20 @@ Two lines are needed in the config.yml :
 
 The url must be the root url of the Healthchecks application.
 The Healthchecks API key can be found in Settings > API Access > API key (read-only). The key is needed to access Healthchecks API.
+
+## Proxmox
+
+This 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).
+
+Configuration example:
+
+```yaml
+- name: "Proxmox - Node"
+  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"
+  type: "Proxmox"
+  url: "https://your.proxmox.server"
+  node: "your-node-name"
+  warning_value: 50
+  danger_value: 80
+  api_token: "PVEAPIToken=root@pam!your-api-token-name=your-api-token-key"
+```
\ No newline at end of file
diff --git a/src/components/services/Proxmox.vue b/src/components/services/Proxmox.vue
new file mode 100644 (file)
index 0000000..38d09d3
--- /dev/null
@@ -0,0 +1,101 @@
+<template>
+    <Generic :item="item">
+      <template #content>
+        <p class="title is-4">{{ item.name }}</p>
+        <p class="subtitle is-6">
+          <template v-if="item.subtitle">
+            {{ item.subtitle }}
+          </template>
+          <template v-else-if="vms">
+            <div v-if="error">
+              <strong class="danger">Error loading info!</strong>
+            </div>
+            <div v-else class="metrics">
+              <span>VMs: <strong class="is-number">{{ vms.running }}</strong></span>
+              <span>Disk: <strong class="is-number" :class="statusClass(diskUsed)">{{ diskUsed }}%</strong></span>
+              <span>Mem: <strong class="is-number" :class="statusClass(memoryUsed)">{{ memoryUsed }}%</strong></span>
+              <span>CPU: <strong class="is-number" :class="statusClass(cpuUsed)">{{ cpuUsed }}%</strong></span>
+            </div>
+          </template>
+        </p>
+      </template>
+    </Generic>
+  </template>
+  
+  <script>
+  import service from "@/mixins/service.js";
+  import Generic from "./Generic.vue";
+  
+  export default {
+    name: "Proxmox",
+    mixins: [service],
+    props: {
+      item: Object,
+    },
+    components: {
+      Generic,
+    },
+    data: () => ({
+      vms: {
+        total: 0,
+        running: 0
+      },
+      memoryUsed: 0,
+      diskUsed: 0,
+      cpuUsed: 0,
+      error: false
+    }),
+    created() {
+      this.fetchStatus();
+    },
+    methods: {
+      statusClass(value) {
+        if (value > this.item.danger_value) return 'danger';
+        if (value > this.item.warning_value) return 'warning';
+        return 'healthy'
+      },
+      fetchStatus: async function () {
+        try {
+          const options = {
+            headers: {
+              "Authorization": this.item.api_token
+            }
+          }
+          const status = await this.fetch(`/api2/json/nodes/${this.item.node}/status`, options);
+          // main metrics:
+          this.memoryUsed = ( (status.data.memory.used * 100) / status.data.memory.total ).toFixed(1);
+          this.diskUsed = ( (status.data.rootfs.used * 100) / status.data.rootfs.total ).toFixed(1);
+          this.cpuUsed = (status.data.cpu * 100).toFixed(1);
+          // vms:
+          const vms = await this.fetch(`/api2/json/nodes/${this.item.node}/qemu`, options);
+          this.vms.total += vms.data.length;
+          this.vms.running += vms.data.filter( i => i.status === 'running' ).length;
+          this.error = false;
+        } catch(err) {
+          console.log(err);
+          this.error = true;
+        }
+      },
+    },
+  };
+  </script>
+  
+  <style scoped lang="scss">
+  .is-number {
+    font-family: "Lato"
+  }
+  .healthy {
+    color: green
+  }
+  .warning {
+    color: orange
+  }
+  .danger {
+    color: red
+  }
+  .metrics {
+    display: flex;
+    justify-content: space-between;
+  }
+  </style>
+  
\ No newline at end of file