Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ c9f5ed3f

History | View | Annotate | Download (32 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
<!-- the standard view -->
39
<div id="machinesview-icon" class="standard">
40
    <div class="machine-container" id="machine-container-template" style="display:none">
41
        <div class="machine" id="machine-template">
42
            <div class="actions">
43
                <a href="#" class="action-start">{% trans "Start" %}</a>
44
                <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
45
                <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
46
                <a href="#" class="action-console">{% trans "Console" %}</a>
47
                <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
48
            </div>
49
            <div class="confirm_single">
50
                <button class="yes">{% trans "Confirm" %}</button>
51
                <button class="no">{% trans "Cancel" %}</button>
52
            </div>
53
            <div class="action_error" align="center">
54
                {% trans "<span class='orange'>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
55
                <span class="code"></span>
56
                <span class="message"></span>
57
                <button class="details">{% trans "Details" %}</button>
58
            </div>
59
            <div class="state">
60
                <div class="status">{% trans "Running" %}</div>
61
                <div class="indicator1"></div>
62
                <div class="indicator2"></div>
63
                <div class="indicator3"></div>
64
                <div class="indicator4"></div>
65
                <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
66
                <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
67
            </div>
68
            <div class='connect-border'></div>
69
            <div class='connect-arrow'></div>
70
            <img class="logo" src="" />
71
            <div href="#" class="name">
72
                <h5 class="namecontainer editable">
73
                    <span class="name">node.name</span><span class="rename"></span>
74
                    <div class="editbuttons" style="display:none">
75
                        <div class="save"></div>
76
                        <div class="cancel"></div>
77
                    </div>
78
                </h5>
79
            </div>
80
            <a href="#" class="ip">
81
                <h5>{% trans "IP" %}: <span class="public">node.public_ip</span></h5>
82
            </a>
83
            <div class="info">
84
                <div class="info-header">
85
                    <span class="info-label">{% trans "info" %}</span>
86
                    <div class="toggler down"></div>
87
                </div>
88
                <div class="info-content">
89
                    <div class="metadata-separator"></div>
90
                    <div class="metadata-container">
91
                        <div class="vm-details metadata-column">
92
                            {% trans "CPUs" %}: <span class="cpu-data">1</span><br />
93
                            {% trans "RAM" %}: <span class="ram-data">2048</span> (MB)<br />
94
                            {% trans "System Disk" %}: <span class="disk-data">20</span> (GB) <br /><br />
95
                            {% trans "Image" %}: <span class="image-data">Debian</span><br />
96
                            {% trans "Image Size" %}: <span class="image-size-data">2.3</span> (GB)
97
                        </div>
98
                        <div class="vm-stats metadata-column">
99
                            {% trans "CPU" %} <img src="static/cpu-bar.png" class="metadata-bar" /><br />
100
                            {% trans "RAM" %} <img src="static/ram-bar.png" class="metadata-bar" /><br />
101
                            {% trans "S.Disk" %} <img src="static/cpu-bar.png" class="metadata-bar" /><br />
102
                            {% trans "Net" %} <img src="static/net-bar.png" class="metadata-bar" /><br /><br />
103
                            {% trans "details" %}
104
                        </div>
105
                        <div class="vm-metadata metadata-column">
106
                            <div class="metadata-left">
107
                                {% trans "Metadata" %}: <br />
108
                                (<span class="metadata-count">0</span>)
109
                            </div>
110
                            <div class="metadata-keys-container">
111
                                <div class="scrollable vertical">
112
                                    <div class="items">
113
                                    </div>
114
                                </div>
115
                                <div class="metadata-actions">
116
                                    <div class="prev"></div>
117
                                    <div class="next"></div>
118
                                </div>
119
                            </div>
120
                            <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
121
                        </div>
122
                    </div>
123
                    <div class="metadata-separator"></div>
124
                </div>
125
            </div>
126
        </div>
127
        <div class="separator"></div>
128
    </div>
129
    <div class="running"><div class="large-spinner"></div></div>
130
    <div class="terminated" style="display:none;"></div>
131
</div>
132

    
133
<script>
134
CONFIRMBOX_OFFSET = 200;
135

136
// actions on machine mouseover
137
$("#machinesview-icon.standard .machine").live('mouseover', function() {
138
    // show connect button only if the machine is active
139
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
140
        $(this).find("div.connect-arrow").show();
141
        $(this).find("div.connect-border").show();
142
    }
143
    // change color of info button
144
    $(this).find(".info-header").addClass('info-hover');
145
});
146

147
// actions on machine mouseout
148
$("#machinesview-icon.standard .machine").live('mouseout', function() {
149
    // hide connect button
150
    $(this).find("div.connect-arrow").hide();
151
    $(this).find("div.connect-border").hide();
152
    // change color of info button
153
    $(this).find(".info-header").removeClass('info-hover');
154
});
155

156
// actions on connect arrow border mouseover
157
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
158
    $(this).next().addClass('border-hover');
159
});
160

161
// actions on connect arrow border mouseout
162
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
163
    $(this).next().removeClass('border-hover');
164
});
165

166
// open console on machine logo click
167
$("#machinesview-icon.standard .running img.logo").live('click', function(){
168
    $(this).parent().parent().find("a.action-console").click();
169
    return false;
170
});
171

172
// open console on connect arrow click
173
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
174
    $(this).parent().parent().find("a.action-console").click();
175
    return false;
176
});
177

178
// open console on connect arrow border click
179
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
180
    $(this).parent().parent().find("a.action-console").click();
181
    return false;
182
});
183

184
//hide the all of the info contents
185
$("#machinesview-icon.standard .info-content").hide();
186
//toggle the component with class info-content
187
$("#machinesview-icon.standard div.info").live('click', function() {
188
    if ($(this).find('.toggler').hasClass('up')) {
189
        $(this).find('.toggler').removeClass('up');
190
        $(this).find('.toggler').addClass('down');
191
    } else {
192
        $(this).find('.toggler').removeClass('down');
193
        $(this).find('.toggler').addClass('up');
194
    }
195
    $(this).find(".info-content").slideToggle(600);
196
    return false;
197
});
198

199
// intercept manage metadata click
200
$("#machinesview-icon.standard a.manage-metadata").live('click', function() {
201
    // get server name and server ID
202
    var serverID = $(this).parent().parent().parent().parent().parent().attr("id");
203
    var serverName = $(this).parent().parent().parent().parent().parent().find("span.name").text();
204
    // set server name to all related metadata dialogs
205
    $("#metadata-wizard div.machine-name").text(serverName);
206
    if ($(this).parent().parent().parent().parent().parent().parent().hasClass('terminated')) {
207
        $("#metadata-wizard div#on-off").text('off');
208
    } else {
209
        $("#metadata-wizard div#on-off").text('on');
210
    }
211
    // set server id to all related metadata dialogs
212
    $("#metadata-wizard p").text(serverID);
213
    show_metadata_wizard();
214
    return false;
215
});
216

217
//initiate machine renaming
218
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
219
    $(this).parent().find('.name').html("<input id=\"txtEdit\" type=\"text\" class=\"nametextbox\" value=\"" +
220
                                        $(this).parent().find('.name').text() +
221
                                        "\" / ><span class=\"oldValue\">" +
222
                                        $(this).parent().find('.name').text() + "</span>");
223
    $(this).parent().find('.rename').hide();
224
    $(this).parent().find(".editbuttons").fadeIn();
225
    $(this).parent().find(".nametextbox").focus().select();
226
    $(this).parent().removeClass('editable');
227

228
    //submit wizard by pressing enter on the name textbox
229
    $("#txtEdit").keydown(function (e) {
230
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
231
            $(this).parent().parent().find('div.editbuttons span.save').click();
232
            return false;
233
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
234
            $(this).parent().parent().find('div.editbuttons span.cancel').click();
235
            return true;
236
        }
237
    });
238
    return false;
239
});
240

241
//rename machine
242
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
243
    serverID = $(this).closest('.machine-container').attr("id");
244
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
245
    if (serverName.trim() == ''){
246
        return false;
247
    }
248
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
249
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
250
    $(this).parent().parent().find(".rename").fadeIn("slow");
251
    rename(serverID, serverName);
252
    return false;
253
});
254

255
//cancel renaming
256
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
257
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
258
    $(this).parent().parent().find(".editbuttons").hide();
259
    $(this).parent().parent().find(".rename").fadeIn();
260
    $(this).parent().parent().addClass('editable');
261
    return false;
262
});
263

264
// intercept reboot click
265
$("#machinesview-icon.standard div.actions a.action-reboot").live('click', function(){
266
    var serverID = $(this).parent().parent().parent().attr("id");
267
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
268
    var found = false;
269

270
    $(this).parent().children('a').removeClass('selected');
271
    $(this).addClass('selected');
272
    $(this).parent().addClass('display');
273
    $(this).parent().parent().find('.action_error').hide();
274
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
275
        if (pending_actions[i][1]==serverID){
276
            pending_actions[i][0] = reboot;
277
            found = true
278
        }
279
    }
280
    if (!found) // no pending action for this server was found, so let's just add it to the list
281
        pending_actions.push([reboot, serverID, serverName])
282
    update_confirmations();
283
    return false;
284
});
285

286
// intercept shutdown click
287
$("#machinesview-icon.standard div.actions a.action-shutdown").live('click', function(){
288
    var serverID = $(this).parent().parent().parent().attr("id");
289
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
290
    var found = false;
291
    $(this).parent().children('a').removeClass('selected');
292
    $(this).addClass('selected');
293
    $(this).parent().addClass('display')
294
    $(this).parent().parent().find('.action_error').hide();
295

296
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
297
        if (pending_actions[i][1]==serverID){
298
            pending_actions[i][0] = shutdown;
299
            found = true
300
        }
301
    }
302
    if (!found) // no pending action for this server was found, so let's just add it to the list
303
        pending_actions.push([shutdown, serverID, serverName])
304
    update_confirmations();
305
    return false;
306
});
307

308
// intercept start click
309
$("#machinesview-icon.standard div.actions a.action-start").live('click', function(){
310
    var serverID = $(this).parent().parent().parent().attr("id");
311
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
312
    var found = false;
313
    $(this).parent().children('a').removeClass('selected');
314
    $(this).addClass('selected');
315
    $(this).parent().addClass('display')
316
    $(this).parent().parent().find('.action_error').hide();
317

318
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
319
        if (pending_actions[i][1]==serverID){
320
            pending_actions[i][0] = start;
321
            found = true
322
        }
323
    }
324
    if (!found) // no pending action for this server was found, so let's just add it to the list
325
        pending_actions.push([start, serverID, serverName])
326
    update_confirmations();
327
    return false;
328
});
329

330
// intercept console click
331
$("#machinesview-icon.standard div.actions a.action-console").live('click', function(){
332
    var serverID = $(this).parent().parent().parent().attr("id");
333
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
334
    var found = false;
335
    $(this).parent().children('a').removeClass('selected');
336
    $(this).addClass('selected');
337
    $(this).parent().addClass('display')
338
    $(this).parent().parent().find('.action_error').hide();
339

340
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
341
        if (pending_actions[i][1]==serverID){
342
            pending_actions[i][0] = open_console;
343
            found = true
344
        }
345
    }
346
    if (!found) // no pending action for this server was found, so let's just add it to the list
347
        pending_actions.push([open_console, serverID, serverName])
348
    update_confirmations();
349
    return false;
350
});
351

352

353
// intercept destroy click
354
$("#machinesview-icon.standard div.actions a.action-destroy").live('click', function(){
355
    var serverID = $(this).parent().parent().parent().attr("id");
356
    var serverName = $(this).parent().prevAll("div.name").find("span.name").text();
357
    var found = false;
358
    $(this).parent().children('a').removeClass('selected');
359
    $(this).addClass('selected');
360
    $(this).parent().addClass('display')
361
    $(this).parent().parent().find('.action_error').hide();
362

363
    for (i=0;i<pending_actions.length;i++){ // if there is already a pending action for this server replace it
364
        if (pending_actions[i][1]==serverID){
365
            pending_actions[i][0] = destroy;
366
            found = true
367
        }
368
    }
369
    if (!found) // no pending action for this server was found, so let's just add it to the list
370
        pending_actions.push([destroy, serverID, serverName])
371
    update_confirmations();
372
    return false;
373
});
374

375
$("#machinesview-icon.standard div.confirm_single .yes").live('click', function(){
376
    var serverID = $(this).parent().parent().parent().attr("id");
377
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
378
        if (pending_actions[i][1]==serverID){
379
            action = pending_actions.splice(i,1)[0]; // extract action
380
            // change the status text in cases where no api state exists
381
            if (action[0] == start) {
382
                $(this).parent().parent().find('.status').text(TRANSITIONS['Starting']);
383
                $(this).parent().parent().find('.state').removeClass().addClass('state starting-state');
384
                $(this).parent().parent().find('.spinner').show();
385
            } else if (action[0] == shutdown) {
386
                $(this).parent().parent().find('.status').text(TRANSITIONS['Shutting down']);
387
                $(this).parent().parent().find('.state').removeClass().addClass('state shutting-state');
388
                $(this).parent().parent().find('.spinner').show();
389
            } else if (action[0] == reboot) {
390
                $(this).parent().parent().find('.status').text(TRANSITIONS['Rebooting']);
391
                $(this).parent().parent().find('.state').removeClass().addClass('state rebooting-state');
392
                $(this).parent().parent().find('.spinner').show();
393
            }  else if (action[0] == destroy) {
394
                $(this).parent().parent().find('.status').text(TRANSITIONS['Destroying']);
395
                $(this).parent().parent().find('.state').removeClass().addClass('state destroying-state');
396
                $(this).parent().parent().find('.spinner').show();
397
            }
398
            action[0]([action[1]]); // execute action
399
        }
400
    }
401
    $(this).parent().hide();
402
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
403
    $(this).parent().parent().children('.state').children('.spinner').show()
404
    $(this).parent().parent().children('div.actions').removeClass('display');
405
    update_confirmations();
406
    return false;
407
});
408

409
$("#machinesview-icon.standard div.confirm_single .no").live('click', function(){
410
    // remove the action from the pending list
411
    var serverID = $(this).parent().parent().parent().attr("id");
412

413
    $(this).parent().parent().children('div.actions').children('a').removeClass('selected');
414
    $(this).parent().parent().children('div.actions').removeClass('display');
415
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server remove it
416
        if (pending_actions[i][1]==serverID){
417
            pending_actions.splice(i,1);
418
        }
419
    }
420
    $(this).parent().hide();
421
    update_confirmations();
422
    return false;
423
});
424

425
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
426
    // remove the action from the pending list
427
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
428
    $(this).parent().hide();
429
});
430

431
// TODO: This should be populated with more rules for all available states
432
var actions = { 'reboot':        ['UNKOWN', 'ACTIVE', 'REBOOT'],
433
                'shutdown':      ['UNKOWN', 'ACTIVE', 'REBOOT'],
434
                'console':       ['ACTIVE'],
435
                'start':         ['UNKOWN', 'STOPPED'],
436
                'destroy':       ['UNKOWN', 'ACTIVE', 'STOPPED', 'REBOOT', 'ERROR', 'BUILD']
437
               };
438

439
// update the servers list
440
function update_machines_view(data) {
441
    /*
442
    Go through the servers in the input data. Update existing entries, add
443
    new ones to the list
444
    */
445
    $.each(data.servers.values, function(i,server) {
446
        // get DOM element, if it exists
447
        existing = $('#machinesview-icon.standard #' + server.id);
448
        // get server OS, if it exists
449
        if (!(server.metadata == undefined)) {
450
            var server_image = os_icon(server.metadata);
451
        } else {
452
            var server_image = "unknown"
453
        }
454
        // get server status message, if it exists
455
        var current_message = existing.find(".status").text();
456
        // if multiple machines exist in the DOM, delete all but one
457
        // defensive coding - that shouldn't happen normally
458
        while (existing.length > 1){
459
            existing.remove();
460
        }
461
        // if server already exists in DOM, update its values
462
        if (existing.length){
463
            //  if the status is deleted
464
            if (server.status == 'DELETED') {
465
                // delete server entry from the DOM
466
                log_server_status_change(existing, 'DELETED');
467
                existing.remove();
468
            }
469
            // if the status has changed
470
            else if ( current_message != STATUSES[server.status]) {
471
                /*
472
                Here there are 4 possibilities:
473
                    1. From an active state to an inactive one
474
                    2. From an inactive state to an active one
475
                    3. From an active state to a different active one
476
                    4. From an inactive state to a different inactive one
477
                The last two (3, 4) can be dealt with the same way
478
                */
479
                if (ACTIVE_STATES.indexOf(current_message) >= 0 &&
480
                    INACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
481
                    // from an active state to an inactive one
482
                    log_server_status_change(existing, server.status);
483
                    moved = existing.clone().appendTo("#machinesview-icon.standard .terminated");
484
                    moved.find("img.logo").attr("src",'static/icons/machines/medium/' + server_image + '-off.png');
485
                    existing.remove();
486
                    existing = moved;
487
                    existing.find(".status").text(STATUSES[server.status]);
488
                    existing.find('.spinner').hide();
489
                    if ($("div.terminated").find("div.machine-container").length > 0) {
490
                        $("div.terminated").show();
491
                    }
492
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
493
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
494
                }
495
                else if (INACTIVE_STATES.indexOf(current_message) >= 0 &&
496
                         ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
497
                    // From an inactive state to an active one
498
                    log_server_status_change(existing, server.status);
499
                    moved = existing.clone().appendTo("#machinesview-icon.standard .running");
500
                    moved.find("img.logo").attr('src','static/icons/machines/medium/' + server_image + '-on.png');
501
                    existing.remove();
502
                    existing = moved;
503
                    existing.find(".status").text(STATUSES[server.status]);
504
                    existing.find('.spinner').hide();
505
                    if ($("div.terminated").find("div.machine-container").length == 0) {
506
                        $("div.terminated").hide();
507
                    }
508
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
509
                    existing.find('.state').removeClass().addClass('state running-state');
510
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
511
                }
512
                else {
513
                    // handling active to active or inactive to inactive changes
514
                    if (TRANSITIONS[current_message] && TRANSITIONS[current_message] != 'Rebooting') {
515
                        // don't do anything if it is still in transition
516
                    }
517
                    else if ((TRANSITIONS[current_message] == 'Rebooting' && server.status == 'ACTIVE') ||
518
                             (STATUSES['BUILD'] == current_message && server.status == 'ACTIVE')) {
519
                        // if it has been rebooted or just created
520
                        log_server_status_change(existing, server.status);
521
                        existing.find(".status").text(STATUSES[server.status]);
522
                        existing.find('.spinner').hide();
523
                        existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
524
                        existing.find('.state').removeClass().addClass('state running-state');
525
                        setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
526
                    }
527
                    else {
528
                        // in any other case just change the status and ignore spinners/waves
529
                        existing.find(".status").text(STATUSES[server.status]);
530
                        existing.appendTo("#machinesview-icon.standard .running");
531
                        existing.find('.state').removeClass().addClass('state running-state');
532
                    }
533
                }
534
            }
535
            // find and display ips
536
            var ips = get_public_ips(server);
537
            existing.find("a.ip span.public").text(ips['ip4']);
538
        }
539
        // if it doesn't exist and the server is not DELETED, make a new entry
540
        else if ( server.status != 'DELETED') {
541
            // clone the proper template and put basic values in
542
            var machine = $("#machinesview-icon.standard #machine-container-template").clone().attr("id", server.id).fadeIn("slow");
543
            machine.find(".scrollable").scrollable({vertical: true});
544
            machine.find("div.name span.name").text(server.name.substring(0,100));
545
            machine.find("span.imagetag").text(server_image);
546
            machine.find(".status").text(STATUSES[server.status]);
547
            // check server status to select where to append the new server to
548
            if (ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0 ) {
549
                // append to running
550
                machine.find("img.logo").attr("src","static/icons/machines/medium/"+server_image+'-on.png');
551
                machine.appendTo("#machinesview-icon.standard .running");
552
            } else {
553
                // append to terminated
554
                machine.find("img.logo").attr("src","static/icons/machines/medium/"+server_image+'-off.png');
555
                machine.appendTo("#machinesview-icon.standard .terminated");
556
                if (server.status == "STOPPED") { //if server status us stopped is a different case than status unknown/error
557
                    machine.find('.state').removeClass().addClass('state terminated-state');
558
                } else {
559
                       machine.find('.state').removeClass().addClass('state error-state');
560
                }
561
            }
562
            //show spinner if server is still building or rebooting
563
            if (server.status == 'BUILD') {
564
                machine.find('.spinner').show();
565
                machine.find('.state').removeClass().addClass('state build-state');
566
            }
567
            if (server.status == 'REBOOT') {
568
                machine.find('.spinner').show();
569
                machine.find('.state').removeClass().addClass('state rebooting-state');
570
            }
571
            // find and display flavor parameters
572
            var flavor_params = get_flavor_params(server.flavorRef);
573
            machine.find(".cpu-data").text(flavor_params['cpus']);
574
            machine.find(".ram-data").text(flavor_params['ram']);
575
            machine.find(".disk-data").text(flavor_params['disk']);
576
            // find and display image parameters
577
            var image_params = get_image_params(server.imageRef);
578
            machine.find(".image-data").text(image_params['name'].substring(0,15));
579
            machine.find(".image-size-data").text(image_params['size']);
580
            // find and display ips
581
            var ips = get_public_ips(server);
582
            machine.find("a.ip span.public").text(ips['ip4']);
583
        }
584
        /*
585
        Do some repeated actions that include:
586
            1. Update actions
587
            2. Metadata list updating
588
        */
589
        update_iconview_actions(server.id, server.status);
590
        if (!(server.metadata == undefined)) {
591
                list_metadata_keys(server.id, server.metadata.values);
592
        }
593
        machine.find("img.connect-arrow").hide();
594
    });
595
    /*
596
    Do some standard stuff, repeated each time
597
    FIXME: Can these be moved to a new function?
598
    */
599
    $("div.running > div.large-spinner").hide();
600
    // show all separators and hide the last one
601
    $("#machinesview-icon.standard div.machine-container div.separator").show();
602
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
603
    // the terminated div shows only when terminated machines are available
604
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
605
        $("div.terminated").fadeIn("slow");
606
    } else {
607
        $("div.terminated").fadeOut("slow");
608
    }
609
    // show message in case user has no servers!
610
    if ($('#machinesview-icon .machine-container').length < 2) {
611
        showWelcome();
612
    } else {
613
        hideWelcome();
614
    }
615
    // set confirm box position
616
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height())
617
        $('.confirm_multiple').addClass('fixed');
618
    else
619
        $('.confirm_multiple').removeClass('fixed');
620
}
621

622
// reposition multiple confirmation box on window resize
623
$(window).resize(function(){
624
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
625
        $('.confirm_multiple').addClass('fixed');
626
    else
627
        $('.confirm_multiple').removeClass('fixed');
628
});
629

630
// update metadata list
631
function list_metadata_keys(serverID, keys) {
632
    // empty the list if it already exists
633
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
634
    //start counter
635
    var i=0;
636
    // show values
637
    for (var key in keys) {
638
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
639
        i++;
640
    }
641
    //hide the metadata controls if we have less than 3 metadata
642
    if (i <= 3) {
643
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
644
    }
645
    //show the metadata controls if we have more than 3 metadata
646
    if (i > 3) {
647
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
648
    }
649
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
650
}
651

652
// indicate that the requested action was succesfully completed
653
function display_success(serverID) {
654

655
}
656

657
// indicate that the requested action was not completed
658
function display_failure(status, serverID, action, responseText) {
659
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
660
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
661
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
662
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
663
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
664
}
665

666
// basic functions executed on page load
667
if ( flavors.length == 0 && images.length == 0 ) {
668
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
669
    update_flavors();
670
    // populate image list
671
    update_images();
672
} else if ( flavors.length == 0 && images.length != 0 ) {
673
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
674
    update_flavors();
675
} else if ( flavors.length != 0 && images.length == 0 ) {
676
    // populate image list
677
    update_images();
678
    update_vms(UPDATE_INTERVAL);
679
} else {
680
    // start updating vm list
681
    update_vms(UPDATE_INTERVAL);
682
}
683

684
// set the label of the multiple buttons
685
$('.confirm_multiple button.yes').text('Confirm All');
686
$('.confirm_multiple button.no').text('Cancel All');
687

    
688
</script>