143 lines
4.1 KiB
JavaScript
143 lines
4.1 KiB
JavaScript
import { inject as service } from '@ember/service';
|
|
import { computed } from '@ember/object';
|
|
import { equal, none } from '@ember/object/computed';
|
|
import Model from 'ember-data/model';
|
|
import attr from 'ember-data/attr';
|
|
import { belongsTo, hasMany } from 'ember-data/relationships';
|
|
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
|
|
import intersection from 'lodash.intersection';
|
|
import shortUUIDProperty from '../utils/properties/short-uuid';
|
|
import classic from 'ember-classic-decorator';
|
|
|
|
const STATUS_ORDER = {
|
|
pending: 1,
|
|
running: 2,
|
|
complete: 3,
|
|
failed: 4,
|
|
lost: 5,
|
|
};
|
|
|
|
@classic
|
|
export default class Allocation extends Model {
|
|
@service token;
|
|
|
|
@shortUUIDProperty('id') shortId;
|
|
@belongsTo('job') job;
|
|
@belongsTo('node') node;
|
|
@attr('string') name;
|
|
@attr('string') taskGroupName;
|
|
@fragment('resources') resources;
|
|
@fragment('resources') allocatedResources;
|
|
@attr('number') jobVersion;
|
|
|
|
@attr('number') modifyIndex;
|
|
@attr('date') modifyTime;
|
|
|
|
@attr('number') createIndex;
|
|
@attr('date') createTime;
|
|
|
|
@attr('string') clientStatus;
|
|
@attr('string') desiredStatus;
|
|
|
|
@computed('clientStatus')
|
|
get statusIndex() {
|
|
return STATUS_ORDER[this.clientStatus] || 100;
|
|
}
|
|
|
|
@equal('clientStatus', 'running') isRunning;
|
|
@attr('boolean') isMigrating;
|
|
|
|
// 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.
|
|
@none('allocationTaskGroup') isPartial;
|
|
|
|
// When allocations are server-side rescheduled, a paper trail
|
|
// is left linking all reschedule attempts.
|
|
@belongsTo('allocation', { inverse: 'nextAllocation' }) previousAllocation;
|
|
@belongsTo('allocation', { inverse: 'previousAllocation' }) nextAllocation;
|
|
|
|
@hasMany('allocation', { inverse: 'preemptedByAllocation' }) preemptedAllocations;
|
|
@belongsTo('allocation', { inverse: 'preemptedAllocations' }) preemptedByAllocation;
|
|
@attr('boolean') wasPreempted;
|
|
|
|
@belongsTo('evaluation') followUpEvaluation;
|
|
|
|
@computed('clientStatus')
|
|
get statusClass() {
|
|
const classMap = {
|
|
pending: 'is-pending',
|
|
running: 'is-primary',
|
|
complete: 'is-complete',
|
|
failed: 'is-error',
|
|
lost: 'is-light',
|
|
};
|
|
|
|
return classMap[this.clientStatus] || 'is-dark';
|
|
}
|
|
|
|
@computed('jobVersion', 'job.version')
|
|
get isOld() {
|
|
return this.jobVersion !== this.get('job.version');
|
|
}
|
|
|
|
@computed('isOld', 'jobTaskGroup', 'allocationTaskGroup')
|
|
get taskGroup() {
|
|
if (!this.isOld) return this.jobTaskGroup;
|
|
return this.allocationTaskGroup;
|
|
}
|
|
|
|
@computed('taskGroupName', 'job.taskGroups.[]')
|
|
get jobTaskGroup() {
|
|
const taskGroups = this.get('job.taskGroups');
|
|
return taskGroups && taskGroups.findBy('name', this.taskGroupName);
|
|
}
|
|
|
|
@fragment('task-group', { defaultValue: null }) allocationTaskGroup;
|
|
|
|
@computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]')
|
|
get unhealthyDrivers() {
|
|
const taskGroupUnhealthyDrivers = this.get('taskGroup.drivers');
|
|
const nodeUnhealthyDrivers = this.get('node.unhealthyDriverNames');
|
|
|
|
if (taskGroupUnhealthyDrivers && nodeUnhealthyDrivers) {
|
|
return intersection(taskGroupUnhealthyDrivers, nodeUnhealthyDrivers);
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
@fragmentArray('task-state') states;
|
|
@fragmentArray('reschedule-event') rescheduleEvents;
|
|
|
|
@computed('rescheduleEvents.length', 'nextAllocation')
|
|
get hasRescheduleEvents() {
|
|
return this.get('rescheduleEvents.length') > 0 || this.nextAllocation;
|
|
}
|
|
|
|
@computed('nextAllocation', 'clientStatus', 'followUpEvaluation.content')
|
|
get hasStoppedRescheduling() {
|
|
return (
|
|
!this.get('nextAllocation.content') &&
|
|
!this.get('followUpEvaluation.content') &&
|
|
this.clientStatus === 'failed'
|
|
);
|
|
}
|
|
|
|
stop() {
|
|
return this.store.adapterFor('allocation').stop(this);
|
|
}
|
|
|
|
restart(taskName) {
|
|
return this.store.adapterFor('allocation').restart(this, taskName);
|
|
}
|
|
|
|
ls(path) {
|
|
return this.store.adapterFor('allocation').ls(this, path);
|
|
}
|
|
|
|
stat(path) {
|
|
return this.store.adapterFor('allocation').stat(this, path);
|
|
}
|
|
}
|