]>
Commit | Line | Data |
---|---|---|
10f4cca6 | 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"> | |
13069da1 | 10 | <div v-if="loading"> |
11 | <strong>Loading...</strong> | |
12 | </div> | |
13 | <div v-else-if="error"> | |
14 | <strong class="danger">Error loading info</strong> | |
10f4cca6 | 15 | </div> |
16 | <div v-else class="metrics"> | |
e2748076 | 17 | <span>VMs: <span class="is-number"><strong>{{ vms.running }}</strong>/{{vms.total}}</span></span> |
10f4cca6 | 18 | <span>Disk: <strong class="is-number" :class="statusClass(diskUsed)">{{ diskUsed }}%</strong></span> |
19 | <span>Mem: <strong class="is-number" :class="statusClass(memoryUsed)">{{ memoryUsed }}%</strong></span> | |
20 | <span>CPU: <strong class="is-number" :class="statusClass(cpuUsed)">{{ cpuUsed }}%</strong></span> | |
21 | </div> | |
22 | </template> | |
23 | </p> | |
24 | </template> | |
13069da1 | 25 | <template #indicator> |
26 | <i v-if="loading" class="fa fa-circle-notch fa-spin fa-2xl"></i> | |
27 | <i v-if="error" class="fa fa-exclamation-circle fa-2xl danger"></i> | |
28 | </template> | |
10f4cca6 | 29 | </Generic> |
30 | </template> | |
31 | ||
32 | <script> | |
33 | import service from "@/mixins/service.js"; | |
34 | import Generic from "./Generic.vue"; | |
35 | ||
36 | export default { | |
37 | name: "Proxmox", | |
38 | mixins: [service], | |
39 | props: { | |
40 | item: Object, | |
41 | }, | |
42 | components: { | |
43 | Generic, | |
44 | }, | |
45 | data: () => ({ | |
46 | vms: { | |
47 | total: 0, | |
48 | running: 0 | |
49 | }, | |
50 | memoryUsed: 0, | |
51 | diskUsed: 0, | |
52 | cpuUsed: 0, | |
13069da1 | 53 | error: false, |
54 | loading: true | |
10f4cca6 | 55 | }), |
56 | created() { | |
57 | this.fetchStatus(); | |
58 | }, | |
59 | methods: { | |
60 | statusClass(value) { | |
61 | if (value > this.item.danger_value) return 'danger'; | |
62 | if (value > this.item.warning_value) return 'warning'; | |
63 | return 'healthy' | |
64 | }, | |
65 | fetchStatus: async function () { | |
66 | try { | |
67 | const options = { | |
68 | headers: { | |
69 | "Authorization": this.item.api_token | |
70 | } | |
71 | } | |
72 | const status = await this.fetch(`/api2/json/nodes/${this.item.node}/status`, options); | |
73 | // main metrics: | |
74 | this.memoryUsed = ( (status.data.memory.used * 100) / status.data.memory.total ).toFixed(1); | |
75 | this.diskUsed = ( (status.data.rootfs.used * 100) / status.data.rootfs.total ).toFixed(1); | |
76 | this.cpuUsed = (status.data.cpu * 100).toFixed(1); | |
77 | // vms: | |
78 | const vms = await this.fetch(`/api2/json/nodes/${this.item.node}/qemu`, options); | |
79 | this.vms.total += vms.data.length; | |
80 | this.vms.running += vms.data.filter( i => i.status === 'running' ).length; | |
81 | this.error = false; | |
82 | } catch(err) { | |
83 | console.log(err); | |
84 | this.error = true; | |
85 | } | |
4fe179c5 | 86 | this.loading = false; |
10f4cca6 | 87 | }, |
88 | }, | |
89 | }; | |
90 | </script> | |
91 | ||
92 | <style scoped lang="scss"> | |
93 | .is-number { | |
94 | font-family: "Lato" | |
95 | } | |
96 | .healthy { | |
97 | color: green | |
98 | } | |
99 | .warning { | |
100 | color: orange | |
101 | } | |
102 | .danger { | |
103 | color: red | |
104 | } | |
105 | .metrics { | |
106 | display: flex; | |
107 | justify-content: space-between; | |
108 | } | |
109 | </style> | |
110 |