Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ e5b6f8f8

History | View | Annotate | Download (33.5 kB)

1
<!--
2
Copyright 2011 GRNET S.A. All rights reserved.
3

4
Redistribution and use in source and binary forms, with or
5
without modification, are permitted provided that the following
6
conditions are met:
7

8
  1. Redistributions of source code must retain the above
9
     copyright notice, this list of conditions and the following
10
     disclaimer.
11

12
  2. Redistributions in binary form must reproduce the above
13
     copyright notice, this list of conditions and the following
14
     disclaimer in the documentation and/or other materials
15
     provided with the distribution.
16

17
THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
POSSIBILITY OF SUCH DAMAGE.
29

30
The views and conclusions contained in the software and
31
documentation are those of the authors and should not be
32
interpreted as representing official policies, either expressed
33
or implied, of GRNET S.A.
34
-->
35

    
36
{% load i18n %}
37

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

    
159
<script>
160
CONFIRMBOX_OFFSET = 200;
161

162
// actions on machine mouseover
163
$("#machinesview-icon.standard .machine").live('mouseover', function() {
164
    // show connect button only if the machine is active
165
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
166
        $(this).find("div.connect-arrow").show();
167
        $(this).find("div.connect-border").show();
168
    }
169
});
170

171
// actions on machine mouseout
172
$("#machinesview-icon.standard .machine").live('mouseout', function() {
173
    // hide connect button
174
    $(this).find("div.connect-arrow").hide();
175
    $(this).find("div.connect-border").hide();
176
});
177

178
// actions on connect arrow border mouseover
179
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
180
    $(this).next().addClass('border-hover');
181
});
182

183
// actions on connect arrow border mouseout
184
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
185
    $(this).next().removeClass('border-hover');
186
});
187

188
// open console on machine logo click
189
$("#machinesview-icon.standard .running img.logo").live('click', function(){
190
    $(this).parent().parent().find("a.action-console").click();
191
    return false;
192
});
193

194
// open console on connect arrow click
195
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
196
    $(this).parent().parent().find("a.action-console").click();
197
    return false;
198
});
199

200
// open console on connect arrow border click
201
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
202
    $(this).parent().parent().find("a.action-console").click();
203
    return false;
204
});
205

206
//hide the all of the info contents
207
$("#machinesview-icon.standard .info-content").hide();
208
//toggle the component with class info-content
209
$("#machinesview-icon.standard div.info-header").live('click', function() {
210
    if ($(this).find('.toggler').hasClass('up')) {
211
        $(this).find('.toggler').removeClass('up');
212
        $(this).find('.toggler').addClass('down');
213
        $(this).find('.info-label').removeClass('darker');
214
        $(this).parent().parent().removeClass('light-background');
215
    } else {
216
        $(this).find('.toggler').removeClass('down');
217
        $(this).find('.toggler').addClass('up');
218
        $(this).find('.info-label').addClass('darker');
219
        $(this).parent().parent().addClass('light-background');
220
    }
221
    $(this).parent().find(".info-content").slideToggle(600);
222
    return false;
223
});
224

225
// intercept manage metadata click
226
$("#machinesview-icon.standard a.manage-metadata").live('click', function() {
227
    // get server name and server ID
228
    var serverID = $(this).closest('.machine-container').attr("id");
229
    var serverName = $(this).closest('.machine').find("span.name").text();
230
    // set server name to all related metadata dialogs
231
    $("#metadata-wizard div.machine-name").text(serverName);
232
    if ($(this).closest('.machine-container').parent().hasClass('terminated')) {
233
        $("#metadata-wizard div#on-off").text('off');
234
    } else {
235
        $("#metadata-wizard div#on-off").text('on');
236
    }
237
    // set server id to all related metadata dialogs
238
    $("#metadata-wizard p").text(serverID);
239
    show_metadata_wizard();
240
    return false;
241
});
242

243
//initiate machine renaming
244
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
245
    $(this).parent().find('.name').html("<input id=\"txtEdit\" type=\"text\" class=\"nametextbox\" value=\"" +
246
                                        $(this).parent().find('.name').text() +
247
                                        "\" / ><span class=\"oldValue\">" +
248
                                        $(this).parent().find('.name').text() + "</span>");
249
    $(this).parent().find('.rename').hide();
250
    $(this).parent().find(".editbuttons").fadeIn();
251
    $(this).parent().find(".nametextbox").focus().select();
252
    $(this).parent().removeClass('editable');
253

254
    //submit wizard by pressing enter on the name textbox
255
    $("#txtEdit").keydown(function (e) {
256
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
257
            $(this).parent().parent().find('div.editbuttons span.save').click();
258
            return false;
259
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
260
            $(this).parent().parent().find('div.editbuttons span.cancel').click();
261
            return true;
262
        }
263
    });
264
    return false;
265
});
266

267
//rename machine
268
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
269
    serverID = $(this).closest('.machine-container').attr("id");
270
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
271
    if (serverName.trim() == ''){
272
        return false;
273
    }
274
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
275
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
276
    $(this).parent().parent().find(".rename").fadeIn("slow");
277
    rename(serverID, serverName);
278
    return false;
279
});
280

281
//cancel renaming
282
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
283
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
284
    $(this).parent().parent().find(".editbuttons").hide();
285
    $(this).parent().parent().find(".rename").fadeIn();
286
    $(this).parent().parent().addClass('editable');
287
    return false;
288
});
289

290
// intercept reboot click
291
$("#machinesview-icon.standard div.actions a.action-reboot").live('click', function() {
292
    // get server id and server name from DOM
293
    var serverID = $(this).closest("div.machine-container").attr("id");
294
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
295
    var found = false;
296
    // show/hide proper menus
297
    $(this).parent().parent().find('a').removeClass('selected');
298
    $(this).addClass('selected');
299
    $(this).parent().parent().addClass('display');
300
    $(this).closest("div.machine").find('.action_error').hide();
301
    // if there is already a pending action for this server replace it
302
    for (i=0; i<pending_actions.length; i++) {
303
        if (pending_actions[i][1]==serverID) {
304
            pending_actions[i][0] = reboot;
305
            found = true
306
        }
307
    }
308
    // no pending action for this server was found, so let's just add it to the list
309
    if (!found)
310
        pending_actions.push([reboot, serverID, serverName])
311
    // pass the proper action to update confirmation boxes
312
    update_confirmations();
313
    return false;
314
});
315

316
// intercept shutdown click
317
$("#machinesview-icon.standard div.actions a.action-shutdown").live('click', function() {
318
    // get server id and server name from DOM
319
    var serverID = $(this).closest("div.machine-container").attr("id");
320
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
321
    var found = false;
322
    // show/hide proper menus
323
    $(this).parent().parent().find('a').removeClass('selected');
324
    $(this).addClass('selected');
325
    $(this).parent().parent().addClass('display');
326
    $(this).closest("div.machine").find('.action_error').hide();
327
    // if there is already a pending action for this server replace it
328
    for (i=0; i<pending_actions.length; i++) {
329
        if (pending_actions[i][1]==serverID) {
330
            pending_actions[i][0] = shutdown;
331
            found = true
332
        }
333
    }
334
    // no pending action for this server was found, so let's just add it to the list
335
    if (!found)
336
        pending_actions.push([shutdown, serverID, serverName])
337
    update_confirmations();
338
    return false;
339
});
340

341
// intercept start click
342
$("#machinesview-icon.standard div.actions a.action-start").live('click', function() {
343
    // get server id and server name from DOM
344
    var serverID = $(this).closest("div.machine-container").attr("id");
345
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
346
    var found = false;
347
    // show/hide proper menus
348
    $(this).parent().parent().find('a').removeClass('selected');
349
    $(this).addClass('selected');
350
    $(this).parent().parent().addClass('display');
351
    $(this).closest("div.machine").find('.action_error').hide();
352
    // if there is already a pending action for this server replace it
353
    for (i=0; i<pending_actions.length; i++) {
354
        if (pending_actions[i][1]==serverID) {
355
            pending_actions[i][0] = start;
356
            found = true
357
        }
358
    }
359
    // no pending action for this server was found, so let's just add it to the list
360
    if (!found)
361
        pending_actions.push([start, serverID, serverName])
362
    update_confirmations();
363
    return false;
364
});
365

366
// intercept console click
367
$("#machinesview-icon.standard div.actions a.action-console").live('click', function() {
368
    // get server id and server name from DOM
369
    var serverID = $(this).closest("div.machine-container").attr("id");
370
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
371
    var found = false;
372
    // show/hide proper menus
373
    $(this).parent().parent().find('a').removeClass('selected');
374
    $(this).addClass('selected');
375
    $(this).parent().parent().addClass('display');
376
    $(this).closest("div.machine").find('.action_error').hide();
377
    // if there is already a pending action for this server replace it
378
    for (i=0; i<pending_actions.length; i++) {
379
        if (pending_actions[i][1]==serverID) {
380
            pending_actions[i][0] = open_console;
381
            found = true
382
        }
383
    }
384
    // no pending action for this server was found, so let's just add it to the list
385
    if (!found)
386
        pending_actions.push([open_console, serverID, serverName])
387
    update_confirmations();
388
    return false;
389
});
390

391

392
// intercept destroy click
393
$("#machinesview-icon.standard div.actions a.action-destroy").live('click', function() {
394
    // get server id and server name from DOM
395
    var serverID = $(this).closest("div.machine-container").attr("id");
396
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
397
    var found = false;
398
    // show/hide proper menus
399
    $(this).parent().parent().find('a').removeClass('selected');
400
    $(this).addClass('selected');
401
    $(this).parent().parent().addClass('display');
402
    $(this).closest("div.machine").find('.action_error').hide();
403
    // if there is already a pending action for this server replace it
404
    for (i=0; i<pending_actions.length; i++) {
405
        if (pending_actions[i][1]==serverID) {
406
            pending_actions[i][0] = destroy;
407
            found = true
408
        }
409
    }
410
    // no pending action for this server was found, so let's just add it to the list
411
    if (!found)
412
        pending_actions.push([destroy, serverID, serverName])
413
    update_confirmations();
414
    return false;
415
});
416

417
$("#machinesview-icon.standard div.confirm_single button.yes").live('click', function(){
418
    var serverID = $(this).closest("div.machine-container").attr("id");
419
    // if there is a pending action for this server execute it
420
    for (i=0; i<pending_actions.length; i++) {
421
        if (pending_actions[i][1]==serverID){
422
            action = pending_actions.splice(i,1)[0]; // extract action
423
            // change the status text in cases where no api state exists
424
            if (action[0] == start) {
425
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Starting']);
426
                $(this).closest("div.machine").find('.state').removeClass().addClass('state starting-state');
427
                $(this).closest("div.machine").find('.spinner').show();
428
            } else if (action[0] == shutdown) {
429
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Shutting down']);
430
                $(this).closest("div.machine").find('.state').removeClass().addClass('state shutting-state');
431
                $(this).closest("div.machine").find('.spinner').show();
432
            } else if (action[0] == reboot) {
433
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Rebooting']);
434
                $(this).closest("div.machine").find('.state').removeClass().addClass('state rebooting-state');
435
                $(this).closest("div.machine").find('.spinner').show();
436
            }  else if (action[0] == destroy) {
437
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Destroying']);
438
                $(this).closest("div.machine").find('.state').removeClass().addClass('state destroying-state');
439
                $(this).closest("div.machine").find('.spinner').show();
440
            }
441
            action[0]([action[1]]); // execute action
442
        }
443
    }
444
    $(this).parent().hide();
445
    $(this).closest('div.actions').find('a').removeClass('selected');
446
    $(this).closest("div.machine").children('.state').children('.spinner').show()
447
    $(this).closest("div.machine").children('div.actions').removeClass('display');
448
    update_confirmations();
449
    return false;
450
});
451

452
$("#machinesview-icon.standard div.confirm_single button.no").live('click', function(){
453
    // remove the action from the pending list
454
    var serverID = $(this).closest("div.machine-container").attr("id");
455

456
    $(this).closest('div.action-container').children('a').removeClass('selected');
457
    $(this).closest('div.actions').removeClass('display');
458
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
459
        if (pending_actions[i][1]==serverID) {
460
            pending_actions.splice(i,1);
461
        }
462
    }
463
    $(this).parent().hide();
464
    update_confirmations();
465
    return false;
466
});
467

468
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
469
    // remove the action from the pending list
470
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
471
    $(this).parent().hide();
472
});
473

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

658
// reposition multiple confirmation box on window resize
659
$(window).resize(function(){
660
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
661
        $('.confirm_multiple').addClass('fixed');
662
    else
663
        $('.confirm_multiple').removeClass('fixed');
664
});
665

666
// update metadata list
667
function list_metadata_keys(serverID, keys) {
668
    // empty the list if it already exists
669
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
670
    //start counter
671
    var i=0;
672
    // show values
673
    for (var key in keys) {
674
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
675
        i++;
676
    }
677
    //hide the metadata controls if we have less than 3 metadata
678
    if (i <= 3) {
679
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
680
    }
681
    //show the metadata controls if we have more than 3 metadata
682
    if (i > 3) {
683
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
684
    }
685
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
686
}
687

688
// indicate that the requested action was succesfully completed
689
function display_success(serverID) {
690

691
}
692

693
// indicate that the requested action was not completed
694
function display_failure(status, serverID, action, responseText) {
695
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
696
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
697
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
698
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
699
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
700
}
701

702
// basic functions executed on page load
703
if ( flavors.length == 0 && images.length == 0 ) {
704
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
705
    update_flavors();
706
    // populate image list
707
    update_images();
708
} else if ( flavors.length == 0 && images.length != 0 ) {
709
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
710
    update_flavors();
711
} else if ( flavors.length != 0 && images.length == 0 ) {
712
    // populate image list
713
    update_images();
714
    update_vms(UPDATE_INTERVAL);
715
} else {
716
    // start updating vm list
717
    update_vms(UPDATE_INTERVAL);
718
}
719

720
// set the label of the multiple buttons
721
$('.confirm_multiple button.yes').text('Confirm All');
722
$('.confirm_multiple button.no').text('Cancel All');
723

    
724
</script>