aboutsummaryrefslogblamecommitdiffhomepage
path: root/src/components/services/Proxmox.vue
blob: 2b533db673e1b0ed5d2527a2d3cad9814f40e0c1 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                 




                                                                
                  





                                                                                                                                                                                                                                       



                     



                                                                           




















                                            



                  


                    
               

                   

               
                                                     
















                                                                                                



                                                                                                                   
                 








                                                                                             




                             
                             
        








                                                                                 
















                            




                                        


          
<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>