Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (17.3 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-destroy">{% trans "Destroy" %}</a>
12
        </div>        
13
        <div class="state">
14
            <div class="status">{% trans "Running" %}</div>
15
            <div class="indicator"></div>
16
            <div class="indicator"></div>
17
            <div class="indicator"></div>
18
            <div class="indicator"></div>
19
            <img class="spinner" style="display:none" src="/static/progress.gif" />
20
            <img class="wave" style="display:none" src="/static/wave.gif" />
21
        </div>
22
        <img class="logo" src="" />
23
        <a href="#" class="name">
24
            <h5>{% trans "Name: " %}<span class="name">node.name</span><span class="rename"></span></h5>
25
        </a>
26
        <a href="#" class="ip">
27
            <h5>{% trans "IP: " %}<span class="public">node.public_ip</span></h5>
28
        </a>
29
        <h5 class="settings">
30
            {% trans "Show:" %} 
31
            <a class="show-disks"href="#">{% trans "disks" %}</a> | 
32
            <a class="show-networks"href="#">{% trans "networks" %}</a> | 
33
            <a class="show-group"href="#">{% trans "group" %}</a> | 
34
            <a class="show-metadata" href="#">{% trans "metadata" %}</a>
35
        </h5>
36
        <div class="confirm_single">
37
            <button class="yes">{% trans "Confirm" %}</button>
38
            <button class="no">{% trans "Cancel" %}</button>
39
        </div>
40
        <div class="action_error" align="center">
41
            {% trans "<span class='orange'>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
42
            <span class="code"></span>            
43
            <span class="message"></span>
44
            <button class="details">{% trans "Details" %}</button>
45
        </div>
46
        <div class="separator"></div>
47
    </div>
48
    <div class="running"></div>
49
    <div id="mini" class="separator"></div>
50
    <div class="terminated"></div>
51
</div>
52

    
53
<script>
54

55
// intercept edit metadata click
56
$("a.show-metadata").live('click', function() {
57
    // get server name and server ID
58
    var serverID = $(this).parent().parent().attr("id");
59
    var serverName = $(this).parent().parent().find("span.name").text();
60
    // set server name to all related metadata dialogs
61
    $("#edit-dialog h3 span").text(serverName);
62
    $("#add-dialog h3 span").text(serverName);
63
    // set server id to all related metadata dialogs
64
    $("#edit-dialog h3 p").text(serverID);
65
    $("#add-dialog h3 p").text(serverID);
66
    show_metadata_edit_dialog();
67
    return false;
68
});
69

70
// intercept reboot click 
71
$("div.actions a.action-reboot").live('click', function(){
72
    var serverID = $(this).parent().parent().attr("id");
73
    var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
74
    var found = false;
75
    
76
    $(this).parent().children('a').removeClass('selected');
77
    $(this).addClass('selected');
78
    $(this).parent().addClass('display');
79
    $(this).parent().parent().find('.action_error').hide();
80
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
81
        if (pending_actions[i][1]==serverID){
82
            pending_actions[i][0] = reboot;
83
            found = true
84
        }
85
    }
86
    if (!found) // no pending action for this server was found, so let's just add it to the list
87
        pending_actions.push([reboot, serverID, serverName])
88
    update_confirmations();
89
    return false;
90
});
91

92
// intercept shutdown click
93
$("div.actions a.action-shutdown").live('click', function(){ 
94
    var serverID = $(this).parent().parent().attr("id");
95
    var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
96
    var found = false;
97
    $(this).parent().children('a').removeClass('selected');
98
    $(this).addClass('selected');
99
    $(this).parent().addClass('display')
100
    $(this).parent().parent().find('.action_error').hide();
101

102
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
103
        if (pending_actions[i][1]==serverID){
104
            pending_actions[i][0] = shutdown;
105
            found = true
106
        }
107
    }
108
    if (!found) // no pending action for this server was found, so let's just add it to the list 
109
        pending_actions.push([shutdown, serverID, serverName])
110
    update_confirmations();
111
    return false;
112
});
113

114
// intercept start click
115
$("div.actions a.action-start").live('click', function(){ 
116
    var serverID = $(this).parent().parent().attr("id");
117
    var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
118
    var found = false;
119
    $(this).parent().children('a').removeClass('selected');
120
    $(this).addClass('selected');
121
    $(this).parent().addClass('display')
122
    $(this).parent().parent().find('.action_error').hide();
123

124
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
125
        if (pending_actions[i][1]==serverID){
126
            pending_actions[i][0] = start;
127
            found = true
128
        }
129
    }
130
    if (!found) // no pending action for this server was found, so let's just add it to the list
131
        pending_actions.push([start, serverID, serverName])
132
    update_confirmations();    
133
    return false;
134
});
135

136
// intercept destroy click
137
$("div.actions a.action-destroy").live('click', function(){ 
138
    var serverID = $(this).parent().parent().attr("id");
139
    var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
140
    var found = false;
141
    $(this).parent().children('a').removeClass('selected');
142
    $(this).addClass('selected');
143
    $(this).parent().addClass('display')
144
    $(this).parent().parent().find('.action_error').hide();
145

146
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
147
        if (pending_actions[i][1]==serverID){
148
            pending_actions[i][0] = destroy;
149
            found = true
150
        }
151
    }
152
    if (!found) // no pending action for this server was found, so let's just add it to the list
153
        pending_actions.push([destroy, serverID, serverName])
154
    update_confirmations();    
155
    return false;
156
});
157

158
$("div.confirm_single .yes").live('click', function(){
159
    var serverID = $(this).parent().parent().attr("id");
160
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
161
        if (pending_actions[i][1]==serverID){
162
            action = pending_actions.splice(i,1)[0]; // extract action
163
            // change the status text in cases where no api state exists
164
            if (action[0] == start) {
165
                $(this).parent().parent().find('.status').text('Starting');
166
                $(this).parent().parent().find('.spinner').show();
167
            } else if (action[0] == shutdown) {
168
                $(this).parent().parent().find('.status').text('Shutting down');
169
                $(this).parent().parent().find('.spinner').show();
170
            } else if (action[0] == reboot) {
171
                $(this).parent().parent().find('.status').text('Rebooting');
172
                $(this).parent().parent().find('.spinner').show();
173
            }  else if (action[0] == destroy) {
174
                $(this).parent().parent().find('.status').text('Destroying');
175
                $(this).parent().parent().find('.spinner').show();
176
            }                    
177
            action[0]([action[1]]); // execute action
178
        }
179
    }
180
    $(this).parent().hide();
181
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
182
    $(this).parent().parent().children('.state').children('.spinner').show()
183
    $(this).parent().parent().children('div.actions').removeClass('display');
184
    update_confirmations(); 
185
    return false;
186
});
187

188
$("div.confirm_single .no").live('click', function(){
189
    // remove the action from the pending list
190
    var serverID = $(this).parent().parent().attr("id");
191
    
192
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
193
    $(this).parent().parent().children('div.actions').removeClass('display');    
194
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server remove it
195
        if (pending_actions[i][1]==serverID){
196
            pending_actions.splice(i,1);
197
        }
198
    }
199
    $(this).parent().hide();
200
    update_confirmations();    
201
    return false;
202
});
203

204
$("div.action_error .details").live('click', function(){
205
    // remove the action from the pending list
206
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
207
    $(this).parent().hide();
208
});
209

210

211
// update the servers list
212
function update_machines_view(data){
213
    /* 
214
    Go through the servers in the input data. Update existing entries, add
215
    new ones to the list
216
    */
217
    
218
    $.each(data.servers.values, function(i,server){
219
    
220
        existing = $('#' + server.id);
221
        
222
        // if multiple machines exist in the DOM, delete all but one
223
        // defensive coding - that shouldn't happen normally
224
        while (existing.length > 1){
225
            existing.remove();
226
        }
227

228
        var server_image = os_icon(server.metadata);
229

230
        // server already exists in DOM
231
        if (existing.length){
232
            $("div.machine:last-child").find("div.separator").show();                
233
            //  if the status is deleted, delete it from the DOM
234
            if (server.status == 'DELETED') {
235
                existing.remove();
236
                try {
237
                    console.info(existing.find("a.name span.name").text() + ' removed');
238
                } catch(err) {}            
239
            } else if (existing.find(".status").text() != STATUS_MESSAGES[server.status]) {
240
                try { // firebug console logging
241
                    console.info(existing.find("a.name span.name").text() + ' from ' 
242
                                + existing.find(".status").text() + ' to ' + STATUS_MESSAGES[server.status]);
243
                } catch(err) {}
244
                //show reboot and shutdown actions
245
                if (server.status == 'ACTIVE' || server.status == 'REBOOT') {
246
                    
247
                    $('div.#' + server.id + ' a.action-reboot').attr('style','');
248
                    $('div.#' + server.id + ' a.action-shutdown').attr('style','');
249
                    $('div.#' + server.id + ' a.action-destroy').removeClass('destroy-padding');        
250
                }
251
                if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 &&
252
                    [STATUS_MESSAGES['STOPPED'], STATUS_MESSAGES['ERROR'],
253
                     'Starting'].indexOf(existing.find(".status").text()) >= 0) {
254
                    // from stopped, on error or starting to building, active or rebooting
255
                    // starting is not an api state, it means the vm is stopped or on error
256
                    moved = existing.clone().appendTo(".running");
257
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-on.png');
258
                    existing.remove();
259
                    existing = moved;
260
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
261
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
262
                           [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'], STATUS_MESSAGES['REBOOT'],
263
                            'Shutting down'].indexOf(existing.find(".status").text()) >= 0) {
264
                    // from active, building, rebooting, or shutting down to stopped or on error
265
                    // shutting down is not an api state, it means the server is active
266
                    moved = existing.clone().appendTo(".terminated");
267
                    moved.find("img.logo").attr("src","static/machines/" + server_image + '-off.png');
268
                    existing.remove();
269
                    existing = moved;
270
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
271
                } else if (['BUILD','ACTIVE','REBOOT'].indexOf(server.status) >= 0 && 
272
                            [STATUS_MESSAGES['ACTIVE'], STATUS_MESSAGES['BUILD'],
273
                             STATUS_MESSAGES['REBOOT']].indexOf(existing.find(".status").text()) >= 0) {
274
                    // the server changes status, but remains in running list
275
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
276
                } else if (['STOPPED','ERROR'].indexOf(server.status) >= 0 &&
277
                    [STATUS_MESSAGES['STOPPED'], 
278
                     STATUS_MESSAGES['ERROR']].indexOf(existing.find(".status").text()) >= 0) {
279
                    // the server changes status, but remains in terminated list
280
                    existing.find(".status").text(STATUS_MESSAGES[server.status]); 
281
                }        
282
                existing.find('.spinner').hide();
283
                existing.find(' .wave').attr('src','static/wave.gif').show();
284
                setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
285
                // show spinner while the server is rebooting, starting or shutting down  
286
                if ([STATUS_MESSAGES['REBOOT'], 
287
                    'Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) {
288
                    existing.find(' .wave').hide();
289
                    existing.find('.spinner').show();
290
                }                            
291
            }
292
            existing.find("a.name span.name").text(server.name.substring(0,100));
293
            existing.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));
294
        } else if (server.status != 'DELETED') {
295
            // If it does not exist and it's not deleted, we should create it
296
            var machine = $("#machine-template").clone().attr("id", server.id).fadeIn("slow");
297
            machine.find("a.name span.name").text(server.name.substring(0,100));
298
            machine.find("img.logo").attr("src","static/machines/"+server_image+'-on.png');
299
            machine.find("span.imagetag").text(server_image);
300
            machine.find("a.ip span.public").text(String(server.addresses.values[0].values[0].addr).replace(',',' '));            
301
            machine.find(".status").text(STATUS_MESSAGES[server.status]);
302
            if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf(server.status) >= 0){
303
                machine.appendTo(".running");
304
            } else {
305
                machine.find("img.logo").attr("src","static/machines/"+server_image+'-off.png');
306
                machine.appendTo(".terminated");
307
            }
308
            //show spinner while machine is building
309
            if (server.status == 'BUILD' || 
310
                ['Starting', 'Shutting down'].indexOf(existing.find(".status").text()) >= 0 ) { 
311
                machine.find('.spinner').show();
312
            }   
313
            //allow destroy action only while machine is building
314
            if (server.status == 'BUILD') {
315
                $('div.#' + server.id + ' a.action-reboot').hide();
316
                $('div.#' + server.id + ' a.action-shutdown').hide();        
317
                $('div.#' + server.id + ' a.action-destroy').addClass('destroy-padding');        
318
            }
319
        }  else if (server.status == 'DELETED') {
320
        }
321
    });
322

323
    $("#spinner").hide();
324
    // show all separators
325
    $("div.machine div.separator").show();
326
    // hide the last one
327
    $("div.machine:last-child").find("div.separator").hide();
328
    // the separator shows only when running and terminated machines are available
329
    if ($(".terminated a.name").length > 0 && $(".running a.name").length > 0) {
330
        $("#mini.separator").fadeIn("slow");
331
    } else {
332
        $("#mini.separator").fadeOut("slow");
333
    }
334
    
335
    // show message in case user has no servers!
336
    if ($('.machine').length < 2) {
337
        showWelcome();
338
    } else {
339
        hideWelcome();
340
    }
341
    
342
    // set confirm box position
343
    if (window.innerHeight - 220 < $('#machinesview').height())
344
        $('.confirm_multiple').addClass('fixed');
345
    else
346
        $('.confirm_multiple').removeClass('fixed');
347
}
348

349
// indicate that the requested action was succesfully completed
350
function display_success(serverID) {
351

352
}
353

354
// indicate that the requested action was not completed
355
function display_failure(status, serverID, action, responseText) {
356
    $('#'+serverID+ ' .spinner').hide();
357
    $('#'+serverID+ ' .action_error .action').text(action);
358
    $('#'+serverID+ ' .action_error .code').text(status);
359
    $('#'+serverID+ ' .action_error .message').text(responseText);
360
    $('#'+serverID+ ' .action_error').show();    
361
}
362

363
// basic functions executed on page load
364
if (images.length == 0) {
365
    // populate image list
366
    update_images();
367
}
368
if (flavors.length == 0) {
369
    // configure flavors
370
    update_flavors(); 
371
}
372
// set the label of the multiple buttons 
373
$('div.confirm_multiple button.yes').text('Confirm All');
374
$('div.confirm_multiple button.no').text('Cancel All');
375
// reposition multiple confirmation box on window resize
376
$(window).resize(function(){
377
    if (this.innerHeight - 220 < $('#machinesview').height())
378
        $('.confirm_multiple').addClass('fixed');
379
    else
380
        $('.confirm_multiple').removeClass('fixed');
381
});
382
// start updating vm list
383
update_vms(UPDATE_INTERVAL);
384
</script>