Chromium Code Reviews| OLD | NEW |
|---|---|
| 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-data> | 9 <bot-list-data> |
| 10 | 10 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 | 51 |
| 52 <link rel="import" href="/res/imp/bower_components/iron-ajax/iron-ajax.html"> | 52 <link rel="import" href="/res/imp/bower_components/iron-ajax/iron-ajax.html"> |
| 53 | 53 |
| 54 <link rel="import" href="bot-list-shared.html"> | 54 <link rel="import" href="bot-list-shared.html"> |
| 55 | 55 |
| 56 <dom-module id="bot-list-data"> | 56 <dom-module id="bot-list-data"> |
| 57 <template> | 57 <template> |
| 58 <iron-ajax id="botlist" | 58 <iron-ajax id="botlist" |
| 59 url="/_ah/api/swarming/v1/bots/list" | 59 url="/_ah/api/swarming/v1/bots/list" |
| 60 headers="[[auth_headers]]" | 60 headers="[[auth_headers]]" |
| 61 params="[[_botlistParams(dimensions.*)]]" | |
| 61 handle-as="json" | 62 handle-as="json" |
| 62 last-response="{{_list}}" | 63 last-response="{{_list}}" |
| 63 loading="{{_busy1}}"> | 64 loading="{{_busy1}}"> |
| 64 </iron-ajax> | 65 </iron-ajax> |
| 65 | 66 |
| 67 <iron-ajax id="dimensions" | |
| 68 url="/_ah/api/swarming/v1/bots/dimensions" | |
| 69 headers="[[auth_headers]]" | |
| 70 handle-as="json" | |
| 71 last-response="{{_dimensions}}" | |
| 72 loading="{{_busy2}}"> | |
| 73 </iron-ajax> | |
| 74 | |
| 66 <iron-ajax id="fleet" | 75 <iron-ajax id="fleet" |
| 67 url="/_ah/api/swarming/v1/bots/count" | 76 url="/_ah/api/swarming/v1/bots/count" |
| 68 headers="[[auth_headers]]" | 77 headers="[[auth_headers]]" |
| 69 handle-as="json" | 78 handle-as="json" |
| 70 last-response="{{_count}}" | 79 last-response="{{_count}}" |
| 71 loading="{{_busy2}}"> | 80 loading="{{_busy3}}"> |
| 72 </iron-ajax> | 81 </iron-ajax> |
| 73 </template> | 82 </template> |
| 74 <script> | 83 <script> |
| 75 (function(){ | 84 (function(){ |
| 76 // TODO(kjlubick): Add more of these as well as things from state | 85 |
| 77 // i.e. disk space remaining. | |
| 78 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; | |
| 79 // "gpu" and "devices" are added separately because we need to | |
| 80 // deal with aliases. | |
| 81 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; | |
| 82 Polymer({ | 86 Polymer({ |
| 83 is: 'bot-list-data', | 87 is: 'bot-list-data', |
| 84 | 88 |
| 85 behaviors: [SwarmingBehaviors.BotListBehavior], | 89 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 86 | 90 |
| 87 properties: { | 91 properties: { |
| 88 // inputs | 92 // inputs |
| 89 auth_headers: { | 93 auth_headers: { |
| 90 type: Object, | 94 type: Object, |
| 91 observer: "signIn", | 95 observer: "signIn", |
| 92 }, | 96 }, |
| 97 dimensions: { | |
| 98 type: Array, | |
| 99 }, | |
| 93 | 100 |
| 94 //outputs | 101 //outputs |
| 95 bots: { | 102 bots: { |
| 96 type: Array, | 103 type: Array, |
| 97 computed: "_bots(_list)", | 104 computed: "_bots(_list)", |
| 98 notify: true, | 105 notify: true, |
| 99 }, | 106 }, |
| 100 busy: { | 107 busy: { |
| 101 type: Boolean, | 108 type: Boolean, |
| 102 computed: "_or(_busy1,_busy2)", | 109 computed: "_or(_busy1,_busy2,_busy3)", |
| 103 notify: true, | 110 notify: true, |
| 104 }, | 111 }, |
| 105 fleet: { | 112 fleet: { |
| 106 type: Object, | 113 type: Object, |
| 107 computed: "_fleet(_count)", | 114 computed: "_fleet(_count)", |
| 108 notify: true, | 115 notify: true, |
| 109 }, | 116 }, |
| 110 primary_map: { | 117 primary_map: { |
| 111 type:Object, | 118 type:Object, |
| 112 computed: "_primaryMap(bots)", | 119 computed: "_primaryMap(_dimensions)", |
| 113 notify: true, | 120 notify: true, |
| 114 }, | 121 }, |
| 115 primary_arr: { | 122 primary_arr: { |
| 116 type:Array, | 123 type: Array, |
| 117 value: function() { | 124 // DIMENSIONS and BOT_PROPERTIES are inherited from BotListBehavior |
| 118 return DIMENSIONS.concat(BOT_PROPERTIES); | 125 computed: "_primaryArr(DIMENSIONS, BOT_PROPERTIES)", |
| 119 }, | |
| 120 notify: true, | 126 notify: true, |
| 121 }, | 127 }, |
| 122 | 128 |
| 123 // private | 129 // private |
| 124 _count: { | 130 _count: { |
| 125 type: Object, | 131 type: Object, |
| 126 }, | 132 }, |
| 133 _dimensions: { | |
| 134 type: Object, | |
| 135 }, | |
| 127 _list: { | 136 _list: { |
| 128 type: Object, | 137 type: Object, |
| 129 }, | 138 }, |
| 130 }, | 139 }, |
| 131 | 140 |
| 132 signIn: function(){ | 141 signIn: function(){ |
| 133 this.$.botlist.generateRequest(); | 142 this.$.botlist.auto = true; |
| 134 this.$.fleet.generateRequest(); | 143 this.$.dimensions.auto = true; |
| 144 this.$.fleet.auto = true; | |
| 145 }, | |
| 146 | |
| 147 _botlistParams: function() { | |
| 148 if (!this.dimensions) { | |
| 149 return {}; | |
| 150 } | |
| 151 return { | |
| 152 dimensions: this.dimensions, | |
| 153 }; | |
| 135 }, | 154 }, |
| 136 | 155 |
| 137 _bots: function(){ | 156 _bots: function(){ |
| 138 if (!this._list || !this._list.items) { | 157 if (!this._list || !this._list.items) { |
| 139 return []; | 158 return []; |
| 140 } | 159 } |
| 141 this._list.items.forEach(function(o){ | 160 // Do any preprocessing here |
| 142 o.state = JSON.parse(o.state); | 161 this._list.items.forEach(function(bot){ |
| 162 // Parse the state, which is a JSON string. This contains a lot of | |
| 163 // interesting information like details about the devices attached. | |
| 164 bot.state = JSON.parse(bot.state); | |
| 165 // get the disks in an easier to deal with format, sorted by size. | |
| 166 var disks = bot.state["disks"]; | |
| 167 var keys = Object.keys(disks); | |
| 168 if (!keys || !keys.length) { | |
| 169 bot.disks = [{"id": "unknown", "mb": 0}]; | |
| 170 } else { | |
| 171 bot.disks = []; | |
| 172 for (var i = 0; i < keys.length; i++) { | |
| 173 bot.disks.push({"id":keys[i], "mb":disks[keys[i]].free_mb}); | |
| 174 } | |
| 175 // Sort these so the biggest disk comes first. | |
| 176 bot.disks.sort(function(a, b) { | |
| 177 return b.mb - a.mb; | |
| 178 }); | |
| 179 } | |
| 180 | |
| 143 }); | 181 }); |
| 144 return this._list.items; | 182 return this._list.items; |
| 145 }, | 183 }, |
| 146 | 184 |
| 147 _fleet: function() { | 185 _fleet: function() { |
| 148 if (!this._count) { | 186 if (!this._count) { |
| 149 return {}; | 187 return {}; |
| 150 } | 188 } |
| 151 return { | 189 return { |
| 152 alive: this._count.count || -1, | 190 alive: this._count.count || -1, |
| 153 busy: this._count.busy || -1, | 191 busy: this._count.busy || -1, |
| 154 idle: this._count.count && this._count.busy && | 192 idle: this._count.count && this._count.busy && |
| 155 this._count.count - this._count.busy, | 193 this._count.count - this._count.busy, |
| 156 dead: this._count.dead || -1, | 194 dead: this._count.dead || -1, |
| 157 quarantined: this._count.quarantined || -1, | 195 quarantined: this._count.quarantined || -1, |
| 158 } | 196 } |
| 159 }, | 197 }, |
| 160 | 198 |
| 161 _primaryMap: function(bots){ | 199 _primaryArr: function(dimensions, properties) { |
| 200 return dimensions.concat(properties); | |
| 201 }, | |
| 202 _primaryMap: function(dimensions){ | |
|
jcgregorio
2016/08/08 16:14:42
Blank line above.
kjlubick
2016/08/08 19:07:10
Done.
| |
| 162 // map will keep track of dimensions that we have seen at least once. | 203 // map will keep track of dimensions that we have seen at least once. |
| 163 // This will then basically get turned into an array to be used for | 204 // This will then basically get turned into an array to be used for |
| 164 // filtering. | 205 // filtering. |
| 165 var map = {}; | 206 dimensions = dimensions.bots_dimensions; |
| 166 DIMENSIONS.forEach(function(p){ | |
| 167 map[p] = {}; | |
| 168 }); | |
| 169 map["devices"] = {}; | |
| 170 map["gpu"] = {}; | |
| 171 bots.forEach(function(b){ | |
| 172 DIMENSIONS.forEach(function(d){ | |
| 173 var dims = this._dimension(b, d) || []; | |
| 174 dims.forEach(function(e){ | |
| 175 map[d][e] = true; | |
| 176 }); | |
| 177 }.bind(this)); | |
| 178 | 207 |
| 179 // Add Android devices and their aliases | 208 var pMap = {}; |
| 180 this._devices(b).forEach(function(d){ | 209 dimensions.forEach(function(d){ |
| 181 var dt = this._deviceType(d); | 210 if (this.DIMENSIONS_WITH_ALIASES.indexOf(d.key) === -1) { |
| 182 var alias = this._androidAlias(d); | 211 // value is an array of the values the |
|
jcgregorio
2016/08/08 16:14:42
the values the...?
kjlubick
2016/08/08 19:07:10
Fixed
| |
| 183 if (dt !== "unknown") { | 212 pMap[d.key] = d.value; |
| 184 dt = this._applyAlias(dt,alias); | 213 } else if (d.key === "gpu") { |
| 185 } | 214 var gpus = []; |
| 186 map["devices"][dt] = true; | 215 d.value.forEach(function(g){ |
| 187 }.bind(this)); | 216 var alias = this._gpuAlias(g); |
| 188 map["devices"]["none"] = true; | 217 if (alias !== "unknown") { |
| 189 | 218 gpus.push(this._applyAlias(g, alias)); |
| 190 // Add GPUs and their aliases | 219 } else { |
| 191 var gpus = this._dimension(b, "gpu") || []; | 220 gpus.push(g); |
| 192 gpus.forEach(function(g){ | 221 } |
| 193 var alias = this._gpuAlias(g); | 222 }.bind(this)); |
| 194 if (alias !== "UNKNOWN") { | 223 pMap["gpu"] = gpus; |
| 195 map["gpu"][this._applyAlias(g, alias)] = true; | 224 } else if (d.key === "device_type") { |
| 196 } else { | 225 var devs = []; |
| 197 map["gpu"][g] = true; | 226 d.value.forEach(function(dt){ |
| 198 } | 227 var alias = this._androidAlias(dt); |
| 199 | 228 if (alias !== "unknown") { |
| 200 }.bind(this)); | 229 devs.push(this._applyAlias(dt, alias)); |
| 230 } else { | |
| 231 devs.push(dt); | |
| 232 } | |
| 233 }.bind(this)); | |
| 234 pMap["device_type"] = devs; | |
| 235 } else { | |
| 236 console.log("Unknown alias type: ", d); | |
| 237 } | |
| 201 }.bind(this)); | 238 }.bind(this)); |
| 202 | 239 |
| 203 // Turn the Map<Object,Map<Boolean>> into a Map<Object,Array<String>> | 240 // Add some options that might not show up. |
| 204 // with all of the secondary elements sorted appropriately. | 241 pMap["android_devices"].push("0"); |
| 205 var pMap = {}; | 242 pMap["device_os"].push("none"); |
| 206 for (key in map){ | 243 pMap["device_type"].push("none"); |
| 207 pMap[key] = Object.keys(map[key]).sort(swarming.naturalCompare); | 244 |
| 208 } | 245 pMap["id"] = []; |
| 209 | 246 |
| 210 // Create custom filter options | 247 // Create custom filter options |
| 248 pMap["disk_space"] = []; | |
| 211 pMap["task"] = ["busy", "idle"]; | 249 pMap["task"] = ["busy", "idle"]; |
| 212 pMap["status"] = ["available", "dead", "quarantined"]; | 250 pMap["status"] = ["available", "dead", "quarantined"]; |
| 251 | |
| 252 // No need to sort any of this, bot-filters sorts secondary items | |
| 253 // automatically, especially when the user types a query. | |
| 213 return pMap; | 254 return pMap; |
| 214 }, | 255 }, |
| 215 | 256 |
| 216 }); | 257 }); |
| 217 })(); | 258 })(); |
| 218 </script> | 259 </script> |
| 219 </dom-module> | 260 </dom-module> |
| OLD | NEW |