Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_list.html @ a583aa29

History | View | Annotate | Download (19.5 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
                    <th class="vmgroup">{% trans "Group" %}</th>
75
                    <th class="vmstatus">{% trans "Status" %}</th>
76
                </tr>
77
            </thead>
78
            <tbody class="machines"></tbody>
79
        </table>
80
        <!-- Drop down selector is commented out for v0.5
81
        <ul class="dropdown-selector" style="display: none">
82
            <li class="select-all" ><a href="#">{% trans "all" %}</a></li>
83
            <li class="select-none"><a href="#">{% trans "none" %}</a></li>
84
            <li class="select-group"><a href="#">{% trans "group" %}</a></li>
85
        </ul>
86
        -->
87
    </div>
88
</div>
89

    
90
<script>
91

92
init_action_indicator_handlers('list');
93

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

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

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

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

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

137
*/
138

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

153
// on checkbox click, update the actions
154
$("#machinesview .list tbody input[type='checkbox']").live('change', function() {
155
    update_listview_actions();
156
    pending_actions = [];
157
    $(".selected").removeClass('selected');
158
    return false;
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-details").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
    });
240
    $.cookie('server', serverID);
241
    $('a#single').click();
242
    return false;
243
});
244

245

246
function update_machines_view(data){
247
    /*
248
    Go through the servers in the input data. Update existing entries, add
249
    new ones to the list
250
    */
251
    tableData = vmTable.fnGetData();
252

253
    $.each(data.servers.values, function(i,server){
254
        current = -1;
255
        // check server status to select the appropriate OS icon, defaults to on state
256
        osTag = os_icon(server.metadata);
257
        var osIcon = osTag + "-on.png", imgStr, imgSrc;
258
        // check if the server already exists in the datatable
259
        if (tableData.length > 0) {
260
            tableData.forEach(function(row,index){
261
                if (row[0].split(' ')[2].replace('id=','') == server.id){
262
                    current = index;
263
                }
264
            });
265
        }
266
        if (current != -1) { // if it's there, update the values
267
            // get current status description, including non api states
268
            var server_row = $('#machinesview .list #' + server.id).parent().parent();
269
            var status_desc = server_row.find('span.status').text();
270
            // firebug console logging
271
            try {
272
                console.info(server.name + ' from ' + status_desc + ' to ' + STATUSES[server.status]);
273
            } catch(err) {}
274
            // when server is in deleted status it must be removed from the list
275
            if (server.status == "DELETED") {
276
                vmTable.fnDeleteRow(current);
277
            } else { // when server is not deleted, it should be updated
278
                if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
279
                    [STATUSES['STOPPED'], STATUSES['ERROR'], STATUSES['UNKNOWN'],
280
                     TRANSITIONS['Starting']].indexOf(server_row.find('span.status').text()) >= 0) {
281
                    // from stopped, on error or starting to building, active or rebooting
282
                    // starting is not an api state, it means the server is stopped or on error
283
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
284
                    imgSrc = "static/icons/indicators/small/wave.gif";
285
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
286
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
287
                    tableData[current][2] = "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>";
288
                    //tableData[current][4] = "group"; //TODO
289
                    tableData[current][5] = "<span class=status>" + STATUSES[server.status] + "</span>";
290
                    vmTable.fnUpdate(tableData[current],current);
291
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osIcon + "')", 1600);
292
                } else if (['STOPPED','ERROR', 'UNKNOWN'].indexOf(server.status) >= 0 &&
293
                           [STATUSES['ACTIVE'], STATUSES['BUILD'], STATUSES['REBOOT'],
294
                            TRANSITIONS['Shutting down']].indexOf(server_row.find('span.status').text()) >= 0) {
295
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
296
                    imgSrc = "static/icons/indicators/small/wave.gif";
297
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
298
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
299
                    tableData[current][2] = "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>";
300
                    //tableData[current][4] = "group"; //TODO
301
                    tableData[current][5] = "<span class=status>" + STATUSES[server.status] + "</span>";
302
                    vmTable.fnUpdate(tableData[current],current);
303
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osTag + "-off.png')", 1600);
304
                } else if ( STATUSES[server.status] == server_row.find('span.status').text()) {
305

306
                } else if (server.status == 'ACTIVE' &&
307
                           [STATUSES['BUILD'],TRANSITIONS['Rebooting']].indexOf(server_row.find('span.status').text()) >= 0) {
308
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
309
                    imgSrc = "static/icons/indicators/small/wave.gif";
310
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
311
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
312
                    tableData[current][2] = "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>";
313
                    //tableData[current][4] = "group"; //TODO
314
                    tableData[current][5] = "<span class=status>" + STATUSES[server.status] + "</span>";
315
                    vmTable.fnUpdate(tableData[current],current);
316
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osIcon + "')", 1600);
317
                }
318
            }
319
            update_listview_actions();
320
        } else if (server.status != "DELETED") { // does not exist, we should create it
321
            // check server status to select the appropriate OS icon
322
            if (['ERROR', 'STOPPED', 'UNKNOWN'].indexOf(server.status) >= 0) {
323
                osIcon = "static/icons/machines/small/" + osTag + "-off.png";
324
            } else if ( server.status == 'BUILD') {
325
                osIcon = "static/icons/indicators/small/progress.gif";
326
            } else {
327
                osIcon = "static/icons/machines/small/" + osTag + "-on.png";
328
            }
329
            // find flavor parameters
330
            var flavorLabel;
331
            if ( flavors.length > 0 ) {
332
                var current_flavor = '';
333
                for (i=0; i<flavors.length; i++) {
334
                    if (flavors[i]['id'] == server.flavorRef) {
335
                        current_flavor = flavors[i];
336
                    }
337
                }
338
                var flavor_label = '';
339
                if (current_flavor['cpu'] == '1') {
340
                    flavorLabel = '1 CPU, ';
341
                } else {
342
                    flavorLabel = current_flavor['cpu'] + ' CPUs, ';
343
                }
344
                flavorLabel = flavorLabel + current_flavor['ram'] + 'MB, ' + current_flavor['disk'] + 'GB';
345
            } else {
346
                flavorLabel = 'No flavor data';
347
            }
348

349
            // add new row to the table
350
            vmTable.fnAddData([
351
                "<input class=" + server.status + " id=" + server.id + " type=checkbox>",
352
                "<span class=imagetag>" + osTag + "</span><img class=list-logo src=" + osIcon +
353
                    " title=" + osTag + ">",
354
                "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>",
355
                "<a class=flavor><span>"+ flavorLabel + "</span></a>",
356
                "group",
357
                "<span class=status>" + STATUSES[server.status] + "</span>"
358
            ]);
359
        }
360
    });
361
    update_listview_actions();
362
    $("#machinesview .list > div.large-spinner").hide();
363
    // in case there are no data, leave the page empty
364
    if ($("#machinesview .list table.list-machines tbody").length > 0) {
365
        $("#machinesview .list div.dataTables_filter").show();
366
        $("#machinesview .list div.dataTables_filter input").show();
367
        $("#machinesview .list table.list-machines").show();
368
        $("#machinesview .list div.actions").show();
369
    }
370

371
    // show message in case user has no servers!
372
    if ($("#machinesview .list tbody.machines .dataTables_empty").length > 0) {
373
        standard_view();
374
    } else {
375
        hideWelcome();
376
        $("#machinesview_content").fadeIn("fast");
377
    }
378

379
    // set confirm box position
380
    if (window.innerHeight - 200 < $('#machinesview').height())
381
        $('.confirm_multiple').addClass('fixed');
382
    else
383
        $('.confirm_multiple').removeClass('fixed');
384

385
    $('#machinesview .list .dataTables_scrollHeadInner table').attr('style','');
386
    $('#machinesview .list .dataTables_scrollHeadInner th').attr('style','');
387
}
388

389
function display_success(serverID) {
390
    // do nothing
391
}
392

393
// indicate that the requested action was not completed
394
function display_failure(status, serverID, action, responseText) {
395
    osIcon = $('#machinesview .list #'+serverID).parent().parent().find('.list-logo');
396
    osIcon.attr('src',osIcon.attr('os'));
397
    ajax_error(status, serverID, action, responseText);
398
}
399

400
var vmTable = $("div.list table.list-machines").dataTable({
401
    "bInfo": false,
402
    "bRetrieve": true,
403
    "bPaginate": false,
404
    "bAutoWidth": false,
405
    "bSort": true,
406
    "bStateSave": true,
407
    "sScrollXInner": "500px",
408
    "aoColumnDefs": [
409
        { "bSortable": false, "aTargets": [ 0 ] }
410
    ]
411
});
412

413
// basic functions executed on page load
414
if ( flavors.length == 0 && images.length == 0 ) {
415
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
416
    update_flavors();
417
    // populate image list
418
    update_images();
419
} else if ( flavors.length == 0 && images.length != 0 ) {
420
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
421
    update_flavors();
422
} else if ( flavors.length != 0 && images.length == 0 ) {
423
    // populate image list
424
    update_images();
425
    update_vms(UPDATE_INTERVAL);
426
} else {
427
    // start updating vm list
428
    update_vms(UPDATE_INTERVAL);
429
}
430

431
// reposition multiple confirmation box on window resize
432
$(window).resize(function(){
433
    if (this.innerHeight - 200 < $('#machinesview').height())
434
        $('.confirm_multiple').addClass('fixed');
435
    else
436
        $('.confirm_multiple').removeClass('fixed');
437
});
438

439
// set the label of the multiple buttons
440
$('.confirm_multiple button.yes').text(VARIOUS["CONFIRM"]);
441
$('.confirm_multiple button.no').text(VARIOUS["CANCEL"]);
442
</script>