github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/models/allocation.js (about) 1 import { inject as service } from '@ember/service'; 2 import { computed } from '@ember/object'; 3 import { equal, none } from '@ember/object/computed'; 4 import Model from '@ember-data/model'; 5 import { attr, belongsTo, hasMany } from '@ember-data/model'; 6 import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes'; 7 import intersection from 'lodash.intersection'; 8 import shortUUIDProperty from '../utils/properties/short-uuid'; 9 import classic from 'ember-classic-decorator'; 10 11 const STATUS_ORDER = { 12 pending: 1, 13 running: 2, 14 complete: 3, 15 failed: 4, 16 lost: 5, 17 }; 18 19 @classic 20 export default class Allocation extends Model { 21 @service token; 22 23 @shortUUIDProperty('id') shortId; 24 @belongsTo('job') job; 25 @belongsTo('node') node; 26 @attr('string') name; 27 @attr('string') taskGroupName; 28 @fragment('resources') resources; 29 @fragment('resources') allocatedResources; 30 @attr('number') jobVersion; 31 32 @attr('number') modifyIndex; 33 @attr('date') modifyTime; 34 35 @attr('number') createIndex; 36 @attr('date') createTime; 37 38 @attr('string') clientStatus; 39 @attr('string') desiredStatus; 40 41 @computed('clientStatus') 42 get statusIndex() { 43 return STATUS_ORDER[this.clientStatus] || 100; 44 } 45 46 @equal('clientStatus', 'running') isRunning; 47 @attr('boolean') isMigrating; 48 49 @computed('clientStatus') 50 get isScheduled() { 51 return ['pending', 'running'].includes(this.clientStatus); 52 } 53 54 // An allocation model created from any allocation list response will be lacking 55 // many properties (some of which can always be null). This is an indicator that 56 // the allocation needs to be reloaded to get the complete allocation state. 57 @none('allocationTaskGroup') isPartial; 58 59 // When allocations are server-side rescheduled, a paper trail 60 // is left linking all reschedule attempts. 61 @belongsTo('allocation', { inverse: 'nextAllocation' }) previousAllocation; 62 @belongsTo('allocation', { inverse: 'previousAllocation' }) nextAllocation; 63 64 @hasMany('allocation', { inverse: 'preemptedByAllocation' }) preemptedAllocations; 65 @belongsTo('allocation', { inverse: 'preemptedAllocations' }) preemptedByAllocation; 66 @attr('boolean') wasPreempted; 67 68 @belongsTo('evaluation') followUpEvaluation; 69 70 @computed('clientStatus') 71 get statusClass() { 72 const classMap = { 73 pending: 'is-pending', 74 running: 'is-primary', 75 complete: 'is-complete', 76 failed: 'is-error', 77 lost: 'is-light', 78 }; 79 80 return classMap[this.clientStatus] || 'is-dark'; 81 } 82 83 @computed('jobVersion', 'job.version') 84 get isOld() { 85 return this.jobVersion !== this.get('job.version'); 86 } 87 88 @computed('isOld', 'jobTaskGroup', 'allocationTaskGroup') 89 get taskGroup() { 90 if (!this.isOld) return this.jobTaskGroup; 91 return this.allocationTaskGroup; 92 } 93 94 @computed('taskGroupName', 'job.taskGroups.[]') 95 get jobTaskGroup() { 96 const taskGroups = this.get('job.taskGroups'); 97 return taskGroups && taskGroups.findBy('name', this.taskGroupName); 98 } 99 100 @fragment('task-group', { defaultValue: null }) allocationTaskGroup; 101 102 @computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]') 103 get unhealthyDrivers() { 104 const taskGroupUnhealthyDrivers = this.get('taskGroup.drivers'); 105 const nodeUnhealthyDrivers = this.get('node.unhealthyDriverNames'); 106 107 if (taskGroupUnhealthyDrivers && nodeUnhealthyDrivers) { 108 return intersection(taskGroupUnhealthyDrivers, nodeUnhealthyDrivers); 109 } 110 111 return []; 112 } 113 114 @fragmentArray('task-state') states; 115 @fragmentArray('reschedule-event') rescheduleEvents; 116 117 @computed('rescheduleEvents.length', 'nextAllocation') 118 get hasRescheduleEvents() { 119 return this.get('rescheduleEvents.length') > 0 || this.nextAllocation; 120 } 121 122 @computed('clientStatus', 'followUpEvaluation.content', 'nextAllocation.content') 123 get hasStoppedRescheduling() { 124 return ( 125 !this.get('nextAllocation.content') && 126 !this.get('followUpEvaluation.content') && 127 this.clientStatus === 'failed' 128 ); 129 } 130 131 stop() { 132 return this.store.adapterFor('allocation').stop(this); 133 } 134 135 restart(taskName) { 136 return this.store.adapterFor('allocation').restart(this, taskName); 137 } 138 139 ls(path) { 140 return this.store.adapterFor('allocation').ls(this, path); 141 } 142 143 stat(path) { 144 return this.store.adapterFor('allocation').stat(this, path); 145 } 146 }