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

104 lines
3.1 KiB
JavaScript
Raw Normal View History

import { inject as service } from '@ember/service';
import { readOnly } from '@ember/object/computed';
import { computed } from '@ember/object';
import RSVP from 'rsvp';
2017-09-19 14:47:10 +00:00
import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo } from 'ember-data/relationships';
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import PromiseObject from '../utils/classes/promise-object';
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'),
modifyIndex: attr('number'),
2017-11-30 23:08:31 +00:00
modifyTime: attr('date'),
2017-10-18 19:29:33 +00:00
jobVersion: attr('number'),
2017-09-19 14:47:10 +00:00
// TEMPORARY: https://github.com/emberjs/data/issues/5209
originalJobId: attr('string'),
2017-09-19 14:47:10 +00:00
clientStatus: attr('string'),
desiredStatus: attr('string'),
statusIndex: computed('clientStatus', function() {
return STATUS_ORDER[this.get('clientStatus')] || 100;
}),
2017-09-19 14:47:10 +00:00
statusClass: computed('clientStatus', function() {
const classMap = {
pending: 'is-pending',
running: 'is-primary',
complete: 'is-complete',
failed: 'is-error',
lost: 'is-light',
};
return classMap[this.get('clientStatus')] || 'is-dark';
}),
2017-09-19 14:47:10 +00:00
taskGroup: computed('taskGroupName', 'job.taskGroups.[]', function() {
const taskGroups = this.get('job.taskGroups');
return taskGroups && taskGroups.findBy('name', this.get('taskGroupName'));
}),
memoryUsed: readOnly('stats.ResourceUsage.MemoryStats.RSS'),
cpuUsed: computed('stats.ResourceUsage.CpuStats.TotalTicks', function() {
2017-10-20 00:15:10 +00:00
return Math.floor(this.get('stats.ResourceUsage.CpuStats.TotalTicks') || 0);
}),
percentMemory: computed('taskGroup.reservedMemory', 'memoryUsed', function() {
const used = this.get('memoryUsed') / 1024 / 1024;
const total = this.get('taskGroup.reservedMemory');
if (!total || !used) {
return 0;
2017-09-19 14:47:10 +00:00
}
return used / total;
}),
2017-09-19 14:47:10 +00:00
percentCPU: computed('cpuUsed', 'taskGroup.reservedCPU', function() {
const used = this.get('cpuUsed');
const total = this.get('taskGroup.reservedCPU');
if (!total || !used) {
return 0;
}
return used / total;
2017-09-19 14:47:10 +00:00
}),
stats: computed('node.{isPartial,httpAddr}', function() {
const nodeIsPartial = this.get('node.isPartial');
// If the node doesn't have an httpAddr, it's a partial record.
// Once it reloads, this property will be dirtied and stats will load.
if (nodeIsPartial) {
return PromiseObject.create({
// Never resolve, so the promise object is always in a state of pending
promise: new RSVP.Promise(() => {}),
});
}
const url = `/v1/client/allocation/${this.get('id')}/stats`;
2017-09-19 14:47:10 +00:00
return PromiseObject.create({
promise: this.get('token')
.authorizedRequest(url)
.then(res => res.json()),
2017-09-19 14:47:10 +00:00
});
}),
states: fragmentArray('task-state'),
});