github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/templates/topology.hbs (about) 1 <Breadcrumb @crumb={{hash label="Topology" args=(array "topology")}} /> 2 {{page-title "Cluster Topology"}} 3 <PageLayout> 4 <section class="section is-full-width"> 5 {{#if this.isForbidden}} 6 <ForbiddenMessage /> 7 {{else}} 8 {{#if this.pre09Nodes}} 9 <div class="notification is-warning"> 10 <div data-test-filtered-nodes-warning class="columns"> 11 <div class="column"> 12 <h3 data-test-title class="title is-4"> 13 Some Clients Were Filtered 14 </h3> 15 <p data-test-message> 16 {{this.pre09Nodes.length}} 17 {{if (eq this.pre09Nodes.length 1) "client was" "clients were"}} 18 filtered from the topology visualization. This is most likely due to the 19 {{pluralize "client" this.pre09Nodes.length}} 20 running a version of Nomad 21 </p> 22 </div> 23 <div class="column is-centered is-minimum"> 24 <button 25 data-test-dismiss 26 class="button is-warning" 27 onclick={{action (mut this.pre09Nodes) null}} 28 type="button" 29 > 30 Okay 31 </button> 32 </div> 33 </div> 34 </div> 35 {{/if}} 36 <div class="columns"> 37 <div class="column is-narrow is-400"> 38 {{#if this.showPollingNotice}} 39 <div class="notification is-warning"> 40 <div class="columns"> 41 <div class="column"> 42 <h3 class="title is-4"> 43 No Live Updating 44 </h3> 45 <p> 46 The topology visualization depends on too much data to continuously poll. 47 </p> 48 </div> 49 <div class="column is-centered is-minimum"> 50 <button 51 data-test-polling-notice-dismiss 52 class="button is-warning" 53 type="button" 54 onclick={{toggle-action "showPollingNotice" this}} 55 > 56 Okay 57 </button> 58 </div> 59 </div> 60 </div> 61 {{/if}} 62 <div class="boxed-section"> 63 <div class="boxed-section-head"> 64 Legend 65 {{#if (cannot "list all jobs")}} 66 <span 67 aria-label="Your ACL token may limit your ability to list all allocations" 68 class="tag is-warning pull-right tooltip multiline" 69 > 70 Partial View 71 </span> 72 {{/if}} 73 </div> 74 <div class="boxed-section-body"> 75 <div class="legend"> 76 <h3 class="legend-label"> 77 Metrics 78 </h3> 79 <dl class="legend-terms"> 80 <dt> 81 M: 82 </dt> 83 <dd> 84 Memory 85 </dd> 86 <dt> 87 C: 88 </dt> 89 <dd> 90 CPU 91 </dd> 92 </dl> 93 </div> 94 <div class="legend"> 95 <h3 class="legend-label"> 96 Allocation Status 97 </h3> 98 <dl class="legend-terms"> 99 <div class="legend-term"> 100 <dt> 101 <span class="color-swatch is-wide running" title="Running"></span> 102 </dt> 103 <dd> 104 Running 105 </dd> 106 </div> 107 <div class="legend-term"> 108 <dt> 109 <span class="color-swatch is-wide pending" title="Starting"></span> 110 </dt> 111 <dd> 112 Starting 113 </dd> 114 </div> 115 </dl> 116 </div> 117 </div> 118 </div> 119 <div class="boxed-section"> 120 <div data-test-info-panel-title class="boxed-section-head"> 121 {{#if this.activeNode}} 122 Client 123 {{else if this.activeAllocation}} 124 Allocation 125 {{else}} 126 Cluster 127 {{/if}} 128 Details 129 </div> 130 <div data-test-info-panel class="boxed-section-body"> 131 {{#if this.activeNode}} 132 {{#let this.activeNode.node as |node|}} 133 <div class="dashboard-metric"> 134 <p data-test-allocations class="metric"> 135 {{this.activeNode.allocations.length}} 136 <span class="metric-label"> 137 Allocations 138 </span> 139 </p> 140 </div> 141 <div class="dashboard-metric"> 142 <h3 class="pair"> 143 <strong> 144 Client: 145 </strong> 146 <LinkTo data-test-client-link @route="clients.client" @model={{node}}> 147 {{node.shortId}} 148 </LinkTo> 149 </h3> 150 <p data-test-name class="minor-pair"> 151 <strong> 152 Name: 153 </strong> 154 {{node.name}} 155 </p> 156 <p data-test-address class="minor-pair"> 157 <strong> 158 Address: 159 </strong> 160 {{node.httpAddr}} 161 </p> 162 <p data-test-status class="minor-pair"> 163 <strong> 164 Status: 165 </strong> 166 {{node.status}} 167 </p> 168 </div> 169 <div class="dashboard-metric"> 170 <h3 class="pair"> 171 <strong> 172 Draining? 173 </strong> 174 <span data-test-draining class="{{if node.isDraining "status-text is-info"}}"> 175 {{if node.isDraining "Yes" "No"}} 176 </span> 177 </h3> 178 <h3 class="pair"> 179 <strong> 180 Eligible? 181 </strong> 182 <span 183 data-test-eligible 184 class="{{unless node.isEligible "status-text is-warning"}}" 185 > 186 {{if node.isEligible "Yes" "No"}} 187 </span> 188 </h3> 189 </div> 190 <div class="dashboard-metric with-divider"> 191 <p class="metric"> 192 {{this.nodeUtilization.totalMemoryFormatted}} 193 <span class="metric-units"> 194 {{this.nodeUtilization.totalMemoryUnits}} 195 </span> 196 <span class="metric-label"> 197 of memory 198 </span> 199 </p> 200 <div class="columns graphic"> 201 <div class="column"> 202 <div class="inline-chart"> 203 <progress 204 data-test-memory-progress-bar 205 class="progress is-danger is-small" 206 value="{{this.nodeUtilization.reservedMemoryPercent}}" 207 max="1" 208 > 209 {{this.nodeUtilization.reservedMemoryPercent}} 210 </progress> 211 </div> 212 </div> 213 <div class="column is-minimum"> 214 <span class="nowrap" data-test-percentage> 215 {{format-percentage this.nodeUtilization.reservedMemoryPercent total=1}} 216 </span> 217 </div> 218 </div> 219 <div class="annotation" data-test-memory-absolute-value> 220 <strong> 221 {{format-scheduled-bytes this.nodeUtilization.totalReservedMemory}} 222 </strong> 223 / 224 {{format-scheduled-bytes this.nodeUtilization.totalMemory}} 225 reserved 226 </div> 227 </div> 228 <div class="dashboard-metric"> 229 <p class="metric"> 230 {{this.nodeUtilization.totalCPU}} 231 <span class="metric-units"> 232 MHz 233 </span> 234 <span class="metric-label"> 235 of CPU 236 </span> 237 </p> 238 <div class="columns graphic"> 239 <div class="column"> 240 <div class="inline-chart" data-test-percentage-bar> 241 <progress 242 data-test-cpu-progress-bar 243 class="progress is-info is-small" 244 value="{{this.nodeUtilization.reservedCPUPercent}}" 245 max="1" 246 > 247 {{this.nodeUtilization.reservedCPUPercent}} 248 </progress> 249 </div> 250 </div> 251 <div class="column is-minimum"> 252 <span class="nowrap" data-test-percentage> 253 {{format-percentage this.nodeUtilization.reservedCPUPercent total=1}} 254 </span> 255 </div> 256 </div> 257 <div class="annotation" data-test-cpu-absolute-value> 258 <strong> 259 {{format-scheduled-hertz this.nodeUtilization.totalReservedCPU}} 260 </strong> 261 / 262 {{format-scheduled-hertz this.nodeUtilization.totalCPU}} 263 reserved 264 </div> 265 </div> 266 {{/let}} 267 {{else if this.activeAllocation}} 268 <div class="dashboard-metric"> 269 <h3 class="pair"> 270 <strong> 271 Allocation: 272 </strong> 273 <LinkTo 274 data-test-id 275 @route="allocations.allocation" 276 @model={{this.activeAllocation}} 277 class="is-primary" 278 > 279 {{this.activeAllocation.shortId}} 280 </LinkTo> 281 </h3> 282 <p data-test-sibling-allocs class="minor-pair"> 283 <strong> 284 Sibling Allocations: 285 </strong> 286 {{this.siblingAllocations.length}} 287 </p> 288 <p data-test-unique-placements class="minor-pair"> 289 <strong> 290 Unique Client Placements: 291 </strong> 292 {{this.uniqueActiveAllocationNodes.length}} 293 </p> 294 </div> 295 <div class="dashboard-metric with-divider"> 296 <h3 class="pair"> 297 <strong> 298 Job: 299 </strong> 300 <LinkTo 301 data-test-job 302 @route="jobs.job" 303 @model={{this.activeAllocation.job}} 304 > 305 {{this.activeAllocation.job.name}} 306 </LinkTo> 307 <span class="is-faded" data-test-task-group> 308 / 309 {{this.activeAllocation.taskGroupName}} 310 </span> 311 </h3> 312 <p class="minor-pair"> 313 <strong> 314 Type: 315 </strong> 316 {{this.activeAllocation.job.type}} 317 </p> 318 <p class="minor-pair"> 319 <strong> 320 Priority: 321 </strong> 322 {{this.activeAllocation.job.priority}} 323 </p> 324 </div> 325 <div class="dashboard-metric with-divider"> 326 <h3 class="pair"> 327 <strong> 328 Client: 329 </strong> 330 <LinkTo 331 data-test-client 332 @route="clients.client" 333 @model={{this.activeAllocation.node}} 334 > 335 {{this.activeAllocation.node.shortId}} 336 </LinkTo> 337 </h3> 338 <p class="minor-pair"> 339 <strong> 340 Name: 341 </strong> 342 {{this.activeAllocation.node.name}} 343 </p> 344 <p class="minor-pair"> 345 <strong> 346 Address: 347 </strong> 348 {{this.activeAllocation.node.httpAddr}} 349 </p> 350 </div> 351 <div class="dashboard-metric with-divider"> 352 <PrimaryMetric::Allocation 353 @allocation={{this.activeAllocation}} 354 @metric="memory" 355 class="is-short" 356 /> 357 </div> 358 <div class="dashboard-metric"> 359 <PrimaryMetric::Allocation 360 @allocation={{this.activeAllocation}} 361 @metric="cpu" 362 class="is-short" 363 /> 364 </div> 365 {{else}} 366 <div class="columns is-flush"> 367 <div class="dashboard-metric column"> 368 <p data-test-node-count class="metric"> 369 {{this.model.nodes.length}} 370 <span class="metric-label"> 371 Clients 372 </span> 373 </p> 374 </div> 375 <div class="dashboard-metric column"> 376 <p data-test-alloc-count class="metric"> 377 {{this.scheduledAllocations.length}} 378 <span class="metric-label"> 379 Allocations 380 </span> 381 </p> 382 </div> 383 </div> 384 <div class="dashboard-metric with-divider"> 385 <p class="metric"> 386 {{this.totalMemoryFormatted}} 387 <span class="metric-units"> 388 {{this.totalMemoryUnits}} 389 </span> 390 <span class="metric-label"> 391 of memory 392 </span> 393 </p> 394 <div class="columns graphic"> 395 <div class="column"> 396 <div class="inline-chart" data-test-percentage-bar> 397 <progress 398 data-test-memory-progress-bar 399 class="progress is-danger is-small" 400 value="{{this.reservedMemoryPercent}}" 401 max="1" 402 > 403 {{this.reservedMemoryPercent}} 404 </progress> 405 </div> 406 </div> 407 <div class="column is-minimum"> 408 <span class="nowrap" data-test-memory-percentage> 409 {{format-percentage this.reservedMemoryPercent total=1}} 410 </span> 411 </div> 412 </div> 413 <div class="annotation" data-test-memory-absolute-value> 414 <strong> 415 {{format-bytes this.totalReservedMemory}} 416 </strong> 417 / 418 {{format-bytes this.totalMemory}} 419 reserved 420 </div> 421 </div> 422 <div class="dashboard-metric"> 423 <p class="metric"> 424 {{this.totalCPUFormatted}} 425 <span class="metric-units"> 426 {{this.totalCPUUnits}} 427 </span> 428 <span class="metric-label"> 429 of CPU 430 </span> 431 </p> 432 <div class="columns graphic"> 433 <div class="column"> 434 <div class="inline-chart" data-test-percentage-bar> 435 <progress 436 data-test-cpu-progress-bar 437 class="progress is-info is-small" 438 value="{{this.reservedCPUPercent}}" 439 max="1" 440 > 441 {{this.reservedCPUPercent}} 442 </progress> 443 </div> 444 </div> 445 <div class="column is-minimum"> 446 <span class="nowrap" data-test-cpu-percentage> 447 {{format-percentage this.reservedCPUPercent total=1}} 448 </span> 449 </div> 450 </div> 451 <div class="annotation" data-test-cpu-absolute-value> 452 <strong> 453 {{format-hertz this.totalReservedCPU}} 454 </strong> 455 / 456 {{format-hertz this.totalCPU}} 457 reserved 458 </div> 459 </div> 460 {{/if}} 461 </div> 462 </div> 463 </div> 464 <div class="column"> 465 <div class="toolbar"> 466 <div class="toolbar-item"> 467 {{#if this.model.nodes.length}} 468 <SearchBox 469 @inputClass="node-search" 470 @searchTerm={{mut this.searchTerm}} 471 @placeholder="Search clients..." 472 /> 473 {{/if}} 474 </div> 475 <div class="toolbar-item is-right-aligned is-mobile-full-width"> 476 <div class="button-bar"> 477 <MultiSelectDropdown 478 data-test-datacenter-facet 479 @label="Datacenter" 480 @options={{this.optionsDatacenter}} 481 @selection={{this.selectionDatacenter}} 482 @onSelect={{action this.setFacetQueryParam "qpDatacenter"}} 483 /> 484 <MultiSelectDropdown 485 data-test-class-facet 486 @label="Class" 487 @options={{this.optionsClass}} 488 @selection={{this.selectionClass}} 489 @onSelect={{action this.setFacetQueryParam "qpClass"}} 490 /> 491 <MultiSelectDropdown 492 data-test-state-facet 493 @label="State" 494 @options={{this.optionsState}} 495 @selection={{this.selectionState}} 496 @onSelect={{action this.setFacetQueryParam "qpState"}} 497 /> 498 <MultiSelectDropdown 499 data-test-version-facet 500 @label="Version" 501 @options={{this.optionsVersion}} 502 @selection={{this.selectionVersion}} 503 @onSelect={{action this.setFacetQueryParam "qpVersion"}} 504 /> 505 </div> 506 </div> 507 </div> 508 <TopoViz 509 @nodes={{this.filteredNodes}} 510 @allocations={{this.model.allocations}} 511 @onAllocationSelect={{action this.setAllocation}} 512 @onNodeSelect={{action this.setNode}} 513 @onDataError={{action this.handleTopoVizDataError}} 514 @filters={{hash 515 search=this.searchTerm 516 clientState=this.selectionState 517 clientVersion=this.selectionVersion 518 }} 519 /> 520 </div> 521 </div> 522 {{/if}} 523 </section> 524 </PageLayout>