Statistics
| Branch: | Tag: | Revision:

root / ui / templates / networks.html @ e7d39dd7

History | View | Annotate | Download (49.9 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 create button -->
39
<div id="networks-createcontainer">
40
    <div id="beforecreate"></div>
41
    <a id="networkscreate" rel="#networks-wizard" href="#">{% trans "Create New +" %}</a>
42
</div>
43

    
44
<!-- add new network overlay -->
45
<div>
46
    <div class="modal" id="networks-wizard">
47
        <div class="header">
48
        </div>
49
        <h2>{% trans "Name your network" %}</h2>
50
        <hr class="topruler" />
51
        <div class="container">
52
            <div class="name-input">
53
                <label>{% trans "Name" %}:</label>
54
                <input type="text" class="text" name="machine_name"></input>
55
                <span class="help">{% trans "(* Required field)" %}</span>
56
            </div>
57
        </div>
58
        <hr class="bottomruler" />
59
        <button type="button" id="add-network-cancel" class="cancel">{% trans "Cancel" %}</button>
60
        <button type="button" id="add-network-create" class="create">{% trans "Create Network" %}</button>
61
        <hr class="separator-end"></hr>
62
    </div>
63
</div>
64

    
65
<!-- networks list -->
66
<div id="networks-container">
67
    <!-- spinner while loading list -->
68
    <div class = "large-spinner"></div>
69

    
70
    <!-- public network template -->
71
    <div class="network" id="public-template">
72
        <img class="network-logos" src="static/internet.png" />
73
        <div href="#" class="name-div">
74
            <h5 class="namecontainer">
75
                <span class="name">{% trans "Internet" %}</span>
76
            </h5>
77
        </div>
78
        <div class="network-machines">
79
            <div class="machines-header">
80
                <div class="machines-label">{% trans "machines" %}
81
                    (<span class="machines-count">0</span>)
82
                </div>
83
                <div class="toggler down"></div>
84
            </div>
85
        </div>
86
        <div class="network-contents">
87
            <div class="network-placeholder">
88
                <div class="machines-list">
89
                <!-- append machines here -->
90
                </div>
91
                <!-- Adding servers to public network is not supported in 0.5
92
                <div class="empty-network-slot" id="machine-template">
93
                    <div class='network-add-machine'>
94
                        <span class="add-icon">+</span>
95
                    </div>
96
                </div>
97
                -->
98
            </div>
99
        </div>
100
        <div class="state">
101
            <div class="status">{% trans "Public Network" %}</div>
102
            <div class="indicators network-indicator">
103
                <div class="indicator1"></div>
104
                <div class="indicator2"></div>
105
                <div class="indicator3"></div>
106
                <div class="indicator4"></div>
107
            </div>
108
        </div>
109
        <div class="actions">
110
             <!-- Adding servers to public network is not supported in 0.5
111
            <a href="#" class="action-add">{% trans "Add Machine" %}</a>
112
            -->
113
        </div>
114
        <div class="confirm_single">
115
            <button class="yes">{% trans "Confirm" %}</button>
116
            <button class="no">{% trans "Cancel" %}</button>
117
        </div>
118
        <div class="action_error" align="center">
119
            {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
120
            <span class="code"></span>
121
            <span class="message"></span>
122
            <button class="details">{% trans "Details" %}</button>
123
        </div>
124
    </div>
125

    
126
    <!-- template for machines in public network -->
127
    <div class="network-machine" id="public-machine-template">
128
        <div class="network-cable"></div>
129
        <div class="machine-actions">
130
            <a href="#" class="action-details">{% trans "Details" %}</a>
131
        </div>
132
        <div class="confirm_single">
133
            <button class="yes">{% trans "Confirm" %}</button>
134
            <button class="no">{% trans "Cancel" %}</button>
135
        </div>
136
        <div class="action_error" align="center">
137
            {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
138
            <span class="code"></span>
139
            <span class="message"></span>
140
            <button class="details">{% trans "Details" %}</button>
141
        </div>
142
        <div class="ips">
143
            <div class="ip4-container status">
144
                {% trans "IPv4" %}:
145
                <span class="ip4">192.94.73.15</span>
146
            </div>
147
            <div class="ip6-container status">
148
                {% trans "IPv6" %}:
149
                <span class="ip6">vv</span>
150
            </div>
151
        </div>
152
        <img class="logo" src="static/icons/machines/medium/debian-on.png" />
153
        <div class='network-remove-machine'>
154
            <!-- Removing servers from public network is not supported in 0.5
155
            <span class="remove-icon">X</span>
156
            -->
157
            <span>&nbsp;</span>
158
        </div>
159
        <div href="#" class="machine-name-div">
160
            <h5 class="namecontainer">
161
                <span class="name">my desktop1</span>
162
            </h5>
163
        </div>
164
        <div class="firewall">
165
            <div class="firewall-header">
166
                <div class="firewall-label">{% trans "Firewall" %}
167
                    (<span class="firewall-off">{% trans "Off" %}</span>)
168
                </div>
169
                <div class="toggler down"></div>
170
            </div>
171
        </div>
172
        <div class="firewall-content">
173
            <div class="firewall-cable"></div>
174
            <input type="radio" class="checkboxes" value="DISABLED" name="firewall" />
175
            <span class="checkbox-legends">{% trans "Unprotected mode (Firewall off)" %}</span>
176
            <br />
177
            <input type="radio" class="checkboxes" value="ENABLED" name="firewall" />
178
            <span class="checkbox-legends">{% trans "Fully protected mode (Firewall on)" %}</span>
179
            <br />
180
            <input type="radio" class="checkboxes" value="PROTECTED" name="firewall" />
181
            <span class="checkbox-legends">{% trans "Basically protected mode (Firewall on)" %}</span>
182
            <button type="submit" class="firewall-apply">{% trans "Apply" %}</button>
183
        </div>
184
        <div class="network-separator machines"></div>
185
    </div>
186

    
187
    <div class="separator" style="display:none;"></div>
188

    
189
    <!-- private network template -->
190
    <div class="network" id="private-template">
191
        <div class="actions">
192
            <a href="#" class="action-add">{% trans "Add Machine" %}</a>
193
            <a href="#" class="action-network-destroy">{% trans "Destroy" %}</a>
194
        </div>
195
        <div class="action_error" align="center">
196
            {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
197
            <span class="code"></span>
198
            <span class="message"></span>
199
            <button class="details">{% trans "Details" %}</button>
200
        </div>
201
        <div class="confirm_single">
202
            <button class="yes">{% trans "Confirm" %}</button>
203
            <button class="no">X</button>
204
        </div>
205
        <div class="action_error" align="center">
206
            {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
207
            <span class="code"></span>
208
            <span class="message"></span>
209
            <button class="details">{% trans "Details" %}</button>
210
        </div>
211
        <div class="state">
212
            <div class="status">{% trans "Private Network" %}</div>
213
            <div class="indicators network-indicator">
214
                <div class="indicator1"></div>
215
                <div class="indicator2"></div>
216
                <div class="indicator3"></div>
217
                <div class="indicator4"></div>
218
            </div>
219
            <img class="spinner" style="display:none" src="static/icons/indicators/medium/progress.gif" />
220
            <img class="wave" style="display:none" src="static/icons/indicators/medium/wave.gif" />
221
        </div>
222
        <img class="network-logos" src="static/network.png" />
223
        <div href="#" class="name-div">
224
            <h5 class="namecontainer editable">
225
                <span class="name">{% trans "My Network 1" %}</span>
226
                <span class="rename-network"></span>
227
                <div class="editbuttons" style="display:none">
228
                    <span class="save"></span>
229
                    <span class="cancel"></span>
230
                </div>
231
            </h5>
232
        </div>
233
        <div class="network-machines">
234
            <div class="machines-header">
235
                <div class="machines-label">{% trans "machines" %}
236
                    (<span class="machines-count">0</span>)
237
                </div>
238
                <div class="toggler down"></div>
239
            </div>
240
        </div>
241
        <div class="network-contents">
242
            <div class="network-placeholder">
243
                <div class="machines-list">
244
                <!-- append machines here -->
245
                </div>
246
                <div class="empty-network-slot" id="machine-template">
247
                    <div class='network-add-machine'><div class="add-icon">+</div></div>
248
                </div>
249
            </div>
250
        </div>
251
    </div>
252

    
253
    <!-- template for machines in private network -->
254
    <div class="network-machine" id="private-machine-template">
255
        <div class="machine-actions">
256
            <a href="#" class="action-disconnect">{% trans "Disconnect" %}</a>
257
            <a href="#" class="action-details">{% trans "Details" %}</a>
258
        </div>
259
        <div class="confirm_single">
260
            <button class="yes">{% trans "Confirm" %}</button>
261
            <button class="no">X</button>
262
        </div>
263
        <div class="action_error" align="center">
264
            {% trans "<span>Error</span> on" %} <span class="action">{% trans "error action" %}</span>
265
            <span class="code"></span>
266
            <span class="message"></span>
267
            <button class="details">{% trans "Details" %}</button>
268
        </div>
269
        <img class="logo" src="static/icons/machines/medium/debian-on.png" />
270
        <div class='network-remove-machine'><span class="remove-icon">X</span></div>
271
        <div href="#" class="machine-name-div">
272
            <h5 class="namecontainer editable">
273
                <span class="name">my desktop1</span>
274
            </h5>
275
        </div>
276
        <h5 class='machine-connect'>
277
            <span>{% trans "Connect" %}</span> {% trans "to manage private IPs" %}
278
        </h5>
279
        <div class="network-separator machines"></div>
280
    </div>
281

    
282
    <!-- the actual structure to be populated -->
283
    <div class="public-networks"></div>
284
    <div class="private-networks" style="display:none;"></div>
285
</div>
286

    
287
<!-- add servers to network overlay -->
288
<div>
289
    <div id="add-machines-wizard" class="modal">
290
        <h3 class="popup-header">{% trans "Add machine" %}</h3>
291
        <p style='display:none;'>hidden network id</p>
292
        <div class="popup-body">
293
            <div class="popup-body-inner">
294
                <div class="popup-title">{% trans "Select machines to add to:" %}</div>
295
                <div class="network-name"></div>
296
                <div class="popup-separator"></div>
297
                <div class="machines-container">
298
                    <div class="large-spinner"></div>
299
                    <div id='machine-entry-template' style="display:none;">
300
                        <input type="checkbox" />
301
                        <img class=list-logo src="static/icons/machines/small/debian-on.png" title="debian"></img>
302
                        <span class="machine-name">kati</span>
303
                    </div>
304
                </div>
305
            </div>
306
        </div>
307
        <div class="buttons">
308
            <button type="button" class="cancel" id="add-server-cancel">{% trans "Cancel" %}</button>
309
            <button type="button" class="add" id="add-server-add">{% trans "Add" %}</button>
310
        </div>
311
    </div>
312
</div>
313

    
314
<a id="add-machines-overlay" href="#" rel="#add-machines-wizard"></a>
315

    
316
<!-- reboot dialog -->
317
<div class="reboot-dialog">
318
    <p>{% trans "For the network changes to take effect you need to reboot all affected machines:" %}</p>
319
    <button class="reboot-all">{% trans "Reboot All" %}</button>
320
    <div id="reboot-machine-template" class='reboot-machine-entry'>
321
        <div class="name">my debian server</div>
322
        <button class="reboot-single">{% trans "Reboot" %}</button>
323
        <div class="reboot-error">
324
            <div class="code"></div>
325
            <div class="action"></div>
326
            <div class="message"></div>
327
            <button class="details">{% trans "Error!" %}</button>
328
        </div>
329
    </div>
330
    <div class="reboot-list"></div>
331
</div>
332

    
333
<!-- multiple confirmation dialog -->
334
<div class="confirm_multiple">
335
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "networks or machines" %}</p>
336
    <button class="yes">{% trans "Confirm All" %}</button>
337
    <button class="no">{% trans "Cancel All" %}</button>
338
</div>
339

    
340
<script>
341
// add network wizard initialization
342
$(function() {
343
    // create wizard overlay
344
    $("a#networkscreate").overlay({
345
        mask: '#666',
346
        effect: 'default',
347
        top: '10%',
348
        closeOnClick: false,
349
        oneInstance: false,
350
        closeOnEsc: true,
351
        load: false
352
    });
353
});
354

355
// intercept click to create new private network
356
$("#networkscreate").click(function() {
357
    // reset and load wizard
358
    $('#networks-wizard span.help').removeClass('red');
359
    $('#networks-wizard input').val('');
360
    $('#networks-wizard #add-network-create').text('{% trans 'Create Network' %}');
361
    $("#networks-wizard").show();
362
    $('#networks-wizard input').focus();
363
    $("a#networkscreate").data('overlay').load();
364
    // enable submit button
365
    $("#networks-wizard #add-network-create").removeAttr('disabled');
366
    return false;
367
});
368

369
// exit the add machine to network wizard
370
$("#add-network-cancel").live('click', function() {
371
    $("a#networkscreate").overlay().close();
372
});
373

374
// add selected machines to network
375
$("#add-network-create").live('click', function() {
376
    if ($('#networks-wizard input').val() == '') {
377
        $('#networks-wizard input').focus();
378
        $('#networks-wizard span.help').addClass('red');
379
    } else {
380
        // disable submit button to prevent multiple calls
381
        $(this).attr("disabled", true);
382
        // load progress bar
383
        $(this).text('');
384
        $(this).html('<img src="static/icons/indicators/medium/horizontal-progress.gif"></img>');
385
        // make the call
386
        networkName = $('#networks-wizard input').val();
387
        create_network(networkName);
388
    }
389
    return false;
390
});
391

392
// toggle component with class network-contents
393
$("#networks-pane div.machines-header").live('click', function() {
394
    if ($(this).find('.toggler').hasClass('up')) {
395
        $(this).find('.toggler').removeClass('up');
396
        $(this).find('.toggler').addClass('down');
397
        $(this).find('.machines-label').removeClass('darker');
398
        $(this).closest('div.network').removeClass('light-background');
399
    } else {
400
        $(this).find('.toggler').removeClass('down');
401
        $(this).find('.toggler').addClass('up');
402
        $(this).find('.machines-label').addClass('darker');
403
        $(this).closest('div.network').addClass('light-background');
404
    }
405
    $(this).parent().next("#networks-pane .network-contents").slideToggle(600);
406
    return false;
407
});
408

409
// toggle component with class network-contents
410
$("#networks-pane .network-logos").live('click', function() {
411
    $(this).closest('div.network').find('div.machines-header').click();
412
    return false;
413
});
414

415
//initiate network renaming
416
$("#networks-pane .name-div .rename-network, #networks-pane .name-div h5.editable span.name").live('click', function() {
417
    $(this).parent().find('.name').html("<input id=\"txtEdit\" type=\"text\" class=\"nametextbox\" value=\"" +
418
                                        $(this).parent().find('.name').text() +
419
                                        "\" / ><span class=\"oldValue\">" +
420
                                        $(this).parent().find('.name').text() + "</span>");
421
    $(this).parent().find('.rename-network').hide();
422
    $(this).parent().find(".editbuttons").fadeIn();
423
    $(this).parent().find(".nametextbox").focus().select();
424
    $(this).parent().removeClass('editable');
425

426
    //submit wizard by pressing enter on the name textbox
427
    $("#txtEdit").keydown(function (e) {
428
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
429
            $(this).parent().parent().find('div.editbuttons span.save').click();
430
            return false;
431
        } else if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)) {
432
            $(this).parent().parent().find('div.editbuttons span.cancel').click();
433
            return true;
434
        }
435
    });
436
    return false;
437
});
438

439
//rename machine
440
$("#networks-pane .name-div .editbuttons .save").live('click', function() {
441
    networkID = $(this).closest('.network').attr("id").split('-').pop();
442
    networkName = $(this).parent().parent().find('.nametextbox').val();
443
    if (networkName.trim() == ''){
444
        return false;
445
    }
446
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.nametextbox').val());
447
    $(this).parent().parent().find(".editbuttons").fadeOut("fast");
448
    $(this).parent().parent().find(".rename-network").fadeIn("slow");
449
    rename_network(networkID, networkName);
450
    return false;
451
});
452

453
//cancel renaming
454
$("#networks-pane .name-div .editbuttons .cancel").live('click', function() {
455
    $(this).parent().parent().find('.name').html($(this).parent().parent().find('.oldValue').text());
456
    $(this).parent().parent().find(".editbuttons").hide();
457
    $(this).parent().parent().find(".rename-network").fadeIn();
458
    $(this).parent().parent().addClass('editable');
459
    return false;
460
});
461

462
// intercept click to delete network
463
$("#networks-pane .action-network-destroy").live('click', function() {
464
    var networkID = $(this).parent().parent().attr('id').split('-').pop();
465
    var networkName = $(this).parent().parent().find(".name-div span.name").text();
466
    var found = false;
467
    $(this).parent().children('a').removeClass('selected');
468
    $(this).addClass('selected');
469
    $(this).parent().addClass('display')
470
    $(this).parent().parent().find('.action_error').hide();
471
    for (i=0; i < pending_actions.length; i++){ // if there is already a pending action for this network replace it
472
        if (pending_actions[i][0] == delete_network && pending_actions[i][1] == networkID){
473
            pending_actions[i][0] = delete_network;
474
            found = true
475
        }
476
    }
477
    if (!found) {
478
        // no pending action for this network was found, so let's just add it to the list
479
        pending_actions.push([delete_network, networkID, networkName]);
480
    }
481
    update_network_confirmations();
482
    return false;
483
});
484

485
// intercept click to remove machine from network
486
$("#networks-pane .remove-icon").live('click', function() {
487
    $(this).closest('.network-machine').find('.action-disconnect').click();
488
    return false;
489
});
490

491
// intercept click to remove machine from network
492
$("#networks-pane .action-disconnect").live('click', function() {
493
    var serverID = $(this).parent().parent().attr('id').split('-').pop();
494
    var serverName = $(this).closest('.network-machine').find('span.name').text();
495
    var networkID = $(this).closest('.network').attr('id').split('-').pop();
496
    var serverState = $(this).closest('.network-machine').find('img.logo').attr('src').split('-')[1];
497
    serverState = serverState.split('.')[0];
498
    var found = false;
499
    $(this).parent().children('a').removeClass('selected');
500
    $(this).addClass('selected');
501
    $(this).parent().addClass('display')
502
    $(this).parent().parent().find('.action_error').hide();
503
    for (i=0; i < pending_actions.length; i++){
504
        // if there is already a pending action for this network replace it
505
        if (pending_actions[i][0] == remove_server_from_network &&
506
            pending_actions[i][1] == networkID &&
507
            pending_actions[i][2] == serverID) {
508
                pending_actions[i][0] = remove_server_from_network;
509
                found = true
510
        }
511
    }
512
    if (!found) {
513
        // no pending action for this network was found, so let's just add it to the list
514
        pending_actions.push([remove_server_from_network, networkID, serverID, serverName, serverState]);
515
    }
516
    update_network_confirmations();
517
    return false;
518
});
519

520
$("#networks-pane .action-details").live('click', function() {
521
    var serverID = $(this).parent().parent().attr('id').split('-').pop();
522
    $.cookie('view', '2');
523
    $.cookie('server', serverID);
524
    $('a#machines').click();
525
    return false;
526
});
527

528
// add machines wizard initialization
529
$(function() {
530
    // create wizard overlay
531
    $("a#add-machines-overlay").overlay({
532
        mask: '#666',
533
        effect: 'default',
534
        top: '10%',
535
        closeOnClick: false,
536
        oneInstance: false,
537
        closeOnEsc: true,
538
        load: false
539
    });
540
});
541

542
// intercept click to add machine to  network
543
$("#networks-pane .action-add").live('click', function() {
544
    // reset pre-existing values
545
    $('#add-server-add').text('{% trans 'Add' %}');
546
    $("#add-machines-wizard .network-name").text($(this).closest('.network').find('.name-div span.name').text());
547
    $("#add-machines-wizard p").text($(this).closest('.network').attr('id').split('-').pop());
548
    $("#add-machines-wizard .large-spinner").show();
549
    $('[id^="list-entry-server-"]').remove();
550
    // list new values
551
    list_machines();
552
    // load wizard
553
    $("#add-machines-wizard").show();
554
    $("a#add-machines-overlay").data('overlay').load();
555
    // enable submit button
556
    $("#add-machines-wizard #add-server-add").removeAttr('disabled');
557
    return false;
558
});
559

560
//submit wizard by pressing enter on the name textbox
561
$("#networks-wizard div.name-input input.text").keypress(function (e) {
562
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
563
        $('#add-network-create').click();
564
        return false;
565
    } else {
566
        return true;
567
    }
568
});
569

570
// intercept click to bring up the add machine to network wizard
571
$("#networks-pane .add-icon").live('click', function() {
572
    $(this).closest('.network').find('.action-add').click();
573
});
574

575
// get machines in public network and list them in add server to network wizard
576
function list_machines() {
577
    var networkID = $("#add-machines-wizard p").text();
578
    // get the list of servers from the UI
579
    var all_machines = $("#networks-pane .public-networks .network-machine");
580

581
    $.each(all_machines, function(i, machine) {
582
        var currentID = machine.id.split('-').pop();
583
        // if machine already exists in private network
584
        if ( $('#net-' + networkID + '-server-' + currentID).length > 0 ) {
585
            // do nothing
586
        } else {
587
            // put it in the list
588
            var entry = $("#add-machines-wizard #machine-entry-template").clone().attr("id", "list-entry-server-" + currentID);
589
            entry.find('input').attr("name", currentID);
590
            entry.find('img').attr('src', 'static/icons/machines/small/' + $(machine).find('img.logo').attr('src').split('/').pop());
591
            entry.find('.machine-name').text($(machine).find('span.name').text());
592
            entry.appendTo("#add-machines-wizard .machines-container");
593
        }
594
    });
595
    $("#add-machines-wizard .large-spinner").hide();
596
    $('[id^="list-entry-server-"]').fadeIn("slow");
597
    return false;
598
}
599

600
// exit the add machine to network wizard
601
$("#add-server-cancel").live('click', function() {
602
    $("a#add-machines-overlay").overlay().close();
603
});
604

605
// add selected machines to network
606
$("#add-server-add").live('click', function() {
607
    var selections = $("#add-machines-wizard :checkbox:checked");
608
    // if there are no selections simply close the wizard
609
    if (selections.length == 0 ) {
610
        $("a#add-machines-overlay").overlay().close();
611
    }
612
    // if there are servers selected make the proper call
613
    else {
614
        var networkID = $("#add-machines-wizard p").text();
615
        var serverIDs = [];
616
        var serverNames = [];
617
        var serverState = [];
618
        var serverStates = [];
619
        $.each(selections, function(i, selection) {
620
            serverIDs.push(selection.name);
621
            serverNames.push($("#list-entry-server-" + selection.name + " span.machine-name").text());
622
            serverState = $("#list-entry-server-" + selection.name + " img.list-logo").attr('src').split('-')[1];
623
            serverState = serverState.split('.')[0];
624
            serverStates.push(serverState);
625
        });
626
        // disable submit button to prevent multiple calls
627
        $(this).attr("disabled", true);
628
        // load progress bar
629
        $(this).text('');
630
        $(this).html('<img src="static/icons/indicators/medium/horizontal-progress.gif"></img>');
631
        // show the proper spinner
632
        $('#net-' + networkID + '.network div.status').text(NET_STATES['Connecting']);
633
        $('#net-' + networkID + '.network img.spinner').show();
634
        // make the calls
635
        add_server_to_network(networkID, serverIDs, serverNames, serverStates);
636
    }
637
    return false;
638
});
639

640
// toggle component with class firewall-contents
641
$("#networks-pane div.firewall-header").live('click', function() {
642
    if ($(this).find('.toggler').hasClass('up')) {
643
        $(this).find('.toggler').removeClass('up');
644
        $(this).find('.toggler').addClass('down');
645
        $(this).find('.firewall-label').removeClass('darker');
646
    } else {
647
        $(this).find('.toggler').removeClass('down');
648
        $(this).find('.toggler').addClass('up');
649
        $(this).find('.firewall-label').addClass('darker');
650
    }
651
    $(this).parent().next(".firewall-content").slideToggle(600);
652
    return false;
653
});
654

655
//hide firewall content on apply click
656
$("#networks-pane .firewall-apply").live('click', function() {
657
    var serverID = $(this).closest('.network-machine').attr("id").split('-').pop();
658
    var networkID = $(this).closest('.network-machine').attr("id").split('-')[1];
659
    var profile = $(this).parent().find('input:checked').attr('value');
660
    if (profile != undefined) {
661
        set_firewall(networkID, serverID, profile);
662
        $(this).attr("disabled", true);
663
        $(this).html('<img src="static/icons/indicators/medium/horizontal-progress.gif"></img>');
664
    }
665
    return false;
666
});
667

668
function display_reboot_dialog(networkID, serverID, serverName, serverState) {
669
    // check if the server already exists in the list
670
    var existing_reboot = $("div.reboot-list div#server-" + serverID);
671
    if ( !existing_reboot.length && serverState != 'off') {
672
        $('div.reboot-dialog').fadeIn("slow");
673
        var reboot_entry = $('div#reboot-machine-template').clone().attr("id", "server-" + serverID);
674
        reboot_entry.find('div.name').text(serverName);
675
        reboot_entry.appendTo('div.reboot-list').show();
676
    }
677
    return false;
678
}
679

680
// intercept single reboot click
681
$("div.reboot-dialog button.reboot-single").live('click', function() {
682
    var serverID = $(this).parent().attr('id').split('-')[1];
683
    reboot([serverID]);
684
    // load progress bar
685
    $(this).text('');
686
    $(this).html('<img src="static/icons/indicators/medium/horizontal-progress.gif"></img>');
687
    // disable submit button to prevent multiple calls
688
    $(this).attr("disabled", true);
689
    return false;
690
});
691

692
// intercept multiple reboot click
693
$("div.reboot-dialog button.reboot-all").live('click', function() {
694
    $(this).parent().find('div.reboot-list button.reboot-single').click();
695
    // load progress bar for all buttons
696
    $(this).parent().find('button').text('');
697
    $(this).parent().find('button').html('<img src="static/icons/indicators/medium/horizontal-progress.gif"></img>');
698
    // disable submit button to prevent multiple calls
699
    $(this).attr("disabled", true);
700
    return false;
701
});
702

703
// intercept error on reboot click
704
$("div.reboot-dialog button.details").live('click', function() {
705
    $(this).closest('.reboot-machine-entry').remove();
706
    ajax_error( $(this).parent().children('.code').text(),
707
                undefined,
708
                $(this).parent().children('.action').text(),
709
                $(this).parent().children('.message').text());
710
    if ( !$('div.reboot-list').children().length ) {
711
        $('div.reboot-dialog').hide();
712
    }
713
    return false;
714
});
715

716
// after reboot success
717
function display_reboot_success(serverID) {
718
    // remove server from the list
719
    $('div.reboot-list #server-' + serverID).remove();
720
    // if there are no other servers on the list, hide the reboot dialog
721
    if ( !$('div.reboot-list').children().length ) {
722
        $('div.reboot-dialog').hide();
723
        // reset all buttons
724
        $("div.reboot-dialog button.reboot-all").html('');
725
        $("div.reboot-dialog button.reboot-all").text('{% trans 'Reboot All' %}');
726
        $("div.reboot-dialog button.reboot-single").html('');
727
        $("div.reboot-dialog button.reboot-single").text('{% trans 'Reboot' %}');
728
        // enable submit button
729
        $("#div.reboot-dialog button.reboot-all").removeAttr('disabled');
730
    }
731
    return false;
732
}
733

734
// after reboot error
735
function display_reboot_failure(status, serverID, responseText) {
736
    $('div.reboot-list #server-' + serverID + ' button.reboot-single').hide();
737
    $('div.reboot-list #server-' + serverID + ' div.code').text(status);
738
    $('div.reboot-list #server-' + serverID + ' div.action').text('Reboot');
739
    $('div.reboot-list #server-' + serverID + ' div.message').text(responseText);
740
    $('div.reboot-list #server-' + serverID + ' button.details').show();
741
    return false;
742
}
743

744
// confirm single action
745
$("#networks-pane div.confirm_single .yes").live('click', function() {
746
    // this works both for server and network actions
747
    var serverID = [];
748
    if ($(this).closest('.network-machine').attr('id')) {
749
        serverID = $(this).closest('.network-machine').attr('id').split('-').pop();
750
    }
751
    var networkID = $(this).closest('.network').attr("id").split('-').pop();
752
    // execute actions
753
    for (i=0;i<pending_actions.length;i++){
754
        // if there is a pending action for this server execute it
755
        if (pending_actions[i][0] == delete_network &&
756
            pending_actions[i][1] == networkID) {
757
                action = pending_actions.splice(i,1)[0];
758
                $(this).closest('div.network').find('div.status').text(NET_STATES['Destroying']);
759
                $(this).closest("div.network").find('div.state').addClass('destroying-state');
760
                $(this).closest('div.network').find('img.spinner').show();
761
                action[0]([action[1]]); // execute action
762
        } else if ( pending_actions[i][0] == remove_server_from_network &&
763
                    pending_actions[i][1] == networkID ) {
764
                        $(this).closest('div.network').find('div.status').text(NET_STATES['Disconnecting']);
765
                        $(this).closest('div.network').find('img.spinner').show();
766
                        action = pending_actions.splice(i,1)[0];
767
                        action[0]([action[1]], [action[2]], [action[3]], [action[4]]); // execute action
768
        } // for adding servers to a network look in $("#add-server-add").live('click', function() {...});
769
    }
770
    $(this).parent().hide();
771
    $(this).closest("div.network").find('a.selected').removeClass('selected');
772
    $(this).closest("div.network").children('div.actions').removeClass('display');
773
    update_network_confirmations();
774
    return false;
775
});
776

777
// cancel single action
778
$("#networks-pane div.confirm_single .no").live('click', function(){
779
    // this works both for server and network actions
780
    var serverID = [];
781
    if ($(this).closest('.network-machine').attr('id')) {
782
        serverID = $(this).closest('.network-machine').attr('id').split('-').pop();
783
    }
784
    var networkID = $(this).closest('.network').attr("id").split('-').pop();
785
    // remove the action from the pending list
786
    $(this).parent().parent().children('div.machine-actions').children('a').removeClass('selected');
787
    $(this).parent().parent().children('div.machine-actions').removeClass('display');
788

789
    for (i=0; i < pending_actions.length; i++) { // if there is a pending action for this network remove it
790
        if (pending_actions[i][0] == delete_network && pending_actions[i][1] == networkID) {
791
                pending_actions.splice(i,1);
792
        } else if ( pending_actions[i][0] == remove_server_from_network &&
793
                    pending_actions[i][1] == networkID &&
794
                    pending_actions[i][2] == serverID) {
795
                        pending_actions.splice(i,1);
796
        }
797
    }
798
    $(this).parent().hide();
799
    update_network_confirmations();
800
    return false;
801
});
802

803
// after single action call error
804
function display_net_failure(status, networkID, action, responseText) {
805
    return false;
806
}
807

808
// show, single action, error details
809
$("#networks-pane div.action_error .details").live('click', function(){
810
    $(this).parent().hide();
811
    ajax_error($(this).parent().children('.code').text(),
812
                 undefined,
813
                 $(this).parent().children('.action').text(),
814
                 $(this).parent().children('.message').text());
815
    return false;
816
});
817

818
// confirm all actions
819
$("#networks-pane div.confirm_multiple .yes").live('click', function(){
820
    while(pending_actions.length > 0){ // if there is a pending action for this network execute it
821
        action = pending_actions.pop(); // extract action
822
        var networkID = action[1];
823
        $('#networks-pane .selected').removeClass('selected');
824
        $('#networks-pane .display').removeClass('display');
825
        $('#networks-pane .confirm_single').hide();
826
        if (action[0] == delete_network) {
827
            $('#networks-pane #net-' + networkID + ' .status').text(NET_STATES['Destroying']);
828
            $('#networks-pane #net-' + networkID + ' .state').addClass('destroying-state');
829
            $('#networks-pane #net-' + networkID + ' .spinner').show();
830
            action[0]([networkID]); // execute action
831
        } else if (action[0] == remove_server_from_network) {
832
            $('div.network#net-'+networkID).find('div.status').text(NET_STATES['Disconnecting']);
833
            $('div.network#net-'+networkID).find('img.spinner').show();
834
            action[0]([action[1]], [action[2]], [action[3]], [action[4]]); // execute action
835
        }
836
    }
837
    update_network_confirmations();
838
    return false;
839
});
840

841
// cancel all actions
842
$("#networks-pane div.confirm_multiple .no").live('click', function(){
843
    pending_actions = [];
844
    $('#networks-pane .selected').removeClass('selected');
845
    $('#networks-pane .display').removeClass('display');
846
    $('#networks-pane .confirm_single').hide();
847
    update_network_confirmations();
848
    return false;
849
});
850

851
// update the networks list
852
function update_networks_view(servers_data, networks_data){
853
    /*
854
    Go through the input data. Update existing entries, add
855
    new ones to the list
856
    */
857

858
    // check for changes in networks
859
    if (networks_data){
860
        /*
861
        Here we are interested in private networks only
862
        and for servers disconnected from them
863
        */
864

865
        // if we wait for a new network to be created
866
        if ($('#add-network-create').children().length > 0) {
867
            var response_objects = networks_data.networks.values;
868
            // check all objects in the response
869
            for (i=0; i < response_objects.length; i++) {
870
                // if it contains the network we want to create
871
                var networkName = $('#networks-wizard input').val();
872
                if ( response_objects[i]['name'] == networkName) {
873
                    // close the wizard
874
                    $("a#networkscreate").overlay().close();
875
                    // and the network will be inserted in the DOM
876
                    // during this update loop
877
                }
878
            }
879
        }
880

881
        // update private networks
882
        $.each(networks_data.networks.values, function(i,network) {
883
            // search DOM for this network
884
            existing = $('#networks-pane #net-' + network.id);
885

886
            // If in the DOM exist multiple networks with the same id,
887
            // delete all but one.
888
            // Defensive coding - that shouldn't happen normally
889
            while (existing.length > 1) {
890
                existing.remove();
891
            }
892

893
            // If network already exists in DOM, update it
894
            if (existing.length) {
895
                // network was deleted
896
                if (network.status == 'DELETED') {
897
                    existing.next().remove(); // to delete its separator
898
                    existing.remove();
899
                }
900
                // network was renamed
901
                if (existing.find('.name-div span.name').text() != network.name) {
902
                    // set the new name
903
                    existing.find('.name-div span.name').text(network.name);
904
                }
905
                // a server was disconnected
906
                // search DOM for all machines
907
                existing_machines = $('div.private-networks div.network-machine');
908
                // check if the machines in the DOM exist in the response
909
                for (i=0; i<existing_machines.length; i++) {
910
                    // get the existing server id
911
                    var serverID = existing_machines[i].id.split('-')[3];
912
                    // if a server exists in DOM, but not in the response it has
913
                    // been disconnected
914
                    if ( network.servers.values.indexOf( parseInt(serverID) ) == -1 ) {
915
                        // remove it from DOM and reset all spinners
916
                        $('#' + existing_machines[i].id).remove();
917
                        $('#net-' + network.id + '.network div.status').text(NET_STATES['ACTIVE']);
918
                        $('#net-' + network.id + '.network img.spinner').hide();
919
                    }
920
                }
921
            }
922
            // If network does not exist in DOM, create it, do not take into account public network
923
            else if (network.id != 'public'){
924
                var privNet = $("#networks-pane #private-template").clone().attr("id", "net-" + network.id);
925
                privNet.find(".name-div span.name").text(network.name).fadeIn("slow");
926
                privNet.appendTo("#networks-pane .private-networks");
927
                $('div.separator:last').clone().appendTo("#networks-pane .private-networks");
928
            }
929
        });
930
    }
931

932
    // check for changes in servers
933
    if (servers_data) {
934
        /*
935
        Here we are interested in any server contained
936
        either in a public network or a private one
937
        */
938
        $.each(servers_data.servers.values, function(i,server) {
939
            /*
940
            First update the public network
941
            */
942

943
            // search public network's DOM for this server
944
            existing_public = $('#networks-pane #net-pub-server-' + server.id);
945

946
            // get the server's OS icon
947
            var server_image = os_icon(server.metadata);
948
            if (!(server.metadata == undefined)) {
949
                var server_image = os_icon(server.metadata);
950
            } else {
951
                var server_image = "unknown"
952
            }
953

954
            // server was deleted
955
            if (server.status == 'DELETED') {
956
                existing_public.remove();
957
            }
958

959
            // If server already exists in public network, update it
960
            if (existing_public.length){
961
                // server was renamed
962
                if (server.name != existing_public.find('span.name').text()) {
963
                    existing_public.find('span.name').text(server.name.substring(0,30));
964
                }
965
                // server has changed state
966
                if (server.status=='BUILD' || server.status=='ACTIVE' ||server.status=='REBOOT') {
967
                    existing_public.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-on.png');
968
                } else {
969
                    existing_public.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-off.png');
970
                }
971
                // server has new ips
972
                var old_ip4 = existing_public.find('span.ip4').text();
973
                var old_ip6 = existing_public.find('span.ip6').text();
974
                var new_ips = get_public_ips(server);
975
                var new_ip4 = new_ips['ip4'];
976
                var new_ip6 = new_ips['ip6'];
977
                if (old_ip4 != new_ip4) {
978
                    if (new_ips['ip4'] == undefined) {
979
                        existing_public.find(".ip4-container").hide();
980
                    } else {
981
                        existing_public.find('span.ip4').text(new_ip4);
982
                    }
983
                }
984
                if (old_ip6 != new_ip6) {
985
                    if (new_ip6 == undefined) {
986
                        existing_public.find(".ip6-container").hide();
987
                    } else {
988
                        existing_public.find('span.ip6').text(new_ip6);
989
                    }
990
                }
991
                //TODO: server has changed OS
992
            }
993
            // If server does not exist in public network, create it
994
            else {
995
                var machine = $("#networks-pane #public-machine-template").clone().attr("id", "net-pub-server-" + server.id).fadeIn("slow");
996
                machine.find('span.name').text(server.name.substring(0,30));
997
                // find and display ips
998
                var ips = get_public_ips(server);
999
                if (ips['ip4'] == undefined) {
1000
                    machine.find(".ip4-container").hide();
1001
                } else {
1002
                    machine.find("span.ip4").text(ips['ip4']);
1003
                }
1004
                if (ips['ip6'] == undefined) {
1005
                    machine.find(".ip6-container").hide();
1006
                } else {
1007
                    machine.find("span.ip6").text(ips['ip6']);
1008
                }
1009
                // add the proper icon
1010
                if (server.status=='BUILD' || server.status=='ACTIVE' ||server.status=='REBOOT') {
1011
                    machine.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-on.png');
1012
                } else {
1013
                    machine.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-off.png');
1014
                }
1015
                machine.appendTo("#networks-pane .public-networks .machines-list");
1016
            }
1017

1018
            /*
1019
            Now update all private networks, this does NOT check for
1020
            disconnected servers (see above in updating private networks).
1021
            Since one server may belong to more than one private networks,
1022
            we follow a different approach.
1023
            We check each server and add, update or leave it as it is accordingly
1024
            */
1025
            try {
1026
                $.each(server.addresses.values, function(i,server_net) {
1027
                    // find in which private networks it belongs
1028
                    if (server_net.id != "public") {
1029
                        var existing_private = $("#networks-pane .private-networks #net-" + server_net.id + "-server-" + server.id);
1030
                        // add new server
1031
                        if (!existing_private.length) {
1032
                            var machine = $("#networks-pane #private-machine-template").clone().attr("id", "net-" + server_net.id + "-server-" + server.id).fadeIn("slow");
1033
                            machine.find('span.name').text(server.name.substring(0,30));
1034
                            if (server.status=='BUILD' || server.status=='ACTIVE' ||server.status=='REBOOT') {
1035
                                machine.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-on.png');
1036
                            } else {
1037
                                machine.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-off.png');
1038
                            }
1039
                            machine.appendTo("#networks-pane .private-networks #net-" + server_net.id + " .machines-list");
1040
                        // hide spinners
1041
                        $('#net-' + server_net.id + '.network div.status').text(NET_STATES['ACTIVE']);
1042
                        $('#net-' + server_net.id + '.network img.spinner').hide();
1043
                        }
1044
                        // server was deleted
1045
                        if (server.status == 'DELETED') {
1046
                            existing_private.remove();
1047
                        }
1048
                        // server was renamed
1049
                        if (server.name != existing_private.find('span.name').text()) {
1050
                            existing_private.find('span.name').text(server.name.substring(0,30));
1051
                        }
1052
                        // server has changed state
1053
                        if (server.status=='BUILD' || server.status=='ACTIVE' ||server.status=='REBOOT') {
1054
                            existing_private.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-on.png');
1055
                        } else {
1056
                            existing_private.find("img.logo").attr("src","static/icons/machines/medium/" + server_image + '-off.png');
1057
                        }
1058
                        //TODO: server has changed OS
1059
                    }
1060
                });
1061
            } catch (err) {
1062
                try{console.info('Server ' + server.id + ' has no network addresses')}catch(err){};
1063
            }
1064
        });
1065
    }
1066

1067
    $("#networks-pane #networks-container > .large-spinner").hide();
1068

1069
    // show all separators and hide the last one
1070
    $("div.private-networks div.separator").show();
1071
    $("div.private-networks div.separator:last").hide();
1072
    // update the counters of servers in each network
1073
    var nets = $('#networks-pane .network');
1074
    $.each(nets, function(i,net) {
1075
        $(net).find('span.machines-count').text($(net).find('.network-machine').length);
1076
    });
1077

1078
    // the private div shows only when private networks are available
1079
    if ($("div.private-networks div.network").length > 0) {
1080
        $("div.private-networks").fadeIn("slow");
1081
    } else {
1082
        $("div.private-networks").fadeOut("slow");
1083
    }
1084

1085
    // tag the first and last seperators for better styling
1086
    $("#pub .network-machine").removeClass('first');
1087
    $("#pub .network-machine").first().addClass('first');
1088
    $("#pub .network-machine").removeClass('last');
1089
    $("#pub .network-machine").last().addClass('last');
1090

1091
    if ($("div.public-networks div.network-machine").length == 1) {
1092
        $("div.public-networks div.network-machine div.network-cable").css('height','60px');
1093
    }
1094

1095
    //remove top margin from the first machine of each private network
1096
    $(".private-networks").find(".network-contents .network-machine:first-child").css("margin-top","0");
1097
}
1098

1099
// indicate that the requested action was not completed
1100
function display_failure(status, networkID, action, responseText) {
1101
    $('#networks-container #net-'+networkID+ ' .spinner').hide();
1102
    $('#networks-container #net-'+networkID+ ' .action_error .action').text(action);
1103
    $('#networks-container #net-'+networkID+ ' .action_error .code').text(status);
1104
    $('#networks-container #net-'+networkID+ ' .action_error .message').text(responseText);
1105
    $('#networks-container #net-'+networkID+ ' .action_error').show();
1106
}
1107

1108
// reposition multiple confirmation box on window resize
1109
$(window).resize(function(){
1110
    if (this.innerHeight - 220 < $('#networks-pane #networks-container').height()) {
1111
        $('#networks-pane .confirm_multiple').addClass('fixed');
1112
        $('div.reboot-dialog').addClass('fixed');
1113
    } else {
1114
        $('#networks-pane .confirm_multiple').removeClass('fixed');
1115
        $('div.reboot-dialog').removeClass('fixed');
1116
    }
1117
});
1118

1119
// basic functions executed on page load
1120
// hide the all of the networks contents
1121
$("#networks-pane .network-contents").hide();
1122
// hide the all of the firewall contents
1123
$("#networks-pane .firewall-content").hide();
1124
changes_since = 0; // to reload full list of servers
1125
networks_changes_since= 0; // to reload full list of networks
1126
// there is always one public network to render
1127
var pubNet = $("#networks-pane #public-template").clone().attr("id", "pub").fadeIn("slow");
1128
pubNet.appendTo("#networks-pane .public-networks");
1129
update_networks(UPDATE_INTERVAL);
1130

1131
//fix ie z-index bug by moving the overlays to the bottom
1132
$(document).ready(function() {
1133
    if ($.browser.msie) {
1134
        $("body").append($("#networks-wizard"));
1135
        $("body").append($("#add-machines-wizard"));
1136
    }
1137
});
1138

1139
//IE specific fixes
1140
if ($.browser.msie) {
1141
    //IE fix for network div hover
1142
    $("div.network").live("mouseenter", function () {
1143
        $(this).css("background-color","#A1C8DB");
1144
        $(this).find(".actions a").css("visibility","visible");
1145
    });
1146
    $("div.network").live("mouseleave", function () {
1147
        $(this).css("background-color","transparent");
1148
        $(this).find(".actions a").css("visibility","hidden");
1149
    });
1150
    //IE fix for network machine hover
1151
    $("div.network-machine").live("mouseenter", function () {
1152
        $(this).css("background-color","#84B7D0");
1153
        $(this).find("div.machine-actions a").css("visibility","visible");
1154
    });
1155
    $("div.network-machine").live("mouseleave", function () {
1156
        $(this).css("background-color","transparent");
1157
        $(this).find("div.machine-actions a").css("visibility","hidden");
1158
    });
1159
}
1160
</script>