Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(647)

Side by Side Diff: appengine/swarming/elements/res/imp/botlist/bot-list.html

Issue 2211163003: Update new botlist to use dimensions endpoint (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@limiting
Patch Set: put demo data in luci-py wiki Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!-- 1 <!--
2 Copyright 2016 The LUCI Authors. All rights reserved. 2 Copyright 2016 The LUCI Authors. All rights reserved.
3 Use of this source code is governed under the Apache License, Version 2.0 3 Use of this source code is governed under the Apache License, Version 2.0
4 that can be found in the LICENSE file. 4 that can be found in the LICENSE file.
5 5
6 This in an HTML Import-able file that contains the definition 6 This in an HTML Import-able file that contains the definition
7 of the following elements: 7 of the following elements:
8 8
9 <bot-list> 9 <bot-list>
10 10
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 86
87 <div hidden$="[[_not(_signed_in)]]"> 87 <div hidden$="[[_not(_signed_in)]]">
88 88
89 <div class="horizontal layout"> 89 <div class="horizontal layout">
90 90
91 <bot-filters 91 <bot-filters
92 primary_map="[[_primary_map]]" 92 primary_map="[[_primary_map]]"
93 primary_arr="[[_primary_arr]]" 93 primary_arr="[[_primary_arr]]"
94 94
95 columns="{{_columns}}" 95 columns="{{_columns}}"
96 dimensions="{{_dimensions}}"
96 filter="{{_filter}}" 97 filter="{{_filter}}"
97 verbose="{{_verbose}}"> 98 verbose="{{_verbose}}">
98 </bot-filters> 99 </bot-filters>
99 100
100 <bot-list-summary 101 <bot-list-summary
101 fleet="[[_fleet]]" 102 fleet="[[_fleet]]"
102 filtered_bots="[[_filteredSortedBots]]"> 103 filtered_bots="[[_filteredSortedBots]]">
103 </bot-list-summary> 104 </bot-list-summary>
104 105
105 </div> 106 </div>
106 107
107 <bot-list-data 108 <bot-list-data
108 auth_headers="[[_auth_headers]]" 109 auth_headers="[[_auth_headers]]"
110 dimensions="[[_dimensions]]"
109 111
110 bots="{{_bots}}" 112 bots="{{_bots}}"
111 busy="{{_busy}}" 113 busy="{{_busy}}"
112 fleet="{{_fleet}}" 114 fleet="{{_fleet}}"
113 primary_map="{{_primary_map}}" 115 primary_map="{{_primary_map}}"
114 primary_arr="{{_primary_arr}}"> 116 primary_arr="{{_primary_arr}}">
115 </bot-list-data> 117 </bot-list-data>
116 118
117 <table class="bot-list"> 119 <table class="bot-list">
118 <thead on-sort_change="_sortChange"> 120 <thead on-sort_change="_sortChange">
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 as="c"> 182 as="c">
181 <td hidden$="[[_hide(c)]]"> 183 <td hidden$="[[_hide(c)]]">
182 [[_column(c, bot, _verbose)]] 184 [[_column(c, bot, _verbose)]]
183 </td> 185 </td>
184 </template> 186 </template>
185 187
186 </tr> 188 </tr>
187 <template is="dom-repeat" 189 <template is="dom-repeat"
188 items="[[_devices(bot)]]" 190 items="[[_devices(bot)]]"
189 as="device"> 191 as="device">
190 <tr hidden$="[[_hide('devices', _columns.*)]]" 192 <tr hidden$="[[_hide('android_devices', _columns.*)]]"
191 class$="[[_deviceClass(device)]]"> 193 class$="[[_deviceClass(device)]]">
192 <td></td> 194 <td></td>
193 <td hidden$="[[_hide('task', _columns.*)]]"></td> 195 <td hidden$="[[_hide('task', _columns.*)]]"></td>
194 <template is="dom-repeat" 196 <template is="dom-repeat"
195 items="[[_plain_columns]]" 197 items="[[_plain_columns]]"
196 as="c"> 198 as="c">
197 <td hidden$="[[_hide(c)]]"> 199 <td hidden$="[[_hide(c)]]">
198 [[_deviceColumn(c, device, _verbose)]] 200 [[_deviceColumn(c, device, _verbose)]]
199 </td> 201 </td>
200 </template> 202 </template>
201 </tr> 203 </tr>
202 </template> <!--devices repeat--> 204 </template> <!--devices repeat-->
203 </template> <!--bot-table repeat--> 205 </template> <!--bot-table repeat-->
204 </tbody> 206 </tbody>
205 </table> 207 </table>
206 </div> 208 </div>
207 209
208 </swarming-app> 210 </swarming-app>
209 211
210 </template> 212 </template>
211 <script> 213 <script>
212 (function(){ 214 (function(){
213 var special_columns = ["id", "task"]; 215 var special_columns = ["id", "task"];
214 216
215 var headerMap = { 217 var headerMap = {
216 // "id" and "task" are special, so they don't go here and have their 218 // "id" and "task" are special, so they don't go here and have their
217 // headers hard-coded below. 219 // headers hard-coded below.
220 "android_devices": "Android Devices",
218 "cores": "Cores", 221 "cores": "Cores",
219 "cpu": "CPU", 222 "cpu": "CPU",
220 "devices": "Devices", 223 "device_os": "Device OS",
224 "device_type": "Device Type",
225 "disk_space": "Free Space (MB)",
221 "gpu": "GPU", 226 "gpu": "GPU",
222 "os": "OS", 227 "os": "OS",
223 "pool": "Pool", 228 "pool": "Pool",
224 "status": "Status", 229 "status": "Status",
225 }; 230 };
226 231
227 // This maps column name to a function that will return the content for a 232 // This maps column name to a function that will return the content for a
228 // given bot. These functions are bound to this element, and have access 233 // given bot. These functions are bound to this element, and have access
229 // to all functions defined here and in bot-list-shared. 234 // to all functions defined here and in bot-list-shared.
230 var columnMap = { 235 var columnMap = {
236 android_devices: function(bot) {
237 var devs = this._attribute(bot, "android_devices", "0");
238 if (this._verbose) {
239 return devs.join(" | ") + " devices available";
240 }
241 // max() works on strings as long as they can be coerced to Number.
242 return Math.max(...devs) + " devices available";
243 },
231 cores: function(bot){ 244 cores: function(bot){
232 var cores = this._cores(bot); 245 var cores = this._attribute(bot, "cores");
233 if (this._verbose){ 246 if (this._verbose){
234 return cores.join(" | "); 247 return cores.join(" | ");
235 } 248 }
236 return cores[0]; 249 return cores[0];
237 }, 250 },
238 cpu: function(bot){ 251 cpu: function(bot){
239 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; 252 var cpus = this._attribute(bot, "cpu");
240 if (this._verbose){ 253 if (this._verbose){
241 return cpus.join(" | "); 254 return cpus.join(" | ");
242 } 255 }
243 return cpus[0]; 256 return cpus[0];
244 }, 257 },
245 devices: function(bot){ 258 device_os: function(bot){
246 return this._devices(bot).length + " devices attached"; 259 var os = this._attribute(bot, "device_os", "none");
260 if (this._verbose) {
261 return os.join(" | ");
262 }
263 return os[0];
264 },
265 device_type: function(bot){
266 var dt = this._attribute(bot, "device_type", "none");
267 if (this._verbose) {
268 return dt.join(" | ");
269 }
270 return dt[0];
271 },
272 disk_space: function(bot) {
273 var aliased = [];
274 bot.disks.forEach(function(disk){
275 var alias = swarming.humanBytes(disk.mb, swarming.MB);
276 aliased.push(this._applyAlias(disk.mb, disk.id + " "+ alias));
277 }.bind(this));
278 if (this._verbose) {
279 return aliased.join(" | ");
280 }
281 return aliased[0];
247 }, 282 },
248 gpu: function(bot){ 283 gpu: function(bot){
249 var gpus = this._dimension(bot, 'gpu') 284 var gpus = this._attribute(bot, "gpu", "none")
250 if (!gpus) {
251 return "none";
252 }
253 var verbose = [] 285 var verbose = []
254 var named = []; 286 var named = [];
255 // non-verbose mode has only the top level GPU info "e.g. NVidia" 287 // non-verbose mode has only the top level GPU info "e.g. NVidia"
256 // which is found by looking for gpu ids w/o a colon. 288 // which is found by looking for gpu ids w/o a colon.
257 gpus.forEach(function(g){ 289 gpus.forEach(function(g){
258 var alias = this._gpuAlias(g); 290 var alias = this._gpuAlias(g);
259 if (alias === "UNKNOWN") { 291 if (alias === "unknown") {
260 verbose.push(g); 292 verbose.push(g);
261 if (g.indexOf(":") === -1) { 293 if (g.indexOf(":") === -1) {
262 named.push(g); 294 named.push(g);
263 } 295 }
264 return; 296 return;
265 } 297 }
266 verbose.push(this._applyAlias(g, alias)); 298 verbose.push(this._applyAlias(g, alias));
267 if (g.indexOf(":") === -1) { 299 if (g.indexOf(":") === -1) {
268 named.push(this._applyAlias(g, alias)); 300 named.push(this._applyAlias(g, alias));
269 } 301 }
270 }.bind(this)) 302 }.bind(this))
271 if (this._verbose) { 303 if (this._verbose) {
272 return verbose.join(" | "); 304 return verbose.join(" | ");
273 } 305 }
274 return named.join(" | "); 306 return named.join(" | ");
275 }, 307 },
276 id: function(bot) { 308 id: function(bot) {
277 return bot.bot_id; 309 return bot.bot_id;
278 }, 310 },
279 os: function(bot) { 311 os: function(bot) {
280 var os = this._dimension(bot, 'os') || ['Unknown']; 312 var os = this._attribute(bot, "os");
281 if (this._verbose){ 313 if (this._verbose){
282 return os.join(" | "); 314 return os.join(" | ");
283 } 315 }
284 return os[0]; 316 return os[0];
285 }, 317 },
286 pool: function(bot) { 318 pool: function(bot) {
287 var pool = this._dimension(bot, 'pool') || ['Unknown']; 319 var pool = this._attribute(bot, "pool");
288 return pool.join(" | "); 320 return pool.join(" | ");
289 }, 321 },
290 status: function(bot) { 322 status: function(bot) {
291 // If a bot is both dead and quarantined, show the deadness over the 323 // If a bot is both dead and quarantined, show the deadness over the
292 // quarentinedness. 324 // quarentinedness.
293 if (bot.is_dead) { 325 if (bot.is_dead) {
294 return "Dead: " + bot.is_dead; 326 return "Dead. Last seen " + swarming.diffDate(bot.last_seen_ts) +
327 " ago";
295 } 328 }
296 if (bot.quarantined) { 329 if (bot.quarantined) {
297 return "Quarantined: " + bot.quarantined; 330 return "Quarantined: " + this._attribute(bot, "quarantined");
298 } 331 }
299 return "Alive"; 332 return "Alive";
300 }, 333 },
301 task: function(bot){ 334 task: function(bot){
302 return this._taskId(bot); 335 return this._taskId(bot);
303 }, 336 },
304 }; 337 };
305 338
339 var deviceColumnMap = {
340 android_devices: function(device) {
341 var str = this._androidAliasDevice(device);
342 if (device.okay) {
343 str = this._applyAlias(this._deviceType(device), str);
344 }
345 str += " S/N:";
346 str += device.serial;
347 return str;
348 },
349 device_os: function(device) {
350 if (device.build) {
351 return device.build["build.id"];
352 }
353 return "unknown";
354 },
355 status: function(device) {
356 return device.state;
357 }
358 }
359
360 // specialSort defines any custom sorting rules. By default, a
361 // naturalCompare of the column content is done.
362 var specialSort = {
363 device_type: function(dir, botA, botB) {
364 // We sort on the number of attached devices. Note that this
365 // may not be the same as android_devices, because _devices().length
366 // counts all devices plugged into the bot, whereas android_devices
367 // counts just devices ready for work.
368 var botACol = this._devices(botA).length;
369 var botBCol = this._devices(botB).length;
370 return dir * swarming.naturalCompare(botACol, botBCol);
371 },
372 disk_space: function(dir, botA, botB) {
373 // We sort based on the raw number of MB of the first disk.
374 var botACol = botA.disks[0].mb;
375 var botBCol = botB.disks[0].mb;;
376 return dir * swarming.naturalCompare(botACol, botBCol);
377 },
378 };
379
306 Polymer({ 380 Polymer({
307 is: 'bot-list', 381 is: 'bot-list',
308 behaviors: [SwarmingBehaviors.BotListBehavior], 382 behaviors: [SwarmingBehaviors.BotListBehavior],
309 383
310 properties: { 384 properties: {
311 385
312 _bots: { 386 _bots: {
313 type: Array, 387 type: Array,
314 }, 388 },
315 389
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 _botLink: function(id) { 437 _botLink: function(id) {
364 // TODO(kjlubick) Make this point to /newui/ when appropriate. 438 // TODO(kjlubick) Make this point to /newui/ when appropriate.
365 return "/restricted/bot/"+id; 439 return "/restricted/bot/"+id;
366 }, 440 },
367 441
368 442
369 _column: function(col, bot) { 443 _column: function(col, bot) {
370 return columnMap[col].bind(this)(bot); 444 return columnMap[col].bind(this)(bot);
371 }, 445 },
372 446
447 _androidAliasDevice: function(device) {
448 if (device.notReady) {
449 return UNAUTHENTICATED.toUpperCase();
450 }
451 return this._androidAlias(this._deviceType(device));
452 },
453
373 _deviceColumn: function(col, device) { 454 _deviceColumn: function(col, device) {
374 if (col === "devices") { 455 var f = deviceColumnMap[col];
375 var str = this._androidAlias(device); 456 if (!f || !device) {
376 if (device.okay) { 457 return "";
377 str = this._applyAlias(this._deviceType(device), str);
378 }
379 str += " S/N:";
380 str += device.serial;
381 return str;
382 } 458 }
383 if (col === "status") { 459 return f.bind(this)(device);
384 return device.state;
385 }
386 return "";
387 }, 460 },
388 461
389 _deviceClass: function(device) { 462 _deviceClass: function(device) {
390 if (!device.okay) { 463 if (!device.okay) {
391 return "bad-device"; 464 return "bad-device";
392 } 465 }
393 return ""; 466 return "";
394 }, 467 },
395 468
396 _filterAndSort: function(a,b,c) { 469 _filterAndSort: function(a,b,c) {
(...skipping 22 matching lines...) Expand all
419 }, 492 },
420 493
421 _sortBotTable: function(botA, botB) { 494 _sortBotTable: function(botA, botB) {
422 if (!this._sort) { 495 if (!this._sort) {
423 return 0; 496 return 0;
424 } 497 }
425 var dir = 1; 498 var dir = 1;
426 if (this._sort.direction === "desc") { 499 if (this._sort.direction === "desc") {
427 dir = -1; 500 dir = -1;
428 } 501 }
502 var sort = specialSort[this._sort.name];
503 if (sort) {
504 return sort.bind(this)(dir, botA, botB);
505 }
506 // Default to a natural compare of the columns.
429 var botACol = this._column(this._sort.name, botA); 507 var botACol = this._column(this._sort.name, botA);
430 var botBCol = this._column(this._sort.name, botB); 508 var botBCol = this._column(this._sort.name, botB);
431 509
432 return dir * swarming.naturalCompare(botACol, botBCol); 510 return dir * swarming.naturalCompare(botACol, botBCol);
433 }, 511 },
434 512
435 _sortChange: function(e) { 513 _sortChange: function(e) {
436 // The event we get from sort-toggle tells us the name of what needs 514 // The event we get from sort-toggle tells us the name of what needs
437 // to be sorting and how to sort it. 515 // to be sorting and how to sort it.
438 if (!(e && e.detail && e.detail.name)) { 516 if (!(e && e.detail && e.detail.name)) {
(...skipping 16 matching lines...) Expand all
455 if (data && data.task_id) { 533 if (data && data.task_id) {
456 return "/user/task/" + data.task_id; 534 return "/user/task/" + data.task_id;
457 } 535 }
458 return undefined; 536 return undefined;
459 } 537 }
460 538
461 }); 539 });
462 })(); 540 })();
463 </script> 541 </script>
464 </dom-module> 542 </dom-module>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698