Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 99b5161d

History | View | Annotate | Download (18.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">1</span><div class="headerbody">{% 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 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
                                <strong>{% trans "small" %}</strong>
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
                                <strong>{% trans "medium" %}</strong>
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
                                <strong>{% trans "large" %}</strong>
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
                                <strong>{% trans "custom" %}</strong>
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">
137
                        <label>
138
                            <strong>Name:</strong>
139
                            <input type="text" class="text" name="machine_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
// hardcoded image types
199
// TODO: get this from the metadata
200
var image_tags = {
201
                1: 'archlinux',
202
                2: 'centos',
203
                3: 'debian',
204
                4: 'freebsd',
205
                5: 'gentoo',
206
                6: 'netbsd',
207
                7: 'openbsd',
208
                8: 'redhat',
209
                9: 'slackware',
210
                10: 'suse',
211
                11: 'ubuntu',
212
                12: 'windows',
213
                20: 'ubuntu',
214
               };
215

216
// switch to list view
217
$("a#list").click(function(){
218
    list_view(); 
219
    return false;
220
});
221

222
// switch to standard view
223
$("a#standard").click(function(){
224
    standard_view();
225
    return false;
226
});
227

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

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

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

308
// disable sliders in flavor selection
309
function disableSliders() {
310
    $("#cpu").attr('disabled',true);
311
    $("#ram").attr('disabled',true);
312
    $("#storage").attr('disabled',true);
313
}
314

315
// confirm all actions
316
$("div.confirm_multiple .yes").live('click', function(){
317
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
318
        action = pending_actions.pop(); // extract action
319
        var serverID = action[1];
320
        if ($.cookie("list") != '1') { // standard view
321
            $('#' + serverID + ' .selected').removeClass('selected');
322
            $('#' + serverID + ' .display').removeClass('display');
323
            if (action[0] == shutdown) {
324
                $('#' + serverID + ' .status').text('Shutting down');
325
            } else if (action[0] == start) {
326
                $('#' + serverID + ' .status').text('Starting');
327
            }
328
            $('#' + serverID + ' .spinner').show();
329
        } else { // list view
330
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
331
            osIcon.attr('os',osIcon.attr('src'));
332
            osIcon.attr('src','static/progress.gif');
333
        }
334
        action[0]([serverID]); // execute action
335
    }
336
    update_confirmations();    
337
});
338

339
// cancel all actions
340
$("div.confirm_multiple .no").live('click', function(){
341
    pending_actions = [];
342
    $('.machine .selected').removeClass('selected');
343
    $('.machine .display').removeClass('display');
344
    update_confirmations();
345
});
346

347
// validate cpu input box
348
$("#cpu-indicator").live('change',function(){
349
    var v = Number(this.value);
350
    var i = cpus.indexOf(v);
351
    if (isNaN(v)) {
352
        $(this).value = cpus[0];
353
        $("#cpu").data('rangeinput').setValue(0);
354
    } else if (i == -1) {
355
        for (var j=0; j < cpus.length; j++)
356
            if (v<cpus[j])
357
                break;
358
        $("#cpu").data('rangeinput').setValue(j);
359
    } else {
360
        $("#cpu").data('rangeinput').setValue(i);
361
    }   
362
    return false;
363
});
364

365
// validate ram input box
366
$("#ram-indicator").live('change',function(){
367
    var v = Number(this.value);
368
    var i = ram.indexOf(v);
369
    if (isNaN(v)) {
370
        $(this).value = cpus[0];
371
        $("#ram").data('rangeinput').setValue(0);
372
    } else if (i == -1) {
373
        for (var j=0; j < ram.length; j++)
374
            if (v<ram[j])
375
                break;
376
        $("#ram").data('rangeinput').setValue(j);
377
    } else {
378
        $("#ram").data('rangeinput').setValue(i);
379
    }   
380
    return false;
381
});
382

383

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

402
// selecting the small size
403
$("#small").click(function(){
404
    $("#cpu").data('rangeinput').setValue(0);
405
    $("#ram").data('rangeinput').setValue(0);
406
    $("#storage").data('rangeinput').setValue(0);
407
    $("#cpu-indicator")[0].value = cpus[0];
408
    $("#ram-indicator")[0].value = ram[0];
409
    $("#storage-indicator")[0].value = disks[0];
410
    $("#small").addClass("active");
411
    $("#medium").removeClass("active");    
412
    $("#large").removeClass("active");    
413
    $("#custom").removeClass("active");    
414
});
415

416
// selecting the medium size
417
$("#medium").click(function(){
418
    $("#cpu").data('rangeinput').setValue(1);
419
    $("#ram").data('rangeinput').setValue(1);
420
    $("#storage").data('rangeinput').setValue(1);
421
    $("#cpu-indicator")[0].value = cpus[1];
422
    $("#ram-indicator")[0].value = ram[1];
423
    $("#storage-indicator")[0].value = disks[1];  
424
    $("#medium").addClass("active");  
425
    $("#small").removeClass("active");    
426
    $("#large").removeClass("active");    
427
    $("#custom").removeClass("active");  
428
});
429

430
// selecting the large size
431
$("#large").click(function(){
432
    $("#cpu").data('rangeinput').setValue(2);
433
    $("#ram").data('rangeinput').setValue(2);
434
    $("#storage").data('rangeinput').setValue(2);
435
    $("#cpu-indicator")[0].value = cpus[2];
436
    $("#ram-indicator")[0].value = ram[2];
437
    $("#storage-indicator")[0].value = disks[2];   
438
    $("#large").addClass("active"); 
439
    $("#medium").removeClass("active");    
440
    $("#small").removeClass("active");    
441
    $("#custom").removeClass("active");  
442
});
443

444
// selecting the custom flavor enables the sliders
445
$("#custom").click(function(){
446
    $("#cpu").attr('disabled',false);
447
    $("#ram").attr('disabled',false);
448
    $("#storage").attr('disabled',false);
449
    $("strong.sliders").style = 'color: #778899;';
450
    $("#custom").addClass("active"); 
451
    $("#medium").removeClass("active");    
452
    $("#large").removeClass("active");    
453
    $("#small").removeClass("active");  
454
});
455

456
// exit the wizard
457
$("#cancel").click(function(){
458
    $("a#create").overlay().close();
459
});
460

461
// starting a new VM through the wizard
462
$("#start").click(function(){
463
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
464
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
465
    var machineName = $('input[name=machine_name]')[0].value;
466

467
    create_vm(machineName, imageRef, flavorRef);
468

469
    $('a#create').data('overlay').close();
470
    $("#emptymachineslist").hide();
471

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

474
    $("#wizard").hide();
475
});
476

477
// basic functions executed on page load
478
if (images.length > 0) {
479
    // populate image list
480
    update_wizard_images();
481
}
482
if (flavors.length > 0) {
483
    // configure flavors
484
    update_wizard_flavors(); 
485
}
486
// create tabs for main menu
487
$("ul.tabs").tabs("div.panes ul");
488

    
489
</script>