Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_list.html @ 9ac432ec

History | View | Annotate | Download (22.1 kB)

1
<!--
2
Copyright 2011 GRNET S.A. All rights reserved.
3

4
Redistribution and use in source and binary forms, with or
5
without modification, are permitted provided that the following
6
conditions are met:
7

8
  1. Redistributions of source code must retain the above
9
     copyright notice, this list of conditions and the following
10
     disclaimer.
11

12
  2. Redistributions in binary form must reproduce the above
13
     copyright notice, this list of conditions and the following
14
     disclaimer in the documentation and/or other materials
15
     provided with the distribution.
16

17
THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
POSSIBILITY OF SUCH DAMAGE.
29

30
The views and conclusions contained in the software and
31
documentation are those of the authors and should not be
32
interpreted as representing official policies, either expressed
33
or implied, of GRNET S.A.
34
-->
35

    
36
{% load i18n %}
37

    
38
<div id="machinesview-list" class="list">
39
    <div class="large-spinner"></div>
40
    <div id="machinesview_content">
41
        <div class="actions">
42
            <a id="action-start">{% trans "Start" %}</a>
43
            <a id="action-reboot">{% trans "Reboot" %}</a>
44
            <a id="action-shutdown">{% trans "Shutdown" %}</a>
45
            <br />
46
            <a id="action-destroy">{% trans "Destroy" %}</a>
47
            <br />
48
            <a id="action-details">{% trans "Show Details" %}</a>
49
            {% comment %}<a id="action-group">{% trans "Add to group" %}</a>{% endcomment %}
50
            <br />
51
            <a id="action-console">{% trans "Console" %}</a>
52
            <a id="action-connect">{% trans "Connect" %}</a>
53
            <br />
54
            {% comment %}
55
            <a id="action-attach">{% trans "Attach disk" %}</a>
56
            <a id="action-detach">{% trans "Detach disk" %}</a>
57
            <br />
58
            <a id="action-network-connect">{% trans "Connect to network" %}</a>
59
            <a id="action-network-disconnect">{% trans "Disconnect from net" %}</a>
60
            {% endcomment %}
61
        </div>
62
        <table class="list-machines" style="display: none">
63
            <thead>
64
                <tr>
65
                    <th class="selection select-running">
66
                        <input type="checkbox"/>
67
                        <!-- Drop down selector is commented out for v0.5
68
                        <div class="expand-icon"></div>
69
                        -->
70
                    </th>
71
                    <th class="vmos">{% trans "OS" %}</th>
72
                    <th class="vmname">{% trans "Name" %}</th>
73
                    <th class="vmflavor">{% trans "Flavor" %}</th>
74
                    <!--  Group column is commented out for v0.5
75
                    <th class="vmgroup">{% trans "Group" %}</th>
76
                    -->
77
                    <th class="vmstatus">{% trans "Status" %}</th>
78
                </tr>
79
            </thead>
80
            <tbody class="machines"></tbody>
81
        </table>
82
        <!-- Drop down selector is commented out for v0.5
83
        <ul class="dropdown-selector" style="display: none">
84
            <li class="select-all" ><a href="#">{% trans "all" %}</a></li>
85
            <li class="select-none"><a href="#">{% trans "none" %}</a></li>
86
            <li class="select-group"><a href="#">{% trans "group" %}</a></li>
87
        </ul>
88
        -->
89
    </div>
90
</div>
91

    
92
<script>
93

94
init_action_indicator_handlers('list');
95

96
// select/deselect all from checkbox widget of table headers
97
$("#machinesview .list table thead tr th.selection input:checkbox").click( function() {
98
    if ( $(this).is(":checked") ) {
99
        $(":checkbox").attr("checked", true);
100
    }
101
    else {
102
        $(":checkbox").attr("checked", false);
103
    }
104
    update_listview_actions();
105
});
106

107
/* Drop down selector is commented out for v0.5
108
// select all from drop down menu
109
$("#machinesview .list ul.dropdown-selector li.select-all a").live('click', function() {
110
    $(":checkbox").attr("checked", true);
111
    $(".dropdown-selector").slideToggle('medium');
112
    update_listview_actions();
113
    return false;
114
});
115

116
// select none from drop down menu
117
$("#machinesview .list ul.dropdown-selector li.select-none a").live('click', function() {
118
    $(":checkbox").attr("checked", false);
119
    $(".dropdown-selector").slideToggle('medium');
120
    update_listview_actions();
121
    return false;
122
});
123

124
// select group from drop down menu
125
$("#machinesview .list ul.dropdown-selector li.select-group a").live('click', function() {
126
    $(":checkbox").attr("checked", true);
127
    $(".dropdown-selector").slideToggle('medium');
128
    update_listview_actions();
129
    return false;
130
});
131

132
// menu toggle, running menu
133
$("#machinesview .list table.list-machines thead tr th.selection .expand-icon").click( function (obj) {
134
    $(".dropdown-selector").slideToggle('medium');
135
    return false;
136
});
137

138
*/
139

140
// TODO: This should be populated with more rules for all available states
141
//a key represents an action, while values are lists with permitted states to which the action can be applied
142
var actions = { 'reboot':        ['UNKOWN', 'ACTIVE', 'REBOOT', 'network', 'multiple'],
143
                'shutdown':      ['UNKOWN', 'ACTIVE', 'REBOOT', 'network', 'multiple'],
144
                'connect':       ['UNKOWN', 'network'],
145
                //'network-connect':       ['UNKOWN', 'ACTIVE'],
146
                //'network-disconnect':    ['UNKOWN', 'ACTIVE', 'network'],
147
                'console':       ['UNKOWN', 'ACTIVE', 'multiple', 'network'],
148
                'details':       ['UNKOWN', 'ACTIVE', 'REBOOT', 'STOPPED', 'network'],
149
                'start':         ['UNKOWN', 'STOPPED', 'multiple'],
150
                'destroy':       ['UNKOWN', 'ACTIVE', 'STOPPED', 'REBOOT', 'ERROR', 'BUILD', 'network', 'multiple']
151
                //'group':         ['UNKOWN', 'ACTIVE', 'STOPPED', 'REBOOT','multiple'],
152
               };
153

154
// on checkbox click, update the actions
155
$("#machinesview .list tbody input[type='checkbox']").live('click', function() {
156
    update_listview_actions();
157
    pending_actions = [];
158
    $(".selected").removeClass('selected');
159
});
160

161
// destroy action
162
$("#machinesview .list a.enabled#action-destroy").live('click', function() {
163
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
164
    $("#machinesview .list .selected").removeClass('selected');
165
    $(this).addClass('selected');
166
    pending_actions = []; // reset pending actions
167
    checked.each(function(i,c) {
168
        serverID=c.id;
169
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
170
        pending_actions.push([destroy, serverID]);
171
    });
172
    update_confirmations();
173
    return false;
174
});
175

176
$("#machinesview .list a.enabled#action-reboot").live('click', function() {
177
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
178
    $("#machinesview .list .selected").removeClass('selected');
179
    $(this).addClass('selected');
180
    pending_actions = []; // reset pending actions
181
    checked.each(function(i,c) {
182
        serverID=c.id;
183
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
184
        pending_actions.push([reboot, serverID]);
185
    });
186
    update_confirmations();
187
    return false;
188
});
189

190
$("#machinesview .list a.enabled#action-start").live('click', function() {
191
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
192
    $("#machinesview .list .selected").removeClass('selected');
193
    $(this).addClass('selected');
194
    pending_actions = []; // reset pending actions
195
    checked.each(function(i,c) {
196
        serverID=c.id;
197
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
198
        pending_actions.push([start, serverID]);
199
    });
200
    update_confirmations();
201
    return false;
202
});
203

204
$("#machinesview .list a.enabled#action-shutdown").live('click', function() {
205
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
206
    $("#machinesview .list .selected").removeClass('selected');
207
    $(this).addClass('selected');
208
    pending_actions = []; // reset pending actions
209
    checked.each(function(i,c) {
210
        serverID=c.id;
211
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
212
        pending_actions.push([shutdown, serverID]);
213
    });
214
    update_confirmations();
215
    return false;
216
});
217

218
$("#machinesview .list a.enabled#action-console").live('click', function() {
219
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
220
    $("#machinesview .list .selected").removeClass('selected');
221
    $(this).addClass('selected');
222
    pending_actions = []; // reset pending actions
223
    checked.each(function(i,c) {
224
        serverID=c.id;
225
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
226
        pending_actions.push([open_console, serverID]);
227
    });
228
    update_confirmations();
229
    return false;
230
});
231

232
$("#machinesview .list a.enabled#action-connect").live('click', function() {
233
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
234
    $("#machinesview .list .selected").removeClass('selected');
235
    $(this).addClass('selected');
236
    pending_actions = []; // reset pending actions
237
    checked.each(function(i,c) {
238
        serverID=c.id;
239
        serverName = $('#machinesview .list #'+serverID+' span.name').text();
240
        pending_actions.push([machine_connect, serverID]);
241
    });
242
    update_confirmations();
243
    return false;
244
});
245

246

247
$("#machinesview .list a.enabled#action-details").live('click', function() {
248
    var checked = $("#machinesview .list table.list-machines tbody input[type='checkbox']:checked");
249
    $("#machinesview .list .selected").removeClass('selected');
250
    $(this).addClass('selected');
251
    pending_actions = []; // reset pending actions
252
    checked.each(function(i,c) {
253
        serverID=c.id;
254
    });
255
    $.cookie('server', serverID);
256
    $('a#single').click();
257
    return false;
258
});
259

260

261
function update_machines_view(data){
262
    /*
263
    Go through the servers in the input data. Update existing entries, add
264
    new ones to the list
265
    */
266
    console.log("updating", data);
267
    tableData = vmTable.fnGetData();
268

269
    $.each(data.servers.values, function(i,server){
270
        
271
        current = -1;
272
        // check server status to select the appropriate OS icon, defaults to on state
273
        osTag = os_icon(server.metadata);
274
        var osIcon = osTag + "-on.png", imgStr, imgSrc;
275
        // check if the server already exists in the datatable
276
        if (tableData.length > 0) {
277
            // ie does not support forEach use jquery helper to iterate data
278
            $.each(tableData, function(index, row){
279
                if (row[0].split(' ')[2].replace('id=','') == server.id){
280
                    current = index;
281
                }
282
            });
283
        }
284
        if (current != -1) { // if it's there, update the values
285
            // get current status description, including non api states
286
            var server_row = $('#machinesview .list #' + server.id).parent().parent();
287
            var status_desc = server_row.find('span.status').text().replace(TRANSITION_STATE_APPEND, "");
288
            // firebug console logging
289
            try {
290
                console.info(server.name + ' from ' + status_desc + ' to ' + STATUSES[server.status]);
291
            } catch(err) {}
292
            // when server is in deleted status it must be removed from the list
293
            if (server.status == "DELETED") {
294
                vmTable.fnDeleteRow(current);
295
                } else { // when server is not deleted, it should be updated
296
                
297
                var current_status = server_row.find('span.status').text().replace(TRANSITION_STATE_APPEND, "");
298

299
                if (['BUILD', 'REBOOT'].indexOf(server.status) >= 0 && [TRANSITIONS['Starting'],STATUSES['ACTIVE']].indexOf(current_status) >= 0) {
300
                    // from running to reboot (or building which should never happen)
301
                    imgSrc = "static/icons/indicators/small/progress.gif";
302
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
303
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
304
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
305
                    tableData[current][2] = "<a class=name><span class=name>" + fix_server_name(server.name) + "</span></a>";
306
                    //tableData[current][4] = "group"; //TODO
307
                    tableData[current][4] = "<span class=status>" + STATUSES[server.status] + "</span>";
308
                    vmTable.fnUpdate(tableData[current],current);
309
                } else if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
310
                    [STATUSES['STOPPED'], STATUSES['ERROR'], STATUSES['UNKNOWN'], TRANSITIONS['Starting']].indexOf(current_status) >= 0) {
311
                    // from stopped, on error or starting to building, active or rebooting
312
                    // starting is not an api state, it means the server is stopped or on error
313
                    imgSrc = "static/icons/indicators/small/wave.gif";
314
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
315
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
316
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
317
                    tableData[current][2] = "<a class=name><span class=name>" + fix_server_name(server.name) + "</span></a>";
318
                    //tableData[current][4] = "group"; //TODO
319
                    tableData[current][4] = "<span class=status>" + STATUSES[server.status] + "</span>";
320
                    vmTable.fnUpdate(tableData[current],current);
321
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osIcon + "')", 1600);
322
                } else if (['STOPPED','ERROR', 'UNKNOWN'].indexOf(server.status) >= 0 &&
323
                           [STATUSES['ACTIVE'], STATUSES['BUILD'], STATUSES['REBOOT'],
324
                            TRANSITIONS['Shutting down']].indexOf(current_status) >= 0) {
325
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
326
                    imgSrc = "static/icons/indicators/small/wave.gif";
327
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
328
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
329
                    tableData[current][2] = "<a class=name><span class=name>" + fix_server_name(server.name) + "</span></a>";
330
                    //tableData[current][4] = "group"; //TODO
331
                    tableData[current][4] = "<span class=status>" + STATUSES[server.status] + "</span>";
332
                    vmTable.fnUpdate(tableData[current],current);
333
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osTag + "-off.png')", 1600);
334
                } else if ( STATUSES[server.status] == current_status) {
335

336
                } else if (server.status == 'ACTIVE' &&
337
                           [STATUSES['BUILD'],TRANSITIONS['Rebooting']].indexOf(current_status) >= 0) {
338
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
339
                    imgSrc = "static/icons/indicators/small/wave.gif";
340
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
341
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
342
                    tableData[current][2] = "<a class=name><span class=name>" + fix_server_name(server.name) + "</span></a>";
343
                    //tableData[current][4] = "group"; //TODO
344
                    tableData[current][4] = "<span class=status>" + STATUSES[server.status] + "</span>";
345
                    vmTable.fnUpdate(tableData[current],current);
346
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osIcon + "')", 1600);
347
                }
348
            }
349
            update_listview_actions();
350
        } else if (server.status != "DELETED") { // does not exist, we should create it
351
            // check server status to select the appropriate OS icon
352
            if (['ERROR', 'STOPPED', 'UNKNOWN'].indexOf(server.status) >= 0) {
353
                osIcon = "static/icons/machines/small/" + osTag + "-off.png";
354
            } else if ( server.status == 'BUILD' || server.status == "DESTROY" || server.status == "REBOOT") {
355
                osIcon = "static/icons/indicators/small/progress.gif";
356
            } else {
357
                osIcon = "static/icons/machines/small/" + osTag + "-on.png";
358
            }
359
            // find flavor parameters
360
            var flavorLabel;
361
            if ( flavors.length > 0 ) {
362
                var current_flavor = '';
363
                for (i=0; i<flavors.length; i++) {
364
                    if (flavors[i]['id'] == server.flavorRef) {
365
                        current_flavor = flavors[i];
366
                    }
367
                }
368
                var flavor_label = '';
369
                if (current_flavor['cpu'] == '1') {
370
                    flavorLabel = '1 CPU, ';
371
                } else {
372
                    flavorLabel = current_flavor['cpu'] + ' CPUs, ';
373
                }
374
                flavorLabel = flavorLabel + current_flavor['ram'] + 'MB, ' + current_flavor['disk'] + 'GB';
375
            } else {
376
                flavorLabel = 'No flavor data';
377
            }
378

379
            var status_string = STATUSES[server.status];
380

381
            // if destroy is requested don't change the state
382
            var server = get_machine(server.id);
383
            if (server.status == "DESTROY") {
384
                status_string = TRANSITIONS['Destroying'];
385
                osIcon = "static/icons/indicators/small/progress.gif";
386
            }
387

388
            // add new row to the table
389
            vmTable.fnAddData([
390
                "<input class=" + server.status + " id=" + server.id + " type=checkbox>",
391
                "<span class=imagetag>" + osTag + "</span><img class=list-logo src=" + osIcon +
392
                    " title=" + osTag + ">",
393
                "<a class=name><span class=name>" + fix_server_name(server.name) + "</span></a>",
394
                "<a class=flavor><span>"+ flavorLabel + "</span></a>",
395
                //"group",
396
                "<span class=status>" + status_string + "</span>"
397
            ]);
398
        }
399
        });
400

401
    update_transition_names();
402
    update_listview_actions();
403

404
    $("#machinesview .list > div.large-spinner").hide();
405
    // in case there are no data, leave the page empty
406
    if ($("#machinesview .list table.list-machines tbody").length > 0) {
407
        $("#machinesview .list div.dataTables_filter").show();
408
        $("#machinesview .list div.dataTables_filter input").show();
409
        $("#machinesview .list table.list-machines").show();
410
        $("#machinesview .list div.actions").show();
411
    }
412

413
    // show message in case user has no servers!
414
    if ($("#machinesview .list tbody.machines .dataTables_empty").length > 0) {
415
        standard_view();
416
    } else {
417
        hideWelcome();
418
        $("#machinesview_content").fadeIn("fast");
419
    }
420

421
    // set confirm box position
422
    if (window.innerHeight - 200 < $('#machinesview').height())
423
        $('.confirm_multiple').addClass('fixed');
424
    else
425
        $('.confirm_multiple').removeClass('fixed');
426

427
    $('#machinesview .list .dataTables_scrollHeadInner table').attr('style','');
428
    $('#machinesview .list .dataTables_scrollHeadInner th').attr('style','');
429
}
430

431
// define these to avoid exceptions
432
function display_reboot_success() {
433
}
434

435
function display_reboot_failure() {
436
}
437

438
// append string to transition states
439
function update_transition_names() {
440
    $("td span.status").each(function(index,el){
441
    var tr_text = $(this).text().replace(TRANSITION_STATE_APPEND,"");
442
    if (TRANSITION_STATES.indexOf(tr_text) >= 0) {
443
            $(this).text(tr_text + TRANSITION_STATE_APPEND);
444
        }
445
    })
446
}
447

448
function display_success(serverID) {
449
    // do nothing
450
}
451

452
// indicate that the requested action was not completed
453
function display_failure(status, serverID, action, responseText) {
454
    osIcon = $('#machinesview .list #'+serverID).parent().parent().find('.list-logo');
455
    osIcon.attr('src',osIcon.attr('os'));
456
    ajax_error(status, serverID, action, responseText);
457
}
458

459
var vmTable = $("div.list table.list-machines").dataTable({
460
    "bInfo": false,
461
    "bRetrieve": true,
462
    "bPaginate": false,
463
    "bAutoWidth": false,
464
    "bSort": true,
465
    "bStateSave": true,
466
    "sScrollXInner": "500px",
467
    "aoColumnDefs": [
468
        { "bSortable": false, "aTargets": [ 0 ] }
469
    ]
470
});
471

472
// basic functions executed on page load
473
if ( flavors.length == 0 && images.length == 0 ) {
474
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
475
    update_flavors();
476
    // populate image list
477
    update_images();
478
} else if ( flavors.length == 0 && images.length != 0 ) {
479
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
480
    update_flavors();
481
} else if ( flavors.length != 0 && images.length == 0 ) {
482
    // populate image list
483
    update_images();
484
    update_vms(UPDATE_INTERVAL);
485
} else {
486
    // start updating vm list
487
    update_vms(UPDATE_INTERVAL);
488
}
489

490
// reposition multiple confirmation box on window resize
491
$(window).resize(function(){
492
    if (this.innerHeight - 200 < $('#machinesview').height())
493
        $('.confirm_multiple').addClass('fixed');
494
    else
495
        $('.confirm_multiple').removeClass('fixed');
496
});
497

498
// set the label of the multiple buttons
499
$('.confirm_multiple button.yes').text(VARIOUS["CONFIRM"]);
500
$('.confirm_multiple button.no').text(VARIOUS["CANCEL"]);
501
</script>