+ [Tautulli](#tautulli)
+ [Mealie](#mealie)
+ [Healthchecks](#healthchecks)
++ [Proxmox](#proxmox)
If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page.
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
--- /dev/null
+<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