github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/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 });