Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ a09987c3

History | View | Annotate | Download (41.1 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 cpu-cont'>
80
                            <img src="./static/placeholder.png" class="cpu bar" />
81
                            <img src="./static/icons/indicators/small/progress.gif" class="stat-busy" />
82
                            <div class='stat-error'>{% trans "Could not fetch CPU stats graph." %}</div>
83
                        </div>
84
                        <div class='stat-label'>{% trans "Net" %}</div>
85
                        <div class='stat-content net-cont'>
86
                            <img src="./static/placeholder.png" class="net bar" />
87
                            <img src="./static/icons/indicators/small/progress.gif" class="stat-busy" />
88
                            <div class='stat-error'>{% trans "Could not fetch Net stats graph." %}</div>
89
                        </div>
90
                        <a href="#" class="stats-report">{% trans "Full report" %}</a>
91
                    </div>
92
                    <div class="vm-metadata metadata-column">
93
                        <div class="metadata-left">
94
                            {% trans "Tags" %}: <br />
95
                            (<span class="metadata-count">0</span>)
96
                        </div>
97
                        <div class="metadata-keys-container">
98
                            <div class="scrollable vertical">
99
                                <div class="items">
100
                                </div>
101
                            </div>
102
                            <div class="metadata-actions">
103
                                <div class="prev"></div>
104
                                <div class="next"></div>
105
                            </div>
106
                        </div>
107
                        <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
108
                    </div>
109
                </div>
110
            </div>
111
            <div class="state">
112
                <div class="status">{% trans "Running" %}</div>
113
                <div class="indicators">
114
                    <div class="indicator1"></div>
115
                    <div class="indicator2"></div>
116
                    <div class="indicator3"></div>
117
                    <div class="indicator4"></div>
118
                </div>
119
                <div class="action-indicator" style="display:none"></div>
120
                <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
121
                <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
122
            </div>
123
            <div class="actions clearfix">
124
                <div class="action-container start">
125
                    <a href="#" class="action-start">{% trans "Start" %}</a>
126
                    <div class="confirm_single">
127
                        <button class="yes">{% trans "Confirm" %}</button>
128
                        <button class="no">X</button>
129
                    </div>
130
                </div>
131
                <div class="action-container reboot">
132
                    <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
133
                    <div class="confirm_single">
134
                        <button class="yes">{% trans "Confirm" %}</button>
135
                        <button class="no">X</button>
136
                    </div>
137
                </div>
138
                <div class="action-container shutdown">
139
                    <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
140
                    <div class="confirm_single">
141
                        <button class="yes">{% trans "Confirm" %}</button>
142
                        <button class="no">X</button>
143
                    </div>
144
                </div>
145
                <div class="action-container console">
146
                    <a href="#" class="action-console">{% trans "Console" %}</a>
147
                    <div class="confirm_single">
148
                        <button class="yes">{% trans "Confirm" %}</button>
149
                        <button class="no">X</button>
150
                    </div>
151
                </div>
152
                <div class="action-container destroy">
153
                    <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
154
                    <div class="confirm_single">
155
                        <button class="yes">{% trans "Confirm" %}</button>
156
                        <button class="no">X</button>
157
                    </div>
158
                </div>
159
            </div>
160
            <div class="action_error" align="center">
161
                {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
162
                <span class="code"></span>
163
                <span class="message"></span>
164
                <button class="details">{% trans "Details" %}</button>
165
            </div>
166
        </div>
167
        <div class="separator"></div>
168
    </div><div class="large-spinner"></div>
169
    <div class="running disabled"></div>
170
    <div class="terminated" style="display:none;"></div>
171
</div>
172

    
173
<script>
174
CONFIRMBOX_OFFSET = 200;
175

176
init_action_indicator_handlers('icon');
177

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

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

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

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

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

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

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

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

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

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

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

256
//hide the all of the info contents
257
$("#machinesview-icon.standard .info-content").hide();
258
//toggle the component with class info-content
259
$("#machinesview-icon.standard div.info-header").live('click', function() {
260
    if ($(this).find('.toggler').hasClass('up')) {
261
        // toggle drop-down pane
262
        $(this).find('.toggler').removeClass('up');
263
        $(this).find('.toggler').addClass('down');
264
        $(this).find('.info-label').removeClass('darker');
265
        $(this).parent().parent().removeClass('light-background');
266
    } else {
267
        // reset stats
268
        $(this).closest('.machine-container').find('.vm-stats div.stat-error').hide();
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

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

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

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

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

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

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

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

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

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

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

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

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

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

461

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

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

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

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

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

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

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

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

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

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

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

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

726
        // if machine in destroy state keep it that way
727
        var server = get_machine(server.id);
728
        if (server.status == "DESTROY") {
729
            existing = $('#machinesview-icon.standard #' + server.id);
730
            if (existing.length) {
731
                $(existing).find('.status').text(TRANSITIONS['Destroying']);
732
                $(existing).find('.state').removeClass().addClass('state destroying-state');
733
                $(existing).find('.spinner').show();
734
                $(existing).find('.wave').hide();
735
            }
736
        }
737
    });
738
    /*
739
    Do some standard stuff, repeated each time
740
    FIXME: Can these be moved to a new function?
741
    */
742
    fix_v6_addresses();
743
    $("div.large-spinner").hide();
744
    $("div.running").removeClass("disabled");
745
    // show all separators and hide the last one
746
    $("#machinesview-icon.standard div.machine-container div.separator").show();
747
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
748
    // the terminated div shows only when terminated machines are available
749
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
750
        $("div.terminated").fadeIn("slow");
751
    } else {
752
        $("div.terminated").fadeOut("slow");
753
    }
754
    // show message in case user has no servers!
755
    if ($('#machinesview-icon .machine-container').length < 2) {
756
        showWelcome();
757
    } else {
758
        hideWelcome();
759
    }
760
    // set confirm box position
761
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height()) {
762
        $('.confirm_multiple').addClass('fixed');
763
    } else {
764
        $('.confirm_multiple').removeClass('fixed');
765
    }
766

767
    update_transition_names();
768
}
769

770
// reposition multiple confirmation box on window resize
771
$(window).resize(function(){
772
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
773
        $('.confirm_multiple').addClass('fixed');
774
    else
775
        $('.confirm_multiple').removeClass('fixed');
776
});
777

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

800
// define these to avoid exceptions
801
function display_reboot_success() {
802
}
803

804
function display_reboot_failure() {
805
}
806

807
// append string to transition states
808
function update_transition_names() {
809
    $(".state .status").each(function(index,el){
810
    var tr_text = $(this).text().replace(TRANSITION_STATE_APPEND,"");
811
    if (TRANSITION_STATES.indexOf(tr_text) >= 0) {
812
            $(this).text(tr_text + TRANSITION_STATE_APPEND);
813
        }
814
    })
815
}
816

817
// indicate that the requested action was succesfully completed
818
function display_success(serverID) {
819

820
}
821

822
// indicate that the requested action was not completed
823
function display_failure(status, serverID, action, responseText) {
824
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
825
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
826
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
827
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
828
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
829
}
830

831
// handle update stats
832
function update_server_stats() {
833
    // TODO: only reload images for expanded machines
834
    $(".vm-stats").each(function(){
835
        var serverID = $(this).closest(".machine-container").attr("id");
836
        get_server_stats(serverID);
837
    });
838
}
839

840
// basic functions executed on page load
841
if ( flavors.length == 0 && images.length == 0 ) {
842
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
843
    update_flavors();
844
    // populate image list
845
    update_images();
846
} else if ( flavors.length == 0 && images.length != 0 ) {
847
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
848
    update_flavors();
849
} else if ( flavors.length != 0 && images.length == 0 ) {
850
    // populate image list
851
    update_images();
852
    update_vms(UPDATE_INTERVAL);
853
} else {
854
    // start updating vm list
855
    update_vms(UPDATE_INTERVAL);
856
}
857

858
// set the label of the multiple buttons
859
$('.confirm_multiple button.yes').text('Confirm All');
860
$('.confirm_multiple button.no').text('Cancel All');
861

862
//IE specific fixes
863
if ($.browser.msie) {
864
    //IE fix for machine div hover
865
    $("div.machine").live("mouseenter", function () {
866
        $(this).css("background-color","#A1C8DB");
867
        $(this).find("div.info-header").css("background-color","#84b7d0");
868
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
869
        $(this).find(".actions a").css("visibility","visible");
870
    });
871
    $("div.machine").live("mouseleave", function () {
872
        $(this).css("background-color","transparent");
873
        $(this).find("div.info-header").css("background-color","#A1C8DB");
874
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
875
        if ($(this).parent().find(".confirm_single:visible").length == 0) {
876
            $(this).find(".actions a").css("visibility","hidden");
877
        }
878
    });
879
    //IE fix for green arrow hover
880
    $("div.connect-arrow").live("mouseenter", function () {
881
        $(this).addClass("connect-arrow-ie");
882
    });
883
    $("div.connect-arrow").live("mouseleave", function () {
884
        $(this).removeClass("connect-arrow-ie");
885
    });
886
    //IE fix for details button
887
    $("button.details").live("mouseenter", function () {
888
        $(this).css("background-color","#FF7F2A");
889
    });
890
    $("button.details").live("mouseleave", function () {
891
        $(this).css("background-color","transparent");
892
    });
893
    //IE fix for multiple conf yes button
894
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
895
        $(this).css("background-color","#FF7F2A");
896
    });
897
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
898
        $(this).css("background-color","transparent");
899
    });
900
    //IE fix for multiple conf no button
901
    $("div.confirm_multiple button.no").live("mouseenter", function () {
902
        $(this).css("background-color","#5CA1C0");
903
    });
904
    $("div.confirm_multiple button.no").live("mouseleave", function () {
905
        $(this).css("background-color","transparent");
906
    });
907

908

909
}
910

911
$(".stats-report").live('click', function(){
912
    var el = $(this);
913
    var srvID = el.closest(".machine-container").attr("id");
914

915
    $.cookie('server', srvID);
916
    $('a#single').click();
917
})
918
</script>