aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/services/Proxmox.vue
blob: 1d2c2c93ef61515cde6bb7acc80c993fa9043739 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<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="loading">
              <strong>Loading...</strong>
            </div>
            <div v-else-if="error">
              <strong class="danger">Error loading info</strong>
            </div>
            <div v-else class="metrics">
              <span>VMs: <span class="is-number"><strong>{{ vms.running }}</strong>/{{vms.total}}</span></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>
      <template #indicator>
        <i v-if="loading" class="fa fa-circle-notch fa-spin fa-2xl"></i>
        <i v-if="error" class="fa fa-exclamation-circle fa-2xl danger"></i>
      </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,
      loading: true
    }),
    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;
        }
        this.loading = false;
      },
    },
  };
  </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>