Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (42.7 kB)

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

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

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

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

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

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

    
36
{% load i18n %}
37

    
38
<!-- the standard view -->
39
<div id="machinesview-icon" class="standard">
40
    <div class="machine-container" id="machine-container-template" style="display:none">
41
        <div class="machine" id="machine-template">
42
            <div class='connect-border' title='{% trans 'Connect  machine' %}'></div>
43
            <div class='connect-arrow' title='{% trans 'Connect  machine' %}'></div>
44
            <div class="logo"></div>
45
            <div class="machine-details">
46
                <div href="#" class="name">
47
                    <h5 class="namecontainer editable">
48
                        <span class="name">node.name</span><span class="rename"></span>
49
                        <div class="editbuttons" style="display:none">
50
                            <div class="save"></div>
51
                            <div class="cancel"></div>
52
                        </div>
53
                    </h5>
54
                </div>
55
                <span class="ip">
56
                    <h5>
57
                        {% trans "IP:" %} <span class="ip-version-label">v4</span> <span class="public ipv4-text"></span>
58
                        <span class="ip-version-label">v6</span> <span class="public ipv6-text"></span>
59
                    </h5>
60
                </span>
61
                <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
        vm = iconview_closest_vm(this);
183
        if ($(this).parent().parent().find('.status').text().replace(TRANSITION_STATE_APPEND, "") != STATUSES['ACTIVE'] || !vm_has_public_ip(vm)) { return };
184
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1);
185
        var parent = $(this).parent().parent();
186
        parent.find(".connect-arrow").show().addClass('border-hover');
187
    });
188

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

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

207
$("div.connect-arrow, div.running .machine .logo").live('mouseup',
208
    function() {
209
        vm = iconview_closest_vm(this);
210
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0 || !vm_has_public_ip(vm)) { return };
211
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1, "click");
212
    });
213

214
// actions on machine mouseover
215
$("#machinesview-icon.standard .machine").live('mouseover', function() {
216
    // show connect button only if the machine is active
217
    vm = iconview_closest_vm(this);
218
    if ($(this).find('.status').text().replace(TRANSITION_STATE_APPEND, "") == STATUSES['ACTIVE'] && vm_has_public_ip(vm)) {
219
        $(this).find("div.connect-arrow").show();
220
        $(this).find("div.connect-border").show();
221
    }
222
});
223

224
// actions on machine mouseout
225
$("#machinesview-icon.standard .machine").live('mouseout', function() {
226
    // hide connect button
227
    $(this).find("div.connect-arrow").hide();
228
    $(this).find("div.connect-border").hide();
229
});
230

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

236
// actions on connect arrow border mouseout
237
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
238
    $(this).next().removeClass('border-hover');
239
});
240

241
// open console on machine logo click
242
$("#machinesview-icon.standard .running div.logo").live('click', function(){
243
    vm = iconview_closest_vm(this);
244
    if ($(this).parent().parent().find(".connect-arrow:visible").length == 0 || !vm_has_public_ip(vm)) { return };
245
    var serverID = $(this).parent().parent().attr("id");
246
    machine_connect([machine_connect, serverID]);
247
    return false;
248
});
249

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

256
// open console on connect arrow border click
257
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
258
    var serverID = $(this).parent().parent().attr("id");
259
    machine_connect([machine_connect, serverID]);
260
    return false;
261
});
262

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

286
    // toggling resizes the main content, check the confirmations box position
287
    $(this).parent().parent().find(".info-content").slideToggle(600, update_confirmations_position);
288
    return false;
289
});
290

291

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

310
//initiate machine renaming
311
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
312
    serverId = $(this).closest('.machine-container').attr("id");
313
    vm = get_machine(serverId);
314

315
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
316
                                        vm.name +
317
                                        "\" / ><span class=\"oldValue\">" +
318
                                        vm.name + "</span>");
319
    $(this).parent().find('.rename').hide();
320
    $(this).parent().find(".editbuttons").fadeIn();
321
    $(this).parent().find(".nametextbox").focus().select();
322
    $(this).parent().removeClass('editable');
323

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

337
//rename machine
338
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
339
    serverID = $(this).closest('.machine-container').attr("id");
340
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
341
    if (serverName.trim() == ''){
342
        return false;
343
    }
344

345
    vm = get_machine(serverId)
346
    vm.name = serverName;
347
    longName = vm.name;
348

349
    var serverName = $(this).parent().parent().find('.nametextbox').val();
350
    serverName = fix_server_name(serverName);
351

352
    $(this).parent().parent().find('.name').html(serverName);
353
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
354
    $(this).parent().parent().find(".rename").fadeIn("slow");
355
    $(this).parent().parent().addClass('editable');
356
    rename(serverID, longName);
357
    return false;
358
});
359

360
//cancel renaming
361
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
362
    $(this).parent().parent().find('.name').html(fix_server_name($(this).parent().parent().find('.oldValue').text()));
363
    $(this).parent().parent().find(".editbuttons").hide();
364
    $(this).parent().parent().find(".rename").fadeIn();
365
    $(this).parent().parent().addClass('editable');
366
    return false;
367
});
368

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

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

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

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

470

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

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

524
    $(this).parent().hide();
525
    $(this).closest('div.actions').find('a').removeClass('selected');
526
    $(this).closest("div.machine").children('.state').children('.spinner').show()
527
    $(this).closest("div.machine").children('div.actions').removeClass('display');
528
    update_transition_names();
529
    update_confirmations();
530
    return false;
531
});
532

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

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

549
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
550
    // remove the action from the pending list
551
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
552
    $(this).parent().hide();
553
});
554

555
// update the servers list
556
function update_machines_view(data) {
557
    /*
558
    Go through the servers in the input data. Update existing entries, add
559
    new ones to the list
560
    */
561
    $.each(data.servers.values, function(i,server) {
562

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

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

693
            //show spinner if server is still building or rebooting
694
            if (server.status == 'BUILD') {
695
                machine.find('.spinner').show();
696
                machine.find('.state').removeClass().addClass('state build-state');
697
                machine.addClass('vm-building');
698
            } else {
699
                machine.removeClass('vm-building');
700
            }
701

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

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

739
        var server = get_machine(server.id);
740
        existing = $('#machinesview-icon.standard #' + server.id);
741

742
        // if machine in destroy state keep it that way
743
        if (server.status == "DESTROY" && existing.length >0) {
744
            $(existing).find('.status').text(TRANSITIONS['Destroying']);
745
            $(existing).find('.state').removeClass().addClass('state destroying-state');
746
            $(existing).find('.spinner').show();
747
            $(existing).find('.wave').hide();
748
        }
749

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

785
    // set confirm box position
786
    update_confirmations_position();
787
    update_transition_names();
788
}
789

790
function update_confirmations_position() {
791
    // ie fix
792
    var height = window.innerHeight || window.document.body.clientHeight;
793
    if (height - CONFIRMBOX_OFFSET < $('#machinesview-icon').height()) {
794
        $('.confirm_multiple').addClass('fixed');
795
    } else {
796
        $('.confirm_multiple').removeClass('fixed');
797
    }
798
}
799

800
// reposition multiple confirmation box on window resize
801
$(window).resize(function(){
802
    update_confirmations_position();
803
});
804

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

827
// define these to avoid exceptions
828
function display_reboot_success() {
829
}
830

831
function display_reboot_failure() {
832
}
833

834
// append string to transition states
835
function update_transition_names() {
836
    $(".state .status").each(function(index,el){
837
    var tr_text = $(this).text().replace(TRANSITION_STATE_APPEND,"");
838
    if (TRANSITION_STATES.indexOf(tr_text) >= 0) {
839
            $(this).text(tr_text + TRANSITION_STATE_APPEND);
840
        }
841
    })
842
}
843

844
// indicate that the requested action was succesfully completed
845
function display_success(serverID) {
846

847
}
848

849
// indicate that the requested action was not completed
850
function display_failure(status, serverID, action, responseText) {
851
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
852
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
853
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
854
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
855
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
856
}
857

858
// handle update stats
859
function update_server_stats() {
860
// TODO: only reload images for expanded machines
861
    $(".vm-stats").each(function(){
862
        var serverID = $(this).closest(".machine-container").attr("id");
863
        get_server_stats(serverID);
864
    });
865
}
866

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

885
// set the label of the multiple buttons
886
$('.confirm_multiple button.yes').text('Confirm All');
887
$('.confirm_multiple button.no').text('Cancel All');
888

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

935

936
}
937

938
$(".stats-report").live('click', function(){
939
    var el = $(this);
940
    var srvID = el.closest(".machine-container").attr("id");
941

942
    $.cookie('server', srvID);
943
    $('a#single').click();
944
})
945

946
// machine rename hover handlers
947
if ($.browser.msie) {
948
    $(".machine .name, .machine .namecontainer, .machine span.name").live('mouseover', function() {
949
        $(this).parent().find("span.rename").addClass("rename_hovered");
950
    })
951
    $(".machine .name").live('mouseout', function() {
952
        $(this).parent().find("span.rename").removeClass("rename_hovered");
953
    })
954
}
955

    
956
</script>