Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_list.html @ a70fb308

History | View | Annotate | Download (19.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
                    <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
// select/deselect all from checkbox widget of table headers
93
$("#machinesview .list table thead tr th.selection :checkbox").live('change', function() {
94
    if ( $(this).is(":checked") ) {
95
        $(":checkbox").attr("checked", true);
96
    }
97
    else {
98
        $(":checkbox").attr("checked", false);
99
    }
100
    update_listview_actions();
101
    return false;
102
});
103

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

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

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

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

135
*/
136

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

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

159
$("div.confirm_multiple button").click(function() {
160
    $(".selected").removeClass('selected');
161
});
162

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

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

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

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

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

234
function update_machines_view(data){
235
    /*
236
    Go through the servers in the input data. Update existing entries, add
237
    new ones to the list
238
    */
239
    tableData = vmTable.fnGetData();
240

241
    $.each(data.servers.values, function(i,server){
242
        current = -1;
243
        // check server status to select the appropriate OS icon, defaults to on state
244
        osTag = os_icon(server.metadata);
245
        var osIcon = osTag + "-on.png", imgStr, imgSrc;
246

247
        // check if the server already exists in the datatable
248
        tableData.forEach(function(row,index){
249

250
            if (row[0].split(' ')[2].replace('id=','') == server.id){
251
                current = index;
252
            }
253
        });
254
        if (current != -1) { // if it's there, update the values
255
            // get current status description, including non api states
256
            var server_row = $('#machinesview .list #' + server.id).parent().parent();
257
            var status_desc = server_row.find('span.status').text();
258
            // firebug console logging
259
            try {
260
                console.info(server.name + ' from ' + status_desc + ' to ' + STATUSES[server.status]);
261
            } catch(err) {}
262
            // when server is in deleted status it must be removed from the list
263
            if (server.status == "DELETED") {
264
                vmTable.fnDeleteRow(current);
265
            } else { // when server is not deleted, it should be updated
266
                if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
267
                    [STATUSES['STOPPED'], STATUSES['ERROR'], STATUSES['UNKNOWN'],
268
                     TRANSITIONS['Starting']].indexOf(server_row.find('span.status').text()) >= 0) {
269
                    // from stopped, on error or starting to building, active or rebooting
270
                    // starting is not an api state, it means the server is stopped or on error
271
                    tableData[current][0] = "<input class="+server.status+" id="+server.id+" type=checkbox>";
272
                    imgSrc = "static/icons/indicators/small/wave.gif";
273
                    imgStr = "<img class=list-logo src=" + imgSrc + " title=" + osTag + "></img>";
274
                    tableData[current][1] = "<span class=imagetag>" + osTag + "</span>" + imgStr;
275
                    tableData[current][2] = "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>";
276
                    //tableData[current][4] = "group"; //TODO
277
                    tableData[current][5] = "<span class=status>" + STATUSES[server.status] + "</span>";
278
                    vmTable.fnUpdate(tableData[current],current);
279
                    setTimeout("$('#machinesview .list #"+server.id+"').parent().parent().find('.list-logo').attr('src','static/icons/machines/small/" + osIcon + "')", 1600);
280
                } else if (['STOPPED','ERROR', 'UNKNOWN'].indexOf(server.status) >= 0 &&
281
                           [STATUSES['ACTIVE'], STATUSES['BUILD'], STATUSES['REBOOT'],
282
                            TRANSITIONS['Shutting down']].indexOf(server_row.find('span.status').text()) >= 0) {
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/" + osTag + "-off.png')", 1600);
292
                } else if ( STATUSES[server.status] == server_row.find('span.status').text()) {
293

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

337
            // add new row to the table
338
            vmTable.fnAddData([
339
                "<input class=" + server.status + " id=" + server.id + " type=checkbox>",
340
                "<span class=imagetag>" + osTag + "</span><img class=list-logo src=" + osIcon +
341
                    " title=" + osTag + ">",
342
                "<a class=name><span class=name>" + server.name.substring(0,60) + "</span></a>",
343
                "<a class=flavor><span>"+ flavorLabel + "</span></a>",
344
                "group",
345
                "<span class=status>" + STATUSES[server.status] + "</span>"
346
            ]);
347
        }
348
    });
349
    update_listview_actions();
350
    $("#machinesview .list > div.large-spinner").hide();
351
    // in case there are no data, leave the page empty
352
    if ($("#machinesview .list table.list-machines tbody").length > 0) {
353
        $("#machinesview .list div.dataTables_filter").show();
354
        $("#machinesview .list div.dataTables_filter input").show();
355
        $("#machinesview .list table.list-machines").show();
356
        $("#machinesview .list div.actions").show();
357
    }
358

359
    // show message in case user has no servers!
360
    if ($("#machinesview .list tbody.machines .dataTables_empty").length > 0) {
361
        standard_view();
362
    } else {
363
        hideWelcome();
364
        $("#machinesview_content").fadeIn("fast");
365
    }
366

367
    // set confirm box position
368
    if (window.innerHeight - 200 < $('#machinesview').height())
369
        $('.confirm_multiple').addClass('fixed');
370
    else
371
        $('.confirm_multiple').removeClass('fixed');
372

373
    $('#machinesview .list .dataTables_scrollHeadInner table').attr('style','');
374
    $('#machinesview .list .dataTables_scrollHeadInner th').attr('style','');
375

376
}
377

378
function display_success(serverID) {
379
    // do nothing
380
}
381

382
// indicate that the requested action was not completed
383
function display_failure(status, serverID, action, responseText) {
384
    osIcon = $('#machinesview .list #'+serverID).parent().parent().find('.list-logo');
385
    osIcon.attr('src',osIcon.attr('os'));
386
    ajax_error(status, serverID, action, responseText);
387
}
388

389
var vmTable = $("div.list table.list-machines").dataTable({
390
    "bInfo": false,
391
    "bRetrieve": true,
392
    "bPaginate": false,
393
    "bAutoWidth": false,
394
    "bSort": true,
395
    "bStateSave": true,
396
    "sScrollY": "270px",
397
    "sScrollX": "515px",
398
    "sScrollXInner": "500px",
399
    "aoColumnDefs": [
400
        { "bSortable": false, "aTargets": [ 0 ] }
401
    ]
402
});
403

404
// basic functions executed on page load
405
if ( flavors.length == 0 && images.length == 0 ) {
406
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
407
    update_flavors();
408
    // populate image list
409
    update_images();
410
} else if ( flavors.length == 0 && images.length != 0 ) {
411
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
412
    update_flavors();
413
} else if ( flavors.length != 0 && images.length == 0 ) {
414
    // populate image list
415
    update_images();
416
    update_vms(UPDATE_INTERVAL);
417
} else {
418
    // start updating vm list
419
    update_vms(UPDATE_INTERVAL);
420
}
421

422
// reposition multiple confirmation box on window resize
423
$(window).resize(function(){
424
    if (this.innerHeight - 200 < $('#machinesview').height())
425
        $('.confirm_multiple').addClass('fixed');
426
    else
427
        $('.confirm_multiple').removeClass('fixed');
428
});
429

430
// set the label of the multiple buttons
431
$('.confirm_multiple button.yes').text({% trans 'Confirm' %});
432
$('.confirm_multiple button.no').text({% trans 'Cancel' %});
433
</script>