Statistics
| Branch: | Tag: | Revision:

root / ui / static / synnefo.js @ e6561111

History | View | Annotate | Download (26.1 kB)

1
var flavors = [], images = [], servers = [], disks = [], cpus = [], ram = [];
2
var changes_since = 0, deferred = 0, update_request = false, load_request = false, pending_actions = [];
3
var API_URL = "/api/v1.1";
4

    
5
function ISODateString(d){
6
    //return a date in an ISO 8601 format using UTC.
7
    //do not include time zone info (Z) at the end
8
    //taken from the Mozilla Developer Center
9
    function pad(n){ return n<10 ? '0'+n : n }
10
    return  d.getUTCFullYear()+ '-' +
11
                        pad(d.getUTCMonth()+1) + '-' +
12
                        pad(d.getUTCDate()) + 'T' +
13
                        pad(d.getUTCHours()) + ':' +
14
                        pad(d.getUTCMinutes()) + ':' +
15
                        pad(d.getUTCSeconds()) +'Z'
16
}
17

    
18

    
19
function parse_error(responseText){
20
        var errors = [];
21
        if (responseText.length == 0){
22
                errors[0] = {'code': 0};
23
        } else {
24
                responseObj = JSON.parse(responseText);
25
                //console.info(inp);
26
                for (var err in responseObj){
27
                        errors[errors.length] = responseObj[err];
28
                }
29
        }
30
        return errors;
31
}
32

    
33
// indexOf prototype for IE
34
if (!Array.prototype.indexOf) {
35
  Array.prototype.indexOf = function(elt /*, from*/) {
36
    var len = this.length;
37
    var from = Number(arguments[1]) || 0;
38
    from = (from < 0)
39
         ? Math.ceil(from)
40
         : Math.floor(from);
41
    if (from < 0)
42
      from += len;
43

    
44
    for (; from < len; from++) {
45
      if (from in this &&
46
          this[from] === elt)
47
        return from;
48
    }
49
    return -1;
50
  };
51
}
52

    
53

    
54
function update_confirmations(){
55
    // hide all confirm boxes to begin with
56
    $('div.confirm_single').hide();
57
    $('div.confirm_multiple').hide();
58

    
59
        // standard view only
60
        if ($.cookie("list") != '1') {
61
                for (var i=0;i<pending_actions.length;i++){
62
            // show single confirms
63
                        $("div.machine-container#"+pending_actions[i][1]+' .confirm_single').show();
64
                }                
65
        }
66

    
67
        // if more than one pending action show multiple confirm box
68
        if (pending_actions.length>1 || $.cookie("list") == '1' && pending_actions.length == 1){
69
                $('div.confirm_multiple span.actionLen').text(pending_actions.length);
70
                $('div.confirm_multiple').show();
71
        }
72
}
73

    
74
function list_view() {
75
        changes_since = 0; // to reload full list
76
        pending_actions = []; // clear pending actions
77
        update_confirmations();
78
        clearTimeout(deferred);        // clear old deferred calls
79
        try {
80
                update_request.abort(); // cancel pending ajax updates
81
                load_request.abort();
82
        }catch(err){}
83
    $.cookie("list", '1'); // set list cookie
84
        
85
        uri = $("#list").attr("href");
86
    load_request = $.ajax({
87
        url: uri,
88
        type: "GET",
89
        timeout: TIMEOUT,
90
        dataType: "html",
91
        error: function(jqXHR, textStatus, errorThrown) {                                                
92
                        return false;
93
                },
94
        success: function(data, textStatus, jqXHR) {
95
                        $("a#list")[0].className += ' activelink';
96
                        $("a#standard")[0].className = '';
97
                        $("div#machinesview").html(data);
98
                }
99
        });
100

    
101
    return false;
102
}
103

    
104
function standard_view() {
105
        changes_since = 0; // to reload full list
106
        pending_actions = []; // clear pending actions
107
        update_confirmations();
108
        clearTimeout(deferred);        // clear old deferred calls
109
        try {
110
                update_request.abort() // cancel pending ajax updates
111
                load_request.abort();
112
        }catch(err){}        
113
    $.cookie("list", '0');
114
        
115
    uri = $("a#standard").attr("href");
116
    load_request = $.ajax({
117
        url: uri,
118
        type: "GET",
119
        timeout: TIMEOUT,
120
        dataType: "html",
121
        error: function(jqXHR, textStatus, errorThrown) {                                                
122
                        return false;
123
                },
124
        success: function(data, textStatus, jqXHR) {
125
                        $("a#standard")[0].className += ' activelink';
126
                        $("a#list")[0].className = '';
127
                        $("div#machinesview").html(data);
128
                }
129
        });        
130

    
131
    return false;
132
}
133

    
134
function choose_view() {
135
    if ($.cookie("list")=='1') {
136
        list_view();
137
    } else {
138
        standard_view();
139
    }
140
}
141

    
142
function toggleMenu() {
143
    var primary = $("ul.css-tabs li a.primary");
144
    var secondary = $("ul.css-tabs li a.secondary");
145
    var all = $("ul.css-tabs li a");                        
146
    var toggled = $('ul.css-tabs li a.current').hasClass('secondary');
147

    
148
    // if anything is still moving, do nothing
149
    if ($(":animated").length) {
150
        return;
151
    }
152

    
153
    // nothing is current to begin with
154
    $('ul.css-tabs li a.current').removeClass('current');
155

    
156
    // move stuff around
157
    all.animate({top:'30px'}, {complete: function() {
158
        $(this).hide();
159
        if (toggled) {
160
            primary.show();
161
            primary.animate({top:'9px'}, {complete: function() {
162
                $('ul.css-tabs li a.primary#machines').addClass('current');
163
                $('a#machines').click();                                   
164
            }});
165
        } else {
166
            secondary.show();
167
            secondary.animate({top:'9px'}, {complete: function() {
168
                $('ul.css-tabs li a.secondary#files').addClass('current');
169
                $('a#files').click();                                                                           
170
            }});
171
        }
172
    }});
173

    
174
    // rotate arrow icon
175
    if (toggled) {
176
        $("#arrow").rotate({animateAngle: (0), bind:[{"click":function(){toggleMenu()}}]});
177
        $("#arrow").rotateAnimation(0);                    
178
    } else {
179
        $("#arrow").rotate({animateAngle: (-180), bind:[{"click":function(){toggleMenu()}}]});
180
        $("#arrow").rotateAnimation(-180);
181
    }
182
}
183

    
184
// confirmation overlay generation
185
function confirm_action(action_string, action_function, serverIDs, serverNames) {
186
    if (serverIDs.length == 1){
187
        $("#yes-no h3").text('You are about to ' + action_string + ' vm ' + serverNames[0]);
188
    } else if (serverIDs.length > 1){
189
        $("#yes-no h3").text('You are about to ' + action_string + ' ' + serverIDs.length + ' machines');
190
    } else {
191
        return false;
192
    }
193
    // action confirmation overlay
194
    var triggers = $("a#confirmation").overlay({
195
            // some mask tweaks suitable for modal dialogs
196
            mask: {
197
                    color: '#ebecff',
198
                    opacity: '0.9'
199
            },
200
        top: 'center',
201
        load: false
202
    });
203
    // yes or no?
204
    var buttons = $("#yes-no button").click(function(e) {
205
            // get user input
206
            var yes = buttons.index(this) === 0;
207
        //close the confirmation window
208
        $("a#confirmation").overlay().close();
209
        // return true=yes or false=no
210
        if (yes) {
211
            action_function(serverIDs);
212
        }
213
    });
214
    $("a#confirmation").data('overlay').load();
215
    return false;
216
}
217

    
218
// get and show a list of running and terminated machines
219
function update_vms(interval) {
220
    try{ console.info('updating machines'); } catch(err){}
221
        var uri= API_URL + '/servers/detail';
222

    
223
        if (changes_since != 0)
224
                uri+='?changes-since='+changes_since
225
                
226
    update_request = $.ajax({
227
        url: uri,
228
        type: "GET",
229
        timeout: TIMEOUT,
230
        dataType: "json",
231
        error: function(jqXHR, textStatus, errorThrown) {
232
                        // don't forget to try again later
233
                        if (interval) {
234
                                clearTimeout(deferred);        // clear old deferred calls
235
                                deferred = setTimeout(update_vms,interval,interval);
236
                        }
237
                        // as for now, just show an error message
238
                        try { console.info('update_vms errback:' + jqXHR.status ) } catch(err) {}
239
                        ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);                                                
240
                        return false;
241
                        },
242
        success: function(data, textStatus, jqXHR) {
243
            var contentText = $.ajax({
244
                url: "/datetime",
245
                async: false
246
            }).responseText;
247
            // create changes_since string if necessary
248
            if (jqXHR.getResponseHeader('Date') != null){
249
                            changes_since_date = new Date(jqXHR.getResponseHeader('Date'));
250
                            changes_since = ISODateString(changes_since_date);
251
            }
252

    
253
                        if (interval) {
254
                                clearTimeout(deferred);        // clear old deferred calls
255
                                deferred = setTimeout(update_vms,interval,interval);
256
                        }
257
                        
258
                        if (jqXHR.status == 200 || jqXHR.status == 203) {
259
                                try {
260
                                        servers = data.servers.values;
261
                                } catch(err) { ajax_error('400', undefined, 'Update VMs', jqXHR.responseText);}
262
                                update_machines_view(data);
263
                        } else if (jqXHR.status != 304){
264
                                try { console.info('update_vms callback:' + jqXHR.status ) } catch(err) {}
265
                                //ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);                                        
266
                        }
267
                        return false;
268
        }
269
    });
270
    return false;
271
}
272

    
273
// get and show a list of available standard and custom images
274
function update_images() {
275
    $.ajax({
276
        url: API_URL + '/images/detail',
277
        type: "GET",
278
        //async: false,
279
        dataType: "json",
280
        timeout: TIMEOUT,
281
        error: function(jqXHR, textStatus, errorThrown) {
282
                    ajax_error(jqXHR.status, undefined, 'Update Images', jqXHR.responseText);
283
                    },
284
        success: function(data, textStatus, jqXHR) {
285
            try {
286
                                images = data.images.values;
287
                                update_wizard_images();
288
                        } catch(err){
289
                                ajax_error("NO_IMAGES");
290
                        }
291
        }
292
    });
293
    return false;
294
}
295

    
296
function update_wizard_images() {
297
        if ($("ul#standard-images li").toArray().length + $("ul#custom-images li").toArray().length == 0) {
298
                $.each(images, function(i,image){
299
                        var img = $('#image-template').clone().attr("id","img-"+image.id).fadeIn("slow");
300
                        img.find("label").attr('for',"img-radio-" + image.id);
301
                        img.find(".image-title").text(image.name);
302
            if (image.metadata) {
303
                if (image.metadata.values.description != undefined) {
304
                    img.find(".description").text(image.metadata.values.description);
305
                }
306
                if (image.metadata.values.size != undefined) {
307
                                img.find("#size").text(image.metadata.values.size);
308
                }
309
            }
310
                        img.find("input.radio").attr('id',"img-radio-" + image.id);
311
                        if (i==0) img.find("input.radio").attr("checked","checked");
312
            var image_logo = os_icon(image.metadata);
313
                        img.find("img.image-logo").attr('src','static/os_logos/'+image_logo+'.png');
314
            if (image.metadata) {
315
                if (image.metadata.values.serverId != undefined) {
316
                    img.appendTo("ul#custom-images");
317
                } else {
318
                    img.appendTo("ul#standard-images");
319
                }
320
            } else {
321
                img.appendTo("ul#standard-images");
322
            }
323
                });
324
        }        
325
}
326

    
327
function update_wizard_flavors(){
328
        // sliders for selecting VM flavor
329
        $("#cpu:range").rangeinput({min:0,
330
                                                           value:0,
331
                                                           step:1,
332
                                                           progress: true,
333
                                                           max:cpus.length-1});
334
        
335
        $("#storage:range").rangeinput({min:0,
336
                                                           value:0,
337
                                                           step:1,
338
                                                           progress: true,
339
                                                           max:disks.length-1});
340

    
341
        $("#ram:range").rangeinput({min:0,
342
                                                           value:0,
343
                                                           step:1,
344
                                                           progress: true,
345
                                                           max:ram.length-1});
346
        $("#small").click();
347

    
348
        // update the indicators when sliding
349
        $("#cpu:range").data().rangeinput.onSlide(function(event,value){
350
                $("#cpu-indicator")[0].value = cpus[Number(value)];
351
        $("#cpu-indicator").addClass('selectedrange');
352
        });
353
        $("#cpu:range").data().rangeinput.change(function(event,value){
354
                $("#cpu-indicator")[0].value = cpus[Number(value)];                                
355
                $("#custom").click();
356
        $("#cpu-indicator").removeClass('selectedrange');                
357
        });                        
358
        $("#ram:range").data().rangeinput.onSlide(function(event,value){
359
                $("#ram-indicator")[0].value = ram[Number(value)];
360
        $("#ram-indicator").addClass('selectedrange');
361
        });
362
        $("#ram:range").data().rangeinput.change(function(event,value){
363
                $("#ram-indicator")[0].value = ram[Number(value)];                                
364
                $("#custom").click();
365
        $("#ram-indicator").removeClass('selectedrange');                
366
        });                        
367
        $("#storage:range").data().rangeinput.onSlide(function(event,value){
368
                $("#storage-indicator")[0].value = disks[Number(value)];
369
        $("#storage-indicator").addClass('selectedrange');
370
        });
371
        $("#storage:range").data().rangeinput.change(function(event,value){
372
                $("#storage-indicator")[0].value = disks[Number(value)];                                
373
                $("#custom").click();
374
        $("#storage-indicator").removeClass('selectedrange');                
375
        });                                
376
}
377

    
378
Array.prototype.unique = function () {
379
        var r = new Array();
380
        o:for(var i = 0, n = this.length; i < n; i++)
381
        {
382
                for(var x = 0, y = r.length; x < y; x++)
383
                {
384
                        if(r[x]==this[i])
385
                        {
386
                                continue o;
387
                        }
388
                }
389
                r[r.length] = this[i];
390
        }
391
        return r;
392
}
393

    
394
// get and configure flavor selection
395
function update_flavors() {
396
    $.ajax({
397
        url: API_URL + '/flavors/detail',
398
        type: "GET",
399
        //async: false,
400
        dataType: "json",
401
        timeout: TIMEOUT,
402
        error: function(jqXHR, textStatus, errorThrown) {
403
            try {
404
                                ajax_error(jqXHR.status, undefined, 'Update Flavors', jqXHR.responseText);
405
                        } catch (err) {
406
                                ajax_error(err);
407
                        }
408
            // start updating vm list
409
            update_vms(UPDATE_INTERVAL);
410
        },
411
        success: function(data, textStatus, jqXHR) {
412
            flavors = data.flavors.values;
413
            $.each(flavors, function(i, flavor) {
414
                cpus[i] = flavor['cpu'];
415
                disks[i] = flavor['disk'];
416
                ram[i] = flavor['ram'];
417
            });
418
            cpus = cpus.unique();
419
            disks = disks.unique();
420
            ram = ram.unique();
421
                        update_wizard_flavors();
422
            // start updating vm list
423
            update_vms(UPDATE_INTERVAL);
424
        }
425
    });
426
    return false;
427
}
428

    
429
// return flavorRef from cpu, disk, ram values
430
function identify_flavor(cpu, disk, ram){
431
    for (i=0;i<flavors.length;i++){
432
        if (flavors[i]['cpu'] == cpu && flavors[i]['disk']==disk && flavors[i]['ram']==ram) {
433
            return flavors[i]['id']
434
        }
435
    }
436
    return 0;
437
}
438

    
439
// return image entry from imageRef
440
function get_image(imageRef) {
441
    for (i=0;i<images.length;i++){
442
        if (images[i]['id'] == imageRef) {
443
            return images[i];
444
        }
445
    }
446
    return 0;
447
}
448

    
449
// update the actions in list view
450
function updateActions() {
451
        var states = [];
452
        var on = [];
453
        var checked = $("table.list-machines tbody input[type='checkbox']:checked");
454
        // disable all actions to begin with
455
        for (action in actions) {
456
                $("#action-" + action).removeClass('enabled');
457
        }
458

    
459
        // are there multiple machines selected?
460
        if (checked.length>1)
461
                states[0] = 'multiple';
462
        
463
        // check the states of selected machines
464
        checked.each(function(i,checkbox) {
465
                states[states.length] = checkbox.className;
466
                var ip = $("#" + checkbox.id.replace('input-','') + ".ip span.public").text();
467
                if (ip.replace('undefined','').length)
468
                        states[states.length] = 'network';
469
        });
470

    
471
        // decide which actions should be enabled
472
        for (a in actions) {
473
                var enabled = false;
474
                for (var s =0; s<states.length; s++) {
475
                        if (actions[a].indexOf(states[s]) != -1 ) {
476
                                enabled = true;
477
                        } else {
478
                                enabled = false;
479
                                break;
480
                        }
481
                }
482
                if (enabled)
483
                        on[on.length]=a;
484
        }
485
        // enable those actions
486
        for (action in on) {
487
                $("#action-" + on[action]).addClass('enabled');
488
        }
489
}
490

    
491
//create server action
492
function create_vm(machineName, imageRef, flavorRef){
493

    
494
    var image_logo = os_icon(get_image(imageRef).metadata);
495

    
496
    var payload = {
497
        "server": {
498
            "name": machineName,
499
            "imageRef": imageRef,
500
            "flavorRef" : flavorRef,
501
            "metadata" : {
502
                "OS" : image_logo
503
            }
504
        }
505
    };
506
        var uri = API_URL + '/servers';
507

    
508
    $.ajax({
509
    url: uri,
510
    type: "POST",
511
        contentType: "application/json",
512
    dataType: "json",
513
    data: JSON.stringify(payload),
514
    timeout: TIMEOUT,
515
    error: function(jqXHR, textStatus, errorThrown) {
516
                ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
517
           },
518
    success: function(data, textStatus, jqXHR) {
519
                if ( jqXHR.status == '202') {
520
                    ajax_success("CREATE_VM_SUCCESS", data.server.adminPass);
521
                } else {
522
                    ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
523
                }
524
            }
525
    });
526
}
527

    
528
// reboot action
529
function reboot(serverIDs){
530
        if (!serverIDs.length){
531
                //ajax_success('DEFAULT');
532
                return false;
533
        }        
534
    // ajax post reboot call
535
    var payload = {
536
        "reboot": {"type" : "HARD"}
537
    };
538
    var serverID = serverIDs.pop();
539
        
540
        $.ajax({
541
                url: API_URL + '/servers/' + serverID + '/action',
542
                type: "POST",
543
                contentType: "application/json",
544
                dataType: "json",
545
                data: JSON.stringify(payload),
546
                timeout: TIMEOUT,
547
                error: function(jqXHR, textStatus, errorThrown) {
548
                    display_failure(jqXHR.status, serverID, 'Reboot', jqXHR.responseText)
549
                                },
550
                success: function(data, textStatus, jqXHR) {
551
                                        if ( jqXHR.status == '202') {
552
                        try {
553
                            console.info('rebooted ' + serverID);
554
                        } catch(err) {}
555
                                                // indicate that the action succeeded
556
                                                display_success(serverID);
557
                                                // continue with the rest of the servers
558
                                                reboot(serverIDs);
559
                                        } else {
560
                                                ajax_error(jqXHR.status, serverID, 'Reboot', jqXHR.responseText);
561
                                        }
562
                                }
563
    });
564

    
565
    return false;
566
}
567

    
568
// shutdown action
569
function shutdown(serverIDs) {
570
        if (!serverIDs.length){
571
                //ajax_success('DEFAULT');
572
                return false;
573
        }
574
    // ajax post shutdown call
575
    var payload = {
576
        "shutdown": {}
577
    };
578

    
579
        var serverID = serverIDs.pop()
580
    $.ajax({
581
            url: API_URL + '/servers/' + serverID + '/action',
582
            type: "POST",
583
                contentType: "application/json",
584
            dataType: "json",
585
        data: JSON.stringify(payload),
586
        timeout: TIMEOUT,
587
        error: function(jqXHR, textStatus, errorThrown) {
588
                    display_failure(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText)
589
                    },
590
        success: function(data, textStatus, jqXHR) {
591
                    if ( jqXHR.status == '202') {
592
                                                try {
593
                            console.info('suspended ' + serverID);
594
                        } catch(err) {}
595
                                                // indicate that the action succeeded
596
                                                display_success(serverID);
597
                                                // continue with the rest of the servers
598
                        shutdown(serverIDs);
599
                    } else {
600
                        ajax_error(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText);
601
                    }
602
                }
603
    });
604

    
605
    return false;
606
}
607

    
608
// destroy action
609
function destroy(serverIDs) {
610
        if (!serverIDs.length){
611
                //ajax_success('DEFAULT');
612
                return false;
613
        }
614
    // ajax post destroy call can have an empty request body
615
    var payload = {};
616

    
617
        serverID = serverIDs.pop()
618
    $.ajax({
619
            url: API_URL + '/servers/' + serverID,
620
            type: "DELETE",
621
                contentType: "application/json",
622
            dataType: "json",
623
        data: JSON.stringify(payload),
624
        timeout: TIMEOUT,
625
        error: function(jqXHR, textStatus, errorThrown) {
626
                    display_failure(jqXHR.status, serverID, 'Destroy', jqXHR.responseText)
627
                    },
628
        success: function(data, textStatus, jqXHR) {
629
                    if ( jqXHR.status == '204') {
630
                                                try {
631
                            console.info('destroyed ' + serverID);
632
                        } catch (err) {}
633
                                                // indicate that the action succeeded
634
                                                display_success(serverID);
635
                                                // continue with the rest of the servers
636
                        destroy(serverIDs);
637
                    } else {
638
                        ajax_error(jqXHR.status, serverID, 'Destroy', jqXHR.responseText);
639
                    }
640
                }
641
    });
642

    
643
    return false;
644
}
645

    
646
// start action
647
function start(serverIDs){
648
        if (!serverIDs.length){
649
                //ajax_success('DEFAULT');
650
                return false;
651
        }        
652
    // ajax post start call
653
    var payload = {
654
        "start": {}
655
    };
656

    
657
        var serverID = serverIDs.pop()
658
    $.ajax({
659
        url: API_URL + '/servers/' + serverID + '/action',
660
        type: "POST",
661
                contentType: "application/json",
662
        dataType: "json",
663
        data: JSON.stringify(payload),
664
        timeout: TIMEOUT,
665
        error: function(jqXHR, textStatus, errorThrown) {
666
                    display_failure(jqXHR.status, serverID, 'Start', jqXHR.responseText)
667
                    },
668
        success: function(data, textStatus, jqXHR) {
669
                    if ( jqXHR.status == '202') {
670
                                            try {
671
                            console.info('started ' + serverID);
672
                        } catch(err) {}
673
                                                // indicate that the action succeeded
674
                                                display_success(serverID);
675
                                                // continue with the rest of the servers                                                
676
                        start(serverIDs);
677
                    } else {
678
                        ajax_error(jqXHR.status, serverID, 'Start', jqXHR.responseText);
679
                    }
680
                }
681
    });
682

    
683
    return false;
684
}
685

    
686
// Show VNC console
687
function vnc_attachment(host, port, password) {
688
    // FIXME: Must be made into parameters, in settings.py
689
    //vnc = open("", "displayWindow",
690
    //    "status=yes,toolbar=yes,menubar=yes");
691
    vd = document.open("application/x-vnc");
692

    
693
    vd.writeln("[connection]");
694
    vd.writeln("host=" + host);
695
    vd.writeln("port=" + port);
696
    vd.writeln("password=" + password);
697

    
698
    vd.close();
699
}
700

    
701

    
702
// Show VNC console
703
function show_vnc_console(host, port, password) {
704
    // FIXME: Must be made into parameters, in settings.py
705

    
706
    var params_url = '?host=' + host + '&port=' + port + '&password=' + password ;
707

    
708
    window.open('/machines/console' + params_url, 'formresult', 'scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');
709

    
710
    return false;
711
}
712

    
713

    
714
// console action
715
function open_console(serverIDs){
716
        if (!serverIDs.length){
717
                //ajax_success('DEFAULT');
718
                return false;
719
        }
720
    // ajax post start call
721
    var payload = {
722
        "console": {"type": "vnc"}
723
    };
724

    
725
        var serverID = serverIDs.pop()
726
    $.ajax({
727
        url: API_URL + '/servers/' + serverID + '/action',
728
        type: "POST",
729
                contentType: "application/json",
730
        dataType: "json",
731
        data: JSON.stringify(payload),
732
        timeout: TIMEOUT,
733
        error: function(jqXHR, textStatus, errorThrown) {
734
                    display_failure(jqXHR.status, serverID, 'Console', jqXHR.responseText)
735
                    },
736
        success: function(data, textStatus, jqXHR) {
737
                    if ( jqXHR.status == '200') {
738
                                            try {
739
                            console.info('got_console ' + serverID);
740
                        } catch(err) {}
741
                                                // indicate that the action succeeded
742
                        show_vnc_console(data.console.host,data.console.port,data.console.password);
743
                                                display_success(serverID);
744
                        // hide spinner
745
                        $('#' + serverID + ' .spinner').hide();
746
                                                // continue with the rest of the servers
747
                        open_console(serverIDs);
748
                    } else {
749
                        ajax_error(jqXHR.status, serverID, 'Console', jqXHR.responseText);
750
                    }
751
                }
752
    });
753
    return false;
754
}
755

    
756

    
757
// rename server name action
758
function rename(serverID, serverName){
759
        if (!serverID.length){
760
                //ajax_success('DEFAULT');
761
                return false;
762
        }        
763
    // ajax post rename call
764
    var payload = {
765
        "server": {"name": serverName}
766
    };
767

    
768
    $.ajax({
769
        url: API_URL + '/servers/' + serverID,
770
        type: "PUT",
771
                contentType: "application/json",
772
        dataType: "json",
773
        data: JSON.stringify(payload),
774
        timeout: TIMEOUT,
775
        error: function(jqXHR, textStatus, errorThrown) {
776
                    display_failure(jqXHR.status, serverID, 'Rename', jqXHR.responseText)
777
                    },
778
        success: function(data, textStatus, jqXHR) {
779
                    if ( jqXHR.status == '204') {
780
                                            try {
781
                            console.info('renamed ' + serverID);
782
                        } catch(err) {}
783
                                                // indicate that the action succeeded
784
                                                display_success(serverID);
785
                    } else {
786
                        ajax_error(jqXHR.status, serverID, 'Rename', jqXHR.responseText);
787
                    }
788
                }
789
    });
790

    
791
    return false;
792
}
793

    
794
// get server metadata
795
function get_metadata(serverID) {
796
    $.ajax({
797
        url: API_URL + '/servers/' + serverID + '/meta',
798
        type: "GET",
799
        //async: false,
800
        dataType: "json",
801
        timeout: TIMEOUT,
802
        error: function(jqXHR, textStatus, errorThrown) {
803
            try {
804
                                ajax_error(jqXHR.status, undefined, 'Get metadata', jqXHR.responseText);
805
                        } catch (err) {
806
                                ajax_error(err);
807
                        }
808
        },
809
        success: function(data, textStatus, jqXHR) {
810
            // to list the new results in the edit dialog
811
            list_metadata(data);
812
            list_metadata_keys(serverID, data);
813
        }
814
    });
815
    return false;
816
}
817

    
818
// delete metadata key-value pair
819
function delete_metadata(serverID, meta_key) {
820
    $.ajax({
821
        url: API_URL + '/servers/' + serverID + '/meta/' + meta_key,
822
        type: "DELETE",
823
        //async: false,
824
        dataType: "json",
825
        timeout: TIMEOUT,
826
        error: function(jqXHR, textStatus, errorThrown) {
827
            try {
828
                                ajax_error(jqXHR.status, undefined, 'Delete metadata', jqXHR.responseText);
829
                        } catch (err) {
830
                                ajax_error(err);
831
                        }
832
        },
833
        success: function(data, textStatus, jqXHR) {
834
            // to GET new results and list them in the edit dialog
835
            get_metadata(serverID);
836
        }
837
    });
838
    return false;
839
}
840

    
841

    
842
// add metadata key-value pair
843
function add_metadata(serverID, meta_key, meta_value) {
844

    
845
    var payload = {
846
        "meta": {
847
        }
848
    };
849
    payload["meta"][meta_key] = meta_value;
850

    
851
    $.ajax({
852
        url: API_URL + '/servers/' + serverID + '/meta/' + meta_key,
853
        type: "PUT",
854
            contentType: "application/json",
855
        dataType: "json",
856
        data: JSON.stringify(payload),
857
        timeout: TIMEOUT,
858
        error: function(jqXHR, textStatus, errorThrown) {
859
            try {
860
                                ajax_error(jqXHR.status, undefined, 'add metadata', jqXHR.responseText);
861
                        } catch (err) {
862
                                ajax_error(err);
863
                        }
864
        },
865
        success: function(data, textStatus, jqXHR) {
866
            // to GET new results and list them in the edit dialog
867
            get_metadata(serverID);
868
        }
869
    });
870
    return false;
871
}
872

    
873

    
874
// show the welcome screen
875
function showWelcome() {
876
    $("#view-select").fadeOut("fast");
877
    $("#machinesview.standard").fadeOut("fast");
878
    $("#createcontainer").addClass('emptycreatecontainer')
879
    $("#create").addClass('emptycreate')
880
    $("#emptymachineslist").fadeIn("fast");
881
    $("#createbody").fadeIn("fast");
882
    $("#create").css("display", "block");
883
}
884

    
885
// hide the welcome screen
886
function hideWelcome() {
887
    $("#emptymachineslist").fadeOut("fast");
888
    $("#createbody").fadeOut("fast");
889
    $("#createcontainer").removeClass('emptycreatecontainer')
890
    $("#create").removeClass('emptycreate')
891
    $("#view-select").fadeIn("fast");
892
    $("#machinesview.standard").fadeIn("fast");
893
    $("div#view-select").show();
894
    $("#create").css("display", "inline");
895
}
896