Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 2b837adf

History | View | Annotate | Download (37.7 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>{% 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
// handle connect machine image states
174
$("div.connect-arrow, div.running .machine .logo").live('mouseover',
175
    function() {
176
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
177
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1);
178
    });
179

180
$("div.connect-arrow, div.running .machine .logo").live('mouseleave',
181
    function() {
182
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
183
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "hover");
184
        // mouseup outside the element is not fired
185
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "click");
186
    });
187

188
$("div.connect-arrow, div.running .machine .logo").live('mousedown',
189
function() {
190
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
191
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1);
192
    });
193

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

200
// actions on machine mouseover
201
$("#machinesview-icon.standard .machine").live('mouseover', function() {
202
    // show connect button only if the machine is active
203
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
204
        $(this).find("div.connect-arrow").show();
205
        $(this).find("div.connect-border").show();
206
    }
207
});
208

209
// actions on machine mouseout
210
$("#machinesview-icon.standard .machine").live('mouseout', function() {
211
    // hide connect button
212
    $(this).find("div.connect-arrow").hide();
213
    $(this).find("div.connect-border").hide();
214
});
215

216
// actions on connect arrow border mouseover
217
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
218
    $(this).next().addClass('border-hover');
219
});
220

221
// actions on connect arrow border mouseout
222
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
223
    $(this).next().removeClass('border-hover');
224
});
225

226
// open console on machine logo click
227
$("#machinesview-icon.standard .running div.logo").live('click', function(){
228
    var serverID = $(this).parent().parent().attr("id");
229
    machine_connect([machine_connect, serverID]);
230
    return false;
231
});
232

233
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
234
    var serverID = $(this).parent().parent().attr("id");
235
    machine_connect([machine_connect, serverID]);
236
    return false;
237
});
238

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

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

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

292
//initiate machine renaming
293
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
294
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
295
                                        $(this).parent().find('.name').text() +
296
                                        "\" / ><span class=\"oldValue\">" +
297
                                        $(this).parent().find('.name').text() + "</span>");
298
    $(this).parent().find('.rename').hide();
299
    $(this).parent().find(".editbuttons").fadeIn();
300
    $(this).parent().find(".nametextbox").focus().select();
301
    $(this).parent().removeClass('editable');
302

303
    //submit wizard by pressing enter on the name textbox
304
    $(".nametextbox").keydown(function (e) {
305
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
306
            $(this).parent().parent().find('div.editbuttons div.save').click();
307
            return false;
308
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
309
            $(this).parent().parent().find('div.editbuttons div.cancel').click();
310
            return true;
311
        }
312
    });
313
    return false;
314
});
315

316
//rename machine
317
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
318
    serverID = $(this).closest('.machine-container').attr("id");
319
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
320
    if (serverName.trim() == ''){
321
        return false;
322
    }
323
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
324
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
325
    $(this).parent().parent().find(".rename").fadeIn("slow");
326
    $(this).parent().parent().addClass('editable');
327
    rename(serverID, serverName);
328
    return false;
329
});
330

331
//cancel renaming
332
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
333
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
334
    $(this).parent().parent().find(".editbuttons").hide();
335
    $(this).parent().parent().find(".rename").fadeIn();
336
    $(this).parent().parent().addClass('editable');
337
    return false;
338
});
339

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

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

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

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

441

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

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

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

506
    $(this).closest('div.action-container').children('a').removeClass('selected');
507
    $(this).closest('div.actions').removeClass('display');
508
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
509
        if (pending_actions[i][1] == serverID) {
510
            pending_actions.splice(i,1);
511
        }
512
    }
513
    $(this).parent().hide();
514
    update_confirmations();
515
    return false;
516
});
517

518
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
519
    // remove the action from the pending list
520
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
521
    $(this).parent().hide();
522
});
523

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

708
// reposition multiple confirmation box on window resize
709
$(window).resize(function(){
710
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
711
        $('.confirm_multiple').addClass('fixed');
712
    else
713
        $('.confirm_multiple').removeClass('fixed');
714
});
715

716
// update metadata list
717
function list_metadata_keys(serverID, keys) {
718
    // empty the list if it already exists
719
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
720
    //start counter
721
    var i=0;
722
    // show values
723
    for (var key in keys) {
724
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
725
        i++;
726
    }
727
    //hide the metadata controls if we have less than 3 metadata
728
    if (i <= 3) {
729
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
730
    }
731
    //show the metadata controls if we have more than 3 metadata
732
    if (i > 3) {
733
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
734
    }
735
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
736
}
737

738
// indicate that the requested action was succesfully completed
739
function display_success(serverID) {
740

741
}
742

743
// indicate that the requested action was not completed
744
function display_failure(status, serverID, action, responseText) {
745
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
746
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
747
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
748
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
749
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
750
}
751

752
// basic functions executed on page load
753
if ( flavors.length == 0 && images.length == 0 ) {
754
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
755
    update_flavors();
756
    // populate image list
757
    update_images();
758
} else if ( flavors.length == 0 && images.length != 0 ) {
759
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
760
    update_flavors();
761
} else if ( flavors.length != 0 && images.length == 0 ) {
762
    // populate image list
763
    update_images();
764
    update_vms(UPDATE_INTERVAL);
765
} else {
766
    // start updating vm list
767
    update_vms(UPDATE_INTERVAL);
768
}
769

770
// set the label of the multiple buttons
771
$('.confirm_multiple button.yes').text('Confirm All');
772
$('.confirm_multiple button.no').text('Cancel All');
773

774
//IE specific fixes
775
if ($.browser.msie) {
776
    //IE fix for machine div hover
777
    $("div.machine").live("mouseenter", function () {
778
        $(this).css("background-color","#A1C8DB");
779
        $(this).find("div.info-header").css("background-color","#84b7d0");
780
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
781
        $(this).find(".actions a").css("visibility","visible");
782
    });
783
    $("div.machine").live("mouseleave", function () {
784
        $(this).css("background-color","transparent");
785
        $(this).find("div.info-header").css("background-color","#A1C8DB");
786
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
787
        $(this).find(".actions a").css("visibility","hidden");
788
    });
789
    //IE fix for green arrow hover
790
    $("div.connect-arrow").live("mouseenter", function () {
791
        $(this).addClass("connect-arrow-ie");
792
    });
793
    $("div.connect-arrow").live("mouseleave", function () {
794
        $(this).removeClass("connect-arrow-ie");
795
    });
796
    //IE fix for details button
797
    $("button.details").live("mouseenter", function () {
798
        $(this).css("background-color","#FF7F2A");
799
    });
800
    $("button.details").live("mouseleave", function () {
801
        $(this).css("background-color","transparent");
802
    });
803
    //IE fix for multiple conf yes button
804
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
805
        $(this).css("background-color","#FF7F2A");
806
    });
807
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
808
        $(this).css("background-color","transparent");
809
    });
810
    //IE fix for multiple conf no button
811
    $("div.confirm_multiple button.no").live("mouseenter", function () {
812
        $(this).css("background-color","#5CA1C0");
813
    });
814
    $("div.confirm_multiple button.no").live("mouseleave", function () {
815
        $(this).css("background-color","transparent");
816
    });
817
}
818
</script>