aboutsummaryrefslogblamecommitdiffhomepage
path: root/src/components/services/Proxmox.vue
blob: 813605038dbb6425858d0e857f961d2507491f50 (plain) (tree)
1
          



























































































                                                                            
      


                 
      















                                                            
      




























                                                                       
         











                                                     
       









                                                                               
      























                                      
<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"
            :class="{
              'is-size-7-mobile': item.small_font_on_small_screens,
              'is-small': item.small_font_on_desktop,
            }"
          >
            <span v-if="isValueShown('vms')" class="margined"
              >VMs:
              <span class="is-number"
                ><span class="has-text-weight-bold">{{ vms.running }}</span
                ><span v-if="isValueShown('vms_total')"
                  >/{{ vms.total }}</span
                ></span
              ></span
            >
            <span v-if="isValueShown('lxcs')" class="margined"
              >LXCs:
              <span class="is-number"
                ><span class="has-text-weight-bold">{{ lxcs.running }}</span
                ><span v-if="isValueShown('lxcs_total')"
                  >/{{ lxcs.total }}</span
                ></span
              ></span
            >
            <span v-if="isValueShown('disk')" class="margined"
              >Disk:
              <span
                class="has-text-weight-bold is-number"
                :class="statusClass(diskUsed)"
                >{{ diskUsed }}%</span
              ></span
            >
            <span v-if="isValueShown('mem')" class="margined"
              >Mem:
              <span
                class="has-text-weight-bold is-number"
                :class="statusClass(memoryUsed)"
                >{{ memoryUsed }}%</span
              ></span
            >
            <span v-if="isValueShown('cpu')" class="margined"
              >CPU:
              <span
                class="has-text-weight-bold is-number"
                :class="statusClass(cpuUsed)"
                >{{ cpuUsed }}%</span
              ></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,
    },
    lxcs: {
      total: 0,
      running: 0,
    },
    memoryUsed: 0,
    diskUsed: 0,
    cpuUsed: 0,
    hide: [],
    error: false,
    loading: true,
  }),
  created() {
    if (this.item.hide) this.hide = this.item.hide;
    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:
        const decimalsToShow = this.item.hide_decimals ? 0 : 1;
        this.memoryUsed = (
          (status.data.memory.used * 100) /
          status.data.memory.total
        ).toFixed(decimalsToShow);
        this.diskUsed = (
          (status.data.rootfs.used * 100) /
          status.data.rootfs.total
        ).toFixed(decimalsToShow);
        this.cpuUsed = (status.data.cpu * 100).toFixed(decimalsToShow);
        // vms:
        if (this.isValueShown("vms")) {
          const vms = await this.fetch(
            `/api2/json/nodes/${this.item.node}/qemu`,
            options
          );
          this.parseVMsAndLXCs(vms, this.vms);
        }
        // lxc containers:
        if (this.isValueShown("lxcs")) {
          const lxcs = await this.fetch(
            `/api2/json/nodes/${this.item.node}/lxc`,
            options
          );
          this.parseVMsAndLXCs(lxcs, this.lxcs);
        }
        this.error = false;
      } catch (err) {
        console.log(err);
        this.error = true;
      }
      this.loading = false;
    },
    parseVMsAndLXCs(items, value) {
      value.total += items.data.length;
      value.running += items.data.filter((i) => i.status === "running").length;
      // if no vms, hide this value:
      if (value.total == 0) this.hide.push("lxcs");
    },
    isValueShown(value) {
      return this.hide.indexOf(value) == -1;
    },
  },
};
</script>

<style scoped lang="scss">
.is-number {
  font-family: "Lato";
}
.healthy {
  color: green;
}
.warning {
  color: orange;
}
.danger {
  color: red;
}
.metrics .margined:not(:first-child) {
  margin-left: 0.3rem;
}
.is-small {
  font-size: small;
}
</style>