Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 1df63521

History | View | Annotate | Download (38.2 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 if (STATUSES[server.status] == "Rebooting") { 
614
                        // from running to rebooting
615
                        log_server_status_change(existing, server.status);
616
                        existing.find(".state").removeClass().addClass('state rebooting-state');
617
                        existing.find('.spinner').show();
618
                        existing.find(".status").text(STATUSES[server.status]);
619
                    } else {
620
                        // in any other case just change the status and ignore spinners/waves
621
                        existing.find(".status").text(STATUSES[server.status]);
622
                        existing.appendTo("#machinesview-icon.standard .running");
623
                        existing.find('.state').removeClass().addClass('state running-state');
624
                    }
625
                }
626
            }
627
            // find and display ips
628
            var ips = get_public_ips(server);
629
            existing.find("a.ip span.public").text(ips['ip4']);
630
        }
631
        // if it doesn't exist and the server is not DELETED, make a new entry
632
        else if ( server.status != 'DELETED') {
633
            // clone the proper template and put basic values in
634
            var machine = $("#machinesview-icon.standard #machine-container-template").clone().attr("id", server.id).fadeIn("slow");
635
            machine.find(".scrollable").scrollable({vertical: true});
636
            machine.find("div.name span.name").text(server.name.substring(0,50));
637
            machine.find("span.imagetag").text(server_image);
638
            machine.find(".status").text(STATUSES[server.status]);
639
            // check server status to select where to append the new server to
640
            if (ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0 ) {
641
                // append to running
642
                set_machine_os_image(machine, "icon", "on", server_image);
643
                machine.appendTo("#machinesview-icon.standard .running");
644
            } else {
645
                // append to terminated
646
                set_machine_os_image(machine, "icon", "off", server_image);
647
                machine.appendTo("#machinesview-icon.standard .terminated");
648
                if (server.status == "STOPPED") { //if server status us stopped is a different case than status unknown/error
649
                    machine.find('.state').removeClass().addClass('state terminated-state');
650
                } else {
651
                       machine.find('.state').removeClass().addClass('state error-state');
652
                }
653
            }
654
            //show spinner if server is still building or rebooting
655
            if (server.status == 'BUILD') {
656
                machine.find('.spinner').show();
657
                machine.find('.state').removeClass().addClass('state build-state');
658
            }
659
            if (server.status == 'REBOOT') {
660
                machine.find('.spinner').show();
661
                machine.find('.state').removeClass().addClass('state rebooting-state');
662
            }
663
            // find and display flavor parameters
664
            var flavor_params = get_flavor_params(server.flavorRef);
665
            machine.find(".cpu-data").text(flavor_params['cpus']);
666
            machine.find(".ram-data").text(flavor_params['ram']);
667
            machine.find(".disk-data").text(flavor_params['disk']);
668
            // find and display image parameters
669
            var image_params = get_image_params(server.imageRef);
670
            machine.find(".image-data").text(image_params['name'].substring(0,15));
671
            machine.find(".image-size-data").text(image_params['size']);
672
            // find and display ips
673
            var ips = get_public_ips(server);
674
            machine.find("a.ip span.public").text(ips['ip4']);
675
        }
676
        /*
677
        Do some repeated actions that include:
678
            1. Update actions
679
            2. Metadata list updating
680
        */
681
        update_iconview_actions(server.id, server.status);
682
        if (!(server.metadata == undefined)) {
683
                list_metadata_keys(server.id, server.metadata.values);
684
        }
685
    });
686
    /*
687
    Do some standard stuff, repeated each time
688
    FIXME: Can these be moved to a new function?
689
    */
690
    $("div.running > div.large-spinner").hide();
691
    // show all separators and hide the last one
692
    $("#machinesview-icon.standard div.machine-container div.separator").show();
693
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
694
    // the terminated div shows only when terminated machines are available
695
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
696
        $("div.terminated").fadeIn("slow");
697
    } else {
698
        $("div.terminated").fadeOut("slow");
699
    }
700
    // show message in case user has no servers!
701
    if ($('#machinesview-icon .machine-container').length < 2) {
702
        showWelcome();
703
    } else {
704
        hideWelcome();
705
    }
706
    // set confirm box position
707
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height()) {
708
        $('.confirm_multiple').addClass('fixed');
709
    } else {
710
        $('.confirm_multiple').removeClass('fixed');
711
    }
712
}
713

714
// reposition multiple confirmation box on window resize
715
$(window).resize(function(){
716
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
717
        $('.confirm_multiple').addClass('fixed');
718
    else
719
        $('.confirm_multiple').removeClass('fixed');
720
});
721

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

744
// indicate that the requested action was succesfully completed
745
function display_success(serverID) {
746

747
}
748

749
// indicate that the requested action was not completed
750
function display_failure(status, serverID, action, responseText) {
751
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
752
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
753
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
754
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
755
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
756
}
757

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

776
// set the label of the multiple buttons
777
$('.confirm_multiple button.yes').text('Confirm All');
778
$('.confirm_multiple button.no').text('Cancel All');
779

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