| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 20536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20547 <script> | 20547 <script> |
| 20548 Polymer({ | 20548 Polymer({ |
| 20549 is: 'paper-input', | 20549 is: 'paper-input', |
| 20550 | 20550 |
| 20551 behaviors: [ | 20551 behaviors: [ |
| 20552 Polymer.IronFormElementBehavior, | 20552 Polymer.IronFormElementBehavior, |
| 20553 Polymer.PaperInputBehavior | 20553 Polymer.PaperInputBehavior |
| 20554 ] | 20554 ] |
| 20555 }); | 20555 }); |
| 20556 </script> | 20556 </script> |
| 20557 <script> |
| 20558 |
| 20559 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; |
| 20560 (function(){ |
| 20561 var ANDROID_ALIASES = { |
| 20562 "bullhead": "Nexus 5X", |
| 20563 "flo": "Nexus 7", |
| 20564 "flounder": "Nexus 9", |
| 20565 "hammerhead": "Nexus 5", |
| 20566 "mako": "Nexus 4", |
| 20567 "shamu": "Nexus 6", |
| 20568 }; |
| 20569 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html |
| 20570 var BATTERY_HEALTH_UNKNOWN = 1; |
| 20571 var BATTERY_HEALTH_GOOD = 2; |
| 20572 var BATTERY_STATUS_CHARGING = 2; |
| 20573 |
| 20574 var UNAUTHENTICATED = "unauthenticated"; |
| 20575 var AVAILABLE = "available"; |
| 20576 var UNKNOWN = "unknown"; |
| 20577 |
| 20578 var GPU_ALIASES = { |
| 20579 "1002": "AMD", |
| 20580 "1002:6779": "AMD Radeon HD 6450/7450/8450", |
| 20581 "1002:6821": "AMD Radeon HD 8870M", |
| 20582 "1002:9830": "AMD Radeon HD 8400", |
| 20583 "102b": "Matrox", |
| 20584 "102b:0522": "Matrox MGA G200e", |
| 20585 "102b:0532": "Matrox MGA G200eW", |
| 20586 "102b:0534": "Matrox G200eR2", |
| 20587 "10de": "NVIDIA", |
| 20588 "10de:08aa": "NVIDIA GeForce 320M", |
| 20589 "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", |
| 20590 "10de:104a": "NVIDIA GeForce GT 610", |
| 20591 "10de:11c0": "NVIDIA GeForce GTX 660", |
| 20592 "10de:1244": "NVIDIA GeForce GTX 550 Ti", |
| 20593 "10de:1401": "NVIDIA GeForce GTX 960", |
| 20594 "8086": "Intel", |
| 20595 "8086:041a": "Intel Xeon Integrated", |
| 20596 "8086:0a2e": "Intel Haswell Integrated", |
| 20597 "8086:0d26": "Intel Crystal Well Integrated", |
| 20598 } |
| 20599 |
| 20600 // For consistency, all aliases are displayed like: |
| 20601 // Nexus 5X (bullhead) |
| 20602 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. |
| 20603 var ALIAS_REGEXP = /.+ \((.*)\)/; |
| 20604 |
| 20605 // This behavior wraps up all the shared bot-list functionality. |
| 20606 SwarmingBehaviors.BotListBehavior = { |
| 20607 |
| 20608 properties: { |
| 20609 // TODO(kjlubick): Add more of these things from state, as they |
| 20610 // needed/useful/requested. |
| 20611 DIMENSIONS: { |
| 20612 type: Array, |
| 20613 value: function(){ |
| 20614 return ["android_devices", "cores", "cpu", "device_type", |
| 20615 "device_os", "gpu", "id", "os", "pool"]; |
| 20616 }, |
| 20617 }, |
| 20618 DIMENSIONS_WITH_ALIASES: { |
| 20619 type: Array, |
| 20620 value: function(){ |
| 20621 return ["device_type", "gpu"]; |
| 20622 }, |
| 20623 }, |
| 20624 BOT_PROPERTIES: { |
| 20625 type: Array, |
| 20626 value: function() { |
| 20627 return ["disk_space", "task", "status"]; |
| 20628 } |
| 20629 }, |
| 20630 }, |
| 20631 |
| 20632 _androidAlias: function(dt) { |
| 20633 var a = ANDROID_ALIASES[dt]; |
| 20634 if (!a) { |
| 20635 return UNKNOWN; |
| 20636 } |
| 20637 return a; |
| 20638 }, |
| 20639 |
| 20640 // _applyAlias is the consistent way to modify a string to show its alias. |
| 20641 _applyAlias: function(orig, alias) { |
| 20642 return alias +" ("+orig+")"; |
| 20643 }, |
| 20644 |
| 20645 // _attribute looks first in dimension and then in state for the |
| 20646 // specified attribute. This will always return an array. If there is |
| 20647 // no matching attribute, ["unknown"] will be returned. |
| 20648 _attribute: function(bot, attr, none) { |
| 20649 none = none || UNKNOWN; |
| 20650 return this._dimension(bot, attr) || this._state(bot, attr) || [none]; |
| 20651 }, |
| 20652 |
| 20653 _devices: function(bot) { |
| 20654 var devices = []; |
| 20655 var d = (bot && bot.state && bot.state.devices) || {}; |
| 20656 // state.devices is like {Serial:Object}, so we need to keep the serial |
| 20657 for (key in d) { |
| 20658 var o = d[key]; |
| 20659 o.serial = key; |
| 20660 o.okay = (o.state === AVAILABLE); |
| 20661 devices.push(o); |
| 20662 } |
| 20663 return devices; |
| 20664 }, |
| 20665 |
| 20666 // _deviceType returns the codename of a given Android device. |
| 20667 _deviceType: function(device) { |
| 20668 if (!device || !device.build) { |
| 20669 return UNKNOWN; |
| 20670 } |
| 20671 var t = device.build["build.product"] || device.build["product.board"] |
| |
| 20672 device.build["product.device"] || UNKNOWN; |
| 20673 return t.toLowerCase(); |
| 20674 }, |
| 20675 |
| 20676 // _dimension returns the given dimension of a bot. If it is defined, it |
| 20677 // is an array of strings. |
| 20678 _dimension: function(bot, dim) { |
| 20679 if (!bot || !bot.dimensions || !dim) { |
| 20680 return undefined; |
| 20681 } |
| 20682 for (var i = 0; i < bot.dimensions.length; i++) { |
| 20683 if (bot.dimensions[i].key === dim) { |
| 20684 return bot.dimensions[i].value; |
| 20685 } |
| 20686 } |
| 20687 return undefined; |
| 20688 }, |
| 20689 |
| 20690 _gpuAlias: function(gpu) { |
| 20691 var a = GPU_ALIASES[gpu]; |
| 20692 if (!a) { |
| 20693 return UNKNOWN; |
| 20694 } |
| 20695 return a; |
| 20696 }, |
| 20697 |
| 20698 _not: function(a) { |
| 20699 return !a; |
| 20700 }, |
| 20701 |
| 20702 _or: function() { |
| 20703 var result = false; |
| 20704 // can't use .foreach, as arguments isn't really a function. |
| 20705 for (var i = 0; i < arguments.length; i++) { |
| 20706 result = result || arguments[i]; |
| 20707 } |
| 20708 return result; |
| 20709 }, |
| 20710 |
| 20711 // _state returns the requested attribute from a bot's state. |
| 20712 // For consistency with _dimension, if the attribute is not an array, |
| 20713 // it is put as theonly element in an array. |
| 20714 _state: function(bot, attr) { |
| 20715 if (!bot || !bot.state || !bot.state[attr]) { |
| 20716 return undefined |
| 20717 } |
| 20718 var state = bot.state[attr]; |
| 20719 if (Array.isArray(state)) { |
| 20720 return state; |
| 20721 } |
| 20722 return [state]; |
| 20723 }, |
| 20724 |
| 20725 _taskId: function(bot) { |
| 20726 if (bot && bot.task_id) { |
| 20727 return bot.task_id; |
| 20728 } |
| 20729 return "idle"; |
| 20730 }, |
| 20731 |
| 20732 // _unalias will return the base dimension/state with its alias removed |
| 20733 // if it had one. This is handy for sorting and filtering. |
| 20734 _unalias: function(str) { |
| 20735 var match = ALIAS_REGEXP.exec(str); |
| 20736 if (match) { |
| 20737 return match[1]; |
| 20738 } |
| 20739 return str; |
| 20740 }, |
| 20741 } |
| 20742 })() |
| 20743 </script> |
| 20557 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> | 20744 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> |
| 20558 <template> | 20745 <template> |
| 20559 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
ning"> | 20746 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
ning"> |
| 20560 :host { | 20747 :host { |
| 20561 display: block; | 20748 display: block; |
| 20562 font-family: sans-serif; | 20749 font-family: sans-serif; |
| 20563 } | 20750 } |
| 20564 #filter { | 20751 #filter { |
| 20565 margin:0 5px; | 20752 margin:0 5px; |
| 20566 } | 20753 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20685 </div> | 20872 </div> |
| 20686 | 20873 |
| 20687 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> | 20874 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> |
| 20688 </div> | 20875 </div> |
| 20689 | 20876 |
| 20690 </div> | 20877 </div> |
| 20691 | 20878 |
| 20692 </template> | 20879 </template> |
| 20693 <script> | 20880 <script> |
| 20694 (function(){ | 20881 (function(){ |
| 20695 var FILTER_SEP = " | "; | 20882 var FILTER_SEP = ":"; |
| 20696 // filterMap is a map of primary -> function. The function returns a | 20883 // filterMap is a map of primary -> function. The function returns a |
| 20697 // boolean "does the bot (first arg) match the second argument". These | 20884 // boolean "does the bot (first arg) match the second argument". These |
| 20698 // functions will have "this" be the botlist, and will have access to all | 20885 // functions will have "this" be the botlist, and will have access to all |
| 20699 // functions defined in bot-list and bot-list-shared. | 20886 // functions defined in bot-list and bot-list-shared. |
| 20700 var filterMap = { | 20887 var filterMap = { |
| 20701 cores: function(bot, cores){ | 20888 android_devices: function(bot, num) { |
| 20702 var o = this._cores(bot); | 20889 var o = this._attribute(bot, "android_devices", "0"); |
| 20890 return o.indexOf(num) !== -1; |
| 20891 }, |
| 20892 cores: function(bot, cores) { |
| 20893 var o = this._attribute(bot, "cores"); |
| 20703 return o.indexOf(cores) !== -1; | 20894 return o.indexOf(cores) !== -1; |
| 20704 }, | 20895 }, |
| 20705 cpu: function(bot, cpu){ | 20896 cpu: function(bot, cpu) { |
| 20706 var o = this._dimension(bot, "cpu") || ["none"]; | 20897 var o = this._attribute(bot, "cpu"); |
| 20707 return o.indexOf(cpu) !== -1; | 20898 return o.indexOf(cpu) !== -1; |
| 20708 }, | 20899 }, |
| 20709 devices: function(bot, device){ | 20900 device_os: function(bot, os) { |
| 20710 if (device === "none") { | 20901 var o = this._attribute(bot, "device_os", "none"); |
| 20711 return this._devices(bot).length === 0; | 20902 return o.indexOf(os) !== -1; |
| 20712 } | |
| 20713 // extract the deviceType, if it is not "unknown". | |
| 20714 device = this._unalias(device); | |
| 20715 var found = false; | |
| 20716 this._devices(bot).forEach(function(d) { | |
| 20717 if (this._deviceType(d) === device) { | |
| 20718 found = true; | |
| 20719 } | |
| 20720 }.bind(this)); | |
| 20721 return found; | |
| 20722 }, | 20903 }, |
| 20723 gpu: function(bot, gpu){ | 20904 device_type: function(bot, dt) { |
| 20724 var o = this._dimension(bot, "gpu") || ["none"]; | 20905 var o = this._attribute(bot, "device_type", "none"); |
| 20906 return o.indexOf(this._unalias(dt)) !== -1; |
| 20907 }, |
| 20908 disk_space: function(bot, space) { |
| 20909 return true; |
| 20910 }, |
| 20911 gpu: function(bot, gpu) { |
| 20912 var o = this._attribute(bot, "gpu", "none"); |
| 20725 return o.indexOf(this._unalias(gpu)) !== -1; | 20913 return o.indexOf(this._unalias(gpu)) !== -1; |
| 20726 }, | 20914 }, |
| 20727 id: function(bot, id) { | 20915 id: function(bot, id) { |
| 20728 return bot.bot_id === id; | 20916 return true; |
| 20729 }, | 20917 }, |
| 20730 os: function(bot, os){ | 20918 os: function(bot, os) { |
| 20731 var o = this._dimension(bot, "os") || ["Unknown"]; | 20919 var o = this._attribute(bot, "os"); |
| 20732 return o.indexOf(os) !== -1; | 20920 return o.indexOf(os) !== -1; |
| 20733 }, | 20921 }, |
| 20734 pool: function(bot, pool){ | 20922 pool: function(bot, pool) { |
| 20735 var o = this._dimension(bot, "pool") || ["Unknown"]; | 20923 var o = this._attribute(bot, "pool"); |
| 20736 return o.indexOf(pool) !== -1; | 20924 return o.indexOf(pool) !== -1; |
| 20737 }, | 20925 }, |
| 20738 status: function(bot, status){ | 20926 status: function(bot, status) { |
| 20739 if (status === "quarantined") { | 20927 if (status === "quarantined") { |
| 20740 return bot.quarantined; | 20928 return bot.quarantined; |
| 20741 } else if (status === "dead") { | 20929 } else if (status === "dead") { |
| 20742 return bot.is_dead; | 20930 return bot.is_dead; |
| 20743 } else { | 20931 } else { |
| 20744 // Status must be "available". | 20932 // Status must be "available". |
| 20745 return !bot.quarantined && !bot.is_dead; | 20933 return !bot.quarantined && !bot.is_dead; |
| 20746 } | 20934 } |
| 20747 }, | 20935 }, |
| 20748 task: function(bot, task) { | 20936 task: function(bot, task) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20781 }; | 20969 }; |
| 20782 } | 20970 } |
| 20783 } | 20971 } |
| 20784 return { | 20972 return { |
| 20785 idx: -1, | 20973 idx: -1, |
| 20786 }; | 20974 }; |
| 20787 }; | 20975 }; |
| 20788 | 20976 |
| 20789 Polymer({ | 20977 Polymer({ |
| 20790 is: "bot-filters", | 20978 is: "bot-filters", |
| 20979 |
| 20980 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 20981 |
| 20791 properties: { | 20982 properties: { |
| 20792 // input | 20983 // input |
| 20793 primary_map: { | 20984 primary_map: { |
| 20794 type: Object, | 20985 type: Object, |
| 20795 }, | 20986 }, |
| 20796 primary_arr: { | 20987 primary_arr: { |
| 20797 type: Array, | 20988 type: Array, |
| 20798 }, | 20989 }, |
| 20799 | 20990 |
| 20800 // output | 20991 // output |
| 20801 columns: { | 20992 columns: { |
| 20802 type: Array, | 20993 type: Array, |
| 20803 value: function() { | 20994 value: function() { |
| 20804 // TODO(kjlubick) back these up to URL params and load them from | 20995 // TODO(kjlubick) back these up to URL params and load them from |
| 20805 // there on reload. | 20996 // there on reload. |
| 20806 return ["id","os","task","status"]; | 20997 return ["id","os","task","status"]; |
| 20807 }, | 20998 }, |
| 20808 notify: true, | 20999 notify: true, |
| 20809 }, | 21000 }, |
| 21001 dimensions: { |
| 21002 type: Array, |
| 21003 computed: "_extractDimensions(DIMENSIONS.*,_filters.*)", |
| 21004 notify: true, |
| 21005 }, |
| 20810 filter: { | 21006 filter: { |
| 20811 type: Object, | 21007 type: Object, |
| 20812 computed: "_makeFilter(_filters.*)", | 21008 computed: "_makeFilter(_filters.*)", |
| 20813 notify: true, | 21009 notify: true, |
| 20814 }, | 21010 }, |
| 20815 verbose: { | 21011 verbose: { |
| 20816 type: Boolean, | 21012 type: Boolean, |
| 20817 value: false, | 21013 value: false, |
| 20818 notify: true, | 21014 notify: true, |
| 20819 }, | 21015 }, |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21025 }, | 21221 }, |
| 21026 | 21222 |
| 21027 _afterBold: function(item, query) { | 21223 _afterBold: function(item, query) { |
| 21028 var match = matchPartCaseInsensitive(item, query); | 21224 var match = matchPartCaseInsensitive(item, query); |
| 21029 if (match.idx === -1) { | 21225 if (match.idx === -1) { |
| 21030 return ""; | 21226 return ""; |
| 21031 } | 21227 } |
| 21032 return item.substring(match.idx + match.part.length); | 21228 return item.substring(match.idx + match.part.length); |
| 21033 }, | 21229 }, |
| 21034 | 21230 |
| 21231 _extractDimensions: function() { |
| 21232 var dims = [] |
| 21233 this._filters.forEach(function(f) { |
| 21234 var split = f.split(FILTER_SEP, 1) |
| 21235 var col = split[0]; |
| 21236 if (this.DIMENSIONS.indexOf(col) !== -1) { |
| 21237 var rest = f.substring(col.length + FILTER_SEP.length); |
| 21238 dims.push(col + FILTER_SEP + this._unalias(rest)) |
| 21239 }; |
| 21240 }.bind(this)); |
| 21241 return dims; |
| 21242 } |
| 21243 |
| 21035 }); | 21244 }); |
| 21036 })(); | 21245 })(); |
| 21037 </script> | 21246 </script> |
| 21038 </dom-module><script> | 21247 </dom-module><dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> |
| 21039 | |
| 21040 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; | |
| 21041 (function(){ | |
| 21042 var ANDROID_ALIASES = { | |
| 21043 "bullhead": "Nexus 5X", | |
| 21044 "flo": "Nexus 7", | |
| 21045 "hammerhead": "Nexus 5", | |
| 21046 "mako": "Nexus 4", | |
| 21047 "shamu": "Nexus 6", | |
| 21048 }; | |
| 21049 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html | |
| 21050 var BATTERY_HEALTH_UNKNOWN = 1; | |
| 21051 var BATTERY_HEALTH_GOOD = 2; | |
| 21052 var BATTERY_STATUS_CHARGING = 2; | |
| 21053 | |
| 21054 var UNAUTHENTICATED = "unauthenticated"; | |
| 21055 var AVAILABLE = "available"; | |
| 21056 | |
| 21057 var GPU_ALIASES = { | |
| 21058 "1002": "AMD", | |
| 21059 "1002:6779": "AMD Radeon HD 6450/7450/8450", | |
| 21060 "1002:6821": "AMD Radeon HD 8870M", | |
| 21061 "102b": "Matrox", | |
| 21062 "102b:0522": "Matrox MGA G200e", | |
| 21063 "102b:0532": "Matrox MGA G200eW", | |
| 21064 "102b:0534": "Matrox G200eR2", | |
| 21065 "10de": "NVIDIA", | |
| 21066 "10de:08aa": "NVIDIA GeForce 320M", | |
| 21067 "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", | |
| 21068 "10de:104a": "NVIDIA GeForce GT 610", | |
| 21069 "10de:11c0": "NVIDIA GeForce GTX 660", | |
| 21070 "10de:1244": "NVIDIA GeForce GTX 550 Ti", | |
| 21071 "10de:1401": "NVIDIA GeForce GTX 960", | |
| 21072 "8086": "Intel", | |
| 21073 "8086:041a": "Intel Xeon Integrated", | |
| 21074 "8086:0a2e": "Intel Haswell Integrated", | |
| 21075 "8086:0d26": "Intel Crystal Well Integrated", | |
| 21076 } | |
| 21077 | |
| 21078 // For consistency, all aliases are displayed like: | |
| 21079 // Nexus 5X (bullhead) | |
| 21080 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. | |
| 21081 var ALIAS_REGEXP = /.+ \((.*)\)/; | |
| 21082 | |
| 21083 // This behavior wraps up all the shared bot-list functionality. | |
| 21084 SwarmingBehaviors.BotListBehavior = { | |
| 21085 | |
| 21086 _androidAlias: function(device) { | |
| 21087 if (device.notReady) { | |
| 21088 return UNAUTHENTICATED.toUpperCase(); | |
| 21089 } | |
| 21090 var t = this._deviceType(device); | |
| 21091 var a = ANDROID_ALIASES[t]; | |
| 21092 if (!a) { | |
| 21093 return "UNKNOWN"; | |
| 21094 } | |
| 21095 return a; | |
| 21096 }, | |
| 21097 | |
| 21098 // _applyAlias is the consistent way to modify a string to show its alias. | |
| 21099 _applyAlias: function(orig, alias) { | |
| 21100 return alias +" ("+orig+")"; | |
| 21101 }, | |
| 21102 | |
| 21103 _cores: function(bot) { | |
| 21104 // For whatever reason, sometimes cores are in dimensions and sometimes | |
| 21105 // they are in state, but never both. | |
| 21106 var c = (bot && bot.state && bot.state.cores); | |
| 21107 if (c && c.length > 0) { | |
| 21108 return c; | |
| 21109 } | |
| 21110 c = this._dimension(bot, "cores") || ["Unknown"]; | |
| 21111 return c; | |
| 21112 }, | |
| 21113 | |
| 21114 _devices: function(bot) { | |
| 21115 var devices = []; | |
| 21116 var d = (bot && bot.state && bot.state.devices) || {}; | |
| 21117 // state.devices is like {Serial:Object}, so we need to keep the serial | |
| 21118 for (key in d) { | |
| 21119 var o = d[key]; | |
| 21120 o.serial = key; | |
| 21121 o.okay = (o.state === AVAILABLE); | |
| 21122 devices.push(o); | |
| 21123 } | |
| 21124 return devices; | |
| 21125 }, | |
| 21126 | |
| 21127 // _deviceType returns the codename of a given Android device. | |
| 21128 _deviceType: function(device) { | |
| 21129 if (!device || !device.build) { | |
| 21130 return "unknown"; | |
| 21131 } | |
| 21132 var t = device.build["build.product"] || device.build["product.board"] |
| | |
| 21133 device.build["product.device"] || "unknown"; | |
| 21134 return t.toLowerCase(); | |
| 21135 }, | |
| 21136 | |
| 21137 // _dimension returns the given dimension of a bot. If it is defined, it | |
| 21138 // is typically an array of strings. | |
| 21139 _dimension: function(bot, dim) { | |
| 21140 if (!bot || !bot.dimensions || !dim) { | |
| 21141 return undefined; | |
| 21142 } | |
| 21143 for (var i = 0; i < bot.dimensions.length; i++) { | |
| 21144 if (bot.dimensions[i].key === dim) { | |
| 21145 return bot.dimensions[i].value; | |
| 21146 } | |
| 21147 } | |
| 21148 return undefined; | |
| 21149 }, | |
| 21150 | |
| 21151 _gpuAlias: function(gpu) { | |
| 21152 var a = GPU_ALIASES[gpu]; | |
| 21153 if (!a) { | |
| 21154 return "UNKNOWN"; | |
| 21155 } | |
| 21156 return a; | |
| 21157 }, | |
| 21158 | |
| 21159 _not: function(a) { | |
| 21160 return !a; | |
| 21161 }, | |
| 21162 | |
| 21163 _or: function() { | |
| 21164 var result = false; | |
| 21165 // can't use .foreach, as arguments isn't really a function. | |
| 21166 for (var i = 0; i < arguments.length; i++) { | |
| 21167 result = result || arguments[i]; | |
| 21168 } | |
| 21169 return result; | |
| 21170 }, | |
| 21171 | |
| 21172 _taskId: function(bot) { | |
| 21173 if (bot && bot.task_id) { | |
| 21174 return bot.task_id; | |
| 21175 } | |
| 21176 return "idle"; | |
| 21177 }, | |
| 21178 | |
| 21179 // _unalias will return the base dimension/state with its alias removed | |
| 21180 // if it had one. This is handy for sorting and filtering. | |
| 21181 _unalias: function(str) { | |
| 21182 var match = ALIAS_REGEXP.exec(str); | |
| 21183 if (match) { | |
| 21184 return match[1]; | |
| 21185 } | |
| 21186 return str; | |
| 21187 }, | |
| 21188 } | |
| 21189 })() | |
| 21190 </script> | |
| 21191 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> | |
| 21192 <template> | 21248 <template> |
| 21193 <iron-ajax id="botlist" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" handle-as="json" last-response="{{_list}}" loading="{{_busy1}}"> | 21249 <iron-ajax id="botlist" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" params="[[_botlistParams(dimensions.*)]]" handle-as="json" last-resp
onse="{{_list}}" loading="{{_busy1}}"> |
| 21194 </iron-ajax> | 21250 </iron-ajax> |
| 21195 | 21251 |
| 21196 <iron-ajax id="fleet" url="/_ah/api/swarming/v1/bots/count" headers="[[auth_
headers]]" handle-as="json" last-response="{{_count}}" loading="{{_busy2}}"> | 21252 <iron-ajax id="dimensions" url="/_ah/api/swarming/v1/bots/dimensions" header
s="[[auth_headers]]" handle-as="json" last-response="{{_dimensions}}" loading="{
{_busy2}}"> |
| 21253 </iron-ajax> |
| 21254 |
| 21255 <iron-ajax id="fleet" url="/_ah/api/swarming/v1/bots/count" headers="[[auth_
headers]]" handle-as="json" last-response="{{_count}}" loading="{{_busy3}}"> |
| 21197 </iron-ajax> | 21256 </iron-ajax> |
| 21198 </template> | 21257 </template> |
| 21199 <script> | 21258 <script> |
| 21200 (function(){ | 21259 (function(){ |
| 21201 // TODO(kjlubick): Add more of these as well as things from state | 21260 |
| 21202 // i.e. disk space remaining. | |
| 21203 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; | |
| 21204 // "gpu" and "devices" are added separately because we need to | |
| 21205 // deal with aliases. | |
| 21206 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; | |
| 21207 Polymer({ | 21261 Polymer({ |
| 21208 is: 'bot-list-data', | 21262 is: 'bot-list-data', |
| 21209 | 21263 |
| 21210 behaviors: [SwarmingBehaviors.BotListBehavior], | 21264 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21211 | 21265 |
| 21212 properties: { | 21266 properties: { |
| 21213 // inputs | 21267 // inputs |
| 21214 auth_headers: { | 21268 auth_headers: { |
| 21215 type: Object, | 21269 type: Object, |
| 21216 observer: "signIn", | 21270 observer: "signIn", |
| 21217 }, | 21271 }, |
| 21272 dimensions: { |
| 21273 type: Array, |
| 21274 }, |
| 21218 | 21275 |
| 21219 //outputs | 21276 //outputs |
| 21220 bots: { | 21277 bots: { |
| 21221 type: Array, | 21278 type: Array, |
| 21222 computed: "_bots(_list)", | 21279 computed: "_bots(_list)", |
| 21223 notify: true, | 21280 notify: true, |
| 21224 }, | 21281 }, |
| 21225 busy: { | 21282 busy: { |
| 21226 type: Boolean, | 21283 type: Boolean, |
| 21227 computed: "_or(_busy1,_busy2)", | 21284 computed: "_or(_busy1,_busy2,_busy3)", |
| 21228 notify: true, | 21285 notify: true, |
| 21229 }, | 21286 }, |
| 21230 fleet: { | 21287 fleet: { |
| 21231 type: Object, | 21288 type: Object, |
| 21232 computed: "_fleet(_count)", | 21289 computed: "_fleet(_count)", |
| 21233 notify: true, | 21290 notify: true, |
| 21234 }, | 21291 }, |
| 21235 primary_map: { | 21292 primary_map: { |
| 21236 type:Object, | 21293 type:Object, |
| 21237 computed: "_primaryMap(bots)", | 21294 computed: "_primaryMap(_dimensions)", |
| 21238 notify: true, | 21295 notify: true, |
| 21239 }, | 21296 }, |
| 21240 primary_arr: { | 21297 primary_arr: { |
| 21241 type:Array, | 21298 type: Array, |
| 21242 value: function() { | 21299 // DIMENSIONS and BOT_PROPERTIES are inherited from BotListBehavior |
| 21243 return DIMENSIONS.concat(BOT_PROPERTIES); | 21300 computed: "_primaryArr(DIMENSIONS, BOT_PROPERTIES)", |
| 21244 }, | |
| 21245 notify: true, | 21301 notify: true, |
| 21246 }, | 21302 }, |
| 21247 | 21303 |
| 21248 // private | 21304 // private |
| 21249 _count: { | 21305 _count: { |
| 21250 type: Object, | 21306 type: Object, |
| 21251 }, | 21307 }, |
| 21308 _dimensions: { |
| 21309 type: Object, |
| 21310 }, |
| 21252 _list: { | 21311 _list: { |
| 21253 type: Object, | 21312 type: Object, |
| 21254 }, | 21313 }, |
| 21255 }, | 21314 }, |
| 21256 | 21315 |
| 21257 signIn: function(){ | 21316 signIn: function(){ |
| 21258 this.$.botlist.generateRequest(); | 21317 this.$.botlist.auto = true; |
| 21259 this.$.fleet.generateRequest(); | 21318 this.$.dimensions.auto = true; |
| 21319 this.$.fleet.auto = true; |
| 21320 }, |
| 21321 |
| 21322 _botlistParams: function() { |
| 21323 if (!this.dimensions) { |
| 21324 return {}; |
| 21325 } |
| 21326 return { |
| 21327 dimensions: this.dimensions, |
| 21328 }; |
| 21260 }, | 21329 }, |
| 21261 | 21330 |
| 21262 _bots: function(){ | 21331 _bots: function(){ |
| 21263 if (!this._list || !this._list.items) { | 21332 if (!this._list || !this._list.items) { |
| 21264 return []; | 21333 return []; |
| 21265 } | 21334 } |
| 21266 this._list.items.forEach(function(o){ | 21335 // Do any preprocessing here |
| 21267 o.state = JSON.parse(o.state); | 21336 this._list.items.forEach(function(bot){ |
| 21337 // Parse the state, which is a JSON string. This contains a lot of |
| 21338 // interesting information like details about the devices attached. |
| 21339 bot.state = JSON.parse(bot.state); |
| 21340 // get the disks in an easier to deal with format, sorted by size. |
| 21341 var disks = bot.state["disks"]; |
| 21342 var keys = Object.keys(disks); |
| 21343 if (!keys || !keys.length) { |
| 21344 bot.disks = [{"id": "unknown", "mb": 0}]; |
| 21345 } else { |
| 21346 bot.disks = []; |
| 21347 for (var i = 0; i < keys.length; i++) { |
| 21348 bot.disks.push({"id":keys[i], "mb":disks[keys[i]].free_mb}); |
| 21349 } |
| 21350 // Sort these so the biggest disk comes first. |
| 21351 bot.disks.sort(function(a, b) { |
| 21352 return b.mb - a.mb; |
| 21353 }); |
| 21354 } |
| 21355 |
| 21268 }); | 21356 }); |
| 21269 return this._list.items; | 21357 return this._list.items; |
| 21270 }, | 21358 }, |
| 21271 | 21359 |
| 21272 _fleet: function() { | 21360 _fleet: function() { |
| 21273 if (!this._count) { | 21361 if (!this._count) { |
| 21274 return {}; | 21362 return {}; |
| 21275 } | 21363 } |
| 21276 return { | 21364 return { |
| 21277 alive: this._count.count || -1, | 21365 alive: this._count.count || -1, |
| 21278 busy: this._count.busy || -1, | 21366 busy: this._count.busy || -1, |
| 21279 idle: this._count.count && this._count.busy && | 21367 idle: this._count.count && this._count.busy && |
| 21280 this._count.count - this._count.busy, | 21368 this._count.count - this._count.busy, |
| 21281 dead: this._count.dead || -1, | 21369 dead: this._count.dead || -1, |
| 21282 quarantined: this._count.quarantined || -1, | 21370 quarantined: this._count.quarantined || -1, |
| 21283 } | 21371 } |
| 21284 }, | 21372 }, |
| 21285 | 21373 |
| 21286 _primaryMap: function(bots){ | 21374 _primaryArr: function(dimensions, properties) { |
| 21375 return dimensions.concat(properties); |
| 21376 }, |
| 21377 _primaryMap: function(dimensions){ |
| 21287 // map will keep track of dimensions that we have seen at least once. | 21378 // map will keep track of dimensions that we have seen at least once. |
| 21288 // This will then basically get turned into an array to be used for | 21379 // This will then basically get turned into an array to be used for |
| 21289 // filtering. | 21380 // filtering. |
| 21290 var map = {}; | 21381 dimensions = dimensions.bots_dimensions; |
| 21291 DIMENSIONS.forEach(function(p){ | |
| 21292 map[p] = {}; | |
| 21293 }); | |
| 21294 map["devices"] = {}; | |
| 21295 map["gpu"] = {}; | |
| 21296 bots.forEach(function(b){ | |
| 21297 DIMENSIONS.forEach(function(d){ | |
| 21298 var dims = this._dimension(b, d) || []; | |
| 21299 dims.forEach(function(e){ | |
| 21300 map[d][e] = true; | |
| 21301 }); | |
| 21302 }.bind(this)); | |
| 21303 | 21382 |
| 21304 // Add Android devices and their aliases | 21383 var pMap = {}; |
| 21305 this._devices(b).forEach(function(d){ | 21384 dimensions.forEach(function(d){ |
| 21306 var dt = this._deviceType(d); | 21385 if (this.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) { |
| 21307 var alias = this._androidAlias(d); | 21386 // value is an array of the values the |
| 21308 if (dt !== "unknown") { | 21387 pMap[d.key] = d.value; |
| 21309 dt = this._applyAlias(dt,alias); | 21388 } else if (d.key === "gpu") { |
| 21310 } | 21389 var gpus = []; |
| 21311 map["devices"][dt] = true; | 21390 d.value.forEach(function(g){ |
| 21312 }.bind(this)); | 21391 var alias = this._gpuAlias(g); |
| 21313 map["devices"]["none"] = true; | 21392 if (alias !== "unknown") { |
| 21314 | 21393 gpus.push(this._applyAlias(g, alias)); |
| 21315 // Add GPUs and their aliases | 21394 } else { |
| 21316 var gpus = this._dimension(b, "gpu") || []; | 21395 gpus.push(g); |
| 21317 gpus.forEach(function(g){ | 21396 } |
| 21318 var alias = this._gpuAlias(g); | 21397 }.bind(this)); |
| 21319 if (alias !== "UNKNOWN") { | 21398 pMap["gpu"] = gpus; |
| 21320 map["gpu"][this._applyAlias(g, alias)] = true; | 21399 } else if (d.key === "device_type") { |
| 21321 } else { | 21400 var devs = []; |
| 21322 map["gpu"][g] = true; | 21401 d.value.forEach(function(dt){ |
| 21323 } | 21402 var alias = this._androidAlias(dt); |
| 21324 | 21403 if (alias !== "unknown") { |
| 21325 }.bind(this)); | 21404 devs.push(this._applyAlias(dt, alias)); |
| 21405 } else { |
| 21406 devs.push(dt); |
| 21407 } |
| 21408 }.bind(this)); |
| 21409 pMap["device_type"] = devs; |
| 21410 } else { |
| 21411 console.log("Unknown alias type: ", d); |
| 21412 } |
| 21326 }.bind(this)); | 21413 }.bind(this)); |
| 21327 | 21414 |
| 21328 // Turn the Map<Object,Map<Boolean>> into a Map<Object,Array<String>> | 21415 // Add some options that might not show up. |
| 21329 // with all of the secondary elements sorted appropriately. | 21416 pMap["android_devices"].push("0"); |
| 21330 var pMap = {}; | 21417 pMap["device_os"].push("none"); |
| 21331 for (key in map){ | 21418 pMap["device_type"].push("none"); |
| 21332 pMap[key] = Object.keys(map[key]).sort(swarming.naturalCompare); | 21419 |
| 21333 } | 21420 pMap["id"] = []; |
| 21334 | 21421 |
| 21335 // Create custom filter options | 21422 // Create custom filter options |
| 21423 pMap["disk_space"] = []; |
| 21336 pMap["task"] = ["busy", "idle"]; | 21424 pMap["task"] = ["busy", "idle"]; |
| 21337 pMap["status"] = ["available", "dead", "quarantined"]; | 21425 pMap["status"] = ["available", "dead", "quarantined"]; |
| 21426 |
| 21427 // No need to sort any of this, bot-filters sorts secondary items |
| 21428 // automatically, especially when the user types a query. |
| 21338 return pMap; | 21429 return pMap; |
| 21339 }, | 21430 }, |
| 21340 | 21431 |
| 21341 }); | 21432 }); |
| 21342 })(); | 21433 })(); |
| 21343 </script> | 21434 </script> |
| 21344 </dom-module><dom-module id="bot-list-summary" assetpath="/res/imp/botlist/"> | 21435 </dom-module><dom-module id="bot-list-summary" assetpath="/res/imp/botlist/"> |
| 21345 <template> | 21436 <template> |
| 21346 <style include="swarming-app-style"> | 21437 <style include="swarming-app-style"> |
| 21347 :host { | 21438 :host { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21518 </style> | 21609 </style> |
| 21519 | 21610 |
| 21520 <swarming-app auth_headers="{{_auth_headers}}" signed_in="{{_signed_in}}" bu
sy="[[_busy]]" name="Swarming Bot List"> | 21611 <swarming-app auth_headers="{{_auth_headers}}" signed_in="{{_signed_in}}" bu
sy="[[_busy]]" name="Swarming Bot List"> |
| 21521 | 21612 |
| 21522 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> | 21613 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> |
| 21523 | 21614 |
| 21524 <div hidden$="[[_not(_signed_in)]]"> | 21615 <div hidden$="[[_not(_signed_in)]]"> |
| 21525 | 21616 |
| 21526 <div class="horizontal layout"> | 21617 <div class="horizontal layout"> |
| 21527 | 21618 |
| 21528 <bot-filters primary_map="[[_primary_map]]" primary_arr="[[_primary_ar
r]]" columns="{{_columns}}" filter="{{_filter}}" verbose="{{_verbose}}"> | 21619 <bot-filters primary_map="[[_primary_map]]" primary_arr="[[_primary_ar
r]]" columns="{{_columns}}" dimensions="{{_dimensions}}" filter="{{_filter}}" ve
rbose="{{_verbose}}"> |
| 21529 </bot-filters> | 21620 </bot-filters> |
| 21530 | 21621 |
| 21531 <bot-list-summary fleet="[[_fleet]]" filtered_bots="[[_filteredSortedB
ots]]"> | 21622 <bot-list-summary fleet="[[_fleet]]" filtered_bots="[[_filteredSortedB
ots]]"> |
| 21532 </bot-list-summary> | 21623 </bot-list-summary> |
| 21533 | 21624 |
| 21534 </div> | 21625 </div> |
| 21535 | 21626 |
| 21536 <bot-list-data auth_headers="[[_auth_headers]]" bots="{{_bots}}" busy="{
{_busy}}" fleet="{{_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_prim
ary_arr}}"> | 21627 <bot-list-data auth_headers="[[_auth_headers]]" dimensions="[[_dimension
s]]" bots="{{_bots}}" busy="{{_busy}}" fleet="{{_fleet}}" primary_map="{{_primar
y_map}}" primary_arr="{{_primary_arr}}"> |
| 21537 </bot-list-data> | 21628 </bot-list-data> |
| 21538 | 21629 |
| 21539 <table class="bot-list"> | 21630 <table class="bot-list"> |
| 21540 <thead on-sort_change="_sortChange"> | 21631 <thead on-sort_change="_sortChange"> |
| 21541 | 21632 |
| 21542 <tr> | 21633 <tr> |
| 21543 <th> | 21634 <th> |
| 21544 <span>Bot Id</span> | 21635 <span>Bot Id</span> |
| 21545 <sort-toggle name="id" current="[[_sort]]"> | 21636 <sort-toggle name="id" current="[[_sort]]"> |
| 21546 </sort-toggle> | 21637 </sort-toggle> |
| (...skipping 28 matching lines...) Expand all Loading... |
| 21575 </td> | 21666 </td> |
| 21576 | 21667 |
| 21577 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> | 21668 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> |
| 21578 <td hidden$="[[_hide(c)]]"> | 21669 <td hidden$="[[_hide(c)]]"> |
| 21579 [[_column(c, bot, _verbose)]] | 21670 [[_column(c, bot, _verbose)]] |
| 21580 </td> | 21671 </td> |
| 21581 </template> | 21672 </template> |
| 21582 | 21673 |
| 21583 </tr> | 21674 </tr> |
| 21584 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> | 21675 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> |
| 21585 <tr hidden$="[[_hide('devices', _columns.*)]]" class$="[[_device
Class(device)]]"> | 21676 <tr hidden$="[[_hide('android_devices', _columns.*)]]" class$="[
[_deviceClass(device)]]"> |
| 21586 <td></td> | 21677 <td></td> |
| 21587 <td hidden$="[[_hide('task', _columns.*)]]"></td> | 21678 <td hidden$="[[_hide('task', _columns.*)]]"></td> |
| 21588 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> | 21679 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> |
| 21589 <td hidden$="[[_hide(c)]]"> | 21680 <td hidden$="[[_hide(c)]]"> |
| 21590 [[_deviceColumn(c, device, _verbose)]] | 21681 [[_deviceColumn(c, device, _verbose)]] |
| 21591 </td> | 21682 </td> |
| 21592 </template> | 21683 </template> |
| 21593 </tr> | 21684 </tr> |
| 21594 </template> | 21685 </template> |
| 21595 </template> | 21686 </template> |
| 21596 </tbody> | 21687 </tbody> |
| 21597 </table> | 21688 </table> |
| 21598 </div> | 21689 </div> |
| 21599 | 21690 |
| 21600 </swarming-app> | 21691 </swarming-app> |
| 21601 | 21692 |
| 21602 </template> | 21693 </template> |
| 21603 <script> | 21694 <script> |
| 21604 (function(){ | 21695 (function(){ |
| 21605 var special_columns = ["id", "task"]; | 21696 var special_columns = ["id", "task"]; |
| 21606 | 21697 |
| 21607 var headerMap = { | 21698 var headerMap = { |
| 21608 // "id" and "task" are special, so they don't go here and have their | 21699 // "id" and "task" are special, so they don't go here and have their |
| 21609 // headers hard-coded below. | 21700 // headers hard-coded below. |
| 21701 "android_devices": "Android Devices", |
| 21610 "cores": "Cores", | 21702 "cores": "Cores", |
| 21611 "cpu": "CPU", | 21703 "cpu": "CPU", |
| 21612 "devices": "Devices", | 21704 "device_os": "Device OS", |
| 21705 "device_type": "Device Type", |
| 21706 "disk_space": "Free Space (MB)", |
| 21613 "gpu": "GPU", | 21707 "gpu": "GPU", |
| 21614 "os": "OS", | 21708 "os": "OS", |
| 21615 "pool": "Pool", | 21709 "pool": "Pool", |
| 21616 "status": "Status", | 21710 "status": "Status", |
| 21617 }; | 21711 }; |
| 21618 | 21712 |
| 21619 // This maps column name to a function that will return the content for a | 21713 // This maps column name to a function that will return the content for a |
| 21620 // given bot. These functions are bound to this element, and have access | 21714 // given bot. These functions are bound to this element, and have access |
| 21621 // to all functions defined here and in bot-list-shared. | 21715 // to all functions defined here and in bot-list-shared. |
| 21622 var columnMap = { | 21716 var columnMap = { |
| 21717 android_devices: function(bot) { |
| 21718 var devs = this._attribute(bot, "android_devices", "0"); |
| 21719 if (this._verbose) { |
| 21720 return devs.join(" | ") + " devices available"; |
| 21721 } |
| 21722 // max() works on strings as long as they can be coerced to Number. |
| 21723 return Math.max(...devs) + " devices available"; |
| 21724 }, |
| 21623 cores: function(bot){ | 21725 cores: function(bot){ |
| 21624 var cores = this._cores(bot); | 21726 var cores = this._attribute(bot, "cores"); |
| 21625 if (this._verbose){ | 21727 if (this._verbose){ |
| 21626 return cores.join(" | "); | 21728 return cores.join(" | "); |
| 21627 } | 21729 } |
| 21628 return cores[0]; | 21730 return cores[0]; |
| 21629 }, | 21731 }, |
| 21630 cpu: function(bot){ | 21732 cpu: function(bot){ |
| 21631 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; | 21733 var cpus = this._attribute(bot, "cpu"); |
| 21632 if (this._verbose){ | 21734 if (this._verbose){ |
| 21633 return cpus.join(" | "); | 21735 return cpus.join(" | "); |
| 21634 } | 21736 } |
| 21635 return cpus[0]; | 21737 return cpus[0]; |
| 21636 }, | 21738 }, |
| 21637 devices: function(bot){ | 21739 device_os: function(bot){ |
| 21638 return this._devices(bot).length + " devices attached"; | 21740 var os = this._attribute(bot, "device_os", "none"); |
| 21741 if (this._verbose) { |
| 21742 return os.join(" | "); |
| 21743 } |
| 21744 return os[0]; |
| 21745 }, |
| 21746 device_type: function(bot){ |
| 21747 var dt = this._attribute(bot, "device_type", "none"); |
| 21748 if (this._verbose) { |
| 21749 return dt.join(" | "); |
| 21750 } |
| 21751 return dt[0]; |
| 21752 }, |
| 21753 disk_space: function(bot) { |
| 21754 var aliased = []; |
| 21755 bot.disks.forEach(function(disk){ |
| 21756 var alias = swarming.humanBytes(disk.mb, swarming.MB); |
| 21757 aliased.push(this._applyAlias(disk.mb, disk.id + " "+ alias)); |
| 21758 }.bind(this)); |
| 21759 if (this._verbose) { |
| 21760 return aliased.join(" | "); |
| 21761 } |
| 21762 return aliased[0]; |
| 21639 }, | 21763 }, |
| 21640 gpu: function(bot){ | 21764 gpu: function(bot){ |
| 21641 var gpus = this._dimension(bot, 'gpu') | 21765 var gpus = this._attribute(bot, "gpu", "none") |
| 21642 if (!gpus) { | |
| 21643 return "none"; | |
| 21644 } | |
| 21645 var verbose = [] | 21766 var verbose = [] |
| 21646 var named = []; | 21767 var named = []; |
| 21647 // non-verbose mode has only the top level GPU info "e.g. NVidia" | 21768 // non-verbose mode has only the top level GPU info "e.g. NVidia" |
| 21648 // which is found by looking for gpu ids w/o a colon. | 21769 // which is found by looking for gpu ids w/o a colon. |
| 21649 gpus.forEach(function(g){ | 21770 gpus.forEach(function(g){ |
| 21650 var alias = this._gpuAlias(g); | 21771 var alias = this._gpuAlias(g); |
| 21651 if (alias === "UNKNOWN") { | 21772 if (alias === "unknown") { |
| 21652 verbose.push(g); | 21773 verbose.push(g); |
| 21653 if (g.indexOf(":") === -1) { | 21774 if (g.indexOf(":") === -1) { |
| 21654 named.push(g); | 21775 named.push(g); |
| 21655 } | 21776 } |
| 21656 return; | 21777 return; |
| 21657 } | 21778 } |
| 21658 verbose.push(this._applyAlias(g, alias)); | 21779 verbose.push(this._applyAlias(g, alias)); |
| 21659 if (g.indexOf(":") === -1) { | 21780 if (g.indexOf(":") === -1) { |
| 21660 named.push(this._applyAlias(g, alias)); | 21781 named.push(this._applyAlias(g, alias)); |
| 21661 } | 21782 } |
| 21662 }.bind(this)) | 21783 }.bind(this)) |
| 21663 if (this._verbose) { | 21784 if (this._verbose) { |
| 21664 return verbose.join(" | "); | 21785 return verbose.join(" | "); |
| 21665 } | 21786 } |
| 21666 return named.join(" | "); | 21787 return named.join(" | "); |
| 21667 }, | 21788 }, |
| 21668 id: function(bot) { | 21789 id: function(bot) { |
| 21669 return bot.bot_id; | 21790 return bot.bot_id; |
| 21670 }, | 21791 }, |
| 21671 os: function(bot) { | 21792 os: function(bot) { |
| 21672 var os = this._dimension(bot, 'os') || ['Unknown']; | 21793 var os = this._attribute(bot, "os"); |
| 21673 if (this._verbose){ | 21794 if (this._verbose){ |
| 21674 return os.join(" | "); | 21795 return os.join(" | "); |
| 21675 } | 21796 } |
| 21676 return os[0]; | 21797 return os[0]; |
| 21677 }, | 21798 }, |
| 21678 pool: function(bot) { | 21799 pool: function(bot) { |
| 21679 var pool = this._dimension(bot, 'pool') || ['Unknown']; | 21800 var pool = this._attribute(bot, "pool"); |
| 21680 return pool.join(" | "); | 21801 return pool.join(" | "); |
| 21681 }, | 21802 }, |
| 21682 status: function(bot) { | 21803 status: function(bot) { |
| 21683 // If a bot is both dead and quarantined, show the deadness over the | 21804 // If a bot is both dead and quarantined, show the deadness over the |
| 21684 // quarentinedness. | 21805 // quarentinedness. |
| 21685 if (bot.is_dead) { | 21806 if (bot.is_dead) { |
| 21686 return "Dead: " + bot.is_dead; | 21807 return "Dead. Last seen " + swarming.diffDate(bot.last_seen_ts) + |
| 21808 " ago"; |
| 21687 } | 21809 } |
| 21688 if (bot.quarantined) { | 21810 if (bot.quarantined) { |
| 21689 return "Quarantined: " + bot.quarantined; | 21811 return "Quarantined: " + this._attribute(bot, "quarantined"); |
| 21690 } | 21812 } |
| 21691 return "Alive"; | 21813 return "Alive"; |
| 21692 }, | 21814 }, |
| 21693 task: function(bot){ | 21815 task: function(bot){ |
| 21694 return this._taskId(bot); | 21816 return this._taskId(bot); |
| 21695 }, | 21817 }, |
| 21696 }; | 21818 }; |
| 21697 | 21819 |
| 21820 var deviceColumnMap = { |
| 21821 android_devices: function(device) { |
| 21822 var str = this._androidAliasDevice(device); |
| 21823 if (device.okay) { |
| 21824 str = this._applyAlias(this._deviceType(device), str); |
| 21825 } |
| 21826 str += " S/N:"; |
| 21827 str += device.serial; |
| 21828 return str; |
| 21829 }, |
| 21830 device_os: function(device) { |
| 21831 if (device.build) { |
| 21832 return device.build["build.id"]; |
| 21833 } |
| 21834 return "unknown"; |
| 21835 }, |
| 21836 status: function(device) { |
| 21837 return device.state; |
| 21838 } |
| 21839 } |
| 21840 |
| 21841 // specialSort defines any custom sorting rules. By default, a |
| 21842 // naturalCompare of the column content is done. |
| 21843 var specialSort = { |
| 21844 device_type: function(dir, botA, botB) { |
| 21845 // We sort on the number of attached devices. Note that this |
| 21846 // may not be the same as android_devices, because _devices().length |
| 21847 // counts all devices plugged into the bot, whereas android_devices |
| 21848 // counts just devices ready for work. |
| 21849 var botACol = this._devices(botA).length; |
| 21850 var botBCol = this._devices(botB).length; |
| 21851 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21852 }, |
| 21853 disk_space: function(dir, botA, botB) { |
| 21854 // We sort based on the raw number of MB of the first disk. |
| 21855 var botACol = botA.disks[0].mb; |
| 21856 var botBCol = botB.disks[0].mb;; |
| 21857 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21858 }, |
| 21859 }; |
| 21860 |
| 21698 Polymer({ | 21861 Polymer({ |
| 21699 is: 'bot-list', | 21862 is: 'bot-list', |
| 21700 behaviors: [SwarmingBehaviors.BotListBehavior], | 21863 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21701 | 21864 |
| 21702 properties: { | 21865 properties: { |
| 21703 | 21866 |
| 21704 _bots: { | 21867 _bots: { |
| 21705 type: Array, | 21868 type: Array, |
| 21706 }, | 21869 }, |
| 21707 | 21870 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21755 _botLink: function(id) { | 21918 _botLink: function(id) { |
| 21756 // TODO(kjlubick) Make this point to /newui/ when appropriate. | 21919 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 21757 return "/restricted/bot/"+id; | 21920 return "/restricted/bot/"+id; |
| 21758 }, | 21921 }, |
| 21759 | 21922 |
| 21760 | 21923 |
| 21761 _column: function(col, bot) { | 21924 _column: function(col, bot) { |
| 21762 return columnMap[col].bind(this)(bot); | 21925 return columnMap[col].bind(this)(bot); |
| 21763 }, | 21926 }, |
| 21764 | 21927 |
| 21928 _androidAliasDevice: function(device) { |
| 21929 if (device.notReady) { |
| 21930 return UNAUTHENTICATED.toUpperCase(); |
| 21931 } |
| 21932 return this._androidAlias(this._deviceType(device)); |
| 21933 }, |
| 21934 |
| 21765 _deviceColumn: function(col, device) { | 21935 _deviceColumn: function(col, device) { |
| 21766 if (col === "devices") { | 21936 var f = deviceColumnMap[col]; |
| 21767 var str = this._androidAlias(device); | 21937 if (!f || !device) { |
| 21768 if (device.okay) { | 21938 return ""; |
| 21769 str = this._applyAlias(this._deviceType(device), str); | |
| 21770 } | |
| 21771 str += " S/N:"; | |
| 21772 str += device.serial; | |
| 21773 return str; | |
| 21774 } | 21939 } |
| 21775 if (col === "status") { | 21940 return f.bind(this)(device); |
| 21776 return device.state; | |
| 21777 } | |
| 21778 return ""; | |
| 21779 }, | 21941 }, |
| 21780 | 21942 |
| 21781 _deviceClass: function(device) { | 21943 _deviceClass: function(device) { |
| 21782 if (!device.okay) { | 21944 if (!device.okay) { |
| 21783 return "bad-device"; | 21945 return "bad-device"; |
| 21784 } | 21946 } |
| 21785 return ""; | 21947 return ""; |
| 21786 }, | 21948 }, |
| 21787 | 21949 |
| 21788 _filterAndSort: function(a,b,c) { | 21950 _filterAndSort: function(a,b,c) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 21811 }, | 21973 }, |
| 21812 | 21974 |
| 21813 _sortBotTable: function(botA, botB) { | 21975 _sortBotTable: function(botA, botB) { |
| 21814 if (!this._sort) { | 21976 if (!this._sort) { |
| 21815 return 0; | 21977 return 0; |
| 21816 } | 21978 } |
| 21817 var dir = 1; | 21979 var dir = 1; |
| 21818 if (this._sort.direction === "desc") { | 21980 if (this._sort.direction === "desc") { |
| 21819 dir = -1; | 21981 dir = -1; |
| 21820 } | 21982 } |
| 21983 var sort = specialSort[this._sort.name]; |
| 21984 if (sort) { |
| 21985 return sort.bind(this)(dir, botA, botB); |
| 21986 } |
| 21987 // Default to a natural compare of the columns. |
| 21821 var botACol = this._column(this._sort.name, botA); | 21988 var botACol = this._column(this._sort.name, botA); |
| 21822 var botBCol = this._column(this._sort.name, botB); | 21989 var botBCol = this._column(this._sort.name, botB); |
| 21823 | 21990 |
| 21824 return dir * swarming.naturalCompare(botACol, botBCol); | 21991 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21825 }, | 21992 }, |
| 21826 | 21993 |
| 21827 _sortChange: function(e) { | 21994 _sortChange: function(e) { |
| 21828 // The event we get from sort-toggle tells us the name of what needs | 21995 // The event we get from sort-toggle tells us the name of what needs |
| 21829 // to be sorting and how to sort it. | 21996 // to be sorting and how to sort it. |
| 21830 if (!(e && e.detail && e.detail.name)) { | 21997 if (!(e && e.detail && e.detail.name)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 21847 if (data && data.task_id) { | 22014 if (data && data.task_id) { |
| 21848 return "/user/task/" + data.task_id; | 22015 return "/user/task/" + data.task_id; |
| 21849 } | 22016 } |
| 21850 return undefined; | 22017 return undefined; |
| 21851 } | 22018 } |
| 21852 | 22019 |
| 21853 }); | 22020 }); |
| 21854 })(); | 22021 })(); |
| 21855 </script> | 22022 </script> |
| 21856 </dom-module></div></body></html> | 22023 </dom-module></div></body></html> |
| OLD | NEW |