Statistics
| Branch: | Tag: | Revision:

root / ui / static / synnefo.js @ 4337c7e5

History | View | Annotate | Download (47.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
var API_URL = "/api/v1.1";
36
var changes_since = 0, deferred = 0, update_request = false, load_request = false, pending_actions = [];
37
var flavors = [], images = [], servers = [], disks = [], cpus = [], ram = [];
38
var networks = [], networks_changes_since = 0;
39

    
40

    
41
//FIXME: authentication
42
//if cookie with value X-Auth-Token exists, set the value on the headers.
43
    $.ajaxSetup({
44
        'beforeSend': function(xhr) {
45
            //if ($.cookie("X-Auth-Token") != null) {
46
              xhr.setRequestHeader("X-Auth-Token", $.cookie("X-Auth-Token"));
47
            //} else {
48
            //    $.cookie("X-Auth-Token", "46e427d657b20defe352804f0eb6f8a2"); // set X-Auth-Token cookie
49
            //}
50
        }
51
    });
52

    
53
function ISODateString(d){
54
    //return a date in an ISO 8601 format using UTC.
55
    //do not include time zone info (Z) at the end
56
    //taken from the Mozilla Developer Center
57
    function pad(n){ return n<10 ? '0'+n : n }
58
    return  d.getUTCFullYear()+ '-' +
59
            pad(d.getUTCMonth()+1) + '-' +
60
            pad(d.getUTCDate()) + 'T' +
61
            pad(d.getUTCHours()) + ':' +
62
            pad(d.getUTCMinutes()) + ':' +
63
            pad(d.getUTCSeconds()) +'Z'
64
}
65

    
66
function parse_error(responseText, errorCode){
67
    var errors = [];
68
    try {
69
        responseObj = JSON.parse(responseText);
70
    }
71
    catch(err) {
72
        errors[0] = {'code': errorCode};
73
        return errors;
74
    }
75
    for (var err in responseObj){
76
        errors[errors.length] = responseObj[err];
77
    }
78
    return errors;
79
}
80

    
81
// indexOf prototype for IE
82
if (!Array.prototype.indexOf) {
83
  Array.prototype.indexOf = function(elt /*, from*/) {
84
    var len = this.length;
85
    var from = Number(arguments[1]) || 0;
86
    from = (from < 0)
87
         ? Math.ceil(from)
88
         : Math.floor(from);
89
    if (from < 0)
90
      from += len;
91

    
92
    for (; from < len; from++) {
93
      if (from in this &&
94
          this[from] === elt)
95
        return from;
96
    }
97
    return -1;
98
  };
99
}
100

    
101
function update_confirmations() {
102
    // hide all confirm boxes to begin with
103
    $('#machines-pane div.confirm_single').hide();
104
    $('#machines-pane div.confirm_multiple').hide();
105
    var action_type = [];
106
    // standard view or single view
107
    if ($.cookie("view") == '0' || $.cookie("view") == '2') {
108
        for (var i=0; i<pending_actions.length; i++) {
109
            // show single confirms
110
            if (pending_actions[i][0] == reboot) {
111
                action_type = "reboot";
112
            } else if (pending_actions[i][0] == shutdown) {
113
                action_type = "shutdown";
114
            } else if (pending_actions[i][0] == start) {
115
                action_type = "start";
116
            } else if (pending_actions[i][0] == open_console) {
117
                action_type = "console";
118
            } else {
119
                action_type = "destroy";
120
            }
121
            $("#machines-pane #" + pending_actions[i][1] +
122
            " div.action-container." + action_type + " div.confirm_single").show();
123
        }
124
    }
125
    // if more than one pending action show multiple confirm box
126
    if (pending_actions.length>1 || $.cookie("view") == '1' && pending_actions.length == 1){
127
        $('#machines-pane div.confirm_multiple span.actionLen').text(pending_actions.length);
128
        $('#machines-pane div.confirm_multiple').show();
129
    }
130
}
131

    
132
function update_network_confirmations(){
133
    // hide all confirm boxes to begin with
134
    $('#networks-pane div.confirm_multiple').hide();
135

    
136
    for (var i=0;i<pending_actions.length;i++){
137
        // show single confirms depending on the action
138
        if (pending_actions[i][0] == delete_network) {
139
            $("#networks-pane div.network#net-"+pending_actions[i][1]).children('.confirm_single').show();
140
        } else if (pending_actions[i][0] == remove_server_from_network) {
141
            $("#networks-pane div.network #net-"+pending_actions[i][1]+"-server-"+pending_actions[i][2]).children('.confirm_single').show();
142
        } // else {}
143
    }
144

    
145
    // if more than one pending action show multiple confirm box
146
    if (pending_actions.length > 1){
147
        $('#networks-pane div.confirm_multiple span.actionLen').text(pending_actions.length);
148
        $('#networks-pane div.confirm_multiple').show();
149
    }
150
}
151

    
152
function list_view() {
153
    changes_since = 0; // to reload full list
154
    pending_actions = []; // clear pending actions
155
    update_confirmations();
156
    clearTimeout(deferred);    // clear old deferred calls
157
    try {
158
        update_request.abort(); // cancel pending ajax updates
159
        load_request.abort();
160
    }catch(err){}
161
    $.cookie("view", '1'); // set list cookie
162
    uri = $("a#list").attr("href");
163
    load_request = $.ajax({
164
        url: uri,
165
        type: "GET",
166
        timeout: TIMEOUT,
167
        dataType: "html",
168
        error: function(jqXHR, textStatus, errorThrown) {
169
            return false;
170
        },
171
        success: function(data, textStatus, jqXHR) {
172
            $("a#list")[0].className += ' activelink';
173
            $("a#standard")[0].className = '';
174
            $("a#single")[0].className = '';
175
            $("div#machinesview").html(data);
176
        }
177
    });
178
    return false;
179
}
180

    
181
function single_view() {
182
    changes_since = 0; // to reload full list
183
    pending_actions = []; // clear pending actions
184
    update_confirmations();
185
    clearTimeout(deferred);    // clear old deferred calls
186
    try {
187
        update_request.abort(); // cancel pending ajax updates
188
        load_request.abort();
189
    }catch(err){}
190
    $.cookie("view", '2'); // set list cookie
191
    uri = $("a#single").attr("href");
192
    load_request = $.ajax({
193
        url: uri,
194
        type: "GET",
195
        timeout: TIMEOUT,
196
        dataType: "html",
197
        error: function(jqXHR, textStatus, errorThrown) {
198
            return false;
199
        },
200
        success: function(data, textStatus, jqXHR) {
201
            $("a#single")[0].className += ' activelink';
202
            $("a#standard")[0].className = '';
203
            $("a#list")[0].className = '';
204
            $("div#machinesview").html(data);
205
        }
206
    });
207
    return false;
208
}
209

    
210
function standard_view() {
211
    changes_since = 0; // to reload full list
212
    pending_actions = []; // clear pending actions
213
    update_confirmations();
214
    clearTimeout(deferred);    // clear old deferred calls
215
    try {
216
        update_request.abort() // cancel pending ajax updates
217
        load_request.abort();
218
    }catch(err){}
219
    $.cookie("view", '0');
220
    uri = $("a#standard").attr("href");
221
    load_request = $.ajax({
222
        url: uri,
223
        type: "GET",
224
        timeout: TIMEOUT,
225
        dataType: "html",
226
        error: function(jqXHR, textStatus, errorThrown) {
227
            return false;
228
        },
229
        success: function(data, textStatus, jqXHR) {
230
            $("a#standard")[0].className += ' activelink';
231
            $("a#list")[0].className = '';
232
            $("a#single")[0].className = '';
233
            $("div#machinesview").html(data);
234
        }
235
    });
236
    return false;
237
}
238

    
239
function choose_view() {
240
    if ($.cookie("view")=='1') {
241
        list_view();
242
    } else if ($.cookie("view")=='2'){
243
        single_view();
244
    } else {
245
        standard_view();
246
    }
247
}
248

    
249
// return value from metadata key "OS", if it exists
250
function os_icon(metadata) {
251
    if (!metadata) {
252
        return 'unknown';
253
    }
254
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
255
        return 'unknown';
256
    } else {
257
        if (os_icons.indexOf(metadata.values.OS) == -1) {
258
            return 'unknown';
259
        } else {
260
            return metadata.values.OS;
261
        }
262
    }
263
}
264

    
265
function os_icon_from_value(metadata) {
266
    if (!metadata) {
267
        return 'unknown';
268
    }
269
if (metadata == undefined || metadata == '') {
270
        return 'unknown';
271
    } else {
272
        if (os_icons.indexOf(metadata) == -1) {
273
            return 'unknown';
274
        } else {
275
            return metadata;
276
        }
277
    }
278
}
279

    
280
// get and show a list of running and terminated machines
281
function update_vms(interval) {
282
    try{ console.info('updating machines'); } catch(err){}
283
    var uri= API_URL + '/servers/detail';
284

    
285
    if (changes_since != 0)
286
        uri+='?changes-since='+changes_since
287

    
288
    update_request = $.ajax({
289
        cache: false,
290
        url: uri,
291
        type: "GET",
292
        timeout: TIMEOUT,
293
        dataType: "json",
294
        error: function(jqXHR, textStatus, errorThrown) {
295
            // don't forget to try again later
296
            if (interval) {
297
                clearTimeout(deferred);    // clear old deferred calls
298
                deferred = setTimeout(function() {update_vms(interval);},interval,interval);
299
            }
300
            // as for now, just show an error message
301
            try { console.info('update_vms errback:' + jqXHR.status ) } catch(err) {}
302
            ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);
303
            return false;
304
            },
305
        success: function(data, textStatus, jqXHR) {
306
            // create changes_since string if necessary
307
            if (jqXHR.getResponseHeader('Date') != null){
308
                changes_since_date = new Date(jqXHR.getResponseHeader('Date'));
309
                changes_since = ISODateString(changes_since_date);
310
            }
311

    
312
            if (interval) {
313
                clearTimeout(deferred);    // clear old deferred calls
314
                deferred = setTimeout(function() {update_vms(interval);},interval,interval);
315
            }
316

    
317
            if (jqXHR.status == 200 || jqXHR.status == 203) {
318
                try {
319
                    servers = data.servers.values;
320
                    jQuery.parseJSON(data);
321
                    update_machines_view(data);
322
                } catch(err) { ajax_error('400', undefined, 'Update VMs', jqXHR.responseText);}
323
            } else if (jqXHR.status != 304){
324
                try { console.info('update_vms callback:' + jqXHR.status ) } catch(err) {}
325
                /*
326
                FIXME:  Here it should return the error, however Opera does not support 304.
327
                        Instead 304 it returns 0. To dealt with this we treat 0 as an
328
                        304, which should be corrected (Bug #317).
329
                */
330
                //ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);
331
            }
332
            return false;
333
        }
334
    });
335
    return false;
336
}
337

    
338
// get a list of running and terminated machines, used in network view
339
function update_networks(interval) {
340
    try{ console.info('updating networks'); } catch(err){}
341
    var uri= API_URL + '/servers/detail';
342

    
343
    if (changes_since != 0)
344
        uri+='?changes-since='+changes_since
345

    
346
    update_request = $.ajax({
347
        cache: false,
348
        url: uri,
349
        type: "GET",
350
        timeout: TIMEOUT,
351
        dataType: "json",
352
        error: function(jqXHR, textStatus, errorThrown) {
353
            // don't forget to try again later
354
            if (interval) {
355
                clearTimeout(deferred);    // clear old deferred calls
356
                deferred = setTimeout(function() {update_networks(interval);},interval,interval);
357
            }
358
            // as for now, just show an error message
359
            try { console.info('update_networks errback:' + jqXHR.status ) } catch(err) {}
360
            ajax_error(jqXHR.status, undefined, 'Update networks', jqXHR.responseText);
361
            return false;
362
            },
363
        success: function(data, textStatus, jqXHR) {
364
            // create changes_since string if necessary
365
            if (jqXHR.getResponseHeader('Date') != null){
366
                changes_since_date = new Date(jqXHR.getResponseHeader('Date'));
367
                changes_since = ISODateString(changes_since_date);
368
            }
369

    
370
            if (interval) {
371
                clearTimeout(deferred);    // clear old deferred calls
372
                deferred = setTimeout(function() {update_networks(interval);},interval,interval);
373
            }
374

    
375
            if (jqXHR.status == 200 || jqXHR.status == 203) {
376
                try {
377
                    servers = data.servers.values;
378
                    jQuery.parseJSON(data);
379
                    update_network_names(data);
380
                } catch(err) { ajax_error('400', undefined, 'Update networks', jqXHR.responseText);}
381
            } else if (jqXHR.status == 304) {
382
                update_network_names();
383
            }
384
            else {
385
                try { console.info('update_networks callback:' + jqXHR.status ) } catch(err) {}
386
                /*
387
                FIXME:  Here it should return the error, however Opera does not support 304.
388
                        Instead 304 it returns 0. To dealt with this we treat 0 as an
389
                        304, which should be corrected (Bug #317).
390
                */
391
                //ajax_error(jqXHR.status, undefined, 'Update networks', jqXHR.responseText);
392
                update_network_names();
393
            }
394
            return false;
395
        }
396
    });
397
    return false;
398
}
399

    
400
// get and show a list of public and private networks
401
function update_network_names(servers_data) {
402
    try{ console.info('updating network names'); } catch(err){}
403
    var uri= API_URL + '/networks/detail';
404

    
405
    if (networks_changes_since != 0)
406
        //FIXME: Comment out the following, until metadata do not 304 when changed
407
        uri+='?changes-since=' + networks_changes_since
408

    
409
    update_request = $.ajax({
410
        cache: false,
411
        url: uri,
412
        type: "GET",
413
        timeout: TIMEOUT,
414
        dataType: "json",
415
        error: function(jqXHR, textStatus, errorThrown) {
416
            // as for now, just show an error message
417
            try {
418
                console.info('update_network names errback:' + jqXHR.status )
419
            } catch(err) {}
420
            ajax_error(jqXHR.status, undefined, 'Update network names', jqXHR.responseText);
421
            return false;
422
            },
423
        success: function(data, textStatus, jqXHR) {
424
            // create changes_since string if necessary
425
            if (jqXHR.getResponseHeader('Date') != null){
426
                changes_since_date = new Date(jqXHR.getResponseHeader('Date'));
427
                networks_changes_since = ISODateString(changes_since_date);
428
            }
429

    
430
            if (jqXHR.status == 200 || jqXHR.status == 203) {
431
                try {
432
                    networks = data.networks.values;
433
                    jQuery.parseJSON(data);
434
                    update_networks_view(servers_data, data);
435
                } catch(err) {
436
                    ajax_error('400', undefined, 'Update network names', jqXHR.responseText);
437
                }
438
            } else if (jqXHR.status == 304) {
439
                update_networks_view(servers_data);
440
            } else if (jqXHR.status != 304){
441
                try { console.info('update_network_names callback:' + jqXHR.status ) } catch(err) {}
442
                /*
443
                FIXME:  Here it should return the error, however Opera does not support 304.
444
                        Instead 304 it returns 0. To dealt with this we treat 0 as an
445
                        304, which should be corrected (Bug #317).
446
                */
447
                //ajax_error(jqXHR.status, undefined, 'Update network names', jqXHR.responseText);
448
                update_networks_view(servers_data);
449
            }
450
            return false;
451
        }
452
    });
453
    return false;
454
}
455

    
456
// get and show a list of available standard and custom images
457
function update_images() {
458
    $.ajax({
459
        url: API_URL + '/images/detail',
460
        type: "GET",
461
        //async: false,
462
        dataType: "json",
463
        timeout: TIMEOUT,
464
        error: function(jqXHR, textStatus, errorThrown) {
465
                    ajax_error(jqXHR.status, undefined, 'Update Images', jqXHR.responseText);
466
                    },
467
        success: function(data, textStatus, jqXHR) {
468
            try {
469
                images = data.images.values;
470
                                jQuery.parseJSON(data);
471
                update_wizard_images();
472
            } catch(err){
473
                ajax_error("NO_IMAGES");
474
            }
475
        }
476
    });
477
    return false;
478
}
479

    
480
function update_wizard_images() {
481
    if ($("ul#standard-images li").toArray().length + $("ul#custom-images li").toArray().length == 0) {
482
        $.each(images, function(i,image){
483
            var img = $('#image-template').clone().attr("id","img-"+image.id).fadeIn("slow");
484
            img.find("label").attr('for',"img-radio-" + image.id);
485
            img.find(".image-title").text(image.name);
486
            if (image.metadata) {
487
                if (image.metadata.values.description != undefined) {
488
                    img.find(".description").text(image.metadata.values.description);
489
                }
490
                if (image.metadata.values.size != undefined) {
491
                    img.find("#size").text(image.metadata.values.size);
492
                }
493
            }
494
            img.find("input.radio").attr('id',"img-radio-" + image.id);
495
            if (i==0) img.find("input.radio").attr("checked","checked");
496
            var image_logo = os_icon(image.metadata);
497
            img.find("img.image-logo").attr('src','static/icons/os/'+image_logo+'.png');
498
            if (image.metadata) {
499
                if (image.metadata.values.serverId != undefined) {
500
                    img.appendTo("ul#custom-images");
501
                } else {
502
                    img.appendTo("ul#standard-images");
503
                }
504
            } else {
505
                img.appendTo("ul#standard-images");
506
            }
507
        });
508
    }
509
}
510

    
511
function update_wizard_flavors(){
512
    // sliders for selecting VM flavor
513
    $("#cpu:range").rangeinput({min:0,
514
                               value:0,
515
                               step:1,
516
                               progress: true,
517
                               max:cpus.length-1});
518

    
519
    $("#storage:range").rangeinput({min:0,
520
                               value:0,
521
                               step:1,
522
                               progress: true,
523
                               max:disks.length-1});
524

    
525
    $("#ram:range").rangeinput({min:0,
526
                               value:0,
527
                               step:1,
528
                               progress: true,
529
                               max:ram.length-1});
530
    $("#small").click();
531

    
532
    // update the indicators when sliding
533
    $("#cpu:range").data().rangeinput.onSlide(function(event,value){
534
        $("#cpu-indicator")[0].value = cpus[Number(value)];
535
        $("#cpu-indicator").addClass('selectedrange');
536
    });
537
    $("#cpu:range").data().rangeinput.change(function(event,value){
538
        $("#cpu-indicator")[0].value = cpus[Number(value)];
539
        $("#custom").click();
540
        $("#cpu-indicator").removeClass('selectedrange');
541
    });
542
    $("#ram:range").data().rangeinput.onSlide(function(event,value){
543
        $("#ram-indicator")[0].value = ram[Number(value)];
544
        $("#ram-indicator").addClass('selectedrange');
545
    });
546
    $("#ram:range").data().rangeinput.change(function(event,value){
547
        $("#ram-indicator")[0].value = ram[Number(value)];
548
        $("#custom").click();
549
        $("#ram-indicator").removeClass('selectedrange');
550
    });
551
    $("#storage:range").data().rangeinput.onSlide(function(event,value){
552
        $("#storage-indicator")[0].value = disks[Number(value)];
553
        $("#storage-indicator").addClass('selectedrange');
554
    });
555
    $("#storage:range").data().rangeinput.change(function(event,value){
556
        $("#storage-indicator")[0].value = disks[Number(value)];
557
        $("#custom").click();
558
        $("#storage-indicator").removeClass('selectedrange');
559
    });
560
}
561

    
562
Array.prototype.unique = function () {
563
    var r = new Array();
564
    o:for(var i = 0, n = this.length; i < n; i++)
565
    {
566
        for(var x = 0, y = r.length; x < y; x++)
567
        {
568
            if(r[x]==this[i])
569
            {
570
                continue o;
571
            }
572
        }
573
        r[r.length] = this[i];
574
    }
575
    return r;
576
}
577

    
578
// get and configure flavor selection
579
function update_flavors() {
580
    $.ajax({
581
        url: API_URL + '/flavors/detail',
582
        type: "GET",
583
        //async: false,
584
        dataType: "json",
585
        timeout: TIMEOUT,
586
        error: function(jqXHR, textStatus, errorThrown) {
587
            try {
588
                ajax_error(jqXHR.status, undefined, 'Update Flavors', jqXHR.responseText);
589
            } catch (err) {
590
                ajax_error(err);
591
            }
592
            // start updating vm list
593
            update_vms(UPDATE_INTERVAL);
594
        },
595
        success: function(data, textStatus, jqXHR) {
596

    
597
            try {
598
                flavors = data.flavors.values;
599
                jQuery.parseJSON(data);
600
                $.each(flavors, function(i, flavor) {
601
                    cpus[i] = flavor['cpu'];
602
                    disks[i] = flavor['disk'];
603
                    ram[i] = flavor['ram'];
604
                });
605
                cpus = cpus.unique();
606
                disks = disks.unique();
607
                ram = ram.unique();
608
                update_wizard_flavors();
609
            } catch(err){
610
                ajax_error("NO_FLAVORS");
611
            }
612
            // start updating vm list
613
            update_vms(UPDATE_INTERVAL);
614
        }
615
    });
616
    return false;
617
}
618

    
619
// return flavorRef from cpu, disk, ram values
620
function identify_flavor(cpu, disk, ram){
621
    for (i=0;i<flavors.length;i++){
622
        if (flavors[i]['cpu'] == cpu && flavors[i]['disk']==disk && flavors[i]['ram']==ram) {
623
            return flavors[i]['id']
624
        }
625
    }
626
    return 0;
627
}
628

    
629
// return image entry from imageRef
630
function get_image(imageRef) {
631
    for (i=0;i<images.length;i++){
632
        if (images[i]['id'] == imageRef) {
633
            return images[i];
634
        }
635
    }
636
    return 0;
637
}
638

    
639
// return machine entry from serverID
640
function get_machine(serverID) {
641
    for (i=0;i<servers.length;i++){
642
        if (servers[i]['id'] == serverID) {
643
            return servers[i];
644
        }
645
    }
646
    return 0;
647
}
648

    
649
// update the actions in icon view, per server
650
function update_iconview_actions(serverID, server_status) {
651
    if ($.cookie("view")=='2') {
652
        // remove .disable from all actions to begin with
653
        $('#machinesview-single.single #' + serverID + ' div.single-actions').children().show();
654
        // decide which actions should be disabled
655
        for (current_action in actions) {
656
            if (actions[current_action].indexOf(server_status) == -1 ) {
657
                $('#machinesview-single.single #' + serverID + ' div.action-' + current_action).hide();
658
            }
659
        }
660
    } else {
661
        // remove .disable from all actions to begin with
662
        $('#machinesview-icon.standard #' + serverID + ' div.actions').find('a').removeClass('disabled');
663
        // decide which actions should be disabled
664
        for (current_action in actions) {
665
            if (actions[current_action].indexOf(server_status) == -1 ) {
666
                $('#machinesview-icon.standard #' + serverID + ' a.action-' + current_action).addClass('disabled');
667
            }
668
        }
669
    }
670
}
671

    
672
// update the actions in list view
673
function update_listview_actions() {
674
    var states = [];
675
    var on = [];
676
    var checked = $("table.list-machines tbody input[type='checkbox']:checked");
677
    // disable all actions to begin with
678
    $('#machinesview .list div.actions').children().removeClass('enabled');
679

    
680
    // are there multiple machines selected?
681
    if (checked.length>1)
682
        states[0] = 'multiple';
683

    
684
    // check the states of selected machines
685
    checked.each(function(i,checkbox) {
686
        states[states.length] = checkbox.className;
687
        var ip = $("#" + checkbox.id.replace('input-','') + ".ip span.public").text();
688
        if (ip.replace('undefined','').length)
689
            states[states.length] = 'network';
690
    });
691

    
692
    // decide which actions should be enabled
693
    for (a in actions) {
694
        var enabled = false;
695
        for (var s =0; s<states.length; s++) {
696
            if (actions[a].indexOf(states[s]) != -1 ) {
697
                enabled = true;
698
            } else {
699
                enabled = false;
700
                break;
701
            }
702
        }
703
        if (enabled)
704
            on[on.length]=a;
705
    }
706
    // enable those actions
707
    for (action in on) {
708
        $("#action-" + on[action]).addClass('enabled');
709
    }
710
}
711

    
712
//create server action
713
function create_vm(machineName, imageRef, flavorRef){
714
    var image_logo = os_icon(get_image(imageRef).metadata);
715
    var uri = API_URL + '/servers';
716
    var payload = {
717
        "server": {
718
            "name": machineName,
719
            "imageRef": imageRef,
720
            "flavorRef" : flavorRef,
721
            "metadata" : {
722
                "OS" : image_logo
723
            }
724
        }
725
    };
726

    
727
    $.ajax({
728
    url: uri,
729
    type: "POST",
730
    contentType: "application/json",
731
    dataType: "json",
732
    data: JSON.stringify(payload),
733
    timeout: TIMEOUT,
734
    error: function(jqXHR, textStatus, errorThrown) {
735
                ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
736
           },
737
    success: function(data, textStatus, jqXHR) {
738
                if ( jqXHR.status == '202') {
739
                    ajax_success("CREATE_VM_SUCCESS", data.server.adminPass);
740
                } else {
741
                    ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
742
                }
743
            }
744
    });
745
}
746

    
747
// reboot action
748
function reboot(serverIDs){
749
    if (!serverIDs.length){
750
        //ajax_success('DEFAULT');
751
        return false;
752
    }
753
    // ajax post reboot call
754
    var payload = {
755
        "reboot": {"type" : "HARD"}
756
    };
757

    
758
    var serverID = serverIDs.pop();
759

    
760
    $.ajax({
761
        url: API_URL + '/servers/' + serverID + '/action',
762
        type: "POST",
763
        contentType: "application/json",
764
        dataType: "json",
765
        data: JSON.stringify(payload),
766
        timeout: TIMEOUT,
767
        error: function(jqXHR, textStatus, errorThrown) {
768
                    display_failure(jqXHR.status, serverID, 'Reboot', jqXHR.responseText)
769
                },
770
        success: function(data, textStatus, jqXHR) {
771
                    if ( jqXHR.status == '202') {
772
                        try {
773
                            console.info('rebooted ' + serverID);
774
                        } catch(err) {}
775
                        // indicate that the action succeeded
776
                        display_success(serverID);
777
                        // continue with the rest of the servers
778
                        reboot(serverIDs);
779
                    } else {
780
                        ajax_error(jqXHR.status, serverID, 'Reboot', jqXHR.responseText);
781
                    }
782
                }
783
    });
784
    return false;
785
}
786

    
787
// shutdown action
788
function shutdown(serverIDs) {
789
    if (!serverIDs.length){
790
        //ajax_success('DEFAULT');
791
        return false;
792
    }
793
    // ajax post shutdown call
794
    var payload = {
795
        "shutdown": {}
796
    };
797

    
798
    var serverID = serverIDs.pop();
799

    
800
    $.ajax({
801
        url: API_URL + '/servers/' + serverID + '/action',
802
        type: "POST",
803
        contentType: "application/json",
804
        dataType: "json",
805
        data: JSON.stringify(payload),
806
        timeout: TIMEOUT,
807
        error: function(jqXHR, textStatus, errorThrown) {
808
                    display_failure(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText)
809
                    },
810
        success: function(data, textStatus, jqXHR) {
811
                    if ( jqXHR.status == '202') {
812
                        try {
813
                            console.info('suspended ' + serverID);
814
                        } catch(err) {}
815
                        // indicate that the action succeeded
816
                        display_success(serverID);
817
                        // continue with the rest of the servers
818
                        shutdown(serverIDs);
819
                    } else {
820
                        ajax_error(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText);
821
                    }
822
                }
823
    });
824
    return false;
825
}
826

    
827
// destroy action
828
function destroy(serverIDs) {
829
    if (!serverIDs.length){
830
        //ajax_success('DEFAULT');
831
        return false;
832
    }
833
    // ajax post destroy call can have an empty request body
834
    var payload = {};
835

    
836
    var serverID = serverIDs.pop();
837

    
838
    $.ajax({
839
        url: API_URL + '/servers/' + serverID,
840
        type: "DELETE",
841
        contentType: "application/json",
842
        dataType: "json",
843
        data: JSON.stringify(payload),
844
        timeout: TIMEOUT,
845
        error: function(jqXHR, textStatus, errorThrown) {
846
                    display_failure(jqXHR.status, serverID, 'Destroy', jqXHR.responseText)
847
                    },
848
        success: function(data, textStatus, jqXHR) {
849
                    if ( jqXHR.status == '204') {
850
                        try {
851
                            console.info('destroyed ' + serverID);
852
                        } catch (err) {}
853
                        // indicate that the action succeeded
854
                        display_success(serverID);
855
                        // continue with the rest of the servers
856
                        destroy(serverIDs);
857
                    } else {
858
                        ajax_error(jqXHR.status, serverID, 'Destroy', jqXHR.responseText);
859
                    }
860
                }
861
    });
862
    return false;
863
}
864

    
865
// start action
866
function start(serverIDs){
867
    if (!serverIDs.length){
868
        //ajax_success('DEFAULT');
869
        return false;
870
    }
871
    // ajax post start call
872
    var payload = {
873
        "start": {}
874
    };
875

    
876
    var serverID = serverIDs.pop();
877

    
878
    $.ajax({
879
        url: API_URL + '/servers/' + serverID + '/action',
880
        type: "POST",
881
        contentType: "application/json",
882
        dataType: "json",
883
        data: JSON.stringify(payload),
884
        timeout: TIMEOUT,
885
        error: function(jqXHR, textStatus, errorThrown) {
886
                    display_failure(jqXHR.status, serverID, 'Start', jqXHR.responseText)
887
                    },
888
        success: function(data, textStatus, jqXHR) {
889
                    if ( jqXHR.status == '202') {
890
                        try {
891
                            console.info('started ' + serverID);
892
                        } catch(err) {}
893
                        // indicate that the action succeeded
894
                        display_success(serverID);
895
                        // continue with the rest of the servers
896
                        start(serverIDs);
897
                    } else {
898
                        ajax_error(jqXHR.status, serverID, 'Start', jqXHR.responseText);
899
                    }
900
                }
901
    });
902
    return false;
903
}
904

    
905
// Show VNC console
906
function vnc_attachment(host, port, password) {
907
    // FIXME: Must be made into parameters, in settings.py
908
    //vnc = open("", "displayWindow",
909
    //    "status=yes,toolbar=yes,menubar=yes");
910
    vd = document.open("application/x-vnc");
911

    
912
    vd.writeln("[connection]");
913
    vd.writeln("host=" + host);
914
    vd.writeln("port=" + port);
915
    vd.writeln("password=" + password);
916

    
917
    vd.close();
918
}
919

    
920
// Show VNC console
921
function show_vnc_console(serverID, serverName, serverIP, host, port, password) {
922
    var params_url = '?machine=' + serverName + '&host_ip=' + serverIP + '&host=' + host + '&port=' + port + '&password=' + password;
923
    var params_window = 'scrollbars=no,' +
924
                        'menubar=no,' +
925
                        'toolbar=no,' +
926
                        'status=no,' +
927
                        'top=0,' +
928
                        'left=0,' +
929
                        'height=' + screen.height + ',' +
930
                        'width=' + screen.width + ',' +
931
                        'fullscreen=yes';
932

    
933
    window.open('machines/console' + params_url, 'formresult' + serverID, params_window);
934

    
935
    // Restore os icon in list view
936
    osIcon = $('#'+serverID).parent().parent().find('.list-logo');
937
    osIcon.attr('src',osIcon.attr('os'));
938
    return false;
939
}
940

    
941
// console action
942
function open_console(serverIDs){
943
    if (!serverIDs.length){
944
        //ajax_success('DEFAULT');
945
        return false;
946
    }
947
    // ajax post start call
948
    var payload = {
949
        "console": {"type": "vnc"}
950
    };
951

    
952
    var serverID = serverIDs.pop();
953

    
954
    var machine = get_machine(serverID);
955
    var serverName = machine.name;
956
    var serverIP = machine.addresses.values[0].values[0].addr;
957

    
958
    $.ajax({
959
        url: API_URL + '/servers/' + serverID + '/action',
960
        type: "POST",
961
        contentType: "application/json",
962
        dataType: "json",
963
        data: JSON.stringify(payload),
964
        timeout: TIMEOUT,
965
        error: function(jqXHR, textStatus, errorThrown) {
966
                    display_failure(jqXHR.status, serverID, 'Console', jqXHR.responseText)
967
                    },
968
        success: function(data, textStatus, jqXHR) {
969
                    if ( jqXHR.status == '200') {
970
                        try {
971
                            console.info('got_console ' + serverID);
972
                        } catch(err) {}
973
                        // indicate that the action succeeded
974
                        //show_vnc_console(serverID, serverName, serverIP, data.console.host,data.console.port,data.console.password);
975
show_vnc_console(serverID, serverName, serverIP, data.console.host,data.console.port,data.console.password);
976
                        display_success(serverID);
977
                        // hide spinner
978
                        $('#' + serverID + ' .spinner').hide();
979
                        // continue with the rest of the servers
980
                        open_console(serverIDs);
981
                    } else {
982
                        ajax_error(jqXHR.status, serverID, 'Console', jqXHR.responseText);
983
                    }
984
                }
985
    });
986
    return false;
987
}
988

    
989
// rename server
990
function rename(serverID, serverName){
991
    if (!serverID.length){
992
        //ajax_success('DEFAULT');
993
        return false;
994
    }
995
    // ajax post rename call
996
    var payload = {
997
        "server": {"name": serverName}
998
    };
999

    
1000
    $.ajax({
1001
        url: API_URL + '/servers/' + serverID,
1002
        type: "PUT",
1003
        contentType: "application/json",
1004
        dataType: "json",
1005
        data: JSON.stringify(payload),
1006
        timeout: TIMEOUT,
1007
        error: function(jqXHR, textStatus, errorThrown) {
1008
                    display_failure(jqXHR.status, serverID, 'Rename', jqXHR.responseText)
1009
                    },
1010
        success: function(data, textStatus, jqXHR) {
1011
                    if ( jqXHR.status == '204') {
1012
                        try {
1013
                            console.info('renamed ' + serverID);
1014
                        } catch(err) {}
1015
                        // indicate that the action succeeded
1016
                        display_success(serverID);
1017
                    } else {
1018
                        ajax_error(jqXHR.status, serverID, 'Rename', jqXHR.responseText);
1019
                    }
1020
                }
1021
    });
1022
    return false;
1023
}
1024

    
1025
// get server metadata
1026
function get_metadata(serverID, keys_only) {
1027
    $.ajax({
1028
        url: API_URL + '/servers/' + serverID + '/meta',
1029
        type: "GET",
1030
        //async: false,
1031
        dataType: "json",
1032
        timeout: TIMEOUT,
1033
        error: function(jqXHR, textStatus, errorThrown) {
1034
            try {
1035
                ajax_error(jqXHR.status, undefined, 'Get metadata', jqXHR.responseText);
1036
            } catch (err) {
1037
                ajax_error(err);
1038
            }
1039
        },
1040
        success: function(data, textStatus, jqXHR) {
1041
            // to list the new results in the edit dialog
1042
            if (keys_only) {
1043
                list_metadata_keys(serverID, data.metadata.values);
1044
            } else {
1045
                list_metadata(data);
1046
                list_metadata_keys(serverID, data.metadata.values);
1047
            }
1048
            //hide spinner
1049
            $('#metadata-wizard .large-spinner').hide();
1050
        }
1051
    });
1052
    return false;
1053
}
1054

    
1055
// delete metadata key-value pair
1056
function delete_metadata(serverID, meta_key) {
1057
    $.ajax({
1058
        url: API_URL + '/servers/' + serverID + '/meta/' + meta_key,
1059
        type: "DELETE",
1060
        //async: false,
1061
        dataType: "json",
1062
        timeout: TIMEOUT,
1063
        error: function(jqXHR, textStatus, errorThrown) {
1064
            try {
1065
                ajax_error(jqXHR.status, undefined, 'Delete metadata', jqXHR.responseText);
1066
            } catch (err) {
1067
                ajax_error(err);
1068
            }
1069
        },
1070
        success: function(data, textStatus, jqXHR) {
1071
            // success: Do nothing, the UI is already updated
1072
        }
1073
    });
1074
    return false;
1075
}
1076

    
1077
// add metadata key-value pair
1078
function update_metadata(serverID, meta_key, meta_value) {
1079
    var payload = {
1080
        "meta": {
1081
        }
1082
    };
1083
    payload["meta"][meta_key] = meta_value;
1084

    
1085
    $.ajax({
1086
        url: API_URL + '/servers/' + serverID + '/meta/' + meta_key,
1087
        type: "PUT",
1088
        contentType: "application/json",
1089
        dataType: "json",
1090
        data: JSON.stringify(payload),
1091
        timeout: TIMEOUT,
1092
        error: function(jqXHR, textStatus, errorThrown) {
1093
            try {
1094
                ajax_error(jqXHR.status, undefined, 'add metadata', jqXHR.responseText);
1095
            } catch (err) {
1096
                ajax_error(err);
1097
            }
1098
        },
1099
        success: function(data, textStatus, jqXHR) {
1100
            // success: Update icons if meta key is OS
1101
            if (meta_key == "OS") {
1102
                $("#metadata-wizard .machine-icon").attr("src","static/icons/machines/small/" + os_icon_from_value(meta_value) + '-' + $("#metadata-wizard div#on-off").text() + '.png');
1103
                $("#machinesview-icon").find("div#" + serverID).find("img.logo").attr("src", "static/icons/machines/medium/" + os_icon_from_value(meta_value) + '-' + $("#metadata-wizard div#on-off").text() + '.png');
1104
            }
1105
        }
1106
    });
1107
    return false;
1108
}
1109

    
1110
// create network
1111
function create_network(networkName){
1112
    // ajax post start call
1113
    var payload = {
1114
        "network": { "name": networkName }
1115
    };
1116

    
1117
    $.ajax({
1118
        url: API_URL + '/networks',
1119
        type: "POST",
1120
        contentType: "application/json",
1121
        dataType: "json",
1122
        data: JSON.stringify(payload),
1123
        timeout: TIMEOUT,
1124
        error: function(jqXHR, textStatus, errorThrown) {
1125
            try {
1126
                ajax_error(jqXHR.status, undefined, 'Create network', jqXHR.responseText);
1127
            } catch (err) {
1128
                ajax_error(err);
1129
            }
1130
        },
1131
        success: function(data, textStatus, jqXHR) {
1132
            if ( jqXHR.status == '202') {
1133
                try {
1134
                    console.info('created network ' + networkName);
1135
                } catch(err) {}
1136
                // update_networks(UPDATE_INTERVAL);
1137
                // $("a#networkscreate").overlay().close();
1138
            } else {
1139
                ajax_error(jqXHR.status, undefined, 'Create network', jqXHR.responseText);
1140
            }
1141
        }
1142
    });
1143
    return false;
1144
}
1145

    
1146
// rename network
1147
function rename_network(networkID, networkName){
1148
    if (!networkID.length){
1149
        //ajax_success('DEFAULT');
1150
        return false;
1151
    }
1152
    // prepare payload
1153
    var payload = {
1154
        "network": {"name": networkName}
1155
    };
1156
    // ajax call
1157
    $.ajax({
1158
        url: API_URL + '/networks/' + networkID,
1159
        type: "PUT",
1160
        contentType: "application/json",
1161
        dataType: "json",
1162
        data: JSON.stringify(payload),
1163
        timeout: TIMEOUT,
1164
        error: function(jqXHR, textStatus, errorThrown) {
1165
            try {
1166
                ajax_error(jqXHR.status, undefined, 'Rename network', jqXHR.responseText);
1167
            } catch (err) {
1168
                ajax_error(err);
1169
            }
1170
        },
1171
        success: function(data, textStatus, jqXHR) {
1172
            if ( jqXHR.status == '204') {
1173
                try {
1174
                    console.info('renamed network' + networkID);
1175
                } catch(err) {}
1176
            } else {
1177
                ajax_error(jqXHR.status, undefined, 'Rename network', jqXHR.responseText);
1178
            }
1179
        }
1180
    });
1181
    return false;
1182
}
1183

    
1184
function delete_network(networkIDs){
1185
    if (!networkIDs.length){
1186
        //ajax_success('DEFAULT');
1187
        return false;
1188
    }
1189
    // get a network
1190
    var networkID = networkIDs.pop();
1191
    // ajax post destroy call can have an empty request body
1192
    var payload = {};
1193
    // ajax call
1194
    $.ajax({
1195
        url: API_URL + '/networks/' + networkID,
1196
        type: "DELETE",
1197
        contentType: "application/json",
1198
        dataType: "json",
1199
        data: JSON.stringify(payload),
1200
        timeout: TIMEOUT,
1201
        error: function(jqXHR, textStatus, errorThrown) {
1202
            try {
1203
                display_failure(jqXHR.status, networkID, 'Delete', jqXHR.responseText)
1204
            } catch (err) {
1205
                ajax_error(err);
1206
            }
1207
        },
1208
        success: function(data, textStatus, jqXHR) {
1209
            if ( jqXHR.status == '204') {
1210
                try {
1211
                    console.info('deleted network ' + networkID);
1212
                } catch(err) {}
1213
                // continue with the rest of the servers
1214
                delete_network(networkIDs);
1215
            } else {
1216
                ajax_error(jqXHR.status, undefined, 'Delete network', jqXHR.responseText);
1217
            }
1218
        }
1219
    });
1220
    return false;
1221
}
1222

    
1223
function add_server_to_network(networkID, serverIDs) {
1224
    if (!serverIDs.length){
1225
        //ajax_success('DEFAULT');
1226
        //update_networks(UPDATE_INTERVAL);
1227
        //$("a#add-machines-overlay").overlay().close();
1228
        return false;
1229
    }
1230
    // get a server
1231
    var serverID = serverIDs.pop();
1232
    // prepare payload
1233
    var payload = {
1234
            "add": { "serverRef": serverID }
1235
        };
1236
    // prepare ajax call
1237
    $.ajax({
1238
        url: API_URL + '/networks/' + networkID + '/action',
1239
        type: "POST",
1240
        contentType: "application/json",
1241
        dataType: "json",
1242
        data: JSON.stringify(payload),
1243
        timeout: TIMEOUT,
1244
        error: function(jqXHR, textStatus, errorThrown) {
1245
            try {
1246
                ajax_error(jqXHR.status, undefined, 'Add server to network', jqXHR.responseText);
1247
            } catch (err) {
1248
                ajax_error(err);
1249
            }
1250
        },
1251
        success: function(data, textStatus, jqXHR) {
1252
            if ( jqXHR.status == '202') {
1253
                try {
1254
                    console.info('added server ' + serverID + ' to network ' + networkID);
1255
                } catch(err) {}
1256
                // continue with the rest of the servers
1257
                add_server_to_network(networkID, serverIDs);
1258
            } else {
1259
                ajax_error(jqXHR.status, undefined, 'Add server to network', jqXHR.responseText);
1260
            }
1261
        }
1262
    });
1263
    return false;
1264
}
1265

    
1266
function remove_server_from_network(networkIDs, serverIDs) {
1267
    if (!networkIDs.length){
1268
        //ajax_success('DEFAULT');
1269
        return false;
1270
    }
1271
    // get a network and a server
1272
    var networkID = networkIDs.pop();
1273
    var serverID = serverIDs.pop();
1274
    // prepare payload
1275
    var payload = {
1276
            "remove": { "serverRef": serverID }
1277
        };
1278
    // prepare ajax call
1279
    $.ajax({
1280
        url: API_URL + '/networks/' + networkID + '/action',
1281
        type: "POST",
1282
        contentType: "application/json",
1283
        dataType: "json",
1284
        data: JSON.stringify(payload),
1285
        timeout: TIMEOUT,
1286
        error: function(jqXHR, textStatus, errorThrown) {
1287
            try {
1288
                ajax_error(jqXHR.status, undefined, 'Remove server form network', jqXHR.responseText);
1289
            } catch (err) {
1290
                ajax_error(err);
1291
            }
1292
        },
1293
        success: function(data, textStatus, jqXHR) {
1294
            if ( jqXHR.status == '202') {
1295
                try {
1296
                    console.info('deleted server ' + serverID + ' from network ' + networkID);
1297
                } catch(err) {}
1298
                // remove it from DOM
1299
                $('#net-' + networkID + '-server-' + serverID).fadeOut('slow').remove();
1300
                // continue with the rest of the servers
1301
                remove_server_form_network(networkIDs, serverIDs);
1302
            } else {
1303
                ajax_error(jqXHR.status, undefined, 'Remove server form network', jqXHR.responseText);
1304
            }
1305
        }
1306
    });
1307
    return false;
1308
}
1309

    
1310
// show the welcome screen
1311
function showWelcome() {
1312
    $("#view-select").fadeOut("fast");
1313
    $("#emptymachineslist").fadeIn("fast");
1314
    $("#machinesview").hide();
1315
}
1316

    
1317
// hide the welcome screen
1318
function hideWelcome() {
1319
    $("#emptymachineslist").fadeOut("fast");
1320
    $("#view-select").fadeIn("fast");
1321
    $("div#view-select").show();
1322
    $("#machinesview").show();
1323
}
1324

    
1325
function log_server_status_change(server_entry, new_status) {
1326
    // firebug console logging
1327
    try {
1328
        if ($("#machinesview-single").length > 0) {
1329
            console.info(server_entry.find("div.machine-details div.name").text() +
1330
                        ' from ' + server_entry.find(".state-label").text() +
1331
                        ' to ' + STATUSES[new_status]);
1332
        } else {
1333
            console.info(server_entry.find("div.name span.name").text() +
1334
                        ' from ' + server_entry.find(".status").text() +
1335
                        ' to ' + STATUSES[new_status]);
1336
        }
1337
    } catch(err) {}
1338
}
1339

    
1340
function get_flavor_params(flavorRef) {
1341
    var cpus, ram, disk;
1342
    if ( flavors.length > 0 ) {
1343
        var current_flavor = '';
1344
        for (i=0; i<flavors.length; i++) {
1345
            if (flavors[i]['id'] == flavorRef) {
1346
                current_flavor = flavors[i];
1347
            }
1348
        }
1349
        cpus = current_flavor['cpu'];
1350
        ram = current_flavor['ram'];
1351
        disk = current_flavor['disk'];
1352
    } else {
1353
        cpus = 'undefined';
1354
        ram = 'undefined';
1355
        disk = 'undefined';
1356
    }
1357
    return {'cpus': cpus, 'ram': ram, 'disk': disk};
1358
}
1359

    
1360
function get_image_params(imageRef) {
1361
    var image_name, image_size;
1362
    if ( images.length > 0 ) {
1363
        var current_image = '';
1364
        for (i=0; i<images.length; i++) {
1365
            if (images[i]['id'] == imageRef) {
1366
                current_image = images[i];
1367
            }
1368
        }
1369
        try {
1370
            image_name = current_image['name'];
1371
        } catch(err) { image_name = 'undefined'; }
1372
        try{
1373
            image_size = current_image['metadata']['values']['size'];
1374
        } catch(err) { image_size = 'undefined'; }
1375
    } else {
1376
        image_name = 'undefined';
1377
        image_size = 'undefined';
1378
    }
1379
    return {'name': image_name,'size': image_size};
1380
}
1381

    
1382
function get_public_ips(server) {
1383
    var ip4, ip6;
1384
    try {
1385
        if (server.addresses.values) {
1386
            $.each (server.addresses.values, function(i, value) {
1387
                if (value.id == 'public') {
1388
                    try {
1389
                        $.each (value.values, function(i, ip) {
1390
                            if (ip.version == '4') {
1391
                                ip4 = ip.addr;
1392
                            } else if (ip.version == '6') {
1393
                                ip6 = ip.addr;
1394
                            } else {
1395
                                ip4 = 'undefined';
1396
                                ip6 = 'undefined';
1397
                            }
1398
                        });
1399
                    } catch (err){
1400
                        try{console.info('Server ' + server.id + ' has invalid ips')}catch(err){};
1401
                        ip4 = 'undefined';
1402
                        ip6 = 'undefined';
1403
                    }
1404
                }
1405
            });
1406
        }
1407
    } catch (err) {
1408
        try{console.info('Server ' + server.id + ' has no network addresses')}catch(err){};
1409
        ip4 = 'undefined';
1410
        ip6 = 'undefined';
1411
    }
1412
    return {'ip4': ip4, 'ip6': ip6};
1413
}
1414

    
1415
function get_private_ips(server) {
1416

    
1417
}