Statistics
| Branch: | Tag: | Revision:

root / ui / templates / standard.html @ 0a8e39b4

History | View | Annotate | Download (25 kB)

1
{% load i18n %}
2

    
3
<!-- the standard view -->
4
<div id="machinesview" class="standard">
5
    <div id="spinner"></div>
6
    <div class="machine" id="machine-template" style="display:none">
7
        <div class="actions">
8
            <a href="#" class="action-start">{% trans "Start" %}</a>
9
            <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
10
            <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
11
            <a href="#" class="action-console">{% trans "Console" %}</a>
12
            <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
13
        </div>        
14
        <div class="state">
15
            <div class="status">{% trans "Running" %}</div>
16
            <div class="indicator"></div>
17
            <div class="indicator"></div>
18
            <div class="indicator"></div>
19
            <div class="indicator"></div>
20
            <img class="spinner" style="display:none" src="/static/progress.gif" />
21
            <img class="wave" style="display:none" src="/static/wave.gif" />
22
        </div>
23
        <img class="logo" src="" />
24
        <div href="#" class="name">
25
            <h5 class="namecontainer editable">
26
                {% trans "Name: " %}<span class="name">node.name</span><span class="rename"></span>
27
                <div class="editbuttons" style="display:none">
28
                    <span class="save" />
29
                    <span class="cancel" />
30
                </div>
31
            </h5>
32
        </div>
33
        <a href="#" class="ip">
34
            <h5>{% trans "IP: " %}<span class="public">node.public_ip</span></h5>
35
        </a>
36
        <h5 class="settings">
37
            {% trans "Show:" %} 
38
            <a class="show-disks" href="#">{% trans "disks" %}</a> | 
39
            <a class="show-networks" href="#">{% trans "networks" %}</a> | 
40
            <a class="show-info" href="#">{% trans "more info" %}</a>
41
        </h5>
42
        <div class="info-content">
43
            <div class="metadata-separator"></div>
44
            <div class="metadata-container">
45
                <div class="vm-details metadata-column">
46
                    CPUs: 1<br />
47
                    RAM: 2048 (MB)<br />
48
                    System Disk: 20 (GB) <br /><br />
49
                    Image: Debian blah<br />
50
                    Image Size: 2.3 (GB)
51
                </div>
52
                <div class="vm-stats metadata-column">
53
                    CPU<br />
54
                    RAM<br />
55
                    S.Disk<br />
56
                    Net<br /><br />
57
                    details
58
                </div>
59
                <div class="vm-labels metadata-column">
60
                    Labels<br />
61
                    (4)<br />
62
                </div>
63
                <div class="vm-metadata metadata-column">
64
                    <div class="metadata-left">
65
                        Metadata:<br />
66
                        (7)
67
                    </div>
68
                    <div>
69
                        <div class="scrollable vertical">
70
                            <div class="items">
71
                                <div>
72
                                    <div class="item">OS</div>
73
                                    <div class="item">Description</div>
74
                                    <div class="item">Key3</div>
75
                                </div>
76
                                <div>
77
                                    <div class="item">Descripition</div>
78
                                    <div class="item">dsffa</div>
79
                                    <div class="item">dsfdas</div>
80
                                </div>
81
                                <div>
82
                                    <div class="item">dsfdas</div>
83
                                    <div class="item">sdfdsfsd</div>
84
                                </div>
85
                            </div>
86
                        </div>
87
                        <a class="prev" href="#">Less</a>
88
                        <a class="next" href="#">More</a>
89
                    </div>
90
                    <a href="#" class="manage-metadata">Manage Metadata</a>
91
                </div>
92
            </div>
93
            <div class="metadata-separator"></div>
94
        </div>
95
        <div class="confirm_single">
96
            <button class="yes">{% trans "Confirm" %}</button>
97
            <button class="no">{% trans "Cancel" %}</button>
98
        </div>
99
        <div class="action_error" align="center">
100
            {% trans "<span class='orange'>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
101
            <span class="code"></span>            
102
            <span class="message"></span>
103
            <button class="details">{% trans "Details" %}</button>
104
        </div>
105
        <div class="separator"></div>
106
    </div>
107
    <div class="running"></div>
108
    <div id="mini" class="separator"></div>
109
    <div class="terminated"></div>
110
</div>
111

    
112
<script>
113

114
$(".scrollable").scrollable({ vertical: true});        
115

116
//hide the all of the info contents
117
$(".info-content").hide();
118
//toggle the component with class info-content
119
$("a.show-info").live('click', function() {
120
    $(this).parent().parent().find(".info-content").slideToggle(600);
121
    return false;
122
});
123

124

125
// intercept manage metadata click
126
$("a.manage-metadata").live('click', function() {
127
    // get server name and server ID
128
    var serverID = $(this).parent().parent().parent().parent().attr("id");
129
    var serverName = $(this).parent().parent().parent().parent().find("span.name").text();
130
    // set server name to all related metadata dialogs
131
    $("#edit-dialog h3 span").text(serverName);
132
    $("#add-dialog h3 span").text(serverName);
133
    // set server id to all related metadata dialogs
134
    $("#edit-dialog h3 p").text(serverID);
135
    $("#add-dialog h3 p").text(serverID);
136
    show_metadata_wizard();
137
    return false;
138
});
139

140
//initiate machine renaming
141
$(".rename, h5.editable span.name").live('click', function() {
142
    $(this).parent().find('.name').html("<input id=\"txtEdit\" type=\"text\" class=\"nametextbox\" value=\"" +
143
                                        $(this).parent().find('.name').text() + 
144
                                        "\" / ><span class=\"oldValue\" style=\"display:none;\" >" + 
145
                                        $(this).parent().find('.name').text() + "</span>");
146
    $(this).parent().find('.rename').hide();
147
    $(this).parent().find(".editbuttons").fadeIn();
148
    $(this).parent().find(".nametextbox").focus().select();
149
    $(this).parent().removeClass('editable');
150

151
    //submit wizard by pressing enter on the name textbox
152
    $("#txtEdit").keydown(function (e) {
153
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
154
            $(this).parent().parent().find('div.editbuttons span.save').click();
155
                        return false;
156
                } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
157
            $(this).parent().parent().find('div.editbuttons span.cancel').click();
158
                        return true;
159
                }
160
    });
161
    return false;
162
});
163

164
//rename machine
165
$(".editbuttons .save").live('click', function() {
166
    serverID = $(this).closest('.machine').attr("id");
167
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
168
    if (serverName.trim() == ''){
169
        return false;
170
    }
171
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
172
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
173
    $(this).parent().parent().find(".rename").fadeIn("slow");
174
    rename(serverID, serverName);
175
    return false;
176
});
177

178
//cancel renaming
179
$(".editbuttons .cancel").live('click', function() {
180
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.name').find('.oldValue').text());
181
    $(this).parent().parent().find(".editbuttons").hide();
182
    $(this).parent().parent().find(".rename").fadeIn();
183
    $(this).parent().parent().addClass('editable');
184
});
185

186
// intercept reboot click 
187
$("div.actions a.action-reboot").live('click', function(){
188
    var serverID = $(this).parent().parent().attr("id");
189
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
190
    var found = false;
191
    
192
    $(this).parent().children('a').removeClass('selected');
193
    $(this).addClass('selected');
194
    $(this).parent().addClass('display');
195
    $(this).parent().parent().find('.action_error').hide();
196
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
197
        if (pending_actions[i][1]==serverID){
198
            pending_actions[i][0] = reboot;
199
            found = true
200
        }
201
    }
202
    if (!found) // no pending action for this server was found, so let's just add it to the list
203
        pending_actions.push([reboot, serverID, serverName])
204
    update_confirmations();
205
    return false;
206
});
207

208
// intercept shutdown click
209
$("div.actions a.action-shutdown").live('click', function(){ 
210
    var serverID = $(this).parent().parent().attr("id");
211
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
212
    var found = false;
213
    $(this).parent().children('a').removeClass('selected');
214
    $(this).addClass('selected');
215
    $(this).parent().addClass('display')
216
    $(this).parent().parent().find('.action_error').hide();
217

218
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
219
        if (pending_actions[i][1]==serverID){
220
            pending_actions[i][0] = shutdown;
221
            found = true
222
        }
223
    }
224
    if (!found) // no pending action for this server was found, so let's just add it to the list 
225
        pending_actions.push([shutdown, serverID, serverName])
226
    update_confirmations();
227
    return false;
228
});
229

230
// intercept start click
231
$("div.actions a.action-start").live('click', function(){ 
232
    var serverID = $(this).parent().parent().attr("id");
233
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
234
    var found = false;
235
    $(this).parent().children('a').removeClass('selected');
236
    $(this).addClass('selected');
237
    $(this).parent().addClass('display')
238
    $(this).parent().parent().find('.action_error').hide();
239

240
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
241
        if (pending_actions[i][1]==serverID){
242
            pending_actions[i][0] = start;
243
            found = true
244
        }
245
    }
246
    if (!found) // no pending action for this server was found, so let's just add it to the list
247
        pending_actions.push([start, serverID, serverName])
248
    update_confirmations();    
249
    return false;
250
});
251

252
// intercept console click
253
$("div.actions a.action-console").live('click', function(){
254
    var serverID = $(this).parent().parent().attr("id");
255
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
256
    var found = false;
257
    $(this).parent().children('a').removeClass('selected');
258
    $(this).addClass('selected');
259
    $(this).parent().addClass('display')
260
    $(this).parent().parent().find('.action_error').hide();
261

262
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
263
        if (pending_actions[i][1]==serverID){
264
            pending_actions[i][0] = open_console;
265
            found = true
266
        }
267
    }
268
    if (!found) // no pending action for this server was found, so let's just add it to the list
269
        pending_actions.push([open_console, serverID, serverName])
270
    update_confirmations();
271
    return false;
272
});
273

274

275
// intercept destroy click
276
$("div.actions a.action-destroy").live('click', function(){ 
277
    var serverID = $(this).parent().parent().attr("id");
278
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
279
    var found = false;
280
    $(this).parent().children('a').removeClass('selected');
281
    $(this).addClass('selected');
282
    $(this).parent().addClass('display')
283
    $(this).parent().parent().find('.action_error').hide();
284

285
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
286
        if (pending_actions[i][1]==serverID){
287
            pending_actions[i][0] = destroy;
288
            found = true
289
        }
290
    }
291
    if (!found) // no pending action for this server was found, so let's just add it to the list
292
        pending_actions.push([destroy, serverID, serverName])
293
    update_confirmations();    
294
    return false;
295
});
296

297
$("div.confirm_single .yes").live('click', function(){
298
    var serverID = $(this).parent().parent().attr("id");
299
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
300
        if (pending_actions[i][1]==serverID){
301
            action = pending_actions.splice(i,1)[0]; // extract action
302
            // change the status text in cases where no api state exists
303
            if (action[0] == start) {
304
                $(this).parent().parent().find('.status').text('Starting');
305
                $(this).parent().parent().find('.spinner').show();
306
            } else if (action[0] == shutdown) {
307
                $(this).parent().parent().find('.status').text('Shutting down');
308
                $(this).parent().parent().find('.spinner').show();
309
            } else if (action[0] == reboot) {
310
                $(this).parent().parent().find('.status').text('Rebooting');
311
                $(this).parent().parent().find('.spinner').show();
312
            }  else if (action[0] == destroy) {
313
                $(this).parent().parent().find('.status').text('Destroying');
314
                $(this).parent().parent().find('.spinner').show();
315
            }                    
316
            action[0]([action[1]]); // execute action
317
        }
318
    }
319
    $(this).parent().hide();
320
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
321
    $(this).parent().parent().children('.state').children('.spinner').show()
322
    $(this).parent().parent().children('div.actions').removeClass('display');
323
    update_confirmations(); 
324
    return false;
325
});
326

327
$("div.confirm_single .no").live('click', function(){
328
    // remove the action from the pending list
329
    var serverID = $(this).parent().parent().attr("id");
330
    
331
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
332
    $(this).parent().parent().children('div.actions').removeClass('display');    
333
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server remove it
334
        if (pending_actions[i][1]==serverID){
335
            pending_actions.splice(i,1);
336
        }
337
    }
338
    $(this).parent().hide();
339
    update_confirmations();    
340
    return false;
341
});
342

343
$("div.action_error .details").live('click', function(){
344
    // remove the action from the pending list
345
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
346
    $(this).parent().hide();
347
});
348

349

350
// update the servers list
351
function update_machines_view(data){
352
    /* 
353
    Go through the servers in the input data. Update existing entries, add
354
    new ones to the list
355
    */
356
    
357
    $.each(data.servers.values, function(i,server){
358
    
359
        existing = $('#' + server.id);
360
        
361
        // if multiple machines exist in the DOM, delete all but one
362
        // defensive coding - that shouldn't happen normally
363
        while (existing.length > 1){
364
            existing.remove();
365
        }
366

367
        var server_image = os_icon(server.metadata);
368

369
        // server already exists in DOM
370
        if (existing.length){
371
            $("div.machine:last-child").find("div.separator").show();                
372
            //  if the status is deleted, delete it from the DOM
373
            if (server.status == 'DELETED') {
374
                existing.remove();
375
                try {
376
                    console.info(existing.find("div.name span.name").text() + ' removed');
377
                } catch(err) {}            
378
            } else if (existing.find(".status").text() != STATUS_MESSAGES[server.status]) {
379
                try { // firebug console logging
380
                    console.info(existing.find("div.name span.name").text() + ' from ' 
381
                                + existing.find(".status").text() + ' to ' + STATUS_MESSAGES[server.status]);
382
                } catch(err) {}
383
                // show console action only on active servers, else hide it
384
                if (server.status == 'ACTIVE') {
385
                    $('div.#' + server.id + ' a.action-console').attr('style','');
386
                    $('div.#' + server.id + ' a.action-shutdown').removeClass('shutdown-padding');        
387
                } else {
388
                    $('div.#' + server.id + ' a.action-console').hide();
389
                }
390
                // show reboot and shutdown actions on active of rebooting servers
391
                if (server.status == 'ACTIVE' || server.status == 'REBOOT') {                   
392
                    $('div.#' + server.id + ' a.action-reboot').attr('style','');
393
                    $('div.#' + server.id + ' a.action-shutdown').attr('style','');
394
                    $('div.#' + server.id + ' a.action-destroy').removeClass('destroy-padding');        
395
                }
396
                if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
397
                    [STATUS_MESSAGES['STOPPED'], STATUS_MESSAGES['ERROR'],
398
                     'Starting'].indexOf(existing.find(".status").text()) >= 0) {
399
                    // from stopped, on error or starting to building, active or rebooting
400
                    // starting is not an api state, it means the vm is stopped or on error
401
                    moved = existing.clone().appendTo(".running");
402
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-on.png');
403
                    existing.remove();
404
                    existing = moved;
405
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
406
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
407
                           [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'], STATUS_MESSAGES['REBOOT'],
408
                            'Shutting down', 'Starting'].indexOf(existing.find(".status").text()) >= 0) {
409
                    // from active, building, rebooting, or shutting down to stopped or on error
410
                    // shutting down is not an api state, it means the server is active
411
                    moved = existing.clone().appendTo(".terminated");
412
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-off.png');
413
                    existing.remove();
414
                    existing = moved;
415
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
416
                } else if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 && 
417
                            [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'],
418
                             STATUS_MESSAGES['REBOOT']].indexOf(existing.find(".status").text()) >= 0) {
419
                    // the server changes status, but remains in running list
420
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
421
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
422
                    [STATUS_MESSAGES['STOPPED'], 
423
                     STATUS_MESSAGES['ERROR']].indexOf(existing.find(".status").text()) >= 0) {
424
                    // the server changes status, but remains in terminated list
425
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
426
                }        
427
                existing.find('.spinner').hide();
428
                existing.find(' .wave').attr('src','static/wave.gif').show();
429
                setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
430
                // show spinner while the server is rebooting, starting or shutting down  
431
                if ([STATUS_MESSAGES['REBOOT'], 
432
                    'Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) {
433
                    existing.find(' .wave').hide();
434
                    existing.find('.spinner').show();
435
                }                            
436
            } else if (existing.find(".status").text() == STATUS_MESSAGES['REBOOT'] && server.status == 'REBOOT') {
437
                    $('div.#' + server.id + ' a.action-console').hide();
438
                    $('div.#' + server.id + ' a.action-shutdown').addClass('shutdown-padding');
439
            }
440
            //existing.find(".status").text(STATUS_MESSAGES[server.status]);
441
            if (existing.find(".editbuttons").css('display') == 'none') { 
442
                existing.find("div.name span.name").text(server.name.substring(0,100));
443
            } else {
444
                existing.find(".editbuttons .cancel").click();
445
                existing.find("div.name span.name").text(server.name.substring(0,100));
446
            }
447
            existing.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));
448
        } else if (server.status != 'DELETED') {
449
            // If it does not exist and it's not deleted, we should create it
450
            var machine = $("#machine-template").clone().attr("id", server.id).fadeIn("slow");
451
            machine.find("div.name span.name").text(server.name.substring(0,100));
452
            machine.find("img.logo").attr("src","static/machines/"+server_image+'-on.png');
453
            machine.find("span.imagetag").text(server_image);
454
            machine.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));            
455
            machine.find(".status").text(STATUS_MESSAGES[server.status]);
456
            if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf(server.status) >= 0){
457
                machine.appendTo(".running");
458
            } else {
459
                machine.find("img.logo").attr("src","static/machines/"+server_image+'-off.png');
460
                machine.appendTo(".terminated");
461
            }
462
            //show spinner while machine is building
463
            if (server.status == 'BUILD' || 
464
                ['Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) { 
465
                machine.find('.spinner').show();
466
            }   
467
            //disable reboot and shutdown actions while machine is building
468
            if (server.status == 'BUILD') {
469
                $('div.#' + server.id + ' a.action-reboot').hide();
470
                $('div.#' + server.id + ' a.action-shutdown').hide();
471
                $('div.#' + server.id + ' a.action-destroy').addClass('destroy-padding');        
472
            }
473
            // show console action only on active servers
474
            if (server.status == 'ACTIVE') {
475
                $('div.#' + server.id + ' a.action-console').attr('style','');
476
            } else if (server.status == 'REBOOT'){
477
                $('div.#' + server.id + ' a.action-console').hide();
478
                $('div.#' + server.id + ' a.action-shutdown').addClass('shutdown-padding');
479
            } else {
480
                $('div.#' + server.id + ' a.action-console').hide();
481
            }
482
        } 
483
    });
484

485
    $("#spinner").hide();
486
    // show all separators
487
    $("div.machine div.separator").show();
488
    // hide the last one
489
    $("div.machine:last-child").find("div.separator").hide();
490
    // the separator shows only when running and terminated machines are available
491
    if ($(".terminated div.name").length > 0 && $(".running div.name").length > 0) {
492
        $("#mini.separator").fadeIn("slow");
493
    } else {
494
        $("#mini.separator").fadeOut("slow");
495
    }
496
    
497
    // show message in case user has no servers!
498
    if ($('.machine').length < 2) {
499
        showWelcome();
500
    } else {
501
        hideWelcome();
502
    }
503
    
504
    // set confirm box position
505
    if (window.innerHeight - 220 < $('#machinesview').height())
506
        $('.confirm_multiple').addClass('fixed');
507
    else
508
        $('.confirm_multiple').removeClass('fixed');
509
}
510

511
// indicate that the requested action was succesfully completed
512
function display_success(serverID) {
513

514
}
515

516
// indicate that the requested action was not completed
517
function display_failure(status, serverID, action, responseText) {
518
    $('#'+serverID+ ' .spinner').hide();
519
    $('#'+serverID+ ' .action_error .action').text(action);
520
    $('#'+serverID+ ' .action_error .code').text(status);
521
    $('#'+serverID+ ' .action_error .message').text(responseText);
522
    $('#'+serverID+ ' .action_error').show();    
523
}
524

525
// basic functions executed on page load
526
if ( flavors.length == 0 && images.length == 0 ) {
527
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
528
    update_flavors();
529
    // populate image list
530
    update_images(); 
531
} else if ( flavors.length == 0 && images.length != 0 ) {
532
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
533
    update_flavors();
534
} else if ( flavors.length != 0 && images.length == 0 ) {
535
    // populate image list
536
    update_images(); 
537
    update_vms(UPDATE_INTERVAL);
538
} else {
539
    // start updating vm list
540
    update_vms(UPDATE_INTERVAL);
541
}
542

543
// set the label of the multiple buttons 
544
$('div.confirm_multiple button.yes').text('Confirm All');
545
$('div.confirm_multiple button.no').text('Cancel All');
546

547
// reposition multiple confirmation box on window resize
548
$(window).resize(function(){
549
    if (this.innerHeight - 220 < $('#machinesview').height())
550
        $('.confirm_multiple').addClass('fixed');
551
    else
552
        $('.confirm_multiple').removeClass('fixed');
553
});
554
</script>