Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ f277a1cd

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

    
171
<script>
172
CONFIRMBOX_OFFSET = 200;
173

174
init_action_indicator_handlers('icon');
175

176
// handle connect machine image states
177
$("div.connect-arrow, div.running .machine .logo").live('mouseover',
178
    function() {
179
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
180
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1);
181
        var parent = $(this).parent().parent();
182
        parent.find(".connect-arrow").show().addClass('border-hover');
183
    });
184

185
$("div.connect-arrow, div.running .machine .logo").live('mouseleave',
186
    function() {
187
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
188
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "hover");
189
        // mouseup outside the element is not fired
190
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "click");
191
        var parent = $(this).parent().parent();
192
        parent.find(".connect-arrow").show().removeClass('border-hover');
193
    });
194

195
$("div.connect-arrow, div.running .machine .logo").live('mousedown',
196
function() {
197
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
198
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1);
199
    });
200

201
$("div.connect-arrow, div.running .machine .logo").live('mouseup',
202
    function() {
203
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
204
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1, "click");
205
    });
206

207
// actions on machine mouseover
208
$("#machinesview-icon.standard .machine").live('mouseover', function() {
209
    // show connect button only if the machine is active
210
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
211
        $(this).find("div.connect-arrow").show();
212
        $(this).find("div.connect-border").show();
213
    }
214
});
215

216
// actions on machine mouseout
217
$("#machinesview-icon.standard .machine").live('mouseout', function() {
218
    // hide connect button
219
    $(this).find("div.connect-arrow").hide();
220
    $(this).find("div.connect-border").hide();
221
});
222

223
// actions on connect arrow border mouseover
224
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
225
    $(this).next().addClass('border-hover');
226
});
227

228
// actions on connect arrow border mouseout
229
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
230
    $(this).next().removeClass('border-hover');
231
});
232

233
// open console on machine logo click
234
$("#machinesview-icon.standard .running div.logo").live('click', function(){
235
    if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
236
    var serverID = $(this).parent().parent().attr("id");
237
    machine_connect([machine_connect, serverID]);
238
    return false;
239
});
240

241
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
242
    var serverID = $(this).parent().parent().attr("id");
243
    machine_connect([machine_connect, serverID]);
244
    return false;
245
});
246

247
// open console on connect arrow border click
248
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
249
    var serverID = $(this).parent().parent().attr("id");
250
    machine_connect([machine_connect, serverID]);
251
    return false;
252
});
253

254
//hide the all of the info contents
255
$("#machinesview-icon.standard .info-content").hide();
256
//toggle the component with class info-content
257
$("#machinesview-icon.standard div.info-header").live('click', function() {
258
    if ($(this).find('.toggler').hasClass('up')) {
259
        // toggle drop-down pane
260
        $(this).find('.toggler').removeClass('up');
261
        $(this).find('.toggler').addClass('down');
262
        $(this).find('.info-label').removeClass('darker');
263
        $(this).parent().parent().removeClass('light-background');
264
    } else {
265
        // reset stats
266
        $(this).closest('.machine-container').find('.vm-stats div.stat-error').hide();
267
        $(this).closest('.machine-container').find('.vm-stats img.cpu').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
268
        $(this).closest('.machine-container').find('.vm-stats img.net').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
269
        // get new stats
270
        var serverID = $(this).closest('.machine-container').attr('id');
271
        get_server_stats(serverID);
272
        // toggle drop-down pane
273
        $(this).find('.toggler').removeClass('down');
274
        $(this).find('.toggler').addClass('up');
275
        $(this).find('.info-label').addClass('darker');
276
        $(this).parent().parent().addClass('light-background');
277
    }
278
    $(this).parent().parent().find(".info-content").slideToggle(600);
279
    return false;
280
});
281

282
// intercept manage metadata click
283
$("#machinesview-icon.standard a.manage-metadata").live('click', function() {
284
    // get server name and server ID
285
    var serverID = $(this).closest('.machine-container').attr("id");
286
    var serverName = $(this).closest('.machine').find("span.name").text();
287
    // set server name to all related metadata dialogs
288
    $("#metadata-wizard div.machine-name").text(serverName);
289
    if ($(this).closest('.machine-container').parent().hasClass('terminated')) {
290
        $("#metadata-wizard div#on-off").text('off');
291
    } else {
292
        $("#metadata-wizard div#on-off").text('on');
293
    }
294
    // set server id to all related metadata dialogs
295
    $("#metadata-wizard p").text(serverID);
296
    show_metadata_wizard();
297
    return false;
298
});
299

300
//initiate machine renaming
301
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
302
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
303
                                        $(this).parent().find('.name').text() +
304
                                        "\" / ><span class=\"oldValue\">" +
305
                                        $(this).parent().find('.name').text() + "</span>");
306
    $(this).parent().find('.rename').hide();
307
    $(this).parent().find(".editbuttons").fadeIn();
308
    $(this).parent().find(".nametextbox").focus().select();
309
    $(this).parent().removeClass('editable');
310

311
    //submit wizard by pressing enter on the name textbox
312
    $(".nametextbox").keydown(function (e) {
313
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
314
            $(this).parent().parent().find('div.editbuttons div.save').click();
315
            return false;
316
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
317
            $(this).parent().parent().find('div.editbuttons div.cancel').click();
318
            return true;
319
        }
320
    });
321
    return false;
322
});
323

324
//rename machine
325
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
326
    serverID = $(this).closest('.machine-container').attr("id");
327
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
328
    if (serverName.trim() == ''){
329
        return false;
330
    }
331
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
332
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
333
    $(this).parent().parent().find(".rename").fadeIn("slow");
334
    $(this).parent().parent().addClass('editable');
335
    rename(serverID, serverName);
336
    return false;
337
});
338

339
//cancel renaming
340
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
341
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
342
    $(this).parent().parent().find(".editbuttons").hide();
343
    $(this).parent().parent().find(".rename").fadeIn();
344
    $(this).parent().parent().addClass('editable');
345
    return false;
346
});
347

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

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

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

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

449

450
// intercept destroy click
451
$("#machinesview-icon.standard div.actions a.action-destroy").live('click', function() {
452
    // get server id and server name from DOM
453
    var serverID = $(this).closest("div.machine-container").attr("id");
454
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
455
    var found = false;
456
    // show/hide proper menus
457
    $(this).parent().parent().find('a').removeClass('selected');
458
    $(this).addClass('selected');
459
    $(this).parent().parent().addClass('display');
460
    $(this).closest("div.machine").find('.action_error').hide();
461
    // if there is already a pending action for this server replace it
462
    for (i=0; i<pending_actions.length; i++) {
463
        if (pending_actions[i][1] == serverID) {
464
            pending_actions[i][0] = destroy;
465
            found = true
466
        }
467
    }
468
    // no pending action for this server was found, so let's just add it to the list
469
    if (!found)
470
        pending_actions.push([destroy, serverID, serverName])
471
    update_confirmations();
472
    return false;
473
});
474

475
$("#machinesview-icon.standard div.confirm_single button.yes").live('click', function(){
476
    var serverID = $(this).closest("div.machine-container").attr("id");
477
    // if there is a pending action for this server execute it
478
    for (i=0; i<pending_actions.length; i++) {
479
        if (pending_actions[i][1]==serverID){
480
            action = pending_actions.splice(i,1)[0]; // extract action
481
            // change the status text in cases where no api state exists
482
            if (action[0] == start) {
483
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Starting']);
484
                $(this).closest("div.machine").find('.state').removeClass().addClass('state starting-state');
485
                $(this).closest("div.machine").find('.spinner').show();
486
            } else if (action[0] == shutdown) {
487
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Shutting down']);
488
                $(this).closest("div.machine").find('.state').removeClass().addClass('state shutting-state');
489
                $(this).closest("div.machine").find('.spinner').show();
490
            } else if (action[0] == reboot) {
491
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Rebooting']);
492
                $(this).closest("div.machine").find('.state').removeClass().addClass('state rebooting-state');
493
                $(this).closest("div.machine").find('.spinner').show();
494
            }  else if (action[0] == destroy) {
495
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Destroying']);
496
                $(this).closest("div.machine").find('.state').removeClass().addClass('state destroying-state');
497
                $(this).closest("div.machine").find('.spinner').show();
498
            }
499
            action[0]([action[1]]); // execute action
500
        }
501
    }
502
    $(this).parent().hide();
503
    $(this).closest('div.actions').find('a').removeClass('selected');
504
    $(this).closest("div.machine").children('.state').children('.spinner').show()
505
    $(this).closest("div.machine").children('div.actions').removeClass('display');
506
    update_confirmations();
507
    return false;
508
});
509

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

514
    $(this).closest('div.action-container').children('a').removeClass('selected');
515
    $(this).closest('div.actions').removeClass('display');
516
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
517
        if (pending_actions[i][1] == serverID) {
518
            pending_actions.splice(i,1);
519
        }
520
    }
521
    $(this).parent().hide();
522
    update_confirmations();
523
    return false;
524
});
525

526
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
527
    // remove the action from the pending list
528
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
529
    $(this).parent().hide();
530
});
531

532
// update the servers list
533
function update_machines_view(data) {
534
    /*
535
    Go through the servers in the input data. Update existing entries, add
536
    new ones to the list
537
    */
538
    $.each(data.servers.values, function(i,server) {
539

540
        // get DOM element, if it exists
541
        existing = $('#machinesview-icon.standard #' + server.id);
542
        // get server OS, if it exists
543
        if (!(server.metadata == undefined)) {
544
            var server_image = os_icon(server.metadata);
545
        } else {
546
            var server_image = "unknown"
547
        }
548
        // get server status message, if it exists
549
        var current_message = existing.find(".status").text();
550
        // if multiple machines exist in the DOM, delete all but one
551
        // defensive coding - that shouldn't happen normally
552
        while (existing.length > 1){
553
            existing.remove();
554
        }
555
        // if server already exists in DOM, update its values
556
        if (existing.length){
557
            //  if the status is deleted
558
            if (server.status == 'DELETED') {
559
                // delete server entry from the DOM
560
                log_server_status_change(existing, 'DELETED');
561
                existing.remove();
562
            }
563
            // if the status has changed
564
            else if ( current_message != STATUSES[server.status]) {
565
                /*
566
                Here there are 4 possibilities:
567
                    1. From an active state to an inactive one
568
                    2. From an inactive state to an active one
569
                    3. From an active state to a different active one
570
                    4. From an inactive state to a different inactive one
571
                The last two (3, 4) can be dealt with the same way
572
                */
573
                if (ACTIVE_STATES.indexOf(current_message) >= 0 &&
574
                    INACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
575
                    // from an active state to an inactive one
576
                    log_server_status_change(existing, server.status);
577
                    moved = existing.clone().appendTo("#machinesview-icon.standard .terminated");
578
                    set_machine_os_image(moved, "icon", "off", server_image);
579
                    existing.remove();
580
                    existing = moved;
581
                    existing.find(".status").text(STATUSES[server.status]);
582
                    existing.find('.spinner').hide();
583
                    if ($("div.terminated").find("div.machine-container").length > 0) {
584
                        $("div.terminated").show();
585
                    }
586
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
587
                    existing.find('.state').removeClass().addClass('state terminated-state');
588
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
589
                }
590
                else if (INACTIVE_STATES.indexOf(current_message) >= 0 &&
591
                         ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
592
                    // From an inactive state to an active one
593
                    log_server_status_change(existing, server.status);
594
                    moved = existing.clone().appendTo("#machinesview-icon.standard .running");
595
                    set_machine_os_image(moved, "icon", "on", server_image);
596
                    existing.remove();
597
                    existing = moved;
598
                    existing.find(".status").text(STATUSES[server.status]);
599
                    existing.find('.spinner').hide();
600
                    if ($("div.terminated").find("div.machine-container").length == 0) {
601
                        $("div.terminated").hide();
602
                    }
603
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
604
                    existing.find('.state').removeClass().addClass('state running-state');
605
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
606
                }
607
                else {
608
                    // handling active to active or inactive to inactive changes
609
                    if (TRANSITIONS[current_message] && TRANSITIONS[current_message] != 'Rebooting') {
610
                        // don't do anything if it is still in transition
611
                    }
612
                    else if ((TRANSITIONS[current_message] == 'Rebooting' && server.status == 'ACTIVE') ||
613
                             (STATUSES['BUILD'] == current_message && server.status == 'ACTIVE')) {
614
                        // if it has been rebooted or just created
615
                        log_server_status_change(existing, server.status);
616
                        existing.find(".status").text(STATUSES[server.status]);
617
                        existing.find('.spinner').hide();
618
                        existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
619
                        existing.find('.state').removeClass().addClass('state running-state');
620
                        setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
621
                    }
622
                    else if (STATUSES[server.status] == "Rebooting") { 
623
                        // from running to rebooting
624
                        log_server_status_change(existing, server.status);
625
                        existing.find(".state").removeClass().addClass('state rebooting-state');
626
                        existing.find('.spinner').show();
627
                        existing.find(".status").text(STATUSES[server.status]);
628
                    } else {
629
                        // in any other case just change the status and ignore spinners/waves
630
                        existing.find(".status").text(STATUSES[server.status]);
631
                        existing.appendTo("#machinesview-icon.standard .running");
632
                        existing.find('.state').removeClass().addClass('state running-state');
633
                    }
634
                }
635
            }
636
            // find and display ips
637
            var ips = get_public_ips(server);
638
            existing.find("a.ip span.public").text(ips['ip4']);
639
            existing.find("a.ip span.public.ipv6-text").text(ips['ip6']);
640
        }
641
        // if it doesn't exist and the server is not DELETED, make a new entry
642
        else if ( server.status != 'DELETED') {
643
            // clone the proper template and put basic values in
644
            var machine = $("#machinesview-icon.standard #machine-container-template").clone().attr("id", server.id).fadeIn("slow");
645

646
            machine.find(".scrollable").scrollable({vertical: true});
647
            machine.find("div.name span.name").text(server.name.substring(0,50));
648
            machine.find("span.imagetag").text(server_image);
649
            machine.find(".status").text(STATUSES[server.status]);
650
            // check server status to select where to append the new server to
651
            if (ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0 ) {
652
                // append to running
653
                set_machine_os_image(machine, "icon", "on", server_image);
654
                machine.appendTo("#machinesview-icon.standard .running");
655
            } else {
656
                // append to terminated
657
                set_machine_os_image(machine, "icon", "off", server_image);
658
                machine.appendTo("#machinesview-icon.standard .terminated");
659
                if (server.status == "STOPPED") { //if server status us stopped is a different case than status unknown/error
660
                    machine.find('.state').removeClass().addClass('state terminated-state');
661
                } else {
662
                       machine.find('.state').removeClass().addClass('state error-state');
663
                }
664
            }
665

666
            //show spinner if server is still building or rebooting
667
            if (server.status == 'BUILD') {
668
                machine.find('.spinner').show();
669
                machine.find('.state').removeClass().addClass('state build-state');
670
                machine.addClass('vm-building');
671
            } else {
672
                machine.removeClass('vm-building');
673
            }
674

675
            if (server.status == 'REBOOT') {
676
                machine.find('.spinner').show();
677
                machine.find('.state').removeClass().addClass('state rebooting-state');
678
            }
679
            // find and display flavor parameters
680
            var flavor_params = get_flavor_params(server.flavorRef);
681
            machine.find(".cpu-data").text(flavor_params['cpus']);
682
            machine.find(".ram-data").text(flavor_params['ram']);
683
            machine.find(".disk-data").text(flavor_params['disk']);
684
            // find and display image parameters
685
            var image_params = get_image_params(server.imageRef);
686
            machine.find(".image-data").text(image_params['name'].substring(0,15));
687
            machine.find(".image-size-data").text(image_params['size']);
688
            // find and display ips
689
            var ips = get_public_ips(server);
690
            machine.find("a.ip span.public").text(ips['ip4']);
691
            machine.find("a.ip span.public.ipv6-text").text(ips['ip6']);
692
        }
693
        /*
694
        Do some repeated actions that include:
695
            1. Update actions
696
            2. Metadata list updating
697
        */
698
        update_iconview_actions(server.id, server.status);
699
        if (!(server.metadata == undefined)) {
700
                list_metadata_keys(server.id, server.metadata.values);
701
        }
702

703
        // if machine in destroy state keep it that way
704
        var server = get_machine(server.id);
705
        if (server.status == "DESTROY") {
706
            existing = $('#machinesview-icon.standard #' + server.id);
707
            if (existing.length) {
708
                $(existing).find('.status').text(TRANSITIONS['Destroying']);
709
                $(existing).find('.state').removeClass().addClass('state destroying-state');
710
                $(existing).find('.spinner').show();
711
                $(existing).find('.wave').hide();
712
            }
713
        }
714

715

716
    });
717
    /*
718
    Do some standard stuff, repeated each time
719
    FIXME: Can these be moved to a new function?
720
    */
721
    fix_v6_addresses();
722
    $("div.large-spinner").hide();
723
    $("div.running").removeClass("disabled");
724
    // show all separators and hide the last one
725
    $("#machinesview-icon.standard div.machine-container div.separator").show();
726
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
727
    // the terminated div shows only when terminated machines are available
728
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
729
        $("div.terminated").fadeIn("slow");
730
    } else {
731
        $("div.terminated").fadeOut("slow");
732
    }
733
    // show message in case user has no servers!
734
    if ($('#machinesview-icon .machine-container').length < 2) {
735
        showWelcome();
736
    } else {
737
        hideWelcome();
738
    }
739
    // set confirm box position
740
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height()) {
741
        $('.confirm_multiple').addClass('fixed');
742
    } else {
743
        $('.confirm_multiple').removeClass('fixed');
744
    }
745
}
746

747
// reposition multiple confirmation box on window resize
748
$(window).resize(function(){
749
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
750
        $('.confirm_multiple').addClass('fixed');
751
    else
752
        $('.confirm_multiple').removeClass('fixed');
753
});
754

755
// update metadata list
756
function list_metadata_keys(serverID, keys) {
757
    // empty the list if it already exists
758
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
759
    //start counter
760
    var i=0;
761
    // show values
762
    for (var key in keys) {
763
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
764
        i++;
765
    }
766
    //hide the metadata controls if we have less than 3 metadata
767
    if (i <= 3) {
768
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
769
    }
770
    //show the metadata controls if we have more than 3 metadata
771
    if (i > 3) {
772
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
773
    }
774
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
775
}
776

777
// indicate that the requested action was succesfully completed
778
function display_success(serverID) {
779

780
}
781

782
// indicate that the requested action was not completed
783
function display_failure(status, serverID, action, responseText) {
784
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
785
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
786
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
787
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
788
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
789
}
790

791
// basic functions executed on page load
792
if ( flavors.length == 0 && images.length == 0 ) {
793
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
794
    update_flavors();
795
    // populate image list
796
    update_images();
797
} else if ( flavors.length == 0 && images.length != 0 ) {
798
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
799
    update_flavors();
800
} else if ( flavors.length != 0 && images.length == 0 ) {
801
    // populate image list
802
    update_images();
803
    update_vms(UPDATE_INTERVAL);
804
} else {
805
    // start updating vm list
806
    update_vms(UPDATE_INTERVAL);
807
}
808

809
// set the label of the multiple buttons
810
$('.confirm_multiple button.yes').text('Confirm All');
811
$('.confirm_multiple button.no').text('Cancel All');
812

813
//IE specific fixes
814
if ($.browser.msie) {
815
    //IE fix for machine div hover
816
    $("div.machine").live("mouseenter", function () {
817
        $(this).css("background-color","#A1C8DB");
818
        $(this).find("div.info-header").css("background-color","#84b7d0");
819
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
820
        $(this).find(".actions a").css("visibility","visible");
821
    });
822
    $("div.machine").live("mouseleave", function () {
823
        $(this).css("background-color","transparent");
824
        $(this).find("div.info-header").css("background-color","#A1C8DB");
825
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
826
        if ($(this).parent().find(".confirm_single:visible").length == 0) {
827
            $(this).find(".actions a").css("visibility","hidden");
828
        }
829
    });
830
    //IE fix for green arrow hover
831
    $("div.connect-arrow").live("mouseenter", function () {
832
        $(this).addClass("connect-arrow-ie");
833
    });
834
    $("div.connect-arrow").live("mouseleave", function () {
835
        $(this).removeClass("connect-arrow-ie");
836
    });
837
    //IE fix for details button
838
    $("button.details").live("mouseenter", function () {
839
        $(this).css("background-color","#FF7F2A");
840
    });
841
    $("button.details").live("mouseleave", function () {
842
        $(this).css("background-color","transparent");
843
    });
844
    //IE fix for multiple conf yes button
845
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
846
        $(this).css("background-color","#FF7F2A");
847
    });
848
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
849
        $(this).css("background-color","transparent");
850
    });
851
    //IE fix for multiple conf no button
852
    $("div.confirm_multiple button.no").live("mouseenter", function () {
853
        $(this).css("background-color","#5CA1C0");
854
    });
855
    $("div.confirm_multiple button.no").live("mouseleave", function () {
856
        $(this).css("background-color","transparent");
857
    });
858
}
859
</script>