Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ 056964f6

History | View | Annotate | Download (42.4 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

280
    // toggling resizes the main content, check the confirmations box position
281
    $(this).parent().parent().find(".info-content").slideToggle(600, update_confirmations_position);
282
    return false;
283
});
284

285

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

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

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

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

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

339
    vm = get_machine(serverId)
340
    vm.name = serverName;
341
    longName = vm.name;
342

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

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

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

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

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

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

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

464

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

779
    // set confirm box position
780
    update_confirmations_position();
781
    update_transition_names();
782
}
783

784
function update_confirmations_position() {
785
    // ie fix
786
    var height = window.innerHeight || window.document.body.clientHeight;
787
    if (height - CONFIRMBOX_OFFSET < $('#machinesview-icon').height()) {
788
        $('.confirm_multiple').addClass('fixed');
789
    } else {
790
        $('.confirm_multiple').removeClass('fixed');
791
    }
792
}
793

794
// reposition multiple confirmation box on window resize
795
$(window).resize(function(){
796
    update_confirmations_position();
797
});
798

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

821
// define these to avoid exceptions
822
function display_reboot_success() {
823
}
824

825
function display_reboot_failure() {
826
}
827

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

838
// indicate that the requested action was succesfully completed
839
function display_success(serverID) {
840

841
}
842

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

852
// handle update stats
853
function update_server_stats() {
854
// TODO: only reload images for expanded machines
855
    $(".vm-stats").each(function(){
856
        var serverID = $(this).closest(".machine-container").attr("id");
857
        get_server_stats(serverID);
858
    });
859
}
860

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

879
// set the label of the multiple buttons
880
$('.confirm_multiple button.yes').text('Confirm All');
881
$('.confirm_multiple button.no').text('Cancel All');
882

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

929

930
}
931

932
$(".stats-report").live('click', function(){
933
    var el = $(this);
934
    var srvID = el.closest(".machine-container").attr("id");
935

936
    $.cookie('server', srvID);
937
    $('a#single').click();
938
})
939

940

941
// machine rename hover handlers
942
if ($.browser.msie) {
943
    $(".machine .name, .machine .namecontainer, .machine span.name").live('mouseover', function() {
944
        $(this).parent().find("span.rename").addClass("rename_hovered");
945
    })
946
    $(".machine .name").live('mouseout', function() {
947
        $(this).parent().find("span.rename").removeClass("rename_hovered");
948
    })
949
}
950
</script>