Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_single.html @ cb748f1f

History | View | Annotate | Download (37.3 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
        var parent = $(this).parent().parent();
201
        parent.find(".connect-arrow").show().addClass('border-hover');
202
    });
203

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

409
// connect to machine on machine logo click
410
$("#machinesview-single.single div.single-image").live('click', function(){
411
    if ($(this).parent().find(".connect-arrow:visible").length == 0) { return };
412
    var serverID = $(this).closest(".single-container").attr("id");
413
    machine_connect([machine_connect, serverID]);
414
    return false;
415
});
416

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

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

431
// update the servers list
432
function update_machines_view(data){
433
    /*
434
    Go through the servers in the input data. Update existing entries, add
435
    new ones to the list
436
    */
437

438
    $.each(data.servers.values, function(i,server){
439

440
        existing = $('#machinesview-single.single #' + server.id);
441
        existing_link = $('#machinesview-single div.column3 #link-' + server.id);
442
        var current_Id = current_serverId();
443

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

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

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

618

619
            //show the first machine and select it in the widget
620
            $('.single-container:eq(1)').show();
621
            $('.single .column3').find('.server-name:eq(1)').addClass('column3-selected');
622
        }
623
        update_iconview_actions(server.id, server.status);
624
        if (!(server.metadata == undefined)) {
625
                list_metadata_keys(server.id, server.metadata.values);
626
        }
627
        if (server.id == current_serverId()) {
628
            get_server_stats(server.id);
629
        }
630

631
        // if machine in destroy state keep it that way
632
        var server = get_machine(server.id);
633
        if (server.status == "DESTROY") {
634
            existing = $('#machinesview-single.single #' + server.id);
635
            if (existing.length) {
636
                existing.find(".column1 .state-label").text(TRANSITIONS['Destroying']);
637
                existing.find(".column1 .state").removeClass().addClass('state destroying-state');
638
                existing.find(".column1 .state .spinner").show();
639
                existing.find(".column1 .wave").hide();
640
            }
641
        }
642
    });
643

644
    // hide pane spinner
645
    $("#machinesview-single.single > div.large-spinner").hide();
646

647
    // show message in case user has no server!
648
    if ($('#machinesview-single div.single-container').length == 1) {
649
        showWelcome();
650
    } else {
651
        hideWelcome();
652
        $('.single .column3').show();
653
    }
654

655
    //enable widget links
656
    $(".server-name").live('click', function() {
657
        $('.single').find('.single-container').hide()
658
        $('.single').find('#' + $(this).attr('id').substring(5)).show();
659
        $('.single .column3').find('.column3-selected').removeClass('column3-selected');
660
        $(this).addClass('column3-selected');
661
        update_prev_next()
662
    });
663

664
    if ($.cookie('server')) {
665
        $('div#link-' + $.cookie('server')).click();
666
        $.cookie('server', null);
667
    }
668

669
    //if it is the last vm, disable the next button
670
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
671
        $("#machinesview-single.single .column3 .next").addClass('disabled');
672
    }
673

674
    //if it is the first vm, disable the prev button
675
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:eq(1)").attr("id")) {
676
        $("#machinesview-single.single .column3 .previous").addClass('disabled');
677
    }
678
}
679

680
//get currently displayed serverId
681
function current_serverId() {
682
    return $("#machinesview-single.single").find("div.single-container:visible").attr("id");
683
}
684

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

701
$("#machinesview-single.single .column3 .next").live('click', function() {
702
    // set behavior
703
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") == $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
704
        return false;
705
        } else {
706
        current_server = $('#machinesview-single.single .column3').find('.column3-selected').attr("id").substring(5);
707
        $('#machinesview-single.single').find('#' + current_server).hide();
708
        $('#machinesview-single.single').find('#' + current_server).next().show();
709
        $('#machinesview-single.single .column3').find('#link-' + current_server).removeClass('column3-selected');
710
        $('#machinesview-single.single .column3').find('#link-' + current_server).next().addClass('column3-selected');
711
        update_prev_next()
712
        return false;
713
    }
714
});
715

716

717
//enables-disables previous/next buttons accordingly
718
function update_prev_next() {
719
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") != $("#machinesview-single.single .column3 .server-name:eq(1)").attr("id")) {
720
        $(".single .column3 .previous").removeClass('disabled');
721
    } else {
722
        //disable class
723
        $(".single .column3 .previous").addClass('disabled');
724
    }
725
    if ($("#machinesview-single.single .column3 .column3-selected").attr("id") != $("#machinesview-single.single .column3 .server-name:last").attr("id")) {
726
        $(".single .column3 .next").removeClass('disabled');
727
    } else {
728
        //disable class
729
        $(".single .column3 .next").addClass('disabled');
730
    }
731
    get_server_stats(current_serverId());
732
}
733

734
// basic functions executed on page load
735
if ( flavors.length == 0 && images.length == 0 ) {
736
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
737
    update_flavors();
738
    // populate image list
739
    update_images();
740
} else if ( flavors.length == 0 && images.length != 0 ) {
741
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
742
    update_flavors();
743
} else if ( flavors.length != 0 && images.length == 0 ) {
744
    // populate image list
745
    update_images();
746
    update_vms(UPDATE_INTERVAL);
747
} else {
748
    // start updating vm list
749
    update_vms(UPDATE_INTERVAL);
750
}
751

752
//IE specific fixes
753
if ($.browser.msie) {
754
    //IE fix for green arrow hover
755
    $("div.connect-arrow").live("mouseenter", function () {
756
        $(this).addClass("connect-arrow-ie");
757
    });
758
    $("div.connect-arrow").live("mouseleave", function () {
759
        $(this).removeClass("connect-arrow-ie");
760
    });
761
    //IE fix for details button
762
    $("button.details").live("mouseenter", function () {
763
        $(this).css("background-color","#FF7F2A");
764
    });
765
    $("button.details").live("mouseleave", function () {
766
        $(this).css("background-color","transparent");
767
    });
768
}
769

    
770
</script>