Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 23a4a31b

History | View | Annotate | Download (37.9 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 img.logo").live('click', function(){
228
    $(this).parent().parent().find("a.action-console").click();
229
    return false;
230
});
231

232
// open console on connect arrow click
233
$("#machinesview-icon.standard .running div.logo").live('click', function(){
234
    $(this).parent().parent().find("a.action-console").click();
235
    return false;
236
});
237

238
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
239
    $(this).parent().parent().find("a.action-console").click();
240
    return false;
241
});
242

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

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

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

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

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

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

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

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

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

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

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

446

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

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

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

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

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

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

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

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

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

746
}
747

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

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

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

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