Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 3091ead5

History | View | Annotate | Download (19.6 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="image-id" 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
//update radio button when clicking on text
328
$("#small-body").live('click' ,function() { 
329
    $(this).parent().find("#small").click();
330
});
331
$("#medium-body").live('click' ,function() { 
332
    $(this).parent().find("#medium").click();
333
});
334
$("#large-body").live('click' ,function() { 
335
    $(this).parent().find("#large").click();
336
});
337
$("#custom-body").live('click' ,function() { 
338
    $(this).parent().find("#custom").click();
339
});
340

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

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

373
// cancel all actions
374
$("div.confirm_multiple .no").live('click', function(){
375
    pending_actions = [];
376
    $('.machine .selected').removeClass('selected');
377
    $('.machine .display').removeClass('display');
378
    update_confirmations();
379
});
380

381
// validate cpu input box
382
$("#cpu-indicator").live('change',function(){
383
    var v = Number(this.value);
384
    var i = cpus.indexOf(v);
385
    if (isNaN(v)) {
386
        $(this).value = cpus[0];
387
        $("#cpu").data('rangeinput').setValue(0);
388
    } else if (i == -1) {
389
        for (var j=0; j < cpus.length; j++)
390
            if (v<cpus[j])
391
                break;
392
        $("#cpu").data('rangeinput').setValue(j);
393
    } else {
394
        $("#cpu").data('rangeinput').setValue(i);
395
    }   
396
    return false;
397
});
398

399
// validate ram input box
400
$("#ram-indicator").live('change',function(){
401
    var v = Number(this.value);
402
    var i = ram.indexOf(v);
403
    if (isNaN(v)) {
404
        $(this).value = cpus[0];
405
        $("#ram").data('rangeinput').setValue(0);
406
    } else if (i == -1) {
407
        for (var j=0; j < ram.length; j++)
408
            if (v<ram[j])
409
                break;
410
        $("#ram").data('rangeinput').setValue(j);
411
    } else {
412
        $("#ram").data('rangeinput').setValue(i);
413
    }   
414
    return false;
415
});
416

417

418
// validate storage input box
419
$("#storage-indicator").live('change',function(){
420
    var v = Number(this.value);
421
    var i = disks.indexOf(v);
422
    if (isNaN(v)) {
423
        $(this).value = disks[0];
424
        $("#storage").data('rangeinput').setValue(0);
425
    } else if (i == -1) {
426
        for (var j=0; j < disks.length; j++)
427
            if (v<disks[j])
428
                break;
429
        $("#storage").data('rangeinput').setValue(j);
430
    } else {
431
        $("#storage").data('rangeinput').setValue(i);
432
    }   
433
    return false;
434
});
435

436
// selecting the small size
437
$("#small").click(function(){
438
    $("#cpu").data('rangeinput').setValue(0);
439
    $("#ram").data('rangeinput').setValue(0);
440
    $("#storage").data('rangeinput').setValue(0);
441
    $("#cpu-indicator")[0].value = cpus[0];
442
    $("#ram-indicator")[0].value = ram[0];
443
    $("#storage-indicator")[0].value = disks[0];
444
    $("#small").addClass("active");
445
    $("#medium").removeClass("active");    
446
    $("#large").removeClass("active");    
447
    $("#custom").removeClass("active");    
448
});
449

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

464
// selecting the large size
465
$("#large").click(function(){
466
    $("#cpu").data('rangeinput').setValue(2);
467
    $("#ram").data('rangeinput').setValue(2);
468
    $("#storage").data('rangeinput').setValue(2);
469
    $("#cpu-indicator")[0].value = cpus[2];
470
    $("#ram-indicator")[0].value = ram[2];
471
    $("#storage-indicator")[0].value = disks[2];   
472
    $("#large").addClass("active"); 
473
    $("#medium").removeClass("active");    
474
    $("#small").removeClass("active");    
475
    $("#custom").removeClass("active");  
476
});
477

478
// selecting the custom flavor enables the sliders
479
$("#custom").click(function(){
480
    $("#cpu").attr('disabled',false);
481
    $("#ram").attr('disabled',false);
482
    $("#storage").attr('disabled',false);
483
    $("strong.sliders").style = 'color: #778899;';
484
    $("#custom").addClass("active"); 
485
    $("#medium").removeClass("active");    
486
    $("#large").removeClass("active");    
487
    $("#small").removeClass("active");  
488
});
489

490
// exit the wizard
491
$("#cancel").click(function(){
492
    $("a#create").overlay().close();
493
});
494

495
// starting a new VM through the wizard
496
$("#start").click(function(){
497
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
498
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
499
    var machineName = $('input[name=machine_name]')[0].value;
500

501
    create_vm(machineName, imageRef, flavorRef);
502

503
    $('a#create').data('overlay').close();
504
    $("#emptymachineslist").hide();
505

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

508
    $("#wizard").hide();
509
});
510

511
// basic functions executed on page load
512
if (images.length > 0) {
513
    // populate image list
514
    update_wizard_images();
515
}
516
if (flavors.length > 0) {
517
    // configure flavors
518
    update_wizard_flavors(); 
519
}
520
// create tabs for main menu
521
$("ul.tabs").tabs("div.panes ul");
522

    
523
</script>