Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 69ba1fcf

History | View | Annotate | Download (41.9 kB)

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

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

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

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

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

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

    
36
{% load i18n %}
37

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

    
174
<script>
175
CONFIRMBOX_OFFSET = 200;
176

177
init_action_indicator_handlers('icon');
178

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

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

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

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

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

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

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

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

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

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

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

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

283

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

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

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

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

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

337
    vm = get_machine(serverId)
338
    vm.name = serverName;
339
    longName = vm.name;
340

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

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

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

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

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

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

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

462

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

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

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

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

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

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

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

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

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

685
            //show spinner if server is still building or rebooting
686
            if (server.status == 'BUILD') {
687
                machine.find('.spinner').show();
688
                machine.find('.state').removeClass().addClass('state build-state');
689
                machine.addClass('vm-building');
690
            } else {
691
                machine.removeClass('vm-building');
692
            }
693

694
            if (server.status == 'REBOOT') {
695
                machine.find('.spinner').show();
696
                machine.find('.state').removeClass().addClass('state rebooting-state');
697
            }
698
            // find and display flavor parameters
699
            var flavor_params = get_flavor_params(server.flavorRef);
700
            machine.find(".cpu-data").text(flavor_params['cpus']);
701
            machine.find(".ram-data").text(flavor_params['ram']);
702
            machine.find(".disk-data").text(flavor_params['disk']);
703
            // find and display image parameters
704
            var image_params = get_image_params(server.imageRef);
705
            machine.find(".image-data").text(image_params['name'].substring(0,15));
706
            machine.find(".image-size-data").text(image_params['size']);
707
            // find and display ips
708
            var ips = get_public_ips(server);
709
            machine.find("span.ip span.public").text(ips['ip4']);
710
            machine.find("span.ip span.public.ipv6-text").text(ips['ip6']);
711

712
            // add stats images error events handlers
713
            $("img.cpu, img.net").error(function(){
714
                $(this).hide();
715
                $(this).parent().find(".stat-error").show();
716
            }).load(function(){
717
                $(this).show();
718
                $(this).parent().find(".stat-error").hide();
719
            });
720
        }
721
        /*
722
        Do some repeated actions that include:
723
            1. Update actions
724
            2. Metadata list updating
725
        */
726
        update_iconview_actions(server.id, server.status);
727
        if (!(server.metadata == undefined)) {
728
                list_metadata_keys(server.id, server.metadata.values);
729
        }
730

731
        var server = get_machine(server.id);
732
        existing = $('#machinesview-icon.standard #' + server.id);
733

734
        // if machine in destroy state keep it that way
735
        if (server.status == "DESTROY" && existing.length >0) {
736
            $(existing).find('.status').text(TRANSITIONS['Destroying']);
737
            $(existing).find('.state').removeClass().addClass('state destroying-state');
738
            $(existing).find('.spinner').show();
739
            $(existing).find('.wave').hide();
740
        }
741

742
        // update progress
743
        if (server.status == 'BUILD' && existing.length > 0) {
744
            // update bulding progress
745
            var progress_details = get_progress_details(server.id);
746
            existing.find("span.ip").hide();
747
            existing.find("span.build-progress").show().text(progress_details.msg);
748
        } else {
749
            // hide building progress
750
            existing.find("span.ip").show()
751
            existing.find("span.build-progress").hide();
752
        }
753
    });
754
    /*
755
    Do some standard stuff, repeated each time
756
    FIXME: Can these be moved to a new function?
757
    */
758
    fix_v6_addresses();
759
    $("div.large-spinner").hide();
760
    $("div.running").removeClass("disabled");
761
    // show all separators and hide the last one
762
    $("#machinesview-icon.standard div.machine-container div.separator").show();
763
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
764
    // the terminated div shows only when terminated machines are available
765
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
766
        $("div.terminated").fadeIn("slow");
767
    } else {
768
        $("div.terminated").fadeOut("slow");
769
    }
770
    // show message in case user has no servers!
771
    if ($('#machinesview-icon .machine-container').length < 2) {
772
        showWelcome();
773
    } else {
774
        hideWelcome();
775
    }
776
    // set confirm box position
777
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height()) {
778
        $('.confirm_multiple').addClass('fixed');
779
    } else {
780
        $('.confirm_multiple').removeClass('fixed');
781
    }
782

783
    update_transition_names();
784
}
785

786
// reposition multiple confirmation box on window resize
787
$(window).resize(function(){
788
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
789
        $('.confirm_multiple').addClass('fixed');
790
    else
791
        $('.confirm_multiple').removeClass('fixed');
792
});
793

794
// update metadata list
795
function list_metadata_keys(serverID, keys) {
796
    // empty the list if it already exists
797
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
798
    //start counter
799
    var i=0;
800
    // show values
801
    for (var key in keys) {
802
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
803
        i++;
804
    }
805
    //hide the metadata controls if we have less than 3 metadata
806
    if (i <= 3) {
807
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
808
    }
809
    //show the metadata controls if we have more than 3 metadata
810
    if (i > 3) {
811
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
812
    }
813
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
814
}
815

816
// define these to avoid exceptions
817
function display_reboot_success() {
818
}
819

820
function display_reboot_failure() {
821
}
822

823
// append string to transition states
824
function update_transition_names() {
825
    $(".state .status").each(function(index,el){
826
    var tr_text = $(this).text().replace(TRANSITION_STATE_APPEND,"");
827
    if (TRANSITION_STATES.indexOf(tr_text) >= 0) {
828
            $(this).text(tr_text + TRANSITION_STATE_APPEND);
829
        }
830
    })
831
}
832

833
// indicate that the requested action was succesfully completed
834
function display_success(serverID) {
835

836
}
837

838
// indicate that the requested action was not completed
839
function display_failure(status, serverID, action, responseText) {
840
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
841
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
842
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
843
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
844
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
845
}
846

847
// handle update stats
848
function update_server_stats() {
849
    // TODO: only reload images for expanded machines
850
    $(".vm-stats").each(function(){
851
        var serverID = $(this).closest(".machine-container").attr("id");
852
        get_server_stats(serverID);
853
    });
854
}
855

856
// basic functions executed on page load
857
if ( flavors.length == 0 && images.length == 0 ) {
858
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
859
    update_flavors();
860
    // populate image list
861
    update_images();
862
} else if ( flavors.length == 0 && images.length != 0 ) {
863
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
864
    update_flavors();
865
} else if ( flavors.length != 0 && images.length == 0 ) {
866
    // populate image list
867
    update_images();
868
    update_vms(UPDATE_INTERVAL);
869
} else {
870
    // start updating vm list
871
    update_vms(UPDATE_INTERVAL);
872
}
873

874
// set the label of the multiple buttons
875
$('.confirm_multiple button.yes').text('Confirm All');
876
$('.confirm_multiple button.no').text('Cancel All');
877

878
//IE specific fixes
879
if ($.browser.msie) {
880
    //IE fix for machine div hover
881
    $("div.machine").live("mouseenter", function () {
882
        $(this).css("background-color","#A1C8DB");
883
        $(this).find("div.info-header").css("background-color","#84b7d0");
884
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
885
        $(this).find(".actions a").css("visibility","visible");
886
    });
887
    $("div.machine").live("mouseleave", function () {
888
        $(this).css("background-color","transparent");
889
        $(this).find("div.info-header").css("background-color","#A1C8DB");
890
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
891
        if ($(this).parent().find(".confirm_single:visible").length == 0) {
892
            $(this).find(".actions a").css("visibility","hidden");
893
        }
894
    });
895
    //IE fix for green arrow hover
896
    $("div.connect-arrow").live("mouseenter", function () {
897
        $(this).addClass("connect-arrow-ie");
898
    });
899
    $("div.connect-arrow").live("mouseleave", function () {
900
        $(this).removeClass("connect-arrow-ie");
901
    });
902
    //IE fix for details button
903
    $("button.details").live("mouseenter", function () {
904
        $(this).css("background-color","#FF7F2A");
905
    });
906
    $("button.details").live("mouseleave", function () {
907
        $(this).css("background-color","transparent");
908
    });
909
    //IE fix for multiple conf yes button
910
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
911
        $(this).css("background-color","#FF7F2A");
912
    });
913
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
914
        $(this).css("background-color","transparent");
915
    });
916
    //IE fix for multiple conf no button
917
    $("div.confirm_multiple button.no").live("mouseenter", function () {
918
        $(this).css("background-color","#5CA1C0");
919
    });
920
    $("div.confirm_multiple button.no").live("mouseleave", function () {
921
        $(this).css("background-color","transparent");
922
    });
923

924

925
}
926

927
$(".stats-report").live('click', function(){
928
    var el = $(this);
929
    var srvID = el.closest(".machine-container").attr("id");
930

931
    $.cookie('server', srvID);
932
    $('a#single').click();
933
})
934
</script>