Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines_icon.html @ a4d2780c

History | View | Annotate | Download (39.1 kB)

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

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

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

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

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

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

    
36
{% load i18n %}
37

    
38
<!-- the standard view -->
39
<div id="machinesview-icon" class="standard">
40
    <div class="machine-container" id="machine-container-template" style="display:none">
41
        <div class="machine" id="machine-template">
42
            <div class='connect-border' title='{% trans 'Connect  machine' %}'></div>
43
            <div class='connect-arrow' title='{% trans 'Connect  machine' %}'></div>
44
            <div class="logo"></div>
45
            <div class="machine-details">
46
                <div href="#" class="name">
47
                    <h5 class="namecontainer editable">
48
                        <span class="name">node.name</span><span class="rename"></span>
49
                        <div class="editbuttons" style="display:none">
50
                            <div class="save"></div>
51
                            <div class="cancel"></div>
52
                        </div>
53
                    </h5>
54
                </div>
55
                <a href="#" class="ip">
56
                    <h5>{% trans "IP" %}: <span class="public">node.public_ip</span></h5>
57
                </a>
58
            </div>
59
            <div class="info">
60
                <div class="info-header">
61
                    <div class="info-label">{% trans "info" %}</div>
62
                    <div class="toggler down"></div>
63
                </div>
64
            </div>
65
            <div class="info-content">
66
                <div class="metadata-container">
67
                    <div class="vm-details metadata-column">
68
                        {% trans "CPUs" %}: <span class="cpu-data">1</span><br />
69
                        {% trans "RAM" %}: <span class="ram-data">2048</span> (MB)<br />
70
                        {% trans "System Disk" %}: <span class="disk-data">20</span> (GB) <br /><br />
71
                        {% trans "Image" %}: <span class="image-data">Debian</span><br />
72
                        {% trans "Image Size" %}: <span class="image-size-data">2.3</span> (GB)
73
                    </div>
74
                    <div class="vm-stats metadata-column">
75
                        <div class='stat-label'>{% trans "CPU" %}</div>
76
                        <div class='stat-content'>
77
                            <img src="./static/icons/indicators/small/progress.gif" class="cpu busy" />
78
                            <div class='stat-error'>{% trans "Could not fetch CPU stats." %}</div>
79
                        </div>
80
                        <div class='stat-label'>{% trans "Net" %}</div>
81
                        <div class='stat-content'>
82
                            <img src="./static/icons/indicators/small/progress.gif" class="net busy" />
83
                            <div class='stat-error'>{% trans "Could not fetch Net stats." %}</div>
84
                        </div>
85
                        <a href="#" class="stats-report">{% trans "Full report" %}</a>
86
                    </div>
87
                    <div class="vm-metadata metadata-column">
88
                        <div class="metadata-left">
89
                            {% trans "Tags" %}: <br />
90
                            (<span class="metadata-count">0</span>)
91
                        </div>
92
                        <div class="metadata-keys-container">
93
                            <div class="scrollable vertical">
94
                                <div class="items">
95
                                </div>
96
                            </div>
97
                            <div class="metadata-actions">
98
                                <div class="prev"></div>
99
                                <div class="next"></div>
100
                            </div>
101
                        </div>
102
                        <a href="#" class="manage-metadata">{% trans "Manage Tags" %}</a>
103
                    </div>
104
                </div>
105
            </div>
106
            <div class="state">
107
                <div class="status">{% trans "Running" %}</div>
108
                <div class="indicators">
109
                    <div class="indicator1"></div>
110
                    <div class="indicator2"></div>
111
                    <div class="indicator3"></div>
112
                    <div class="indicator4"></div>
113
                </div>
114
                <div class="action-indicator" style="display:none"></div>
115
                <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
116
                <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
117
            </div>
118
            <div class="actions clearfix">
119
                <div class="action-container start">
120
                    <a href="#" class="action-start">{% trans "Start" %}</a>
121
                    <div class="confirm_single">
122
                        <button class="yes">{% trans "Confirm" %}</button>
123
                        <button class="no">X</button>
124
                    </div>
125
                </div>
126
                <div class="action-container reboot">
127
                    <a href="#" class="action-reboot">{% trans "Reboot" %}</a>
128
                    <div class="confirm_single">
129
                        <button class="yes">{% trans "Confirm" %}</button>
130
                        <button class="no">X</button>
131
                    </div>
132
                </div>
133
                <div class="action-container shutdown">
134
                    <a href="#" class="action-shutdown">{% trans "Shutdown" %}</a>
135
                    <div class="confirm_single">
136
                        <button class="yes">{% trans "Confirm" %}</button>
137
                        <button class="no">X</button>
138
                    </div>
139
                </div>
140
                <div class="action-container console">
141
                    <a href="#" class="action-console">{% trans "Console" %}</a>
142
                    <div class="confirm_single">
143
                        <button class="yes">{% trans "Confirm" %}</button>
144
                        <button class="no">X</button>
145
                    </div>
146
                </div>
147
                <div class="action-container destroy">
148
                    <a href="#" class="action-destroy">{% trans "Destroy" %}</a>
149
                    <div class="confirm_single">
150
                        <button class="yes">{% trans "Confirm" %}</button>
151
                        <button class="no">X</button>
152
                    </div>
153
                </div>
154
            </div>
155
            <div class="action_error" align="center">
156
                {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
157
                <span class="code"></span>
158
                <span class="message"></span>
159
                <button class="details">{% trans "Details" %}</button>
160
            </div>
161
        </div>
162
        <div class="separator"></div>
163
    </div><div class="large-spinner"></div>
164
    <div class="running disabled"></div>
165
    <div class="terminated" style="display:none;"></div>
166
</div>
167

    
168
<script>
169
CONFIRMBOX_OFFSET = 200;
170

171
init_action_indicator_handlers('icon');
172

173
// handle connect machine image states
174
$("div.connect-arrow, div.running .machine .logo").live('mouseover',
175
    function() {
176
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
177
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1);
178
        var parent = $(this).parent().parent();
179
        parent.find(".connect-arrow").show().addClass('border-hover');
180
    });
181

182
$("div.connect-arrow, div.running .machine .logo").live('mouseleave',
183
    function() {
184
        if ($(this).parent().parent().find('.status').text() != STATUSES['ACTIVE']) { return };
185
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "hover");
186
        // mouseup outside the element is not fired
187
        set_machine_os_image($(this).parent().parent(), "icon", "hover", undefined, 1, "click");
188
        var parent = $(this).parent().parent();
189
        parent.find(".connect-arrow").show().removeClass('border-hover');
190
    });
191

192
$("div.connect-arrow, div.running .machine .logo").live('mousedown',
193
function() {
194
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
195
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1);
196
    });
197

198
$("div.connect-arrow, div.running .machine .logo").live('mouseup',
199
    function() {
200
        if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
201
        set_machine_os_image($(this).parent().parent(), "icon", "click", undefined, 1, "click");
202
    });
203

204
// actions on machine mouseover
205
$("#machinesview-icon.standard .machine").live('mouseover', function() {
206
    // show connect button only if the machine is active
207
    if ($(this).find('.status').text() == STATUSES['ACTIVE']) {
208
        $(this).find("div.connect-arrow").show();
209
        $(this).find("div.connect-border").show();
210
    }
211
});
212

213
// actions on machine mouseout
214
$("#machinesview-icon.standard .machine").live('mouseout', function() {
215
    // hide connect button
216
    $(this).find("div.connect-arrow").hide();
217
    $(this).find("div.connect-border").hide();
218
});
219

220
// actions on connect arrow border mouseover
221
$("#machinesview-icon.standard .running div.connect-border").live('mouseover', function() {
222
    $(this).next().addClass('border-hover');
223
});
224

225
// actions on connect arrow border mouseout
226
$("#machinesview-icon.standard .running div.connect-border").live('mouseout', function() {
227
    $(this).next().removeClass('border-hover');
228
});
229

230
// open console on machine logo click
231
$("#machinesview-icon.standard .running div.logo").live('click', function(){
232
    if ($(this).parent().parent().find(".connect-arrow:visible").length == 0) { return };
233
    var serverID = $(this).parent().parent().attr("id");
234
    machine_connect([machine_connect, serverID]);
235
    return false;
236
});
237

238
$("#machinesview-icon.standard .running div.connect-arrow").live('click', function(){
239
    var serverID = $(this).parent().parent().attr("id");
240
    machine_connect([machine_connect, serverID]);
241
    return false;
242
});
243

244
// open console on connect arrow border click
245
$("#machinesview-icon.standard .running div.connect-border").live('click', function(){
246
    var serverID = $(this).parent().parent().attr("id");
247
    machine_connect([machine_connect, serverID]);
248
    return false;
249
});
250

251
//hide the all of the info contents
252
$("#machinesview-icon.standard .info-content").hide();
253
//toggle the component with class info-content
254
$("#machinesview-icon.standard div.info-header").live('click', function() {
255
    if ($(this).find('.toggler').hasClass('up')) {
256
        // toggle drop-down pane
257
        $(this).find('.toggler').removeClass('up');
258
        $(this).find('.toggler').addClass('down');
259
        $(this).find('.info-label').removeClass('darker');
260
        $(this).parent().parent().removeClass('light-background');
261
    } else {
262
        // reset stats
263
        $(this).closest('.machine-container').find('.vm-stats div.stat-error').hide();
264
        $(this).closest('.machine-container').find('.vm-stats img.cpu').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
265
        $(this).closest('.machine-container').find('.vm-stats img.net').attr('src', './static/icons/indicators/small/progress.gif').addClass('busy').show();
266
        // get new stats
267
        var serverID = $(this).closest('.machine-container').attr('id');
268
        get_server_stats(serverID);
269
        // toggle drop-down pane
270
        $(this).find('.toggler').removeClass('down');
271
        $(this).find('.toggler').addClass('up');
272
        $(this).find('.info-label').addClass('darker');
273
        $(this).parent().parent().addClass('light-background');
274
    }
275
    $(this).parent().parent().find(".info-content").slideToggle(600);
276
    return false;
277
});
278

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

297
//initiate machine renaming
298
$("#machinesview-icon.standard .rename, #machinesview-icon.standard h5.editable span.name").live('click', function() {
299
    $(this).parent().find('.name').html("<input type=\"text\" class=\"nametextbox\" value=\"" +
300
                                        $(this).parent().find('.name').text() +
301
                                        "\" / ><span class=\"oldValue\">" +
302
                                        $(this).parent().find('.name').text() + "</span>");
303
    $(this).parent().find('.rename').hide();
304
    $(this).parent().find(".editbuttons").fadeIn();
305
    $(this).parent().find(".nametextbox").focus().select();
306
    $(this).parent().removeClass('editable');
307

308
    //submit wizard by pressing enter on the name textbox
309
    $(".nametextbox").keydown(function (e) {
310
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
311
            $(this).parent().parent().find('div.editbuttons div.save').click();
312
            return false;
313
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
314
            $(this).parent().parent().find('div.editbuttons div.cancel').click();
315
            return true;
316
        }
317
    });
318
    return false;
319
});
320

321
//rename machine
322
$("#machinesview-icon.standard .editbuttons .save").live('click', function() {
323
    serverID = $(this).closest('.machine-container').attr("id");
324
    serverName = $(this).parent().parent().find('.name').find('.nametextbox').val();
325
    if (serverName.trim() == ''){
326
        return false;
327
    }
328
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
329
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
330
    $(this).parent().parent().find(".rename").fadeIn("slow");
331
    $(this).parent().parent().addClass('editable');
332
    rename(serverID, serverName);
333
    return false;
334
});
335

336
//cancel renaming
337
$("#machinesview-icon.standard .editbuttons .cancel").live('click', function() {
338
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
339
    $(this).parent().parent().find(".editbuttons").hide();
340
    $(this).parent().parent().find(".rename").fadeIn();
341
    $(this).parent().parent().addClass('editable');
342
    return false;
343
});
344

345
// intercept reboot click
346
$("#machinesview-icon.standard div.actions a.action-reboot").live('click', function() {
347
    // get server id and server name from DOM
348
    var serverID = $(this).closest("div.machine-container").attr("id");
349
    var serverName = $(this).closest("div.machine").find("div.name span.name").text();
350
    var found = false;
351
    // show/hide proper menus
352
    $(this).parent().parent().find('a').removeClass('selected');
353
    $(this).addClass('selected');
354
    $(this).parent().parent().addClass('display');
355
    $(this).closest("div.machine").find('.action_error').hide();
356
    // if there is already a pending action for this server replace it
357
    for (i=0; i<pending_actions.length; i++) {
358
        if (pending_actions[i][1] == serverID) {
359
            pending_actions[i][0] = reboot;
360
            found = true
361
        }
362
    }
363
    // no pending action for this server was found, so let's just add it to the list
364
    if (!found)
365
        pending_actions.push([reboot, serverID, serverName])
366
    // pass the proper action to update confirmation boxes
367
    update_confirmations();
368
    return false;
369
});
370

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

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

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

446

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

472
$("#machinesview-icon.standard div.confirm_single button.yes").live('click', function(){
473
    var serverID = $(this).closest("div.machine-container").attr("id");
474
    // if there is a pending action for this server execute it
475
    for (i=0; i<pending_actions.length; i++) {
476
        if (pending_actions[i][1]==serverID){
477
            action = pending_actions.splice(i,1)[0]; // extract action
478
            // change the status text in cases where no api state exists
479
            if (action[0] == start) {
480
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Starting']);
481
                $(this).closest("div.machine").find('.state').removeClass().addClass('state starting-state');
482
                $(this).closest("div.machine").find('.spinner').show();
483
            } else if (action[0] == shutdown) {
484
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Shutting down']);
485
                $(this).closest("div.machine").find('.state').removeClass().addClass('state shutting-state');
486
                $(this).closest("div.machine").find('.spinner').show();
487
            } else if (action[0] == reboot) {
488
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Rebooting']);
489
                $(this).closest("div.machine").find('.state').removeClass().addClass('state rebooting-state');
490
                $(this).closest("div.machine").find('.spinner').show();
491
            }  else if (action[0] == destroy) {
492
                $(this).closest("div.machine").find('.status').text(TRANSITIONS['Destroying']);
493
                $(this).closest("div.machine").find('.state').removeClass().addClass('state destroying-state');
494
                $(this).closest("div.machine").find('.spinner').show();
495
            }
496
            action[0]([action[1]]); // execute action
497
        }
498
    }
499
    $(this).parent().hide();
500
    $(this).closest('div.actions').find('a').removeClass('selected');
501
    $(this).closest("div.machine").children('.state').children('.spinner').show()
502
    $(this).closest("div.machine").children('div.actions').removeClass('display');
503
    update_confirmations();
504
    return false;
505
});
506

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

511
    $(this).closest('div.action-container').children('a').removeClass('selected');
512
    $(this).closest('div.actions').removeClass('display');
513
    for (i=0; i<pending_actions.length; i++) { // if there is a pending action for this server remove it
514
        if (pending_actions[i][1] == serverID) {
515
            pending_actions.splice(i,1);
516
        }
517
    }
518
    $(this).parent().hide();
519
    update_confirmations();
520
    return false;
521
});
522

523
$("#machinesview-icon.standard div.action_error .details").live('click', function(){
524
    // remove the action from the pending list
525
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
526
    $(this).parent().hide();
527
});
528

529
// update the servers list
530
function update_machines_view(data) {
531
    /*
532
    Go through the servers in the input data. Update existing entries, add
533
    new ones to the list
534
    */
535
    $.each(data.servers.values, function(i,server) {
536

537
        // get DOM element, if it exists
538
        existing = $('#machinesview-icon.standard #' + server.id);
539
        // get server OS, if it exists
540
        if (!(server.metadata == undefined)) {
541
            var server_image = os_icon(server.metadata);
542
        } else {
543
            var server_image = "unknown"
544
        }
545
        // get server status message, if it exists
546
        var current_message = existing.find(".status").text();
547
        // if multiple machines exist in the DOM, delete all but one
548
        // defensive coding - that shouldn't happen normally
549
        while (existing.length > 1){
550
            existing.remove();
551
        }
552
        // if server already exists in DOM, update its values
553
        if (existing.length){
554
            //  if the status is deleted
555
            if (server.status == 'DELETED') {
556
                // delete server entry from the DOM
557
                log_server_status_change(existing, 'DELETED');
558
                existing.remove();
559
            }
560
            // if the status has changed
561
            else if ( current_message != STATUSES[server.status]) {
562
                /*
563
                Here there are 4 possibilities:
564
                    1. From an active state to an inactive one
565
                    2. From an inactive state to an active one
566
                    3. From an active state to a different active one
567
                    4. From an inactive state to a different inactive one
568
                The last two (3, 4) can be dealt with the same way
569
                */
570
                if (ACTIVE_STATES.indexOf(current_message) >= 0 &&
571
                    INACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
572
                    // from an active state to an inactive one
573
                    log_server_status_change(existing, server.status);
574
                    moved = existing.clone().appendTo("#machinesview-icon.standard .terminated");
575
                    set_machine_os_image(moved, "icon", "off", server_image);
576
                    existing.remove();
577
                    existing = moved;
578
                    existing.find(".status").text(STATUSES[server.status]);
579
                    existing.find('.spinner').hide();
580
                    if ($("div.terminated").find("div.machine-container").length > 0) {
581
                        $("div.terminated").show();
582
                    }
583
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
584
                    existing.find('.state').removeClass().addClass('state terminated-state');
585
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
586
                }
587
                else if (INACTIVE_STATES.indexOf(current_message) >= 0 &&
588
                         ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0) {
589
                    // From an inactive state to an active one
590
                    log_server_status_change(existing, server.status);
591
                    moved = existing.clone().appendTo("#machinesview-icon.standard .running");
592
                    set_machine_os_image(moved, "icon", "on", server_image);
593
                    existing.remove();
594
                    existing = moved;
595
                    existing.find(".status").text(STATUSES[server.status]);
596
                    existing.find('.spinner').hide();
597
                    if ($("div.terminated").find("div.machine-container").length == 0) {
598
                        $("div.terminated").hide();
599
                    }
600
                    existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
601
                    existing.find('.state').removeClass().addClass('state running-state');
602
                    setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
603
                }
604
                else {
605
                    // handling active to active or inactive to inactive changes
606
                    if (TRANSITIONS[current_message] && TRANSITIONS[current_message] != 'Rebooting') {
607
                        // don't do anything if it is still in transition
608
                    }
609
                    else if ((TRANSITIONS[current_message] == 'Rebooting' && server.status == 'ACTIVE') ||
610
                             (STATUSES['BUILD'] == current_message && server.status == 'ACTIVE')) {
611
                        // if it has been rebooted or just created
612
                        log_server_status_change(existing, server.status);
613
                        existing.find(".status").text(STATUSES[server.status]);
614
                        existing.find('.spinner').hide();
615
                        existing.find(' .wave').attr('src','static/icons/indicators/medium/wave.gif').show();
616
                        existing.find('.state').removeClass().addClass('state running-state');
617
                        setTimeout("$('#" + server.id +" .wave').attr('src','').hide()", 3000);
618
                    }
619
                    else if (STATUSES[server.status] == "Rebooting") { 
620
                        // from running to rebooting
621
                        log_server_status_change(existing, server.status);
622
                        existing.find(".state").removeClass().addClass('state rebooting-state');
623
                        existing.find('.spinner').show();
624
                        existing.find(".status").text(STATUSES[server.status]);
625
                    } else {
626
                        // in any other case just change the status and ignore spinners/waves
627
                        existing.find(".status").text(STATUSES[server.status]);
628
                        existing.appendTo("#machinesview-icon.standard .running");
629
                        existing.find('.state').removeClass().addClass('state running-state');
630
                    }
631
                }
632
            }
633
            // find and display ips
634
            var ips = get_public_ips(server);
635
            existing.find("a.ip span.public").text(ips['ip4']);
636
        }
637
        // if it doesn't exist and the server is not DELETED, make a new entry
638
        else if ( server.status != 'DELETED') {
639
            // clone the proper template and put basic values in
640
            var machine = $("#machinesview-icon.standard #machine-container-template").clone().attr("id", server.id).fadeIn("slow");
641
            machine.find(".scrollable").scrollable({vertical: true});
642
            machine.find("div.name span.name").text(server.name.substring(0,50));
643
            machine.find("span.imagetag").text(server_image);
644
            machine.find(".status").text(STATUSES[server.status]);
645
            // check server status to select where to append the new server to
646
            if (ACTIVE_STATES.indexOf(STATUSES[server.status]) >= 0 ) {
647
                // append to running
648
                set_machine_os_image(machine, "icon", "on", server_image);
649
                machine.appendTo("#machinesview-icon.standard .running");
650
            } else {
651
                // append to terminated
652
                set_machine_os_image(machine, "icon", "off", server_image);
653
                machine.appendTo("#machinesview-icon.standard .terminated");
654
                if (server.status == "STOPPED") { //if server status us stopped is a different case than status unknown/error
655
                    machine.find('.state').removeClass().addClass('state terminated-state');
656
                } else {
657
                       machine.find('.state').removeClass().addClass('state error-state');
658
                }
659
            }
660
            //show spinner if server is still building or rebooting
661
            if (server.status == 'BUILD') {
662
                machine.find('.spinner').show();
663
                machine.find('.state').removeClass().addClass('state build-state');
664
            }
665
            if (server.status == 'REBOOT') {
666
                machine.find('.spinner').show();
667
                machine.find('.state').removeClass().addClass('state rebooting-state');
668
            }
669
            // find and display flavor parameters
670
            var flavor_params = get_flavor_params(server.flavorRef);
671
            machine.find(".cpu-data").text(flavor_params['cpus']);
672
            machine.find(".ram-data").text(flavor_params['ram']);
673
            machine.find(".disk-data").text(flavor_params['disk']);
674
            // find and display image parameters
675
            var image_params = get_image_params(server.imageRef);
676
            machine.find(".image-data").text(image_params['name'].substring(0,15));
677
            machine.find(".image-size-data").text(image_params['size']);
678
            // find and display ips
679
            var ips = get_public_ips(server);
680
            machine.find("a.ip span.public").text(ips['ip4']);
681
        }
682
        /*
683
        Do some repeated actions that include:
684
            1. Update actions
685
            2. Metadata list updating
686
        */
687
        update_iconview_actions(server.id, server.status);
688
        if (!(server.metadata == undefined)) {
689
                list_metadata_keys(server.id, server.metadata.values);
690
        }
691

692
        // if machine in destroy state keep it that way
693
        var server = get_machine(server.id);
694
        if (server.status == "DESTROY") {
695
            existing = $('#machinesview-icon.standard #' + server.id);
696
            if (existing.length) {
697
                $(existing).find('.status').text(TRANSITIONS['Destroying']);
698
                $(existing).find('.state').removeClass().addClass('state destroying-state');
699
                $(existing).find('.spinner').show();
700
                $(existing).find('.wave').hide();
701
            }
702
        }
703

704

705
    });
706
    /*
707
    Do some standard stuff, repeated each time
708
    FIXME: Can these be moved to a new function?
709
    */
710
    $("div.large-spinner").hide();
711
    $("div.running").removeClass("disabled");
712
    // show all separators and hide the last one
713
    $("#machinesview-icon.standard div.machine-container div.separator").show();
714
    $("#machinesview-icon.standard div.machine-container:last-child").find("div.separator").hide();
715
    // the terminated div shows only when terminated machines are available
716
    if ($("#machinesview-icon.standard .terminated div.name").length > 0) {
717
        $("div.terminated").fadeIn("slow");
718
    } else {
719
        $("div.terminated").fadeOut("slow");
720
    }
721
    // show message in case user has no servers!
722
    if ($('#machinesview-icon .machine-container').length < 2) {
723
        showWelcome();
724
    } else {
725
        hideWelcome();
726
    }
727
    // set confirm box position
728
    if (window.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon.standard').height()) {
729
        $('.confirm_multiple').addClass('fixed');
730
    } else {
731
        $('.confirm_multiple').removeClass('fixed');
732
    }
733
}
734

735
// reposition multiple confirmation box on window resize
736
$(window).resize(function(){
737
    if (this.innerHeight - CONFIRMBOX_OFFSET < $('#machinesview-icon').height())
738
        $('.confirm_multiple').addClass('fixed');
739
    else
740
        $('.confirm_multiple').removeClass('fixed');
741
});
742

743
// update metadata list
744
function list_metadata_keys(serverID, keys) {
745
    // empty the list if it already exists
746
    $("#machinesview-icon.standard div.#" +serverID).find("div.items").empty();
747
    //start counter
748
    var i=0;
749
    // show values
750
    for (var key in keys) {
751
        $("#machinesview-icon.standard div.#" +serverID).find(".items").append("<div class='item'>" + key + "</div>");
752
        i++;
753
    }
754
    //hide the metadata controls if we have less than 3 metadata
755
    if (i <= 3) {
756
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").hide();
757
    }
758
    //show the metadata controls if we have more than 3 metadata
759
    if (i > 3) {
760
        $("#machinesview-icon.standard div.#" +serverID).find(".metadata-actions").show();
761
    }
762
    $("#machinesview-icon.standard div.#" +serverID).find(".metadata-count").text(i);
763
}
764

765
// indicate that the requested action was succesfully completed
766
function display_success(serverID) {
767

768
}
769

770
// indicate that the requested action was not completed
771
function display_failure(status, serverID, action, responseText) {
772
    $('#machinesview-icon.standard #'+serverID+ ' .spinner').hide();
773
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .action').text(action);
774
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .code').text(status);
775
    $('#machinesview-icon.standard #'+serverID+ ' .action_error .message').text(responseText);
776
    $('#machinesview-icon.standard #'+serverID+ ' .action_error').show();
777
}
778

779
// basic functions executed on page load
780
if ( flavors.length == 0 && images.length == 0 ) {
781
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
782
    update_flavors();
783
    // populate image list
784
    update_images();
785
} else if ( flavors.length == 0 && images.length != 0 ) {
786
    // configure flavors, this also calls update_vms(UPDATE_INTERVAL)
787
    update_flavors();
788
} else if ( flavors.length != 0 && images.length == 0 ) {
789
    // populate image list
790
    update_images();
791
    update_vms(UPDATE_INTERVAL);
792
} else {
793
    // start updating vm list
794
    update_vms(UPDATE_INTERVAL);
795
}
796

797
// set the label of the multiple buttons
798
$('.confirm_multiple button.yes').text('Confirm All');
799
$('.confirm_multiple button.no').text('Cancel All');
800

801
//IE specific fixes
802
if ($.browser.msie) {
803
    //IE fix for machine div hover
804
    $("div.machine").live("mouseenter", function () {
805
        $(this).css("background-color","#A1C8DB");
806
        $(this).find("div.info-header").css("background-color","#84b7d0");
807
        $(this).find("div.toggler div.down").css("background-color","#84b7d0");
808
        $(this).find(".actions a").css("visibility","visible");
809
    });
810
    $("div.machine").live("mouseleave", function () {
811
        $(this).css("background-color","transparent");
812
        $(this).find("div.info-header").css("background-color","#A1C8DB");
813
        $(this).find("div.toggler div.down").css("background-color","#A1C8DB");
814
        if ($(this).parent().find(".confirm_single:visible").length == 0) {
815
            $(this).find(".actions a").css("visibility","hidden");
816
        }
817
    });
818
    //IE fix for green arrow hover
819
    $("div.connect-arrow").live("mouseenter", function () {
820
        $(this).addClass("connect-arrow-ie");
821
    });
822
    $("div.connect-arrow").live("mouseleave", function () {
823
        $(this).removeClass("connect-arrow-ie");
824
    });
825
    //IE fix for details button
826
    $("button.details").live("mouseenter", function () {
827
        $(this).css("background-color","#FF7F2A");
828
    });
829
    $("button.details").live("mouseleave", function () {
830
        $(this).css("background-color","transparent");
831
    });
832
    //IE fix for multiple conf yes button
833
    $("div.confirm_multiple button.yes").live("mouseenter", function () {
834
        $(this).css("background-color","#FF7F2A");
835
    });
836
    $("div.confirm_multiple button.yes").live("mouseleave", function () {
837
        $(this).css("background-color","transparent");
838
    });
839
    //IE fix for multiple conf no button
840
    $("div.confirm_multiple button.no").live("mouseenter", function () {
841
        $(this).css("background-color","#5CA1C0");
842
    });
843
    $("div.confirm_multiple button.no").live("mouseleave", function () {
844
        $(this).css("background-color","transparent");
845
    });
846
}
847
</script>