Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ bd80f212

History | View | Annotate | Download (36.5 kB)

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

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

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

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

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

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

    
36
{% load i18n %}
37

    
38
<!-- the standard view -->
39
<div id="machinesview-icon" class="standard">
40
    <div class="machine-container" id="machine-container-template" style="display:none">
41
        <div class="machine" id="machine-template">
42
            <div class='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
                        <div class='stat-label'>{% trans "CPU" %}</div>
76
                        <div class='stat-content'>
77
                            <img src="./static/icons/indicators/small/progress.gif" class="cpu busy" />
78
                            <div class='stat-error'>{% trans "Could not fetch CPU stats." %}</div>
79
                        </div>
80
                        <div class='stat-label'>{% trans "Net" %}</div>
81
                        <div class='stat-content'>
82
                            <img src="./static/icons/indicators/small/progress.gif" class="net busy" />
83
                            <div class='stat-error'>{% trans "Could not fetch Net stats." %}</div>
84
                        </div>
85
                        <a href="#" class="stats-report">{% trans "Full report" %}</a>
86
                    </div>
87
                    <div class="vm-metadata metadata-column">
88
                        <div class="metadata-left">
89
                            {% trans "Tags" %}: <br />
90
                            (<span class="metadata-count">0</span>)
91
                        </div>
92
                        <div class="metadata-keys-container">
93
                            <div class="scrollable vertical">
94
                                <div class="items">
95
                                </div>
96
                            </div>
97
                            <div class="metadata-actions">
98
                                <div class="prev"></div>
99
                                <div class="next"></div>
100
                            </div>
101
                        </div>
102
                        <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
103
                    </div>
104
                </div>
105
            </div>
106
            <div class="state">
107
                <div class="status">{% trans "Running" %}</div>
108
                <div class="indicators">
109
                    <div class="indicator1"></div>
110
                    <div class="indicator2"></div>
111
                    <div class="indicator3"></div>
112
                    <div class="indicator4"></div>
113
                </div>
114
                <div class="action-indicator" style="display:none"></div>
115
                <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
116
                <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
117
            </div>
118
            <div class="actions">
119
                <div class="action-container start">
120
                    <a href="#" class="action-start">{% trans "Start" %}</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 reboot">
127
                    <a href="#" class="action-reboot">{% trans "Reboot" %}</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 shutdown">
134
                    <a href="#" class="action-shutdown">{% trans "Shutdown" %}</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 console">
141
                    <a href="#" class="action-console">{% trans "Console" %}</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 class="action-container destroy">
148
                    <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
149
                    <div class="confirm_single">
150
                        <button class="yes">{% trans "Confirm" %}</button>
151
                        <button class="no">X</button>
152
                    </div>
153
                </div>
154
            </div>
155
            <div class="action_error" align="center">
156
                {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
157
                <span class="code"></span>
158
                <span class="message"></span>
159
                <button class="details">{% trans "Details" %}</button>
160
            </div>
161
        </div>
162
        <div class="separator"></div>
163
    </div>
164
    <div class="running"><div class="large-spinner"></div></div>
165
    <div class="terminated" style="display:none;"></div>
166
</div>
167

    
168
<script>
169
CONFIRMBOX_OFFSET = 200;
170

171
init_action_indicator_handlers('icon');
172

173
// actions on machine mouseover
174
$("#machinesview-icon.standard .machine").live('mouseover', function() {
175
    // show connect button only if the machine is active
176
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
177
        $(this).find("div.connect-arrow").show();
178
        $(this).find("div.connect-border").show();
179
    }
180
});
181

182
// actions on machine mouseout
183
$("#machinesview-icon.standard .machine").live('mouseout', function() {
184
    // hide connect button
185
    $(this).find("div.connect-arrow").hide();
186
    $(this).find("div.connect-border").hide();
187
});
188

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

194
// actions on connect arrow border mouseout
195
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
196
    $(this).next().removeClass('border-hover');
197
});
198

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

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

211
// open console on connect arrow border click
212
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
213
    $(this).parent().parent().find("a.action-console").click();
214
    return false;
215
});
216

217
//hide the all of the info contents
218
$("#machinesview-icon.standard .info-content").hide();
219
//toggle the component with class info-content
220
$("#machinesview-icon.standard div.info-header").live('click', function() {
221
    if ($(this).find('.toggler').hasClass('up')) {
222
        // toggle drop-down pane
223
        $(this).find('.toggler').removeClass('up');
224
        $(this).find('.toggler').addClass('down');
225
        $(this).find('.info-label').removeClass('darker');
226
        $(this).parent().parent().removeClass('light-background');
227
    } else {
228
        // reset stats
229
        $(this).closest('.machine-container').find('.vm-stats div.stat-error').hide();
230
        $(this).closest('.machine-container').find('.vm-stats img.cpu').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
231
        $(this).closest('.machine-container').find('.vm-stats img.net').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
232
        // get new stats
233
        var serverID = $(this).closest('.machine-container').attr('id');
234
        get_server_stats(serverID);
235
        // toggle drop-down pane
236
        $(this).find('.toggler').removeClass('down');
237
        $(this).find('.toggler').addClass('up');
238
        $(this).find('.info-label').addClass('darker');
239
        $(this).parent().parent().addClass('light-background');
240
    }
241
    $(this).parent().parent().find(".info-content").slideToggle(600);
242
    return false;
243
});
244

245
// intercept manage metadata click
246
$("#machinesview-icon.standard a.manage-metadata").live('click', function() {
247
    // get server name and server ID
248
    var serverID = $(this).closest('.machine-container').attr("id");
249
    var serverName = $(this).closest('.machine').find("span.name").text();
250
    // set server name to all related metadata dialogs
251
    $("#metadata-wizard div.machine-name").text(serverName);
252
    if ($(this).closest('.machine-container').parent().hasClass('terminated')) {
253
        $("#metadata-wizard div#on-off").text('off');
254
    } else {
255
        $("#metadata-wizard div#on-off").text('on');
256
    }
257
    // set server id to all related metadata dialogs
258
    $("#metadata-wizard p").text(serverID);
259
    show_metadata_wizard();
260
    return false;
261
});
262

263
//initiate machine renaming
264
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
265
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
266
                                        $(this).parent().find('.name').text() +
267
                                        "\" / ><span class=\"oldValue\">" +
268
                                        $(this).parent().find('.name').text() + "</span>");
269
    $(this).parent().find('.rename').hide();
270
    $(this).parent().find(".editbuttons").fadeIn();
271
    $(this).parent().find(".nametextbox").focus().select();
272
    $(this).parent().removeClass('editable');
273

274
    //submit wizard by pressing enter on the name textbox
275
    $(".nametextbox").keydown(function (e) {
276
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
277
            $(this).parent().parent().find('div.editbuttons div.save').click();
278
            return false;
279
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
280
            $(this).parent().parent().find('div.editbuttons div.cancel').click();
281
            return true;
282
        }
283
    });
284
    return false;
285
});
286

287
//rename machine
288
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
289
    serverID = $(this).closest('.machine-container').attr("id");
290
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
291
    if (serverName.trim() == ''){
292
        return false;
293
    }
294
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
295
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
296
    $(this).parent().parent().find(".rename").fadeIn("slow");
297
    $(this).parent().parent().addClass('editable');
298
    rename(serverID, serverName);
299
    return false;
300
});
301

302
//cancel renaming
303
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
304
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
305
    $(this).parent().parent().find(".editbuttons").hide();
306
    $(this).parent().parent().find(".rename").fadeIn();
307
    $(this).parent().parent().addClass('editable');
308
    return false;
309
});
310

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

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

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

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

412

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

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

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

477
    $(this).closest('div.action-container').children('a').removeClass('selected');
478
    $(this).closest('div.actions').removeClass('display');
479
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
480
        if (pending_actions[i][1] == serverID) {
481
            pending_actions.splice(i,1);
482
        }
483
    }
484
    $(this).parent().hide();
485
    update_confirmations();
486
    return false;
487
});
488

489
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
490
    // remove the action from the pending list
491
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
492
    $(this).parent().hide();
493
});
494

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

679
// reposition multiple confirmation box on window resize
680
$(window).resize(function(){
681
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
682
        $('.confirm_multiple').addClass('fixed');
683
    else
684
        $('.confirm_multiple').removeClass('fixed');
685
});
686

687
// update metadata list
688
function list_metadata_keys(serverID, keys) {
689
    // empty the list if it already exists
690
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
691
    //start counter
692
    var i=0;
693
    // show values
694
    for (var key in keys) {
695
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
696
        i++;
697
    }
698
    //hide the metadata controls if we have less than 3 metadata
699
    if (i <= 3) {
700
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
701
    }
702
    //show the metadata controls if we have more than 3 metadata
703
    if (i > 3) {
704
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
705
    }
706
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
707
}
708

709
// indicate that the requested action was succesfully completed
710
function display_success(serverID) {
711

712
}
713

714
// indicate that the requested action was not completed
715
function display_failure(status, serverID, action, responseText) {
716
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
717
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
718
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
719
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
720
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
721
}
722

723
// basic functions executed on page load
724
if ( flavors.length == 0 && images.length == 0 ) {
725
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
726
    update_flavors();
727
    // populate image list
728
    update_images();
729
} else if ( flavors.length == 0 && images.length != 0 ) {
730
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
731
    update_flavors();
732
} else if ( flavors.length != 0 && images.length == 0 ) {
733
    // populate image list
734
    update_images();
735
    update_vms(UPDATE_INTERVAL);
736
} else {
737
    // start updating vm list
738
    update_vms(UPDATE_INTERVAL);
739
}
740

741
// set the label of the multiple buttons
742
$('.confirm_multiple button.yes').text('Confirm All');
743
$('.confirm_multiple button.no').text('Cancel All');
744

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