github.com/thomasobenaus/nomad@v0.11.1/ui/app/models/allocation.js (about) 1 import { inject as service } from '@ember/service'; 2 import { computed } from '@ember/object'; 3 import { equal } from '@ember/object/computed'; 4 import Model from 'ember-data/model'; 5 import attr from 'ember-data/attr'; 6 import { belongsTo, hasMany } from 'ember-data/relationships'; 7 import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes'; 8 import intersection from 'lodash.intersection'; 9 import shortUUIDProperty from '../utils/properties/short-uuid'; 10 11 const STATUS_ORDER = { 12 pending: 1, 13 running: 2, 14 complete: 3, 15 failed: 4, 16 lost: 5, 17 }; 18 19 export default Model.extend({ 20 token: service(), 21 22 shortId: shortUUIDProperty('id'), 23 job: belongsTo('job'), 24 node: belongsTo('node'), 25 name: attr('string'), 26 taskGroupName: attr('string'), 27 resources: fragment('resources'), 28 allocatedResources: fragment('resources'), 29 jobVersion: attr('number'), 30 31 modifyIndex: attr('number'), 32 modifyTime: attr('date'), 33 34 createIndex: attr('number'), 35 createTime: attr('date'), 36 37 clientStatus: attr('string'), 38 desiredStatus: attr('string'), 39 statusIndex: computed('clientStatus', function() { 40 return STATUS_ORDER[this.clientStatus] || 100; 41 }), 42 43 isRunning: equal('clientStatus', 'running'), 44 isMigrating: attr('boolean'), 45 46 // When allocations are server-side rescheduled, a paper trail 47 // is left linking all reschedule attempts. 48 previousAllocation: belongsTo('allocation', { inverse: 'nextAllocation' }), 49 nextAllocation: belongsTo('allocation', { inverse: 'previousAllocation' }), 50 51 preemptedAllocations: hasMany('allocation', { inverse: 'preemptedByAllocation' }), 52 preemptedByAllocation: belongsTo('allocation', { inverse: 'preemptedAllocations' }), 53 wasPreempted: attr('boolean'), 54 55 followUpEvaluation: belongsTo('evaluation'), 56 57 statusClass: computed('clientStatus', function() { 58 const classMap = { 59 pending: 'is-pending', 60 running: 'is-primary', 61 complete: 'is-complete', 62 failed: 'is-error', 63 lost: 'is-light', 64 }; 65 66 return classMap[this.clientStatus] || 'is-dark'; 67 }), 68 69 taskGroup: computed('taskGroupName', 'job.taskGroups.[]', function() { 70 const taskGroups = this.get('job.taskGroups'); 71 return taskGroups && taskGroups.findBy('name', this.taskGroupName); 72 }), 73 74 unhealthyDrivers: computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]', function() { 75 const taskGroupUnhealthyDrivers = this.get('taskGroup.drivers'); 76 const nodeUnhealthyDrivers = this.get('node.unhealthyDriverNames'); 77 78 if (taskGroupUnhealthyDrivers && nodeUnhealthyDrivers) { 79 return intersection(taskGroupUnhealthyDrivers, nodeUnhealthyDrivers); 80 } 81 82 return []; 83 }), 84 85 states: fragmentArray('task-state'), 86 rescheduleEvents: fragmentArray('reschedule-event'), 87 88 hasRescheduleEvents: computed('rescheduleEvents.length', 'nextAllocation', function() { 89 return this.get('rescheduleEvents.length') > 0 || this.nextAllocation; 90 }), 91 92 hasStoppedRescheduling: computed( 93 'nextAllocation', 94 'clientStatus', 95 'followUpEvaluation.content', 96 function() { 97 return ( 98 !this.get('nextAllocation.content') && 99 !this.get('followUpEvaluation.content') && 100 this.clientStatus === 'failed' 101 ); 102 } 103 ), 104 105 stop() { 106 return this.store.adapterFor('allocation').stop(this); 107 }, 108 109 restart(taskName) { 110 return this.store.adapterFor('allocation').restart(this, taskName); 111 }, 112 });