Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_single.html @ 2b837adf

History | View | Annotate | Download (36 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 {
523
                        // in any other case just change the status and ignore spinners/waves
524
                        existing.find(".column1 .state-label").text(STATUSES[server.status]);
525
                    }
526
                }
527
            }
528
            // find and display ips
529
            var ips = get_public_ips(server);
530
            existing.find(".machine-details div.ipv4").text(ips['ip4']);
531
            existing.find(".machine-details div.ipv6").text(ips['ip6']);
532

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

619
    // hide pane spinner
620
    $("#machinesview-single.single > div.large-spinner").hide();
621

622
    // show message in case user has no server!
623
    if ($('#machinesview-single div.single-container').length == 1) {
624
        showWelcome();
625
    } else {
626
        hideWelcome();
627
        $('.single .column3').show();
628
    }
629

630
    //enable widget links
631
    $(".server-name").live('click', function() {
632
        $('.single').find('.single-container').hide()
633
        $('.single').find('#' + $(this).attr('id').substring(5)).show();
634
        $('.single .column3').find('.column3-selected').removeClass('column3-selected');
635
        $(this).addClass('column3-selected');
636
        update_prev_next()
637
    });
638

639
    if ($.cookie('server')) {
640
        $('div#link-' + $.cookie('server')).click();
641
        $.cookie('server', null);
642
    }
643

644
    //if it is the last vm, disable the next button
645
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
646
        $("#machinesview-single.single .column3 .next").addClass('disabled');
647
    }
648

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

655
//get currently displayed serverId
656
function current_serverId() {
657
    return $("#machinesview-single.single").find("div.single-container:visible").attr("id");
658
}
659

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

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

691

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

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

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

    
745
</script>