Add cluster details to the topology page

This commit is contained in:
Michael Lange
2020-09-10 23:29:07 -07:00
parent 0b3a78b9ef
commit c2b7f7c073
7 changed files with 163 additions and 7 deletions

View File

@@ -42,9 +42,11 @@ export default class TopoViz extends Component {
if (this.activeTaskGroup === taskGroup && this.activeJobId === jobId) {
this.activeTaskGroup = null;
this.activeJobId = null;
if (this.args.onAllocationSelect) this.args.onAllocationSelect(null);
} else {
this.activeTaskGroup = taskGroup;
this.activeJobId = jobId;
if (this.args.onAllocationSelect) this.args.onAllocationSelect(allocation);
}
}
}

View File

@@ -0,0 +1,57 @@
import Controller from '@ember/controller';
import { computed } from '@ember/object';
import classic from 'ember-classic-decorator';
import { reduceToLargestUnit } from 'nomad-ui/helpers/format-bytes';
@classic
export default class TopologyControllers extends Controller {
get datacenters() {
return Array.from(new Set(this.model.nodes.mapBy('datacenter'))).compact();
}
@computed('model.nodes.@each.resources')
get totalMemory() {
const mibs = this.model.nodes
.mapBy('resources.memory')
.reduce((sum, memory) => sum + (memory || 0), 0);
return mibs * 1024 * 1024;
}
@computed('model.nodes.@each.resources')
get totalCPU() {
return this.model.nodes.mapBy('resources.cpu').reduce((sum, cpu) => sum + (cpu || 0), 0);
}
@computed('totalMemory')
get totalMemoryFormatted() {
return reduceToLargestUnit(this.totalMemory)[0].toFixed(2);
}
@computed('totalCPU')
get totalMemoryUnits() {
return reduceToLargestUnit(this.totalMemory)[1];
}
@computed('model.allocations.@each.resources')
get totalReservedMemory() {
const mibs = this.model.allocations
.mapBy('resources.memory')
.reduce((sum, memory) => sum + (memory || 0), 0);
return mibs * 1024 * 1024;
}
@computed('model.allocations.@each.resources')
get totalReservedCPU() {
return this.model.allocations.mapBy('resources.cpu').reduce((sum, cpu) => sum + (cpu || 0), 0);
}
@computed('totalMemory', 'totalReservedMemory')
get reservedMemoryPercent() {
return this.totalReservedMemory / this.totalMemory;
}
@computed('totalCPU', 'totalReservedCPU')
get reservedCPUPercent() {
return this.totalReservedCPU / this.totalCPU;
}
}

View File

@@ -1,6 +1,6 @@
import Helper from '@ember/component/helper';
const UNITS = ['Bytes', 'KiB', 'MiB'];
const UNITS = ['Bytes', 'KiB', 'MiB', 'GiB'];
/**
* Bytes Formatter
@@ -10,7 +10,7 @@ const UNITS = ['Bytes', 'KiB', 'MiB'];
* Outputs the bytes reduced to the largest supported unit size for which
* bytes is larger than one.
*/
export function formatBytes([bytes]) {
export function reduceToLargestUnit(bytes) {
bytes || (bytes = 0);
let unitIndex = 0;
while (bytes >= 1024 && unitIndex < UNITS.length - 1) {
@@ -18,7 +18,12 @@ export function formatBytes([bytes]) {
unitIndex++;
}
return `${Math.floor(bytes)} ${UNITS[unitIndex]}`;
return [bytes, UNITS[unitIndex]];
}
export function formatBytes([bytes]) {
const [number, unit] = reduceToLargestUnit(bytes);
return `${Math.floor(number)} ${unit}`;
}
export default Helper.helper(formatBytes);

View File

@@ -4,6 +4,7 @@
@import './components/codemirror';
@import './components/copy-button';
@import './components/cli-window';
@import './components/dashboard-metric';
@import './components/dropdown';
@import './components/ember-power-select';
@import './components/empty-message';

View File

@@ -0,0 +1,31 @@
.dashboard-metric {
margin-top: 1.5em;
.metric {
text-align: left;
font-weight: $weight-bold;
font-size: $size-3;
.metric-units {
font-size: $size-4;
}
.metric-label {
font-size: $body-size;
font-weight: $weight-normal;
}
}
.graphic {
padding-bottom: 0;
margin-bottom: 0;
> .column {
padding: 0.5rem 0.75rem;
}
}
.annotation {
margin-top: -0.75rem;
}
}

View File

@@ -24,14 +24,74 @@
</div>
</div>
<div class="boxed-section">
<div class="boxed-section-head">Cluster Details</div>
<div class="boxed-section-head">{{if this.activeAllocation "Allocation" "Cluster"}} Details</div>
<div class="boxed-section-body">
Aggregate metrics go here.
{{#if this.activeAllocation}}
Showing alloc details for {{this.activeAllocation.shortId}}
{{else}}
<div class="metric-group columns is-centered">
<div class="metric">
<h3 class="label">DCs</h3>
<p class="value">{{this.datacenters.length}}</p>
</div>
<div class="metric">
<h3 class="label">Clients</h3>
<p class="value">{{this.model.nodes.length}}</p>
</div>
<div class="metric">
<h3 class="label">Allocations</h3>
{{! TODO: make sure that this is only the scheduled allocations }}
<p class="value">{{this.model.allocations.length}}</p>
</div>
</div>
<div class="dashboard-metric">
<p class="metric">{{this.totalMemoryFormatted}} <span class="metric-units">{{this.totalMemoryUnits}}</span> <span class="metric-label">of memory</span></p>
<div class="columns graphic">
<div class="column">
<div class="inline-chart" data-test-percentage-bar>
<progress
class="progress is-danger is-small"
value="{{this.reservedMemoryPercent}}"
max="1">
{{this.reservedMemoryPercent}}
</progress>
</div>
</div>
<div class="column is-minimum">
<span class="nowrap" data-test-percentage>{{format-percentage this.reservedMemoryPercent total=1}}</span>
</div>
</div>
<div class="annotation" data-test-absolute-value>
<strong>{{format-bytes this.totalReservedMemory}}</strong> / {{format-bytes this.totalMemory}} reserved
</div>
</div>
<div class="dashboard-metric">
<p class="metric">{{this.totalCPU}} <span class="metric-units">Mhz</span> <span class="metric-label">of CPU</span></p>
<div class="columns graphic">
<div class="column">
<div class="inline-chart" data-test-percentage-bar>
<progress
class="progress is-info is-small"
value="{{this.reservedCPUPercent}}"
max="1">
{{this.reservedCPUPercent}}
</progress>
</div>
</div>
<div class="column is-minimum">
<span class="nowrap" data-test-percentage>{{format-percentage this.reservedCPUPercent total=1}}</span>
</div>
</div>
<div class="annotation" data-test-absolute-value>
<strong>{{this.totalReservedCPU}} Mhz</strong> / {{this.totalCPU}} Mhz reserved
</div>
</div>
{{/if}}
</div>
</div>
</div>
<div class="column">
<TopoViz @nodes={{this.model.nodes}} @allocations={{this.model.allocations}} />
<TopoViz @nodes={{this.model.nodes}} @allocations={{this.model.allocations}} @onAllocationSelect={{action (mut this.activeAllocation)}} />
</div>
</div>
</section>

View File

@@ -17,7 +17,7 @@ export function topoSmall(server) {
});
const jobResources = [
['M: 256, C: 150'],
['M: 2560, C: 150'],
['M: 128, C: 400'],
['M: 512, C: 100'],
['M: 256, C: 150'],