github.com/thomasobenaus/nomad@v0.11.1/ui/app/models/node.js (about)

     1  import { computed } from '@ember/object';
     2  import { equal } from '@ember/object/computed';
     3  import Model from 'ember-data/model';
     4  import attr from 'ember-data/attr';
     5  import { hasMany } from 'ember-data/relationships';
     6  import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
     7  import RSVP from 'rsvp';
     8  import shortUUIDProperty from '../utils/properties/short-uuid';
     9  import ipParts from '../utils/ip-parts';
    10  
    11  export default Model.extend({
    12    // Available from list response
    13    name: attr('string'),
    14    datacenter: attr('string'),
    15    nodeClass: attr('string'),
    16    isDraining: attr('boolean'),
    17    schedulingEligibility: attr('string'),
    18    status: attr('string'),
    19    statusDescription: attr('string'),
    20    shortId: shortUUIDProperty('id'),
    21    modifyIndex: attr('number'),
    22  
    23    // Available from single response
    24    httpAddr: attr('string'),
    25    tlsEnabled: attr('boolean'),
    26    attributes: fragment('node-attributes'),
    27    meta: fragment('node-attributes'),
    28    resources: fragment('resources'),
    29    reserved: fragment('resources'),
    30    drainStrategy: fragment('drain-strategy'),
    31  
    32    isEligible: equal('schedulingEligibility', 'eligible'),
    33  
    34    address: computed('httpAddr', function() {
    35      return ipParts(this.httpAddr).address;
    36    }),
    37  
    38    port: computed('httpAddr', function() {
    39      return ipParts(this.httpAddr).port;
    40    }),
    41  
    42    isPartial: computed('httpAddr', function() {
    43      return this.httpAddr == null;
    44    }),
    45  
    46    allocations: hasMany('allocations', { inverse: 'node' }),
    47    completeAllocations: computed('allocations.@each.clientStatus', function() {
    48      return this.allocations.filterBy('clientStatus', 'complete');
    49    }),
    50    runningAllocations: computed('allocations.@each.isRunning', function() {
    51      return this.allocations.filterBy('isRunning');
    52    }),
    53    migratingAllocations: computed('allocations.@each.{isMigrating,isRunning}', function() {
    54      return this.allocations.filter(alloc => alloc.isRunning && alloc.isMigrating);
    55    }),
    56    lastMigrateTime: computed('allocations.@each.{isMigrating,isRunning,modifyTime}', function() {
    57      const allocation = this.allocations
    58        .filterBy('isRunning', false)
    59        .filterBy('isMigrating')
    60        .sortBy('modifyTime')
    61        .reverse()[0];
    62      if (allocation) {
    63        return allocation.modifyTime;
    64      }
    65    }),
    66  
    67    drivers: fragmentArray('node-driver'),
    68    events: fragmentArray('node-event'),
    69    hostVolumes: fragmentArray('host-volume'),
    70  
    71    detectedDrivers: computed('drivers.@each.detected', function() {
    72      return this.drivers.filterBy('detected');
    73    }),
    74  
    75    unhealthyDrivers: computed('detectedDrivers.@each.healthy', function() {
    76      return this.detectedDrivers.filterBy('healthy', false);
    77    }),
    78  
    79    unhealthyDriverNames: computed('unhealthyDrivers.@each.name', function() {
    80      return this.unhealthyDrivers.mapBy('name');
    81    }),
    82  
    83    // A status attribute that includes states not included in node status.
    84    // Useful for coloring and sorting nodes
    85    compositeStatus: computed('isDraining', 'isEligible', 'status', function() {
    86      if (this.isDraining) {
    87        return 'draining';
    88      } else if (!this.isEligible) {
    89        return 'ineligible';
    90      } else {
    91        return this.status;
    92      }
    93    }),
    94  
    95    compositeStatusIcon: computed('isDraining', 'isEligible', 'status', function() {
    96      if (this.isDraining || !this.isEligible) {
    97        return 'alert-circle-fill';
    98      } else if (this.status === 'down') {
    99        return 'cancel-circle-fill';
   100      } else if (this.status === 'initializing') {
   101        return 'node-init-circle-fill';
   102      }
   103      return 'check-circle-fill';
   104    }),
   105  
   106    setEligible() {
   107      if (this.isEligible) return RSVP.resolve();
   108      // Optimistically update schedulingEligibility for immediate feedback
   109      this.set('schedulingEligibility', 'eligible');
   110      return this.store.adapterFor('node').setEligible(this);
   111    },
   112  
   113    setIneligible() {
   114      if (!this.isEligible) return RSVP.resolve();
   115      // Optimistically update schedulingEligibility for immediate feedback
   116      this.set('schedulingEligibility', 'ineligible');
   117      return this.store.adapterFor('node').setIneligible(this);
   118    },
   119  
   120    drain(drainSpec) {
   121      return this.store.adapterFor('node').drain(this, drainSpec);
   122    },
   123  
   124    forceDrain(drainSpec) {
   125      return this.store.adapterFor('node').forceDrain(this, drainSpec);
   126    },
   127  
   128    cancelDrain() {
   129      return this.store.adapterFor('node').cancelDrain(this);
   130    },
   131  });