Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ a583aa29

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

    
162
<script>
163
CONFIRMBOX_OFFSET = 200;
164

165
init_action_indicator_handlers('icon');
166

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

176
// actions on machine mouseout
177
$("#machinesview-icon.standard .machine").live('mouseout', function() {
178
    // hide connect button
179
    $(this).find("div.connect-arrow").hide();
180
    $(this).find("div.connect-border").hide();
181
});
182

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

188
// actions on connect arrow border mouseout
189
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
190
    $(this).next().removeClass('border-hover');
191
});
192

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

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

205
// open console on connect arrow border click
206
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
207
    $(this).parent().parent().find("a.action-console").click();
208
    return false;
209
});
210

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

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

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

259
    //submit wizard by pressing enter on the name textbox
260
    $(".nametextbox").keydown(function (e) {
261
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
262
            $(this).parent().parent().find('div.editbuttons div.save').click();
263
            return false;
264
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
265
            $(this).parent().parent().find('div.editbuttons div.cancel').click();
266
            return true;
267
        }
268
    });
269
    return false;
270
});
271

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

287
//cancel renaming
288
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
289
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
290
    $(this).parent().parent().find(".editbuttons").hide();
291
    $(this).parent().parent().find(".rename").fadeIn();
292
    $(this).parent().parent().addClass('editable');
293
    return false;
294
});
295

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

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

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

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

397

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

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

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

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

474
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
475
    // remove the action from the pending list
476
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
477
    $(this).parent().hide();
478
});
479

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

664
// reposition multiple confirmation box on window resize
665
$(window).resize(function(){
666
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
667
        $('.confirm_multiple').addClass('fixed');
668
    else
669
        $('.confirm_multiple').removeClass('fixed');
670
});
671

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

694
// indicate that the requested action was succesfully completed
695
function display_success(serverID) {
696

697
}
698

699
// indicate that the requested action was not completed
700
function display_failure(status, serverID, action, responseText) {
701
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
702
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
703
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
704
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
705
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
706
}
707

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

726
// set the label of the multiple buttons
727
$('.confirm_multiple button.yes').text('Confirm All');
728
$('.confirm_multiple button.no').text('Cancel All');
729

730
//IE specific fixes
731
if ($.browser.msie) {
732
    //IE fix for machine div hover
733
    $("div.machine").live("mouseenter", function () {
734
        $(this).css("background-color","#A1C8DB");
735
        $(this).find(".actions a").css("visibility","visible");
736
    });
737
    $("div.machine").live("mouseleave", function () {
738
        $(this).css("background-color","transparent");
739
        $(this).find(".actions a").css("visibility","hidden");
740
    });
741
    //IE fix for green arrow hover
742
    $("div.connect-arrow").live("mouseenter", function () {
743
        $(this).addClass("connect-arrow-ie");
744
    });
745
    $("div.connect-arrow").live("mouseleave", function () {
746
        $(this).removeClass("connect-arrow-ie");
747
    });
748
}
749
</script>