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

Side by Side Diff: appengine/swarming/elements/res/imp/botlist/bot-list-data.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: Make devices column make more sense 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-data> 9 <bot-list-data>
10 10
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
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>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698