Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 23ca3bc9

History | View | Annotate | Download (35.6 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" %} <br />
76
                        <img src="http://stats.okeanos.grnet.gr/test/cpu-bar.png" class="cpu metadata-bar" />
77
                        {% trans "Net" %} <br />
78
                         <img src="http://stats.okeanos.grnet.gr/test/net-bar.png" class="net metadata-bar" /><br />
79
                    </div>
80
                    <div class="vm-metadata metadata-column">
81
                        <div class="metadata-left">
82
                            {% trans "Tags" %}: <br />
83
                            (<span class="metadata-count">0</span>)
84
                        </div>
85
                        <div class="metadata-keys-container">
86
                            <div class="scrollable vertical">
87
                                <div class="items">
88
                                </div>
89
                            </div>
90
                            <div class="metadata-actions">
91
                                <div class="prev"></div>
92
                                <div class="next"></div>
93
                            </div>
94
                        </div>
95
                        <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
96
                    </div>
97
                </div>
98
            </div>
99
            <div class="state">
100
                <div class="status">{% trans "Running" %}</div>
101
                <div class="indicators">
102
                    <div class="indicator1"></div>
103
                    <div class="indicator2"></div>
104
                    <div class="indicator3"></div>
105
                    <div class="indicator4"></div>
106
                </div>
107
                <div class="action-indicator" style="display:none"></div>
108
                <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
109
                <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
110
            </div>
111
            <div class="actions">
112
                <div class="action-container start">
113
                    <a href="#" class="action-start">{% trans "Start" %}</a>
114
                    <div class="confirm_single">
115
                        <button class="yes">{% trans "Confirm" %}</button>
116
                        <button class="no">X</button>
117
                    </div>
118
                </div>
119
                <div class="action-container reboot">
120
                    <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
121
                    <div class="confirm_single">
122
                        <button class="yes">{% trans "Confirm" %}</button>
123
                        <button class="no">X</button>
124
                    </div>
125
                </div>
126
                <div class="action-container shutdown">
127
                    <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
128
                    <div class="confirm_single">
129
                        <button class="yes">{% trans "Confirm" %}</button>
130
                        <button class="no">X</button>
131
                    </div>
132
                </div>
133
                <div class="action-container console">
134
                    <a href="#" class="action-console">{% trans "Console" %}</a>
135
                    <div class="confirm_single">
136
                        <button class="yes">{% trans "Confirm" %}</button>
137
                        <button class="no">X</button>
138
                    </div>
139
                </div>
140
                <div class="action-container destroy">
141
                    <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
142
                    <div class="confirm_single">
143
                        <button class="yes">{% trans "Confirm" %}</button>
144
                        <button class="no">X</button>
145
                    </div>
146
                </div>
147
            </div>
148
            <div class="action_error" align="center">
149
                {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
150
                <span class="code"></span>
151
                <span class="message"></span>
152
                <button class="details">{% trans "Details" %}</button>
153
            </div>
154
        </div>
155
        <div class="separator"></div>
156
    </div>
157
    <div class="running"><div class="large-spinner"></div></div>
158
    <div class="terminated" style="display:none;"></div>
159
</div>
160

    
161
<script>
162
CONFIRMBOX_OFFSET = 200;
163

164
init_action_indicator_handlers('icon');
165

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

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

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

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

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

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

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

210
//hide the all of the info contents
211
$("#machinesview-icon.standard .info-content").hide();
212
//toggle the component with class info-content
213
$("#machinesview-icon.standard div.info-header").live('click', function() {
214
    if ($(this).find('.toggler').hasClass('up')) {
215
        // toggle drop-down pane
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
        // make the get stats call
222
        var serverID = $(this).closest('.machine-container').attr('id');
223
        get_server_stats(serverID);
224
        // toggle drop-down pane
225
        $(this).find('.toggler').removeClass('down');
226
        $(this).find('.toggler').addClass('up');
227
        $(this).find('.info-label').addClass('darker');
228
        $(this).parent().parent().addClass('light-background');
229
    }
230
    $(this).parent().parent().find(".info-content").slideToggle(600);
231
    return false;
232
});
233

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

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

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

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

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

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

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

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

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

401

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

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

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

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

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

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

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

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

698
// indicate that the requested action was succesfully completed
699
function display_success(serverID) {
700

701
}
702

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

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

730
// set the label of the multiple buttons
731
$('.confirm_multiple button.yes').text('Confirm All');
732
$('.confirm_multiple button.no').text('Cancel All');
733

734
//IE specific fixes
735
if ($.browser.msie) {
736
    //IE fix for machine div hover
737
    $("div.machine").live("mouseenter", function () {
738
        $(this).css("background-color","#A1C8DB");
739
        $(this).find("div.info-header").css("background-color","#84b7d0");
740
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
741
        $(this).find(".actions a").css("visibility","visible");
742
    });
743
    $("div.machine").live("mouseleave", function () {
744
        $(this).css("background-color","transparent");
745
        $(this).find("div.info-header").css("background-color","#A1C8DB");
746
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
747
        $(this).find(".actions a").css("visibility","hidden");
748
    });
749
    //IE fix for green arrow hover
750
    $("div.connect-arrow").live("mouseenter", function () {
751
        $(this).addClass("connect-arrow-ie");
752
    });
753
    $("div.connect-arrow").live("mouseleave", function () {
754
        $(this).removeClass("connect-arrow-ie");
755
    });
756
    //IE fix for details button
757
    $("button.details").live("mouseenter", function () {
758
        $(this).css("background-color","#FF7F2A");
759
    });
760
    $("button.details").live("mouseleave", function () {
761
        $(this).css("background-color","transparent");
762
    });
763
    //IE fix for multiple conf yes button
764
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
765
        $(this).css("background-color","#FF7F2A");
766
    });
767
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
768
        $(this).css("background-color","transparent");
769
    });
770
    //IE fix for multiple conf no button
771
    $("div.confirm_multiple button.no").live("mouseenter", function () {
772
        $(this).css("background-color","#5CA1C0");
773
    });
774
    $("div.confirm_multiple button.no").live("mouseleave", function () {
775
        $(this).css("background-color","transparent");
776
    });
777
}
778
</script>