Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 0aec49e0

History | View | Annotate | Download (34.8 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="metadata-bar" />
77
                        {% trans "Net" %} <br />
78
                         <img src="http://stats.okeanos.grnet.gr/test/net-bar.png" class="metadata-bar" /><br />
79
                    </div>
80
                    <div class="vm-metadata metadata-column">
81
                        <div class="metadata-left">
82
                            {% trans "Metadata" %}: <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
        $(this).find('.toggler').removeClass('up');
216
        $(this).find('.toggler').addClass('down');
217
        $(this).find('.info-label').removeClass('darker');
218
        $(this).parent().parent().removeClass('light-background');
219
    } else {
220
        $(this).find('.toggler').removeClass('down');
221
        $(this).find('.toggler').addClass('up');
222
        $(this).find('.info-label').addClass('darker');
223
        $(this).parent().parent().addClass('light-background');
224
    }
225
    $(this).parent().parent().find(".info-content").slideToggle(600);
226
    return false;
227
});
228

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

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

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

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

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

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

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

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

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

396

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

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

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

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

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

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

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

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

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

696
}
697

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

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

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

729
//IE specific fixes
730
if ($.browser.msie) {
731
    //IE fix for machine div hover
732
    $("div.machine").live("mouseenter", function () {
733
        $(this).css("background-color","#A1C8DB");
734
        $(this).find("div.info-header").css("background-color","#84b7d0");
735
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
736
        $(this).find(".actions a").css("visibility","visible");
737
    });
738
    $("div.machine").live("mouseleave", function () {
739
        $(this).css("background-color","transparent");
740
        $(this).find("div.info-header").css("background-color","#A1C8DB");
741
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
742
        $(this).find(".actions a").css("visibility","hidden");
743
    });
744
    //IE fix for green arrow hover
745
    $("div.connect-arrow").live("mouseenter", function () {
746
        $(this).addClass("connect-arrow-ie");
747
    });
748
    $("div.connect-arrow").live("mouseleave", function () {
749
        $(this).removeClass("connect-arrow-ie");
750
    });
751
    //IE fix for details button
752
    $("button.details").live("mouseenter", function () {
753
        $(this).css("background-color","#FF7F2A");
754
    });
755
    $("button.details").live("mouseleave", function () {
756
        $(this).css("background-color","transparent");
757
    });
758
}
759
</script>