Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 6dd01959

History | View | Annotate | Download (40.7 kB)

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

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

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

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

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

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

    
36
{% load i18n %}
37

    
38
<!-- the standard view -->
39
<div id="machinesview-icon" class="standard">
40
    <div class="machine-container" id="machine-container-template" style="display:none">
41
        <div class="machine" id="machine-template">
42
            <div class='connect-border' title='{% trans 'Connect  machine' %}'></div>
43
            <div class='connect-arrow' title='{% trans 'Connect  machine' %}'></div>
44
            <div class="logo"></div>
45
            <div class="machine-details">
46
                <div href="#" class="name">
47
                    <h5 class="namecontainer editable">
48
                        <span class="name">node.name</span><span class="rename"></span>
49
                        <div class="editbuttons" style="display:none">
50
                            <div class="save"></div>
51
                            <div class="cancel"></div>
52
                        </div>
53
                    </h5>
54
                </div>
55
                <span 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
                </span>
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().replace(TRANSITION_STATE_APPEND, "") != 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().replace(TRANSITION_STATE_APPEND, "") != 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().replace(TRANSITION_STATE_APPEND, "") == 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

514
    $(this).parent().hide();
515
    $(this).closest('div.actions').find('a').removeClass('selected');
516
    $(this).closest("div.machine").children('.state').children('.spinner').show()
517
    $(this).closest("div.machine").children('div.actions').removeClass('display');
518
    update_transition_names();
519
    update_confirmations();
520
    return false;
521
});
522

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

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

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

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

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

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

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

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

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

728

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

759
    update_transition_names();
760
}
761

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

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

792
// define these to avoid exceptions
793
function display_reboot_success() {
794
}
795

796
function display_reboot_failure() {
797
}
798

799
// append string to transition states
800
function update_transition_names() {
801
    $(".state .status").each(function(index,el){
802
    var tr_text = $(this).text().replace(TRANSITION_STATE_APPEND,"");
803
    if (TRANSITION_STATES.indexOf(tr_text) >= 0) {
804
            $(this).text(tr_text + TRANSITION_STATE_APPEND);
805
        }
806
    })
807
}
808

809
// indicate that the requested action was succesfully completed
810
function display_success(serverID) {
811

812
}
813

814
// indicate that the requested action was not completed
815
function display_failure(status, serverID, action, responseText) {
816
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
817
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
818
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
819
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
820
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
821
}
822

823
// basic functions executed on page load
824
if ( flavors.length == 0 && images.length == 0 ) {
825
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
826
    update_flavors();
827
    // populate image list
828
    update_images();
829
} else if ( flavors.length == 0 && images.length != 0 ) {
830
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
831
    update_flavors();
832
} else if ( flavors.length != 0 && images.length == 0 ) {
833
    // populate image list
834
    update_images();
835
    update_vms(UPDATE_INTERVAL);
836
} else {
837
    // start updating vm list
838
    update_vms(UPDATE_INTERVAL);
839
}
840

841
// set the label of the multiple buttons
842
$('.confirm_multiple button.yes').text('Confirm All');
843
$('.confirm_multiple button.no').text('Cancel All');
844

845
//IE specific fixes
846
if ($.browser.msie) {
847
    //IE fix for machine div hover
848
    $("div.machine").live("mouseenter", function () {
849
        $(this).css("background-color","#A1C8DB");
850
        $(this).find("div.info-header").css("background-color","#84b7d0");
851
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
852
        $(this).find(".actions a").css("visibility","visible");
853
    });
854
    $("div.machine").live("mouseleave", function () {
855
        $(this).css("background-color","transparent");
856
        $(this).find("div.info-header").css("background-color","#A1C8DB");
857
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
858
        if ($(this).parent().find(".confirm_single:visible").length == 0) {
859
            $(this).find(".actions a").css("visibility","hidden");
860
        }
861
    });
862
    //IE fix for green arrow hover
863
    $("div.connect-arrow").live("mouseenter", function () {
864
        $(this).addClass("connect-arrow-ie");
865
    });
866
    $("div.connect-arrow").live("mouseleave", function () {
867
        $(this).removeClass("connect-arrow-ie");
868
    });
869
    //IE fix for details button
870
    $("button.details").live("mouseenter", function () {
871
        $(this).css("background-color","#FF7F2A");
872
    });
873
    $("button.details").live("mouseleave", function () {
874
        $(this).css("background-color","transparent");
875
    });
876
    //IE fix for multiple conf yes button
877
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
878
        $(this).css("background-color","#FF7F2A");
879
    });
880
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
881
        $(this).css("background-color","transparent");
882
    });
883
    //IE fix for multiple conf no button
884
    $("div.confirm_multiple button.no").live("mouseenter", function () {
885
        $(this).css("background-color","#5CA1C0");
886
    });
887
    $("div.confirm_multiple button.no").live("mouseleave", function () {
888
        $(this).css("background-color","transparent");
889
    });
890

891

892
}
893

894
$(".stats-report").live('click', function(){
895
    var el = $(this);
896
    var srvID = el.closest(".machine-container").attr("id");
897

898
    $.cookie('server', srvID);
899
    $('a#single').click();
900
})
901
</script>