Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 1704ae25

History | View | Annotate | Download (20 kB)

1
{% load i18n %}
2

    
3
<div id="machines" class="separator"></div>
4

    
5
<!-- the create button -->
6
<div id="createcontainer">
7
    <span id="createbody">{% trans "Start by creating a new Virtual Machine:" %}</span><br />
8
    <a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
9
</div>
10

    
11
<!-- changing between standard/list view -->
12
<div id="view-select">
13
    <a id="standard" href="/machines/standard">#</a>
14
    <span class="view-separator">|</span>
15
    <a id="list" href="/machines/list">=</a>
16
</div>
17

    
18
<div id="emptymachineslist"><h1 id="welcomeheader">{% trans "Welcome to the ocean!" %}</h1><br />
19
    <span class="welcomebody">{% trans "From this panel you will be able to manage your Virtual Machines (VMs). If you don't know what a VM is: take the " %}<a href="#">{% trans "tour" %}</a>.</span><br /><br />
20
    <span class="welcomebody">{% trans "The panel is currently empty, because you don't have any VMs yet. You can start by creating your new VM by clicking the blue button on the right. The wizard will guide you through the hole process." %}</span><br /><br />
21
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="#">{% trans "here" %}</a>.</span>
22
</div>
23

    
24
<!-- the form -->
25
<form action="#">
26
        <!-- scrollable root element -->
27
        <div class="modal" id="wizard">
28
                <!-- status bar -->
29
                <ul id="status">
30
                        <li class="active"><span class="headernumber" class="first">1</span><div class="headerbody first">{% trans "Image" %}</div></li>
31
                        <li><span class="headernumber">2</span><div class="headerbody">{% trans "Flavor" %}</div></li>
32
                        <li><span class="headernumber">3</span><div class="headerbody">{% trans "Name" %}</div></li>
33
                </ul>
34
                <!-- scrollable items -->
35
                <div class="items">
36
                        <!-- pages -->
37
                        <div class="page">
38
                <h2>{% trans "Select an OS" %}</h2>
39
                <hr class="topruler" />
40
                <ul class="tabs">
41
                    <li><a href="#">{% trans "system images" %}</a></li>
42
                    <li><a href="#">{% trans "your images" %}</a></li>
43
                </ul>
44
                <div class="panes">
45
                            <li id="image-template" style="display:none">
46
                                    <label for="image.id"> 
47
                            <a>
48
                                <div class="image-container">
49
                                    <div class="image">
50
                                        <input class="radio" type="radio" name="imageGroup" id="image-id" />
51
                                        <img src="" class="image-logo"/>
52
                                        <strong class="image-title">image.title</strong>
53
                                        <br />
54
                                        <span class="description">image.description</span> 
55
                                        <span id="size" class="size">?? MB</span><span class="size">MB</span>                         
56
                                    </div>
57
                                </div>  
58
                            </a>
59
                                    </label>
60
                            </li>
61
                    <ul class="pane" id="standard-images">
62
                                            <!-- standard images -->
63
                                    </ul>
64
                    <ul class="pane" id="custom-images">
65
                                            <!-- custom images -->
66
                    </ul>
67
                </div>
68
                <hr class="bottomruler" />
69
                                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
70
                                <button type="button" class="next right">{% trans "Next" %}</button>
71
            </div>
72
                        <div class="page">
73
                                <h2>{% trans "Select CPUs, RAM and Disk Size" %}</h2>
74
                <hr class="topruler" />
75
                <ul>
76
                    <li id="machinetype">
77
                        <div class="machine-type">
78
                            <label for="small" id="small">
79
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
80
                                <span class="typebody" id="small-body">{% trans "small" %}</span>
81
                            </label>
82
                        </div>
83
                        <div class="machine-type">      
84
                            <label for="medium" id="medium">
85
                                <input type="radio" id="medium" name="machine-type" value="medium" />                  
86
                                <span class="typebody" id="medium-body">{% trans "medium" %}</span>
87
                            </label>
88
                        </div>
89
                        <div class="machine-type">
90
                            <label for="large" id="large">
91
                                <input type="radio" id="large" name="machine-type" value="large" />
92
                                <span class="typebody" id="large-body">{% trans "large" %}</span>
93
                            </label>
94
                        </div>
95
                        <div class="machine-type">
96
                            <label for="custom" id="custom">
97
                                <input type="radio" name="machine-type" id="custom" value="large" />
98
                                <span class="typebody" id="custom-body">{% trans "custom" %}</span>
99
                            </label>
100
                        </div>
101
                    </li>
102
                    <div id="page2-container">
103
                        <li class="slider-container">
104
                                        <label><strong class="sliders">CPUs</strong></label>
105
                            <input type="range" id="cpu" style="display:none" />
106
                            <input type="text" class="range" id="cpu-indicator" />
107
                                        <span class="units">cores</span>
108
                        </li>
109
                        <li class="slider-container">
110
                                        <label><strong class="sliders">RAM</strong></label>
111
                            <input type="range" id="ram" style="display:none" />
112
                            <input type="text" class="range" id="ram-indicator" />
113
                                        <span class="units">MB</span>
114
                        </li>
115
                        <li class="slider-container">
116
                                    <label><strong class="sliders">Size</strong></label>
117
                            <input type="range" id="storage" style="display:none" />
118
                            <input type="text" class="range" id="storage-indicator" />
119
                                        <span class="units">GB</span>
120
                        </li>
121
                        <li>
122
                            <div class="cost">
123
                                <span> {% trans "Your wallet:" %} 10,000 Credits </span> | <span>{% trans "This setup will cost you:" %}<input type="text" id="credits-indicator" value="20" class="range" />{% trans "C/hour" %}</span>
124
                            </div>
125
                        </li>
126
                    </div>
127
                </ul>
128
                <hr class="bottomruler" />
129
                                <button type="button" class="prev">{% trans "Back" %}</button>
130
                                <button type="button" class="next right">{% trans "Next" %}</button>
131
            </div>
132
                        <div class="page">
133
                                <h2>{% trans "Confirm your settings" %}</h2>
134
                <hr class="topruler" />
135
                <ul id="page3-container">
136
                    <li class="required" id="label-name">
137
                        <label>
138
                            <strong>Name:</strong>
139
                            <input type="text" class="text" name="machine_name" id="name" value="My Ubuntu 10.04 x86_64 server"/>
140
                        </label>
141
                    </li>
142
                    <li>
143
                        <span>{% trans "Image:" %}</span> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
144
                    </li>
145
                    <li>
146
                        <span>{% trans "CPUs:" %}</span> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
147
                    </li>
148
                    <li>
149
                        <span>{% trans "RAM:" %}</span> <span id="machine_ram-label">1024</span><span>MB</span>
150
                    </li>
151
                    <li>
152
                        <span>{% trans "System Disk:" %}</span> <span id="machine_storage-label">10</span><span>GB</span>
153
                    </li>
154
                    <li>
155
                        <span>{% trans "Cost per Hour:" %}</span> <span>40 {% trans "credits" %}</span>
156
                    </li>
157
                    <li>
158
                        <span>{% trans "Credits in Wallet:" %}</span> <span>10.000</span>
159
                    </li>
160
                </ul>
161
                <hr class="bottomruler" />
162
                                <button type="button" class="prev">{% trans "Back" %}</button>
163
                                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>        
164
            </div>
165
                </div>
166
        </div>
167
</form>
168

    
169
<!-- notification after wizard completion -->
170
<a id="notification" rel="#error-success" href="#"></a>
171

    
172
<div class="modal" id="error-success">
173
    <h3>{% trans "Error!/Success!" %}</h3>
174
    <div><p>{% trans "More details about the result"%}</p></div>
175
</div>
176

    
177
<!-- confirmation before executing an action -->
178
<a id="confirmation" rel="#yes-no" href="#"></a>
179

    
180
<div class="modal" id="yes-no">
181
    <h3>{% trans "You are about to xxx machine yyy" %}</h3>
182
    <p>{% trans "Are you sure you want to proceed?" %}</p>
183
    <button>{% trans "Yes" %}</button>
184
        <button>{% trans "No" %}</button>
185
</div>
186

    
187
<div id="machinesview"></div>
188

    
189
<div class="confirm_multiple">
190
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
191
    <button class="yes">{% trans "Confirm All" %}</button>
192
        <button class="no">{% trans "Cancel All" %}</button>
193
</div>
194

    
195
<div id="machines" class="separator"></div>
196

    
197
<script>
198
//add hover to labels
199
$('span.typebody').mouseover(function() {
200
    $(this).addClass('typehover')
201
});
202
$('span.typebody').mouseout(function() {
203
    $(this).removeClass('typehover')
204
});
205

206
// return value from metadata key "OS", if it exists
207
function os_icon(metadata) {
208
    if (!metadata) {
209
        return 'unknown';
210
    }
211

212
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
213
        return 'unknown';
214
    } else {
215
        return metadata.values.OS;
216
    }
217
} 
218

219
// switch to list view
220
$("a#list").click(function(){
221
    list_view(); 
222
    return false;
223
});
224

225

226
// switch to standard view
227
$("a#standard").click(function(){
228
    standard_view();
229
    return false;
230
});
231

232
// launch VM creation wizard
233
$("a#create").click(function(){
234
    // launch wizard only if images and flavors are found
235
    if (images.length > 0  && flavors.length > 0) {
236
        $("#wizard").scrollable().begin();
237
        $("#wizard").show();
238
        $('a#create').data('overlay').load()   
239
    } else if (images.length == 0 ) {
240
        ajax_error('NO_IMAGES');
241
        return false;   
242
    } else if (flavors.length == 0) {
243
        ajax_error('NO_FLAVORS');
244
        return false;
245
    }
246
});
247

248
// create wizard overlay
249
$(function() { 
250
    $("a#create").overlay({
251
        mask: '#000', 
252
        effect: 'default', 
253
        top: '5%', 
254
        oneInstance: false,
255
        closeOnClick: false
256
    });
257
});
258

259
// wizard
260
$(function() {
261
    var root = $("#wizard").scrollable();
262
    var api = root.scrollable();
263
    // rangeinput with default configuration
264
    // validation logic is done inside the onBeforeSeek callback
265
    api.onBeforeSeek(function(event, i) {
266
            // we are going 1 step backwards so no need for validation
267
            if (api.getIndex() < i) {
268
             // 1. get current page
269
                     var page = root.find(".page").eq(api.getIndex()),
270
                         // 2. .. and all required fields inside the page
271
                         inputs = page.find(".required :input").removeClass("error"),
272
                         // 3. .. which are empty
273
                         empty = inputs.filter(function() {
274
                                return $(this).val().replace(/\s*/g, '') == '';
275
                         });
276
                     // if there are empty fields, then
277
                    if (empty.length) {
278
                            // add a CSS class name "error" for empty & required fields
279
                            empty.addClass("error");
280
                            // cancel seeking of the scrollable by returning false
281
                            return false;
282
                    // everything is good
283
                    } 
284
            }
285
            // update status bar
286
            $("#status li").removeClass("active").eq(i).addClass("active");
287
        // update confirm step
288
        if (api.getIndex()==0) {
289
            var image = $("input[type=radio][name=image-id]:checked");
290
            var imageRef = image.length ? image[0].id : false
291
            if (imageRef) {
292
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
293
                $("#machine_image-label")[0].textContent = imageName;
294
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
295
            }
296
        } else if (api.getIndex()==1) {
297
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
298
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
299
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
300
        }    
301
    });
302
    // if tab is pressed on the next button seek to next page
303
    root.find("button.next").keydown(function(e) {
304
            if (e.keyCode == 9) {
305
                    // seeks to next tab by executing our validation routine
306
                    api.next();
307
                    e.preventDefault();
308
            }
309
    });
310
    $("#name").keypress(function (e) {
311
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
312
                        $('#start').click();
313
                        return false;
314
                } else {
315
                        return true;
316
                }
317
    });
318
});
319

320
// disable sliders in flavor selection
321
function disableSliders() {
322
    $("#cpu").attr('disabled',true);
323
    $("#ram").attr('disabled',true);
324
    $("#storage").attr('disabled',true);
325
}
326

327
if($('.radio:checked').val() == 'true')  {
328
    $(this).parent().addClass('selecteddiv');
329
}
330

331
//update radio button when clicking on text
332
$("#small-body").live('click' ,function() { 
333
    $(this).parent().find("#small").click();
334
});
335
$("#medium-body").live('click' ,function() { 
336
    $(this).parent().find("#medium").click();
337
});
338
$("#large-body").live('click' ,function() { 
339
    $(this).parent().find("#large").click();
340
});
341
$("#custom-body").live('click' ,function() { 
342
    $(this).parent().find("#custom").click();
343
});
344

345
//select image div on radio button select
346
$('.radio').live('click' ,function() {           
347
    $(this).parents("div").find(".image").removeClass('selecteddiv');
348
    if($(this).is(':checked'))  {
349
        $(this).parent().addClass('selecteddiv');
350
    }
351
});
352

353
// confirm all actions
354
$("div.confirm_multiple .yes").live('click', function(){
355
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
356
        action = pending_actions.pop(); // extract action
357
        var serverID = action[1];
358
        if ($.cookie("list") != '1') { // standard view
359
            $('#' + serverID + ' .selected').removeClass('selected');
360
            $('#' + serverID + ' .display').removeClass('display');
361
            if (action[0] == shutdown) {
362
                $('#' + serverID + ' .status').text('Shutting down');
363
            } else if (action[0] == start) {
364
                $('#' + serverID + ' .status').text('Starting');
365
            }
366
            $('#' + serverID + ' .spinner').show();
367
        } else { // list view
368
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
369
            osIcon.attr('os',osIcon.attr('src'));
370
            osIcon.attr('src','static/progress.gif');
371
            if (action[0] == shutdown) {
372
                $('#' + serverID).parent().parent().find('span.status').text('Shutting down');
373
            } else if (action[0] == start) {
374
                $('#' + serverID).parent().parent().find('span.status').text('Starting');
375
            }
376
        }
377
        action[0]([serverID]); // execute action
378
    }
379
    update_confirmations();    
380
});
381

382
// cancel all actions
383
$("div.confirm_multiple .no").live('click', function(){
384
    pending_actions = [];
385
    $('.machine .selected').removeClass('selected');
386
    $('.machine .display').removeClass('display');
387
    update_confirmations();
388
});
389

390
// validate cpu input box
391
$("#cpu-indicator").live('change',function(){
392
    var v = Number(this.value);
393
    var i = cpus.indexOf(v);
394
    if (isNaN(v)) {
395
        $(this).value = cpus[0];
396
        $("#cpu").data('rangeinput').setValue(0);
397
    } else if (i == -1) {
398
        for (var j=0; j < cpus.length; j++)
399
            if (v<cpus[j])
400
                break;
401
        $("#cpu").data('rangeinput').setValue(j);
402
    } else {
403
        $("#cpu").data('rangeinput').setValue(i);
404
    }   
405
    return false;
406
});
407

408
// validate ram input box
409
$("#ram-indicator").live('change',function(){
410
    var v = Number(this.value);
411
    var i = ram.indexOf(v);
412
    if (isNaN(v)) {
413
        $(this).value = cpus[0];
414
        $("#ram").data('rangeinput').setValue(0);
415
    } else if (i == -1) {
416
        for (var j=0; j < ram.length; j++)
417
            if (v<ram[j])
418
                break;
419
        $("#ram").data('rangeinput').setValue(j);
420
    } else {
421
        $("#ram").data('rangeinput').setValue(i);
422
    }   
423
    return false;
424
});
425

426

427
// validate storage input box
428
$("#storage-indicator").live('change',function(){
429
    var v = Number(this.value);
430
    var i = disks.indexOf(v);
431
    if (isNaN(v)) {
432
        $(this).value = disks[0];
433
        $("#storage").data('rangeinput').setValue(0);
434
    } else if (i == -1) {
435
        for (var j=0; j < disks.length; j++)
436
            if (v<disks[j])
437
                break;
438
        $("#storage").data('rangeinput').setValue(j);
439
    } else {
440
        $("#storage").data('rangeinput').setValue(i);
441
    }   
442
    return false;
443
});
444

445
// selecting the small size
446
$("#small").click(function(){
447
    $("#cpu").data('rangeinput').setValue(0);
448
    $("#ram").data('rangeinput').setValue(0);
449
    $("#storage").data('rangeinput').setValue(0);
450
    $("#cpu-indicator")[0].value = cpus[0];
451
    $("#ram-indicator")[0].value = ram[0];
452
    $("#storage-indicator")[0].value = disks[0];
453
    $("#small").addClass("active");
454
    $("#medium").removeClass("active");    
455
    $("#large").removeClass("active");    
456
    $("#custom").removeClass("active");    
457
});
458

459
// selecting the medium size
460
$("#medium").click(function(){
461
    $("#cpu").data('rangeinput').setValue(1);
462
    $("#ram").data('rangeinput').setValue(1);
463
    $("#storage").data('rangeinput').setValue(1);
464
    $("#cpu-indicator")[0].value = cpus[1];
465
    $("#ram-indicator")[0].value = ram[1];
466
    $("#storage-indicator")[0].value = disks[1];  
467
    $("#medium").addClass("active");  
468
    $("#small").removeClass("active");    
469
    $("#large").removeClass("active");    
470
    $("#custom").removeClass("active");  
471
});
472

473
// selecting the large size
474
$("#large").click(function(){
475
    $("#cpu").data('rangeinput').setValue(2);
476
    $("#ram").data('rangeinput').setValue(2);
477
    $("#storage").data('rangeinput').setValue(2);
478
    $("#cpu-indicator")[0].value = cpus[2];
479
    $("#ram-indicator")[0].value = ram[2];
480
    $("#storage-indicator")[0].value = disks[2];   
481
    $("#large").addClass("active"); 
482
    $("#medium").removeClass("active");    
483
    $("#small").removeClass("active");    
484
    $("#custom").removeClass("active");  
485
});
486

487
// selecting the custom flavor enables the sliders
488
$("#custom").click(function(){
489
    $("#cpu").attr('disabled',false);
490
    $("#ram").attr('disabled',false);
491
    $("#storage").attr('disabled',false);
492
    $("strong.sliders").style = 'color: #778899;';
493
    $("#custom").addClass("active"); 
494
    $("#medium").removeClass("active");    
495
    $("#large").removeClass("active");    
496
    $("#small").removeClass("active");  
497
});
498

499
// exit the wizard
500
$("#cancel").click(function(){
501
    $("a#create").overlay().close();
502
});
503

504
// starting a new VM through the wizard
505
$("#start").click(function(){
506
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
507
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
508
    var machineName = $('input[name=machine_name]')[0].value;
509

510
    create_vm(machineName, imageRef, flavorRef);
511

512
    $('a#create').data('overlay').close();
513
    $("#emptymachineslist").hide();
514

515
    try{console.warn('creating ' + $("input[name=machine_name]")[0].value)} catch(err){}
516

517
    $("#wizard").hide();
518
});
519

520
// basic functions executed on page load
521
if (images.length > 0) {
522
    // populate image list
523
    update_wizard_images();
524
}
525
if (flavors.length > 0) {
526
    // configure flavors
527
    update_wizard_flavors(); 
528
}
529
// create tabs for main menu
530
$("ul.tabs").tabs("div.panes ul");
531

    
532
</script>