open-nomad/ui/app/models/allocation.js

129 lines
4.0 KiB
JavaScript
Raw Normal View History

import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import { equal, none } from '@ember/object/computed';
2017-09-19 14:47:10 +00:00
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
2019-04-16 19:11:43 +00:00
import { belongsTo, hasMany } from 'ember-data/relationships';
2017-09-19 14:47:10 +00:00
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import intersection from 'lodash.intersection';
2017-09-19 14:47:10 +00:00
import shortUUIDProperty from '../utils/properties/short-uuid';
const STATUS_ORDER = {
pending: 1,
running: 2,
complete: 3,
failed: 4,
lost: 5,
};
2017-09-19 14:47:10 +00:00
export default Model.extend({
token: service(),
2017-09-19 14:47:10 +00:00
shortId: shortUUIDProperty('id'),
job: belongsTo('job'),
node: belongsTo('node'),
name: attr('string'),
taskGroupName: attr('string'),
resources: fragment('resources'),
allocatedResources: fragment('resources'),
2018-07-19 20:31:39 +00:00
jobVersion: attr('number'),
2017-09-19 14:47:10 +00:00
modifyIndex: attr('number'),
2017-11-30 23:08:31 +00:00
modifyTime: attr('date'),
2018-07-19 20:31:39 +00:00
createIndex: attr('number'),
createTime: attr('date'),
2017-09-19 14:47:10 +00:00
clientStatus: attr('string'),
desiredStatus: attr('string'),
statusIndex: computed('clientStatus', function() {
2019-03-26 07:46:44 +00:00
return STATUS_ORDER[this.clientStatus] || 100;
}),
2017-09-19 14:47:10 +00:00
isRunning: equal('clientStatus', 'running'),
isMigrating: attr('boolean'),
// An allocation model created from any allocation list response will be lacking
// many properties (some of which can always be null). This is an indicator that
// the allocation needs to be reloaded to get the complete allocation state.
isPartial: none('allocationTaskGroup'),
2018-04-25 22:50:15 +00:00
// When allocations are server-side rescheduled, a paper trail
// is left linking all reschedule attempts.
previousAllocation: belongsTo('allocation', { inverse: 'nextAllocation' }),
nextAllocation: belongsTo('allocation', { inverse: 'previousAllocation' }),
2019-04-16 19:11:43 +00:00
preemptedAllocations: hasMany('allocation', { inverse: 'preemptedByAllocation' }),
preemptedByAllocation: belongsTo('allocation', { inverse: 'preemptedAllocations' }),
2019-04-16 20:23:16 +00:00
wasPreempted: attr('boolean'),
2019-04-16 19:11:43 +00:00
followUpEvaluation: belongsTo('evaluation'),
2018-04-25 22:50:15 +00:00
statusClass: computed('clientStatus', function() {
const classMap = {
pending: 'is-pending',
running: 'is-primary',
complete: 'is-complete',
failed: 'is-error',
lost: 'is-light',
};
2019-03-26 07:46:44 +00:00
return classMap[this.clientStatus] || 'is-dark';
}),
isOld: computed('jobVersion', 'job.version', function() {
return this.jobVersion !== this.get('job.version');
}),
taskGroup: computed('isOld', 'jobTaskGroup', 'allocationTaskGroup', function() {
if (!this.isOld) return this.jobTaskGroup;
return this.allocationTaskGroup;
}),
jobTaskGroup: computed('taskGroupName', 'job.taskGroups.[]', function() {
2017-09-19 14:47:10 +00:00
const taskGroups = this.get('job.taskGroups');
2019-03-26 07:46:44 +00:00
return taskGroups && taskGroups.findBy('name', this.taskGroupName);
2017-09-19 14:47:10 +00:00
}),
allocationTaskGroup: fragment('task-group', { defaultValue: null }),
unhealthyDrivers: computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]', function() {
const taskGroupUnhealthyDrivers = this.get('taskGroup.drivers');
const nodeUnhealthyDrivers = this.get('node.unhealthyDriverNames');
if (taskGroupUnhealthyDrivers && nodeUnhealthyDrivers) {
return intersection(taskGroupUnhealthyDrivers, nodeUnhealthyDrivers);
}
return [];
}),
2017-09-19 14:47:10 +00:00
states: fragmentArray('task-state'),
2018-04-25 22:50:15 +00:00
rescheduleEvents: fragmentArray('reschedule-event'),
hasRescheduleEvents: computed('rescheduleEvents.length', 'nextAllocation', function() {
2019-03-26 07:46:44 +00:00
return this.get('rescheduleEvents.length') > 0 || this.nextAllocation;
}),
2018-05-03 19:17:06 +00:00
hasStoppedRescheduling: computed(
'nextAllocation',
'clientStatus',
2019-03-25 22:54:48 +00:00
'followUpEvaluation.content',
2018-05-03 19:17:06 +00:00
function() {
2019-04-16 19:11:43 +00:00
return (
!this.get('nextAllocation.content') &&
!this.get('followUpEvaluation.content') &&
this.clientStatus === 'failed'
);
2018-05-03 19:17:06 +00:00
}
),
stop() {
return this.store.adapterFor('allocation').stop(this);
},
restart(taskName) {
return this.store.adapterFor('allocation').restart(this, taskName);
},
2017-09-19 14:47:10 +00:00
});