Statistics
| Branch: | Tag: | Revision:

root / ui / static / synnefo.js @ 0317c509

History | View | Annotate | Download (14.3 kB)

1
var flavors = [], images = [], servers = [], disks = [], cpus = [], ram = [];
2
var changes_since = 0, deferred = 0;
3

    
4
function list_view() {
5
        changes_since = 0; // to reload full list
6
        clearTimeout(deferred);        // clear old deferred calls
7
    $.cookie("list", '1'); // set list cookie
8
    $("div#machinesview").load($("#list").attr("href"), function(){
9
        $("a#standard")[0].className += ' activelink';
10
        $("a#list")[0].className = '';
11
    });
12
    return false;
13
}
14

    
15
function standard_view() {
16
        changes_since = 0; // to reload full list
17
        clearTimeout(deferred);        // clear old deferred calls
18
    $.cookie("list", '0');
19
    href=$("a#standard").attr("href");
20
    $("div#machinesview").load(href, function(){
21
        $("a#list")[0].className += ' activelink';
22
        $("a#standard")[0].className = '';
23
    });
24
    return false;
25
}
26

    
27
function choose_view() {
28
    if ($.cookie("list")=='1') {
29
        list_view();
30
    } else {
31
        standard_view();
32
    }
33
}
34

    
35
function toggleMenu() {
36
    var primary = $("ul.css-tabs li a.primary");
37
    var secondary = $("ul.css-tabs li a.secondary");
38
    var all = $("ul.css-tabs li a");                        
39
    var toggled = $('ul.css-tabs li a.current').hasClass('secondary');
40
    
41
    // if anything is still moving, do nothing
42
    if ($(":animated").length) {
43
        return;
44
    } 
45
    
46
    // nothing is current to begin with
47
    $('ul.css-tabs li a.current').removeClass('current');
48
    
49
    // move stuff around
50
    all.animate({top:'30px'}, {complete: function() { 
51
        $(this).hide();
52
        if (toggled) {
53
            primary.show();
54
            primary.animate({top:'9px'}, {complete: function() {
55
                $('ul.css-tabs li a.primary#machines').addClass('current');
56
                $('a#machines').click();                                   
57
            }});
58
        } else {
59
            secondary.show();
60
            secondary.animate({top:'9px'}, {complete: function() {
61
                $('ul.css-tabs li a.secondary#files').addClass('current');
62
                $('a#files').click();                                                                           
63
            }});
64
        }                                              
65
    }});
66
    
67
    // rotate arrow icon
68
    if (toggled) {
69
        $("#arrow").rotate({animateAngle: (0), bind:[{"click":function(){toggleMenu()}}]});
70
        $("#arrow").rotateAnimation(0);                    
71
    } else {
72
        $("#arrow").rotate({animateAngle: (-180), bind:[{"click":function(){toggleMenu()}}]});
73
        $("#arrow").rotateAnimation(-180);
74
    }            
75
}
76

    
77
// confirmation overlay generation
78
function confirm_action(action_string, action_function, serverIDs, serverNames) {
79
    if (serverIDs.length == 1){
80
        $("#yes-no h3").text('You are about to ' + action_string + ' vm ' + serverNames[0]);
81
    } else if (serverIDs.length > 1){
82
        $("#yes-no h3").text('You are about to ' + action_string + ' ' + serverIDs.length + ' machines');
83
    } else {
84
        return false;
85
    }
86
    // action confirmation overlay
87
    var triggers = $("a#confirmation").overlay({
88
            // some mask tweaks suitable for modal dialogs
89
            mask: {
90
                    color: '#ebecff',
91
                    opacity: '0.9'
92
            },
93
        top: 'center',
94
        load: false
95
    });
96
    // yes or no?
97
    var buttons = $("#yes-no button").click(function(e) {
98
            // get user input
99
            var yes = buttons.index(this) === 0;
100
        //close the confirmation window
101
        $("a#confirmation").overlay().close(); 
102
        // return true=yes or false=no
103
        if (yes) {
104
            action_function(serverIDs);
105
        }
106
    });
107
    $("a#confirmation").data('overlay').load();
108
    return false;
109
}
110

    
111
// get and show a list of running and terminated machines
112
function update_vms(interval) {
113
    try{ console.info('updating machines'); } catch(err){}
114
        var uri='/api/v1.0/servers/detail';
115
        
116
        if (changes_since > 0)
117
                uri+='?changes-since='+changes_since
118
                
119
    $.ajax({
120
        url: uri,
121
        type: "GET",
122
        timeout: TIMEOUT,
123
        dataType: "json",
124
        error: function(jqXHR, textStatus, errorThrown) {
125
                        // don't forget to try again later
126
                        if (interval) {
127
                                deferred = setTimeout(update_vms,interval,interval);
128
                        }
129
                        // as for now, just show an error message
130
                        try { console.info('update_vms errback:' + jqXHR.status ) } catch(err) {}
131
                        ajax_error();                                                
132
                        return false;
133
                        },
134
        success: function(data, textStatus, jqXHR) {
135
                        changes_since = Date.parse(jqXHR.getResponseHeader('Date'))/1000;
136
                        if (interval) {                        
137
                                deferred = setTimeout(update_vms,interval,interval);
138
                        }
139
                        
140
                        if (jqXHR.status == 200 || jqXHR.status == 203) {
141
                                try {
142
                                        servers = data.servers;
143
                                } catch(err) { ajax_error('400');}
144
                                update_machines_view(data);
145
                        } else if (jqXHR.status != 304){
146
                                try { console.info('update_vms callback:' + jqXHR.status ) } catch(err) {}
147
                                //ajax_error();                                                
148
                        }
149
                        return false;
150
        }
151
    });
152
    return false;
153
}
154

    
155
// get and show a list of available standard and custom images
156
function update_images() { 
157
    $.ajax({
158
        url: '/api/v1.0/images/detail',
159
        type: "GET",
160
        //async: false,
161
        dataType: "json",
162
        timeout: TIMEOUT,
163
        error: function(jqXHR, textStatus, errorThrown) { 
164
                    ajax_error(jqXHR.status);
165
                    },
166
        success: function(data, textStatus, jqXHR) {
167
            try {
168
                                images = data.images;
169
                        } catch(err){
170
                                ajax_error("NO_IMAGES");
171
                        }
172
            if ($("ul#standard-images li").toArray().length + $("ul#custom-images li").toArray().length == 0) {
173
                $.each(data.images, function(i,image){
174
                    var img = $('#image-template').clone().attr("id","img-"+image.id).fadeIn("slow");
175
                    img.find("label").attr('for',"img-radio-" + image.id);
176
                    img.find(".image-title").text(image.name);
177
                    img.find(".description").text(image.description);
178
                    img.find(".size").text(image.size);
179
                    img.find("input.radio").attr('id',"img-radio-" + image.id);
180
                    if (i==0) img.find("input.radio").attr("checked","checked"); 
181
                    img.find("img.image-logo").attr('src','static/os_logos/'+image_tags[image.id]+'.png');
182
                    if (image.serverId) {
183
                        img.appendTo("ul#custom-images");
184
                    } else {
185
                        img.appendTo("ul#standard-images");
186
                    }
187
                });
188
            }
189
        }
190
    });
191
    return false;
192
}
193

    
194
Array.prototype.unique = function () {
195
        var r = new Array();
196
        o:for(var i = 0, n = this.length; i < n; i++)
197
        {
198
                for(var x = 0, y = r.length; x < y; x++)
199
                {
200
                        if(r[x]==this[i])
201
                        {
202
                                continue o;
203
                        }
204
                }
205
                r[r.length] = this[i];
206
        }
207
        return r;
208
}
209

    
210
// get and configure flavor selection
211
function update_flavors() { 
212
    $.ajax({
213
        url: '/api/v1.0/flavors/detail',
214
        type: "GET",
215
        //async: false,
216
        dataType: "json",
217
        timeout: TIMEOUT,
218
        error: function(jqXHR, textStatus, errorThrown) { 
219
            try {
220
                                ajax_error(jqXHR.status);
221
                        } catch (err) {
222
                                ajax_error(err);
223
                        }
224
        },
225
        success: function(data, textStatus, jqXHR) {
226
            flavors = data.flavors;
227
            $.each(flavors, function(i, flavor) {
228
                cpus[i] = flavor['cpu'];
229
                disks[i] = flavor['disk'];
230
                ram[i] = flavor['ram'];
231
            });
232
            cpus = cpus.unique();
233
            disks = disks.unique();
234
            ram = ram.unique();
235
            // sliders for selecting VM flavor
236
            $("#cpu:range").rangeinput({min:0,
237
                                       value:0,
238
                                       step:1,
239
                                       progress: true,
240
                                       max:cpus.length-1});
241
            
242
            $("#storage:range").rangeinput({min:0,
243
                                       value:0,
244
                                       step:1,
245
                                       progress: true,
246
                                       max:disks.length-1});
247

    
248
            $("#ram:range").rangeinput({min:0,
249
                                       value:0,
250
                                       step:1,
251
                                       progress: true,
252
                                       max:ram.length-1});
253
            $("#small").click();
254
            
255
            // update the indicators when sliding
256
            $("#cpu:range").data().rangeinput.onSlide(function(event,value){
257
                $("#cpu-indicator")[0].value = cpus[Number(value)];
258
            });
259
            $("#cpu:range").data().rangeinput.change(function(event,value){
260
                $("#cpu-indicator")[0].value = cpus[Number(value)];                                
261
                $("#custom").click();                                
262
                        });                        
263
            $("#ram:range").data().rangeinput.onSlide(function(event,value){
264
                $("#ram-indicator")[0].value = ram[Number(value)];
265
            });
266
            $("#ram:range").data().rangeinput.change(function(event,value){
267
                $("#ram-indicator")[0].value = ram[Number(value)];                                
268
                $("#custom").click();
269
            });                        
270
            $("#storage:range").data().rangeinput.onSlide(function(event,value){
271
                $("#storage-indicator")[0].value = disks[Number(value)];
272
            });
273
            $("#storage:range").data().rangeinput.change(function(event,value){
274
                $("#storage-indicator")[0].value = disks[Number(value)];                                
275
                $("#custom").click();
276
            });                        
277
        }
278
    });
279
    return false;
280
}
281

    
282
// return flavorRef from cpu, disk, ram values
283
function identify_flavor(cpu, disk, ram){
284
    for (i=0;i<flavors.length;i++){
285
        if (flavors[i]['cpu'] == cpu && flavors[i]['disk']==disk && flavors[i]['ram']==ram) {
286
            return flavors[i]['id']
287
        }
288
    }
289
    return 0;
290
}
291

    
292
// update the actions in the 
293
function updateActions() {
294
        var states = [];
295
        var on = [];
296
        var checked = $("table.list-machines tbody input[type='checkbox']:checked");
297
        // disable all actions to begin with
298
        for (action in actions) {
299
                $("#action-" + action).removeClass('enabled');
300
        }
301

    
302
        // are there multiple machines selected?
303
        if (checked.length>1)
304
                states[0] = 'multiple';
305
        
306
        // check the states of selected machines
307
        checked.each(function(i,checkbox) {
308
                states[states.length] = checkbox.className;
309
                var ip = $("#" + checkbox.id.replace('input-','') + ".ip span.public").text();
310
                if (ip.replace('undefined','').length)
311
                        states[states.length] = 'network';
312
        });
313

    
314
        // decide which actions should be enabled
315
        for (a in actions) {
316
                var enabled = false;
317
                for (var s =0; s<states.length; s++) {
318
                        if (actions[a].indexOf(states[s]) != -1 ) {
319
                                enabled = true;
320
                        } else {
321
                                enabled = false;
322
                                break;
323
                        }
324
                }
325
                if (enabled)
326
                        on[on.length]=a;
327
        }
328
        // enable those actions
329
        for (action in on) {
330
                $("#action-" + on[action]).addClass('enabled');
331
        }
332
}
333

    
334
// reboot action
335
function reboot(serverIDs){
336
        if (!serverIDs.length){
337
                ajax_success('DEFAULT');
338
                return false;
339
        }        
340
    // ajax post reboot call
341
    var payload = {
342
        "reboot": {"type" : "HARD"}
343
    };
344
    serverID = serverIDs.pop();
345
        
346
        $.ajax({
347
                url: '/api/v1.0/servers/' + serverID + '/action',
348
                type: "POST",        
349
                dataType: "json",
350
                data: JSON.stringify(payload),
351
                timeout: TIMEOUT,
352
                error: function(jqXHR, textStatus, errorThrown) {
353
                                        ajax_error(jqXHR.status);
354
                                },
355
                success: function(data, textStatus, jqXHR) {
356
                                        if ( jqXHR.status == '202') {
357
                        try {
358
                            console.info('rebooted ' + serverID);
359
                        } catch(err) {}                   
360
                                                reboot(serverIDs);
361
                                        } else {
362
                                                ajax_error(jqXHR.status);
363
                                        }
364
                                }
365
    });
366

    
367
    return false;
368
}
369

    
370
// shutdown action
371
function shutdown(serverIDs) {
372
        if (!serverIDs.length){
373
                ajax_success('DEFAULT');
374
                return false;
375
        }
376
    // ajax post shutdown call
377
    var payload = {
378
        "shutdown": {"timeout" : "5"}
379
    };   
380

    
381
        serverID = serverIDs.pop()
382
    $.ajax({
383
            url: '/api/v1.0/servers/' + serverID + '/action',
384
            type: "POST",
385
            dataType: "json",
386
        data: JSON.stringify(payload),
387
        timeout: TIMEOUT,
388
        error: function(jqXHR, textStatus, errorThrown) { 
389
                    ajax_error(jqXHR.status);
390
                    },
391
        success: function(data, textStatus, jqXHR) {
392
                    if ( jqXHR.status == '202') {
393
                                                try {
394
                            console.info('suspended ' + serverID);
395
                        } catch(err) {}                                       
396
                        shutdown(serverIDs);
397
                    } else {
398
                        ajax_error(jqXHR.status);
399
                    }
400
                }             
401
    });
402

    
403
    return false;    
404
}
405

    
406
// destroy action
407
function destroy(serverIDs) {
408
        if (!serverIDs.length){
409
                ajax_success('DEFAULT');
410
                return false;
411
        }
412
    // ajax post destroy call can have an empty request body
413
    var payload = {};   
414

    
415
        serverID = serverIDs.pop()
416
    $.ajax({
417
            url: '/api/v1.0/servers/' + serverID,
418
            type: "DELETE",
419
            dataType: "json",
420
        data: JSON.stringify(payload),
421
        timeout: TIMEOUT,
422
        error: function(jqXHR, textStatus, errorThrown) { 
423
                    ajax_error(jqXHR.status);
424
                    },
425
        success: function(data, textStatus, jqXHR) {
426
                    if ( jqXHR.status == '202') {
427
                                                try {
428
                            console.info('destroyed ' + serverID);
429
                        } catch (err) {}                                        
430
                        destroy(serverIDs);
431
                    } else {
432
                        ajax_error(jqXHR.status);
433
                    }
434
                }             
435
    });
436

    
437
    return false;    
438
}
439

    
440
// start action
441
function start(serverIDs){
442
        if (!serverIDs.length){
443
                ajax_success('DEFAULT');
444
                return false;
445
        }        
446
    // ajax post start call
447
    var payload = {
448
        "start": {"type" : "NORMAL"}
449
    };   
450

    
451
        serverID = serverIDs.pop()
452
    $.ajax({
453
        url: '/api/v1.0/servers/' + serverID + '/action',
454
        type: "POST",
455
        dataType: "json",
456
        data: JSON.stringify(payload),
457
        timeout: TIMEOUT,
458
        error: function(jqXHR, textStatus, errorThrown) { 
459
                    ajax_error(jqXHR.status);
460
                    },
461
        success: function(data, textStatus, jqXHR) {
462
                    if ( jqXHR.status == '202') {
463
                                            try {
464
                            console.info('started ' + serverID);
465
                        } catch(err) {}                      
466
                        start(serverIDs);
467
                    } else {
468
                        ajax_error(jqXHR.status);
469
                    }
470
                }
471
    });
472

    
473
    return false;
474
}