Merge lp:~blake-rouse/maas/images-ajax-view into lp:~maas-committers/maas/trunk
- images-ajax-view
- Merge into trunk
Proposed by
Blake Rouse
Status: | Merged |
---|---|
Approved by: | Blake Rouse |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3188 |
Proposed branch: | lp:~blake-rouse/maas/images-ajax-view |
Merge into: | lp:~maas-committers/maas/trunk |
Prerequisite: | lp:~blake-rouse/maas/images-ajax-response |
Diff against target: |
834 lines (+293/-358) 7 files modified
src/maasserver/context_processors.py (+2/-0) src/maasserver/static/js/image_views.js (+21/-0) src/maasserver/static/js/tests/test_image_views.js (+23/-0) src/maasserver/templates/maasserver/images.html (+245/-246) src/maasserver/templates/maasserver/js-conf.html (+2/-1) src/maasserver/views/images.py (+0/-10) src/maasserver/views/tests/test_images.py (+0/-101) |
To merge this branch: | bzr merge lp:~blake-rouse/maas/images-ajax-view |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Newell Jensen (community) | Approve | ||
Review via email: mp+236949@code.launchpad.net |
Commit message
Use the ImagesView on the images page. Status of importing is updated every 15 seconds, new Ubuntu resources will appear and disappear along with its current status.
Description of the change
To post a comment you must log in.
Revision history for this message
Newell Jensen (newell-jensen) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/maasserver/context_processors.py' |
2 | --- src/maasserver/context_processors.py 2014-09-29 15:26:08 +0000 |
3 | +++ src/maasserver/context_processors.py 2014-10-02 18:55:55 +0000 |
4 | @@ -56,6 +56,8 @@ |
5 | 'css/multiselect_widget.css', |
6 | ], |
7 | 'JS_LIST': [ |
8 | + 'js/image.js', |
9 | + 'js/image_views.js', |
10 | 'js/license_key.js', |
11 | 'js/morph.js', |
12 | 'js/user_panel.js', |
13 | |
14 | === modified file 'src/maasserver/static/js/image_views.js' |
15 | --- src/maasserver/static/js/image_views.js 2014-10-02 18:55:55 +0000 |
16 | +++ src/maasserver/static/js/image_views.js 2014-10-02 18:55:55 +0000 |
17 | @@ -254,9 +254,11 @@ |
18 | if(ubuntuImages.length == 0) { |
19 | this.ubuntuMissingImages.removeClass('hidden'); |
20 | this.ubuntuTable.addClass('hidden'); |
21 | + this.updateUbuntuButton(false); |
22 | } else { |
23 | this.ubuntuMissingImages.addClass('hidden'); |
24 | this.ubuntuTable.removeClass('hidden'); |
25 | + this.updateUbuntuButton(true); |
26 | } |
27 | var self = this; |
28 | var innerTable = ""; |
29 | @@ -273,6 +275,25 @@ |
30 | }, |
31 | |
32 | /** |
33 | + * Update the value of the ubuntuButton. |
34 | + * |
35 | + * The value of the button can be locked meaning it should not change, this |
36 | + * is done using the data attribute lock-value. data-lock-value="true" |
37 | + * |
38 | + * @method updateUbuntuButton |
39 | + */ |
40 | + updateUbuntuButton: function(showApply) { |
41 | + if(!Y.Lang.isValue(this.ubuntuButton)) |
42 | + return; |
43 | + if(this.ubuntuButton.getData('lock-value') === "true") |
44 | + return; |
45 | + if(showApply) |
46 | + this.ubuntuButton.set('value', 'Apply changes'); |
47 | + else |
48 | + this.ubuntuButton.set('value', 'Import images'); |
49 | + }, |
50 | + |
51 | + /** |
52 | * Return the HTML for the downloading spinner for the given model. |
53 | * |
54 | * @method getSpinner |
55 | |
56 | === modified file 'src/maasserver/static/js/tests/test_image_views.js' |
57 | --- src/maasserver/static/js/tests/test_image_views.js 2014-10-02 18:55:55 +0000 |
58 | +++ src/maasserver/static/js/tests/test_image_views.js 2014-10-02 18:55:55 +0000 |
59 | @@ -369,6 +369,29 @@ |
60 | }); |
61 | }, |
62 | |
63 | + testUpdateUbuntuButtonSetValueForApply: function() { |
64 | + var view = this.makeImagesView(); |
65 | + var ubuntuButton = view.srcNode.one('#ubuntu-apply'); |
66 | + view.updateUbuntuButton(true); |
67 | + Y.Assert.areSame('Apply changes', ubuntuButton.get('value')); |
68 | + }, |
69 | + |
70 | + testUpdateUbuntuButtonSetValueForImport: function() { |
71 | + var view = this.makeImagesView(); |
72 | + var ubuntuButton = view.srcNode.one('#ubuntu-apply'); |
73 | + view.updateUbuntuButton(false); |
74 | + Y.Assert.areSame('Import images', ubuntuButton.get('value')); |
75 | + }, |
76 | + |
77 | + testUpdateUbuntuButtonDoesNothingIfLockValueExists: function() { |
78 | + var view = this.makeImagesView(); |
79 | + var ubuntuButton = view.srcNode.one('#ubuntu-apply'); |
80 | + ubuntuButton.set('value', 'testing'); |
81 | + ubuntuButton.setData('lock-value', 'true'); |
82 | + view.updateUbuntuButton(true); |
83 | + Y.Assert.areSame('testing', ubuntuButton.get('value')); |
84 | + }, |
85 | + |
86 | testGetSpinnerReturnsEmptyForComplete: function() { |
87 | var view = this.makeImagesView(); |
88 | var model = new Y.maas.image.Image({complete: true}); |
89 | |
90 | === modified file 'src/maasserver/templates/maasserver/images.html' |
91 | --- src/maasserver/templates/maasserver/images.html 2014-09-30 18:59:13 +0000 |
92 | +++ src/maasserver/templates/maasserver/images.html 2014-10-02 18:55:55 +0000 |
93 | @@ -42,7 +42,11 @@ |
94 | -webkit-border-radius: 5px; |
95 | background-color: rgba(221, 72, 20, 0.3); |
96 | } |
97 | - .importing { |
98 | + #loader { |
99 | + width: 10px; |
100 | + margin: 16px auto 0 auto; |
101 | + } |
102 | + #importing { |
103 | margin: -20px auto -19px auto; |
104 | width: 230px; |
105 | font-weight: bold; |
106 | @@ -85,82 +89,212 @@ |
107 | } |
108 | } |
109 | </style> |
110 | + <script type="text/javascript"> |
111 | + <!-- |
112 | + YUI().use('maas.image_views', 'maas.shortpoll', function (Y) { |
113 | + Y.on('load', function() { |
114 | + var view = new Y.maas.image_views.ImagesView({ |
115 | + srcNode: '#content', |
116 | + loader: '#loader', |
117 | + content: '#images-content', |
118 | + importer: '#importing', |
119 | + ubuntuOptions: '#ubuntu-options', |
120 | + ubuntuTable: '#ubuntu-resources', |
121 | + ubuntuMissingImages: '#missing-ubuntu-images', |
122 | + ubuntuButton: '#ubuntu-apply'}); |
123 | + |
124 | + var poller = new Y.maas.shortpoll.ShortPollManager({ |
125 | + uri: MAAS_config.uris.images_handler |
126 | + }); |
127 | + view.addLoader(poller.get("io")); |
128 | + poller.poll(); |
129 | + }); |
130 | + }); |
131 | + // --> |
132 | + </script> |
133 | {% endblock %} |
134 | |
135 | {% block content %} |
136 | - {% if region_import_running or cluster_import_running %} |
137 | - <div class="importing"> |
138 | + <div id="loader"> |
139 | <div class="spinner spin"></div> |
140 | - {% if region_import_running %} |
141 | - Step 1/2: Region importing |
142 | - {% elif cluster_import_running %} |
143 | - Step 2/2: Clusters importing |
144 | + </div> |
145 | + <div id="images-content" class="hidden"> |
146 | + <div id="importing" class="hidden"> |
147 | + <div class="spinner spin"></div> |
148 | + <span class="importing-text"></span> |
149 | + <span class="importing-dot">.</span> |
150 | + <span class="importing-dot" style="-webkit-animation-delay: 0.2s; animation-delay: 0.2s;">.</span> |
151 | + <span class="importing-dot" style="-webkit-animation-delay: 0.3s; animation-delay: 0.3s;">.</span> |
152 | + </div> |
153 | + <div id="ubuntu-images" class="section"> |
154 | + <h2>Ubuntu</h2> |
155 | + <div class="content"> |
156 | + <form id="ubuntu_images" |
157 | + method="POST" |
158 | + action="{% url 'images' %}"> |
159 | + {% csrf_token %} |
160 | + <input type="hidden" name="ubuntu_images" value="1" /> |
161 | + {% if user.is_superuser %} |
162 | + <div id="ubuntu-options" class="row hidden"> |
163 | + {% if connection_error %} |
164 | + <div id="connection-error" class="images-warning"> |
165 | + Connection Error: Unable to retrieve image information from |
166 | + boot sources. |
167 | + </div> |
168 | + {% else %} |
169 | + {% if ubuntu_streams_count == 0 %} |
170 | + <div id="no-ubuntu-sources" class="images-warning"> |
171 | + Error: No boot sources provide Ubuntu images. |
172 | + </div> |
173 | + {% elif ubuntu_streams_count == 1 %} |
174 | + <div class="col2"> |
175 | + <div class="space-bottom-small">Release:</div> |
176 | + <ul id="ubuntu-releases" class="data-list"> |
177 | + {% for release in ubuntu_releases %} |
178 | + <li><input type="checkbox" name="release" |
179 | + value="{{release.name}}" |
180 | + {% if release.checked %}checked="checked"{% endif %}> |
181 | + {{release.title}}</li> |
182 | + {% endfor %} |
183 | + </ul> |
184 | + </div> |
185 | + <div class="col10 last"> |
186 | + <div class="space-bottom-small">Architecture:</div> |
187 | + <ul id="ubuntu-arches" class="data-list"> |
188 | + {% for arch in ubuntu_arches %} |
189 | + <li><input type="checkbox" name="arch" |
190 | + value="{{arch.name}}" |
191 | + {% if arch.checked %}checked="checked"{% endif %}> |
192 | + {{arch.title}}</li> |
193 | + {% endfor %} |
194 | + </ul> |
195 | + </div> |
196 | + {% else %} |
197 | + <div id="too-many-ubuntu-sources" class="images-warning"> |
198 | + More than one boot source is providing Ubuntu images. Image |
199 | + selection cannot be performed using the WebUI. |
200 | + </div> |
201 | + {% endif %} |
202 | + {% endif %} |
203 | + </div> |
204 | + <div class="clear"></div> |
205 | + {% endif %} |
206 | + <div class="row space-top"> |
207 | + <table id="ubuntu-resources" class="space-top list hidden"> |
208 | + <thead> |
209 | + <tr> |
210 | + <th class="spinner-col"></th> |
211 | + <th>Release</th> |
212 | + <th>Architecture</th> |
213 | + <th>Size</th> |
214 | + <th>Nodes deployed</th> |
215 | + <th>Last update</th> |
216 | + </tr> |
217 | + </thead> |
218 | + <tbody> |
219 | + {# maas.image_view.ImageView will render this part #} |
220 | + </tbody> |
221 | + </table> |
222 | + <div id="missing-ubuntu-images" class="images-warning hidden"> |
223 | + No Ubuntu images have been imported. Ubuntu images are required |
224 | + to allow nodes to enlist, commission, and install.</div> |
225 | + </div> |
226 | + <div class="clear"></div> |
227 | + <div class="row space-top end-row"> |
228 | + {% if user.is_superuser %} |
229 | + <div class="col12 last align-right"> |
230 | + {% if ubuntu_streams_count == 1 %} |
231 | + <input id="ubuntu-apply" type="submit" class="button hidden" value="Import images"> |
232 | + {% elif ubuntu_streams_count > 1 %} |
233 | + <input id="ubuntu-apply" type="submit" class="button hidden" data-lock-value="true" value="Import images"> |
234 | + {% endif %} |
235 | + </div> |
236 | + {% endif %} |
237 | + </div> |
238 | + <div class="clear"></div> |
239 | + </form> |
240 | + </div> |
241 | + </div> |
242 | + {% if other_resources %} |
243 | + <div id="other-sync-images" class="section"> |
244 | + <h2>Other Images</h2> |
245 | + <div class="content"> |
246 | + <form id="other_images" |
247 | + method="POST" |
248 | + action="{% url 'images' %}"> |
249 | + {% csrf_token %} |
250 | + <input type="hidden" name="other_images" value="1" /> |
251 | + <div class="row space-top"> |
252 | + <table id="other-resources" class="space-top list"> |
253 | + <thead> |
254 | + <tr> |
255 | + <th class="spinner-col"></th> |
256 | + <th>Name</th> |
257 | + <th>Architecture</th> |
258 | + <th>Size</th> |
259 | + <th>Nodes deployed</th> |
260 | + <th>Last update</th> |
261 | + </tr> |
262 | + </thead> |
263 | + <tbody> |
264 | + {% for resource in other_resources %} |
265 | + <tr |
266 | + class="{% cycle 'even' 'odd' %}" |
267 | + data-id="{% if resource.id %}{{ resource.id }}{% endif %}"> |
268 | + <td> |
269 | + {% if region_import_running and resource.exists %} |
270 | + {% if not resource.complete %} |
271 | + <div |
272 | + title="{{ resource.status }}" |
273 | + class=" |
274 | + spinner |
275 | + {% if resource.downloading %}spin{% endif %}"> |
276 | + </div> |
277 | + {% endif %} |
278 | + {% elif not region_import_running and user.is_superuser %} |
279 | + <input |
280 | + type="checkbox" |
281 | + name="image" |
282 | + value="{{ resource.os }}/{{ resource.arch }}/{{ resource.subarch }}/{{ resource.release }}" |
283 | + {% if resource.exists %} |
284 | + checked="checked" |
285 | + {% endif %} |
286 | + > |
287 | + {% endif %} |
288 | + </td> |
289 | + <td>{{ resource.title }}</td> |
290 | + <td>{{ resource.arch }}</td> |
291 | + <td>{{ resource.size }}</td> |
292 | + <td>{{ resource.number_of_nodes }}</td> |
293 | + <td>{{ resource.last_update }}</td> |
294 | + </tr> |
295 | + {% endfor %} |
296 | + </tbody> |
297 | + </table> |
298 | + </div> |
299 | + <div class="clear"></div> |
300 | + <div class="row space-top end-row"> |
301 | + {% if user.is_superuser and not region_import_running %} |
302 | + <div class="col12 last align-right"> |
303 | + <input type="submit" class="button" value="Apply changes"> |
304 | + </div> |
305 | + {% endif %} |
306 | + </div> |
307 | + <div class="clear"></div> |
308 | + </form> |
309 | + </div> |
310 | + </div> |
311 | {% endif %} |
312 | - <span class="importing-dot">.</span> |
313 | - <span class="importing-dot" style="-webkit-animation-delay: 0.2s; animation-delay: 0.2s;">.</span> |
314 | - <span class="importing-dot" style="-webkit-animation-delay: 0.3s; animation-delay: 0.3s;">.</span> |
315 | - </div> |
316 | - {% endif %} |
317 | - <div id="ubuntu-images" class="section"> |
318 | - <h2>Ubuntu</h2> |
319 | - <div class="content"> |
320 | - <form id="ubuntu_images" |
321 | - method="POST" |
322 | - action="{% url 'images' %}"> |
323 | - {% csrf_token %} |
324 | - <input type="hidden" name="ubuntu_images" value="1" /> |
325 | - {% if user.is_superuser and not region_import_running %} |
326 | - <div class="row"> |
327 | - {% if connection_error %} |
328 | - <div id="connection-error" class="images-warning"> |
329 | - Connection Error: Unable to retrieve image information from |
330 | - boot sources. |
331 | - </div> |
332 | - {% else %} |
333 | - {% if ubuntu_streams_count == 0 %} |
334 | - <div id="no-ubuntu-sources" class="images-warning"> |
335 | - Error: No boot sources provide Ubuntu images. |
336 | - </div> |
337 | - {% elif ubuntu_streams_count == 1 %} |
338 | - <div class="col2"> |
339 | - <div class="space-bottom-small">Release:</div> |
340 | - <ul id="ubuntu-releases" class="data-list"> |
341 | - {% for release in ubuntu_releases %} |
342 | - <li><input type="checkbox" name="release" |
343 | - value="{{release.name}}" |
344 | - {% if release.checked %}checked="checked"{% endif %}> |
345 | - {{release.title}}</li> |
346 | - {% endfor %} |
347 | - </ul> |
348 | - </div> |
349 | - <div class="col10 last"> |
350 | - <div class="space-bottom-small">Architecture:</div> |
351 | - <ul id="ubuntu-arches" class="data-list"> |
352 | - {% for arch in ubuntu_arches %} |
353 | - <li><input type="checkbox" name="arch" |
354 | - value="{{arch.name}}" |
355 | - {% if arch.checked %}checked="checked"{% endif %}> |
356 | - {{arch.title}}</li> |
357 | - {% endfor %} |
358 | - </ul> |
359 | - </div> |
360 | - {% else %} |
361 | - <div id="too-many-ubuntu-sources" class="images-warning"> |
362 | - More than one boot source is providing Ubuntu images. Image |
363 | - selection cannot be performed using the WebUI. |
364 | - </div> |
365 | - {% endif %} |
366 | - {% endif %} |
367 | - </div> |
368 | - <div class="clear"></div> |
369 | - {% endif %} |
370 | + {% if generated_resources %} |
371 | + <div id="generated-images" class="section"> |
372 | + <h2>Generated Images</h2> |
373 | + <div class="content"> |
374 | <div class="row space-top"> |
375 | - {% if ubuntu_resources|length %} |
376 | - <table id="ubuntu-resources" class="space-top list"> |
377 | + <table id="generated-resources" class="space-top list"> |
378 | <thead> |
379 | <tr> |
380 | <th class="spinner-col"></th> |
381 | - <th>Release</th> |
382 | + <th>Name</th> |
383 | <th>Architecture</th> |
384 | <th>Size</th> |
385 | <th>Nodes deployed</th> |
386 | @@ -168,7 +302,7 @@ |
387 | </tr> |
388 | </thead> |
389 | <tbody> |
390 | - {% for resource in ubuntu_resources %} |
391 | + {% for resource in generated_resources %} |
392 | <tr |
393 | class="{% cycle 'even' 'odd' %}" |
394 | data-id="{{ resource.id }}"> |
395 | @@ -182,7 +316,18 @@ |
396 | </div> |
397 | {% endif %} |
398 | </td> |
399 | - <td>{{ resource.title }}</td> |
400 | + <td>{{ resource.title }} |
401 | + {% if user.is_superuser %} |
402 | + <a |
403 | + title="Delete image" |
404 | + href="{% url 'image-delete' resource.id %}"> |
405 | + <img |
406 | + class="small-icon" |
407 | + src="{{ STATIC_URL }}img/delete.png" |
408 | + alt="delete" /> |
409 | + </a> |
410 | + {% endif %} |
411 | + </td> |
412 | <td>{{ resource.arch }}</td> |
413 | <td>{{ resource.size }}</td> |
414 | <td>{{ resource.number_of_nodes }}</td> |
415 | @@ -191,46 +336,22 @@ |
416 | {% endfor %} |
417 | </tbody> |
418 | </table> |
419 | - {% else %} |
420 | - <div id="missing-ubuntu-images" class="images-warning"> |
421 | - No Ubuntu images have been imported. Ubuntu images are required |
422 | - to allow nodes to enlist, commission, and install.</div> |
423 | - {% endif %} |
424 | - </div> |
425 | - <div class="clear"></div> |
426 | - <div class="row space-top end-row"> |
427 | - {% if user.is_superuser and not region_import_running %} |
428 | - <div class="col12 last align-right"> |
429 | - {% if ubuntu_streams_count == 1 %} |
430 | - {% if ubuntu_resources|length %} |
431 | - <input type="submit" class="button" value="Apply changes"> |
432 | - {% else %} |
433 | - <input type="submit" class="button" value="Import images"> |
434 | - {% endif %} |
435 | - {% elif ubuntu_streams_count > 1 %} |
436 | - <input type="submit" class="button" value="Import images"> |
437 | - {% endif %} |
438 | - </div> |
439 | - {% endif %} |
440 | - </div> |
441 | - <div class="clear"></div> |
442 | - </form> |
443 | + </div> |
444 | + <div class="clear"></div> |
445 | + <div class="row space-top end-row"></div> |
446 | + <div class="clear"></div> |
447 | + </div> |
448 | </div> |
449 | - </div> |
450 | - {% if other_resources %} |
451 | - <div id="other-sync-images" class="section"> |
452 | - <h2>Other Images</h2> |
453 | - <div class="content"> |
454 | - <form id="other_images" |
455 | - method="POST" |
456 | - action="{% url 'images' %}"> |
457 | - {% csrf_token %} |
458 | - <input type="hidden" name="other_images" value="1" /> |
459 | + {% endif %} |
460 | + <div id="custom-images" class="section"> |
461 | + <h2>Custom Images</h2> |
462 | + <div class="content"> |
463 | <div class="row space-top"> |
464 | - <table id="other-resources" class="space-top list"> |
465 | + {% if uploaded_resources|length %} |
466 | + <table id="uploaded-resources" class="space-top list"> |
467 | <thead> |
468 | <tr> |
469 | - <th class="spinner-col"></th> |
470 | + <th></th> |
471 | <th>Name</th> |
472 | <th>Architecture</th> |
473 | <th>Size</th> |
474 | @@ -239,12 +360,9 @@ |
475 | </tr> |
476 | </thead> |
477 | <tbody> |
478 | - {% for resource in other_resources %} |
479 | - <tr |
480 | - class="{% cycle 'even' 'odd' %}" |
481 | - data-id="{% if resource.id %}{{ resource.id }}{% endif %}"> |
482 | + {% for resource in uploaded_resources %} |
483 | + <tr class="{% cycle 'even' 'odd' %}"> |
484 | <td> |
485 | - {% if region_import_running and resource.exists %} |
486 | {% if not resource.complete %} |
487 | <div |
488 | title="{{ resource.status }}" |
489 | @@ -253,154 +371,35 @@ |
490 | {% if resource.downloading %}spin{% endif %}"> |
491 | </div> |
492 | {% endif %} |
493 | - {% elif not region_import_running and user.is_superuser %} |
494 | - <input |
495 | - type="checkbox" |
496 | - name="image" |
497 | - value="{{ resource.os }}/{{ resource.arch }}/{{ resource.subarch }}/{{ resource.release }}" |
498 | - {% if resource.exists %} |
499 | - checked="checked" |
500 | - {% endif %} |
501 | - > |
502 | + </td> |
503 | + <td>{{ resource.title }} |
504 | + {% if user.is_superuser %} |
505 | + <a |
506 | + title="Delete image" |
507 | + href="{% url 'image-delete' resource.id %}"> |
508 | + <img |
509 | + class="small-icon" |
510 | + src="{{ STATIC_URL }}img/delete.png" |
511 | + alt="delete" /> |
512 | + </a> |
513 | {% endif %} |
514 | </td> |
515 | - <td>{{ resource.title }}</td> |
516 | <td>{{ resource.arch }}</td> |
517 | <td>{{ resource.size }}</td> |
518 | <td>{{ resource.number_of_nodes }}</td> |
519 | <td>{{ resource.last_update }}</td> |
520 | </tr> |
521 | - {% endfor %} |
522 | + {% endfor %} |
523 | </tbody> |
524 | </table> |
525 | - </div> |
526 | - <div class="clear"></div> |
527 | - <div class="row space-top end-row"> |
528 | - {% if user.is_superuser and not region_import_running %} |
529 | - <div class="col12 last align-right"> |
530 | - <input type="submit" class="button" value="Apply changes"> |
531 | + {% else %} |
532 | + <div id="no-custom-images" class="images-info"> |
533 | + No custom images have been uploaded. |
534 | </div> |
535 | {% endif %} |
536 | </div> |
537 | <div class="clear"></div> |
538 | - </form> |
539 | - </div> |
540 | - </div> |
541 | - {% endif %} |
542 | - {% if generated_resources %} |
543 | - <div id="generated-images" class="section"> |
544 | - <h2>Generated Images</h2> |
545 | - <div class="content"> |
546 | - <div class="row space-top"> |
547 | - <table id="generated-resources" class="space-top list"> |
548 | - <thead> |
549 | - <tr> |
550 | - <th class="spinner-col"></th> |
551 | - <th>Name</th> |
552 | - <th>Architecture</th> |
553 | - <th>Size</th> |
554 | - <th>Nodes deployed</th> |
555 | - <th>Last update</th> |
556 | - </tr> |
557 | - </thead> |
558 | - <tbody> |
559 | - {% for resource in generated_resources %} |
560 | - <tr |
561 | - class="{% cycle 'even' 'odd' %}" |
562 | - data-id="{{ resource.id }}"> |
563 | - <td> |
564 | - {% if not resource.complete %} |
565 | - <div |
566 | - title="{{ resource.status }}" |
567 | - class=" |
568 | - spinner |
569 | - {% if resource.downloading %}spin{% endif %}"> |
570 | - </div> |
571 | - {% endif %} |
572 | - </td> |
573 | - <td>{{ resource.title }} |
574 | - {% if user.is_superuser %} |
575 | - <a |
576 | - title="Delete image" |
577 | - href="{% url 'image-delete' resource.id %}"> |
578 | - <img |
579 | - class="small-icon" |
580 | - src="{{ STATIC_URL }}img/delete.png" |
581 | - alt="delete" /> |
582 | - </a> |
583 | - {% endif %} |
584 | - </td> |
585 | - <td>{{ resource.arch }}</td> |
586 | - <td>{{ resource.size }}</td> |
587 | - <td>{{ resource.number_of_nodes }}</td> |
588 | - <td>{{ resource.last_update }}</td> |
589 | - </tr> |
590 | - {% endfor %} |
591 | - </tbody> |
592 | - </table> |
593 | - </div> |
594 | - <div class="clear"></div> |
595 | - <div class="row space-top end-row"></div> |
596 | - <div class="clear"></div> |
597 | - </div> |
598 | - </div> |
599 | - {% endif %} |
600 | - <div id="custom-images" class="section"> |
601 | - <h2>Custom Images</h2> |
602 | - <div class="content"> |
603 | - <div class="row space-top"> |
604 | - {% if uploaded_resources|length %} |
605 | - <table id="uploaded-resources" class="space-top list"> |
606 | - <thead> |
607 | - <tr> |
608 | - <th></th> |
609 | - <th>Name</th> |
610 | - <th>Architecture</th> |
611 | - <th>Size</th> |
612 | - <th>Nodes deployed</th> |
613 | - <th>Last update</th> |
614 | - </tr> |
615 | - </thead> |
616 | - <tbody> |
617 | - {% for resource in uploaded_resources %} |
618 | - <tr class="{% cycle 'even' 'odd' %}"> |
619 | - <td> |
620 | - {% if not resource.complete %} |
621 | - <div |
622 | - title="{{ resource.status }}" |
623 | - class=" |
624 | - spinner |
625 | - {% if resource.downloading %}spin{% endif %}"> |
626 | - </div> |
627 | - {% endif %} |
628 | - </td> |
629 | - <td>{{ resource.title }} |
630 | - {% if user.is_superuser %} |
631 | - <a |
632 | - title="Delete image" |
633 | - href="{% url 'image-delete' resource.id %}"> |
634 | - <img |
635 | - class="small-icon" |
636 | - src="{{ STATIC_URL }}img/delete.png" |
637 | - alt="delete" /> |
638 | - </a> |
639 | - {% endif %} |
640 | - </td> |
641 | - <td>{{ resource.arch }}</td> |
642 | - <td>{{ resource.size }}</td> |
643 | - <td>{{ resource.number_of_nodes }}</td> |
644 | - <td>{{ resource.last_update }}</td> |
645 | - </tr> |
646 | - {% endfor %} |
647 | - </tbody> |
648 | - </table> |
649 | - {% else %} |
650 | - <div id="no-custom-images" class="images-info"> |
651 | - No custom images have been uploaded. |
652 | - </div> |
653 | - {% endif %} |
654 | - </div> |
655 | - <div class="clear"></div> |
656 | + </div> |
657 | </div> |
658 | </div> |
659 | {% endblock %} |
660 | |
661 | === modified file 'src/maasserver/templates/maasserver/js-conf.html' |
662 | --- src/maasserver/templates/maasserver/js-conf.html 2012-06-26 09:47:31 +0000 |
663 | +++ src/maasserver/templates/maasserver/js-conf.html 2014-10-02 18:55:55 +0000 |
664 | @@ -14,7 +14,8 @@ |
665 | statics: '{{ STATIC_URL }}', |
666 | maas_handler: '{% url "maas_handler" %}', |
667 | nodes_handler: '{% url "nodes_handler" %}', |
668 | - account_handler: '{% url "account_handler" %}' |
669 | + account_handler: '{% url "account_handler" %}', |
670 | + images_handler: '{% url "images" %}' |
671 | }, |
672 | debug: {% if YUI_DEBUG %}true{% else %}false{% endif %} |
673 | }; |
674 | |
675 | === modified file 'src/maasserver/views/images.py' |
676 | --- src/maasserver/views/images.py 2014-10-02 18:55:55 +0000 |
677 | +++ src/maasserver/views/images.py 2014-10-02 18:55:55 +0000 |
678 | @@ -140,7 +140,6 @@ |
679 | context['ubuntu_streams_count'] = len(self.ubuntu_sources) |
680 | context['ubuntu_releases'] = self.format_ubuntu_releases() |
681 | context['ubuntu_arches'] = self.format_ubuntu_arches() |
682 | - context['ubuntu_resources'] = self.get_ubuntu_resources() |
683 | context['other_resources'] = self.get_other_resources() |
684 | context['generated_resources'] = self.get_generated_resources() |
685 | context['uploaded_resources'] = self.get_uploaded_resources() |
686 | @@ -247,15 +246,6 @@ |
687 | else: |
688 | return resource.name |
689 | |
690 | - def get_ubuntu_resources(self): |
691 | - """Return all Ubuntu resources, for usage in the template.""" |
692 | - resources = list(BootResource.objects.filter( |
693 | - rtype=BOOT_RESOURCE_TYPE.SYNCED, |
694 | - name__startswith='ubuntu/').order_by('-name', 'architecture')) |
695 | - for resource in resources: |
696 | - self.add_resource_template_attributes(resource) |
697 | - return resources |
698 | - |
699 | def add_resource_template_attributes(self, resource): |
700 | """Adds helper attributes to the resource.""" |
701 | resource.title = self.get_resource_title(resource) |
702 | |
703 | === modified file 'src/maasserver/views/tests/test_images.py' |
704 | --- src/maasserver/views/tests/test_images.py 2014-10-02 18:55:55 +0000 |
705 | +++ src/maasserver/views/tests/test_images.py 2014-10-02 18:55:55 +0000 |
706 | @@ -43,7 +43,6 @@ |
707 | ) |
708 | from requests import ConnectionError |
709 | from testtools.matchers import ( |
710 | - Contains, |
711 | ContainsAll, |
712 | HasLength, |
713 | ) |
714 | @@ -62,17 +61,6 @@ |
715 | mock_get_os_info.return_value = (sources, releases, arches) |
716 | return mock_get_os_info |
717 | |
718 | - def make_ubuntu_resource(self, release=None): |
719 | - if release is None: |
720 | - release = factory.make_name('release') |
721 | - name = 'ubuntu/%s' % release |
722 | - arch = factory.make_name('arch') |
723 | - subarch = factory.make_name('subarch') |
724 | - architecture = '%s/%s' % (arch, subarch) |
725 | - return factory.make_usable_boot_resource( |
726 | - rtype=BOOT_RESOURCE_TYPE.SYNCED, |
727 | - name=name, architecture=architecture) |
728 | - |
729 | def test_shows_connection_error(self): |
730 | self.client_log_in(as_admin=True) |
731 | mock_get_os_info = self.patch( |
732 | @@ -128,83 +116,6 @@ |
733 | warnings = doc.cssselect('div#missing-ubuntu-images') |
734 | self.assertEqual(1, len(warnings)) |
735 | |
736 | - def test_shows_ubuntu_resources(self): |
737 | - self.client_log_in() |
738 | - releases = [factory.make_name('release') for _ in range(3)] |
739 | - [self.make_ubuntu_resource(release) for release in releases] |
740 | - response = self.client.get(reverse('images')) |
741 | - doc = fromstring(response.content) |
742 | - table_content = doc.cssselect( |
743 | - 'table#ubuntu-resources')[0].text_content() |
744 | - self.assertThat(table_content, ContainsAll(releases)) |
745 | - |
746 | - def test_shows_ubuntu_release_version_name(self): |
747 | - self.client_log_in() |
748 | - # Use trusty as known to map to "14.04 LTS" |
749 | - release = 'trusty' |
750 | - version = '14.04 LTS' |
751 | - self.make_ubuntu_resource(release) |
752 | - response = self.client.get(reverse('images')) |
753 | - doc = fromstring(response.content) |
754 | - table_content = doc.cssselect( |
755 | - 'table#ubuntu-resources')[0].text_content() |
756 | - self.assertThat(table_content, Contains(version)) |
757 | - |
758 | - def test_shows_number_of_nodes_deployed_for_ubuntu_resource(self): |
759 | - self.client_log_in() |
760 | - resource = self.make_ubuntu_resource() |
761 | - os_name, series = resource.name.split('/') |
762 | - number_of_nodes = random.randint(1, 4) |
763 | - for _ in range(number_of_nodes): |
764 | - factory.make_Node( |
765 | - status=NODE_STATUS.DEPLOYED, |
766 | - osystem=os_name, distro_series=series, |
767 | - architecture=resource.architecture) |
768 | - response = self.client.get(reverse('images')) |
769 | - doc = fromstring(response.content) |
770 | - count = int(doc.cssselect( |
771 | - 'table#ubuntu-resources > tbody > tr > td')[4].text_content()) |
772 | - self.assertEqual(number_of_nodes, count) |
773 | - |
774 | - def test_shows_number_of_default_nodes_deployed_for_ubuntu_resource(self): |
775 | - self.client_log_in() |
776 | - resource = self.make_ubuntu_resource() |
777 | - os_name, series = resource.name.split('/') |
778 | - Config.objects.set_config('default_osystem', os_name) |
779 | - Config.objects.set_config('default_distro_series', series) |
780 | - number_of_nodes = random.randint(1, 4) |
781 | - for _ in range(number_of_nodes): |
782 | - factory.make_Node( |
783 | - status=NODE_STATUS.DEPLOYED, |
784 | - architecture=resource.architecture) |
785 | - response = self.client.get(reverse('images')) |
786 | - doc = fromstring(response.content) |
787 | - count = int(doc.cssselect( |
788 | - 'table#ubuntu-resources > tbody > tr > td')[4].text_content()) |
789 | - self.assertEqual(number_of_nodes, count) |
790 | - |
791 | - def test_shows_number_of_nodes_deployed_for_ubuntu_subarch_resource(self): |
792 | - self.client_log_in() |
793 | - resource = self.make_ubuntu_resource() |
794 | - arch, subarch = resource.split_arch() |
795 | - extra_subarch = factory.make_name('subarch') |
796 | - resource.extra['subarches'] = ','.join([subarch, extra_subarch]) |
797 | - resource.save() |
798 | - |
799 | - os_name, series = resource.name.split('/') |
800 | - node_architecture = '%s/%s' % (arch, extra_subarch) |
801 | - number_of_nodes = random.randint(1, 4) |
802 | - for _ in range(number_of_nodes): |
803 | - factory.make_Node( |
804 | - status=NODE_STATUS.DEPLOYED, |
805 | - osystem=os_name, distro_series=series, |
806 | - architecture=node_architecture) |
807 | - response = self.client.get(reverse('images')) |
808 | - doc = fromstring(response.content) |
809 | - count = int(doc.cssselect( |
810 | - 'table#ubuntu-resources > tbody > tr > td')[4].text_content()) |
811 | - self.assertEqual(number_of_nodes, count) |
812 | - |
813 | def test_hides_import_button_if_not_admin(self): |
814 | self.client_log_in() |
815 | sources = [factory.make_BootSource()] |
816 | @@ -225,18 +136,6 @@ |
817 | '#ubuntu-images')[0].cssselect('input[type="submit"]') |
818 | self.assertEqual(1, len(import_button)) |
819 | |
820 | - def test_hides_import_button_if_import_running(self): |
821 | - self.client_log_in() |
822 | - sources = [factory.make_BootSource()] |
823 | - self.patch_get_os_info_from_boot_sources(sources) |
824 | - self.patch( |
825 | - images_view, 'is_import_resources_running').return_value = True |
826 | - response = self.client.get(reverse('images')) |
827 | - doc = fromstring(response.content) |
828 | - import_button = doc.cssselect( |
829 | - '#ubuntu-images')[0].cssselect('input[type="submit"]') |
830 | - self.assertEqual(0, len(import_button)) |
831 | - |
832 | def test_post_returns_forbidden_if_not_admin(self): |
833 | self.client_log_in() |
834 | response = self.client.post( |