Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_single.html @ 1df63521

History | View | Annotate | Download (36.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 single view -->
39
<div id="machinesview-single" class="single">
40
    <div class="large-spinner"></div>
41
    <div class="single-container" id="machine-container-template" style="display:none;" >
42
        <div class="upper">
43
            <div class="column1">
44
                <div class='connect-border' title='{% trans 'Connect  machine' %}'></div>
45
                <div class='connect-arrow' title='{% trans 'Connect  machine' %}'></div>
46
                <div class="single-image" />
47
                <div class="state">
48
                    <span class="state-label">{% trans "Running" %}</span>
49
                    <div class="indicators">
50
                        <div class="indicator1"></div>
51
                        <div class="indicator2"></div>
52
                        <div class="indicator3"></div>
53
                        <div class="indicator4"></div>
54
                    </div>
55
                    <div class="action-indicator" style="display:none"></div>
56
                    <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
57
                    <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
58
                </div>
59
            </div>
60
            <div class="column2">
61
                <div class="machine-labels">
62
                    <div class="machine-label name">{% trans "Name" %}:</div>
63
                    <div class="machine-label cpus">{% trans "CPUs" %}:</div>
64
                    <div class="machine-label ram">{% trans "RAM (MB)" %}:</div>
65
                    <div class="machine-label disk">{% trans "System Disk (GB)" %}:</div>
66
                    <div class="machine-label image-name">{% trans "Image Name" %}:</div>
67
                    <div class="machine-label image-size">{% trans "Image Size (GB)" %}:</div>
68
                    <div class="machine-label ipv4">{% trans "Public IPv4" %}:</div>
69
                    <div class="machine-label ipv6">{% trans "Public IPv6" %}:</div>
70
                </div>
71
                <div class="machine-details">
72
                    <div class="machine-detail name">My Desktop</div>
73
                    <div class="machine-detail cpus">4</div>
74
                    <div class="machine-detail ram">2048</div>
75
                    <div class="machine-detail disk">100</div>
76
                    <div class="machine-detail image-name">windos_XP_blah_blah</div>
77
                    <div class="machine-detail image-size">2.3</div>
78
                    <div class="machine-detail ipv4">no ipv4</div>
79
                    <div class="machine-detail ipv6">2001:db8:1f70::999:de8:7648:6e8</div>
80
                </div>
81
                <div class="tags">
82
                    <div class="tags-header">
83
                        <div class="tags-label">{% trans "Tags" %}</div>
84
                        <div class="toggler down"></div>
85
                    </div>
86
                    <div class="tags-content">
87
                        <div class="metadata-keys-container">
88
                            <div class="scrollable vertical">
89
                                <div class="items">
90
                                </div>
91
                            </div>
92
                            <div class="metadata-actions">
93
                                <div class="prev"></div>
94
                                <div class="next"></div>
95
                            </div>
96
                        </div>
97
                        <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
98
                    </div>
99
                </div>
100
            </div>
101
            <div class="single-actions">
102
                <div class="action-container start">
103
                    <div class="single-action action-start">{% trans "Start" %}</div>
104
                    <div class="confirm_single">
105
                        <button class="yes">{% trans "Confirm" %}</button>
106
                        <button class="no">X</button>
107
                    </div>
108
                </div>
109
                <div class="action-container reboot">
110
                    <div class="single-action action-reboot">{% trans "Reboot" %}</div>
111
                    <div class="confirm_single">
112
                        <button class="yes">{% trans "Confirm" %}</button>
113
                        <button class="no">X</button>
114
                    </div>
115
                </div>
116
                <div class="action-container shutdown">
117
                    <div class="single-action action-shutdown">{% trans "Shutdown" %}</div>
118
                    <div class="confirm_single">
119
                        <button class="yes">{% trans "Confirm" %}</button>
120
                        <button class="no">X</button>
121
                    </div>
122
                </div>
123
                <div class="action-container console">
124
                    <div class="single-action action-console">{% trans "Console" %}</div>
125
                    <div class="confirm_single">
126
                        <button class="yes">{% trans "Confirm" %}</button>
127
                        <button class="no">X</button>
128
                    </div>
129
                </div>
130
                <div class="action-container destroy">
131
                    <div class="single-action action-destroy">{% trans "Destroy" %}</div>
132
                    <div class="confirm_single">
133
                        <button class="yes">{% trans "Confirm" %}</button>
134
                        <button class="no">X</button>
135
                    </div>
136
                </div>
137
            </div>
138
            <div class="action_error" align="center">
139
                {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
140
                <span class="code"></span>
141
                <span class="message"></span>
142
                <button class="details">{% trans "Details" %}</button>
143
            </div>
144
        </div>
145
        <div class="lower">
146
            <div class="single-cpu">
147
                <div class="cpu-usage">
148
                    {% trans "CPU Utilization" %}
149
                </div>
150
                <div class="cpu-graph">
151
                    <img src="http://stats.okeanos.grnet.gr/test/cpu-ts.png" class="stats" />
152
                </div>
153
            </div>
154
            <div class="single-network">
155
                <div class="network-usage">
156
                    {% trans "Network Utilization" %}
157
                </div>
158
                <div class="network-graph">
159
                    <img src="http://stats.okeanos.grnet.gr/test/net-ts.png" class="stats" />
160
                </div>
161
            </div>
162
        </div>
163
    </div>
164
    <div class="column3" style="display:none;">
165
        <div class="controls">
166
            <div class="previous" style="display:block;">
167
                <div class="prev-arrow"></div>
168
                <div class="prev-label">
169
                    {% trans "previous" %}
170
                </div>
171
            </div>
172
            <div class="next" style="display:block;">
173
                <div class="next-arrow"></div>
174
                <div class="next-label">
175
                    {% trans "next" %}
176
                </div>
177
            </div>
178
        </div>
179
        <div class="separator">
180
        </div>
181
        <div class="servers">
182
            <div class="server-name" id="servers-widget-template" style="display:none;">server1</div>
183
        </div>
184
    </div>
185
</div>
186

    
187
<script>
188

189
init_action_indicator_handlers('single');
190

191
//hide the all of the tags contents
192
$("#machinesview-single.single .tags-content").hide();
193

194
// handle connect machine image states
195
$("div.connect-arrow, .single-image").live('mouseenter',
196
    function() {
197
        // ugly check to see if machine is running
198
        if ($(this).parent().find(".connect-arrow:visible").length == 0) { return };
199
        set_machine_os_image($(this).parent().parent(), "single", "hover", undefined, 1);
200
    });
201

202
$("div.connect-arrow, .single-image").live('mouseleave',
203
    function() {
204
        if ($(this).parent().find(".connect-arrow:visible").length == 0) { return };
205
        set_machine_os_image($(this).parent().parent(), "single", "hover", undefined, 1, "hover");
206
        set_machine_os_image($(this).parent().parent(), "single", "click", undefined, 1, "click");
207
    });
208

209
$("div.connect-arrow, .single-image").live('mousedown',
210
    function() {
211
        if ($(this).parent().find(".connect-arrow:visible").length == 0) { return };
212
        set_machine_os_image($(this).parent().parent(), "single", "click", undefined, 1);
213
    });
214

215
$("div.connect-arrow, .single-image").live('mouseup',
216
    function() {
217
        if ($(this).parent().find(".connect-arrow:visible").length == 0) { return };
218
        set_machine_os_image($(this).parent().parent(), "single", "click", undefined, 1, "click");
219
    });
220

221
//toggle the component with class tags-content
222
$("#machinesview-single.single div.tags-header").live('click', function() {
223
    if ($(this).find('.toggler').hasClass('up')) {
224
        $(this).find('.toggler').removeClass('up');
225
        $(this).find('.toggler').addClass('down');
226
        $(this).find('.tags-label').removeClass('darker');
227
        $(this).parent().parent().removeClass('light-background');
228
    } else {
229
        $(this).find('.toggler').removeClass('down');
230
        $(this).find('.toggler').addClass('up');
231
        $(this).find('.tags-label').addClass('darker');
232
        $(this).parent().parent().addClass('light-background');
233
    }
234
    $(this).parent().parent().find(".tags-content").slideToggle(600);
235
    return false;
236
});
237

238
// indicate that the requested action was not completed
239
function display_failure(status, serverID, action, responseText) {
240
    $('#machinesview-single.single #'+serverID+ ' .spinner').hide();
241
    $('#machinesview-single.single #'+serverID+ ' .action_error .action').text(action);
242
    $('#machinesview-single.single #'+serverID+ ' .action_error .code').text(status);
243
    $('#machinesview-single.single #'+serverID+ ' .action_error .message').text(responseText);
244
    $('#machinesview-single.single #'+serverID+ ' .action_error').show();
245
}
246

247
// cancel action
248
$("#machinesview-single.single div.confirm_single .no").live('click', function(){
249
    pending_actions = [];
250
    $('#machinesview-single').find('div.single-action').removeClass("selected");
251
    update_confirmations();
252
});
253

254
// update metadata list
255
function list_metadata_keys(serverID, keys) {
256
    // empty the list if it already exists
257
    $("#machinesview-single.single div.#" +serverID).find("div.items").empty();
258
    //start counter
259
    var i=0;
260
    // show values
261
    for (var key in keys) {
262
        $("#machinesview-single.single div.#" +serverID).find(".items").append("<div class='item'>" + key + ": " + keys[key].substring(0,40) + "</div>");
263
        i++;
264
    }
265
    //hide the metadata controls if we have less than 3 metadata
266
    if (i <= 3) {
267
        $("#machinesview-single.single div.#" +serverID).find(".metadata-actions").hide();
268
    }
269
    //show the metadata controls if we have more than 3 metadata
270
    if (i > 3) {
271
        $("#machinesview-single.single div.#" +serverID).find(".metadata-actions").show();
272
    }
273
    $("#machinesview-single.single div.#" +serverID).find(".metadata-count").text(i);
274
}
275

276
//show error popup box
277
$("#machinesview-single.single div.action_error .details").live('click', function(){
278
    // remove the action from the pending list
279
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
280
    $(this).parent().hide();
281
});
282

283
//confirm action
284
$("#machinesview-single.single div.confirm_single .yes").live('click', function(){
285
    var serverID = $(this).closest(".single-container").attr("id");
286
    for (i=0;i<pending_actions.length;i++){ // if there is a pending action for this server execute it
287
        if (pending_actions[i][1]==serverID){
288
            action = pending_actions.splice(i,1)[0]; // extract action
289
            // change the status text in cases where no api state exists
290
            if (action[0] == start) {
291
                $(this).closest(".single-container").find(".column1 .state-label").text(TRANSITIONS['Starting']);
292
                $(this).closest(".single-container").find(".column1 .state").removeClass().addClass('state starting-state');
293
                $(this).closest(".single-container").find(".column1 .state .spinner").show();
294
            } else if (action[0] == shutdown) {
295
                $(this).closest(".single-container").find(".column1 .state-label").text(TRANSITIONS['Shutting down']);
296
                $(this).closest(".single-container").find(".column1 .state").removeClass().addClass('state shutting-state');
297
                $(this).closest(".single-container").find(".column1 .state .spinner").show();
298
            } else if (action[0] == reboot) {
299
                $(this).closest(".single-container").find(".column1 .state-label").text(TRANSITIONS['Rebooting']);
300
                $(this).closest(".single-container").find(".column1 .state").removeClass().addClass('state rebooting-state');
301
                $(this).closest(".single-container").find(".column1 .state .spinner").show();
302
            }  else if (action[0] == destroy) {
303
                $(this).closest(".single-container").find(".column1 .state-label").text(TRANSITIONS['Destroying']);
304
                $(this).closest(".single-container").find(".column1 .state").removeClass().addClass('state destroying-state');
305
                $(this).closest(".single-container").find(".column1 .state .spinner").show();
306
            }
307
            action[0]([action[1]]); // execute action
308
        }
309
    }
310
    $(this).parent().hide();
311
    $(this).closest('div.action-container').children('div.single-action').removeClass('selected');
312
    $(this).parent().parent().find('.state').children('.spinner').show();
313
    update_confirmations();
314
    return false;
315
});
316

317
// intercept manage metadata click
318
$("#machinesview-single.single a.manage-metadata").live('click', function() {
319
    // get server name and server ID
320
    var serverID = $(this).parent().parent().parent().parent().parent().attr("id");
321
    var serverName = $(this).closest('.machine-container').find("div.machine-details div.name").text();
322
    if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf($(this).parent().parent().parent().parent().parent().find(".status").text()) < 0) {
323
        $("#metadata-wizard div#on-off").text('on');
324
    } else {
325
        $("#metadata-wizard div#on-off").text('off');
326
    }
327
    // set server name to all related metadata dialogs
328
    $("#metadata-wizard div.machine-name").text(serverName);
329
    // set server id to all related metadata dialogs
330
    $("#metadata-wizard p").text(serverID);
331
    show_metadata_wizard();
332
    return false;
333
});
334

335
// intercept start click
336
$("#machinesview-single.single div.action-start").live('click', function(){
337
    var serverID = $(this).closest(".single-container").attr("id");
338
    var serverName = $(this).closest("div.upper").find(".machine-details div.name").text();
339
    $('#machinesview-single').find('div.single-action').removeClass('selected');
340
    $(this).addClass('selected');
341
    $(this).parent().parent().find('.action_error').hide();
342
    // reset pending actions so not to allow multiple actions in this view
343
    pending_actions = [];
344
    pending_actions.push([start, serverID, serverName]);
345
    update_confirmations();
346
    return false;
347
});
348

349
// intercept shutdown click
350
$("#machinesview-single.single div.action-shutdown").live('click', function(){
351
    var serverID = $(this).closest(".single-container").attr("id");
352
    var serverName = $(this).closest("div.upper").find(".machine-details div.name").text();
353
    $('#machinesview-single').find('div.single-action').removeClass('selected');
354
    $(this).addClass('selected');
355
    $(this).parent().parent().find('.action_error').hide();
356
    // reset pending actions so not to allow multiple actions in this view
357
    pending_actions = [];
358
    pending_actions.push([shutdown, serverID, serverName]);
359
    update_confirmations();
360
    return false;
361
});
362

363
// intercept reboot click
364
$("#machinesview-single.single div.action-reboot").live('click', function(){
365
    var serverID = $(this).closest(".single-container").attr("id");
366
    var serverName = $(this).closest("div.upper").find(".machine-details div.name").text();
367
    $('#machinesview-single').find('div.single-action').removeClass('selected');
368
    $(this).addClass('selected');
369
    $(this).parent().parent().find('.action_error').hide();
370
    // reset pending actions so not to allow multiple actions in this view
371
    pending_actions = [];
372
    pending_actions.push([reboot, serverID, serverName]);
373
    update_confirmations();
374
    return false;
375
});
376

377
// intercept destroy click
378
$("#machinesview-single.single div.action-destroy").live('click', function(){
379
    var serverID = $(this).closest(".single-container").attr("id");
380
    var serverName = $(this).closest("div.upper").find(".machine-details div.name").text();
381
    $('#machinesview-single').find('div.single-action').removeClass('selected');
382
    $(this).addClass('selected');
383
    $(this).parent().parent().find('.action_error').hide();
384
    // reset pending actions so not to allow multiple actions in this view
385
    pending_actions = [];
386
    pending_actions.push([destroy, serverID, serverName]);
387
    update_confirmations();
388
    return false;
389
});
390

391
// intercept console click
392
$("#machinesview-single.single div.action-console").live('click', function(){
393
    var serverID = $(this).closest(".single-container").attr("id");
394
    var serverName = $(this).closest("div.upper").find(".machine-details div.name").text();
395
    $('#machinesview-single').find('div.single-action').removeClass('selected');
396
    $(this).addClass('selected');
397
    $(this).parent().parent().find('.action_error').hide();
398
    // reset pending actions so not to allow multiple actions in this view
399
    pending_actions = [];
400
    pending_actions.push([open_console, serverID, serverName]);
401
    update_confirmations();
402
    return false;
403
});
404

405
// connect to machine on machine logo click
406
$("#machinesview-single.single div.single-image").live('click', function(){
407
    var serverID = $(this).closest(".single-container").attr("id");
408
    machine_connect([machine_connect, serverID]);
409
    return false;
410
});
411

412
// connect to machine on connect arrow click
413
$("#machinesview-single.single div.connect-arrow").live('click', function(){
414
    var serverID = $(this).closest(".single-container").attr("id");
415
    machine_connect([machine_connect, serverID]);
416
    return false;
417
});
418

419
// connect to machine on connect arrow border click
420
$("#machinesview-single.single div.connect-border").live('click', function(){
421
    var serverID = $(this).closest(".single-container").attr("id");
422
    machine_connect([machine_connect, serverID]);
423
    return false;
424
});
425

426
// update the servers list
427
function update_machines_view(data){
428
    /*
429
    Go through the servers in the input data. Update existing entries, add
430
    new ones to the list
431
    */
432

433
    $.each(data.servers.values, function(i,server){
434

435
        existing = $('#machinesview-single.single #' + server.id);
436
        existing_link = $('#machinesview-single div.column3 #link-' + server.id);
437
        var current_Id = current_serverId();
438

439
        // if multiple machines exist in the DOM, delete all but one
440
        // defensive coding - that shouldn't happen normally
441
        while (existing.length > 1){
442
            existing.remove();
443
        }
444
        // get server OS, if it exists
445
        if (!(server.metadata == undefined)) {
446
            var server_image = os_icon(server.metadata);
447
        } else {
448
            var server_image = "unknown"
449
        }
450
        // get server status message, if it exists
451
        var current_message = existing.find(".state-label").text();
452

453
        // server already exists in DOM
454
        if (existing.length){
455
            $("#machinesview-single.single div.single-container:last-child").find("div.separator").show();
456
            //  if the status is deleted, delete it from the DOM
457
            if (server.status == 'DELETED') {
458
                existing.remove();
459
                existing_link.remove();
460
                //if the deleted vm is the displayed one, display the 1st vm
461
                if (server.id == current_Id) {
462
                    $("#machinesview-single.single div.single-container:eq(1)").show()
463
                    $('#machinesview-single.single .column3').find('.server-name:eq(1)').addClass('column3-selected');
464
                }
465
                try {
466
                    console.info(existing.find(".machine-details div.name").text() + ' removed');
467
                } catch(err) {}
468
            }
469
            // if the status has changed
470
            else if ( current_message != STATUSES[server.status]) {
471
                /*
472
                Here there are 4 possibilities:
473
                    1. From an active state to an inactive one
474
                    2. From an inactive state to an active one
475
                    3. From an active state to a different active one
476
                    4. From an inactive state to a different inactive one
477
                The last two (3, 4) can be dealt with the same way
478
                */
479
                if (ACTIVE_STATES.indexOf(current_message) >= 0 &&
480
                    INACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
481
                    // from an active state to an inactive one
482
                    log_server_status_change(existing, server.status);
483
                    set_machine_os_image(existing, "single", "off", server_image);
484
                    existing.find(".column1 .state-label").text(STATUSES[server.status]);
485
                    existing.find(".connect-border").hide();
486
                    existing.find(".connect-arrow").hide();
487
                    existing.find(".column1 .state .spinner").hide();
488
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
489
                    existing.find(".column1 .state").removeClass().addClass("state terminated-state");
490
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
491
                }
492
                else if (INACTIVE_STATES.indexOf(current_message) >= 0 &&
493
                         ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
494
                    // From an inactive state to an active one
495
                    log_server_status_change(existing, server.status);
496
                    set_machine_os_image(existing, "single", "on", server_image);
497
                    existing.find(".column1 .state-label").text(STATUSES[server.status]);
498
                    existing.find(".connect-border").show();
499
                    existing.find(".connect-arrow").show();
500
                    existing.find(".column1 .state .spinner").hide();
501
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
502
                    existing.find(".column1 .state").removeClass().addClass("state running-state");
503
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
504
                }
505
                else {
506
                    // handling active to active or inactive to inactive changes
507
                    if (TRANSITIONS[current_message] && TRANSITIONS[current_message] != 'Rebooting') {
508
                        // don't do anything if it is still in transition
509
                    }
510
                    else if ((TRANSITIONS[current_message] == 'Rebooting' && server.status == 'ACTIVE') ||
511
                             (STATUSES['BUILD'] == current_message && server.status == 'ACTIVE')) {
512
                        // if it has been rebooted or just created
513
                        log_server_status_change(existing, server.status);
514
                        existing.find(".column1 .state-label").text(STATUSES[server.status]);
515
                        existing.find(".connect-border").show();
516
                        existing.find(".connect-arrow").show();
517
                        existing.find(".column1 .state .spinner").hide();
518
                        existing.find(".column1 .state").attr('src','static/icons/indicators/medium/wave.gif').show();
519
                        existing.find(".column1 .state").removeClass().addClass("state running-state");
520
                        setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
521
                    }
522
                    else if (STATUSES[server.status] == "Rebooting") { 
523
                        // from running to rebooting
524
                        log_server_status_change(existing, server.status);
525
                        existing.find(".column1 .state").removeClass().addClass('state rebooting-state');
526
                        existing.find('.column1 .state .spinner').show();
527
                        existing.find(".column1 .state-label").text(STATUSES[server.status]);
528
                    } else {
529
                        // in any other case just change the status and ignore spinners/waves
530
                        existing.find(".column1 .state-label").text(STATUSES[server.status]);
531
                    }
532
                }
533
            }
534
            // find and display ips
535
            var ips = get_public_ips(server);
536
            existing.find(".machine-details div.ipv4").text(ips['ip4']);
537
            existing.find(".machine-details div.ipv6").text(ips['ip6']);
538

539
        } else if (server.status != 'DELETED') {
540
            // If it does not exist and it's not deleted, we should create it
541
            var serverwidget = $("#servers-widget-template").clone().attr("id", 'link-' + server.id);
542
            if (server.name.length > 18) {
543
                serverwidget.text(server.name.substring(0,15) + '...');
544
            } else {
545
                serverwidget.text(server.name)
546
            }
547
            serverwidget.appendTo('.servers');
548
            serverwidget.show();
549
            //find and hide the previously selected server
550
            $('.single').find('.single-container').hide();
551
            $('.single .column3').find('.column3-selected').removeClass('column3-selected');
552
            //create and select the new one
553
            var machine = $("#machinesview-single.single #machine-container-template").clone().attr("id", server.id);
554
            machine.find(".scrollable").scrollable({vertical: true});
555
            machine.find(".machine-details div.name").text(server.name.substring(0,30));
556
            set_machine_os_image(machine, "single", "on", server_image);
557
            machine.find("span.imagetag").text(server_image);
558
            machine.find(".column1 .state-label").text(STATUSES[server.status]);
559
            // find and display flavor parameters
560
            var flavor_params = get_flavor_params(server.flavorRef);
561
            machine.find(".machine-details div.cpus").text(flavor_params['cpus']);
562
            machine.find(".machine-details div.ram").text(flavor_params['ram']);
563
            machine.find(".machine-details div.disk").text(flavor_params['disk']);
564
            // find and display image parameters
565
            var image_params = get_image_params(server.imageRef);
566
            machine.find(".machine-details div.image-name").text(image_params['name'].substring(0,15));
567
            machine.find(".machine-details div.image-size").text(image_params['size']);
568
            // find and display ips
569
            var ips = get_public_ips(server);
570
            machine.find(".machine-details div.ipv4").text(ips['ip4']);
571
            machine.find(".machine-details div.ipv6").text(ips['ip6']);
572
            //show off image if server is not active
573
            if (['BUILD', 'ACTIVE', 'REBOOT'].indexOf(server.status) < 0){
574
                    set_machine_os_image(machine, "single", "off", server_image);
575
                    machine.find(".connect-border").hide();
576
                    machine.find(".connect-arrow").hide();
577
                    machine.find(".column1 .state").removeClass().addClass("state terminated-state");
578
            }
579
            //show spinner while machine is building or rebooting
580
            if (server.status == 'BUILD' ||
581
                [TRANSITIONS['Starting'], TRANSITIONS['Shutting down']].indexOf(existing.find(".status").text()) >= 0 ) {
582
                machine.find(".column1 .state .spinner").show();
583
                machine.find(".connect-border").hide();
584
                machine.find(".connect-arrow").hide();
585
                machine.find(".column1 .state").removeClass().addClass('state build-state');
586
            }
587
            if (server.status == 'REBOOT') {
588
                machine.find(".column1 .state").find('.spinner').show();
589
                machine.find(".connect-border").hide();
590
                machine.find(".connect-arrow").hide();
591
                machine.find(".column1 .state").removeClass().addClass('state rebooting-state');
592
            }
593
            machine.appendTo("#machinesview-single.single");
594
            //disable reboot and shutdown actions while machine is building
595
            if (server.status == 'BUILD') {
596
                $('#machinesview-single.single div.#' + server.id + ' div.action-reboot').hide();
597
                $('#machinesview-single.single div.#' + server.id + ' div.action-shutdown').hide();
598
            }
599
            // show console action only on active servers
600
            if (server.status == 'ACTIVE') {
601
                $('#machinesview-single.single div.#' + server.id + ' div.action-console').show();
602
                $('#machinesview-single.single div.#' + server.id + ' div.action-start').hide();
603
                machine.find(".connect-border").show();
604
                machine.find(".connect-arrow").show();
605
            } else if (server.status == 'REBOOT'){
606
                $('#machinesview-single.single div.#' + server.id + ' div.action-console').hide();
607
            } else {
608
                $('#machinesview-single.single div.#' + server.id + ' div.action-console').hide();
609
                $('#machinesview-single.single div.#' + server.id + ' div.action-reboot').hide();
610
                $('#machinesview-single.single div.#' + server.id + ' div.action-shutdown').hide();
611
            }
612
            //show the first machine and select it in the widget
613
            $('.single-container:eq(1)').show();
614
            $('.single .column3').find('.server-name:eq(1)').addClass('column3-selected');
615
        }
616
        update_iconview_actions(server.id, server.status);
617
        if (!(server.metadata == undefined)) {
618
                list_metadata_keys(server.id, server.metadata.values);
619
        }
620
        if (server.id == current_serverId()) {
621
            get_server_stats(server.id);
622
        }
623
    });
624

625
    // hide pane spinner
626
    $("#machinesview-single.single > div.large-spinner").hide();
627

628
    // show message in case user has no server!
629
    if ($('#machinesview-single div.single-container').length == 1) {
630
        showWelcome();
631
    } else {
632
        hideWelcome();
633
        $('.single .column3').show();
634
    }
635

636
    //enable widget links
637
    $(".server-name").live('click', function() {
638
        $('.single').find('.single-container').hide()
639
        $('.single').find('#' + $(this).attr('id').substring(5)).show();
640
        $('.single .column3').find('.column3-selected').removeClass('column3-selected');
641
        $(this).addClass('column3-selected');
642
        update_prev_next()
643
    });
644

645
    if ($.cookie('server')) {
646
        $('div#link-' + $.cookie('server')).click();
647
        $.cookie('server', null);
648
    }
649

650
    //if it is the last vm, disable the next button
651
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
652
        $("#machinesview-single.single .column3 .next").addClass('disabled');
653
    }
654

655
    //if it is the first vm, disable the prev button
656
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:eq(1)").attr("id")) {
657
        $("#machinesview-single.single .column3 .previous").addClass('disabled');
658
    }
659
}
660

661
//get currently displayed serverId
662
function current_serverId() {
663
    return $("#machinesview-single.single").find("div.single-container:visible").attr("id");
664
}
665

666
//enable prev-next buttons
667
$("#machinesview-single.single .column3 .previous").live('click', function() {
668
    // set behavior
669
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:eq(1)").attr("id")) {
670
        return false;
671
    } else {
672
        current_server = $('#machinesview-single.single .column3').find('.column3-selected').attr("id").substring(5);
673
        $('#machinesview-single.single').find('#' + current_server).hide();
674
        $('#machinesview-single.single').find('#' + current_server).prev().show();
675
        $('#machinesview-single.single .column3').find('#link-' + current_server).removeClass('column3-selected');
676
        $('#machinesview-single.single .column3').find('#link-' + current_server).prev().addClass('column3-selected');
677
        update_prev_next()
678
        return false;
679
    }
680
});
681

682
$("#machinesview-single.single .column3 .next").live('click', function() {
683
    // set behavior
684
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
685
        return false;
686
        } else {
687
        current_server = $('#machinesview-single.single .column3').find('.column3-selected').attr("id").substring(5);
688
        $('#machinesview-single.single').find('#' + current_server).hide();
689
        $('#machinesview-single.single').find('#' + current_server).next().show();
690
        $('#machinesview-single.single .column3').find('#link-' + current_server).removeClass('column3-selected');
691
        $('#machinesview-single.single .column3').find('#link-' + current_server).next().addClass('column3-selected');
692
        update_prev_next()
693
        return false;
694
    }
695
});
696

697

698
//enables-disables previous/next buttons accordingly
699
function update_prev_next() {
700
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") != $("#machinesview-single.single .column3 .server-name:eq(1)").attr("id")) {
701
        $(".single .column3 .previous").removeClass('disabled');
702
    } else {
703
        //disable class
704
        $(".single .column3 .previous").addClass('disabled');
705
    }
706
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") != $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
707
        $(".single .column3 .next").removeClass('disabled');
708
    } else {
709
        //disable class
710
        $(".single .column3 .next").addClass('disabled');
711
    }
712
    get_server_stats(current_serverId());
713
}
714

715
// basic functions executed on page load
716
if ( flavors.length == 0 && images.length == 0 ) {
717
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
718
    update_flavors();
719
    // populate image list
720
    update_images();
721
} else if ( flavors.length == 0 && images.length != 0 ) {
722
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
723
    update_flavors();
724
} else if ( flavors.length != 0 && images.length == 0 ) {
725
    // populate image list
726
    update_images();
727
    update_vms(UPDATE_INTERVAL);
728
} else {
729
    // start updating vm list
730
    update_vms(UPDATE_INTERVAL);
731
}
732

733
//IE specific fixes
734
if ($.browser.msie) {
735
    //IE fix for green arrow hover
736
    $("div.connect-arrow").live("mouseenter", function () {
737
        $(this).addClass("connect-arrow-ie");
738
    });
739
    $("div.connect-arrow").live("mouseleave", function () {
740
        $(this).removeClass("connect-arrow-ie");
741
    });
742
    //IE fix for details button
743
    $("button.details").live("mouseenter", function () {
744
        $(this).css("background-color","#FF7F2A");
745
    });
746
    $("button.details").live("mouseleave", function () {
747
        $(this).css("background-color","transparent");
748
    });
749
}
750

    
751
</script>