mirror of https://github.com/bastienwirtz/homer
Adds custom service for Proxmox
parent
fdf6d4284d
commit
10f4cca67a
|
@ -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"
|
||||
```
|
|
@ -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>
|
||||
|
Loading…
Reference in New Issue