Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 7af53e78

History | View | Annotate | Download (37.3 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('mouseenter',
175
    function() {
176
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1);
177
    });
178

179
$("div.connect-arrow, div.running .machine .logo").live('mouseleave',
180
    function() {
181
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "hover");
182
    });
183

184
$("div.connect-arrow, div.running .machine .logo").live('mousedown',
185
    function() {
186
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1);
187
    });
188

189
$("div.connect-arrow, div.running .machine .logo").live('mouseup',
190
    function() {
191
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1, "click");
192
    });
193

194
// actions on machine mouseover
195
$("#machinesview-icon.standard .machine").live('mouseover', function() {
196
    // show connect button only if the machine is active
197
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
198
        $(this).find("div.connect-arrow").show();
199
        $(this).find("div.connect-border").show();
200
    }
201
});
202

203
// actions on machine mouseout
204
$("#machinesview-icon.standard .machine").live('mouseout', function() {
205
    // hide connect button
206
    $(this).find("div.connect-arrow").hide();
207
    $(this).find("div.connect-border").hide();
208
});
209

210
// actions on connect arrow border mouseover
211
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
212
    $(this).next().addClass('border-hover');
213
});
214

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

220
// open console on machine logo click
221
$("#machinesview-icon.standard .running img.logo").live('click', function(){
222
    $(this).parent().parent().find("a.action-console").click();
223
    return false;
224
});
225

226
// open console on connect arrow click
227
$("#machinesview-icon.standard .running div.logo").live('click', function(){
228
    $(this).parent().parent().find("a.action-console").click();
229
    return false;
230
});
231

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

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

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

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

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

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

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

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

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

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

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

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

440

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

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

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

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

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

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

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

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

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

740
}
741

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

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

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

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