Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 9c87f9a9

History | View | Annotate | Download (40 kB)

1
<!--
2
Copyright 2011 GRNET S.A. All rights reserved.
3

4
Redistribution and use in source and binary forms, with or
5
without modification, are permitted provided that the following
6
conditions are met:
7

8
  1. Redistributions of source code must retain the above
9
     copyright notice, this list of conditions and the following
10
     disclaimer.
11

12
  2. Redistributions in binary form must reproduce the above
13
     copyright notice, this list of conditions and the following
14
     disclaimer in the documentation and/or other materials
15
     provided with the distribution.
16

17
THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
POSSIBILITY OF SUCH DAMAGE.
29

30
The views and conclusions contained in the software and
31
documentation are those of the authors and should not be
32
interpreted as representing official policies, either expressed
33
or implied, of GRNET S.A.
34
-->
35

    
36
{% load i18n %}
37

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

    
171
<script>
172
CONFIRMBOX_OFFSET = 200;
173

174
init_action_indicator_handlers('icon');
175

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

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

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

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

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

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

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

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

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

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

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

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

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

300
//initiate machine renaming
301
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
302
    serverId = $(this).closest('.machine-container').attr("id");
303
    vm = get_machine(serverId);
304

305
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
306
                                        vm.name +
307
                                        "\" / ><span class=\"oldValue\">" +
308
                                        vm.name + "</span>");
309
    $(this).parent().find('.rename').hide();
310
    $(this).parent().find(".editbuttons").fadeIn();
311
    $(this).parent().find(".nametextbox").focus().select();
312
    $(this).parent().removeClass('editable');
313

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

327
//rename machine
328
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
329
    serverID = $(this).closest('.machine-container').attr("id");
330
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
331
    if (serverName.trim() == ''){
332
        return false;
333
    }
334

335
    vm = get_machine(serverId)
336
    vm.name = serverName;
337
    longName = vm.name;
338

339
    var serverName = $(this).parent().parent().find('.nametextbox').val();
340
    serverName = fix_server_name(serverName);
341

342
    $(this).parent().parent().find('.name').html(serverName);
343
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
344
    $(this).parent().parent().find(".rename").fadeIn("slow");
345
    $(this).parent().parent().addClass('editable');
346
    rename(serverID, longName);
347
    return false;
348
});
349

350
//cancel renaming
351
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
352
    $(this).parent().parent().find('.name').html(fix_server_name($(this).parent().parent().find('.oldValue').text()));
353
    $(this).parent().parent().find(".editbuttons").hide();
354
    $(this).parent().parent().find(".rename").fadeIn();
355
    $(this).parent().parent().addClass('editable');
356
    return false;
357
});
358

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

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

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

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

460

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

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

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

525
    $(this).closest('div.action-container').children('a').removeClass('selected');
526
    $(this).closest('div.actions').removeClass('display');
527
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
528
        if (pending_actions[i][1] == serverID) {
529
            pending_actions.splice(i,1);
530
        }
531
    }
532
    $(this).parent().hide();
533
    update_confirmations();
534
    return false;
535
});
536

537
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
538
    // remove the action from the pending list
539
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
540
    $(this).parent().hide();
541
});
542

543
// update the servers list
544
function update_machines_view(data) {
545
    /*
546
    Go through the servers in the input data. Update existing entries, add
547
    new ones to the list
548
    */
549
    $.each(data.servers.values, function(i,server) {
550

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

657
            machine.find(".scrollable").scrollable({vertical: true});
658
            machine.find("div.name span.name").text(fix_server_name(server.name));
659
            machine.find("span.imagetag").text(server_image);
660
            machine.find(".status").text(STATUSES[server.status]);
661
            // check server status to select where to append the new server to
662
            if (ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0 ) {
663
                // append to running
664
                set_machine_os_image(machine, "icon", "on", server_image);
665
                machine.appendTo("#machinesview-icon.standard .running");
666
            } else {
667
                // append to terminated
668
                set_machine_os_image(machine, "icon", "off", server_image);
669
                machine.appendTo("#machinesview-icon.standard .terminated");
670
                if (server.status == "STOPPED") { //if server status us stopped is a different case than status unknown/error
671
                    machine.find('.state').removeClass().addClass('state terminated-state');
672
                } else {
673
                       machine.find('.state').removeClass().addClass('state error-state');
674
                }
675
            }
676

677
            //show spinner if server is still building or rebooting
678
            if (server.status == 'BUILD') {
679
                machine.find('.spinner').show();
680
                machine.find('.state').removeClass().addClass('state build-state');
681
                machine.addClass('vm-building');
682
            } else {
683
                machine.removeClass('vm-building');
684
            }
685

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

714
        // if machine in destroy state keep it that way
715
        var server = get_machine(server.id);
716
        if (server.status == "DESTROY") {
717
            existing = $('#machinesview-icon.standard #' + server.id);
718
            if (existing.length) {
719
                $(existing).find('.status').text(TRANSITIONS['Destroying']);
720
                $(existing).find('.state').removeClass().addClass('state destroying-state');
721
                $(existing).find('.spinner').show();
722
                $(existing).find('.wave').hide();
723
            }
724
        }
725

726

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

758
// reposition multiple confirmation box on window resize
759
$(window).resize(function(){
760
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
761
        $('.confirm_multiple').addClass('fixed');
762
    else
763
        $('.confirm_multiple').removeClass('fixed');
764
});
765

766
// update metadata list
767
function list_metadata_keys(serverID, keys) {
768
    // empty the list if it already exists
769
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
770
    //start counter
771
    var i=0;
772
    // show values
773
    for (var key in keys) {
774
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
775
        i++;
776
    }
777
    //hide the metadata controls if we have less than 3 metadata
778
    if (i <= 3) {
779
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
780
    }
781
    //show the metadata controls if we have more than 3 metadata
782
    if (i > 3) {
783
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
784
    }
785
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
786
}
787

788
// indicate that the requested action was succesfully completed
789
function display_success(serverID) {
790

791
}
792

793
// indicate that the requested action was not completed
794
function display_failure(status, serverID, action, responseText) {
795
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
796
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
797
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
798
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
799
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
800
}
801

802
// basic functions executed on page load
803
if ( flavors.length == 0 && images.length == 0 ) {
804
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
805
    update_flavors();
806
    // populate image list
807
    update_images();
808
} else if ( flavors.length == 0 && images.length != 0 ) {
809
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
810
    update_flavors();
811
} else if ( flavors.length != 0 && images.length == 0 ) {
812
    // populate image list
813
    update_images();
814
    update_vms(UPDATE_INTERVAL);
815
} else {
816
    // start updating vm list
817
    update_vms(UPDATE_INTERVAL);
818
}
819

820
// set the label of the multiple buttons
821
$('.confirm_multiple button.yes').text('Confirm All');
822
$('.confirm_multiple button.no').text('Cancel All');
823

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

870

871
}
872

873
$(".stats-report").live('click', function(){
874
    var el = $(this);
875
    var srvID = el.closest(".machine-container").attr("id");
876

877
    $.cookie('server', srvID);
878
    $('a#single').click();
879
})
880
</script>